From 0ef0c933d2bc795355f973a13e2ce415cfafd8a9 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 1 Mar 2016 17:18:14 -0500 Subject: [PATCH] Import code from internal repository to git --- .gitignore | 70 + CONTRIBUTING.md | 27 + CONTRIBUTORS | 23 + LICENSE.txt | 202 + README.md | 190 + WORKSPACE | 476 + apiserving/discoverydata/admin/BUILD | 6 + apiserving/discoverydata/bigquery/BUILD | 6 + apiserving/discoverydata/drive/BUILD | 6 + apiserving/discoverydata/groupssettings/BUILD | 6 + .../client/extensions/appengine/http/BUILD | 10 + .../api/client/googleapis/auth/oauth2/BUILD | 10 + .../extensions/appengine/auth/oauth2/BUILD | 10 + .../google/api/client/googleapis/json/BUILD | 6 + java/com/google/api/client/http/BUILD | 9 + java/com/google/api/client/http/javanet/BUILD | 9 + java/com/google/api/client/json/BUILD | 9 + .../com/google/api/client/json/jackson2/BUILD | 9 + java/com/google/api/client/testing/http/BUILD | 9 + java/com/google/common/annotations/BUILD | 6 + java/com/google/common/base/BUILD | 6 + java/com/google/common/cache/BUILD | 6 + java/com/google/common/collect/BUILD | 6 + java/com/google/common/escape/BUILD | 6 + java/com/google/common/hash/BUILD | 6 + java/com/google/common/html/BUILD | 6 + java/com/google/common/io/BUILD | 6 + java/com/google/common/math/BUILD | 6 + java/com/google/common/net/BUILD | 6 + java/com/google/common/primitives/BUILD | 6 + java/com/google/common/reflect/BUILD | 6 + java/com/google/common/testing/BUILD | 7 + java/com/google/common/util/concurrent/BUILD | 6 + java/com/google/domain/registry/BUILD | 11 + java/com/google/domain/registry/backup/BUILD | 31 + .../domain/registry/backup/BackupModule.java | 92 + .../domain/registry/backup/BackupUtils.java | 75 + .../backup/CommitLogCheckpointAction.java | 86 + .../backup/CommitLogCheckpointStrategy.java | 180 + .../backup/DeleteOldCommitLogsAction.java | 160 + .../backup/ExportCommitLogDiffAction.java | 219 + .../registry/backup/GcsDiffFileLister.java | 128 + .../backup/RestoreCommitLogsAction.java | 207 + .../domain/registry/backup/package-info.java | 16 + .../com/google/domain/registry/bigquery/BUILD | 30 + .../registry/bigquery/BigqueryConnection.java | 775 + .../registry/bigquery/BigqueryFactory.java | 33 + .../registry/bigquery/BigqueryHelper.java | 75 + .../bigquery/BigqueryJobFailureException.java | 120 + .../registry/bigquery/BigqueryModule.java | 61 + .../registry/bigquery/BigqueryUtils.java | 169 + .../registry/bigquery/package-info.java | 16 + .../google/domain/registry/braintree/BUILD | 15 + .../registry/braintree/BraintreeModule.java | 47 + .../registry/braintree/package-info.java | 17 + java/com/google/domain/registry/config/BUILD | 18 + .../domain/registry/config/ConfigModule.java | 558 + .../domain/registry/config/ConfigUtils.java | 37 + .../registry/config/RegistryConfig.java | 252 + .../registry/config/RegistryEnvironment.java | 90 + .../registry/config/TestRegistryConfig.java | 191 + .../domain/registry/config/package-info.java | 16 + java/com/google/domain/registry/cron/BUILD | 25 + .../registry/cron/CommitLogFanoutAction.java | 58 + .../domain/registry/cron/CronModule.java | 76 + .../domain/registry/cron/TldFanoutAction.java | 134 + .../domain/registry/cron/package-info.java | 16 + java/com/google/domain/registry/dns/BUILD | 41 + .../domain/registry/dns/DnsConstants.java | 35 + .../google/domain/registry/dns/DnsModule.java | 93 + .../google/domain/registry/dns/DnsQueue.java | 161 + .../registry/dns/PublishDnsUpdatesAction.java | 98 + .../registry/dns/ReadDnsQueueAction.java | 204 + .../domain/registry/dns/RefreshDns.java | 80 + .../domain/registry/dns/WriteDnsTask.java | 158 + .../domain/registry/dns/writer/api/BUILD | 15 + .../registry/dns/writer/api/DnsWriter.java | 48 + .../dns/writer/api/DnsWriterZone.java | 24 + .../dns/writer/api/VoidDnsWriter.java | 49 + .../dns/writer/api/VoidDnsWriterModule.java | 28 + java/com/google/domain/registry/env/BUILD | 4 + .../google/domain/registry/env/common/BUILD | 5 + .../common/META-INF/appengine-application.xml | 4 + .../env/common/META-INF/application.xml | 34 + .../domain/registry/env/common/backend/BUILD | 7 + .../common/backend/WEB-INF/logging.properties | 13 + .../env/common/backend/WEB-INF/web.xml | 499 + .../domain/registry/env/common/default/BUILD | 7 + .../default/WEB-INF/datastore-indexes.xml | 136 + .../env/common/default/WEB-INF/dos.xml | 16 + .../common/default/WEB-INF/logging.properties | 13 + .../env/common/default/WEB-INF/queue.xml | 288 + .../env/common/default/WEB-INF/web.xml | 375 + .../domain/registry/env/common/tools/BUILD | 7 + .../common/tools/WEB-INF/logging.properties | 13 + .../registry/env/common/tools/WEB-INF/web.xml | 284 + .../domain/registry/env/production/BUILD | 4 + .../registry/env/production/backend/BUILD | 5 + .../backend/WEB-INF/appengine-web.xml | 33 + .../registry/env/production/default/BUILD | 5 + .../default/WEB-INF/appengine-web.xml | 34 + .../env/production/default/WEB-INF/cron.xml | 193 + .../registry/env/production/tools/BUILD | 5 + .../tools/WEB-INF/appengine-web.xml | 33 + java/com/google/domain/registry/export/BUILD | 44 + .../export/BigqueryPollJobAction.java | 173 + .../registry/export/BigquerySchemas.java | 148 + .../registry/export/CheckSnapshotServlet.java | 170 + .../registry/export/DatastoreBackupInfo.java | 150 + .../export/DatastoreBackupService.java | 123 + .../domain/registry/export/DriveModule.java | 61 + .../registry/export/ExportConstants.java | 96 + .../registry/export/ExportRequestModule.java | 49 + .../export/ExportReservedTermsTask.java | 85 + .../export/ExportSnapshotServlet.java | 82 + .../domain/registry/export/ExportUtils.java | 53 + .../registry/export/LoadSnapshotServlet.java | 207 + .../export/PublishDetailReportAction.java | 124 + .../registry/export/SyncGroupMembersTask.java | 235 + .../export/UpdateSnapshotViewServlet.java | 142 + .../domain/registry/export/package-info.java | 16 + .../google/domain/registry/export/sheet/BUILD | 26 + .../registry/export/sheet/SheetModule.java | 36 + .../export/sheet/SheetSynchronizer.java | 106 + .../sheet/SpreadsheetServiceModule.java | 39 + .../export/sheet/SyncRegistrarsSheet.java | 211 + .../export/sheet/SyncRegistrarsSheetTask.java | 162 + .../registry/export/sheet/package-info.java | 16 + java/com/google/domain/registry/flows/BUILD | 47 + .../registry/flows/EppConsoleServlet.java | 119 + .../domain/registry/flows/EppController.java | 114 + .../domain/registry/flows/EppException.java | 240 + .../registry/flows/EppServletUtils.java | 67 + .../domain/registry/flows/EppTlsServlet.java | 72 + .../domain/registry/flows/EppToolServlet.java | 53 + .../registry/flows/EppXmlTransformer.java | 170 + .../google/domain/registry/flows/Flow.java | 130 + .../domain/registry/flows/FlowRegistry.java | 334 + .../domain/registry/flows/FlowRunner.java | 191 + .../registry/flows/HttpSessionMetadata.java | 61 + .../domain/registry/flows/LoggedInFlow.java | 135 + .../flows/OwnedResourceMutateFlow.java | 43 + ...wnedResourceMutatePendingTransferFlow.java | 43 + .../flows/ResourceAsyncDeleteFlow.java | 85 + .../registry/flows/ResourceCheckFlow.java | 83 + .../registry/flows/ResourceCreateFlow.java | 129 + .../flows/ResourceCreateOrMutateFlow.java | 168 + .../registry/flows/ResourceDeleteFlow.java | 65 + .../domain/registry/flows/ResourceFlow.java | 103 + .../registry/flows/ResourceFlowUtils.java | 194 + .../registry/flows/ResourceInfoFlow.java | 49 + .../registry/flows/ResourceMutateFlow.java | 64 + .../ResourceMutatePendingTransferFlow.java | 104 + .../registry/flows/ResourceQueryFlow.java | 55 + .../flows/ResourceSyncDeleteFlow.java | 59 + .../flows/ResourceTransferApproveFlow.java | 73 + .../flows/ResourceTransferCancelFlow.java | 79 + .../registry/flows/ResourceTransferFlow.java | 27 + .../flows/ResourceTransferQueryFlow.java | 72 + .../flows/ResourceTransferRejectFlow.java | 63 + .../flows/ResourceTransferRequestFlow.java | 220 + .../registry/flows/ResourceUpdateFlow.java | 133 + .../registry/flows/SessionMetadata.java | 162 + .../registry/flows/SingleResourceFlow.java | 104 + .../StatelessRequestSessionMetadata.java | 87 + .../domain/registry/flows/TlsCredentials.java | 180 + .../registry/flows/TransactionalFlow.java | 23 + .../registry/flows/TransportCredentials.java | 39 + .../registry/flows/async/AsyncFlowUtils.java | 60 + .../flows/async/AsyncFlowsModule.java | 58 + .../async/DeleteContactResourceAction.java | 82 + .../flows/async/DeleteEppResourceAction.java | 272 + .../flows/async/DeleteHostResourceAction.java | 84 + .../async/DnsRefreshForHostRenameAction.java | 110 + .../flows/contact/ContactCheckFlow.java | 45 + .../flows/contact/ContactCreateFlow.java | 65 + .../flows/contact/ContactDeleteFlow.java | 87 + .../flows/contact/ContactFlowUtils.java | 77 + .../flows/contact/ContactInfoFlow.java | 27 + .../contact/ContactTransferApproveFlow.java | 37 + .../contact/ContactTransferCancelFlow.java | 37 + .../contact/ContactTransferQueryFlow.java | 30 + .../contact/ContactTransferRejectFlow.java | 37 + .../contact/ContactTransferRequestFlow.java | 46 + .../flows/contact/ContactUpdateFlow.java | 54 + .../flows/domain/BaseDomainCheckFlow.java | 57 + .../flows/domain/BaseDomainCreateFlow.java | 376 + .../flows/domain/BaseDomainInfoFlow.java | 51 + .../flows/domain/BaseDomainUpdateFlow.java | 154 + .../flows/domain/ClaimsCheckFlow.java | 80 + .../flows/domain/DomainAllocateFlow.java | 223 + .../domain/DomainApplicationCreateFlow.java | 251 + .../domain/DomainApplicationDeleteFlow.java | 96 + .../domain/DomainApplicationInfoFlow.java | 117 + .../domain/DomainApplicationUpdateFlow.java | 95 + .../flows/domain/DomainCheckFlow.java | 128 + .../flows/domain/DomainCreateFlow.java | 197 + .../domain/DomainCreateOrAllocateFlow.java | 118 + .../flows/domain/DomainDeleteFlow.java | 198 + .../flows/domain/DomainFlowUtils.java | 966 + .../registry/flows/domain/DomainInfoFlow.java | 94 + .../flows/domain/DomainRenewFlow.java | 206 + .../domain/DomainRestoreRequestFlow.java | 208 + .../domain/DomainTransferApproveFlow.java | 138 + .../domain/DomainTransferCancelFlow.java | 59 + .../flows/domain/DomainTransferQueryFlow.java | 29 + .../domain/DomainTransferRejectFlow.java | 58 + .../domain/DomainTransferRequestFlow.java | 238 + .../flows/domain/DomainUpdateFlow.java | 165 + .../registry/flows/host/HostCheckFlow.java | 45 + .../registry/flows/host/HostCreateFlow.java | 143 + .../registry/flows/host/HostDeleteFlow.java | 87 + .../registry/flows/host/HostFlowUtils.java | 143 + .../registry/flows/host/HostInfoFlow.java | 26 + .../registry/flows/host/HostUpdateFlow.java | 235 + .../registry/flows/poll/PollAckFlow.java | 148 + .../domain/registry/flows/poll/PollFlow.java | 90 + .../registry/flows/poll/PollRequestFlow.java | 71 + .../registry/flows/session/HelloFlow.java | 27 + .../registry/flows/session/LoginFlow.java | 200 + .../registry/flows/session/LogoutFlow.java | 34 + java/com/google/domain/registry/gcs/BUILD | 18 + .../domain/registry/gcs/GcsServiceModule.java | 35 + .../google/domain/registry/gcs/GcsUtils.java | 101 + java/com/google/domain/registry/groups/BUILD | 25 + .../groups/DirectoryGroupsConnection.java | 171 + .../registry/groups/DirectoryModule.java | 62 + .../registry/groups/GroupsConnection.java | 62 + .../domain/registry/groups/GroupsModule.java | 28 + .../registry/groups/GroupssettingsModule.java | 61 + .../google/domain/registry/idn/Arabic-IDN.txt | 76 + .../domain/registry/idn/Armenian-IDN.txt | 61 + java/com/google/domain/registry/idn/BUILD | 4 + .../domain/registry/idn/Bengali-IDN.txt | 102 + .../domain/registry/idn/Chinese-IDN.txt | 19928 +++++++++++++++ .../domain/registry/idn/Cyrillic-IDN.txt | 57 + .../domain/registry/idn/Devanagari-IDN.txt | 152 + .../domain/registry/idn/Ethiopic-IDN.txt | 480 + .../domain/registry/idn/Georgian-IDN.txt | 105 + .../google/domain/registry/idn/Greek-IDN.txt | 136 + .../domain/registry/idn/Gurmukhi-IDN.txt | 97 + .../google/domain/registry/idn/Hebrew-IDN.txt | 55 + .../domain/registry/idn/Japanese-IDN.txt | 6589 +++++ .../domain/registry/idn/Kannada-IDN.txt | 108 + .../google/domain/registry/idn/Khmer-IDN.txt | 120 + .../google/domain/registry/idn/Korean-IDN.txt | 11219 +++++++++ .../google/domain/registry/idn/Latin-IDN.txt | 152 + .../domain/registry/idn/Malayalam-IDN.txt | 112 + .../domain/registry/idn/Myanmar-IDN.txt | 201 + .../google/domain/registry/idn/Oriya-IDN.txt | 104 + .../domain/registry/idn/Sinhala-IDN.txt | 102 + .../google/domain/registry/idn/Tamil-IDN.txt | 84 + .../google/domain/registry/idn/Telugu-IDN.txt | 108 + .../google/domain/registry/idn/Thai-IDN.txt | 92 + .../domain/registry/idn/Tibetan-IDN.txt | 138 + .../registry/idn/Traditional-Chinese-IDN.txt | 19963 ++++++++++++++++ .../google/domain/registry/keyring/api/BUILD | 16 + .../registry/keyring/api/KeyModule.java | 133 + .../domain/registry/keyring/api/Keyring.java | 165 + .../registry/keyring/api/PgpHelper.java | 176 + .../registry/keyring/api/VoidKeyring.java | 116 + .../keyring/api/VoidKeyringModule.java | 32 + .../registry/keyring/api/package-info.java | 16 + .../com/google/domain/registry/loadtest/BUILD | 30 + .../domain/registry/loadtest/LoadTask.java | 49 + .../registry/loadtest/LoadTestAction.java | 232 + .../registry/loadtest/LoadTestModule.java | 114 + .../loadtest/templates/contact_create.xml | 33 + .../loadtest/templates/contact_info.xml | 14 + .../loadtest/templates/domain_check.xml | 11 + .../loadtest/templates/domain_create.xml | 21 + .../loadtest/templates/domain_info.xml | 11 + .../loadtest/templates/host_create.xml | 11 + .../registry/loadtest/templates/host_info.xml | 11 + .../google/domain/registry/mapreduce/BUILD | 26 + .../registry/mapreduce/ChunkingKeyInput.java | 113 + .../mapreduce/ConcatenatingInput.java | 66 + .../registry/mapreduce/EppResourceInputs.java | 396 + .../registry/mapreduce/MapreduceAction.java | 24 + .../registry/mapreduce/MapreduceModule.java | 52 + .../registry/mapreduce/MapreduceRunner.java | 246 + .../domain/registry/mapreduce/NullInput.java | 54 + .../registry/model/AbstractFieldExposer.java | 35 + java/com/google/domain/registry/model/BUILD | 94 + .../registry/model/BackupGroupRoot.java | 44 + .../domain/registry/model/Buildable.java | 108 + .../registry/model/CreateAutoTimestamp.java | 40 + .../domain/registry/model/EntityClasses.java | 129 + .../domain/registry/model/EppResource.java | 441 + .../registry/model/EppResourceUtils.java | 408 + .../registry/model/ImmutableObject.java | 167 + .../domain/registry/model/JsonMapBuilder.java | 91 + .../domain/registry/model/Jsonifiable.java | 29 + .../domain/registry/model/ModelUtils.java | 296 + .../domain/registry/model/RoidSuffixes.java | 65 + .../domain/registry/model/SchemaVersion.java | 75 + .../registry/model/UpdateAutoTimestamp.java | 43 + .../annotations/ExternalMessagingName.java | 27 + .../model/annotations/NotBackedUp.java | 47 + .../model/annotations/VirtualEntity.java | 32 + .../registry/model/billing/BillingEvent.java | 541 + .../model/billing/RegistrarBillingEntry.java | 212 + .../model/billing/RegistrarBillingUtils.java | 100 + .../model/billing/RegistrarCredit.java | 216 + .../model/billing/RegistrarCreditBalance.java | 253 + .../model/common/CrossTldSingleton.java | 35 + .../model/common/EntityGroupRoot.java | 47 + .../model/common/GaeUserIdConverter.java | 78 + .../model/common/PersistedRangeLong.java | 56 + .../registry/model/common/TimeOfYear.java | 93 + .../model/common/TimedTransitionProperty.java | 189 + .../model/contact/ContactAddress.java | 37 + .../model/contact/ContactAuthInfo.java | 51 + .../model/contact/ContactCommand.java | 239 + .../model/contact/ContactPhoneNumber.java | 35 + .../model/contact/ContactResource.java | 259 + .../registry/model/contact/Disclose.java | 136 + .../registry/model/contact/PostalInfo.java | 122 + .../registry/model/contact/package-info.java | 31 + .../model/domain/DesignatedContact.java | 73 + .../model/domain/DomainApplication.java | 172 + .../registry/model/domain/DomainAuthInfo.java | 64 + .../registry/model/domain/DomainBase.java | 293 + .../registry/model/domain/DomainCommand.java | 462 + .../model/domain/DomainRenewData.java | 41 + .../registry/model/domain/DomainResource.java | 413 + .../registry/model/domain/DomainUtils.java | 43 + .../registry/model/domain/GracePeriod.java | 137 + .../domain/registry/model/domain/Period.java | 59 + .../registry/model/domain/ReferenceUnion.java | 104 + .../allocate/AllocateCreateExtension.java | 85 + .../model/domain/allocate/package-info.java | 31 + .../registry/model/domain/fee/BaseFee.java | 86 + .../model/domain/fee/BaseFeeCommand.java | 48 + .../domain/fee/BaseFeeCommandResponse.java | 54 + .../model/domain/fee/BaseFeeRequest.java | 52 + .../model/domain/fee/BaseFeeResponse.java | 91 + .../registry/model/domain/fee/Credit.java | 29 + .../domain/registry/model/domain/fee/Fee.java | 29 + .../model/domain/fee/FeeCheckExtension.java | 54 + .../domain/fee/FeeCheckResponseExtension.java | 62 + .../domain/fee/FeeCommandDescriptor.java | 67 + .../model/domain/fee/FeeCreateExtension.java | 25 + .../fee/FeeCreateResponseExtension.java | 33 + .../fee/FeeDeleteResponseExtension.java | 59 + .../model/domain/fee/FeeInfoExtension.java | 25 + .../domain/fee/FeeInfoResponseExtension.java | 31 + .../model/domain/fee/FeeRenewExtension.java | 25 + .../domain/fee/FeeRenewResponseExtension.java | 33 + .../domain/fee/FeeTransferExtension.java | 25 + .../fee/FeeTransferResponseExtension.java | 33 + .../model/domain/fee/FeeUpdateExtension.java | 25 + .../fee/FeeUpdateResponseExtension.java | 33 + .../model/domain/fee/package-info.java | 31 + .../launch/ApplicationIdTargetExtension.java | 23 + .../domain/launch/ApplicationStatus.java | 58 + .../domain/launch/LaunchCheckExtension.java | 83 + .../launch/LaunchCheckResponseExtension.java | 94 + .../domain/launch/LaunchCreateExtension.java | 117 + .../launch/LaunchCreateResponseExtension.java | 32 + .../domain/launch/LaunchDeleteExtension.java | 25 + .../model/domain/launch/LaunchExtension.java | 58 + .../domain/launch/LaunchInfoExtension.java | 35 + .../launch/LaunchInfoResponseExtension.java | 59 + .../model/domain/launch/LaunchNotice.java | 133 + .../model/domain/launch/LaunchPhase.java | 126 + .../domain/launch/LaunchUpdateExtension.java | 25 + .../model/domain/launch/package-info.java | 31 + .../domain/metadata/MetadataExtension.java | 53 + .../model/domain/metadata/package-info.java | 27 + .../registry/model/domain/package-info.java | 39 + .../model/domain/rgp/GracePeriodStatus.java | 104 + .../model/domain/rgp/RestoreCommand.java | 48 + .../model/domain/rgp/RgpInfoExtension.java | 35 + .../model/domain/rgp/RgpUpdateExtension.java | 31 + .../model/domain/rgp/package-info.java | 27 + .../domain/secdns/DelegationSignerData.java | 95 + .../domain/secdns/SecDnsCreateExtension.java | 49 + .../domain/secdns/SecDnsInfoExtension.java | 38 + .../domain/secdns/SecDnsUpdateExtension.java | 106 + .../model/domain/secdns/package-info.java | 27 + .../registry/model/eppcommon/Address.java | 133 + .../registry/model/eppcommon/AuthInfo.java | 90 + .../registry/model/eppcommon/PhoneNumber.java | 88 + .../model/eppcommon/PresenceMarker.java | 35 + .../model/eppcommon/ProtocolDefinition.java | 113 + .../registry/model/eppcommon/StatusValue.java | 106 + .../domain/registry/model/eppcommon/Trid.java | 85 + .../model/eppcommon/package-info.java | 22 + .../registry/model/eppinput/EppInput.java | 361 + .../model/eppinput/ResourceCommand.java | 152 + .../registry/model/eppinput/package-info.java | 27 + .../registry/model/eppoutput/CheckData.java | 167 + .../registry/model/eppoutput/CreateData.java | 84 + .../registry/model/eppoutput/EppOutput.java | 53 + .../registry/model/eppoutput/Greeting.java | 88 + .../registry/model/eppoutput/Response.java | 202 + .../registry/model/eppoutput/Result.java | 190 + .../model/eppoutput/package-info.java | 31 + .../model/export/LogsExportCursor.java | 82 + .../registry/model/generate_field_exposer.sh | 36 + .../model/generate_field_exposer_registry.sh | 31 + .../registry/model/host/HostCommand.java | 143 + .../registry/model/host/HostResource.java | 208 + .../model/host/InetAddressAdapter.java | 69 + .../registry/model/host/package-info.java | 34 + .../model/index/DomainApplicationIndex.java | 132 + .../model/index/EppResourceIndex.java | 68 + .../model/index/EppResourceIndexBucket.java | 66 + .../registry/model/index/ForeignKeyIndex.java | 168 + .../model/mark/CommonMarkContactFields.java | 74 + .../registry/model/mark/CommonMarkFields.java | 84 + .../domain/registry/model/mark/CourtMark.java | 66 + .../domain/registry/model/mark/Mark.java | 60 + .../registry/model/mark/MarkAddress.java | 32 + .../registry/model/mark/MarkContact.java | 43 + .../registry/model/mark/MarkHolder.java | 43 + .../registry/model/mark/MarkPhoneNumber.java | 32 + .../registry/model/mark/MarkProtection.java | 54 + .../registry/model/mark/ProtectedMark.java | 43 + .../domain/registry/model/mark/Trademark.java | 99 + .../model/mark/TreatyOrStatuteMark.java | 65 + .../registry/model/mark/package-info.java | 31 + .../registry/model/ofy/AugmentedDeleter.java | 90 + .../registry/model/ofy/AugmentedSaver.java | 63 + .../registry/model/ofy/CommitLogBucket.java | 177 + .../model/ofy/CommitLogCheckpoint.java | 98 + .../model/ofy/CommitLogCheckpointRoot.java | 64 + .../registry/model/ofy/CommitLogManifest.java | 90 + .../registry/model/ofy/CommitLogMutation.java | 94 + .../registry/model/ofy/CommitLoggedWork.java | 213 + .../registry/model/ofy/ObjectifyService.java | 182 + .../google/domain/registry/model/ofy/Ofy.java | 351 + .../domain/registry/model/ofy/OfyFilter.java | 44 + .../registry/model/ofy/ReadOnlyWork.java | 41 + .../ofy/SessionKeyExposingObjectify.java | 34 + .../ofy/TimestampInversionException.java | 64 + .../registry/model/ofy/TransactionInfo.java | 99 + .../domain/registry/model/package-info.java | 48 + .../registry/model/poll/MessageQueueInfo.java | 70 + .../PendingActionNotificationResponse.java | 124 + .../registry/model/poll/PollMessage.java | 324 + .../poll/PollMessageExternalKeyConverter.java | 106 + .../registry/model/poll/package-info.java | 31 + .../domain/registry/model/rde/RdeMode.java | 38 + .../registry/model/rde/RdeNamingUtils.java | 54 + .../registry/model/rde/RdeRevision.java | 89 + .../registry/model/registrar/Registrar.java | 850 + .../model/registrar/RegistrarAddress.java | 45 + .../model/registrar/RegistrarContact.java | 318 + .../registry/model/registry/Registries.java | 112 + .../registry/model/registry/Registry.java | 782 + .../model/registry/RegistryCursor.java | 92 + .../registry/label/BaseDomainLabelList.java | 193 + .../registry/label/DomainLabelEntry.java | 84 + .../model/registry/label/PremiumList.java | 383 + .../model/registry/label/ReservationType.java | 46 + .../model/registry/label/ReservedList.java | 316 + .../model/registry/label/package-info.java | 16 + .../model/reporting/HistoryEntry.java | 225 + .../domain/registry/model/server/Lock.java | 253 + .../registry/model/server/ServerSecret.java | 67 + .../model/smd/AbstractSignedMark.java | 23 + .../registry/model/smd/EncodedSignedMark.java | 76 + .../domain/registry/model/smd/IssuerInfo.java | 69 + .../smd/RemoveWhitespaceTextAdapter.java | 39 + .../domain/registry/model/smd/SignedMark.java | 86 + .../model/smd/SignedMarkRevocationList.java | 191 + .../registry/model/smd/package-info.java | 31 + .../registry/model/tmch/ClaimsListShard.java | 277 + .../domain/registry/model/tmch/TmchCrl.java | 75 + .../model/transfer/BaseTransferObject.java | 118 + .../registry/model/transfer/TransferData.java | 177 + .../model/transfer/TransferResponse.java | 110 + .../model/transfer/TransferStatus.java | 54 + .../registry/model/transfer/package-info.java | 31 + .../AbstractSimpleTranslatorFactory.java | 63 + .../CidrAddressBlockTranslatorFactory.java | 40 + .../CommitLogRevisionsTranslatorFactory.java | 77 + .../CreateAutoTimestampTranslatorFactory.java | 54 + .../translators/CurrencyUnitAdapter.java | 44 + .../CurrencyUnitTranslatorFactory.java | 40 + .../DurationTranslatorFactory.java | 39 + .../translators/EnumToAttributeAdapter.java | 56 + .../ImmutableSortedMapTranslatorFactory.java | 168 + .../InetAddressTranslatorFactory.java | 42 + .../ReadableInstantUtcTranslatorFactory.java | 68 + .../model/translators/StatusValueAdapter.java | 26 + .../UpdateAutoTimestampTranslatorFactory.java | 54 + .../domain/registry/module/backend/BUILD | 50 + .../module/backend/BackendComponent.java | 74 + .../module/backend/BackendModule.java | 39 + .../backend/BackendRequestComponent.java | 102 + .../module/backend/BackendServlet.java | 58 + .../registry/module/backend/package-info.java | 16 + .../domain/registry/module/frontend/BUILD | 44 + .../module/frontend/FrontendComponent.java | 44 + .../frontend/FrontendRequestComponent.java | 59 + .../module/frontend/FrontendServlet.java | 58 + .../module/frontend/package-info.java | 16 + .../google/domain/registry/module/tools/BUILD | 43 + .../registry/module/tools/ToolsComponent.java | 62 + .../module/tools/ToolsRequestComponent.java | 71 + .../registry/module/tools/ToolsServlet.java | 58 + .../domain/registry/monitoring/whitebox/BUILD | 31 + .../monitoring/whitebox/EppMetrics.java | 72 + .../registry/monitoring/whitebox/Metrics.java | 76 + .../whitebox/MetricsTaskServlet.java | 158 + .../monitoring/whitebox/package-info.java | 16 + java/com/google/domain/registry/rdap/BUILD | 30 + .../domain/registry/rdap/RdapActionBase.java | 178 + .../registry/rdap/RdapAutnumAction.java | 55 + .../registry/rdap/RdapDomainAction.java | 64 + .../registry/rdap/RdapDomainSearchAction.java | 270 + .../registry/rdap/RdapEntityAction.java | 90 + .../registry/rdap/RdapEntitySearchAction.java | 166 + .../domain/registry/rdap/RdapHelpAction.java | 139 + .../domain/registry/rdap/RdapIpAction.java | 56 + .../registry/rdap/RdapJsonFormatter.java | 721 + .../domain/registry/rdap/RdapModule.java | 67 + .../registry/rdap/RdapNameserverAction.java | 64 + .../rdap/RdapNameserverSearchAction.java | 181 + .../registry/rdap/RdapSearchPattern.java | 155 + java/com/google/domain/registry/rde/BUILD | 41 + .../domain/registry/rde/BrdaCopyTask.java | 130 + .../rde/ContactResourceToXjcConverter.java | 193 + .../domain/registry/rde/DepositFragment.java | 36 + .../rde/DomainResourceToXjcConverter.java | 291 + .../domain/registry/rde/EscrowTaskRunner.java | 121 + .../google/domain/registry/rde/Ghostryde.java | 522 + .../rde/HostResourceToXjcConverter.java | 75 + .../domain/registry/rde/JSchModule.java | 61 + .../domain/registry/rde/JSchSftpChannel.java | 48 + .../domain/registry/rde/JSchSshSession.java | 128 + .../domain/registry/rde/PendingDeposit.java | 44 + .../registry/rde/PendingDepositChecker.java | 133 + .../domain/registry/rde/RdeAdapter.java | 40 + .../domain/registry/rde/RdeCounter.java | 97 + .../domain/registry/rde/RdeMarshaller.java | 165 + .../google/domain/registry/rde/RdeModule.java | 70 + .../domain/registry/rde/RdeReportTask.java | 102 + .../domain/registry/rde/RdeReporter.java | 124 + .../domain/registry/rde/RdeResourceType.java | 66 + .../domain/registry/rde/RdeStagingAction.java | 208 + .../domain/registry/rde/RdeStagingMapper.java | 193 + .../registry/rde/RdeStagingReducer.java | 226 + .../domain/registry/rde/RdeUploadTask.java | 221 + .../domain/registry/rde/RdeUploadUrl.java | 216 + .../google/domain/registry/rde/RdeUtil.java | 99 + .../registry/rde/RegistrarToXjcConverter.java | 187 + .../rde/RydePgpCompressionOutputStream.java | 59 + .../rde/RydePgpEncryptionOutputStream.java | 120 + .../registry/rde/RydePgpFileOutputStream.java | 71 + .../rde/RydePgpSigningOutputStream.java | 112 + .../registry/rde/RydeTarOutputStream.java | 70 + .../domain/registry/rde/package-info.java | 23 + .../domain/registry/request/Action.java | 64 + .../domain/registry/request/Actions.java | 31 + java/com/google/domain/registry/request/BUILD | 46 + .../request/DelegatedOAuthScopes.java | 28 + .../domain/registry/request/Header.java | 26 + .../registry/request/HttpException.java | 229 + .../registry/request/JsonActionRunner.java | 50 + .../domain/registry/request/JsonPayload.java | 28 + .../domain/registry/request/JsonResponse.java | 68 + .../domain/registry/request/Modules.java | 202 + .../domain/registry/request/OAuthScopes.java | 25 + .../domain/registry/request/Parameter.java | 26 + .../domain/registry/request/ParameterMap.java | 24 + .../domain/registry/request/Payload.java | 28 + .../registry/request/RequestHandler.java | 158 + .../registry/request/RequestMethod.java | 28 + .../registry/request/RequestModule.java | 154 + .../registry/request/RequestParameters.java | 201 + .../domain/registry/request/RequestPath.java | 28 + .../domain/registry/request/RequestScope.java | 30 + .../domain/registry/request/Response.java | 64 + .../domain/registry/request/ResponseImpl.java | 73 + .../google/domain/registry/request/Route.java | 47 + .../domain/registry/request/Router.java | 107 + .../registry/request/ServletDelegate.java | 51 + .../domain/registry/request/package-info.java | 16 + .../com/google/domain/registry/security/BUILD | 41 + .../domain/registry/security/JsonHttp.java | 97 + .../registry/security/JsonResponseHelper.java | 63 + .../security/JsonTransportServlet.java | 76 + .../security/XsrfProtectedServlet.java | 86 + .../registry/security/XsrfTokenManager.java | 106 + .../registry/security/package-info.java | 16 + .../domain/registry/storage/drive/BUILD | 23 + .../storage/drive/DriveConnection.java | 151 + .../domain/registry/tldconfig/idn/BUILD | 21 + .../tldconfig/idn/IdnLabelValidator.java | 56 + .../registry/tldconfig/idn/IdnTable.java | 142 + .../registry/tldconfig/idn/IdnTableEnum.java | 49 + .../idn/JapaneseLanguageValidator.java | 122 + .../tldconfig/idn/LanguageValidator.java | 33 + .../registry/tldconfig/idn/extended_latin.txt | 133 + .../domain/registry/tldconfig/idn/ja.txt | 6573 +++++ java/com/google/domain/registry/tmch/BUILD | 38 + .../registry/tmch/ClaimsListParser.java | 80 + .../google/domain/registry/tmch/LordnLog.java | 257 + .../tmch/LordnRequestInitializer.java | 48 + .../domain/registry/tmch/LordnTask.java | 162 + .../google/domain/registry/tmch/Marksdb.java | 129 + .../registry/tmch/NordnUploadAction.java | 165 + .../registry/tmch/NordnVerifyAction.java | 141 + .../domain/registry/tmch/SmdrlCsvParser.java | 72 + .../tmch/TmchCertificateAuthority.java | 143 + .../domain/registry/tmch/TmchCrlTask.java | 48 + .../google/domain/registry/tmch/TmchData.java | 54 + .../domain/registry/tmch/TmchDnlTask.java | 59 + .../domain/registry/tmch/TmchModule.java | 77 + .../domain/registry/tmch/TmchSmdrlTask.java | 59 + .../registry/tmch/TmchXmlSignature.java | 192 + .../domain/registry/tmch/icann-tmch-test.crl | 15 + .../domain/registry/tmch/icann-tmch-test.crt | 26 + .../domain/registry/tmch/icann-tmch.crl | 13 + .../domain/registry/tmch/icann-tmch.crt | 25 + .../registry/tmch/marksdb-public-key.asc | 31 + .../domain/registry/tmch/package-info.java | 16 + .../registry/tools/AllocateDomainCommand.java | 187 + .../registry/tools/AppEngineConnection.java | 179 + .../registry/tools/AuctionStatusCommand.java | 121 + java/com/google/domain/registry/tools/BUILD | 90 + .../registry/tools/BigqueryCommand.java | 46 + .../tools/BigqueryCommandUtilities.java | 54 + .../registry/tools/BigqueryParameters.java | 103 + .../tools/CanonicalizeLabelsCommand.java | 91 + .../registry/tools/CheckSnapshotCommand.java | 49 + .../google/domain/registry/tools/Command.java | 35 + .../registry/tools/CommandUtilities.java | 68 + .../registry/tools/ConfirmingCommand.java | 64 + .../registry/tools/ConvertIdnCommand.java | 48 + .../tools/CreateAnchorTenantCommand.java | 102 + .../tools/CreateAuctionCreditsCommand.java | 215 + .../registry/tools/CreateContactCommand.java | 137 + .../tools/CreateCreditBalanceCommand.java | 77 + .../registry/tools/CreateCreditCommand.java | 95 + .../CreateOrUpdatePremiumListCommand.java | 137 + .../tools/CreateOrUpdateRegistrarCommand.java | 398 + .../CreateOrUpdateReservedListCommand.java | 51 + .../tools/CreateOrUpdateTldCommand.java | 408 + .../tools/CreatePremiumListCommand.java | 51 + .../tools/CreateRegistrarCommand.java | 88 + .../tools/CreateRegistrarGroupsCommand.java | 90 + .../tools/CreateReservedListCommand.java | 80 + .../tools/CreateSandboxTldCommand.java | 34 + .../registry/tools/CreateTldCommand.java | 83 + .../registry/tools/DeleteCreditCommand.java | 60 + .../registry/tools/DeleteDomainCommand.java | 60 + .../registry/tools/DeleteEntityCommand.java | 69 + .../tools/DeleteEppResourceCommand.java | 114 + .../tools/DeletePremiumListCommand.java | 73 + .../tools/DeleteReservedListCommand.java | 53 + .../tools/DomainApplicationInfoCommand.java | 69 + .../tools/DomainCheckClaimsCommand.java | 52 + .../registry/tools/DomainCheckCommand.java | 51 + .../registry/tools/DomainCheckFeeCommand.java | 51 + .../tools/EncryptEscrowDepositCommand.java | 59 + .../domain/registry/tools/EppToolCommand.java | 166 + .../tools/EscrowDepositEncryptor.java | 96 + .../registry/tools/ExecuteEppCommand.java | 59 + .../GenerateApplicationsReportCommand.java | 182 + .../tools/GenerateAuctionDataCommand.java | 257 + .../tools/GenerateDnsReportCommand.java | 158 + .../tools/GenerateEscrowDepositCommand.java | 243 + .../registry/tools/GenerateLordnCommand.java | 91 + .../tools/GenerateZoneFilesCommand.java | 77 + .../registry/tools/GetApplicationCommand.java | 41 + .../tools/GetApplicationIdsCommand.java | 73 + .../tools/GetAppliedLabelsCommand.java | 96 + .../registry/tools/GetClaimsListCommand.java | 53 + .../registry/tools/GetContactCommand.java | 41 + .../registry/tools/GetDomainCommand.java | 41 + .../registry/tools/GetEppResourceCommand.java | 78 + .../tools/GetHistoryEntriesCommand.java | 63 + .../domain/registry/tools/GetHostCommand.java | 41 + .../registry/tools/GetRegistrarCommand.java | 46 + .../tools/GetResourceByKeyCommand.java | 56 + .../registry/tools/GetSchemaCommand.java | 29 + .../domain/registry/tools/GetTldCommand.java | 43 + .../registry/tools/GhostrydeCommand.java | 124 + .../domain/registry/tools/GtechTool.java | 79 + .../tools/HashCertificateCommand.java | 51 + .../domain/registry/tools/HelpCommand.java | 48 + .../domain/registry/tools/Injector.java | 56 + .../registry/tools/ListCreditsCommand.java | 76 + .../registry/tools/ListCursorsCommand.java | 72 + .../registry/tools/ListDomainsCommand.java | 45 + .../registry/tools/ListHostsCommand.java | 29 + .../registry/tools/ListObjectsCommand.java | 141 + .../tools/ListPremiumListsCommand.java | 29 + .../registry/tools/ListRegistrarsCommand.java | 30 + .../tools/ListReservedListsCommand.java | 29 + .../registry/tools/ListTldsCommand.java | 30 + .../registry/tools/LoadSnapshotCommand.java | 126 + .../registry/tools/LoggingParameters.java | 78 + .../tools/MakeBillingTablesCommand.java | 219 + .../registry/tools/MutatingCommand.java | 237 + .../tools/MutatingEppToolCommand.java | 41 + .../registry/tools/PasswordGenerator.java | 22 + .../registry/tools/PendingEscrowCommand.java | 55 + .../tools/PublishDetailReportCommand.java | 104 + .../tools/RandomPasswordGenerator.java | 46 + .../tools/RegistrarActivityReportCommand.java | 116 + .../tools/RegistrarContactCommand.java | 264 + .../domain/registry/tools/RegistryCli.java | 139 + .../domain/registry/tools/RegistryTool.java | 83 + .../registry/tools/RegistryToolComponent.java | 59 + .../tools/RegistryToolEnvironment.java | 114 + .../registry/tools/RegistryToolModule.java | 47 + .../tools/SendEscrowReportToIcannCommand.java | 50 + .../registry/tools/ServerSideCommand.java | 40 + .../registry/tools/SetupOteCommand.java | 222 + .../tools/UpdateApplicationStatusCommand.java | 183 + .../tools/UpdateClaimsNoticeCommand.java | 120 + .../registry/tools/UpdateCreditsCommand.java | 142 + .../registry/tools/UpdateCursorsCommand.java | 64 + .../tools/UpdatePremiumListCommand.java | 32 + .../tools/UpdateRegistrarCommand.java | 33 + .../tools/UpdateReservedListCommand.java | 50 + .../tools/UpdateSandboxTldCommand.java | 34 + .../tools/UpdateServerLocksCommand.java | 117 + .../registry/tools/UpdateSmdCommand.java | 112 + .../registry/tools/UpdateTldCommand.java | 60 + .../tools/UploadClaimsListCommand.java | 65 + .../domain/registry/tools/UserIdProvider.java | 29 + .../tools/ValidateEscrowDepositCommand.java | 178 + .../ValidateLoginCredentialsCommand.java | 145 + .../registry/tools/VerifyOteCommand.java | 119 + .../registry/tools/WhoisQueryCommand.java | 58 + .../tools/javascrap/LoadAndResaveCommand.java | 78 + .../domain/registry/tools/logging.properties | 3 + .../domain/registry/tools/mapreduce/BUILD | 30 + .../mapreduce/DeleteProberDataAction.java | 171 + .../ResaveAllEppResourcesAction.java | 76 + .../domain/registry/tools/package-info.java | 16 + .../google/domain/registry/tools/params/BUILD | 22 + .../tools/params/DateTimeParameter.java | 58 + .../tools/params/DurationParameter.java | 31 + .../params/EppResourceTypeParameter.java | 37 + .../tools/params/HostAndPortParameter.java | 26 + .../params/InternetDomainNameParameter.java | 31 + .../tools/params/LocalDateParameter.java | 31 + .../tools/params/LoggingLevelParameter.java | 35 + .../registry/tools/params/LongParameter.java | 24 + .../registry/tools/params/MoneyParameter.java | 40 + .../tools/params/OptionalLongParameter.java | 19 + .../OptionalParameterConverterValidator.java | 47 + .../params/OptionalPhoneNumberParameter.java | 19 + .../tools/params/OptionalStringParameter.java | 19 + .../params/ParameterConverterValidator.java | 49 + .../tools/params/ParameterFactory.java | 59 + .../registry/tools/params/PathParameter.java | 101 + .../tools/params/PhoneNumberParameter.java | 35 + .../tools/params/StringParameter.java | 24 + .../tools/params/TransitionListParameter.java | 89 + .../tools/params/YearMonthParameter.java | 31 + .../registry/tools/params/package-info.java | 16 + .../google/domain/registry/tools/server/BUILD | 30 + .../tools/server/CreateGroupsTask.java | 130 + .../CreateOrUpdatePremiumListAction.java | 52 + .../tools/server/CreatePremiumListAction.java | 68 + .../tools/server/DeleteEntityAction.java | 118 + .../tools/server/GenerateZoneFilesAction.java | 333 + .../tools/server/KillAllCommitLogsAction.java | 106 + .../server/KillAllEppResourcesAction.java | 110 + .../tools/server/ListDomainsAction.java | 59 + .../tools/server/ListHostsAction.java | 69 + .../tools/server/ListObjectsAction.java | 286 + .../tools/server/ListPremiumListsAction.java | 46 + .../tools/server/ListRegistrarsAction.java | 58 + .../tools/server/ListReservedListsAction.java | 46 + .../registry/tools/server/ListTldsAction.java | 82 + .../tools/server/ToolsServerModule.java | 91 + .../tools/server/UpdatePremiumListAction.java | 69 + .../AnnihilateNonDefaultNamespacesAction.java | 136 + .../google/domain/registry/tools/soy/BUILD | 10 + .../registry/tools/soy/CreateAnchorTenant.soy | 48 + .../registry/tools/soy/CreateContact.soy | 72 + .../registry/tools/soy/DeleteDomain.soy | 28 + .../registry/tools/soy/DomainAllocate.soy | 75 + .../tools/soy/DomainApplicationInfo.soy | 29 + .../domain/registry/tools/soy/DomainCheck.soy | 21 + .../registry/tools/soy/DomainCheckClaims.soy | 28 + .../registry/tools/soy/DomainCheckFee.soy | 32 + .../domain/registry/tools/soy/Login.soy | 27 + .../registry/tools/soy/UpdateServerLocks.soy | 42 + .../registry/tools/sql/ReportingHistory.sql | 38 + .../tools/sql/ReportingIdentifiers.sql | 30 + .../registry/tools/sql/billing_data_view.sql | 175 + .../tools/sql/credit_balance_data_view.sql | 47 + .../registry/tools/sql/credit_data_view.sql | 38 + .../registry/tools/sql/currency_table.sql | 8 + .../tools/sql/premium_list_data_view.sql | 60 + .../tools/sql/recurring_event_data_view.sql | 166 + .../tools/sql/registrar_activity_report.sql | 17 + .../tools/sql/registrar_data_view.sql | 13 + .../registry/tools/sql/registry_data_view.sql | 32 + java/com/google/domain/registry/ui/BUILD | 206 + .../registry/ui/ConsoleConfigModule.java | 54 + .../domain/registry/ui/ConsoleDebug.java | 47 + .../ui/assets/html/brainframe-alpha.html | 8 + .../ui/assets/html/brainframe-map.html | 13 + .../registry/ui/assets/html/brainframe.html | 14 + .../ui/assets/html/insecure-brainframe.html | 10 + .../html/integration-test-brainframe.html | 4 + .../registry/ui/assets/images/ajax-loader.gif | Bin 0 -> 673 bytes .../registry/ui/assets/images/android_sad.png | Bin 0 -> 2601 bytes .../images/disclosure_arrow_dk_grey.png | Bin 0 -> 138 bytes .../images/disclosure_arrow_dk_grey_down.png | Bin 0 -> 138 bytes .../disclosure_arrow_dk_grey_up_down.png | Bin 0 -> 184 bytes .../registry/ui/assets/images/explore_24.png | Bin 0 -> 1016 bytes .../registry/ui/assets/images/folder.png | Bin 0 -> 309 bytes .../registry/ui/assets/images/glogo_black.png | Bin 0 -> 2431 bytes .../registry/ui/assets/images/google.png | Bin 0 -> 11619 bytes .../registry/ui/assets/images/homeContact.png | Bin 0 -> 3961 bytes .../ui/assets/images/homeResources.png | Bin 0 -> 3890 bytes .../ui/assets/images/homeSettings.png | Bin 0 -> 4741 bytes .../ui/assets/images/ic_contacts_blue_12.png | Bin 0 -> 535 bytes .../ui/assets/images/ic_contacts_blue_8.png | Bin 0 -> 327 bytes .../assets/images/icons/svg/Gcomm/search.svg | 17 + .../ui/assets/images/icons/svg/search.svg | 17 + .../ui/assets/images/icons/svg/settings.svg | 19 + .../registry/ui/assets/images/loader1x.gif | Bin 0 -> 28577 bytes .../registry/ui/assets/images/loader4x.gif | Bin 0 -> 81351 bytes .../registry/ui/assets/images/logo_sm.gif | Bin 0 -> 3972 bytes .../ui/assets/images/offline_lightning.png | Bin 0 -> 1073 bytes .../ui/assets/images/ribbon_certified-128.png | Bin 0 -> 2726 bytes .../ui/assets/images/ribbon_certified-64.png | Bin 0 -> 1470 bytes .../ui/assets/images/visibleOff_16.png | Bin 0 -> 556 bytes .../ui/assets/images/visibleOn_16.png | Bin 0 -> 480 bytes .../google/domain/registry/ui/compile_test.js | 24 + .../domain/registry/ui/conformance_proto.txt | 8 + java/com/google/domain/registry/ui/css/BUILD | 70 + .../domain/registry/ui/css/admin-console.css | 18 + .../registry/ui/css/admin_imports_raw.css | 5 + .../google/domain/registry/ui/css/console.css | 102 + .../registry/ui/css/contact-settings.css | 58 + .../domain/registry/ui/css/contact-us.css | 17 + .../domain/registry/ui/css/dashboard.css | 63 + .../domain/registry/ui/css/demo_css.css | 1 + .../com/google/domain/registry/ui/css/epp.css | 61 + .../google/domain/registry/ui/css/forms.css | 182 + .../domain/registry/ui/css/kd_components.css | 4737 ++++ .../registry/ui/css/registrar_imports_raw.css | 10 + .../domain/registry/ui/css/registry.css | 306 + .../domain/registry/ui/css/resources.css | 28 + .../registry/ui/css/security-settings.css | 67 + .../registry/ui/epptmpl/contact_info.xml | 14 + .../ui/epptmpl/contact_transfer_request.xml | 14 + .../domain_create_no_hosts_or_dsdata.xml | 18 + .../registry/ui/epptmpl/domain_delete.xml | 11 + .../epptmpl/domain_update_restore_request.xml | 17 + .../domain/registry/ui/epptmpl/hello.xml | 4 + .../registry/ui/epptmpl/login_valid.xml | 18 + .../domain/registry/ui/epptmpl/logout.xml | 6 + .../domain/registry/ui/epptmpl/poll.xml | 6 + .../google/domain/registry/ui/externs/BUILD | 12 + .../domain/registry/ui/externs/braintree.js | 450 + .../google/domain/registry/ui/externs/json.js | 116 + .../domain/registry/ui/externs/rpc_payment.js | 66 + .../registry/ui/externs/rpc_paymentsetup.js | 68 + .../com/google/domain/registry/ui/forms/BUILD | 13 + .../registry/ui/forms/FormException.java | 58 + .../domain/registry/ui/forms/FormField.java | 790 + .../registry/ui/forms/FormFieldException.java | 176 + .../domain/registry/ui/forms/FormFields.java | 126 + .../registry/ui/forms/package-info.java | 17 + .../com/google/domain/registry/ui/globals.txt | 5 + java/com/google/domain/registry/ui/html/BUILD | 7 + .../google/domain/registry/ui/html/error.html | 15 + .../google/domain/registry/ui/html/index.html | 6 + java/com/google/domain/registry/ui/js/BUILD | 19 + .../google/domain/registry/ui/js/admin/BUILD | 20 + .../domain/registry/ui/js/admin/console.js | 62 + .../domain/registry/ui/js/admin/main.js | 33 + .../domain/registry/ui/js/admin/registrar.js | 136 + .../domain/registry/ui/js/admin/registry.js | 139 + .../google/domain/registry/ui/js/component.js | 212 + .../google/domain/registry/ui/js/console.js | 123 + .../google/domain/registry/ui/js/edit_item.js | 294 + .../com/google/domain/registry/ui/js/forms.js | 135 + .../domain/registry/ui/js/menu_button.js | 135 + .../domain/registry/ui/js/registrar/BUILD | 31 + .../registry/ui/js/registrar/brainframe.js | 265 + .../registry/ui/js/registrar/console.js | 167 + .../registry/ui/js/registrar/contact.js | 125 + .../ui/js/registrar/contact_settings.js | 240 + .../registry/ui/js/registrar/contact_us.js | 49 + .../registry/ui/js/registrar/dashboard.js | 94 + .../domain/registry/ui/js/registrar/domain.js | 202 + .../registry/ui/js/registrar/epp_session.js | 131 + .../domain/registry/ui/js/registrar/host.js | 103 + .../domain/registry/ui/js/registrar/main.js | 35 + .../registry/ui/js/registrar/payment.js | 412 + .../registry/ui/js/registrar/resources.js | 50 + .../ui/js/registrar/security_settings.js | 110 + .../ui/js/registrar/whois_settings.js | 49 + .../ui/js/registrar/xml_resource_component.js | 217 + .../google/domain/registry/ui/js/resource.js | 92 + .../registry/ui/js/resource_component.js | 175 + .../google/domain/registry/ui/js/session.js | 125 + java/com/google/domain/registry/ui/js/util.js | 216 + java/com/google/domain/registry/ui/js/xml.js | 89 + .../domain/registry/ui/package-info.java | 16 + .../registry/ui/server/AbstractUiServlet.java | 105 + .../google/domain/registry/ui/server/BUILD | 32 + .../ui/server/RegistrarFormFields.java | 373 + .../registry/ui/server/SoyTemplateUtils.java | 139 + .../domain/registry/ui/server/StateCode.java | 82 + .../ui/server/admin/AdminResourceServlet.java | 131 + .../ui/server/admin/AdminUiServlet.java | 48 + .../domain/registry/ui/server/admin/BUILD | 36 + .../ui/server/admin/RegistrarServlet.java | 165 + .../ui/server/admin/RegistryServlet.java | 172 + .../ui/server/admin/VerifyOteServlet.java | 337 + .../ui/server/admin/package-info.java | 16 + .../domain/registry/ui/server/api/BUILD | 24 + .../ui/server/api/CheckApiServlet.java | 138 + .../registry/ui/server/api/package-info.java | 16 + .../registry/ui/server/package-info.java | 16 + .../domain/registry/ui/server/registrar/BUILD | 40 + .../ui/server/registrar/ConsoleUiServlet.java | 76 + .../registrar/RegistrarPaymentAction.java | 329 + .../RegistrarPaymentSetupAction.java | 110 + .../ui/server/registrar/RegistrarServlet.java | 261 + .../ui/server/registrar/ResourceServlet.java | 107 + .../ui/server/registrar/SessionUtils.java | 164 + .../ui/server/registrar/package-info.java | 16 + java/com/google/domain/registry/ui/soy/BUILD | 31 + .../google/domain/registry/ui/soy/Console.soy | 162 + .../google/domain/registry/ui/soy/Forms.soy | 308 + .../google/domain/registry/ui/soy/admin/BUILD | 41 + .../domain/registry/ui/soy/admin/Console.soy | 60 + .../registry/ui/soy/admin/Registrar.soy | 360 + .../domain/registry/ui/soy/admin/Registry.soy | 87 + .../google/domain/registry/ui/soy/api/BUILD | 22 + .../registry/ui/soy/api/DomainCheckFeeEpp.soy | 28 + .../domain/registry/ui/soy/registrar/BUILD | 108 + .../registry/ui/soy/registrar/Console.soy | 257 + .../registry/ui/soy/registrar/Contact.soy | 165 + .../registry/ui/soy/registrar/ContactEpp.soy | 104 + .../ui/soy/registrar/ContactSettings.soy | 291 + .../registry/ui/soy/registrar/Domain.soy | 206 + .../registry/ui/soy/registrar/DomainEpp.soy | 231 + .../domain/registry/ui/soy/registrar/Epp.soy | 43 + .../domain/registry/ui/soy/registrar/Host.soy | 94 + .../registry/ui/soy/registrar/HostEpp.soy | 96 + .../registry/ui/soy/registrar/Payment.soy | 126 + .../ui/soy/registrar/SecuritySettings.soy | 170 + .../ui/soy/registrar/WhoisSettings.soy | 216 + .../registry/util/AppEngineTimeLimiter.java | 83 + java/com/google/domain/registry/util/BUILD | 32 + .../registry/util/BasicHttpSession.java | 127 + .../domain/registry/util/CacheUtils.java | 59 + .../registry/util/CapturingLogHandler.java | 47 + .../registry/util/CidrAddressBlock.java | 471 + .../google/domain/registry/util/Clock.java | 27 + .../domain/registry/util/CollectionUtils.java | 153 + .../domain/registry/util/Concurrent.java | 102 + .../registry/util/DatastoreServiceUtils.java | 35 + .../domain/registry/util/DateTimeUtils.java | 81 + .../domain/registry/util/DiffUtils.java | 173 + .../domain/registry/util/DomainNameUtils.java | 42 + .../domain/registry/util/FixedClock.java | 32 + .../registry/util/FormattingLogger.java | 105 + .../domain/registry/util/HexDumper.java | 230 + .../registry/util/HttpServletUtils.java | 45 + java/com/google/domain/registry/util/Idn.java | 78 + .../registry/util/ImprovedInputStream.java | 151 + .../registry/util/ImprovedOutputStream.java | 130 + .../domain/registry/util/ListNamingUtils.java | 30 + .../domain/registry/util/NetworkUtils.java | 135 + .../registry/util/NonFinalForTesting.java | 40 + .../domain/registry/util/ObjectifyUtils.java | 29 + .../domain/registry/util/PathargMatcher.java | 69 + .../domain/registry/util/PipelineUtils.java | 27 + .../domain/registry/util/PosixTarHeader.java | 511 + .../registry/util/PreconditionsUtils.java | 48 + .../domain/registry/util/PredicateUtils.java | 45 + .../domain/registry/util/RegistrarUtils.java | 34 + .../domain/registry/util/ResourceUtils.java | 52 + .../google/domain/registry/util/Retrier.java | 108 + .../registry/util/SendEmailService.java | 37 + .../domain/registry/util/SendEmailUtils.java | 98 + .../domain/registry/util/SerializeUtils.java | 70 + .../google/domain/registry/util/Sleeper.java | 46 + .../domain/registry/util/SqlTemplate.java | 105 + .../domain/registry/util/SystemClock.java | 46 + .../domain/registry/util/SystemSleeper.java | 63 + .../domain/registry/util/TaskEnqueuer.java | 81 + .../domain/registry/util/TeeOutputStream.java | 69 + .../domain/registry/util/TypeUtils.java | 92 + .../registry/util/UrlFetchException.java | 60 + .../domain/registry/util/UrlFetchUtils.java | 108 + .../domain/registry/util/X509Utils.java | 183 + .../domain/registry/util/XmlEnumUtils.java | 31 + .../domain/registry/util/package-info.java | 16 + java/com/google/domain/registry/whois/BUILD | 30 + .../registry/whois/DomainLookupCommand.java | 39 + .../whois/DomainOrHostLookupCommand.java | 70 + .../registry/whois/DomainWhoisResponse.java | 180 + .../whois/NameserverLookupByHostCommand.java | 39 + .../whois/NameserverLookupByIpCommand.java | 67 + .../whois/NameserverWhoisResponse.java | 67 + .../whois/RegistrarLookupCommand.java | 105 + .../whois/RegistrarWhoisResponse.java | 97 + .../google/domain/registry/whois/Whois.java | 51 + .../domain/registry/whois/WhoisCommand.java | 29 + .../domain/registry/whois/WhoisException.java | 71 + .../registry/whois/WhoisHttpServer.java | 178 + .../domain/registry/whois/WhoisModule.java | 47 + .../domain/registry/whois/WhoisReader.java | 212 + .../domain/registry/whois/WhoisResponse.java | 37 + .../registry/whois/WhoisResponseImpl.java | 216 + .../domain/registry/whois/WhoisServer.java | 88 + .../domain/registry/whois/disclaimer.txt | 13 + .../domain/registry/whois/package-info.java | 16 + java/com/google/domain/registry/xjc/BUILD | 64 + .../domain/registry/xjc/README.missing-code | 7 + .../google/domain/registry/xjc/XjcObject.java | 72 + .../registry/xjc/XjcXmlTransformer.java | 83 + .../google/domain/registry/xjc/bindings.xjb | 375 + .../domain/registry/xjc/generated_files.bzl | 336 + .../registry/xjc/list_generated_files.sh | 66 + .../domain/registry/xjc/make_pkginfo.sh | 54 + .../domain/registry/xjc/package-info.java | 16 + .../domain/registry/xjc/package-info.java.in | 85 + java/com/google/domain/registry/xml/BUILD | 22 + .../domain/registry/xml/DateAdapter.java | 69 + .../domain/registry/xml/PeriodAdapter.java | 38 + .../registry/xml/UtcDateTimeAdapter.java | 72 + .../domain/registry/xml/ValidationMode.java | 24 + .../domain/registry/xml/XmlException.java | 31 + .../registry/xml/XmlFragmentMarshaller.java | 88 + .../domain/registry/xml/XmlTransformer.java | 326 + .../domain/registry/xml/package-info.java | 16 + .../domain/registry/xml/xsd/allocate.xsd | 39 + .../domain/registry/xml/xsd/contact.xsd | 389 + .../google/domain/registry/xml/xsd/domain.xsd | 434 + .../google/domain/registry/xml/xsd/dsig.xsd | 292 + .../google/domain/registry/xml/xsd/epp.xsd | 445 + .../google/domain/registry/xml/xsd/eppcom.xsd | 107 + .../google/domain/registry/xml/xsd/fee.xsd | 239 + .../google/domain/registry/xml/xsd/host.xsd | 242 + .../google/domain/registry/xml/xsd/iirdea.xsd | 35 + .../google/domain/registry/xml/xsd/launch.xsd | 246 + .../google/domain/registry/xml/xsd/mark.xsd | 246 + .../domain/registry/xml/xsd/metadata.xsd | 26 + .../domain/registry/xml/xsd/rde-contact.xsd | 96 + .../domain/registry/xml/xsd/rde-domain.xsd | 121 + .../domain/registry/xml/xsd/rde-eppparams.xsd | 50 + .../domain/registry/xml/xsd/rde-header.xsd | 44 + .../domain/registry/xml/xsd/rde-host.xsd | 73 + .../domain/registry/xml/xsd/rde-idn.xsd | 53 + .../domain/registry/xml/xsd/rde-nndn.xsd | 80 + .../registry/xml/xsd/rde-notification.xsd | 48 + .../domain/registry/xml/xsd/rde-policy.xsd | 28 + .../domain/registry/xml/xsd/rde-registrar.xsd | 165 + .../domain/registry/xml/xsd/rde-report.xsd | 37 + .../google/domain/registry/xml/xsd/rde.xsd | 100 + .../google/domain/registry/xml/xsd/rgp.xsd | 133 + .../google/domain/registry/xml/xsd/secdns.xsd | 95 + .../google/domain/registry/xml/xsd/smd.xsd | 71 + java/com/google/gdata/BUILD | 11 + java/com/google/testing/builddefs/BUILD | 1 + .../google/testing/builddefs/GenTestRules.bzl | 109 + javascript/closure/BUILD | 13 + javascript/template/soy/BUILD | 6 + .../com/google/domain/registry/backup/BUILD | 39 + .../backup/CommitLogCheckpointActionTest.java | 105 + .../CommitLogCheckpointStrategyTest.java | 327 + .../backup/DeleteOldCommitLogsActionTest.java | 177 + .../backup/ExportCommitLogDiffActionTest.java | 397 + .../backup/GcsDiffFileListerTest.java | 153 + .../backup/RestoreCommitLogsActionTest.java | 319 + .../com/google/domain/registry/bigquery/BUILD | 28 + .../bigquery/BigqueryConnectionTest.java | 31 + .../registry/bigquery/BigqueryUtilsTest.java | 150 + .../com/google/domain/registry/config/BUILD | 21 + .../config/RegistryEnvironmentTest.java | 41 + .../com/google/domain/registry/cron/BUILD | 32 + .../cron/CommitLogFanoutActionTest.java | 74 + .../registry/cron/TldFanoutActionTest.java | 212 + .../com/google/domain/registry/dns/BUILD | 44 + .../domain/registry/dns/DnsInjectionTest.java | 106 + .../domain/registry/dns/DnsQueueTest.java | 93 + .../domain/registry/dns/DnsTestComponent.java | 37 + .../dns/PublishDnsUpdatesActionTest.java | 134 + .../registry/dns/ReadDnsQueueActionTest.java | 267 + .../domain/registry/dns/RefreshDnsTest.java | 116 + .../domain/registry/dns/WriteDnsTaskTest.java | 197 + .../domain/registry/dns/writer/api/BUILD | 4 + .../com/google/domain/registry/export/BUILD | 52 + .../export/BigqueryPollJobActionTest.java | 224 + .../export/CheckSnapshotServletTest.java | 271 + .../export/DatastoreBackupInfoTest.java | 135 + .../export/DatastoreBackupServiceTest.java | 141 + .../registry/export/ExportConstantsTest.java | 84 + .../export/ExportReservedTermsTaskTest.java | 147 + .../export/ExportSnapshotServletTest.java | 98 + .../registry/export/ExportUtilsTest.java | 63 + .../export/LoadSnapshotServletTest.java | 294 + .../export/PublishDetailReportActionTest.java | 203 + .../export/SyncGroupMembersTaskTest.java | 224 + .../export/UpdateSnapshotViewServletTest.java | 203 + .../domain/registry/export/backup_kinds.txt | 27 + .../google/domain/registry/export/sheet/BUILD | 31 + .../export/sheet/SheetSynchronizerTest.java | 148 + .../sheet/SyncRegistrarsSheetTaskTest.java | 115 + .../export/sheet/SyncRegistrarsSheetTest.java | 349 + .../export/testdata/contact_create.xml | 33 + .../export/testdata/domain_allocate.xml | 28 + .../export/testdata/domain_create.xml | 22 + ...ain_create_sunrise_encoded_signed_mark.xml | 34 + .../registry/export/testdata/domain_renew.xml | 13 + .../com/google/domain/registry/flows/BUILD | 72 + .../flows/EppConsoleAsAdminServletTest.java | 65 + .../registry/flows/EppConsoleServletTest.java | 71 + .../registry/flows/EppControllerTest.java | 50 + .../registry/flows/EppServletTestCase.java | 301 + .../flows/EppServletXmlLoginTestCase.java | 355 + .../registry/flows/EppTlsServletTest.java | 510 + .../registry/flows/EppToolServletTest.java | 136 + .../domain/registry/flows/FlowTestCase.java | 311 + .../flows/ResourceCheckFlowTestCase.java | 39 + .../registry/flows/ResourceFlowTestCase.java | 140 + .../DeleteContactResourceActionTest.java | 293 + .../DeleteEppResourceActionTestCase.java | 142 + .../async/DeleteHostResourceActionTest.java | 226 + .../DnsRefreshForHostRenameActionTest.java | 127 + .../flows/contact/ContactCheckFlowTest.java | 83 + .../flows/contact/ContactCreateFlowTest.java | 95 + .../flows/contact/ContactDeleteFlowTest.java | 189 + .../flows/contact/ContactInfoFlowTest.java | 141 + .../ContactTransferApproveFlowTest.java | 213 + .../ContactTransferCancelFlowTest.java | 199 + .../contact/ContactTransferFlowTestCase.java | 90 + .../contact/ContactTransferQueryFlowTest.java | 187 + .../ContactTransferRejectFlowTest.java | 209 + .../ContactTransferRequestFlowTest.java | 192 + .../flows/contact/ContactUpdateFlowTest.java | 265 + .../flows/contact/testdata/contact_check.xml | 13 + .../contact/testdata/contact_check_50.xml | 60 + .../contact/testdata/contact_check_51.xml | 61 + .../testdata/contact_check_response.xml | 26 + .../flows/contact/testdata/contact_create.xml | 33 + .../contact_create_decline_disclosure.xml | 33 + .../testdata/contact_create_hebrew_int.xml | 45 + .../testdata/contact_create_hebrew_loc.xml | 45 + .../testdata/contact_create_response.xml | 18 + .../flows/contact/testdata/contact_delete.xml | 11 + .../testdata/contact_delete_response.xml | 11 + .../flows/contact/testdata/contact_info.xml | 14 + .../testdata/contact_info_response.xml | 47 + .../testdata/contact_info_response_linked.xml | 48 + .../testdata/contact_transfer_approve.xml | 11 + .../contact_transfer_approve_response.xml | 22 + ...contact_transfer_approve_with_authinfo.xml | 14 + .../testdata/contact_transfer_cancel.xml | 11 + .../contact_transfer_cancel_response.xml | 22 + .../contact_transfer_cancel_with_authinfo.xml | 14 + .../testdata/contact_transfer_query.xml | 11 + .../contact_transfer_query_response.xml | 22 + ...ransfer_query_response_client_approved.xml | 22 + ...ansfer_query_response_client_cancelled.xml | 22 + ...ransfer_query_response_client_rejected.xml | 22 + ...ransfer_query_response_server_approved.xml | 22 + ...ansfer_query_response_server_cancelled.xml | 22 + .../contact_transfer_query_with_authinfo.xml | 14 + .../contact_transfer_query_with_roid.xml | 14 + .../testdata/contact_transfer_reject.xml | 11 + .../contact_transfer_reject_response.xml | 22 + .../contact_transfer_reject_with_authinfo.xml | 14 + .../testdata/contact_transfer_request.xml | 14 + .../contact_transfer_request_no_authinfo.xml | 11 + .../contact_transfer_request_response.xml | 22 + ...t_transfer_request_response_15_minutes.xml | 22 + .../flows/contact/testdata/contact_update.xml | 36 + .../contact_update_decline_disclosure.xml | 36 + .../testdata/contact_update_hebrew_int.xml | 47 + .../testdata/contact_update_hebrew_loc.xml | 47 + .../contact_update_partial_postalinfo.xml | 22 + .../contact_update_prohibited_status.xml | 36 + ...update_remove_client_update_prohibited.xml | 14 + .../testdata/contact_update_response.xml | 11 + .../flows/domain/ClaimsCheckFlowTest.java | 155 + .../flows/domain/DomainAllocateFlowTest.java | 532 + .../DomainApplicationCreateFlowTest.java | 1280 + .../DomainApplicationDeleteFlowTest.java | 278 + .../domain/DomainApplicationInfoFlowTest.java | 320 + .../DomainApplicationUpdateFlowTest.java | 625 + .../flows/domain/DomainCheckFlowTest.java | 410 + .../flows/domain/DomainCreateFlowTest.java | 1229 + .../flows/domain/DomainDeleteFlowTest.java | 611 + .../flows/domain/DomainInfoFlowTest.java | 613 + .../flows/domain/DomainRenewFlowTest.java | 439 + .../domain/DomainRestoreRequestFlowTest.java | 408 + .../domain/DomainTransferApproveFlowTest.java | 487 + .../domain/DomainTransferCancelFlowTest.java | 303 + .../domain/DomainTransferFlowTestCase.java | 244 + .../domain/DomainTransferQueryFlowTest.java | 201 + .../domain/DomainTransferRejectFlowTest.java | 265 + .../domain/DomainTransferRequestFlowTest.java | 609 + .../flows/domain/DomainUpdateFlowTest.java | 1071 + .../flows/domain/testdata/domain_allocate.xml | 28 + .../domain_allocate_13_nameservers.xml | 39 + .../domain_allocate_bad_application_roid.xml | 28 + .../testdata/domain_allocate_bad_checksum.xml | 33 + .../domain_allocate_claims_notice.xml | 33 + .../testdata/domain_allocate_collision.xml | 28 + .../testdata/domain_allocate_dsdata.xml | 37 + .../domain_allocate_dsdata_8_records.xml | 80 + .../domain/testdata/domain_allocate_idn.xml | 28 + .../domain_allocate_no_nameservers.xml | 24 + .../testdata/domain_allocate_premium.xml | 28 + .../testdata/domain_allocate_reserved.xml | 28 + .../testdata/domain_allocate_response.xml | 19 + .../testdata/domain_allocate_smd_id.xml | 29 + .../flows/domain/testdata/domain_check.xml | 12 + .../flows/domain/testdata/domain_check_50.xml | 59 + .../flows/domain/testdata/domain_check_51.xml | 60 + .../domain/testdata/domain_check_anchor.xml | 10 + .../domain/testdata/domain_check_avail.xml | 21 + .../domain/testdata/domain_check_claims.xml | 20 + .../testdata/domain_check_claims_50.xml | 65 + .../testdata/domain_check_claims_51.xml | 67 + .../testdata/domain_check_claims_bad_tld.xml | 19 + .../domain_check_claims_multiple_tlds.xml | 20 + .../testdata/domain_check_claims_response.xml | 25 + ...in_check_claims_response_multiple_tlds.xml | 28 + .../domain_check_claims_response_none.xml | 22 + .../testdata/domain_check_duplicates.xml | 11 + .../domain/testdata/domain_check_fee.xml | 31 + .../testdata/domain_check_fee_bad_period.xml | 19 + .../domain_check_fee_command_phase.xml | 18 + .../domain_check_fee_command_subphase.xml | 18 + .../domain/testdata/domain_check_fee_euro.xml | 31 + .../testdata/domain_check_fee_fractional.xml | 23 + .../domain_check_fee_fractional_response.xml | 29 + .../domain_check_fee_invalid_command.xml | 19 + .../domain_check_fee_multiple_commands.xml | 30 + ...n_check_fee_multiple_commands_response.xml | 51 + .../domain_check_fee_multiyear_restore.xml | 22 + .../domain_check_fee_not_in_avail.xml | 18 + .../testdata/domain_check_fee_premium.xml | 30 + .../domain_check_fee_premium_response.xml | 55 + .../testdata/domain_check_fee_reserved.xml | 116 + .../domain_check_fee_reserved_response.xml | 154 + ...in_check_fee_reserved_sunrise_response.xml | 159 + .../testdata/domain_check_fee_response.xml | 43 + .../domain_check_fee_unknown_command.xml | 19 + ...omain_check_one_multipart_tld_reserved.xml | 13 + .../domain/testdata/domain_check_one_tld.xml | 12 + .../domain_check_one_tld_reserved.xml | 13 + .../domain_check_one_tld_response.xml | 25 + .../domain/testdata/domain_check_premium.xml | 10 + .../domain/testdata/domain_check_template.xml | 10 + .../flows/domain/testdata/domain_create.xml | 22 + .../testdata/domain_create_13_nameservers.xml | 33 + .../testdata/domain_create_14_nameservers.xml | 34 + .../domain_create_anchor_authcode.xml | 22 + .../testdata/domain_create_anchor_tenant.xml | 29 + .../domain_create_anchor_wrong_authcode.xml | 22 + ...omain_create_bad_checksum_claim_notice.xml | 32 + .../testdata/domain_create_bad_idn_minna.xml | 22 + .../domain_create_bad_validator_id.xml | 32 + .../testdata/domain_create_claim_notice.xml | 33 + .../testdata/domain_create_code_with_mark.xml | 56 + .../domain/testdata/domain_create_dsdata.xml | 36 + .../domain_create_dsdata_8_records.xml | 77 + .../domain_create_dsdata_9_records.xml | 83 + .../domain_create_dsdata_no_maxsiglife.xml | 35 + .../domain_create_duplicate_contact.xml | 23 + .../domain/testdata/domain_create_fee.xml | 28 + .../testdata/domain_create_fee_applied.xml | 28 + .../testdata/domain_create_fee_bad_scale.xml | 28 + .../testdata/domain_create_fee_defaults.xml | 28 + .../domain_create_fee_grace_period.xml | 28 + .../testdata/domain_create_fee_refundable.xml | 28 + .../testdata/domain_create_idn_minna.xml | 22 + .../testdata/domain_create_landrush.xml | 28 + ...omain_create_landrush_allowedinsunrise.xml | 28 + .../domain_create_landrush_claim_notice.xml | 32 + .../testdata/domain_create_landrush_fee.xml | 32 + .../domain_create_landrush_fee_applied.xml | 32 + .../domain_create_landrush_fee_bad_scale.xml | 32 + .../domain_create_landrush_fee_defaults.xml | 32 + ...omain_create_landrush_fee_grace_period.xml | 32 + .../domain_create_landrush_fee_refundable.xml | 32 + .../domain_create_landrush_fee_response.xml | 29 + .../domain_create_landrush_months.xml | 29 + .../domain_create_landrush_premium.xml | 28 + ...omain_create_landrush_premium_response.xml | 25 + .../domain_create_landrush_response.xml | 25 + ...domain_create_landrush_response_claims.xml | 25 + .../domain_create_landrush_signed_mark.xml | 33 + .../domain_create_landrush_two_years.xml | 29 + .../domain_create_malformed_claim_notice1.xml | 32 + .../domain_create_malformed_claim_notice2.xml | 32 + .../testdata/domain_create_metadata.xml | 28 + .../testdata/domain_create_missing_admin.xml | 21 + .../domain_create_missing_contact_type.xml | 22 + .../testdata/domain_create_missing_period.xml | 21 + .../domain_create_missing_registrant.xml | 21 + .../testdata/domain_create_missing_tech.xml | 21 + .../domain/testdata/domain_create_months.xml | 22 + .../domain_create_no_hosts_or_dsdata.xml | 18 + .../domain/testdata/domain_create_premium.xml | 22 + .../domain_create_registration_landrush.xml | 30 + ...omain_create_registration_qlp_landrush.xml | 34 + ...egistration_qlp_landrush_claims_notice.xml | 37 + ...ation_qlp_landrush_encoded_signed_mark.xml | 35 + ...domain_create_registration_qlp_sunrise.xml | 32 + ...registration_qlp_sunrise_claims_notice.xml | 37 + ...ration_qlp_sunrise_encoded_signed_mark.xml | 35 + ...domain_create_registration_qlp_sunrush.xml | 34 + ...registration_qlp_sunrush_claims_notice.xml | 37 + ...ration_qlp_sunrush_encoded_signed_mark.xml | 35 + .../domain_create_registration_sunrise.xml | 30 + .../domain_create_registration_sunrush.xml | 30 + .../testdata/domain_create_reserved.xml | 22 + .../domain_create_reserved_response.xml | 19 + .../testdata/domain_create_response.xml | 19 + .../domain_create_response_claims.xml | 19 + ...eate_response_encoded_signed_mark_name.xml | 18 + .../testdata/domain_create_response_fee.xml | 25 + .../domain_create_response_idn_minna.xml | 19 + .../domain_create_response_premium.xml | 19 + .../domain_create_response_wildcard.xml | 19 + .../testdata/domain_create_signed_mark.xml | 137 + .../domain_create_sunrise_bad_encoded_xml.xml | 34 + .../domain_create_sunrise_bad_encoding.xml | 133 + .../domain_create_sunrise_code_with_mark.xml | 56 + ...omain_create_sunrise_duplicate_contact.xml | 34 + ...eate_sunrise_empty_encoded_signed_mark.xml | 32 + ...ain_create_sunrise_encoded_signed_mark.xml | 34 + ...e_sunrise_encoded_signed_mark_response.xml | 25 + ...se_encoded_signed_mark_with_whitespace.xml | 128 + .../domain_create_sunrise_hex_encoding.xml | 34 + ...in_create_sunrise_missing_contact_type.xml | 33 + ...omain_create_sunrise_no_matching_marks.xml | 34 + .../domain_create_sunrise_signed_mark.xml | 137 + ..._create_sunrise_signed_mark_and_notice.xml | 142 + ...in_create_sunrise_signed_mark_reserved.xml | 33 + ..._sunrise_signed_mark_reserved_response.xml | 25 + ...n_create_sunrise_signed_mark_uppercase.xml | 33 + ...create_sunrise_signed_mark_with_secdns.xml | 42 + ...rise_signed_mark_with_secdns_8_records.xml | 84 + ...rise_signed_mark_with_secdns_9_records.xml | 90 + ...domain_create_sunrise_two_signed_marks.xml | 245 + ..._create_sunrise_with_secdns_maxsiglife.xml | 43 + .../domain_create_sunrise_without_marks.xml | 28 + .../domain_create_sunrise_wrong_extension.xml | 44 + .../domain/testdata/domain_create_sunrush.xml | 28 + .../domain_create_sunrush_13_nameservers.xml | 39 + .../domain_create_sunrush_14_nameservers.xml | 40 + ...domain_create_sunrush_allowedinsunrise.xml | 34 + ...eate_sunrush_allowedinsunrise_response.xml | 25 + ...eate_sunrush_bad_checksum_claim_notice.xml | 32 + .../domain_create_sunrush_bad_idn_minna.xml | 27 + ...domain_create_sunrush_bad_validator_id.xml | 32 + .../domain_create_sunrush_claim_notice.xml | 32 + ...ain_create_sunrush_encoded_signed_mark.xml | 34 + ...ncoded_signed_mark_certificate_corrupt.xml | 34 + ...te_sunrush_encoded_signed_mark_corrupt.xml | 34 + ...e_sunrush_encoded_signed_mark_response.xml | 25 + ...nrush_encoded_signed_mark_revoked_cert.xml | 136 + ..._encoded_signed_mark_signature_corrupt.xml | 138 + ...create_sunrush_malformed_claim_notice1.xml | 32 + ...create_sunrush_malformed_claim_notice2.xml | 32 + .../domain_create_sunrush_response.xml | 25 + .../domain_create_sunrush_response_claims.xml | 25 + .../testdata/domain_create_uppercase.xml | 22 + .../testdata/domain_create_with_tld.xml | 22 + .../domain_create_wrong_extension.xml | 35 + .../flows/domain/testdata/domain_delete.xml | 11 + .../testdata/domain_delete_application.xml | 19 + .../domain_delete_application_landrush.xml | 19 + .../domain_delete_application_sunrush.xml | 18 + ...ain_delete_application_wrong_extension.xml | 30 + .../testdata/domain_delete_metadata.xml | 17 + .../testdata/domain_delete_response.xml | 11 + .../domain_delete_response_autorenew_fee.xml | 18 + .../testdata/domain_delete_response_fee.xml | 18 + .../domain_delete_response_pending.xml | 11 + .../domain_delete_response_pending_fee.xml | 18 + .../flows/domain/testdata/domain_info.xml | 11 + .../testdata/domain_info_default_hosts.xml | 11 + .../testdata/domain_info_delegated_hosts.xml | 11 + .../testdata/domain_info_fee_bad_period.xml | 18 + .../domain_info_fee_command_phase.xml | 18 + .../domain_info_fee_command_subphase.xml | 18 + .../testdata/domain_info_fee_create.xml | 18 + .../testdata/domain_info_fee_create_euro.xml | 18 + .../domain_info_fee_create_premium.xml | 18 + ...omain_info_fee_create_premium_response.xml | 47 + .../domain_info_fee_create_response.xml | 46 + .../domain_info_fee_multiyear_restore.xml | 18 + .../domain/testdata/domain_info_fee_renew.xml | 18 + .../domain_info_fee_renew_premium.xml | 18 + ...domain_info_fee_renew_premium_response.xml | 47 + .../domain_info_fee_renew_response.xml | 46 + .../testdata/domain_info_fee_restore.xml | 18 + .../domain_info_fee_restore_premium.xml | 18 + ...main_info_fee_restore_premium_response.xml | 48 + .../domain_info_fee_restore_response.xml | 47 + .../testdata/domain_info_fee_transfer.xml | 18 + .../domain_info_fee_transfer_premium.xml | 18 + ...ain_info_fee_transfer_premium_response.xml | 47 + .../domain_info_fee_transfer_response.xml | 46 + .../testdata/domain_info_none_hosts.xml | 11 + .../domain/testdata/domain_info_response.xml | 38 + .../domain_info_response_addperiod.xml | 41 + .../domain_info_response_autorenewperiod.xml | 44 + .../domain_info_response_delegated_hosts.xml | 36 + .../testdata/domain_info_response_dsdata.xml | 51 + .../domain_info_response_dsdata_addperiod.xml | 53 + .../domain_info_response_none_hosts.xml | 32 + .../domain_info_response_pendingdelete.xml | 44 + .../domain_info_response_redemptionperiod.xml | 44 + .../domain_info_response_renewperiod.xml | 44 + ...in_info_response_stackedaddrenewperiod.xml | 45 + ...domain_info_response_subordinate_hosts.xml | 34 + .../domain_info_response_transferperiod.xml | 44 + .../domain_info_response_unauthorized.xml | 19 + .../domain_info_subordinate_hosts.xml | 11 + .../domain/testdata/domain_info_sunrise.xml | 19 + .../domain_info_sunrise_all_hosts.xml | 20 + .../domain_info_sunrise_allocated.xml | 46 + .../domain_info_sunrise_delegated_hosts.xml | 20 + .../domain_info_sunrise_include_marks.xml | 20 + .../domain_info_sunrise_no_application_id.xml | 19 + .../testdata/domain_info_sunrise_no_marks.xml | 20 + .../domain_info_sunrise_none_hosts.xml | 20 + .../testdata/domain_info_sunrise_response.xml | 46 + .../domain_info_sunrise_response_dsdata.xml | 54 + ...n_info_sunrise_response_no_nameservers.xml | 42 + ...domain_info_sunrise_response_with_mark.xml | 89 + .../domain/testdata/domain_info_with_auth.xml | 14 + .../domain_info_with_contact_auth.xml | 14 + .../flows/domain/testdata/domain_renew.xml | 13 + .../domain/testdata/domain_renew_11_years.xml | 13 + .../domain/testdata/domain_renew_fee.xml | 19 + .../testdata/domain_renew_fee_applied.xml | 19 + .../testdata/domain_renew_fee_bad_scale.xml | 19 + .../testdata/domain_renew_fee_defaults.xml | 19 + .../domain_renew_fee_grace_period.xml | 19 + .../testdata/domain_renew_fee_refundable.xml | 19 + .../testdata/domain_renew_missing_period.xml | 12 + .../domain/testdata/domain_renew_months.xml | 13 + .../domain/testdata/domain_renew_premium.xml | 13 + .../domain/testdata/domain_renew_response.xml | 18 + .../testdata/domain_renew_response_fee.xml | 24 + .../domain_renew_response_missing_period.xml | 18 + .../testdata/domain_transfer_approve.xml | 11 + ...main_transfer_approve_contact_authinfo.xml | 14 + ...omain_transfer_approve_domain_authinfo.xml | 14 + .../testdata/domain_transfer_approve_net.xml | 11 + .../domain_transfer_approve_response.xml | 23 + ...in_transfer_approve_response_autorenew.xml | 23 + .../domain_transfer_approve_response_net.xml | 23 + .../testdata/domain_transfer_cancel.xml | 11 + ...omain_transfer_cancel_contact_authinfo.xml | 14 + ...domain_transfer_cancel_domain_authinfo.xml | 14 + .../domain_transfer_cancel_response.xml | 22 + .../domain/testdata/domain_transfer_query.xml | 11 + ...domain_transfer_query_contact_authinfo.xml | 14 + .../domain_transfer_query_domain_authinfo.xml | 14 + .../domain_transfer_query_response.xml | 23 + ...ransfer_query_response_client_approved.xml | 23 + ...ansfer_query_response_client_cancelled.xml | 22 + ...ransfer_query_response_client_rejected.xml | 22 + ...ransfer_query_response_server_approved.xml | 23 + ...ansfer_query_response_server_cancelled.xml | 22 + .../testdata/domain_transfer_reject.xml | 11 + ...omain_transfer_reject_contact_authinfo.xml | 14 + ...domain_transfer_reject_domain_authinfo.xml | 14 + .../domain_transfer_reject_response.xml | 22 + .../testdata/domain_transfer_request.xml | 15 + .../domain_transfer_request_10_years.xml | 15 + .../domain_transfer_request_2_years.xml | 15 + ...omain_transfer_request_domain_authinfo.xml | 15 + .../testdata/domain_transfer_request_fee.xml | 21 + .../domain_transfer_request_fee_applied.xml | 21 + .../domain_transfer_request_fee_bad_scale.xml | 21 + .../domain_transfer_request_fee_defaults.xml | 21 + ...main_transfer_request_fee_grace_period.xml | 21 + ...domain_transfer_request_fee_refundable.xml | 21 + ...domain_transfer_request_missing_period.xml | 14 + .../domain_transfer_request_months.xml | 15 + .../domain_transfer_request_no_authinfo.xml | 12 + .../domain_transfer_request_premium.xml | 15 + .../domain_transfer_request_response.xml | 23 + ...ain_transfer_request_response_10_years.xml | 23 + ...n_transfer_request_response_15_minutes.xml | 23 + ...main_transfer_request_response_2_years.xml | 23 + .../domain_transfer_request_response_fee.xml | 29 + .../domain_transfer_request_wildcard.xml | 15 + .../flows/domain/testdata/domain_update.xml | 32 + .../testdata/domain_update_add_nameserver.xml | 18 + .../domain_update_add_non_server_status.xml | 15 + .../domain_update_add_remove_same_contact.xml | 25 + .../domain_update_add_remove_same_host.xml | 29 + .../domain_update_add_server_hold_status.xml | 15 + .../domain_update_add_server_status.xml | 21 + ...update_add_server_status_non_registrar.xml | 21 + .../testdata/domain_update_authinfo.xml | 16 + .../domain_update_change_server_status.xml | 25 + .../testdata/domain_update_dsdata_add.xml | 26 + .../testdata/domain_update_dsdata_add_rem.xml | 34 + .../domain_update_dsdata_add_rem_same.xml | 34 + .../testdata/domain_update_dsdata_empty.xml | 18 + .../testdata/domain_update_dsdata_rem.xml | 26 + .../testdata/domain_update_dsdata_rem_all.xml | 21 + .../domain_update_dsdata_rem_all_false.xml | 21 + .../testdata/domain_update_dsdata_urgent.xml | 29 + .../domain_update_duplicate_contact.xml | 34 + .../testdata/domain_update_max_everything.xml | 54 + .../testdata/domain_update_maxsiglife.xml | 21 + .../testdata/domain_update_metadata.xml | 24 + .../domain_update_missing_contact_type.xml | 32 + .../domain_update_prohibited_status.xml | 30 + .../domain_update_registrant_to_tech.xml | 20 + .../testdata/domain_update_remove_admin.xml | 14 + .../domain_update_remove_client_hold.xml | 14 + .../testdata/domain_update_remove_contact.xml | 31 + ...domain_update_remove_multiple_contacts.xml | 24 + .../domain_update_remove_server_hold.xml | 14 + .../domain_update_remove_server_status.xml | 21 + .../testdata/domain_update_remove_tech.xml | 14 + .../testdata/domain_update_response.xml | 11 + .../domain_update_restore_request.xml | 17 + .../domain_update_restore_request_fee.xml | 21 + ...ain_update_restore_request_fee_applied.xml | 21 + ...n_update_restore_request_fee_bad_scale.xml | 21 + ...in_update_restore_request_fee_defaults.xml | 21 + ...pdate_restore_request_fee_grace_period.xml | 21 + ..._update_restore_request_fee_refundable.xml | 21 + .../domain_update_restore_request_premium.xml | 17 + ...in_update_restore_request_response_fee.xml | 18 + ...domain_update_restore_request_with_add.xml | 19 + ...ain_update_restore_request_with_change.xml | 19 + ...ain_update_restore_request_with_remove.xml | 19 + ...ain_update_restore_request_with_secdns.xml | 28 + .../domain_update_subordinate_hosts.xml | 22 + .../domain/testdata/domain_update_sunrise.xml | 38 + .../domain_update_sunrise_add_nameserver.xml | 24 + ...update_sunrise_add_remove_same_contact.xml | 31 + ...in_update_sunrise_add_remove_same_host.xml | 35 + .../domain_update_sunrise_authinfo.xml | 22 + .../domain_update_sunrise_dsdata_add.xml | 30 + .../domain_update_sunrise_dsdata_add_rem.xml | 38 + ...ain_update_sunrise_dsdata_add_rem_same.xml | 38 + .../domain_update_sunrise_dsdata_empty.xml | 22 + .../domain_update_sunrise_dsdata_rem.xml | 30 + .../domain_update_sunrise_dsdata_rem_all.xml | 25 + ...in_update_sunrise_dsdata_rem_all_false.xml | 25 + .../domain_update_sunrise_dsdata_urgent.xml | 33 + ...omain_update_sunrise_duplicate_contact.xml | 40 + .../domain_update_sunrise_maxsiglife.xml | 25 + ...in_update_sunrise_missing_contact_type.xml | 38 + ...omain_update_sunrise_prohibited_status.xml | 36 + ...main_update_sunrise_registrant_to_tech.xml | 26 + .../domain_update_sunrise_remove_admin.xml | 20 + .../domain_update_sunrise_remove_contact.xml | 37 + ...pdate_sunrise_remove_multiple_contacts.xml | 30 + .../domain_update_sunrise_remove_tech.xml | 20 + .../domain_update_sunrise_wrong_extension.xml | 28 + .../domain_update_wrong_extension.xml | 24 + .../flows/host/HostCheckFlowTest.java | 82 + .../flows/host/HostCreateFlowTest.java | 236 + .../flows/host/HostDeleteFlowTest.java | 197 + .../registry/flows/host/HostInfoFlowTest.java | 170 + .../flows/host/HostUpdateFlowTest.java | 892 + .../flows/host/testdata/host_check.xml | 13 + .../flows/host/testdata/host_check_50.xml | 60 + .../flows/host/testdata/host_check_51.xml | 61 + .../host/testdata/host_check_response.xml | 28 + .../flows/host/testdata/host_create.xml | 12 + .../host/testdata/host_create_response.xml | 18 + .../flows/host/testdata/host_delete.xml | 11 + .../host/testdata/host_delete_response.xml | 11 + .../flows/host/testdata/host_info.xml | 11 + .../host/testdata/host_info_response.xml | 28 + .../testdata/host_info_response_linked.xml | 29 + ...t_info_response_superordinate_clientid.xml | 28 + .../flows/host/testdata/host_update.xml | 21 + .../host/testdata/host_update_add_status.xml | 14 + .../testdata/host_update_name_unchanged.xml | 18 + .../host_update_prohibited_status.xml | 21 + ...update_remove_client_update_prohibited.xml | 14 + .../host/testdata/host_update_response.xml | 11 + .../registry/flows/poll/PollAckFlowTest.java | 224 + .../flows/poll/PollRequestFlowTest.java | 232 + .../registry/flows/poll/testdata/poll.xml | 6 + .../registry/flows/poll/testdata/poll_ack.xml | 6 + .../flows/poll/testdata/poll_ack_contact.xml | 6 + .../poll_ack_invalid_eppresource_id.xml | 6 + .../poll/testdata/poll_ack_invalid_id.xml | 6 + .../testdata/poll_ack_invalid_string_id.xml | 6 + .../poll/testdata/poll_ack_missing_id.xml | 6 + .../flows/poll/testdata/poll_ack_response.xml | 12 + .../poll/testdata/poll_ack_response_empty.xml | 11 + .../poll/testdata/poll_response_autorenew.xml | 22 + .../testdata/poll_response_contact_delete.xml | 15 + .../poll_response_contact_transfer.xml | 25 + ...l_response_domain_pending_notification.xml | 25 + .../poll_response_domain_transfer.xml | 26 + .../poll/testdata/poll_response_empty.xml | 11 + .../testdata/poll_response_host_delete.xml | 15 + .../flows/poll/testdata/poll_with_id.xml | 6 + .../registry/flows/session/HelloFlowTest.java | 46 + .../flows/session/LoginFlowTestCase.java | 165 + .../session/LoginFlowViaConsoleTest.java | 173 + .../flows/session/LoginFlowViaTlsTest.java | 149 + .../flows/session/LogoutFlowTest.java | 59 + .../flows/session/testdata/greeting_crr.xml | 27 + .../registry/flows/session/testdata/hello.xml | 4 + .../registry/flows/session/testdata/login.xml | 23 + .../testdata/login_invalid_extension.xml | 21 + .../testdata/login_invalid_language.xml | 18 + .../session/testdata/login_invalid_newpw.xml | 19 + .../session/testdata/login_invalid_types.xml | 19 + .../testdata/login_invalid_version.xml | 18 + .../flows/session/testdata/login_response.xml | 11 + .../flows/session/testdata/login_valid.xml | 18 + .../testdata/login_valid_missing_types.xml | 16 + .../flows/session/testdata/logout.xml | 6 + .../session/testdata/logout_response.xml | 11 + .../contact_create_billion_laughs.xml | 45 + .../flows/testdata/contact_create_jd1234.xml | 33 + .../contact_create_local_response_xxe.xml | 10 + .../testdata/contact_create_local_xxe.xml | 36 + .../contact_create_remote_response_xxe.xml | 10 + .../testdata/contact_create_remote_xxe.xml | 36 + ...contact_create_response_billion_laughs.xml | 10 + .../contact_create_response_jd1234.xml | 18 + .../contact_create_response_sh8013.xml | 18 + .../contact_create_response_template.xml | 18 + .../flows/testdata/contact_create_sh8013.xml | 33 + .../testdata/contact_create_template.xml | 33 + .../contact_delete_response_sh8013.xml | 11 + .../flows/testdata/contact_delete_sh8013.xml | 11 + .../registry/flows/testdata/contact_info.xml | 14 + .../contact_info_from_create_response.xml | 44 + .../flows/testdata/contact_info_not_found.xml | 11 + .../testdata/contact_transfer_request.xml | 14 + ...ct_transfer_request_response_alternate.xml | 22 + .../domain_allocate_response_testvalidate.xml | 19 + ...e_response_testvalidate_only_superuser.xml | 11 + .../testdata/domain_allocate_testvalidate.xml | 28 + .../testdata/domain_check_fee_premium.xml | 18 + .../domain_check_fee_premium_response.xml | 30 + .../flows/testdata/domain_create_fakesite.xml | 22 + .../flows/testdata/domain_create_minna.xml | 18 + .../domain_create_no_hosts_or_dsdata.xml | 18 + .../flows/testdata/domain_create_response.xml | 19 + .../domain_create_response_fakesite.xml | 18 + .../testdata/domain_create_response_minna.xml | 19 + .../domain_create_response_secondsite.xml | 18 + .../testdata/domain_create_secondsite.xml | 22 + .../domain_create_sunrise_encoded_mark.xml | 34 + ...e_sunrise_encoded_signed_mark_response.xml | 25 + ...main_create_testvalidate_invalid_phase.xml | 11 + .../registry/flows/testdata/domain_delete.xml | 11 + .../flows/testdata/domain_delete_fakesite.xml | 10 + .../domain_delete_response_prohibited.xml | 11 + .../registry/flows/testdata/domain_info.xml | 11 + .../flows/testdata/domain_info_fakesite.xml | 11 + ...n_info_response_fakesite_3_nameservers.xml | 37 + ...akesite_3_nameservers_pending_transfer.xml | 37 + ...site_3_nameservers_transfer_successful.xml | 38 + .../domain_info_response_fakesite_ok.xml | 38 + ..._response_fakesite_ok_post_host_update.xml | 34 + ..._info_response_fakesite_pending_delete.xml | 38 + ...nfo_response_fakesite_pending_transfer.xml | 33 + ...se_fakesite_pending_transfer_autorenew.xml | 38 + ...ain_info_response_fakesite_restored_ok.xml | 33 + ...fo_response_fakesite_transfer_complete.xml | 34 + ...info_response_fakesite_transfer_period.xml | 39 + .../domain_info_response_pendingdelete.xml | 36 + ...nfo_response_testvalidate_doesnt_exist.xml | 11 + .../domain_info_response_testvalidate_ok.xml | 37 + .../testdata/domain_info_testvalidate.xml | 10 + .../domain_transfer_query_fakesite.xml | 10 + ...sfer_query_response_completed_fakesite.xml | 22 + ...omain_transfer_query_response_fakesite.xml | 22 + ...fer_query_response_no_transfer_history.xml | 11 + .../domain_transfer_request_1_year.xml | 15 + .../domain_transfer_request_2_years.xml | 15 + .../domain_transfer_response_1_year.xml | 22 + .../domain_transfer_response_2_years.xml | 22 + .../domain_update_add_nameserver_fakesite.xml | 18 + ...pdate_add_nameserver_response_fakesite.xml | 11 + .../domain_update_restore_fakesite.xml | 16 + .../domain_update_restore_request.xml | 17 + ...domain_update_restore_request_response.xml | 11 + ...eneric_success_action_pending_response.xml | 11 + .../testdata/generic_success_response.xml | 11 + .../registry/flows/testdata/greeting_crr.xml | 27 + .../domain/registry/flows/testdata/hello.xml | 4 + .../registry/flows/testdata/host_create.xml | 10 + .../registry/flows/testdata/host_create2.xml | 10 + .../flows/testdata/host_create2_response.xml | 17 + .../flows/testdata/host_create_fakesite.xml | 13 + .../flows/testdata/host_create_response.xml | 17 + .../host_create_response_fakesite.xml | 17 + .../registry/flows/testdata/host_info.xml | 10 + .../flows/testdata/host_info_fakesite.xml | 10 + .../registry/flows/testdata/host_info_ns1.xml | 10 + .../registry/flows/testdata/host_info_ns2.xml | 10 + .../testdata/host_info_ns9000_example.xml | 10 + .../testdata/host_info_response_fakesite.xml | 26 + ...t_info_response_fakesite_post_transfer.xml | 27 + ...onse_fakesite_post_transfer_and_update.xml | 29 + ..._post_transfer_and_update_no_addresses.xml | 26 + ...ost_info_response_fakesite_post_update.xml | 28 + .../flows/testdata/host_info_response_ns1.xml | 22 + .../flows/testdata/host_info_response_ns2.xml | 22 + .../host_info_response_ns9000_example.xml | 25 + .../testdata/host_update_failed_response.xml | 11 + .../flows/testdata/host_update_fakesite.xml | 21 + .../testdata/host_update_ns1_to_fakesite.xml | 19 + .../flows/testdata/host_update_ns1_to_ns2.xml | 16 + ...ost_update_rename_and_remove_addresses.xml | 20 + .../testdata/host_update_rename_only.xml | 17 + .../registry/flows/testdata/login2_valid.xml | 22 + .../flows/testdata/login_response.xml | 11 + .../login_response_bad_certificate.xml | 11 + .../login_response_missing_certificate.xml | 11 + .../login_response_unauthorized_role.xml | 11 + .../login_response_unauthorized_tld.xml | 11 + .../registry/flows/testdata/login_valid.xml | 22 + .../testdata/login_valid_fee_extension.xml | 23 + .../domain/registry/flows/testdata/logout.xml | 6 + .../flows/testdata/logout_response.xml | 11 + .../registry/flows/testdata/pdt_login.xml | 24 + .../domain/registry/flows/testdata/poll.xml | 6 + .../registry/flows/testdata/poll_ack.xml | 6 + .../testdata/poll_ack_response_empty.xml | 11 + .../poll_response_contact_transfer.xml | 25 + .../poll_response_domain_transfer_request.xml | 26 + ...e_domain_transfer_server_approve_loser.xml | 26 + ..._domain_transfer_server_approve_winner.xml | 35 + .../registry/flows/testdata/syntax_error.xml | 24 + .../flows/testdata/syntax_error_response.xml | 10 + .../com/google/domain/registry/groups/BUILD | 40 + .../groups/DirectoryGroupsConnectionTest.java | 295 + .../google/domain/registry/mapreduce/BUILD | 32 + .../mapreduce/EppResourceInputsTest.java | 333 + .../com/google/domain/registry/model/BUILD | 52 + .../model/CreateAutoTimestampTest.java | 87 + .../registry/model/EntityClassesTest.java | 87 + .../domain/registry/model/EntityTestCase.java | 189 + .../registry/model/EppResourceUtilsTest.java | 295 + .../registry/model/ImmutableObjectTest.java | 237 + .../domain/registry/model/ModelUtilsTest.java | 140 + .../model/ResourceCommandTestCase.java | 34 + .../registry/model/RoidSuffixesTest.java | 43 + .../registry/model/SchemaVersionTest.java | 60 + .../model/UpdateAutoTimestampTest.java | 86 + .../model/billing/BillingEventTest.java | 130 + .../billing/RegistrarBillingEntryTest.java | 189 + .../billing/RegistrarBillingUtilsTest.java | 144 + .../billing/RegistrarCreditBalanceTest.java | 190 + .../model/billing/RegistrarCreditTest.java | 101 + .../model/common/GaeUserIdConverterTest.java | 59 + .../model/common/PersistedRangeLongTest.java | 92 + .../registry/model/common/TimeOfYearTest.java | 56 + .../common/TimedTransitionPropertyTest.java | 174 + .../model/contact/ContactCommandTest.java | 178 + .../model/contact/ContactResourceTest.java | 235 + .../model/contact/testdata/contact_check.xml | 13 + .../model/contact/testdata/contact_create.xml | 33 + .../model/contact/testdata/contact_delete.xml | 11 + .../model/contact/testdata/contact_info.xml | 14 + .../testdata/contact_transfer_approve.xml | 11 + .../testdata/contact_transfer_cancel.xml | 11 + .../testdata/contact_transfer_query.xml | 11 + .../testdata/contact_transfer_reject.xml | 11 + .../testdata/contact_transfer_request.xml | 14 + .../model/contact/testdata/contact_update.xml | 36 + .../model/domain/DomainApplicationTest.java | 196 + .../model/domain/DomainCommandTest.java | 162 + .../model/domain/DomainResourceTest.java | 426 + .../model/domain/testdata/domain_check.xml | 12 + .../domain/testdata/domain_check_avail.xml | 21 + .../domain/testdata/domain_check_claims.xml | 20 + .../domain/testdata/domain_check_fee.xml | 41 + .../model/domain/testdata/domain_create.xml | 22 + .../domain/testdata/domain_create_fee.xml | 29 + .../testdata/domain_create_landrush.xml | 24 + .../testdata/domain_create_sunrise_code.xml | 33 + .../domain_create_sunrise_code_with_mark.xml | 56 + ...ain_create_sunrise_encoded_signed_mark.xml | 34 + .../testdata/domain_create_sunrise_mark.xml | 55 + .../domain_create_sunrise_signed_mark.xml | 137 + .../model/domain/testdata/domain_delete.xml | 11 + .../model/domain/testdata/domain_info.xml | 11 + .../model/domain/testdata/domain_info_fee.xml | 17 + .../domain/testdata/domain_info_landrush.xml | 19 + .../domain/testdata/domain_info_sunrise.xml | 19 + .../domain_info_sunrise_no_application_id.xml | 19 + .../model/domain/testdata/domain_renew.xml | 13 + .../domain/testdata/domain_renew_fee.xml | 20 + .../testdata/domain_transfer_approve.xml | 11 + .../testdata/domain_transfer_cancel.xml | 11 + .../domain/testdata/domain_transfer_query.xml | 11 + .../testdata/domain_transfer_reject.xml | 11 + .../testdata/domain_transfer_request.xml | 15 + .../testdata/domain_transfer_request_fee.xml | 22 + .../model/domain/testdata/domain_update.xml | 31 + .../domain/testdata/domain_update_fee.xml | 37 + .../registry/model/eppoutput/ResultTest.java | 33 + .../model/export/LogsExportCursorTest.java | 65 + .../registry/model/host/HostCommandTest.java | 47 + .../registry/model/host/HostResourceTest.java | 296 + .../model/host/testdata/host_check.xml | 13 + .../model/host/testdata/host_create.xml | 14 + .../model/host/testdata/host_delete.xml | 11 + .../model/host/testdata/host_info.xml | 11 + .../model/host/testdata/host_update.xml | 21 + .../index/DomainApplicationIndexTest.java | 128 + .../model/index/EppResourceIndexTest.java | 77 + .../model/index/ForeignKeyIndexTest.java | 110 + .../registry/model/mark/MarkContactTest.java | 33 + .../registry/model/mark/MarkHolderTest.java | 33 + .../model/mark/MarkProtectionTest.java | 39 + .../model/ofy/CommitLogBucketTest.java | 133 + .../model/ofy/CommitLogCheckpointTest.java | 107 + .../model/ofy/CommitLogMutationTest.java | 104 + .../model/ofy/ObjectifyServiceTest.java | 38 + .../registry/model/ofy/OfyCommitLogTest.java | 424 + .../registry/model/ofy/OfyFilterTest.java | 100 + .../domain/registry/model/ofy/OfyTest.java | 408 + .../model/poll/MessageQueueInfoTest.java | 40 + .../PollMessageExternalKeyConverterTest.java | 148 + .../registry/model/poll/PollMessageTest.java | 93 + .../model/rde/RdeNamingUtilsTest.java | 67 + .../registry/model/rde/RdeRevisionTest.java | 144 + .../model/registrar/RegistrarTest.java | 341 + .../model/registry/RegistriesTest.java | 85 + .../model/registry/RegistryCursorTest.java | 46 + .../registry/model/registry/RegistryTest.java | 459 + .../model/registry/label/PremiumListTest.java | 243 + .../registry/label/ReservedListTest.java | 314 + .../model/reporting/HistoryEntryTest.java | 65 + .../google/domain/registry/model/schema.txt | 899 + .../registry/model/server/LockTest.java | 113 + .../registry/model/smd/IssuerInfoTest.java | 42 + .../smd/SignedMarkRevocationListTest.java | 169 + .../registry/model/testdata/domain_create.xml | 22 + .../registry/model/testdata/domain_delete.xml | 11 + .../testdata/domain_update_dsdata_add.xml | 26 + .../testdata/domain_update_dsdata_rem.xml | 26 + .../model/tmch/ClaimsListShardTest.java | 121 + .../registry/model/tmch/TmchCrlTest.java | 42 + .../model/transfer/TransferDataTest.java | 147 + ...mmitLogRevisionsTranslatorFactoryTest.java | 211 + .../translators/StatusValueAdapterTest.java | 92 + .../translators/testdata/host_update.xml | 11 + .../domain/registry/module/backend/BUILD | 29 + .../module/backend/BackendServletTest.java | 42 + .../domain/registry/module/frontend/BUILD | 29 + .../module/frontend/FrontendServletTest.java | 42 + .../google/domain/registry/module/tools/BUILD | 29 + .../module/tools/ToolsServletTest.java | 42 + .../domain/registry/monitoring/whitebox/BUILD | 40 + .../whitebox/MetricsTaskServletTest.java | 168 + .../monitoring/whitebox/MetricsTest.java | 68 + .../com/google/domain/registry/rdap/BUILD | 38 + .../registry/rdap/RdapActionBaseTest.java | 148 + .../registry/rdap/RdapDomainActionTest.java | 257 + .../rdap/RdapDomainSearchActionTest.java | 584 + .../registry/rdap/RdapEntityActionTest.java | 255 + .../rdap/RdapEntitySearchActionTest.java | 303 + .../registry/rdap/RdapHelpActionTest.java | 115 + .../registry/rdap/RdapJsonFormatterTest.java | 382 + .../rdap/RdapNameserverActionTest.java | 218 + .../rdap/RdapNameserverSearchActionTest.java | 384 + .../registry/rdap/RdapSearchPatternTest.java | 105 + .../registry/rdap/testdata/rdap_contact.json | 39 + .../registry/rdap/testdata/rdap_domain.json | 309 + .../rdap/testdata/rdap_domain_unicode.json | 310 + .../rdap/testdata/rdap_error_400.json | 11 + .../rdap/testdata/rdap_error_404.json | 11 + .../rdap/testdata/rdap_error_422.json | 11 + .../rdap/testdata/rdap_error_501.json | 11 + .../rdap/testdata/rdap_help_index.json | 24 + .../registry/rdap/testdata/rdap_host.json | 22 + .../rdap/testdata/rdap_host_external.json | 17 + .../rdap/testdata/rdap_host_unicode.json | 23 + .../rdap/testdata/rdap_multiple_contacts.json | 124 + .../rdap/testdata/rdap_multiple_domains.json | 625 + .../rdap/testdata/rdap_multiple_hosts.json | 47 + .../rdap/testdata/rdap_registrar.json | 80 + .../rdap/testdata/rdapjson_admincontact.json | 39 + .../rdap/testdata/rdapjson_domain_full.json | 172 + .../testdata/rdapjson_domain_no_contacts.json | 66 + .../rdapjson_domain_no_nameservers.json | 130 + .../rdapjson_domain_no_registrant.json | 142 + .../rdap/testdata/rdapjson_error.json | 13 + .../rdap/testdata/rdapjson_host_both.json | 22 + .../rdap/testdata/rdapjson_host_ipv4.json | 21 + .../rdap/testdata/rdapjson_host_ipv6.json | 21 + .../testdata/rdapjson_host_no_addresses.json | 17 + .../rdapjson_notice_alternate_link.json | 18 + .../testdata/rdapjson_notice_self_link.json | 18 + .../rdap/testdata/rdapjson_registrant.json | 28 + .../testdata/rdapjson_registrant_nobase.json | 28 + .../rdap/testdata/rdapjson_registrar.json | 91 + .../rdap/testdata/rdapjson_techcontact.json | 39 + .../rdap/testdata/rdapjson_toplevel.json | 7 + .../com/google/domain/registry/rde/BUILD | 57 + .../domain/registry/rde/BouncyCastleTest.java | 432 + .../domain/registry/rde/BrdaCopyTaskTest.java | 194 + .../ContactResourceToXjcConverterTest.java | 355 + .../rde/DomainResourceToXjcConverterTest.java | 418 + .../registry/rde/EscrowTaskRunnerTest.java | 129 + .../rde/GhostrydeGpgIntegrationTest.java | 175 + .../domain/registry/rde/GhostrydeTest.java | 333 + .../rde/HostResourceToXjcConverterTest.java | 169 + .../rde/PendingDepositCheckerTest.java | 184 + .../domain/registry/rde/RdeFixtures.java | 244 + .../domain/registry/rde/RdeKeyringModule.java | 178 + .../registry/rde/RdeMarshallerTest.java | 127 + .../registry/rde/RdeReportTaskTest.java | 204 + .../registry/rde/RdeStagingActionTest.java | 626 + .../domain/registry/rde/RdeTestData.java | 45 + .../domain/registry/rde/RdeTestSuite.java | 34 + .../registry/rde/RdeUploadTaskTest.java | 359 + .../rde/RegistrarToXjcConverterTest.java | 151 + .../registry/rde/RydeGpgIntegrationTest.java | 286 + .../registry/rde/testdata/contact_create.xml | 33 + .../registry/rde/testdata/deposit_full.xml | 259 + .../rde/testdata/deposit_full_badref.xml | 259 + .../registry/rde/testdata/iirdea_bad.xml | 9 + .../registry/rde/testdata/iirdea_good.xml | 6 + .../testdata/pgp-private-keyring-escrow.asc | 61 + .../testdata/pgp-private-keyring-registry.asc | 98 + .../rde/testdata/pgp-public-keyring.asc | 95 + .../rde/testdata/registry-unittest.id_rsa | 27 + .../rde/testdata/registry-unittest.id_rsa.pub | 1 + .../domain/registry/rde/testdata/report.xml | 36 + ...pReduce_withDomain_producesExpectedXml.xml | 261 + ...MapReduce_withDomain_producesReportXml.xml | 42 + .../com/google/domain/registry/request/BUILD | 33 + .../registry/request/JsonResponseTest.java | 69 + .../registry/request/RequestHandlerTest.java | 324 + .../registry/request/RequestModuleTest.java | 66 + .../request/RequestParametersTest.java | 191 + .../registry/request/ResponseImplTest.java | 76 + .../domain/registry/request/RouterTest.java | 178 + .../com/google/domain/registry/security/BUILD | 56 + .../registry/security/JsonHttpTest.java | 136 + .../registry/security/JsonHttpTestUtils.java | 91 + .../security/JsonTransportServletTest.java | 159 + .../security/XsrfProtectedServletTest.java | 107 + .../security/XsrfTokenManagerTest.java | 96 + .../com/google/domain/registry/server/BUILD | 74 + .../domain/registry/server/Fixture.java | 149 + .../registry/server/HealthzServlet.java | 36 + .../registry/server/RegistryTestServer.java | 117 + .../server/RegistryTestServerMain.java | 172 + .../google/domain/registry/server/Route.java | 34 + .../ServletWrapperDelegatorServlet.java | 84 + .../server/StaticResourceServlet.java | 164 + .../domain/registry/server/TestServer.java | 189 + .../domain/registry/server/UrlChecker.java | 70 + .../domain/registry/storage/drive/BUILD | 27 + .../storage/drive/DriveConnectionTest.java | 247 + .../testing/AbstractDomainBaseSubject.java | 64 + .../testing/AbstractEppResourceSubject.java | 259 + .../registry/testing/AppEngineRule.java | 409 + .../com/google/domain/registry/testing/BUILD | 56 + .../testing/BouncyCastleProviderRule.java | 43 + .../registry/testing/CertificateSamples.java | 79 + .../testing/ContactResourceSubject.java | 130 + .../registry/testing/DatastoreHelper.java | 885 + .../testing/DomainApplicationSubject.java | 84 + .../testing/DomainResourceSubject.java | 72 + .../domain/registry/testing/EppLoader.java | 50 + .../registry/testing/ExceptionRule.java | 107 + .../domain/registry/testing/FailAnswer.java | 55 + .../domain/registry/testing/FakeClock.java | 69 + .../registry/testing/FakeJsonResponse.java | 43 + .../domain/registry/testing/FakeResponse.java | 105 + .../testing/FakeServletInputStream.java | 58 + .../testing/FakeServletOutputStream.java | 65 + .../domain/registry/testing/FakeSleeper.java | 50 + .../registry/testing/FakeURLFetchService.java | 50 + .../testing/ForwardingURLFetchService.java | 50 + .../testing/FullFieldsTestEntityHelper.java | 219 + .../registry/testing/GcsTestingUtils.java | 45 + .../testing/GenericEppResourceSubject.java | 45 + .../testing/GpgSystemCommandRule.java | 110 + .../registry/testing/HistoryEntrySubject.java | 106 + .../registry/testing/HostResourceSubject.java | 39 + .../domain/registry/testing/InjectRule.java | 174 + .../domain/registry/testing/IoSpyRule.java | 123 + .../domain/registry/testing/Providers.java | 36 + .../testing/ReflectiveSubjectFactory.java | 36 + .../registry/testing/RegistryConfigRule.java | 66 + .../domain/registry/testing/SlurpAnswer.java | 42 + .../domain/registry/testing/SystemInfo.java | 63 + .../registry/testing/SystemPropertyRule.java | 97 + .../registry/testing/TaskQueueHelper.java | 346 + .../registry/testing/TestDataHelper.java | 42 + .../domain/registry/testing/TestObject.java | 63 + .../registry/testing/TestSessionMetadata.java | 59 + .../domain/registry/testing/TruthChainer.java | 49 + .../registry/testing/UriParameters.java | 82 + .../domain/registry/testing/UserInfo.java | 47 + .../testing/default_premium_list_testdata.csv | 13 + .../registry/testing/logging.properties | 9 + .../domain/registry/testing/mapreduce/BUILD | 35 + .../testing/mapreduce/MapreduceTestCase.java | 218 + .../domain/registry/testing/package-info.java | 18 + .../google/domain/registry/testing/sftp/BUILD | 20 + .../registry/testing/sftp/SftpServerRule.java | 68 + .../registry/testing/sftp/TestSftpServer.java | 349 + .../domain/registry/tldconfig/idn/BUILD | 27 + .../tldconfig/idn/IdnLabelValidatorTest.java | 118 + .../registry/tldconfig/idn/IdnTableTest.java | 124 + .../com/google/domain/registry/tmch/BUILD | 44 + .../domain/registry/tmch/LordnLogTest.java | 161 + .../domain/registry/tmch/LordnTaskTest.java | 223 + .../registry/tmch/NordnUploadActionTest.java | 241 + .../registry/tmch/NordnVerifyActionTest.java | 182 + .../registry/tmch/SmdrlCsvParserTest.java | 138 + .../tmch/TmchCertificateAuthorityTest.java | 111 + .../domain/registry/tmch/TmchCrlTaskTest.java | 80 + .../domain/registry/tmch/TmchDnlTaskTest.java | 58 + .../registry/tmch/TmchSmdrlTaskTest.java | 59 + .../registry/tmch/TmchTaskTestCase.java | 85 + .../domain/registry/tmch/TmchTestData.java | 47 + .../domain/registry/tmch/TmchTestSuite.java | 34 + .../registry/tmch/TmchXmlSignatureTest.java | 341 + .../active/Court-Agent-Arabic-Active.smd | 109 + .../active/Court-Agent-Chinese-Active.smd | 102 + .../active/Court-Agent-English-Active.smd | 107 + .../active/Court-Agent-French-Active.smd | 108 + .../active/Court-Agent-Russian-Active.smd | 109 + .../active/Court-Holder-Arabic-Active.smd | 103 + .../active/Court-Holder-Chinese-Active.smd | 97 + .../active/Court-Holder-English-Active.smd | 101 + .../active/Court-Holder-French-Active.smd | 102 + .../active/Court-Holder-Russian-Active.smd | 105 + .../active/Trademark-Agent-Arabic-Active.smd | 109 + .../active/Trademark-Agent-Chinese-Active.smd | 104 + .../active/Trademark-Agent-English-Active.smd | 109 + .../active/Trademark-Agent-French-Active.smd | 108 + .../active/Trademark-Agent-Russian-Active.smd | 109 + .../active/Trademark-Holder-Arabic-Active.smd | 103 + .../Trademark-Holder-Chinese-Active.smd | 98 + .../Trademark-Holder-English-Active.smd | 104 + .../active/Trademark-Holder-French-Active.smd | 102 + .../Trademark-Holder-Russian-Active.smd | 98 + .../TreatyStatute-Agent-Arabic-Active.smd | 112 + .../TreatyStatute-Agent-Chinese-Active.smd | 105 + .../TreatyStatute-Agent-English-Active.smd | 110 + .../TreatyStatute-Agent-French-Active.smd | 110 + .../TreatyStatute-Agent-Russian-Active.smd | 113 + .../TreatyStatute-Holder-Arabic-Active.smd | 106 + .../TreatyStatute-Holder-Chinese-Active.smd | 100 + .../TreatyStatute-Holder-English-Active.smd | 104 + .../TreatyStatute-Holder-French-Active.smd | 105 + .../TreatyStatute-Holder-Russian-Active.smd | 108 + .../registry/tmch/testdata/dnl-latest.csv | 115 + .../registry/tmch/testdata/dnl-latest.sig | 11 + .../tmch/testdata/icann-tmch-test-good.crt | 26 + .../tmch/testdata/icann-tmch-test-revoked.crt | 26 + ...lidSignature-Court-Agent-French-Active.smd | 108 + ...gnature-Trademark-Agent-English-Active.smd | 109 + ...gnature-Trademark-Agent-Russian-Active.smd | 109 + ...ure-TreatyStatute-Agent-Chinese-Active.smd | 105 + ...ure-TreatyStatute-Agent-English-Active.smd | 110 + .../domain/registry/tmch/testdata/pubkey | 30 + .../smd/Court-Agent-Arabic-Revoked.smd | 110 + .../smd/Court-Agent-Chinese-Revoked.smd | 102 + .../smd/Court-Agent-English-Revoked.smd | 107 + .../smd/Court-Agent-French-Revoked.smd | 108 + .../smd/Court-Agent-Russian-Revoked.smd | 109 + .../smd/Court-Holder-Arabic-Revoked.smd | 103 + .../smd/Court-Holder-Chinese-Revoked.smd | 97 + .../smd/Court-Holder-English-Revoked.smd | 101 + .../smd/Court-Holder-French-Revoked.smd | 102 + .../smd/Court-Holder-Russian-Revoked.smd | 104 + .../smd/Trademark-Agent-Arabic-Revoked.smd | 109 + .../smd/Trademark-Agent-Chinese-Revoked.smd | 103 + .../smd/Trademark-Agent-English-Revoked.smd | 109 + .../smd/Trademark-Agent-French-Revoked.smd | 108 + .../smd/Trademark-Agent-Russian-Revoked.smd | 109 + .../smd/Trademark-Holder-Arabic-Revoked.smd | 103 + .../smd/Trademark-Holder-Chinese-Revoked.smd | 97 + .../smd/Trademark-Holder-English-Revoked.smd | 103 + .../smd/Trademark-Holder-French-Revoked.smd | 102 + .../smd/Trademark-Holder-Russian-Revoked.smd | 102 + .../TreatyStatute-Agent-Arabic-Revoked.smd | 112 + .../TreatyStatute-Agent-Chinese-Revoked.smd | 105 + .../TreatyStatute-Agent-English-Revoked.smd | 110 + .../TreatyStatute-Agent-French-Revoked.smd | 110 + .../TreatyStatute-Agent-Russian-Revoked.smd | 113 + .../TreatyStatute-Holder-Arabic-Revoked.smd | 106 + .../TreatyStatute-Holder-Chinese-Revoked.smd | 100 + .../TreatyStatute-Holder-English-Revoked.smd | 104 + .../TreatyStatute-Holder-French-Revoked.smd | 105 + .../TreatyStatute-Holder-Russian-Revoked.smd | 106 + .../TMVRevoked-Court-Agent-French-Active.smd | 108 + ...Revoked-Trademark-Agent-English-Active.smd | 109 + ...Revoked-Trademark-Agent-Russian-Active.smd | 109 + ...ked-TreatyStatute-Agent-Chinese-Active.smd | 105 + ...ked-TreatyStatute-Agent-English-Active.smd | 110 + .../registry/tmch/testdata/smdrl-latest.csv | 152 + .../registry/tmch/testdata/smdrl-latest.sig | 11 + .../tmch_test_smd_revocation_list.csv | 1 + .../tools/AllocateDomainCommandTest.java | 192 + .../com/google/domain/registry/tools/BUILD | 58 + .../registry/tools/CommandTestCase.java | 168 + .../tools/CreateAnchorTenantCommandTest.java | 125 + .../tools/CreateContactCommandTest.java | 87 + .../tools/CreateCreditBalanceCommandTest.java | 148 + .../tools/CreateCreditCommandTest.java | 188 + ...ateOrUpdatePremiumListCommandTestCase.java | 47 + ...teOrUpdateReservedListCommandTestCase.java | 68 + .../tools/CreatePremiumListCommandTest.java | 103 + .../tools/CreateRegistrarCommandTest.java | 1171 + .../CreateRegistrarGroupsCommandTest.java | 63 + .../tools/CreateReservedListCommandTest.java | 182 + .../registry/tools/CreateTldCommandTest.java | 372 + .../tools/DeleteCreditCommandTest.java | 137 + .../tools/DeleteDomainCommandTest.java | 83 + .../tools/DeleteEntityCommandTest.java | 59 + .../tools/DeletePremiumListCommandTest.java | 64 + .../tools/DeleteReservedListCommandTest.java | 62 + .../DomainApplicationInfoCommandTest.java | 79 + .../tools/DomainCheckClaimsCommandTest.java | 86 + .../tools/DomainCheckCommandTest.java | 86 + .../tools/DomainCheckFeeCommandTest.java | 86 + .../EncryptEscrowDepositCommandTest.java | 79 + .../registry/tools/EppToolCommandTest.java | 87 + .../tools/EppToolCommandTestCase.java | 91 + .../registry/tools/ExecuteEppCommandTest.java | 94 + .../registry/tools/FakePasswordGenerator.java | 45 + .../tools/GenerateAuctionDataCommandTest.java | 341 + .../tools/GenerateDnsReportCommandTest.java | 223 + .../GenerateEscrowDepositCommandTest.java | 240 + .../tools/GetApplicationCommandTest.java | 105 + .../tools/GetApplicationIdsCommandTest.java | 106 + .../tools/GetClaimsListCommandTest.java | 49 + .../registry/tools/GetContactCommandTest.java | 95 + .../registry/tools/GetDomainCommandTest.java | 112 + .../registry/tools/GetHostCommandTest.java | 114 + .../tools/GetRegistrarCommandTest.java | 53 + .../tools/GetResourceByKeyCommandTest.java | 213 + .../registry/tools/GetTldCommandTest.java | 58 + .../registry/tools/GhostrydeCommandTest.java | 137 + .../domain/registry/tools/GtechToolTest.java | 105 + .../tools/ListCursorsCommandTest.java | 70 + .../tools/ListDomainsCommandTest.java | 39 + .../registry/tools/ListHostsCommandTest.java | 35 + .../tools/ListObjectsCommandTestCase.java | 178 + .../tools/ListPremiumListsCommandTest.java | 36 + .../tools/ListRegistrarsCommandTest.java | 36 + .../tools/ListReservedListsCommandTest.java | 36 + .../registry/tools/ListTldsCommandTest.java | 36 + .../registry/tools/MutatingCommandTest.java | 432 + .../tools/PublishDetailReportCommandTest.java | 96 + .../tools/RegistrarContactCommandTest.java | 195 + .../tools/RegistryToolEnvironmentTest.java | 95 + .../registry/tools/RegistryToolTest.java | 104 + .../registry/tools/SetupOteCommandTest.java | 294 + .../UpdateApplicationStatusCommandTest.java | 286 + .../tools/UpdateClaimsNoticeCommandTest.java | 167 + .../tools/UpdateCursorsCommandTest.java | 58 + .../tools/UpdatePremiumListCommandTest.java | 68 + .../tools/UpdateRegistrarCommandTest.java | 590 + .../tools/UpdateReservedListCommandTest.java | 98 + .../tools/UpdateServerLocksCommandTest.java | 127 + .../registry/tools/UpdateSmdCommandTest.java | 149 + .../registry/tools/UpdateTldCommandTest.java | 624 + .../tools/UploadClaimsListCommandTest.java | 165 + .../ValidateEscrowDepositCommandTest.java | 109 + .../ValidateLoginCredentialsCommandTest.java | 131 + .../domain/registry/tools/mapreduce/BUILD | 40 + .../mapreduce/DeleteProberDataActionTest.java | 179 + .../ResaveAllEppResourcesActionTest.java | 61 + .../google/domain/registry/tools/params/BUILD | 28 + .../tools/params/DateTimeParameterTest.java | 133 + .../tools/params/DurationParameterTest.java | 101 + .../params/HostAndPortParameterTest.java | 52 + .../tools/params/MoneyParameterTest.java | 92 + .../tools/params/PathParameterTest.java | 172 + .../params/PhoneNumberParameterTest.java | 55 + .../tools/params/YearMonthParameterTest.java | 83 + .../google/domain/registry/tools/server/BUILD | 41 + .../tools/server/CreateGroupsTaskTest.java | 155 + .../server/CreatePremiumListActionTest.java | 102 + .../tools/server/DeleteEntityActionTest.java | 108 + .../server/GenerateZoneFilesActionTest.java | 133 + .../server/KillAllCommitLogsActionTest.java | 90 + .../server/KillAllEppResourcesActionTest.java | 160 + .../tools/server/ListActionTestCase.java | 92 + .../tools/server/ListDomainsActionTest.java | 215 + .../tools/server/ListHostsActionTest.java | 109 + .../server/ListPremiumListsActionTest.java | 92 + .../server/ListRegistrarsActionTest.java | 101 + .../server/ListReservedListsActionTest.java | 93 + .../tools/server/ListTldsActionTest.java | 81 + .../server/UpdatePremiumListActionTest.java | 90 + ...ihilateNonDefaultNamespacesActionTest.java | 107 + .../registry/tools/server/testdata/tld.zone | 16 + .../testdata/Court-Agent-Chinese-Active.smd | 102 + .../testdata/Court-Agent-English-Active.smd | 107 + ...gnature-Trademark-Agent-English-Active.smd | 109 + ...Revoked-Trademark-Agent-English-Active.smd | 109 + .../tools/testdata/allocate_domain.xml | 48 + .../tools/testdata/allocate_domain2.xml | 48 + .../tools/testdata/contact_create.xml | 34 + .../testdata/contact_create_complete.xml | 31 + .../tools/testdata/contact_create_minimal.xml | 18 + .../registry/tools/testdata/domain_check.xml | 11 + .../tools/testdata/domain_check_claims.xml | 17 + .../testdata/domain_check_claims_multiple.xml | 19 + .../domain_check_claims_second_tld.xml | 17 + .../tools/testdata/domain_check_fee.xml | 20 + .../testdata/domain_check_fee_multiple.xml | 32 + .../testdata/domain_check_fee_second_tld.xml | 20 + .../tools/testdata/domain_check_multiple.xml | 13 + .../testdata/domain_check_second_tld.xml | 11 + .../testdata/domain_create_anchor_tenant.xml | 25 + ...omain_create_anchor_tenant_fee_premium.xml | 29 + ...main_create_anchor_tenant_fee_standard.xml | 29 + ...ate_anchor_tenant_multiple_word_reason.xml | 25 + .../domain_create_anchor_tenant_no_reason.xml | 24 + .../domain_create_anchor_tenant_password.xml | 25 + .../domain_create_no_hosts_or_dsdata.xml | 18 + .../tools/testdata/domain_create_sunrush.xml | 29 + .../tools/testdata/domain_create_sunrush2.xml | 29 + .../registry/tools/testdata/domain_delete.xml | 17 + .../testdata/domain_delete_by_registrar.xml | 17 + .../domain_delete_multiple_word_reason.xml | 17 + .../tools/testdata/domain_info_landrush.xml | 19 + .../tools/testdata/domain_info_sunrush.xml | 19 + .../example_invalid_premium_terms.csv | 5 + .../tools/testdata/example_premium_terms.csv | 4 + .../tools/testdata/example_reserved_terms.csv | 2 + .../registry/tools/testdata/new-tlds.txt | 7 + .../registry/tools/testdata/old-tlds.txt | 4 + .../update_server_locks_apply_all.xml | 25 + ...date_server_locks_apply_all_remove_one.xml | 24 + .../update_server_locks_apply_one.xml | 21 + ...date_server_locks_multiple_word_reason.xml | 21 + .../update_server_locks_remove_all.xml | 25 + .../update_server_locks_remove_one.xml | 21 + .../xn--q9jyb4c_2010-10-17_full_S1_R0.xml | 137 + .../com/google/domain/registry/ui/forms/BUILD | 25 + .../ui/forms/FormFieldExceptionTest.java | 69 + .../registry/ui/forms/FormFieldTest.java | 491 + .../registry/ui/forms/FormFieldsTest.java | 107 + .../com/google/domain/registry/ui/js/BUILD | 23 + .../google/domain/registry/ui/js/admin/BUILD | 17 + .../registry/ui/js/admin/registrar_test.js | 306 + .../registry/ui/js/admin/registry_test.js | 207 + .../domain/registry/ui/js/component_test.js | 43 + .../domain/registry/ui/js/registrar/BUILD | 30 + .../ui/js/registrar/brainframe_test.js | 97 + .../registry/ui/js/registrar/console_test.js | 156 + .../ui/js/registrar/console_test_util.js | 95 + .../ui/js/registrar/contact_settings_test.js | 321 + .../registry/ui/js/registrar/contact_test.js | 128 + .../registry/ui/js/registrar/domain_test.js | 481 + .../registry/ui/js/registrar/host_test.js | 421 + .../registry/ui/js/registrar/payment_test.js | 222 + .../ui/js/registrar/security_settings_test.js | 143 + .../ui/js/registrar/whois_settings_test.js | 174 + .../google/domain/registry/ui/js/testing.js | 159 + .../google/domain/registry/ui/js/xml_test.js | 183 + .../google/domain/registry/ui/server/BUILD | 23 + .../ui/server/RegistrarFormFieldsTest.java | 65 + .../ui/server/admin/AdminUiServletTest.java | 29 + .../domain/registry/ui/server/admin/BUILD | 32 + .../ui/server/admin/RegistrarServletTest.java | 340 + .../ui/server/admin/RegistryServletTest.java | 304 + .../domain/registry/ui/server/api/BUILD | 27 + .../ui/server/api/CheckApiServletTest.java | 193 + .../domain/registry/ui/server/registrar/BUILD | 43 + .../registrar/ConsoleUiServletTest.java | 99 + .../server/registrar/ContactSettingsTest.java | 139 + .../registrar/RegistrarPaymentActionTest.java | 448 + .../RegistrarPaymentSetupActionTest.java | 90 + .../registrar/RegistrarServletTest.java | 170 + .../registrar/RegistrarServletTestCase.java | 112 + .../registrar/SecuritySettingsTest.java | 148 + .../ui/server/registrar/SessionUtilsTest.java | 146 + .../server/registrar/WhoisSettingsTest.java | 128 + .../registrar/testdata/update_registrar.json | 59 + .../update_registrar_duplicate_contacts.json | 69 + .../testdata/update_registrar_email.txt | 16 + .../com/google/domain/registry/util/BUILD | 34 + .../registry/util/CidrAddressBlockTest.java | 329 + .../registry/util/CollectionUtilsTest.java | 84 + .../domain/registry/util/ConcurrentTest.java | 77 + .../registry/util/DateTimeUtilsTest.java | 89 + .../domain/registry/util/DiffUtilsTest.java | 93 + .../registry/util/DomainNameUtilsTest.java | 53 + .../domain/registry/util/HexDumperTest.java | 216 + .../registry/util/PathargMatcherTest.java | 75 + .../util/PosixTarHeaderSystemTest.java | 265 + .../registry/util/PosixTarHeaderTest.java | 462 + .../domain/registry/util/RetrierTest.java | 67 + .../registry/util/SendEmailUtilsTest.java | 129 + .../registry/util/SerializeUtilsTest.java | 68 + .../domain/registry/util/SqlTemplateTest.java | 139 + .../registry/util/TaskEnqueuerTest.java | 114 + .../registry/util/TeeOutputStreamTest.java | 91 + .../registry/util/UrlFetchUtilsTest.java | 105 + .../com/google/domain/registry/whois/BUILD | 38 + .../whois/DomainWhoisResponseTest.java | 262 + .../whois/NameserverWhoisResponseTest.java | 96 + .../whois/RegistrarWhoisResponseTest.java | 135 + .../domain/registry/whois/WhoisHelper.java | 33 + .../registry/whois/WhoisHttpServerTest.java | 336 + .../registry/whois/WhoisInjectionTest.java | 87 + .../registry/whois/WhoisReaderTest.java | 341 + .../registry/whois/WhoisServerTest.java | 429 + .../registry/whois/WhoisTestComponent.java | 35 + .../registry/whois/testdata/whois_domain.txt | 60 + .../testdata/whois_multiple_nameservers.txt | 16 + .../whois/testdata/whois_nameserver.txt | 9 + .../whois/testdata/whois_registrar.txt | 25 + .../whois/testdata/whois_server_domain.txt | 58 + .../whois_server_domain_not_found.txt | 3 + .../testdata/whois_server_idn_punycode.txt | 58 + .../whois/testdata/whois_server_idn_utf8.txt | 58 + .../testdata/whois_server_ip_not_found.txt | 3 + .../testdata/whois_server_malformed_path.txt | 3 + .../testdata/whois_server_nameserver.txt | 8 + .../whois_server_nameserver_not_found.txt | 3 + .../testdata/whois_server_no_command.txt | 3 + .../whois/testdata/whois_server_registrar.txt | 21 + .../whois_server_registrar_not_found.txt | 3 + .../com/google/domain/registry/xjc/BUILD | 27 + .../domain/registry/xjc/XjcObjectTest.java | 128 + .../domain/registry/xjc/XmlTestdataTest.java | 159 + .../registry/xjc/testdata/contact_check.xml | 13 + .../xjc/testdata/contact_check_response.xml | 26 + .../registry/xjc/testdata/contact_create.xml | 33 + .../xjc/testdata/contact_create_response.xml | 18 + ...contact_create_response_offline_review.xml | 18 + ...eate_response_offline_review_completed.xml | 26 + .../registry/xjc/testdata/contact_delete.xml | 11 + .../xjc/testdata/contact_delete_response.xml | 11 + .../registry/xjc/testdata/contact_info.xml | 14 + .../xjc/testdata/contact_info_response.xml | 48 + .../xjc/testdata/contact_transfer_query.xml | 11 + .../contact_transfer_query_response.xml | 22 + .../xjc/testdata/contact_transfer_request.xml | 14 + .../contact_transfer_request_response.xml | 22 + .../registry/xjc/testdata/contact_update.xml | 36 + .../xjc/testdata/contact_update_response.xml | 11 + .../registry/xjc/testdata/domain_check.xml | 12 + .../xjc/testdata/domain_check_response.xml | 26 + .../registry/xjc/testdata/domain_create.xml | 22 + .../xjc/testdata/domain_create_response.xml | 19 + .../domain_create_response_offline_review.xml | 19 + ...eate_response_offline_review_completed.xml | 26 + .../registry/xjc/testdata/domain_delete.xml | 11 + .../xjc/testdata/domain_delete_response.xml | 11 + .../registry/xjc/testdata/domain_info.xml | 11 + .../xjc/testdata/domain_info_response.xml | 38 + .../domain_info_response_addperiod.xml | 41 + .../domain_info_response_pendingdelete.xml | 44 + .../domain_info_response_pendingrestore.xml | 50 + .../domain_info_response_redemptionperiod.xml | 44 + .../domain_info_response_unauthorized.xml | 19 + .../xjc/testdata/domain_info_with_auth.xml | 14 + .../registry/xjc/testdata/domain_renew.xml | 13 + .../xjc/testdata/domain_renew_response.xml | 18 + .../xjc/testdata/domain_transfer_query.xml | 11 + .../domain_transfer_query_response.xml | 23 + .../xjc/testdata/domain_transfer_request.xml | 15 + .../domain_transfer_request_response.xml | 23 + .../registry/xjc/testdata/domain_update.xml | 32 + .../xjc/testdata/domain_update_response.xml | 11 + .../testdata/domain_update_restore_report.xml | 46 + .../domain_update_restore_request.xml | 17 + ...domain_update_restore_request_response.xml | 11 + .../domain/registry/xjc/testdata/greeting.xml | 25 + .../registry/xjc/testdata/host_check.xml | 13 + .../xjc/testdata/host_check_response.xml | 28 + .../registry/xjc/testdata/host_create.xml | 14 + .../xjc/testdata/host_create_response.xml | 18 + .../host_create_response_offline_review.xml | 18 + ...reate_response_offline_review_complete.xml | 26 + .../registry/xjc/testdata/host_delete.xml | 11 + .../xjc/testdata/host_delete_response.xml | 11 + .../registry/xjc/testdata/host_info.xml | 11 + .../xjc/testdata/host_info_response.xml | 29 + .../registry/xjc/testdata/host_update.xml | 21 + .../xjc/testdata/host_update_response.xml | 11 + .../xjc/testdata/invalid_greeting.xml | 25 + .../domain/registry/xjc/testdata/login.xml | 23 + .../registry/xjc/testdata/login_response.xml | 11 + .../domain/registry/xjc/testdata/logout.xml | 6 + .../registry/xjc/testdata/logout_response.xml | 11 + .../domain/registry/xjc/testdata/poll.xml | 6 + .../domain/registry/xjc/testdata/poll_ack.xml | 6 + .../xjc/testdata/poll_ack_response.xml | 12 + .../xjc/testdata/poll_response_empty.xml | 11 + .../xjc/testdata/poll_response_mixed.xml | 17 + .../xjc/testdata/rde_deposit_differential.xml | 65 + .../xjc/testdata/rde_deposit_full.xml | 242 + .../xjc/testdata/restore_request_response.xml | 20 + .../com/google/domain/registry/xml/BUILD | 29 + .../domain/registry/xml/DateAdapterTest.java | 67 + .../registry/xml/UtcDateTimeAdapterTest.java | 76 + .../domain/registry/xml/XmlTestUtils.java | 151 + third_party/closure/compiler/BUILD | 10 + .../closure/compiler/closure_js_binary.bzl | 96 + .../compiler/closure_js_check_test.bzl | 69 + .../closure/compiler/closure_js_deps.bzl | 54 + .../closure/compiler/closure_js_library.bzl | 40 + third_party/closure/compiler/private/BUILD | 1 + third_party/closure/compiler/private/defs.bzl | 173 + third_party/closure/library/BUILD | 16 + .../closure/library/closure_library.BUILD | 31 + third_party/closure/stylesheets/BUILD | 16 + .../stylesheets/closure_css_binary.bzl | 78 + .../stylesheets/closure_css_library.bzl | 34 + third_party/closure/templates/BUILD | 50 + .../closure_template_java_library.bzl | 185 + .../templates/closure_template_js_library.bzl | 67 + third_party/closure/testing/BUILD | 26 + .../closure/testing/closure_js_test.bzl | 116 + .../closure/testing/externs/phantom.js | 282 + .../testing/phantomjs_jsunit_runner.js | 30 + .../closure/testing/phantomjs_runner.js | 285 + third_party/java/apache_mina/BUILD | 11 + third_party/java/apache_sshd/BUILD | 11 + third_party/java/appengine/BUILD | 77 + third_party/java/appengine_gcs_client/BUILD | 14 + third_party/java/appengine_mapreduce2/BUILD | 26 + third_party/java/appengine_pipeline/BUILD | 15 + third_party/java/auto/BUILD | 61 + third_party/java/bouncycastle/BUILD | 11 + third_party/java/bouncycastle_bcpg/BUILD | 8 + third_party/java/bouncycastle_bcpkix/BUILD | 8 + third_party/java/braintree/BUILD | 8 + third_party/java/charts4j/BUILD | 8 + third_party/java/dagger/BUILD | 49 + third_party/java/ftpserver/BUILD | 8 + third_party/java/google_java_format/BUILD | 12 + third_party/java/hamcrest/BUILD | 11 + third_party/java/icu4j/BUILD | 8 + third_party/java/javapoet/BUILD | 8 + third_party/java/jaxb/BUILD | 19 + third_party/java/jcommander/BUILD | 8 + third_party/java/jetty/v6_1_22/BUILD | 13 + third_party/java/joda_money/BUILD | 8 + third_party/java/joda_time/BUILD | 8 + third_party/java/jsch/BUILD | 8 + third_party/java/jsch/v0_1_44_google/BUILD | 15 + third_party/java/jsch/v0_1_44_google/LICENSE | 30 + .../java/jsch/v0_1_44_google/README.google | 63 + .../v0_1_44_google/jsch-0.1.44_google-src.jar | Bin 0 -> 216622 bytes .../v0_1_44_google/jsch-0.1.44_google.jar | Bin 0 -> 240921 bytes third_party/java/json/BUILD | 8 + third_party/java/json_simple/BUILD | 8 + third_party/java/jsr305_annotations/BUILD | 8 + third_party/java/jsr330_inject/BUILD | 8 + third_party/java/junit/BUILD | 9 + third_party/java/jzlib/BUILD | 8 + third_party/java/mockito/BUILD | 9 + third_party/java/objectify/BUILD | 8 + third_party/java/objectify/v4_1/BUILD | 18 + third_party/java/objectify/v4_1/LICENSE | 22 + third_party/java/objectify/v4_1/README.google | 39 + .../objectify/v4_1/objectify-4.1.3-src.jar | Bin 0 -> 234667 bytes .../java/objectify/v4_1/objectify-4.1.3.jar | Bin 0 -> 350568 bytes third_party/java/qdox/BUILD | 8 + third_party/java/servlet/servlet_api/BUILD | 8 + third_party/java/slf4j_api/BUILD | 8 + third_party/java/soy/BUILD | 32 + third_party/java/truth/BUILD | 9 + third_party/javascript/closure/BUILD | 15 + third_party/phantomjs/BUILD | 19 + 2490 files changed, 281594 insertions(+) create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 CONTRIBUTORS create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 WORKSPACE create mode 100644 apiserving/discoverydata/admin/BUILD create mode 100644 apiserving/discoverydata/bigquery/BUILD create mode 100644 apiserving/discoverydata/drive/BUILD create mode 100644 apiserving/discoverydata/groupssettings/BUILD create mode 100644 java/com/google/api/client/extensions/appengine/http/BUILD create mode 100644 java/com/google/api/client/googleapis/auth/oauth2/BUILD create mode 100644 java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2/BUILD create mode 100644 java/com/google/api/client/googleapis/json/BUILD create mode 100644 java/com/google/api/client/http/BUILD create mode 100644 java/com/google/api/client/http/javanet/BUILD create mode 100644 java/com/google/api/client/json/BUILD create mode 100644 java/com/google/api/client/json/jackson2/BUILD create mode 100644 java/com/google/api/client/testing/http/BUILD create mode 100644 java/com/google/common/annotations/BUILD create mode 100644 java/com/google/common/base/BUILD create mode 100644 java/com/google/common/cache/BUILD create mode 100644 java/com/google/common/collect/BUILD create mode 100644 java/com/google/common/escape/BUILD create mode 100644 java/com/google/common/hash/BUILD create mode 100644 java/com/google/common/html/BUILD create mode 100644 java/com/google/common/io/BUILD create mode 100644 java/com/google/common/math/BUILD create mode 100644 java/com/google/common/net/BUILD create mode 100644 java/com/google/common/primitives/BUILD create mode 100644 java/com/google/common/reflect/BUILD create mode 100644 java/com/google/common/testing/BUILD create mode 100644 java/com/google/common/util/concurrent/BUILD create mode 100644 java/com/google/domain/registry/BUILD create mode 100644 java/com/google/domain/registry/backup/BUILD create mode 100644 java/com/google/domain/registry/backup/BackupModule.java create mode 100644 java/com/google/domain/registry/backup/BackupUtils.java create mode 100644 java/com/google/domain/registry/backup/CommitLogCheckpointAction.java create mode 100644 java/com/google/domain/registry/backup/CommitLogCheckpointStrategy.java create mode 100644 java/com/google/domain/registry/backup/DeleteOldCommitLogsAction.java create mode 100644 java/com/google/domain/registry/backup/ExportCommitLogDiffAction.java create mode 100644 java/com/google/domain/registry/backup/GcsDiffFileLister.java create mode 100644 java/com/google/domain/registry/backup/RestoreCommitLogsAction.java create mode 100644 java/com/google/domain/registry/backup/package-info.java create mode 100644 java/com/google/domain/registry/bigquery/BUILD create mode 100644 java/com/google/domain/registry/bigquery/BigqueryConnection.java create mode 100644 java/com/google/domain/registry/bigquery/BigqueryFactory.java create mode 100644 java/com/google/domain/registry/bigquery/BigqueryHelper.java create mode 100644 java/com/google/domain/registry/bigquery/BigqueryJobFailureException.java create mode 100644 java/com/google/domain/registry/bigquery/BigqueryModule.java create mode 100644 java/com/google/domain/registry/bigquery/BigqueryUtils.java create mode 100644 java/com/google/domain/registry/bigquery/package-info.java create mode 100644 java/com/google/domain/registry/braintree/BUILD create mode 100644 java/com/google/domain/registry/braintree/BraintreeModule.java create mode 100644 java/com/google/domain/registry/braintree/package-info.java create mode 100644 java/com/google/domain/registry/config/BUILD create mode 100644 java/com/google/domain/registry/config/ConfigModule.java create mode 100644 java/com/google/domain/registry/config/ConfigUtils.java create mode 100644 java/com/google/domain/registry/config/RegistryConfig.java create mode 100644 java/com/google/domain/registry/config/RegistryEnvironment.java create mode 100644 java/com/google/domain/registry/config/TestRegistryConfig.java create mode 100644 java/com/google/domain/registry/config/package-info.java create mode 100644 java/com/google/domain/registry/cron/BUILD create mode 100644 java/com/google/domain/registry/cron/CommitLogFanoutAction.java create mode 100644 java/com/google/domain/registry/cron/CronModule.java create mode 100644 java/com/google/domain/registry/cron/TldFanoutAction.java create mode 100644 java/com/google/domain/registry/cron/package-info.java create mode 100644 java/com/google/domain/registry/dns/BUILD create mode 100644 java/com/google/domain/registry/dns/DnsConstants.java create mode 100644 java/com/google/domain/registry/dns/DnsModule.java create mode 100644 java/com/google/domain/registry/dns/DnsQueue.java create mode 100644 java/com/google/domain/registry/dns/PublishDnsUpdatesAction.java create mode 100644 java/com/google/domain/registry/dns/ReadDnsQueueAction.java create mode 100644 java/com/google/domain/registry/dns/RefreshDns.java create mode 100644 java/com/google/domain/registry/dns/WriteDnsTask.java create mode 100644 java/com/google/domain/registry/dns/writer/api/BUILD create mode 100644 java/com/google/domain/registry/dns/writer/api/DnsWriter.java create mode 100644 java/com/google/domain/registry/dns/writer/api/DnsWriterZone.java create mode 100644 java/com/google/domain/registry/dns/writer/api/VoidDnsWriter.java create mode 100644 java/com/google/domain/registry/dns/writer/api/VoidDnsWriterModule.java create mode 100644 java/com/google/domain/registry/env/BUILD create mode 100644 java/com/google/domain/registry/env/common/BUILD create mode 100644 java/com/google/domain/registry/env/common/META-INF/appengine-application.xml create mode 100644 java/com/google/domain/registry/env/common/META-INF/application.xml create mode 100644 java/com/google/domain/registry/env/common/backend/BUILD create mode 100644 java/com/google/domain/registry/env/common/backend/WEB-INF/logging.properties create mode 100644 java/com/google/domain/registry/env/common/backend/WEB-INF/web.xml create mode 100644 java/com/google/domain/registry/env/common/default/BUILD create mode 100644 java/com/google/domain/registry/env/common/default/WEB-INF/datastore-indexes.xml create mode 100644 java/com/google/domain/registry/env/common/default/WEB-INF/dos.xml create mode 100644 java/com/google/domain/registry/env/common/default/WEB-INF/logging.properties create mode 100644 java/com/google/domain/registry/env/common/default/WEB-INF/queue.xml create mode 100644 java/com/google/domain/registry/env/common/default/WEB-INF/web.xml create mode 100644 java/com/google/domain/registry/env/common/tools/BUILD create mode 100644 java/com/google/domain/registry/env/common/tools/WEB-INF/logging.properties create mode 100644 java/com/google/domain/registry/env/common/tools/WEB-INF/web.xml create mode 100644 java/com/google/domain/registry/env/production/BUILD create mode 100644 java/com/google/domain/registry/env/production/backend/BUILD create mode 100644 java/com/google/domain/registry/env/production/backend/WEB-INF/appengine-web.xml create mode 100644 java/com/google/domain/registry/env/production/default/BUILD create mode 100644 java/com/google/domain/registry/env/production/default/WEB-INF/appengine-web.xml create mode 100644 java/com/google/domain/registry/env/production/default/WEB-INF/cron.xml create mode 100644 java/com/google/domain/registry/env/production/tools/BUILD create mode 100644 java/com/google/domain/registry/env/production/tools/WEB-INF/appengine-web.xml create mode 100644 java/com/google/domain/registry/export/BUILD create mode 100644 java/com/google/domain/registry/export/BigqueryPollJobAction.java create mode 100644 java/com/google/domain/registry/export/BigquerySchemas.java create mode 100644 java/com/google/domain/registry/export/CheckSnapshotServlet.java create mode 100644 java/com/google/domain/registry/export/DatastoreBackupInfo.java create mode 100644 java/com/google/domain/registry/export/DatastoreBackupService.java create mode 100644 java/com/google/domain/registry/export/DriveModule.java create mode 100644 java/com/google/domain/registry/export/ExportConstants.java create mode 100644 java/com/google/domain/registry/export/ExportRequestModule.java create mode 100644 java/com/google/domain/registry/export/ExportReservedTermsTask.java create mode 100644 java/com/google/domain/registry/export/ExportSnapshotServlet.java create mode 100644 java/com/google/domain/registry/export/ExportUtils.java create mode 100644 java/com/google/domain/registry/export/LoadSnapshotServlet.java create mode 100644 java/com/google/domain/registry/export/PublishDetailReportAction.java create mode 100644 java/com/google/domain/registry/export/SyncGroupMembersTask.java create mode 100644 java/com/google/domain/registry/export/UpdateSnapshotViewServlet.java create mode 100644 java/com/google/domain/registry/export/package-info.java create mode 100644 java/com/google/domain/registry/export/sheet/BUILD create mode 100644 java/com/google/domain/registry/export/sheet/SheetModule.java create mode 100644 java/com/google/domain/registry/export/sheet/SheetSynchronizer.java create mode 100644 java/com/google/domain/registry/export/sheet/SpreadsheetServiceModule.java create mode 100644 java/com/google/domain/registry/export/sheet/SyncRegistrarsSheet.java create mode 100644 java/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTask.java create mode 100644 java/com/google/domain/registry/export/sheet/package-info.java create mode 100644 java/com/google/domain/registry/flows/BUILD create mode 100644 java/com/google/domain/registry/flows/EppConsoleServlet.java create mode 100644 java/com/google/domain/registry/flows/EppController.java create mode 100644 java/com/google/domain/registry/flows/EppException.java create mode 100644 java/com/google/domain/registry/flows/EppServletUtils.java create mode 100644 java/com/google/domain/registry/flows/EppTlsServlet.java create mode 100644 java/com/google/domain/registry/flows/EppToolServlet.java create mode 100644 java/com/google/domain/registry/flows/EppXmlTransformer.java create mode 100644 java/com/google/domain/registry/flows/Flow.java create mode 100644 java/com/google/domain/registry/flows/FlowRegistry.java create mode 100644 java/com/google/domain/registry/flows/FlowRunner.java create mode 100644 java/com/google/domain/registry/flows/HttpSessionMetadata.java create mode 100644 java/com/google/domain/registry/flows/LoggedInFlow.java create mode 100644 java/com/google/domain/registry/flows/OwnedResourceMutateFlow.java create mode 100644 java/com/google/domain/registry/flows/OwnedResourceMutatePendingTransferFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceAsyncDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceCreateOrMutateFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceFlowUtils.java create mode 100644 java/com/google/domain/registry/flows/ResourceInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceMutateFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceMutatePendingTransferFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceQueryFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceSyncDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferApproveFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferCancelFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferQueryFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferRejectFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceTransferRequestFlow.java create mode 100644 java/com/google/domain/registry/flows/ResourceUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/SessionMetadata.java create mode 100644 java/com/google/domain/registry/flows/SingleResourceFlow.java create mode 100644 java/com/google/domain/registry/flows/StatelessRequestSessionMetadata.java create mode 100644 java/com/google/domain/registry/flows/TlsCredentials.java create mode 100644 java/com/google/domain/registry/flows/TransactionalFlow.java create mode 100644 java/com/google/domain/registry/flows/TransportCredentials.java create mode 100644 java/com/google/domain/registry/flows/async/AsyncFlowUtils.java create mode 100644 java/com/google/domain/registry/flows/async/AsyncFlowsModule.java create mode 100644 java/com/google/domain/registry/flows/async/DeleteContactResourceAction.java create mode 100644 java/com/google/domain/registry/flows/async/DeleteEppResourceAction.java create mode 100644 java/com/google/domain/registry/flows/async/DeleteHostResourceAction.java create mode 100644 java/com/google/domain/registry/flows/async/DnsRefreshForHostRenameAction.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactFlowUtils.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactTransferApproveFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactTransferCancelFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactTransferQueryFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactTransferRejectFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactTransferRequestFlow.java create mode 100644 java/com/google/domain/registry/flows/contact/ContactUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/BaseDomainCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/BaseDomainCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/BaseDomainInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/BaseDomainUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/ClaimsCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainAllocateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainApplicationCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainApplicationDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainApplicationInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainApplicationUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainCreateOrAllocateFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainFlowUtils.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainRenewFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainRestoreRequestFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainTransferApproveFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainTransferCancelFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainTransferQueryFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainTransferRejectFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainTransferRequestFlow.java create mode 100644 java/com/google/domain/registry/flows/domain/DomainUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/host/HostCheckFlow.java create mode 100644 java/com/google/domain/registry/flows/host/HostCreateFlow.java create mode 100644 java/com/google/domain/registry/flows/host/HostDeleteFlow.java create mode 100644 java/com/google/domain/registry/flows/host/HostFlowUtils.java create mode 100644 java/com/google/domain/registry/flows/host/HostInfoFlow.java create mode 100644 java/com/google/domain/registry/flows/host/HostUpdateFlow.java create mode 100644 java/com/google/domain/registry/flows/poll/PollAckFlow.java create mode 100644 java/com/google/domain/registry/flows/poll/PollFlow.java create mode 100644 java/com/google/domain/registry/flows/poll/PollRequestFlow.java create mode 100644 java/com/google/domain/registry/flows/session/HelloFlow.java create mode 100644 java/com/google/domain/registry/flows/session/LoginFlow.java create mode 100644 java/com/google/domain/registry/flows/session/LogoutFlow.java create mode 100644 java/com/google/domain/registry/gcs/BUILD create mode 100644 java/com/google/domain/registry/gcs/GcsServiceModule.java create mode 100644 java/com/google/domain/registry/gcs/GcsUtils.java create mode 100644 java/com/google/domain/registry/groups/BUILD create mode 100644 java/com/google/domain/registry/groups/DirectoryGroupsConnection.java create mode 100644 java/com/google/domain/registry/groups/DirectoryModule.java create mode 100644 java/com/google/domain/registry/groups/GroupsConnection.java create mode 100644 java/com/google/domain/registry/groups/GroupsModule.java create mode 100644 java/com/google/domain/registry/groups/GroupssettingsModule.java create mode 100644 java/com/google/domain/registry/idn/Arabic-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Armenian-IDN.txt create mode 100644 java/com/google/domain/registry/idn/BUILD create mode 100644 java/com/google/domain/registry/idn/Bengali-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Chinese-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Cyrillic-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Devanagari-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Ethiopic-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Georgian-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Greek-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Gurmukhi-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Hebrew-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Japanese-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Kannada-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Khmer-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Korean-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Latin-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Malayalam-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Myanmar-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Oriya-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Sinhala-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Tamil-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Telugu-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Thai-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Tibetan-IDN.txt create mode 100644 java/com/google/domain/registry/idn/Traditional-Chinese-IDN.txt create mode 100644 java/com/google/domain/registry/keyring/api/BUILD create mode 100644 java/com/google/domain/registry/keyring/api/KeyModule.java create mode 100644 java/com/google/domain/registry/keyring/api/Keyring.java create mode 100644 java/com/google/domain/registry/keyring/api/PgpHelper.java create mode 100644 java/com/google/domain/registry/keyring/api/VoidKeyring.java create mode 100644 java/com/google/domain/registry/keyring/api/VoidKeyringModule.java create mode 100644 java/com/google/domain/registry/keyring/api/package-info.java create mode 100644 java/com/google/domain/registry/loadtest/BUILD create mode 100644 java/com/google/domain/registry/loadtest/LoadTask.java create mode 100644 java/com/google/domain/registry/loadtest/LoadTestAction.java create mode 100644 java/com/google/domain/registry/loadtest/LoadTestModule.java create mode 100644 java/com/google/domain/registry/loadtest/templates/contact_create.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/contact_info.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/domain_check.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/domain_create.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/domain_info.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/host_create.xml create mode 100644 java/com/google/domain/registry/loadtest/templates/host_info.xml create mode 100644 java/com/google/domain/registry/mapreduce/BUILD create mode 100644 java/com/google/domain/registry/mapreduce/ChunkingKeyInput.java create mode 100644 java/com/google/domain/registry/mapreduce/ConcatenatingInput.java create mode 100644 java/com/google/domain/registry/mapreduce/EppResourceInputs.java create mode 100644 java/com/google/domain/registry/mapreduce/MapreduceAction.java create mode 100644 java/com/google/domain/registry/mapreduce/MapreduceModule.java create mode 100644 java/com/google/domain/registry/mapreduce/MapreduceRunner.java create mode 100644 java/com/google/domain/registry/mapreduce/NullInput.java create mode 100644 java/com/google/domain/registry/model/AbstractFieldExposer.java create mode 100644 java/com/google/domain/registry/model/BUILD create mode 100644 java/com/google/domain/registry/model/BackupGroupRoot.java create mode 100644 java/com/google/domain/registry/model/Buildable.java create mode 100644 java/com/google/domain/registry/model/CreateAutoTimestamp.java create mode 100644 java/com/google/domain/registry/model/EntityClasses.java create mode 100644 java/com/google/domain/registry/model/EppResource.java create mode 100644 java/com/google/domain/registry/model/EppResourceUtils.java create mode 100644 java/com/google/domain/registry/model/ImmutableObject.java create mode 100644 java/com/google/domain/registry/model/JsonMapBuilder.java create mode 100644 java/com/google/domain/registry/model/Jsonifiable.java create mode 100644 java/com/google/domain/registry/model/ModelUtils.java create mode 100644 java/com/google/domain/registry/model/RoidSuffixes.java create mode 100644 java/com/google/domain/registry/model/SchemaVersion.java create mode 100644 java/com/google/domain/registry/model/UpdateAutoTimestamp.java create mode 100644 java/com/google/domain/registry/model/annotations/ExternalMessagingName.java create mode 100644 java/com/google/domain/registry/model/annotations/NotBackedUp.java create mode 100644 java/com/google/domain/registry/model/annotations/VirtualEntity.java create mode 100644 java/com/google/domain/registry/model/billing/BillingEvent.java create mode 100644 java/com/google/domain/registry/model/billing/RegistrarBillingEntry.java create mode 100644 java/com/google/domain/registry/model/billing/RegistrarBillingUtils.java create mode 100644 java/com/google/domain/registry/model/billing/RegistrarCredit.java create mode 100644 java/com/google/domain/registry/model/billing/RegistrarCreditBalance.java create mode 100644 java/com/google/domain/registry/model/common/CrossTldSingleton.java create mode 100644 java/com/google/domain/registry/model/common/EntityGroupRoot.java create mode 100644 java/com/google/domain/registry/model/common/GaeUserIdConverter.java create mode 100644 java/com/google/domain/registry/model/common/PersistedRangeLong.java create mode 100644 java/com/google/domain/registry/model/common/TimeOfYear.java create mode 100644 java/com/google/domain/registry/model/common/TimedTransitionProperty.java create mode 100644 java/com/google/domain/registry/model/contact/ContactAddress.java create mode 100644 java/com/google/domain/registry/model/contact/ContactAuthInfo.java create mode 100644 java/com/google/domain/registry/model/contact/ContactCommand.java create mode 100644 java/com/google/domain/registry/model/contact/ContactPhoneNumber.java create mode 100644 java/com/google/domain/registry/model/contact/ContactResource.java create mode 100644 java/com/google/domain/registry/model/contact/Disclose.java create mode 100644 java/com/google/domain/registry/model/contact/PostalInfo.java create mode 100644 java/com/google/domain/registry/model/contact/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/DesignatedContact.java create mode 100644 java/com/google/domain/registry/model/domain/DomainApplication.java create mode 100644 java/com/google/domain/registry/model/domain/DomainAuthInfo.java create mode 100644 java/com/google/domain/registry/model/domain/DomainBase.java create mode 100644 java/com/google/domain/registry/model/domain/DomainCommand.java create mode 100644 java/com/google/domain/registry/model/domain/DomainRenewData.java create mode 100644 java/com/google/domain/registry/model/domain/DomainResource.java create mode 100644 java/com/google/domain/registry/model/domain/DomainUtils.java create mode 100644 java/com/google/domain/registry/model/domain/GracePeriod.java create mode 100644 java/com/google/domain/registry/model/domain/Period.java create mode 100644 java/com/google/domain/registry/model/domain/ReferenceUnion.java create mode 100644 java/com/google/domain/registry/model/domain/allocate/AllocateCreateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/allocate/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/fee/BaseFee.java create mode 100644 java/com/google/domain/registry/model/domain/fee/BaseFeeCommand.java create mode 100644 java/com/google/domain/registry/model/domain/fee/BaseFeeCommandResponse.java create mode 100644 java/com/google/domain/registry/model/domain/fee/BaseFeeRequest.java create mode 100644 java/com/google/domain/registry/model/domain/fee/BaseFeeResponse.java create mode 100644 java/com/google/domain/registry/model/domain/fee/Credit.java create mode 100644 java/com/google/domain/registry/model/domain/fee/Fee.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeCheckExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeCheckResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeCommandDescriptor.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeCreateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeCreateResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeDeleteResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeInfoExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeInfoResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeRenewExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeRenewResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeTransferExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeTransferResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeUpdateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/FeeUpdateResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/fee/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/launch/ApplicationIdTargetExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/ApplicationStatus.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchCheckExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchCheckResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchCreateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchCreateResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchDeleteExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchInfoExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchInfoResponseExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchNotice.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchPhase.java create mode 100644 java/com/google/domain/registry/model/domain/launch/LaunchUpdateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/launch/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/metadata/MetadataExtension.java create mode 100644 java/com/google/domain/registry/model/domain/metadata/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/rgp/GracePeriodStatus.java create mode 100644 java/com/google/domain/registry/model/domain/rgp/RestoreCommand.java create mode 100644 java/com/google/domain/registry/model/domain/rgp/RgpInfoExtension.java create mode 100644 java/com/google/domain/registry/model/domain/rgp/RgpUpdateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/rgp/package-info.java create mode 100644 java/com/google/domain/registry/model/domain/secdns/DelegationSignerData.java create mode 100644 java/com/google/domain/registry/model/domain/secdns/SecDnsCreateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/secdns/SecDnsInfoExtension.java create mode 100644 java/com/google/domain/registry/model/domain/secdns/SecDnsUpdateExtension.java create mode 100644 java/com/google/domain/registry/model/domain/secdns/package-info.java create mode 100644 java/com/google/domain/registry/model/eppcommon/Address.java create mode 100644 java/com/google/domain/registry/model/eppcommon/AuthInfo.java create mode 100644 java/com/google/domain/registry/model/eppcommon/PhoneNumber.java create mode 100644 java/com/google/domain/registry/model/eppcommon/PresenceMarker.java create mode 100644 java/com/google/domain/registry/model/eppcommon/ProtocolDefinition.java create mode 100644 java/com/google/domain/registry/model/eppcommon/StatusValue.java create mode 100644 java/com/google/domain/registry/model/eppcommon/Trid.java create mode 100644 java/com/google/domain/registry/model/eppcommon/package-info.java create mode 100644 java/com/google/domain/registry/model/eppinput/EppInput.java create mode 100644 java/com/google/domain/registry/model/eppinput/ResourceCommand.java create mode 100644 java/com/google/domain/registry/model/eppinput/package-info.java create mode 100644 java/com/google/domain/registry/model/eppoutput/CheckData.java create mode 100644 java/com/google/domain/registry/model/eppoutput/CreateData.java create mode 100644 java/com/google/domain/registry/model/eppoutput/EppOutput.java create mode 100644 java/com/google/domain/registry/model/eppoutput/Greeting.java create mode 100644 java/com/google/domain/registry/model/eppoutput/Response.java create mode 100644 java/com/google/domain/registry/model/eppoutput/Result.java create mode 100644 java/com/google/domain/registry/model/eppoutput/package-info.java create mode 100644 java/com/google/domain/registry/model/export/LogsExportCursor.java create mode 100755 java/com/google/domain/registry/model/generate_field_exposer.sh create mode 100755 java/com/google/domain/registry/model/generate_field_exposer_registry.sh create mode 100644 java/com/google/domain/registry/model/host/HostCommand.java create mode 100644 java/com/google/domain/registry/model/host/HostResource.java create mode 100644 java/com/google/domain/registry/model/host/InetAddressAdapter.java create mode 100644 java/com/google/domain/registry/model/host/package-info.java create mode 100644 java/com/google/domain/registry/model/index/DomainApplicationIndex.java create mode 100644 java/com/google/domain/registry/model/index/EppResourceIndex.java create mode 100644 java/com/google/domain/registry/model/index/EppResourceIndexBucket.java create mode 100644 java/com/google/domain/registry/model/index/ForeignKeyIndex.java create mode 100644 java/com/google/domain/registry/model/mark/CommonMarkContactFields.java create mode 100644 java/com/google/domain/registry/model/mark/CommonMarkFields.java create mode 100644 java/com/google/domain/registry/model/mark/CourtMark.java create mode 100644 java/com/google/domain/registry/model/mark/Mark.java create mode 100644 java/com/google/domain/registry/model/mark/MarkAddress.java create mode 100644 java/com/google/domain/registry/model/mark/MarkContact.java create mode 100644 java/com/google/domain/registry/model/mark/MarkHolder.java create mode 100644 java/com/google/domain/registry/model/mark/MarkPhoneNumber.java create mode 100644 java/com/google/domain/registry/model/mark/MarkProtection.java create mode 100644 java/com/google/domain/registry/model/mark/ProtectedMark.java create mode 100644 java/com/google/domain/registry/model/mark/Trademark.java create mode 100644 java/com/google/domain/registry/model/mark/TreatyOrStatuteMark.java create mode 100644 java/com/google/domain/registry/model/mark/package-info.java create mode 100644 java/com/google/domain/registry/model/ofy/AugmentedDeleter.java create mode 100644 java/com/google/domain/registry/model/ofy/AugmentedSaver.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLogBucket.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLogCheckpoint.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLogCheckpointRoot.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLogManifest.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLogMutation.java create mode 100644 java/com/google/domain/registry/model/ofy/CommitLoggedWork.java create mode 100644 java/com/google/domain/registry/model/ofy/ObjectifyService.java create mode 100644 java/com/google/domain/registry/model/ofy/Ofy.java create mode 100644 java/com/google/domain/registry/model/ofy/OfyFilter.java create mode 100644 java/com/google/domain/registry/model/ofy/ReadOnlyWork.java create mode 100644 java/com/google/domain/registry/model/ofy/SessionKeyExposingObjectify.java create mode 100644 java/com/google/domain/registry/model/ofy/TimestampInversionException.java create mode 100644 java/com/google/domain/registry/model/ofy/TransactionInfo.java create mode 100644 java/com/google/domain/registry/model/package-info.java create mode 100644 java/com/google/domain/registry/model/poll/MessageQueueInfo.java create mode 100644 java/com/google/domain/registry/model/poll/PendingActionNotificationResponse.java create mode 100644 java/com/google/domain/registry/model/poll/PollMessage.java create mode 100644 java/com/google/domain/registry/model/poll/PollMessageExternalKeyConverter.java create mode 100644 java/com/google/domain/registry/model/poll/package-info.java create mode 100644 java/com/google/domain/registry/model/rde/RdeMode.java create mode 100644 java/com/google/domain/registry/model/rde/RdeNamingUtils.java create mode 100644 java/com/google/domain/registry/model/rde/RdeRevision.java create mode 100644 java/com/google/domain/registry/model/registrar/Registrar.java create mode 100644 java/com/google/domain/registry/model/registrar/RegistrarAddress.java create mode 100644 java/com/google/domain/registry/model/registrar/RegistrarContact.java create mode 100644 java/com/google/domain/registry/model/registry/Registries.java create mode 100644 java/com/google/domain/registry/model/registry/Registry.java create mode 100644 java/com/google/domain/registry/model/registry/RegistryCursor.java create mode 100644 java/com/google/domain/registry/model/registry/label/BaseDomainLabelList.java create mode 100644 java/com/google/domain/registry/model/registry/label/DomainLabelEntry.java create mode 100644 java/com/google/domain/registry/model/registry/label/PremiumList.java create mode 100644 java/com/google/domain/registry/model/registry/label/ReservationType.java create mode 100644 java/com/google/domain/registry/model/registry/label/ReservedList.java create mode 100644 java/com/google/domain/registry/model/registry/label/package-info.java create mode 100644 java/com/google/domain/registry/model/reporting/HistoryEntry.java create mode 100644 java/com/google/domain/registry/model/server/Lock.java create mode 100644 java/com/google/domain/registry/model/server/ServerSecret.java create mode 100644 java/com/google/domain/registry/model/smd/AbstractSignedMark.java create mode 100644 java/com/google/domain/registry/model/smd/EncodedSignedMark.java create mode 100644 java/com/google/domain/registry/model/smd/IssuerInfo.java create mode 100644 java/com/google/domain/registry/model/smd/RemoveWhitespaceTextAdapter.java create mode 100644 java/com/google/domain/registry/model/smd/SignedMark.java create mode 100644 java/com/google/domain/registry/model/smd/SignedMarkRevocationList.java create mode 100644 java/com/google/domain/registry/model/smd/package-info.java create mode 100644 java/com/google/domain/registry/model/tmch/ClaimsListShard.java create mode 100644 java/com/google/domain/registry/model/tmch/TmchCrl.java create mode 100644 java/com/google/domain/registry/model/transfer/BaseTransferObject.java create mode 100644 java/com/google/domain/registry/model/transfer/TransferData.java create mode 100644 java/com/google/domain/registry/model/transfer/TransferResponse.java create mode 100644 java/com/google/domain/registry/model/transfer/TransferStatus.java create mode 100644 java/com/google/domain/registry/model/transfer/package-info.java create mode 100644 java/com/google/domain/registry/model/translators/AbstractSimpleTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/CidrAddressBlockTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/CommitLogRevisionsTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/CreateAutoTimestampTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/CurrencyUnitAdapter.java create mode 100644 java/com/google/domain/registry/model/translators/CurrencyUnitTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/DurationTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/EnumToAttributeAdapter.java create mode 100644 java/com/google/domain/registry/model/translators/ImmutableSortedMapTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/InetAddressTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/ReadableInstantUtcTranslatorFactory.java create mode 100644 java/com/google/domain/registry/model/translators/StatusValueAdapter.java create mode 100644 java/com/google/domain/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java create mode 100644 java/com/google/domain/registry/module/backend/BUILD create mode 100644 java/com/google/domain/registry/module/backend/BackendComponent.java create mode 100644 java/com/google/domain/registry/module/backend/BackendModule.java create mode 100644 java/com/google/domain/registry/module/backend/BackendRequestComponent.java create mode 100644 java/com/google/domain/registry/module/backend/BackendServlet.java create mode 100644 java/com/google/domain/registry/module/backend/package-info.java create mode 100644 java/com/google/domain/registry/module/frontend/BUILD create mode 100644 java/com/google/domain/registry/module/frontend/FrontendComponent.java create mode 100644 java/com/google/domain/registry/module/frontend/FrontendRequestComponent.java create mode 100644 java/com/google/domain/registry/module/frontend/FrontendServlet.java create mode 100644 java/com/google/domain/registry/module/frontend/package-info.java create mode 100644 java/com/google/domain/registry/module/tools/BUILD create mode 100644 java/com/google/domain/registry/module/tools/ToolsComponent.java create mode 100644 java/com/google/domain/registry/module/tools/ToolsRequestComponent.java create mode 100644 java/com/google/domain/registry/module/tools/ToolsServlet.java create mode 100644 java/com/google/domain/registry/monitoring/whitebox/BUILD create mode 100644 java/com/google/domain/registry/monitoring/whitebox/EppMetrics.java create mode 100644 java/com/google/domain/registry/monitoring/whitebox/Metrics.java create mode 100644 java/com/google/domain/registry/monitoring/whitebox/MetricsTaskServlet.java create mode 100644 java/com/google/domain/registry/monitoring/whitebox/package-info.java create mode 100644 java/com/google/domain/registry/rdap/BUILD create mode 100644 java/com/google/domain/registry/rdap/RdapActionBase.java create mode 100644 java/com/google/domain/registry/rdap/RdapAutnumAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapDomainAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapDomainSearchAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapEntityAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapEntitySearchAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapHelpAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapIpAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapJsonFormatter.java create mode 100644 java/com/google/domain/registry/rdap/RdapModule.java create mode 100644 java/com/google/domain/registry/rdap/RdapNameserverAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapNameserverSearchAction.java create mode 100644 java/com/google/domain/registry/rdap/RdapSearchPattern.java create mode 100644 java/com/google/domain/registry/rde/BUILD create mode 100644 java/com/google/domain/registry/rde/BrdaCopyTask.java create mode 100644 java/com/google/domain/registry/rde/ContactResourceToXjcConverter.java create mode 100644 java/com/google/domain/registry/rde/DepositFragment.java create mode 100644 java/com/google/domain/registry/rde/DomainResourceToXjcConverter.java create mode 100644 java/com/google/domain/registry/rde/EscrowTaskRunner.java create mode 100644 java/com/google/domain/registry/rde/Ghostryde.java create mode 100644 java/com/google/domain/registry/rde/HostResourceToXjcConverter.java create mode 100644 java/com/google/domain/registry/rde/JSchModule.java create mode 100644 java/com/google/domain/registry/rde/JSchSftpChannel.java create mode 100644 java/com/google/domain/registry/rde/JSchSshSession.java create mode 100644 java/com/google/domain/registry/rde/PendingDeposit.java create mode 100644 java/com/google/domain/registry/rde/PendingDepositChecker.java create mode 100644 java/com/google/domain/registry/rde/RdeAdapter.java create mode 100644 java/com/google/domain/registry/rde/RdeCounter.java create mode 100644 java/com/google/domain/registry/rde/RdeMarshaller.java create mode 100644 java/com/google/domain/registry/rde/RdeModule.java create mode 100644 java/com/google/domain/registry/rde/RdeReportTask.java create mode 100644 java/com/google/domain/registry/rde/RdeReporter.java create mode 100644 java/com/google/domain/registry/rde/RdeResourceType.java create mode 100644 java/com/google/domain/registry/rde/RdeStagingAction.java create mode 100644 java/com/google/domain/registry/rde/RdeStagingMapper.java create mode 100644 java/com/google/domain/registry/rde/RdeStagingReducer.java create mode 100644 java/com/google/domain/registry/rde/RdeUploadTask.java create mode 100644 java/com/google/domain/registry/rde/RdeUploadUrl.java create mode 100644 java/com/google/domain/registry/rde/RdeUtil.java create mode 100644 java/com/google/domain/registry/rde/RegistrarToXjcConverter.java create mode 100644 java/com/google/domain/registry/rde/RydePgpCompressionOutputStream.java create mode 100644 java/com/google/domain/registry/rde/RydePgpEncryptionOutputStream.java create mode 100644 java/com/google/domain/registry/rde/RydePgpFileOutputStream.java create mode 100644 java/com/google/domain/registry/rde/RydePgpSigningOutputStream.java create mode 100644 java/com/google/domain/registry/rde/RydeTarOutputStream.java create mode 100644 java/com/google/domain/registry/rde/package-info.java create mode 100644 java/com/google/domain/registry/request/Action.java create mode 100644 java/com/google/domain/registry/request/Actions.java create mode 100644 java/com/google/domain/registry/request/BUILD create mode 100644 java/com/google/domain/registry/request/DelegatedOAuthScopes.java create mode 100644 java/com/google/domain/registry/request/Header.java create mode 100644 java/com/google/domain/registry/request/HttpException.java create mode 100644 java/com/google/domain/registry/request/JsonActionRunner.java create mode 100644 java/com/google/domain/registry/request/JsonPayload.java create mode 100644 java/com/google/domain/registry/request/JsonResponse.java create mode 100644 java/com/google/domain/registry/request/Modules.java create mode 100644 java/com/google/domain/registry/request/OAuthScopes.java create mode 100644 java/com/google/domain/registry/request/Parameter.java create mode 100644 java/com/google/domain/registry/request/ParameterMap.java create mode 100644 java/com/google/domain/registry/request/Payload.java create mode 100644 java/com/google/domain/registry/request/RequestHandler.java create mode 100644 java/com/google/domain/registry/request/RequestMethod.java create mode 100644 java/com/google/domain/registry/request/RequestModule.java create mode 100644 java/com/google/domain/registry/request/RequestParameters.java create mode 100644 java/com/google/domain/registry/request/RequestPath.java create mode 100644 java/com/google/domain/registry/request/RequestScope.java create mode 100644 java/com/google/domain/registry/request/Response.java create mode 100644 java/com/google/domain/registry/request/ResponseImpl.java create mode 100644 java/com/google/domain/registry/request/Route.java create mode 100644 java/com/google/domain/registry/request/Router.java create mode 100644 java/com/google/domain/registry/request/ServletDelegate.java create mode 100644 java/com/google/domain/registry/request/package-info.java create mode 100644 java/com/google/domain/registry/security/BUILD create mode 100644 java/com/google/domain/registry/security/JsonHttp.java create mode 100644 java/com/google/domain/registry/security/JsonResponseHelper.java create mode 100644 java/com/google/domain/registry/security/JsonTransportServlet.java create mode 100644 java/com/google/domain/registry/security/XsrfProtectedServlet.java create mode 100644 java/com/google/domain/registry/security/XsrfTokenManager.java create mode 100644 java/com/google/domain/registry/security/package-info.java create mode 100644 java/com/google/domain/registry/storage/drive/BUILD create mode 100644 java/com/google/domain/registry/storage/drive/DriveConnection.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/BUILD create mode 100644 java/com/google/domain/registry/tldconfig/idn/IdnLabelValidator.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/IdnTable.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/IdnTableEnum.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/JapaneseLanguageValidator.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/LanguageValidator.java create mode 100644 java/com/google/domain/registry/tldconfig/idn/extended_latin.txt create mode 100644 java/com/google/domain/registry/tldconfig/idn/ja.txt create mode 100644 java/com/google/domain/registry/tmch/BUILD create mode 100644 java/com/google/domain/registry/tmch/ClaimsListParser.java create mode 100644 java/com/google/domain/registry/tmch/LordnLog.java create mode 100644 java/com/google/domain/registry/tmch/LordnRequestInitializer.java create mode 100644 java/com/google/domain/registry/tmch/LordnTask.java create mode 100644 java/com/google/domain/registry/tmch/Marksdb.java create mode 100644 java/com/google/domain/registry/tmch/NordnUploadAction.java create mode 100644 java/com/google/domain/registry/tmch/NordnVerifyAction.java create mode 100644 java/com/google/domain/registry/tmch/SmdrlCsvParser.java create mode 100644 java/com/google/domain/registry/tmch/TmchCertificateAuthority.java create mode 100644 java/com/google/domain/registry/tmch/TmchCrlTask.java create mode 100644 java/com/google/domain/registry/tmch/TmchData.java create mode 100644 java/com/google/domain/registry/tmch/TmchDnlTask.java create mode 100644 java/com/google/domain/registry/tmch/TmchModule.java create mode 100644 java/com/google/domain/registry/tmch/TmchSmdrlTask.java create mode 100644 java/com/google/domain/registry/tmch/TmchXmlSignature.java create mode 100644 java/com/google/domain/registry/tmch/icann-tmch-test.crl create mode 100644 java/com/google/domain/registry/tmch/icann-tmch-test.crt create mode 100644 java/com/google/domain/registry/tmch/icann-tmch.crl create mode 100644 java/com/google/domain/registry/tmch/icann-tmch.crt create mode 100644 java/com/google/domain/registry/tmch/marksdb-public-key.asc create mode 100644 java/com/google/domain/registry/tmch/package-info.java create mode 100644 java/com/google/domain/registry/tools/AllocateDomainCommand.java create mode 100644 java/com/google/domain/registry/tools/AppEngineConnection.java create mode 100644 java/com/google/domain/registry/tools/AuctionStatusCommand.java create mode 100644 java/com/google/domain/registry/tools/BUILD create mode 100644 java/com/google/domain/registry/tools/BigqueryCommand.java create mode 100644 java/com/google/domain/registry/tools/BigqueryCommandUtilities.java create mode 100644 java/com/google/domain/registry/tools/BigqueryParameters.java create mode 100644 java/com/google/domain/registry/tools/CanonicalizeLabelsCommand.java create mode 100644 java/com/google/domain/registry/tools/CheckSnapshotCommand.java create mode 100644 java/com/google/domain/registry/tools/Command.java create mode 100644 java/com/google/domain/registry/tools/CommandUtilities.java create mode 100644 java/com/google/domain/registry/tools/ConfirmingCommand.java create mode 100644 java/com/google/domain/registry/tools/ConvertIdnCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateAnchorTenantCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateAuctionCreditsCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateContactCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateCreditBalanceCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateCreditCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateOrUpdatePremiumListCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateOrUpdateRegistrarCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateOrUpdateReservedListCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateOrUpdateTldCommand.java create mode 100644 java/com/google/domain/registry/tools/CreatePremiumListCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateRegistrarCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateRegistrarGroupsCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateReservedListCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateSandboxTldCommand.java create mode 100644 java/com/google/domain/registry/tools/CreateTldCommand.java create mode 100644 java/com/google/domain/registry/tools/DeleteCreditCommand.java create mode 100644 java/com/google/domain/registry/tools/DeleteDomainCommand.java create mode 100644 java/com/google/domain/registry/tools/DeleteEntityCommand.java create mode 100644 java/com/google/domain/registry/tools/DeleteEppResourceCommand.java create mode 100644 java/com/google/domain/registry/tools/DeletePremiumListCommand.java create mode 100644 java/com/google/domain/registry/tools/DeleteReservedListCommand.java create mode 100644 java/com/google/domain/registry/tools/DomainApplicationInfoCommand.java create mode 100644 java/com/google/domain/registry/tools/DomainCheckClaimsCommand.java create mode 100644 java/com/google/domain/registry/tools/DomainCheckCommand.java create mode 100644 java/com/google/domain/registry/tools/DomainCheckFeeCommand.java create mode 100644 java/com/google/domain/registry/tools/EncryptEscrowDepositCommand.java create mode 100644 java/com/google/domain/registry/tools/EppToolCommand.java create mode 100644 java/com/google/domain/registry/tools/EscrowDepositEncryptor.java create mode 100644 java/com/google/domain/registry/tools/ExecuteEppCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateApplicationsReportCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateAuctionDataCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateDnsReportCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateEscrowDepositCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateLordnCommand.java create mode 100644 java/com/google/domain/registry/tools/GenerateZoneFilesCommand.java create mode 100644 java/com/google/domain/registry/tools/GetApplicationCommand.java create mode 100644 java/com/google/domain/registry/tools/GetApplicationIdsCommand.java create mode 100644 java/com/google/domain/registry/tools/GetAppliedLabelsCommand.java create mode 100644 java/com/google/domain/registry/tools/GetClaimsListCommand.java create mode 100644 java/com/google/domain/registry/tools/GetContactCommand.java create mode 100644 java/com/google/domain/registry/tools/GetDomainCommand.java create mode 100644 java/com/google/domain/registry/tools/GetEppResourceCommand.java create mode 100644 java/com/google/domain/registry/tools/GetHistoryEntriesCommand.java create mode 100644 java/com/google/domain/registry/tools/GetHostCommand.java create mode 100644 java/com/google/domain/registry/tools/GetRegistrarCommand.java create mode 100644 java/com/google/domain/registry/tools/GetResourceByKeyCommand.java create mode 100644 java/com/google/domain/registry/tools/GetSchemaCommand.java create mode 100644 java/com/google/domain/registry/tools/GetTldCommand.java create mode 100644 java/com/google/domain/registry/tools/GhostrydeCommand.java create mode 100644 java/com/google/domain/registry/tools/GtechTool.java create mode 100644 java/com/google/domain/registry/tools/HashCertificateCommand.java create mode 100644 java/com/google/domain/registry/tools/HelpCommand.java create mode 100644 java/com/google/domain/registry/tools/Injector.java create mode 100644 java/com/google/domain/registry/tools/ListCreditsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListCursorsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListDomainsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListHostsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListObjectsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListPremiumListsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListRegistrarsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListReservedListsCommand.java create mode 100644 java/com/google/domain/registry/tools/ListTldsCommand.java create mode 100644 java/com/google/domain/registry/tools/LoadSnapshotCommand.java create mode 100644 java/com/google/domain/registry/tools/LoggingParameters.java create mode 100644 java/com/google/domain/registry/tools/MakeBillingTablesCommand.java create mode 100644 java/com/google/domain/registry/tools/MutatingCommand.java create mode 100644 java/com/google/domain/registry/tools/MutatingEppToolCommand.java create mode 100644 java/com/google/domain/registry/tools/PasswordGenerator.java create mode 100644 java/com/google/domain/registry/tools/PendingEscrowCommand.java create mode 100644 java/com/google/domain/registry/tools/PublishDetailReportCommand.java create mode 100644 java/com/google/domain/registry/tools/RandomPasswordGenerator.java create mode 100644 java/com/google/domain/registry/tools/RegistrarActivityReportCommand.java create mode 100644 java/com/google/domain/registry/tools/RegistrarContactCommand.java create mode 100644 java/com/google/domain/registry/tools/RegistryCli.java create mode 100644 java/com/google/domain/registry/tools/RegistryTool.java create mode 100644 java/com/google/domain/registry/tools/RegistryToolComponent.java create mode 100644 java/com/google/domain/registry/tools/RegistryToolEnvironment.java create mode 100644 java/com/google/domain/registry/tools/RegistryToolModule.java create mode 100644 java/com/google/domain/registry/tools/SendEscrowReportToIcannCommand.java create mode 100644 java/com/google/domain/registry/tools/ServerSideCommand.java create mode 100644 java/com/google/domain/registry/tools/SetupOteCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateApplicationStatusCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateClaimsNoticeCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateCreditsCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateCursorsCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdatePremiumListCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateRegistrarCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateReservedListCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateSandboxTldCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateServerLocksCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateSmdCommand.java create mode 100644 java/com/google/domain/registry/tools/UpdateTldCommand.java create mode 100644 java/com/google/domain/registry/tools/UploadClaimsListCommand.java create mode 100644 java/com/google/domain/registry/tools/UserIdProvider.java create mode 100644 java/com/google/domain/registry/tools/ValidateEscrowDepositCommand.java create mode 100644 java/com/google/domain/registry/tools/ValidateLoginCredentialsCommand.java create mode 100644 java/com/google/domain/registry/tools/VerifyOteCommand.java create mode 100644 java/com/google/domain/registry/tools/WhoisQueryCommand.java create mode 100644 java/com/google/domain/registry/tools/javascrap/LoadAndResaveCommand.java create mode 100644 java/com/google/domain/registry/tools/logging.properties create mode 100644 java/com/google/domain/registry/tools/mapreduce/BUILD create mode 100644 java/com/google/domain/registry/tools/mapreduce/DeleteProberDataAction.java create mode 100644 java/com/google/domain/registry/tools/mapreduce/ResaveAllEppResourcesAction.java create mode 100644 java/com/google/domain/registry/tools/package-info.java create mode 100644 java/com/google/domain/registry/tools/params/BUILD create mode 100644 java/com/google/domain/registry/tools/params/DateTimeParameter.java create mode 100644 java/com/google/domain/registry/tools/params/DurationParameter.java create mode 100644 java/com/google/domain/registry/tools/params/EppResourceTypeParameter.java create mode 100644 java/com/google/domain/registry/tools/params/HostAndPortParameter.java create mode 100644 java/com/google/domain/registry/tools/params/InternetDomainNameParameter.java create mode 100644 java/com/google/domain/registry/tools/params/LocalDateParameter.java create mode 100644 java/com/google/domain/registry/tools/params/LoggingLevelParameter.java create mode 100644 java/com/google/domain/registry/tools/params/LongParameter.java create mode 100644 java/com/google/domain/registry/tools/params/MoneyParameter.java create mode 100644 java/com/google/domain/registry/tools/params/OptionalLongParameter.java create mode 100644 java/com/google/domain/registry/tools/params/OptionalParameterConverterValidator.java create mode 100644 java/com/google/domain/registry/tools/params/OptionalPhoneNumberParameter.java create mode 100644 java/com/google/domain/registry/tools/params/OptionalStringParameter.java create mode 100644 java/com/google/domain/registry/tools/params/ParameterConverterValidator.java create mode 100644 java/com/google/domain/registry/tools/params/ParameterFactory.java create mode 100644 java/com/google/domain/registry/tools/params/PathParameter.java create mode 100644 java/com/google/domain/registry/tools/params/PhoneNumberParameter.java create mode 100644 java/com/google/domain/registry/tools/params/StringParameter.java create mode 100644 java/com/google/domain/registry/tools/params/TransitionListParameter.java create mode 100644 java/com/google/domain/registry/tools/params/YearMonthParameter.java create mode 100644 java/com/google/domain/registry/tools/params/package-info.java create mode 100644 java/com/google/domain/registry/tools/server/BUILD create mode 100644 java/com/google/domain/registry/tools/server/CreateGroupsTask.java create mode 100644 java/com/google/domain/registry/tools/server/CreateOrUpdatePremiumListAction.java create mode 100644 java/com/google/domain/registry/tools/server/CreatePremiumListAction.java create mode 100644 java/com/google/domain/registry/tools/server/DeleteEntityAction.java create mode 100644 java/com/google/domain/registry/tools/server/GenerateZoneFilesAction.java create mode 100644 java/com/google/domain/registry/tools/server/KillAllCommitLogsAction.java create mode 100644 java/com/google/domain/registry/tools/server/KillAllEppResourcesAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListDomainsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListHostsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListObjectsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListPremiumListsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListRegistrarsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListReservedListsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ListTldsAction.java create mode 100644 java/com/google/domain/registry/tools/server/ToolsServerModule.java create mode 100644 java/com/google/domain/registry/tools/server/UpdatePremiumListAction.java create mode 100644 java/com/google/domain/registry/tools/server/javascrap/AnnihilateNonDefaultNamespacesAction.java create mode 100644 java/com/google/domain/registry/tools/soy/BUILD create mode 100644 java/com/google/domain/registry/tools/soy/CreateAnchorTenant.soy create mode 100644 java/com/google/domain/registry/tools/soy/CreateContact.soy create mode 100644 java/com/google/domain/registry/tools/soy/DeleteDomain.soy create mode 100644 java/com/google/domain/registry/tools/soy/DomainAllocate.soy create mode 100644 java/com/google/domain/registry/tools/soy/DomainApplicationInfo.soy create mode 100644 java/com/google/domain/registry/tools/soy/DomainCheck.soy create mode 100644 java/com/google/domain/registry/tools/soy/DomainCheckClaims.soy create mode 100644 java/com/google/domain/registry/tools/soy/DomainCheckFee.soy create mode 100644 java/com/google/domain/registry/tools/soy/Login.soy create mode 100644 java/com/google/domain/registry/tools/soy/UpdateServerLocks.soy create mode 100644 java/com/google/domain/registry/tools/sql/ReportingHistory.sql create mode 100644 java/com/google/domain/registry/tools/sql/ReportingIdentifiers.sql create mode 100644 java/com/google/domain/registry/tools/sql/billing_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/credit_balance_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/credit_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/currency_table.sql create mode 100644 java/com/google/domain/registry/tools/sql/premium_list_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/recurring_event_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/registrar_activity_report.sql create mode 100644 java/com/google/domain/registry/tools/sql/registrar_data_view.sql create mode 100644 java/com/google/domain/registry/tools/sql/registry_data_view.sql create mode 100644 java/com/google/domain/registry/ui/BUILD create mode 100644 java/com/google/domain/registry/ui/ConsoleConfigModule.java create mode 100644 java/com/google/domain/registry/ui/ConsoleDebug.java create mode 100644 java/com/google/domain/registry/ui/assets/html/brainframe-alpha.html create mode 100644 java/com/google/domain/registry/ui/assets/html/brainframe-map.html create mode 100644 java/com/google/domain/registry/ui/assets/html/brainframe.html create mode 100644 java/com/google/domain/registry/ui/assets/html/insecure-brainframe.html create mode 100644 java/com/google/domain/registry/ui/assets/html/integration-test-brainframe.html create mode 100644 java/com/google/domain/registry/ui/assets/images/ajax-loader.gif create mode 100644 java/com/google/domain/registry/ui/assets/images/android_sad.png create mode 100644 java/com/google/domain/registry/ui/assets/images/disclosure_arrow_dk_grey.png create mode 100644 java/com/google/domain/registry/ui/assets/images/disclosure_arrow_dk_grey_down.png create mode 100644 java/com/google/domain/registry/ui/assets/images/disclosure_arrow_dk_grey_up_down.png create mode 100644 java/com/google/domain/registry/ui/assets/images/explore_24.png create mode 100644 java/com/google/domain/registry/ui/assets/images/folder.png create mode 100644 java/com/google/domain/registry/ui/assets/images/glogo_black.png create mode 100644 java/com/google/domain/registry/ui/assets/images/google.png create mode 100644 java/com/google/domain/registry/ui/assets/images/homeContact.png create mode 100644 java/com/google/domain/registry/ui/assets/images/homeResources.png create mode 100644 java/com/google/domain/registry/ui/assets/images/homeSettings.png create mode 100644 java/com/google/domain/registry/ui/assets/images/ic_contacts_blue_12.png create mode 100644 java/com/google/domain/registry/ui/assets/images/ic_contacts_blue_8.png create mode 100644 java/com/google/domain/registry/ui/assets/images/icons/svg/Gcomm/search.svg create mode 100644 java/com/google/domain/registry/ui/assets/images/icons/svg/search.svg create mode 100644 java/com/google/domain/registry/ui/assets/images/icons/svg/settings.svg create mode 100644 java/com/google/domain/registry/ui/assets/images/loader1x.gif create mode 100644 java/com/google/domain/registry/ui/assets/images/loader4x.gif create mode 100644 java/com/google/domain/registry/ui/assets/images/logo_sm.gif create mode 100644 java/com/google/domain/registry/ui/assets/images/offline_lightning.png create mode 100644 java/com/google/domain/registry/ui/assets/images/ribbon_certified-128.png create mode 100644 java/com/google/domain/registry/ui/assets/images/ribbon_certified-64.png create mode 100644 java/com/google/domain/registry/ui/assets/images/visibleOff_16.png create mode 100644 java/com/google/domain/registry/ui/assets/images/visibleOn_16.png create mode 100644 java/com/google/domain/registry/ui/compile_test.js create mode 100644 java/com/google/domain/registry/ui/conformance_proto.txt create mode 100644 java/com/google/domain/registry/ui/css/BUILD create mode 100644 java/com/google/domain/registry/ui/css/admin-console.css create mode 100644 java/com/google/domain/registry/ui/css/admin_imports_raw.css create mode 100644 java/com/google/domain/registry/ui/css/console.css create mode 100644 java/com/google/domain/registry/ui/css/contact-settings.css create mode 100644 java/com/google/domain/registry/ui/css/contact-us.css create mode 100644 java/com/google/domain/registry/ui/css/dashboard.css create mode 100644 java/com/google/domain/registry/ui/css/demo_css.css create mode 100644 java/com/google/domain/registry/ui/css/epp.css create mode 100644 java/com/google/domain/registry/ui/css/forms.css create mode 100644 java/com/google/domain/registry/ui/css/kd_components.css create mode 100644 java/com/google/domain/registry/ui/css/registrar_imports_raw.css create mode 100644 java/com/google/domain/registry/ui/css/registry.css create mode 100644 java/com/google/domain/registry/ui/css/resources.css create mode 100644 java/com/google/domain/registry/ui/css/security-settings.css create mode 100644 java/com/google/domain/registry/ui/epptmpl/contact_info.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/contact_transfer_request.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/domain_create_no_hosts_or_dsdata.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/domain_delete.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/domain_update_restore_request.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/hello.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/login_valid.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/logout.xml create mode 100644 java/com/google/domain/registry/ui/epptmpl/poll.xml create mode 100644 java/com/google/domain/registry/ui/externs/BUILD create mode 100644 java/com/google/domain/registry/ui/externs/braintree.js create mode 100644 java/com/google/domain/registry/ui/externs/json.js create mode 100644 java/com/google/domain/registry/ui/externs/rpc_payment.js create mode 100644 java/com/google/domain/registry/ui/externs/rpc_paymentsetup.js create mode 100644 java/com/google/domain/registry/ui/forms/BUILD create mode 100644 java/com/google/domain/registry/ui/forms/FormException.java create mode 100644 java/com/google/domain/registry/ui/forms/FormField.java create mode 100644 java/com/google/domain/registry/ui/forms/FormFieldException.java create mode 100644 java/com/google/domain/registry/ui/forms/FormFields.java create mode 100644 java/com/google/domain/registry/ui/forms/package-info.java create mode 100644 java/com/google/domain/registry/ui/globals.txt create mode 100644 java/com/google/domain/registry/ui/html/BUILD create mode 100644 java/com/google/domain/registry/ui/html/error.html create mode 100644 java/com/google/domain/registry/ui/html/index.html create mode 100644 java/com/google/domain/registry/ui/js/BUILD create mode 100644 java/com/google/domain/registry/ui/js/admin/BUILD create mode 100644 java/com/google/domain/registry/ui/js/admin/console.js create mode 100644 java/com/google/domain/registry/ui/js/admin/main.js create mode 100644 java/com/google/domain/registry/ui/js/admin/registrar.js create mode 100644 java/com/google/domain/registry/ui/js/admin/registry.js create mode 100644 java/com/google/domain/registry/ui/js/component.js create mode 100644 java/com/google/domain/registry/ui/js/console.js create mode 100644 java/com/google/domain/registry/ui/js/edit_item.js create mode 100644 java/com/google/domain/registry/ui/js/forms.js create mode 100644 java/com/google/domain/registry/ui/js/menu_button.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/BUILD create mode 100644 java/com/google/domain/registry/ui/js/registrar/brainframe.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/console.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/contact.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/contact_settings.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/contact_us.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/dashboard.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/domain.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/epp_session.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/host.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/main.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/payment.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/resources.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/security_settings.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/whois_settings.js create mode 100644 java/com/google/domain/registry/ui/js/registrar/xml_resource_component.js create mode 100644 java/com/google/domain/registry/ui/js/resource.js create mode 100644 java/com/google/domain/registry/ui/js/resource_component.js create mode 100644 java/com/google/domain/registry/ui/js/session.js create mode 100644 java/com/google/domain/registry/ui/js/util.js create mode 100644 java/com/google/domain/registry/ui/js/xml.js create mode 100644 java/com/google/domain/registry/ui/package-info.java create mode 100644 java/com/google/domain/registry/ui/server/AbstractUiServlet.java create mode 100644 java/com/google/domain/registry/ui/server/BUILD create mode 100644 java/com/google/domain/registry/ui/server/RegistrarFormFields.java create mode 100644 java/com/google/domain/registry/ui/server/SoyTemplateUtils.java create mode 100644 java/com/google/domain/registry/ui/server/StateCode.java create mode 100644 java/com/google/domain/registry/ui/server/admin/AdminResourceServlet.java create mode 100644 java/com/google/domain/registry/ui/server/admin/AdminUiServlet.java create mode 100644 java/com/google/domain/registry/ui/server/admin/BUILD create mode 100644 java/com/google/domain/registry/ui/server/admin/RegistrarServlet.java create mode 100644 java/com/google/domain/registry/ui/server/admin/RegistryServlet.java create mode 100644 java/com/google/domain/registry/ui/server/admin/VerifyOteServlet.java create mode 100644 java/com/google/domain/registry/ui/server/admin/package-info.java create mode 100644 java/com/google/domain/registry/ui/server/api/BUILD create mode 100644 java/com/google/domain/registry/ui/server/api/CheckApiServlet.java create mode 100644 java/com/google/domain/registry/ui/server/api/package-info.java create mode 100644 java/com/google/domain/registry/ui/server/package-info.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/BUILD create mode 100644 java/com/google/domain/registry/ui/server/registrar/ConsoleUiServlet.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/RegistrarPaymentAction.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/RegistrarPaymentSetupAction.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/RegistrarServlet.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/ResourceServlet.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/SessionUtils.java create mode 100644 java/com/google/domain/registry/ui/server/registrar/package-info.java create mode 100644 java/com/google/domain/registry/ui/soy/BUILD create mode 100644 java/com/google/domain/registry/ui/soy/Console.soy create mode 100644 java/com/google/domain/registry/ui/soy/Forms.soy create mode 100644 java/com/google/domain/registry/ui/soy/admin/BUILD create mode 100644 java/com/google/domain/registry/ui/soy/admin/Console.soy create mode 100644 java/com/google/domain/registry/ui/soy/admin/Registrar.soy create mode 100644 java/com/google/domain/registry/ui/soy/admin/Registry.soy create mode 100644 java/com/google/domain/registry/ui/soy/api/BUILD create mode 100644 java/com/google/domain/registry/ui/soy/api/DomainCheckFeeEpp.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/BUILD create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Console.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Contact.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/ContactEpp.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/ContactSettings.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Domain.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/DomainEpp.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Epp.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Host.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/HostEpp.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/Payment.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/SecuritySettings.soy create mode 100644 java/com/google/domain/registry/ui/soy/registrar/WhoisSettings.soy create mode 100644 java/com/google/domain/registry/util/AppEngineTimeLimiter.java create mode 100644 java/com/google/domain/registry/util/BUILD create mode 100644 java/com/google/domain/registry/util/BasicHttpSession.java create mode 100644 java/com/google/domain/registry/util/CacheUtils.java create mode 100644 java/com/google/domain/registry/util/CapturingLogHandler.java create mode 100644 java/com/google/domain/registry/util/CidrAddressBlock.java create mode 100644 java/com/google/domain/registry/util/Clock.java create mode 100644 java/com/google/domain/registry/util/CollectionUtils.java create mode 100644 java/com/google/domain/registry/util/Concurrent.java create mode 100644 java/com/google/domain/registry/util/DatastoreServiceUtils.java create mode 100644 java/com/google/domain/registry/util/DateTimeUtils.java create mode 100644 java/com/google/domain/registry/util/DiffUtils.java create mode 100644 java/com/google/domain/registry/util/DomainNameUtils.java create mode 100644 java/com/google/domain/registry/util/FixedClock.java create mode 100644 java/com/google/domain/registry/util/FormattingLogger.java create mode 100644 java/com/google/domain/registry/util/HexDumper.java create mode 100644 java/com/google/domain/registry/util/HttpServletUtils.java create mode 100644 java/com/google/domain/registry/util/Idn.java create mode 100644 java/com/google/domain/registry/util/ImprovedInputStream.java create mode 100644 java/com/google/domain/registry/util/ImprovedOutputStream.java create mode 100644 java/com/google/domain/registry/util/ListNamingUtils.java create mode 100644 java/com/google/domain/registry/util/NetworkUtils.java create mode 100644 java/com/google/domain/registry/util/NonFinalForTesting.java create mode 100644 java/com/google/domain/registry/util/ObjectifyUtils.java create mode 100644 java/com/google/domain/registry/util/PathargMatcher.java create mode 100644 java/com/google/domain/registry/util/PipelineUtils.java create mode 100644 java/com/google/domain/registry/util/PosixTarHeader.java create mode 100644 java/com/google/domain/registry/util/PreconditionsUtils.java create mode 100644 java/com/google/domain/registry/util/PredicateUtils.java create mode 100644 java/com/google/domain/registry/util/RegistrarUtils.java create mode 100644 java/com/google/domain/registry/util/ResourceUtils.java create mode 100644 java/com/google/domain/registry/util/Retrier.java create mode 100644 java/com/google/domain/registry/util/SendEmailService.java create mode 100644 java/com/google/domain/registry/util/SendEmailUtils.java create mode 100644 java/com/google/domain/registry/util/SerializeUtils.java create mode 100644 java/com/google/domain/registry/util/Sleeper.java create mode 100644 java/com/google/domain/registry/util/SqlTemplate.java create mode 100644 java/com/google/domain/registry/util/SystemClock.java create mode 100644 java/com/google/domain/registry/util/SystemSleeper.java create mode 100644 java/com/google/domain/registry/util/TaskEnqueuer.java create mode 100644 java/com/google/domain/registry/util/TeeOutputStream.java create mode 100644 java/com/google/domain/registry/util/TypeUtils.java create mode 100644 java/com/google/domain/registry/util/UrlFetchException.java create mode 100644 java/com/google/domain/registry/util/UrlFetchUtils.java create mode 100644 java/com/google/domain/registry/util/X509Utils.java create mode 100644 java/com/google/domain/registry/util/XmlEnumUtils.java create mode 100644 java/com/google/domain/registry/util/package-info.java create mode 100644 java/com/google/domain/registry/whois/BUILD create mode 100644 java/com/google/domain/registry/whois/DomainLookupCommand.java create mode 100644 java/com/google/domain/registry/whois/DomainOrHostLookupCommand.java create mode 100644 java/com/google/domain/registry/whois/DomainWhoisResponse.java create mode 100644 java/com/google/domain/registry/whois/NameserverLookupByHostCommand.java create mode 100644 java/com/google/domain/registry/whois/NameserverLookupByIpCommand.java create mode 100644 java/com/google/domain/registry/whois/NameserverWhoisResponse.java create mode 100644 java/com/google/domain/registry/whois/RegistrarLookupCommand.java create mode 100644 java/com/google/domain/registry/whois/RegistrarWhoisResponse.java create mode 100644 java/com/google/domain/registry/whois/Whois.java create mode 100644 java/com/google/domain/registry/whois/WhoisCommand.java create mode 100644 java/com/google/domain/registry/whois/WhoisException.java create mode 100644 java/com/google/domain/registry/whois/WhoisHttpServer.java create mode 100644 java/com/google/domain/registry/whois/WhoisModule.java create mode 100644 java/com/google/domain/registry/whois/WhoisReader.java create mode 100644 java/com/google/domain/registry/whois/WhoisResponse.java create mode 100644 java/com/google/domain/registry/whois/WhoisResponseImpl.java create mode 100644 java/com/google/domain/registry/whois/WhoisServer.java create mode 100644 java/com/google/domain/registry/whois/disclaimer.txt create mode 100644 java/com/google/domain/registry/whois/package-info.java create mode 100644 java/com/google/domain/registry/xjc/BUILD create mode 100644 java/com/google/domain/registry/xjc/README.missing-code create mode 100644 java/com/google/domain/registry/xjc/XjcObject.java create mode 100644 java/com/google/domain/registry/xjc/XjcXmlTransformer.java create mode 100644 java/com/google/domain/registry/xjc/bindings.xjb create mode 100644 java/com/google/domain/registry/xjc/generated_files.bzl create mode 100755 java/com/google/domain/registry/xjc/list_generated_files.sh create mode 100755 java/com/google/domain/registry/xjc/make_pkginfo.sh create mode 100644 java/com/google/domain/registry/xjc/package-info.java create mode 100644 java/com/google/domain/registry/xjc/package-info.java.in create mode 100644 java/com/google/domain/registry/xml/BUILD create mode 100644 java/com/google/domain/registry/xml/DateAdapter.java create mode 100644 java/com/google/domain/registry/xml/PeriodAdapter.java create mode 100644 java/com/google/domain/registry/xml/UtcDateTimeAdapter.java create mode 100644 java/com/google/domain/registry/xml/ValidationMode.java create mode 100644 java/com/google/domain/registry/xml/XmlException.java create mode 100644 java/com/google/domain/registry/xml/XmlFragmentMarshaller.java create mode 100644 java/com/google/domain/registry/xml/XmlTransformer.java create mode 100644 java/com/google/domain/registry/xml/package-info.java create mode 100644 java/com/google/domain/registry/xml/xsd/allocate.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/contact.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/domain.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/dsig.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/epp.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/eppcom.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/fee.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/host.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/iirdea.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/launch.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/mark.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/metadata.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-contact.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-domain.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-eppparams.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-header.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-host.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-idn.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-nndn.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-notification.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-policy.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-registrar.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde-report.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rde.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/rgp.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/secdns.xsd create mode 100644 java/com/google/domain/registry/xml/xsd/smd.xsd create mode 100644 java/com/google/gdata/BUILD create mode 100644 java/com/google/testing/builddefs/BUILD create mode 100644 java/com/google/testing/builddefs/GenTestRules.bzl create mode 100644 javascript/closure/BUILD create mode 100644 javascript/template/soy/BUILD create mode 100644 javatests/com/google/domain/registry/backup/BUILD create mode 100644 javatests/com/google/domain/registry/backup/CommitLogCheckpointActionTest.java create mode 100644 javatests/com/google/domain/registry/backup/CommitLogCheckpointStrategyTest.java create mode 100644 javatests/com/google/domain/registry/backup/DeleteOldCommitLogsActionTest.java create mode 100644 javatests/com/google/domain/registry/backup/ExportCommitLogDiffActionTest.java create mode 100644 javatests/com/google/domain/registry/backup/GcsDiffFileListerTest.java create mode 100644 javatests/com/google/domain/registry/backup/RestoreCommitLogsActionTest.java create mode 100644 javatests/com/google/domain/registry/bigquery/BUILD create mode 100644 javatests/com/google/domain/registry/bigquery/BigqueryConnectionTest.java create mode 100644 javatests/com/google/domain/registry/bigquery/BigqueryUtilsTest.java create mode 100644 javatests/com/google/domain/registry/config/BUILD create mode 100644 javatests/com/google/domain/registry/config/RegistryEnvironmentTest.java create mode 100644 javatests/com/google/domain/registry/cron/BUILD create mode 100644 javatests/com/google/domain/registry/cron/CommitLogFanoutActionTest.java create mode 100644 javatests/com/google/domain/registry/cron/TldFanoutActionTest.java create mode 100644 javatests/com/google/domain/registry/dns/BUILD create mode 100644 javatests/com/google/domain/registry/dns/DnsInjectionTest.java create mode 100644 javatests/com/google/domain/registry/dns/DnsQueueTest.java create mode 100644 javatests/com/google/domain/registry/dns/DnsTestComponent.java create mode 100644 javatests/com/google/domain/registry/dns/PublishDnsUpdatesActionTest.java create mode 100644 javatests/com/google/domain/registry/dns/ReadDnsQueueActionTest.java create mode 100644 javatests/com/google/domain/registry/dns/RefreshDnsTest.java create mode 100644 javatests/com/google/domain/registry/dns/WriteDnsTaskTest.java create mode 100644 javatests/com/google/domain/registry/dns/writer/api/BUILD create mode 100644 javatests/com/google/domain/registry/export/BUILD create mode 100644 javatests/com/google/domain/registry/export/BigqueryPollJobActionTest.java create mode 100644 javatests/com/google/domain/registry/export/CheckSnapshotServletTest.java create mode 100644 javatests/com/google/domain/registry/export/DatastoreBackupInfoTest.java create mode 100644 javatests/com/google/domain/registry/export/DatastoreBackupServiceTest.java create mode 100644 javatests/com/google/domain/registry/export/ExportConstantsTest.java create mode 100644 javatests/com/google/domain/registry/export/ExportReservedTermsTaskTest.java create mode 100644 javatests/com/google/domain/registry/export/ExportSnapshotServletTest.java create mode 100644 javatests/com/google/domain/registry/export/ExportUtilsTest.java create mode 100644 javatests/com/google/domain/registry/export/LoadSnapshotServletTest.java create mode 100644 javatests/com/google/domain/registry/export/PublishDetailReportActionTest.java create mode 100644 javatests/com/google/domain/registry/export/SyncGroupMembersTaskTest.java create mode 100644 javatests/com/google/domain/registry/export/UpdateSnapshotViewServletTest.java create mode 100644 javatests/com/google/domain/registry/export/backup_kinds.txt create mode 100644 javatests/com/google/domain/registry/export/sheet/BUILD create mode 100644 javatests/com/google/domain/registry/export/sheet/SheetSynchronizerTest.java create mode 100644 javatests/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTaskTest.java create mode 100644 javatests/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTest.java create mode 100644 javatests/com/google/domain/registry/export/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/export/testdata/domain_allocate.xml create mode 100644 javatests/com/google/domain/registry/export/testdata/domain_create.xml create mode 100644 javatests/com/google/domain/registry/export/testdata/domain_create_sunrise_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/export/testdata/domain_renew.xml create mode 100644 javatests/com/google/domain/registry/flows/BUILD create mode 100644 javatests/com/google/domain/registry/flows/EppConsoleAsAdminServletTest.java create mode 100644 javatests/com/google/domain/registry/flows/EppConsoleServletTest.java create mode 100644 javatests/com/google/domain/registry/flows/EppControllerTest.java create mode 100644 javatests/com/google/domain/registry/flows/EppServletTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/EppServletXmlLoginTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/EppTlsServletTest.java create mode 100644 javatests/com/google/domain/registry/flows/EppToolServletTest.java create mode 100644 javatests/com/google/domain/registry/flows/FlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/ResourceCheckFlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/ResourceFlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/async/DeleteContactResourceActionTest.java create mode 100644 javatests/com/google/domain/registry/flows/async/DeleteEppResourceActionTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/async/DeleteHostResourceActionTest.java create mode 100644 javatests/com/google/domain/registry/flows/async/DnsRefreshForHostRenameActionTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactCheckFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactCreateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactDeleteFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactInfoFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferApproveFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferCancelFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferFlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferQueryFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferRejectFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactTransferRequestFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/ContactUpdateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_check.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_check_50.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_check_51.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_check_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_create_decline_disclosure.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_create_hebrew_int.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_create_hebrew_loc.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_delete_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_info.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_info_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_info_response_linked.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_approve.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_approve_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_approve_with_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_cancel.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_cancel_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_cancel_with_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response_client_approved.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response_client_cancelled.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response_client_rejected.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response_server_approved.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_response_server_cancelled.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_with_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_query_with_roid.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_reject.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_reject_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_reject_with_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_request_no_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_request_response.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_transfer_request_response_15_minutes.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_decline_disclosure.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_hebrew_int.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_hebrew_loc.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_partial_postalinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_prohibited_status.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_remove_client_update_prohibited.xml create mode 100644 javatests/com/google/domain/registry/flows/contact/testdata/contact_update_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/ClaimsCheckFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainAllocateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainApplicationCreateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainApplicationDeleteFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainApplicationInfoFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainApplicationUpdateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainCheckFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainCreateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainDeleteFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainInfoFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainRenewFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainRestoreRequestFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferApproveFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferCancelFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferFlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferQueryFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferRejectFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainTransferRequestFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/DomainUpdateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_13_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_bad_application_roid.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_bad_checksum.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_claims_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_collision.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_dsdata_8_records.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_idn.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_no_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_allocate_smd_id.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_50.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_51.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_anchor.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_avail.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_50.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_51.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_bad_tld.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_multiple_tlds.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_response_multiple_tlds.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_claims_response_none.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_duplicates.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_bad_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_command_phase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_command_subphase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_euro.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_fractional.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_fractional_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_invalid_command.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_multiple_commands.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_multiple_commands_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_multiyear_restore.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_not_in_avail.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_reserved_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_reserved_sunrise_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_fee_unknown_command.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_one_multipart_tld_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_one_tld.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_one_tld_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_one_tld_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_check_template.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_13_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_14_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_anchor_authcode.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_anchor_tenant.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_anchor_wrong_authcode.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_bad_checksum_claim_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_bad_idn_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_bad_validator_id.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_claim_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_code_with_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_dsdata_8_records.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_dsdata_9_records.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_dsdata_no_maxsiglife.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_duplicate_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee_applied.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee_bad_scale.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee_defaults.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee_grace_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_fee_refundable.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_idn_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_allowedinsunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_claim_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_applied.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_bad_scale.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_defaults.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_grace_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_refundable.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_fee_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_months.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_response_claims.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_landrush_two_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_malformed_claim_notice1.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_malformed_claim_notice2.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_metadata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_missing_admin.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_missing_contact_type.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_missing_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_missing_registrant.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_missing_tech.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_months.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_no_hosts_or_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_landrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_landrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_landrush_claims_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_landrush_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrise_claims_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrise_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrush_claims_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_qlp_sunrush_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_sunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_registration_sunrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_reserved_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_claims.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_encoded_signed_mark_name.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_idn_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_response_wildcard.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_bad_encoded_xml.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_bad_encoding.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_code_with_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_duplicate_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_empty_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_encoded_signed_mark_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_encoded_signed_mark_with_whitespace.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_hex_encoding.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_missing_contact_type.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_no_matching_marks.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_and_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_reserved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_reserved_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_uppercase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_with_secdns.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_with_secdns_8_records.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_signed_mark_with_secdns_9_records.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_two_signed_marks.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_with_secdns_maxsiglife.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_without_marks.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrise_wrong_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_13_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_14_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_allowedinsunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_allowedinsunrise_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_bad_checksum_claim_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_bad_idn_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_bad_validator_id.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_claim_notice.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark_certificate_corrupt.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark_corrupt.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark_revoked_cert.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_encoded_signed_mark_signature_corrupt.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_malformed_claim_notice1.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_malformed_claim_notice2.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_sunrush_response_claims.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_uppercase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_with_tld.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_create_wrong_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_application.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_application_landrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_application_sunrush.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_application_wrong_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_metadata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_response_autorenew_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_response_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_response_pending.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_delete_response_pending_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_default_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_delegated_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_bad_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_command_phase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_command_subphase.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_create.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_create_euro.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_create_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_create_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_multiyear_restore.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_renew.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_renew_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_renew_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_renew_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_restore.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_restore_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_restore_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_restore_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_transfer_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_transfer_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_fee_transfer_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_none_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_addperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_autorenewperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_delegated_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_dsdata_addperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_none_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_pendingdelete.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_redemptionperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_renewperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_stackedaddrenewperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_subordinate_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_transferperiod.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_response_unauthorized.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_subordinate_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_all_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_allocated.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_delegated_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_include_marks.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_no_application_id.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_no_marks.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_none_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_response_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_response_no_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_sunrise_response_with_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_with_auth.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_info_with_contact_auth.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_11_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee_applied.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee_bad_scale.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee_defaults.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee_grace_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_fee_refundable.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_missing_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_months.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_response_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_renew_response_missing_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_contact_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_domain_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_net.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_response_autorenew.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_approve_response_net.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_cancel.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_cancel_contact_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_cancel_domain_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_cancel_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_contact_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_domain_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response_client_approved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response_client_cancelled.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response_client_rejected.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response_server_approved.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_query_response_server_cancelled.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_reject.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_reject_contact_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_reject_domain_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_reject_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_10_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_2_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_domain_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee_applied.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee_bad_scale.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee_defaults.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee_grace_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_fee_refundable.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_missing_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_months.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_no_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_response_10_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_response_15_minutes.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_response_2_years.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_response_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_transfer_request_wildcard.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_nameserver.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_non_server_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_remove_same_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_remove_same_host.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_server_hold_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_server_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_add_server_status_non_registrar.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_change_server_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_add.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_add_rem.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_add_rem_same.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_empty.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_rem.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_rem_all.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_rem_all_false.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_dsdata_urgent.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_duplicate_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_max_everything.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_maxsiglife.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_metadata.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_missing_contact_type.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_prohibited_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_registrant_to_tech.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_admin.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_client_hold.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_multiple_contacts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_server_hold.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_server_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_remove_tech.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_response.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee_applied.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee_bad_scale.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee_defaults.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee_grace_period.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_fee_refundable.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_response_fee.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_with_add.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_with_change.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_with_remove.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_restore_request_with_secdns.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_subordinate_hosts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_add_nameserver.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_add_remove_same_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_add_remove_same_host.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_authinfo.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_add.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_add_rem.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_add_rem_same.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_empty.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_rem.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_rem_all.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_rem_all_false.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_dsdata_urgent.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_duplicate_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_maxsiglife.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_missing_contact_type.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_prohibited_status.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_registrant_to_tech.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_remove_admin.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_remove_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_remove_multiple_contacts.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_remove_tech.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_sunrise_wrong_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/domain/testdata/domain_update_wrong_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/host/HostCheckFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/host/HostCreateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/host/HostDeleteFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/host/HostInfoFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/host/HostUpdateFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_check.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_check_50.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_check_51.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_check_response.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_create.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_delete_response.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_info.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_info_response.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_info_response_linked.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_info_response_superordinate_clientid.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update_add_status.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update_name_unchanged.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update_prohibited_status.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update_remove_client_update_prohibited.xml create mode 100644 javatests/com/google/domain/registry/flows/host/testdata/host_update_response.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/PollAckFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/poll/PollRequestFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_contact.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_invalid_eppresource_id.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_invalid_id.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_invalid_string_id.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_missing_id.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_response.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_ack_response_empty.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_autorenew.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_contact_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_contact_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_domain_pending_notification.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_domain_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_empty.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_response_host_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/poll/testdata/poll_with_id.xml create mode 100644 javatests/com/google/domain/registry/flows/session/HelloFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/session/LoginFlowTestCase.java create mode 100644 javatests/com/google/domain/registry/flows/session/LoginFlowViaConsoleTest.java create mode 100644 javatests/com/google/domain/registry/flows/session/LoginFlowViaTlsTest.java create mode 100644 javatests/com/google/domain/registry/flows/session/LogoutFlowTest.java create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/greeting_crr.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/hello.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_invalid_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_invalid_language.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_invalid_newpw.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_invalid_types.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_invalid_version.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_response.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_valid.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/login_valid_missing_types.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/logout.xml create mode 100644 javatests/com/google/domain/registry/flows/session/testdata/logout_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_billion_laughs.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_jd1234.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_local_response_xxe.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_local_xxe.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_remote_response_xxe.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_remote_xxe.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_response_billion_laughs.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_response_jd1234.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_response_sh8013.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_response_template.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_sh8013.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_create_template.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_delete_response_sh8013.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_delete_sh8013.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_info.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_info_from_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_info_not_found.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/contact_transfer_request_response_alternate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_allocate_response_testvalidate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_allocate_response_testvalidate_only_superuser.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_allocate_testvalidate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_check_fee_premium.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_check_fee_premium_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_no_hosts_or_dsdata.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_response_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_response_minna.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_response_secondsite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_secondsite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_sunrise_encoded_mark.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_sunrise_encoded_signed_mark_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_create_testvalidate_invalid_phase.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_delete_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_delete_response_prohibited.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_3_nameservers.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_3_nameservers_pending_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_3_nameservers_transfer_successful.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_ok.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_ok_post_host_update.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_pending_delete.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_pending_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_pending_transfer_autorenew.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_restored_ok.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_transfer_complete.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_fakesite_transfer_period.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_pendingdelete.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_testvalidate_doesnt_exist.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_response_testvalidate_ok.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_info_testvalidate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_query_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_query_response_completed_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_query_response_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_query_response_no_transfer_history.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_request_1_year.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_request_2_years.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_response_1_year.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_transfer_response_2_years.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_update_add_nameserver_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_update_add_nameserver_response_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_update_restore_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_update_restore_request.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/domain_update_restore_request_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/generic_success_action_pending_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/generic_success_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/greeting_crr.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/hello.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create2.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create2_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_create_response_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_ns1.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_ns2.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_ns9000_example.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_fakesite_post_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_fakesite_post_transfer_and_update.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_fakesite_post_transfer_and_update_no_addresses.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_fakesite_post_update.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_ns1.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_ns2.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_info_response_ns9000_example.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_failed_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_ns1_to_fakesite.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_ns1_to_ns2.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_rename_and_remove_addresses.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/host_update_rename_only.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login2_valid.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_response_bad_certificate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_response_missing_certificate.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_response_unauthorized_role.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_response_unauthorized_tld.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_valid.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/login_valid_fee_extension.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/logout.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/logout_response.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/pdt_login.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_ack.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_ack_response_empty.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_response_contact_transfer.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_response_domain_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_response_domain_transfer_server_approve_loser.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/poll_response_domain_transfer_server_approve_winner.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/syntax_error.xml create mode 100644 javatests/com/google/domain/registry/flows/testdata/syntax_error_response.xml create mode 100644 javatests/com/google/domain/registry/groups/BUILD create mode 100644 javatests/com/google/domain/registry/groups/DirectoryGroupsConnectionTest.java create mode 100644 javatests/com/google/domain/registry/mapreduce/BUILD create mode 100644 javatests/com/google/domain/registry/mapreduce/EppResourceInputsTest.java create mode 100644 javatests/com/google/domain/registry/model/BUILD create mode 100644 javatests/com/google/domain/registry/model/CreateAutoTimestampTest.java create mode 100644 javatests/com/google/domain/registry/model/EntityClassesTest.java create mode 100644 javatests/com/google/domain/registry/model/EntityTestCase.java create mode 100644 javatests/com/google/domain/registry/model/EppResourceUtilsTest.java create mode 100644 javatests/com/google/domain/registry/model/ImmutableObjectTest.java create mode 100644 javatests/com/google/domain/registry/model/ModelUtilsTest.java create mode 100644 javatests/com/google/domain/registry/model/ResourceCommandTestCase.java create mode 100644 javatests/com/google/domain/registry/model/RoidSuffixesTest.java create mode 100644 javatests/com/google/domain/registry/model/SchemaVersionTest.java create mode 100644 javatests/com/google/domain/registry/model/UpdateAutoTimestampTest.java create mode 100644 javatests/com/google/domain/registry/model/billing/BillingEventTest.java create mode 100644 javatests/com/google/domain/registry/model/billing/RegistrarBillingEntryTest.java create mode 100644 javatests/com/google/domain/registry/model/billing/RegistrarBillingUtilsTest.java create mode 100644 javatests/com/google/domain/registry/model/billing/RegistrarCreditBalanceTest.java create mode 100644 javatests/com/google/domain/registry/model/billing/RegistrarCreditTest.java create mode 100644 javatests/com/google/domain/registry/model/common/GaeUserIdConverterTest.java create mode 100644 javatests/com/google/domain/registry/model/common/PersistedRangeLongTest.java create mode 100644 javatests/com/google/domain/registry/model/common/TimeOfYearTest.java create mode 100644 javatests/com/google/domain/registry/model/common/TimedTransitionPropertyTest.java create mode 100644 javatests/com/google/domain/registry/model/contact/ContactCommandTest.java create mode 100644 javatests/com/google/domain/registry/model/contact/ContactResourceTest.java create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_check.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_delete.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_info.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_transfer_approve.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_transfer_cancel.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_transfer_reject.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/model/contact/testdata/contact_update.xml create mode 100644 javatests/com/google/domain/registry/model/domain/DomainApplicationTest.java create mode 100644 javatests/com/google/domain/registry/model/domain/DomainCommandTest.java create mode 100644 javatests/com/google/domain/registry/model/domain/DomainResourceTest.java create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_check.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_check_avail.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_check_claims.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_check_fee.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_fee.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_landrush.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_sunrise_code.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_sunrise_code_with_mark.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_sunrise_encoded_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_sunrise_mark.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_create_sunrise_signed_mark.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_info.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_info_fee.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_info_landrush.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_info_sunrise.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_info_sunrise_no_application_id.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_renew.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_renew_fee.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_approve.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_cancel.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_reject.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_transfer_request_fee.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_update.xml create mode 100644 javatests/com/google/domain/registry/model/domain/testdata/domain_update_fee.xml create mode 100644 javatests/com/google/domain/registry/model/eppoutput/ResultTest.java create mode 100644 javatests/com/google/domain/registry/model/export/LogsExportCursorTest.java create mode 100644 javatests/com/google/domain/registry/model/host/HostCommandTest.java create mode 100644 javatests/com/google/domain/registry/model/host/HostResourceTest.java create mode 100644 javatests/com/google/domain/registry/model/host/testdata/host_check.xml create mode 100644 javatests/com/google/domain/registry/model/host/testdata/host_create.xml create mode 100644 javatests/com/google/domain/registry/model/host/testdata/host_delete.xml create mode 100644 javatests/com/google/domain/registry/model/host/testdata/host_info.xml create mode 100644 javatests/com/google/domain/registry/model/host/testdata/host_update.xml create mode 100644 javatests/com/google/domain/registry/model/index/DomainApplicationIndexTest.java create mode 100644 javatests/com/google/domain/registry/model/index/EppResourceIndexTest.java create mode 100644 javatests/com/google/domain/registry/model/index/ForeignKeyIndexTest.java create mode 100644 javatests/com/google/domain/registry/model/mark/MarkContactTest.java create mode 100644 javatests/com/google/domain/registry/model/mark/MarkHolderTest.java create mode 100644 javatests/com/google/domain/registry/model/mark/MarkProtectionTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/CommitLogBucketTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/CommitLogCheckpointTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/CommitLogMutationTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/ObjectifyServiceTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/OfyCommitLogTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/OfyFilterTest.java create mode 100644 javatests/com/google/domain/registry/model/ofy/OfyTest.java create mode 100644 javatests/com/google/domain/registry/model/poll/MessageQueueInfoTest.java create mode 100644 javatests/com/google/domain/registry/model/poll/PollMessageExternalKeyConverterTest.java create mode 100644 javatests/com/google/domain/registry/model/poll/PollMessageTest.java create mode 100644 javatests/com/google/domain/registry/model/rde/RdeNamingUtilsTest.java create mode 100644 javatests/com/google/domain/registry/model/rde/RdeRevisionTest.java create mode 100644 javatests/com/google/domain/registry/model/registrar/RegistrarTest.java create mode 100644 javatests/com/google/domain/registry/model/registry/RegistriesTest.java create mode 100644 javatests/com/google/domain/registry/model/registry/RegistryCursorTest.java create mode 100644 javatests/com/google/domain/registry/model/registry/RegistryTest.java create mode 100644 javatests/com/google/domain/registry/model/registry/label/PremiumListTest.java create mode 100644 javatests/com/google/domain/registry/model/registry/label/ReservedListTest.java create mode 100644 javatests/com/google/domain/registry/model/reporting/HistoryEntryTest.java create mode 100644 javatests/com/google/domain/registry/model/schema.txt create mode 100644 javatests/com/google/domain/registry/model/server/LockTest.java create mode 100644 javatests/com/google/domain/registry/model/smd/IssuerInfoTest.java create mode 100644 javatests/com/google/domain/registry/model/smd/SignedMarkRevocationListTest.java create mode 100644 javatests/com/google/domain/registry/model/testdata/domain_create.xml create mode 100644 javatests/com/google/domain/registry/model/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/model/testdata/domain_update_dsdata_add.xml create mode 100644 javatests/com/google/domain/registry/model/testdata/domain_update_dsdata_rem.xml create mode 100644 javatests/com/google/domain/registry/model/tmch/ClaimsListShardTest.java create mode 100644 javatests/com/google/domain/registry/model/tmch/TmchCrlTest.java create mode 100644 javatests/com/google/domain/registry/model/transfer/TransferDataTest.java create mode 100644 javatests/com/google/domain/registry/model/translators/CommitLogRevisionsTranslatorFactoryTest.java create mode 100644 javatests/com/google/domain/registry/model/translators/StatusValueAdapterTest.java create mode 100644 javatests/com/google/domain/registry/model/translators/testdata/host_update.xml create mode 100644 javatests/com/google/domain/registry/module/backend/BUILD create mode 100644 javatests/com/google/domain/registry/module/backend/BackendServletTest.java create mode 100644 javatests/com/google/domain/registry/module/frontend/BUILD create mode 100644 javatests/com/google/domain/registry/module/frontend/FrontendServletTest.java create mode 100644 javatests/com/google/domain/registry/module/tools/BUILD create mode 100644 javatests/com/google/domain/registry/module/tools/ToolsServletTest.java create mode 100644 javatests/com/google/domain/registry/monitoring/whitebox/BUILD create mode 100644 javatests/com/google/domain/registry/monitoring/whitebox/MetricsTaskServletTest.java create mode 100644 javatests/com/google/domain/registry/monitoring/whitebox/MetricsTest.java create mode 100644 javatests/com/google/domain/registry/rdap/BUILD create mode 100644 javatests/com/google/domain/registry/rdap/RdapActionBaseTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapDomainActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapDomainSearchActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapEntityActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapEntitySearchActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapHelpActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapJsonFormatterTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapNameserverActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapNameserverSearchActionTest.java create mode 100644 javatests/com/google/domain/registry/rdap/RdapSearchPatternTest.java create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_contact.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_domain.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_domain_unicode.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_error_400.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_error_404.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_error_422.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_error_501.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_help_index.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_host.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_host_external.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_host_unicode.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_multiple_contacts.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_multiple_domains.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_multiple_hosts.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdap_registrar.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_admincontact.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_domain_full.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_domain_no_contacts.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_domain_no_nameservers.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_domain_no_registrant.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_error.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_host_both.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_host_ipv4.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_host_ipv6.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_host_no_addresses.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_notice_alternate_link.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_notice_self_link.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_registrant.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_registrant_nobase.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_registrar.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_techcontact.json create mode 100644 javatests/com/google/domain/registry/rdap/testdata/rdapjson_toplevel.json create mode 100644 javatests/com/google/domain/registry/rde/BUILD create mode 100644 javatests/com/google/domain/registry/rde/BouncyCastleTest.java create mode 100644 javatests/com/google/domain/registry/rde/BrdaCopyTaskTest.java create mode 100644 javatests/com/google/domain/registry/rde/ContactResourceToXjcConverterTest.java create mode 100644 javatests/com/google/domain/registry/rde/DomainResourceToXjcConverterTest.java create mode 100644 javatests/com/google/domain/registry/rde/EscrowTaskRunnerTest.java create mode 100644 javatests/com/google/domain/registry/rde/GhostrydeGpgIntegrationTest.java create mode 100644 javatests/com/google/domain/registry/rde/GhostrydeTest.java create mode 100644 javatests/com/google/domain/registry/rde/HostResourceToXjcConverterTest.java create mode 100644 javatests/com/google/domain/registry/rde/PendingDepositCheckerTest.java create mode 100644 javatests/com/google/domain/registry/rde/RdeFixtures.java create mode 100644 javatests/com/google/domain/registry/rde/RdeKeyringModule.java create mode 100644 javatests/com/google/domain/registry/rde/RdeMarshallerTest.java create mode 100644 javatests/com/google/domain/registry/rde/RdeReportTaskTest.java create mode 100644 javatests/com/google/domain/registry/rde/RdeStagingActionTest.java create mode 100644 javatests/com/google/domain/registry/rde/RdeTestData.java create mode 100644 javatests/com/google/domain/registry/rde/RdeTestSuite.java create mode 100644 javatests/com/google/domain/registry/rde/RdeUploadTaskTest.java create mode 100644 javatests/com/google/domain/registry/rde/RegistrarToXjcConverterTest.java create mode 100644 javatests/com/google/domain/registry/rde/RydeGpgIntegrationTest.java create mode 100644 javatests/com/google/domain/registry/rde/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/deposit_full.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/deposit_full_badref.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/iirdea_bad.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/iirdea_good.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/pgp-private-keyring-escrow.asc create mode 100644 javatests/com/google/domain/registry/rde/testdata/pgp-private-keyring-registry.asc create mode 100644 javatests/com/google/domain/registry/rde/testdata/pgp-public-keyring.asc create mode 100644 javatests/com/google/domain/registry/rde/testdata/registry-unittest.id_rsa create mode 100644 javatests/com/google/domain/registry/rde/testdata/registry-unittest.id_rsa.pub create mode 100644 javatests/com/google/domain/registry/rde/testdata/report.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/testMapReduce_withDomain_producesExpectedXml.xml create mode 100644 javatests/com/google/domain/registry/rde/testdata/testMapReduce_withDomain_producesReportXml.xml create mode 100644 javatests/com/google/domain/registry/request/BUILD create mode 100644 javatests/com/google/domain/registry/request/JsonResponseTest.java create mode 100644 javatests/com/google/domain/registry/request/RequestHandlerTest.java create mode 100644 javatests/com/google/domain/registry/request/RequestModuleTest.java create mode 100644 javatests/com/google/domain/registry/request/RequestParametersTest.java create mode 100644 javatests/com/google/domain/registry/request/ResponseImplTest.java create mode 100644 javatests/com/google/domain/registry/request/RouterTest.java create mode 100644 javatests/com/google/domain/registry/security/BUILD create mode 100644 javatests/com/google/domain/registry/security/JsonHttpTest.java create mode 100644 javatests/com/google/domain/registry/security/JsonHttpTestUtils.java create mode 100644 javatests/com/google/domain/registry/security/JsonTransportServletTest.java create mode 100644 javatests/com/google/domain/registry/security/XsrfProtectedServletTest.java create mode 100644 javatests/com/google/domain/registry/security/XsrfTokenManagerTest.java create mode 100644 javatests/com/google/domain/registry/server/BUILD create mode 100644 javatests/com/google/domain/registry/server/Fixture.java create mode 100644 javatests/com/google/domain/registry/server/HealthzServlet.java create mode 100644 javatests/com/google/domain/registry/server/RegistryTestServer.java create mode 100644 javatests/com/google/domain/registry/server/RegistryTestServerMain.java create mode 100644 javatests/com/google/domain/registry/server/Route.java create mode 100644 javatests/com/google/domain/registry/server/ServletWrapperDelegatorServlet.java create mode 100644 javatests/com/google/domain/registry/server/StaticResourceServlet.java create mode 100644 javatests/com/google/domain/registry/server/TestServer.java create mode 100644 javatests/com/google/domain/registry/server/UrlChecker.java create mode 100644 javatests/com/google/domain/registry/storage/drive/BUILD create mode 100644 javatests/com/google/domain/registry/storage/drive/DriveConnectionTest.java create mode 100644 javatests/com/google/domain/registry/testing/AbstractDomainBaseSubject.java create mode 100644 javatests/com/google/domain/registry/testing/AbstractEppResourceSubject.java create mode 100644 javatests/com/google/domain/registry/testing/AppEngineRule.java create mode 100644 javatests/com/google/domain/registry/testing/BUILD create mode 100644 javatests/com/google/domain/registry/testing/BouncyCastleProviderRule.java create mode 100644 javatests/com/google/domain/registry/testing/CertificateSamples.java create mode 100644 javatests/com/google/domain/registry/testing/ContactResourceSubject.java create mode 100644 javatests/com/google/domain/registry/testing/DatastoreHelper.java create mode 100644 javatests/com/google/domain/registry/testing/DomainApplicationSubject.java create mode 100644 javatests/com/google/domain/registry/testing/DomainResourceSubject.java create mode 100644 javatests/com/google/domain/registry/testing/EppLoader.java create mode 100644 javatests/com/google/domain/registry/testing/ExceptionRule.java create mode 100644 javatests/com/google/domain/registry/testing/FailAnswer.java create mode 100644 javatests/com/google/domain/registry/testing/FakeClock.java create mode 100644 javatests/com/google/domain/registry/testing/FakeJsonResponse.java create mode 100644 javatests/com/google/domain/registry/testing/FakeResponse.java create mode 100644 javatests/com/google/domain/registry/testing/FakeServletInputStream.java create mode 100644 javatests/com/google/domain/registry/testing/FakeServletOutputStream.java create mode 100644 javatests/com/google/domain/registry/testing/FakeSleeper.java create mode 100644 javatests/com/google/domain/registry/testing/FakeURLFetchService.java create mode 100644 javatests/com/google/domain/registry/testing/ForwardingURLFetchService.java create mode 100644 javatests/com/google/domain/registry/testing/FullFieldsTestEntityHelper.java create mode 100644 javatests/com/google/domain/registry/testing/GcsTestingUtils.java create mode 100644 javatests/com/google/domain/registry/testing/GenericEppResourceSubject.java create mode 100644 javatests/com/google/domain/registry/testing/GpgSystemCommandRule.java create mode 100644 javatests/com/google/domain/registry/testing/HistoryEntrySubject.java create mode 100644 javatests/com/google/domain/registry/testing/HostResourceSubject.java create mode 100644 javatests/com/google/domain/registry/testing/InjectRule.java create mode 100644 javatests/com/google/domain/registry/testing/IoSpyRule.java create mode 100644 javatests/com/google/domain/registry/testing/Providers.java create mode 100644 javatests/com/google/domain/registry/testing/ReflectiveSubjectFactory.java create mode 100644 javatests/com/google/domain/registry/testing/RegistryConfigRule.java create mode 100644 javatests/com/google/domain/registry/testing/SlurpAnswer.java create mode 100644 javatests/com/google/domain/registry/testing/SystemInfo.java create mode 100644 javatests/com/google/domain/registry/testing/SystemPropertyRule.java create mode 100644 javatests/com/google/domain/registry/testing/TaskQueueHelper.java create mode 100644 javatests/com/google/domain/registry/testing/TestDataHelper.java create mode 100644 javatests/com/google/domain/registry/testing/TestObject.java create mode 100644 javatests/com/google/domain/registry/testing/TestSessionMetadata.java create mode 100644 javatests/com/google/domain/registry/testing/TruthChainer.java create mode 100644 javatests/com/google/domain/registry/testing/UriParameters.java create mode 100644 javatests/com/google/domain/registry/testing/UserInfo.java create mode 100644 javatests/com/google/domain/registry/testing/default_premium_list_testdata.csv create mode 100644 javatests/com/google/domain/registry/testing/logging.properties create mode 100644 javatests/com/google/domain/registry/testing/mapreduce/BUILD create mode 100644 javatests/com/google/domain/registry/testing/mapreduce/MapreduceTestCase.java create mode 100644 javatests/com/google/domain/registry/testing/package-info.java create mode 100644 javatests/com/google/domain/registry/testing/sftp/BUILD create mode 100644 javatests/com/google/domain/registry/testing/sftp/SftpServerRule.java create mode 100644 javatests/com/google/domain/registry/testing/sftp/TestSftpServer.java create mode 100644 javatests/com/google/domain/registry/tldconfig/idn/BUILD create mode 100644 javatests/com/google/domain/registry/tldconfig/idn/IdnLabelValidatorTest.java create mode 100644 javatests/com/google/domain/registry/tldconfig/idn/IdnTableTest.java create mode 100644 javatests/com/google/domain/registry/tmch/BUILD create mode 100644 javatests/com/google/domain/registry/tmch/LordnLogTest.java create mode 100644 javatests/com/google/domain/registry/tmch/LordnTaskTest.java create mode 100644 javatests/com/google/domain/registry/tmch/NordnUploadActionTest.java create mode 100644 javatests/com/google/domain/registry/tmch/NordnVerifyActionTest.java create mode 100644 javatests/com/google/domain/registry/tmch/SmdrlCsvParserTest.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchCertificateAuthorityTest.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchCrlTaskTest.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchDnlTaskTest.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchSmdrlTaskTest.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchTaskTestCase.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchTestData.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchTestSuite.java create mode 100644 javatests/com/google/domain/registry/tmch/TmchXmlSignatureTest.java create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Agent-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Agent-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Agent-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Holder-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Holder-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Holder-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Holder-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Court-Holder-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Agent-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Agent-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Agent-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Holder-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Holder-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Holder-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Holder-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/Trademark-Holder-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Agent-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Agent-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Agent-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Holder-Arabic-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Holder-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Holder-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Holder-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/active/TreatyStatute-Holder-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/dnl-latest.csv create mode 100644 javatests/com/google/domain/registry/tmch/testdata/dnl-latest.sig create mode 100644 javatests/com/google/domain/registry/tmch/testdata/icann-tmch-test-good.crt create mode 100644 javatests/com/google/domain/registry/tmch/testdata/icann-tmch-test-revoked.crt create mode 100644 javatests/com/google/domain/registry/tmch/testdata/invalid/InvalidSignature-Court-Agent-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/invalid/InvalidSignature-Trademark-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/invalid/InvalidSignature-Trademark-Agent-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/invalid/InvalidSignature-TreatyStatute-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/invalid/InvalidSignature-TreatyStatute-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/pubkey create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Agent-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Agent-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Agent-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Agent-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Agent-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Holder-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Holder-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Holder-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Holder-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Court-Holder-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Agent-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Agent-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Agent-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Agent-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Agent-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Holder-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Holder-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Holder-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Holder-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/Trademark-Holder-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Agent-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Agent-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Agent-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Agent-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Agent-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Holder-Arabic-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Holder-Chinese-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Holder-English-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Holder-French-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/smd/TreatyStatute-Holder-Russian-Revoked.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/tmv/TMVRevoked-Court-Agent-French-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/tmv/TMVRevoked-Trademark-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/tmv/TMVRevoked-Trademark-Agent-Russian-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/tmv/TMVRevoked-TreatyStatute-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/revoked/tmv/TMVRevoked-TreatyStatute-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tmch/testdata/smdrl-latest.csv create mode 100644 javatests/com/google/domain/registry/tmch/testdata/smdrl-latest.sig create mode 100644 javatests/com/google/domain/registry/tmch/testdata/tmch_test_smd_revocation_list.csv create mode 100644 javatests/com/google/domain/registry/tools/AllocateDomainCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/BUILD create mode 100644 javatests/com/google/domain/registry/tools/CommandTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/CreateAnchorTenantCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateContactCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateCreditBalanceCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateCreditCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateOrUpdatePremiumListCommandTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/CreateOrUpdateReservedListCommandTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/CreatePremiumListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateRegistrarCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateRegistrarGroupsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateReservedListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/CreateTldCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DeleteCreditCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DeleteDomainCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DeleteEntityCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DeletePremiumListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DeleteReservedListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DomainApplicationInfoCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DomainCheckClaimsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DomainCheckCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/DomainCheckFeeCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/EncryptEscrowDepositCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/EppToolCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/EppToolCommandTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/ExecuteEppCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/FakePasswordGenerator.java create mode 100644 javatests/com/google/domain/registry/tools/GenerateAuctionDataCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GenerateDnsReportCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GenerateEscrowDepositCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetApplicationCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetApplicationIdsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetClaimsListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetContactCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetDomainCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetHostCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetRegistrarCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetResourceByKeyCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GetTldCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GhostrydeCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/GtechToolTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListCursorsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListDomainsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListHostsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListObjectsCommandTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/ListPremiumListsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListRegistrarsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListReservedListsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ListTldsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/MutatingCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/PublishDetailReportCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/RegistrarContactCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/RegistryToolEnvironmentTest.java create mode 100644 javatests/com/google/domain/registry/tools/RegistryToolTest.java create mode 100644 javatests/com/google/domain/registry/tools/SetupOteCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateApplicationStatusCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateClaimsNoticeCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateCursorsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdatePremiumListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateRegistrarCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateReservedListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateServerLocksCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateSmdCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UpdateTldCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/UploadClaimsListCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ValidateEscrowDepositCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/ValidateLoginCredentialsCommandTest.java create mode 100644 javatests/com/google/domain/registry/tools/mapreduce/BUILD create mode 100644 javatests/com/google/domain/registry/tools/mapreduce/DeleteProberDataActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/mapreduce/ResaveAllEppResourcesActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/BUILD create mode 100644 javatests/com/google/domain/registry/tools/params/DateTimeParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/DurationParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/HostAndPortParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/MoneyParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/PathParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/PhoneNumberParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/params/YearMonthParameterTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/BUILD create mode 100644 javatests/com/google/domain/registry/tools/server/CreateGroupsTaskTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/CreatePremiumListActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/DeleteEntityActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/GenerateZoneFilesActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/KillAllCommitLogsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/KillAllEppResourcesActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListActionTestCase.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListDomainsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListHostsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListPremiumListsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListRegistrarsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListReservedListsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/ListTldsActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/UpdatePremiumListActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/javascrap/AnnihilateNonDefaultNamespacesActionTest.java create mode 100644 javatests/com/google/domain/registry/tools/server/testdata/tld.zone create mode 100644 javatests/com/google/domain/registry/tools/testdata/Court-Agent-Chinese-Active.smd create mode 100644 javatests/com/google/domain/registry/tools/testdata/Court-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tools/testdata/InvalidSignature-Trademark-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tools/testdata/TMVRevoked-Trademark-Agent-English-Active.smd create mode 100644 javatests/com/google/domain/registry/tools/testdata/allocate_domain.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/allocate_domain2.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/contact_create_complete.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/contact_create_minimal.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_claims.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_claims_multiple.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_claims_second_tld.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_fee.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_fee_multiple.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_fee_second_tld.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_multiple.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_check_second_tld.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant_fee_premium.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant_fee_standard.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant_multiple_word_reason.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant_no_reason.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_anchor_tenant_password.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_no_hosts_or_dsdata.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_sunrush.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_create_sunrush2.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_delete_by_registrar.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_delete_multiple_word_reason.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_info_landrush.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/domain_info_sunrush.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/example_invalid_premium_terms.csv create mode 100644 javatests/com/google/domain/registry/tools/testdata/example_premium_terms.csv create mode 100644 javatests/com/google/domain/registry/tools/testdata/example_reserved_terms.csv create mode 100644 javatests/com/google/domain/registry/tools/testdata/new-tlds.txt create mode 100644 javatests/com/google/domain/registry/tools/testdata/old-tlds.txt create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_apply_all.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_apply_all_remove_one.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_apply_one.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_multiple_word_reason.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_remove_all.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/update_server_locks_remove_one.xml create mode 100644 javatests/com/google/domain/registry/tools/testdata/xn--q9jyb4c_2010-10-17_full_S1_R0.xml create mode 100644 javatests/com/google/domain/registry/ui/forms/BUILD create mode 100644 javatests/com/google/domain/registry/ui/forms/FormFieldExceptionTest.java create mode 100644 javatests/com/google/domain/registry/ui/forms/FormFieldTest.java create mode 100644 javatests/com/google/domain/registry/ui/forms/FormFieldsTest.java create mode 100644 javatests/com/google/domain/registry/ui/js/BUILD create mode 100644 javatests/com/google/domain/registry/ui/js/admin/BUILD create mode 100644 javatests/com/google/domain/registry/ui/js/admin/registrar_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/admin/registry_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/component_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/BUILD create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/brainframe_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/console_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/console_test_util.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/contact_settings_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/contact_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/domain_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/host_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/payment_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/security_settings_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/registrar/whois_settings_test.js create mode 100644 javatests/com/google/domain/registry/ui/js/testing.js create mode 100644 javatests/com/google/domain/registry/ui/js/xml_test.js create mode 100644 javatests/com/google/domain/registry/ui/server/BUILD create mode 100644 javatests/com/google/domain/registry/ui/server/RegistrarFormFieldsTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/admin/AdminUiServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/admin/BUILD create mode 100644 javatests/com/google/domain/registry/ui/server/admin/RegistrarServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/admin/RegistryServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/api/BUILD create mode 100644 javatests/com/google/domain/registry/ui/server/api/CheckApiServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/BUILD create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/ConsoleUiServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/ContactSettingsTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/RegistrarPaymentActionTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/RegistrarPaymentSetupActionTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/RegistrarServletTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/RegistrarServletTestCase.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/SecuritySettingsTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/SessionUtilsTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/WhoisSettingsTest.java create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/testdata/update_registrar.json create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/testdata/update_registrar_duplicate_contacts.json create mode 100644 javatests/com/google/domain/registry/ui/server/registrar/testdata/update_registrar_email.txt create mode 100644 javatests/com/google/domain/registry/util/BUILD create mode 100644 javatests/com/google/domain/registry/util/CidrAddressBlockTest.java create mode 100644 javatests/com/google/domain/registry/util/CollectionUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/ConcurrentTest.java create mode 100644 javatests/com/google/domain/registry/util/DateTimeUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/DiffUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/DomainNameUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/HexDumperTest.java create mode 100644 javatests/com/google/domain/registry/util/PathargMatcherTest.java create mode 100644 javatests/com/google/domain/registry/util/PosixTarHeaderSystemTest.java create mode 100644 javatests/com/google/domain/registry/util/PosixTarHeaderTest.java create mode 100644 javatests/com/google/domain/registry/util/RetrierTest.java create mode 100644 javatests/com/google/domain/registry/util/SendEmailUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/SerializeUtilsTest.java create mode 100644 javatests/com/google/domain/registry/util/SqlTemplateTest.java create mode 100644 javatests/com/google/domain/registry/util/TaskEnqueuerTest.java create mode 100644 javatests/com/google/domain/registry/util/TeeOutputStreamTest.java create mode 100644 javatests/com/google/domain/registry/util/UrlFetchUtilsTest.java create mode 100644 javatests/com/google/domain/registry/whois/BUILD create mode 100644 javatests/com/google/domain/registry/whois/DomainWhoisResponseTest.java create mode 100644 javatests/com/google/domain/registry/whois/NameserverWhoisResponseTest.java create mode 100644 javatests/com/google/domain/registry/whois/RegistrarWhoisResponseTest.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisHelper.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisHttpServerTest.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisInjectionTest.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisReaderTest.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisServerTest.java create mode 100644 javatests/com/google/domain/registry/whois/WhoisTestComponent.java create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_domain.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_multiple_nameservers.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_nameserver.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_registrar.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_domain.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_domain_not_found.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_idn_punycode.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_idn_utf8.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_ip_not_found.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_malformed_path.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_nameserver.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_nameserver_not_found.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_no_command.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_registrar.txt create mode 100644 javatests/com/google/domain/registry/whois/testdata/whois_server_registrar_not_found.txt create mode 100644 javatests/com/google/domain/registry/xjc/BUILD create mode 100644 javatests/com/google/domain/registry/xjc/XjcObjectTest.java create mode 100644 javatests/com/google/domain/registry/xjc/XmlTestdataTest.java create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_check.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_check_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_create.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_create_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_create_response_offline_review.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_create_response_offline_review_completed.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_delete.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_delete_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_info.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_info_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_transfer_query_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_transfer_request_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_update.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/contact_update_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_check.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_check_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_create.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_create_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_create_response_offline_review.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_create_response_offline_review_completed.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_delete.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_delete_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response_addperiod.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response_pendingdelete.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response_pendingrestore.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response_redemptionperiod.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_response_unauthorized.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_info_with_auth.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_renew.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_renew_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_transfer_query.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_transfer_query_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_transfer_request.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_transfer_request_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_update.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_update_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_update_restore_report.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_update_restore_request.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/domain_update_restore_request_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/greeting.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_check.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_check_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_create.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_create_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_create_response_offline_review.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_create_response_offline_review_complete.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_delete.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_delete_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_info.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_info_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_update.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/host_update_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/invalid_greeting.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/login.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/login_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/logout.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/logout_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/poll.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/poll_ack.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/poll_ack_response.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/poll_response_empty.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/poll_response_mixed.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/rde_deposit_differential.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/rde_deposit_full.xml create mode 100644 javatests/com/google/domain/registry/xjc/testdata/restore_request_response.xml create mode 100644 javatests/com/google/domain/registry/xml/BUILD create mode 100644 javatests/com/google/domain/registry/xml/DateAdapterTest.java create mode 100644 javatests/com/google/domain/registry/xml/UtcDateTimeAdapterTest.java create mode 100644 javatests/com/google/domain/registry/xml/XmlTestUtils.java create mode 100644 third_party/closure/compiler/BUILD create mode 100644 third_party/closure/compiler/closure_js_binary.bzl create mode 100644 third_party/closure/compiler/closure_js_check_test.bzl create mode 100644 third_party/closure/compiler/closure_js_deps.bzl create mode 100644 third_party/closure/compiler/closure_js_library.bzl create mode 100644 third_party/closure/compiler/private/BUILD create mode 100644 third_party/closure/compiler/private/defs.bzl create mode 100644 third_party/closure/library/BUILD create mode 100644 third_party/closure/library/closure_library.BUILD create mode 100644 third_party/closure/stylesheets/BUILD create mode 100644 third_party/closure/stylesheets/closure_css_binary.bzl create mode 100644 third_party/closure/stylesheets/closure_css_library.bzl create mode 100644 third_party/closure/templates/BUILD create mode 100644 third_party/closure/templates/closure_template_java_library.bzl create mode 100644 third_party/closure/templates/closure_template_js_library.bzl create mode 100644 third_party/closure/testing/BUILD create mode 100644 third_party/closure/testing/closure_js_test.bzl create mode 100644 third_party/closure/testing/externs/phantom.js create mode 100644 third_party/closure/testing/phantomjs_jsunit_runner.js create mode 100644 third_party/closure/testing/phantomjs_runner.js create mode 100644 third_party/java/apache_mina/BUILD create mode 100644 third_party/java/apache_sshd/BUILD create mode 100644 third_party/java/appengine/BUILD create mode 100644 third_party/java/appengine_gcs_client/BUILD create mode 100644 third_party/java/appengine_mapreduce2/BUILD create mode 100644 third_party/java/appengine_pipeline/BUILD create mode 100644 third_party/java/auto/BUILD create mode 100644 third_party/java/bouncycastle/BUILD create mode 100644 third_party/java/bouncycastle_bcpg/BUILD create mode 100644 third_party/java/bouncycastle_bcpkix/BUILD create mode 100644 third_party/java/braintree/BUILD create mode 100644 third_party/java/charts4j/BUILD create mode 100644 third_party/java/dagger/BUILD create mode 100644 third_party/java/ftpserver/BUILD create mode 100644 third_party/java/google_java_format/BUILD create mode 100644 third_party/java/hamcrest/BUILD create mode 100644 third_party/java/icu4j/BUILD create mode 100644 third_party/java/javapoet/BUILD create mode 100644 third_party/java/jaxb/BUILD create mode 100644 third_party/java/jcommander/BUILD create mode 100644 third_party/java/jetty/v6_1_22/BUILD create mode 100644 third_party/java/joda_money/BUILD create mode 100644 third_party/java/joda_time/BUILD create mode 100644 third_party/java/jsch/BUILD create mode 100644 third_party/java/jsch/v0_1_44_google/BUILD create mode 100644 third_party/java/jsch/v0_1_44_google/LICENSE create mode 100644 third_party/java/jsch/v0_1_44_google/README.google create mode 100644 third_party/java/jsch/v0_1_44_google/jsch-0.1.44_google-src.jar create mode 100644 third_party/java/jsch/v0_1_44_google/jsch-0.1.44_google.jar create mode 100644 third_party/java/json/BUILD create mode 100644 third_party/java/json_simple/BUILD create mode 100644 third_party/java/jsr305_annotations/BUILD create mode 100644 third_party/java/jsr330_inject/BUILD create mode 100644 third_party/java/junit/BUILD create mode 100644 third_party/java/jzlib/BUILD create mode 100644 third_party/java/mockito/BUILD create mode 100644 third_party/java/objectify/BUILD create mode 100644 third_party/java/objectify/v4_1/BUILD create mode 100644 third_party/java/objectify/v4_1/LICENSE create mode 100644 third_party/java/objectify/v4_1/README.google create mode 100644 third_party/java/objectify/v4_1/objectify-4.1.3-src.jar create mode 100644 third_party/java/objectify/v4_1/objectify-4.1.3.jar create mode 100644 third_party/java/qdox/BUILD create mode 100644 third_party/java/servlet/servlet_api/BUILD create mode 100644 third_party/java/slf4j_api/BUILD create mode 100644 third_party/java/soy/BUILD create mode 100644 third_party/java/truth/BUILD create mode 100644 third_party/javascript/closure/BUILD create mode 100644 third_party/phantomjs/BUILD diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..45dcb048f --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +/bazel-* + +###################################################################### +# Java Ignores + +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +###################################################################### +# Eclipse Ignores + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..2827b7d3f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,27 @@ +Want to contribute? Great! First, read this page (including the small print at the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement] +(https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. We +use Github pull requests for this purpose. + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the +[Software Grant and Corporate Contributor License Agreement] +(https://cla.developers.google.com/about/google-corporate). diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 000000000..d1b6e6a4f --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,23 @@ +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# Names should be added to this file as: +# Name + +Seth Goldman +Corey Goldfeder +Richard Roberto +Justine Tunney +Nick Felt +Ben McIlwain +Brian Mountford +Chris Tingue +Jared Brothers +Pablo Mayrgundter +Daisuke Yabuki +Tim Boring diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 000000000..2ff8ab413 --- /dev/null +++ b/README.md @@ -0,0 +1,190 @@ +# Domain Registry + +Domain Registry is a production service for managing registrations on top-level +domains in a shared namespace. Domain Registry runs on [Google App Engine][gae] +and is written primarily in Java. It achieves in a hundred thousand lines of +code what [Jon Postel][postel] used to do on index cards. + +This is the software that [Google Registry][google-registry] uses to operate +TLDs such as .GOOGLE, .HOW, .SOY, and .みんな. + +### What is a Registry? + +When it comes to internet land, ownership flows down the following hierarchy: + +1. [ICANN][icann] +2. [Registries][registry] (e.g. Google Registry) +3. [Registrars][registrar] (e.g. Google Domains) +4. Registrants (e.g. you) + +A registry is any organization that operates an entire top-level domain. For +example, Verisign controls all the .COM domains and Affilias controls all the +.ORG domains. + +### How Scalable is Domain Registry? + +We successfully verified that Domain Registry is able to perform 1,000 EPP +"domain creates" per second, with 99th percentile latency at ~3 seconds, and +95th percentile latency at ~1 second. Please note that 1,000 was the highest QPS +our load tester allowed. + +In theory, Domain Registry is infinitely scalable. The only limitation is that +each individual EPP resource can only support one write per second, which in +practice, is more like ten. However reads to a single resource are free and +unlimited. + +### How Reliable is Domain Registry? + +Domain Registry achieves its scalability without sacrificing the level of +correctness an engineer would expect from an ACID SQL database. + +Domain Registry is built on top of [Google Cloud Datastore][datastore]. This is +a global NoSQL database that provides an unlimited number of [Paxos][paxos] +entity groups, each of which being able to scale to an unlimited size while +supporting a single local transaction per second. Datastore also supports +distributed transactions that span up to twenty-five entity groups. Transactions +are limited to four minutes and ten megabytes in size. Furthermore, queries and +indexes that span entity groups are always eventually consistent, which means +they could take seconds, and very rarely, days to update. While most online +services find eventual consistency useful, it is not appropriate for a service +conducting financial exchanges. Therefore Domain Registry has been engineered +to employ performance and complexity tradeoffs that allow strong consistency to +be applied throughout the codebase. + +Domain Registry has a commit log system. Commit logs are retained in datastore +for thirty days. They are also streamed to Cloud Storage for backup purposes. +Commit logs are written across one thousand entity group shards, each with a +local timestamp. The commit log system is able to reconstruct a global partial +ordering of transactions, based on these local timestamps. This is necessary in +order to do restores. Each EPP resource entity also stores a map of its past +mutations with 24-hour granularity. This makes it possible to have point-in-time +projection queries with effectively no overhead. + +The Registry Data Escrow (RDE) system is also built with reliability in mind. +It executes on top of App Engine task queues, which can be double-executed and +therefore require operations to be idempotent. RDE isn't idempotent. To work +around this, RDE uses datastore transactions to achieve mutual exclusion and +serialization. We call this the "Locking Rolling Cursor Pattern." One benefit of +this pattern, is that if the escrow service should fall into a failure state for +a few days, or weeks, it will automatically catch up on its work once the +problem is resolved. RDE is also able to perform strongly consistent queries +with snapshot isolation across the entire datastore. It does this by sharding +global indexes into entity groups buckets (which can be queried with strong +consistency) and then rewinding the entities to the desired point in time. + +The Domain Registry codebase is also well tested. The core packages in the +codebase (model, flows, rde, whois, etc.) have 95% test coverage. + + +## Setup + +All you have to do is [install Bazel][bazel-install] and clone this repository +locally. Once that's done, here are some example commands to get you started: + +```sh +# Run all tests +bazel test //java{,tests}/com/google/domain/registry/... + +# Run the registry_tool command +bazel run //java/com/google/domain/registry/tool:registry_tool -- --help + +# Run the Registrar Console on a local development server +bazel run //javatests/com/google/domain/registry/server -- --help +bazel run //javatests/com/google/domain/registry/server +google-chrome http://localhost:8080/registrar +``` + + +## Services + +Domain Registry provides the following IETF standard services. + +### Extensible Provisioning Protocol (EPP) + +[EPP][epp] is the core service of the registry. It's an XML protocol that's used +by registrars to register domains from the registry on behalf of registrants. +Domain Registry implements this service as an App Engine HTTP servlet listening +on the `/_dr/epp` path. Requests are forwarded to this path by a public-facing +proxy listening on port 700. + +To supplement EPP, Domain Registry also provides a public API for performing +domain availability checks. This service listens on the `/check` path. + +#### RFCs + +- [RFC 5730: EPP](http://tools.ietf.org/html/rfc5730) +- [RFC 5731: EPP Domain Mapping](http://tools.ietf.org/html/rfc5731) +- [RFC 5732: EPP Host Mapping](http://tools.ietf.org/html/rfc5732) +- [RFC 5733: EPP Contact Mapping](http://tools.ietf.org/html/rfc5733) +- [RFC 3915: EPP Grace Period Mapping](http://tools.ietf.org/html/rfc3915) +- [RFC 5734: EPP Transport over TCP](http://tools.ietf.org/html/rfc5734) +- [RFC 5910: EPP DNSSEC Mapping](http://tools.ietf.org/html/rfc5910) +- [Draft: EPP Launch Phase Mapping (Proposed)](http://tools.ietf.org/html/draft-tan-epp-launchphase-11) + +### Registry Data Escrow (RDE) + +RDE and BRDA are implemented as a cron mapreduce that takes a strongly +consistent point-in-time snapshot of the registration database, turns it into a +gigantic XML file, and uploads it to an SFTP server run by a third party escrow +provider. This happens nightly with RDE and weekly with BRDA. + +This service exists for ICANN regulatory purposes. ICANN needs to know that, +should a registry business ever implode, that they can quickly migrate their +TLDs to a different company so that they'll continue to operate. + +#### RFCs + +- [Draft: Registry Data Escrow Specification](http://tools.ietf.org/html/draft-arias-noguchi-registry-data-escrow-06) +- [Draft: Domain Name Registration Data (DNRD) Objects Mapping](http://tools.ietf.org/html/draft-arias-noguchi-dnrd-objects-mapping-05) +- [Draft: ICANN Registry Interfaces](http://tools.ietf.org/html/draft-lozano-icann-registry-interfaces-05) + +### Trademark Clearing House (TMCH) + +Domain Registry integrates with ICANN and IBM's MarksDB in order to protect +trademark holders, when new TLDs are being launched. + +#### RFCs + +- [Draft: TMCH Functional Spec](http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08) +- [Draft: Mark and Signed Mark Objects Mapping](https://tools.ietf.org/html/draft-lozano-tmch-smd-02) + +### WHOIS + +[WHOIS][whois] is a simple text-based protocol that allows anyone to look up +information about a domain registrant. Domain Registry implements this as an +internal HTTP endpoint running on `/_dr/whois`. A separate proxy running on port +43 forwards requests to that path. Domain Registry also implements a public HTTP +endpoint that listens on the `/whois` path. + +#### RFCs + +- [RFC 3912: WHOIS Protocol Specification](https://tools.ietf.org/html/rfc3912) +- [RFC 7485: Inventory and Analysis of Registration Objects](http://tools.ietf.org/html/rfc7485) + +### Registration Data Access Protocol (RDAP) + +RDAP is the new standard for WHOIS. It provides much richer functionality, such +as the ability to perform wildcard searches. Domain Registry makes this HTTP +service available under the `/rdap/...` path. + +#### RFCs + +- [RFC 7480: RDAP HTTP Usage](http://tools.ietf.org/html/rfc7480) +- [RFC 7481: RDAP Security Services](http://tools.ietf.org/html/rfc7481) +- [RFC 7482: RDAP Query Format](http://tools.ietf.org/html/rfc7482) +- [RFC 7483: RDAP JSON Responses](http://tools.ietf.org/html/rfc7483) +- [RFC 7484: RDAP Finding the Authoritative Registration Data](http://tools.ietf.org/html/rfc7484) + + +[datastore]: https://cloud.google.com/datastore/docs/concepts/overview +[gae]: https://cloud.google.com/appengine/docs/about-the-standard-environment +[bazel-install]: http://bazel.io/docs/install.html +[epp]: https://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol +[google-registry]: https://www.registry.google/ +[gtld]: https://en.wikipedia.org/wiki/Generic_top-level_domain +[icann]: https://en.wikipedia.org/wiki/ICANN +[paxos]: https://en.wikipedia.org/wiki/Paxos_(computer_science) +[postel]: https://en.wikipedia.org/wiki/Jon_Postel +[registrar]: https://en.wikipedia.org/wiki/Domain_name_registrar +[registry]: https://en.wikipedia.org/wiki/Domain_name_registry +[whois]: https://en.wikipedia.org/wiki/WHOIS diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 000000000..c918d77a5 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,476 @@ +maven_jar( + name = "aopalliance", + artifact = "aopalliance:aopalliance:1.0", + sha1 = "0235ba8b489512805ac13a8f9ea77a1ca5ebe3e8", +) + +maven_jar( + name = "asm", + artifact = "org.ow2.asm:asm:5.0.3", + sha1 = "dcc2193db20e19e1feca8b1240dbbc4e190824fa", +) + +maven_jar( + name = "asm_analysis", + artifact = "org.ow2.asm:asm-analysis:5.0.3", + sha1 = "c7126aded0e8e13fed5f913559a0dd7b770a10f3", +) + +maven_jar( + name = "asm_commons", + artifact = "org.ow2.asm:asm-commons:5.0.3", + sha1 = "a7111830132c7f87d08fe48cb0ca07630f8cb91c", +) + +maven_jar( + name = "asm_util", + artifact = "org.ow2.asm:asm-util:5.0.3", + sha1 = "1512e5571325854b05fb1efce1db75fcced54389", +) + +maven_jar( + name = "args4j", + artifact = "args4j:args4j:2.0.26", + sha1 = "01ebb18ebb3b379a74207d5af4ea7c8338ebd78b", +) + +maven_jar( + name = "appengine_api_sdk", + artifact = "com.google.appengine:appengine-api-1.0-sdk:1.9.30", + sha1 = "239376bdb4d57e2c2f5b61197ad11cb5eeca6b6c", +) + +maven_jar( + name = "appengine_api_labs", + artifact = "com.google.appengine:appengine-api-labs:1.9.30", + sha1 = "843a35d7bf4bdcf56b95174f33b702348d16b5ff", +) + +maven_jar( + name = "appengine_api_stubs", + artifact = "com.google.appengine:appengine-api-stubs:1.9.30", + sha1 = "f04454ac4dcc3ea7c4a2b12eae63c6998829a1f0", +) + +maven_jar( + name = "appengine_gcs_client", + artifact = "com.google.appengine.tools:appengine-gcs-client:0.5", + sha1 = "5357744d5fe0c5e800afeb079fd234a46e7618f7", +) + +maven_jar( + name = "appengine_local_endpoints", + artifact = "com.google.appengine:appengine-local-endpoints:1.9.30", + sha1 = "c89715aa01247b37ada5a95966edfd2ca065d563", +) + +maven_jar( + name = "appengine_mapreduce", + artifact = "com.google.appengine.tools:appengine-mapreduce:0.8.5", + sha1 = "46e0456540a9fe9006c4accb51c4c8d9a45a77ce", +) + +maven_jar( + name = "appengine_pipeline", + artifact = "com.google.appengine.tools:appengine-pipeline:0.2.13", + sha1 = "2019a2c6acdbc8216161970afac96bb147d07c36", +) + +maven_jar( + name = "appengine_remote_api", + artifact = "com.google.appengine:appengine-remote-api:1.9.30", + sha1 = "3c2ed95f2c06a433c14c9a71efb56c3917bfe856", +) + +maven_jar( + name = "appengine_testing", + artifact = "com.google.appengine:appengine-testing:1.9.30", + sha1 = "dd2e1cb866712ce7666a34131cc7a1464d9e4b4d", +) + +maven_jar( + name = "appengine_tools_sdk", + artifact = "com.google.appengine:appengine-tools-sdk:1.9.30", + sha1 = "794bd339c2b628ef8580e887398981acb28f3e72", +) + +maven_jar( + name = "auto_common", + artifact = "com.google.auto:auto-common:0.5", + sha1 = "27185563ca9551183fa5379807c3034c0012c8c4", +) + +maven_jar( + name = "auto_factory", + artifact = "com.google.auto.factory:auto-factory:1.0-beta3", + sha1 = "99b2ffe0e41abbd4cc42bf3836276e7174c4929d", +) + +maven_jar( + name = "auto_service", + artifact = "com.google.auto.service:auto-service:1.0-rc2", + sha1 = "51033a5b8fcf7039159e35b6878f106ccd5fb35f", +) + +maven_jar( + name = "auto_value", + artifact = "com.google.auto.value:auto-value:1.1", + sha1 = "f6951c141ea3e89c0f8b01da16834880a1ebf162", +) + +maven_jar( + name = "bcpg_jdk15on", + artifact = "org.bouncycastle:bcpg-jdk15on:1.52", + sha1 = "ff4665a4b5633ff6894209d5dd10b7e612291858", +) + +maven_jar( + name = "bcprov_jdk15on", + artifact = "org.bouncycastle:bcprov-jdk15on:1.52", + sha1 = "88a941faf9819d371e3174b5ed56a3f3f7d73269", +) + +maven_jar( + name = "bcpkix_jdk15on", + artifact = "org.bouncycastle:bcpkix-jdk15on:1.52", + sha1 = "b8ffac2bbc6626f86909589c8cc63637cc936504", +) + +maven_jar( + name = "braintree_java", + artifact = "com.braintreepayments.gateway:braintree-java:2.54.0", + sha1 = "b9940196feaf692de32b0d37c55ded76fb9b1ba7", +) + +maven_jar( + name = "charts4j", + artifact = "com.googlecode.charts4j:charts4j:1.3", + sha1 = "80dd3b0d5591580c429b0e2529706f6be5bddc0f", +) + +maven_jar( + name = "closure_compiler", + artifact = "com.google.javascript:closure-compiler:v20160208", + sha1 = "5a2f4be6cf41e27ed7119d26cb8f106300d87d91", +) + +new_git_repository( + name = "closure_library", + build_file = "third_party/closure/library/closure_library.BUILD", + remote = "https://github.com/google/closure-library.git", + tag = "20160208", +) + +maven_jar( + name = "closure_stylesheets", + artifact = "com.google.closure-stylesheets:closure-stylesheets:20160212", + sha1 = "f0e8625a2cfe0f501b28f5e6438b836358da8a97", +) + +maven_jar( + name = "dagger", + artifact = "com.google.dagger:dagger:2.0.2", + sha1 = "de8416eda7b2fd7c25836b140c39e1cbf10542f6", +) + +maven_jar( + name = "dagger_compiler", + artifact = "com.google.dagger:dagger-compiler:2.0.2", + sha1 = "1170f75c1ce293f80755bbc9fcd60e0765022bd0", +) + +maven_jar( + name = "dagger_producers", + artifact = "com.google.dagger:dagger-producers:2.0-beta", + sha1 = "80276338d1c2542ebebac542b535d1ecd48a3fd7", +) + +maven_jar( + name = "eclipse_jdt_core", + artifact = "org.eclipse.jdt:org.eclipse.jdt.core:3.10.0", + sha1 = "647e19b28c106a63a14401c0f5956289792adf2f", +) + +maven_jar( + name = "fastutil", + artifact = "it.unimi.dsi:fastutil:6.4.3", + sha1 = "634ae8b497f0326136fd4995618207e48989623b", +) + +maven_jar( + name = "ftpserver_core", + artifact = "org.apache.ftpserver:ftpserver-core:1.0.6", + sha1 = "2ad1570cd6c0d7ea7ca4d3c26a205e02452f5d7d", +) + +maven_jar( + name = "gdata_core", + artifact = "com.google.gdata:core:1.47.1", + sha1 = "52ee0d917c1c3461f6e12079f73ed71bc75f12d4", +) + +maven_jar( + name = "google_api_client", + artifact = "com.google.api-client:google-api-client:1.21.0", + sha1 = "16a6b3c680f3bf7b81bb42790ff5c1b72c5bbedc", +) + +maven_jar( + name = "google_api_client_appengine", + artifact = "com.google.api-client:google-api-client-appengine:1.21.0", + sha1 = "b4246cf952f6c536465bb58727a4037176003602", +) + +maven_jar( + name = "google_api_services_admin_directory", + artifact = "com.google.apis:google-api-services-admin-directory:directory_v1-rev50-1.19.1", + sha1 = "fce75e874bf4e447128d89d0d3a5a594bc713eba", +) + +maven_jar( + name = "google_api_services_bigquery", + artifact = "com.google.apis:google-api-services-bigquery:v2-rev154-1.19.0", + sha1 = "4f1ee62be6b1b7258560ee7808094292798ef718", +) + +maven_jar( + name = "google_api_services_drive", + artifact = "com.google.apis:google-api-services-drive:v2-rev160-1.19.1", + sha1 = "098adf9128428643992ae6fa0878a7f45e7cec7d", +) + +maven_jar( + name = "google_api_services_storage", + artifact = "com.google.apis:google-api-services-storage:v1-rev15-1.19.0", + sha1 = "91f40f13ab4c24ac33d505695433ba842690bf40", +) + +maven_jar( + name = "google_api_services_groupssettings", + artifact = "com.google.apis:google-api-services-groupssettings:v1-rev54-1.19.1", + sha1 = "28a658b76985b151fb80ce0429e04df4e0095b26", +) + +maven_jar( + name = "google_http_client", + artifact = "com.google.http-client:google-http-client:1.21.0", + sha1 = "42631630fe1276d4d6d6397bb07d53a4e4fec278", +) + +maven_jar( + name = "google_http_client_appengine", + artifact = "com.google.http-client:google-http-client-appengine:1.21.0", + sha1 = "7244bd3c110b15066f4288baa61e350d6a14120c", +) + +maven_jar( + name = "google_http_client_jackson2", + artifact = "com.google.http-client:google-http-client-jackson2:1.21.0", + sha1 = "8ce17bdd15fff0fd8cf359757f29e778fc7191ad", +) + +maven_jar( + name = "google_oauth_client", + artifact = "com.google.oauth-client:google-oauth-client:1.21.0", + sha1 = "61ec42bbfc51aafde5eb8b4923c602c5b5965bc2", +) + +maven_jar( + name = "google_oauth_client_appengine", + artifact = "com.google.oauth-client:google-oauth-client-appengine:1.21.0", + sha1 = "c11014f06ade0a418b2028df41b17f3b17d9cb21", +) + +maven_jar( + name = "google_java_format", + artifact = "com.google.googlejavaformat:google-java-format:0.1-alpha", + sha1 = "ea73bf013f9e0b69caff0ebf60800dda66a9fd4a", +) + +maven_jar( + name = "guice", + artifact = "com.google.inject:guice:3.0", + sha1 = "9d84f15fe35e2c716a02979fb62f50a29f38aefa", +) + +maven_jar( + name = "guice_assistedinject", + artifact = "com.google.inject.extensions:guice-assistedinject:3.0", + sha1 = "544449ddb19f088dcde44f055d30a08835a954a7", +) + +maven_jar( + name = "guice_multibindings", + artifact = "com.google.inject.extensions:guice-multibindings:3.0", + sha1 = "5e670615a927571234df68a8b1fe1a16272be555", +) + +maven_jar( + name = "hamcrest_core", + artifact = "org.hamcrest:hamcrest-core:1.3", + sha1 = "42a25dc3219429f0e5d060061f71acb49bf010a0", +) + +maven_jar( + name = "hamcrest_library", + artifact = "org.hamcrest:hamcrest-library:1.3", + sha1 = "4785a3c21320980282f9f33d0d1264a69040538f", +) + +maven_jar( + name = "icu4j", + artifact = "com.ibm.icu:icu4j:56.1", + sha1 = "8dd6671f52165a0419e6de5e1016400875a90fa9", +) + +maven_jar( + name = "jackson_core", + artifact = "com.fasterxml.jackson.core:jackson-core:2.5.1", + sha1 = "e2a00ad1d7e540ec395e9296a34da484c8888d4d", +) + +maven_jar( + name = "jackson_databind", + artifact = "com.fasterxml.jackson.core:jackson-databind:2.5.1", + sha1 = "5e57baebad3898aca8a825adaf2be6fd189442f2", +) + +maven_jar( + name = "javapoet", + artifact = "com.squareup:javapoet:1.5.1", + sha1 = "1d36b86b8fecbe64ea38aea741599720cb07b7d2", +) + +maven_jar( + name = "javawriter", + artifact = "com.squareup:javawriter:2.5.1", + sha1 = "54c87b3d91238e5b58e1a436d4916eee680ec959", +) + +maven_jar( + name = "jaxb_api", + artifact = "javax.xml.bind:jaxb-api:2.2.12", + sha1 = "4c83805595b15acf41d71d49e3add7c0e85baaed", +) + +maven_jar( + name = "jaxb_core", + artifact = "com.sun.xml.bind:jaxb-core:2.2.11", + sha1 = "c3f87d654f8d5943cd08592f3f758856544d279a", +) + +maven_jar( + name = "jaxb_impl", + artifact = "com.sun.xml.bind:jaxb-impl:2.2.11", + sha1 = "a49ce57aee680f9435f49ba6ef427d38c93247a6", +) + +maven_jar( + name = "jaxb_xjc", + artifact = "com.sun.xml.bind:jaxb-xjc:2.2.11", + sha1 = "f099cedb9b245323f906ab9f75adc48cef305cfd", +) + +maven_jar( + name = "jcommander", + artifact = "com.beust:jcommander:1.48", + sha1 = "bfcb96281ea3b59d626704f74bc6d625ff51cbce", +) + +maven_jar( + name = "jetty", + artifact = "org.mortbay.jetty:jetty:6.1.22", + sha1 = "e097b3b684cececf84a35cfdd08e56096a3188da", +) + +maven_jar( + name = "jetty_util", + artifact = "org.mortbay.jetty:jetty-util:6.1.22", + sha1 = "9039d1940a9ae1c91d2b5d7fdfd64bd1924cd447", +) + +maven_jar( + name = "joda_money", + artifact = "org.joda:joda-money:0.10.0", + sha1 = "4056712d2e6db043a38b78c4ee2130c74bae7216", +) + +maven_jar( + name = "json", + artifact = "org.json:json:20090211", + sha1 = "c183aa3a2a6250293808bba12262c8920ce5a51c", +) + +maven_jar( + name = "json_simple", + artifact = "com.googlecode.json-simple:json-simple:1.1.1", + sha1 = "c9ad4a0850ab676c5c64461a05ca524cdfff59f1", +) + +maven_jar( + name = "jzlib", + artifact = "com.jcraft:jzlib:1.1.3", + sha1 = "c01428efa717624f7aabf4df319939dda9646b2d", +) + +maven_jar( + name = "mina_core", + artifact = "org.apache.mina:mina-core:2.0.0", + sha1 = "4ae3550e925c2621eca3ef9fb4de5298d6f91cc4", +) + +# XXX: new_http_archive() doesn't maintain the executable bit. +# https://github.com/bazelbuild/bazel/issues/984 +http_file( + name = "phantomjs", + sha256 = "86dd9a4bf4aee45f1a84c9f61cf1947c1d6dce9b9e8d2a907105da7852460d2f", + url = "https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2", +) + +maven_jar( + name = "protobuf_java", + artifact = "com.google.protobuf:protobuf-java:2.6.1", + sha1 = "d9521f2aecb909835746b7a5facf612af5e890e8", +) + +maven_jar( + name = "qdox", + artifact = "com.thoughtworks.qdox:qdox:1.12.1", + sha1 = "f7122f6ab1f64bdf9f5970b0e89bfb355e036897", +) + +maven_jar( + name = "servlet_api", + artifact = "org.apache.tomcat:servlet-api:6.0.20", + sha1 = "230937c21f1e2da527bf5ebb13f28bab6b2f3849", +) + +maven_jar( + name = "slf4j_api", + artifact = "org.slf4j:slf4j-api:1.7.14", + sha1 = "862a5bc736005d68727d1387844d09d62efdb6cb", +) + +maven_jar( + name = "sshd_core", + artifact = "org.apache.sshd:sshd-core:0.7.0", + sha1 = "ef5d0cae23845dead3fc53ecd61bd990ed42f60f", +) + +maven_jar( + name = "soy", + artifact = "com.google.template:soy:2016-01-12", + sha1 = "adadc37aecf1042de7c9c6a6eb8f34719500ed69", +) + +http_file( + name = "soyutils_usegoog", + sha256 = "fdb0e318949c1af668038df1d85d45353a00ff585f321c86efe91ac2a10cc91f", + url = "https://repo1.maven.org/maven2/com/google/template/soy/2016-01-12/soy-2016-01-12-soyutils_usegoog.js", +) + +maven_jar( + name = "sshd_core", + artifact = "org.apache.sshd:sshd-core:0.7.0", + sha1 = "ef5d0cae23845dead3fc53ecd61bd990ed42f60f", +) diff --git a/apiserving/discoverydata/admin/BUILD b/apiserving/discoverydata/admin/BUILD new file mode 100644 index 000000000..84e7dc256 --- /dev/null +++ b/apiserving/discoverydata/admin/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "admin_directory_v1", + exports = ["@google_api_services_admin_directory//jar"], +) diff --git a/apiserving/discoverydata/bigquery/BUILD b/apiserving/discoverydata/bigquery/BUILD new file mode 100644 index 000000000..d1aad23dc --- /dev/null +++ b/apiserving/discoverydata/bigquery/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "bigqueryv2", + exports = ["@google_api_services_bigquery//jar"], +) diff --git a/apiserving/discoverydata/drive/BUILD b/apiserving/discoverydata/drive/BUILD new file mode 100644 index 000000000..dbd688cda --- /dev/null +++ b/apiserving/discoverydata/drive/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "drive", + exports = ["@google_api_services_drive//jar"], +) diff --git a/apiserving/discoverydata/groupssettings/BUILD b/apiserving/discoverydata/groupssettings/BUILD new file mode 100644 index 000000000..59f244bc3 --- /dev/null +++ b/apiserving/discoverydata/groupssettings/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "groupssettings", + exports = ["@google_api_services_groupssettings//jar"], +) diff --git a/java/com/google/api/client/extensions/appengine/http/BUILD b/java/com/google/api/client/extensions/appengine/http/BUILD new file mode 100644 index 000000000..3a27c77cc --- /dev/null +++ b/java/com/google/api/client/extensions/appengine/http/BUILD @@ -0,0 +1,10 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "http", + exports = [ + "@google_api_client//jar", + "@google_api_client_appengine//jar", + "@google_http_client_appengine//jar", + ], +) diff --git a/java/com/google/api/client/googleapis/auth/oauth2/BUILD b/java/com/google/api/client/googleapis/auth/oauth2/BUILD new file mode 100644 index 000000000..843e56ba0 --- /dev/null +++ b/java/com/google/api/client/googleapis/auth/oauth2/BUILD @@ -0,0 +1,10 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "oauth2", + exports = [ + "@google_api_client//jar", + "@google_http_client//jar", + "@google_oauth_client//jar", + ], +) diff --git a/java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2/BUILD b/java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2/BUILD new file mode 100644 index 000000000..56983e0a4 --- /dev/null +++ b/java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2/BUILD @@ -0,0 +1,10 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "oauth2", + exports = [ + "@google_api_client//jar", + "@google_api_client_appengine//jar", + "@google_oauth_client_appengine//jar", + ], +) diff --git a/java/com/google/api/client/googleapis/json/BUILD b/java/com/google/api/client/googleapis/json/BUILD new file mode 100644 index 000000000..4e25073c6 --- /dev/null +++ b/java/com/google/api/client/googleapis/json/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "json", + exports = ["@google_api_client//jar"], +) diff --git a/java/com/google/api/client/http/BUILD b/java/com/google/api/client/http/BUILD new file mode 100644 index 000000000..b6bf91ac5 --- /dev/null +++ b/java/com/google/api/client/http/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "http", + exports = [ + "@google_api_client//jar", + "@google_http_client//jar", + ], +) diff --git a/java/com/google/api/client/http/javanet/BUILD b/java/com/google/api/client/http/javanet/BUILD new file mode 100644 index 000000000..e02246ba0 --- /dev/null +++ b/java/com/google/api/client/http/javanet/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "javanet", + exports = [ + "@google_api_client//jar", + "@google_http_client//jar", + ], +) diff --git a/java/com/google/api/client/json/BUILD b/java/com/google/api/client/json/BUILD new file mode 100644 index 000000000..d251806a7 --- /dev/null +++ b/java/com/google/api/client/json/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "json", + exports = [ + "@google_api_client//jar", + "@google_http_client//jar", + ], +) diff --git a/java/com/google/api/client/json/jackson2/BUILD b/java/com/google/api/client/json/jackson2/BUILD new file mode 100644 index 000000000..06f93664b --- /dev/null +++ b/java/com/google/api/client/json/jackson2/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "jackson2", + exports = [ + "@google_api_client//jar", + "@google_http_client_jackson2//jar", + ], +) diff --git a/java/com/google/api/client/testing/http/BUILD b/java/com/google/api/client/testing/http/BUILD new file mode 100644 index 000000000..b6bf91ac5 --- /dev/null +++ b/java/com/google/api/client/testing/http/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "http", + exports = [ + "@google_api_client//jar", + "@google_http_client//jar", + ], +) diff --git a/java/com/google/common/annotations/BUILD b/java/com/google/common/annotations/BUILD new file mode 100644 index 000000000..83dc63314 --- /dev/null +++ b/java/com/google/common/annotations/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "annotations", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/base/BUILD b/java/com/google/common/base/BUILD new file mode 100644 index 000000000..ae9983e24 --- /dev/null +++ b/java/com/google/common/base/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "base", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/cache/BUILD b/java/com/google/common/cache/BUILD new file mode 100644 index 000000000..ddd09556d --- /dev/null +++ b/java/com/google/common/cache/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "cache", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/collect/BUILD b/java/com/google/common/collect/BUILD new file mode 100644 index 000000000..9d0aa2c38 --- /dev/null +++ b/java/com/google/common/collect/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "collect", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/escape/BUILD b/java/com/google/common/escape/BUILD new file mode 100644 index 000000000..0d7f637c8 --- /dev/null +++ b/java/com/google/common/escape/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "escape", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/hash/BUILD b/java/com/google/common/hash/BUILD new file mode 100644 index 000000000..ebb0fc3e7 --- /dev/null +++ b/java/com/google/common/hash/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "hash", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/html/BUILD b/java/com/google/common/html/BUILD new file mode 100644 index 000000000..6cb5b22b7 --- /dev/null +++ b/java/com/google/common/html/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "html", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/io/BUILD b/java/com/google/common/io/BUILD new file mode 100644 index 000000000..5ae93fd8e --- /dev/null +++ b/java/com/google/common/io/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "io", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/math/BUILD b/java/com/google/common/math/BUILD new file mode 100644 index 000000000..854080a96 --- /dev/null +++ b/java/com/google/common/math/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "math", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/net/BUILD b/java/com/google/common/net/BUILD new file mode 100644 index 000000000..e3f4da66d --- /dev/null +++ b/java/com/google/common/net/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "net", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/primitives/BUILD b/java/com/google/common/primitives/BUILD new file mode 100644 index 000000000..c85328903 --- /dev/null +++ b/java/com/google/common/primitives/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "primitives", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/reflect/BUILD b/java/com/google/common/reflect/BUILD new file mode 100644 index 000000000..121173712 --- /dev/null +++ b/java/com/google/common/reflect/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "reflect", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/common/testing/BUILD b/java/com/google/common/testing/BUILD new file mode 100644 index 000000000..2864a6647 --- /dev/null +++ b/java/com/google/common/testing/BUILD @@ -0,0 +1,7 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "testing", + testonly = 1, + exports = ["@bazel_tools//third_party:guava-testlib"], +) diff --git a/java/com/google/common/util/concurrent/BUILD b/java/com/google/common/util/concurrent/BUILD new file mode 100644 index 000000000..f4e66ed9d --- /dev/null +++ b/java/com/google/common/util/concurrent/BUILD @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +java_library( + name = "concurrent", + exports = ["@bazel_tools//third_party:guava"], +) diff --git a/java/com/google/domain/registry/BUILD b/java/com/google/domain/registry/BUILD new file mode 100644 index 000000000..5bb3dd2e5 --- /dev/null +++ b/java/com/google/domain/registry/BUILD @@ -0,0 +1,11 @@ +package(default_visibility = ["//visibility:public"]) + + +package_group( + name = "registry_project", + packages = [ + "//java/com/google/domain/registry/...", + "//javatests/com/google/domain/registry/...", + ], +) + diff --git a/java/com/google/domain/registry/backup/BUILD b/java/com/google/domain/registry/backup/BUILD new file mode 100644 index 000000000..38b9955a5 --- /dev/null +++ b/java/com/google/domain/registry/backup/BUILD @@ -0,0 +1,31 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "backup", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//java/com/google/common/primitives", + "//java/com/google/common/util/concurrent", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/cron", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_gcs_client", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/backup/BackupModule.java b/java/com/google/domain/registry/backup/BackupModule.java new file mode 100644 index 000000000..ce99fc83b --- /dev/null +++ b/java/com/google/domain/registry/backup/BackupModule.java @@ -0,0 +1,92 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.appengine.api.ThreadManager.currentRequestThreadFactory; +import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator; +import static com.google.domain.registry.backup.ExportCommitLogDiffAction.LOWER_CHECKPOINT_TIME_PARAM; +import static com.google.domain.registry.backup.ExportCommitLogDiffAction.UPPER_CHECKPOINT_TIME_PARAM; +import static com.google.domain.registry.backup.RestoreCommitLogsAction.FROM_TIME_PARAM; +import static com.google.domain.registry.request.RequestParameters.extractRequiredDatetimeParameter; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; +import static java.util.concurrent.Executors.newFixedThreadPool; + +import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.domain.registry.cron.CommitLogFanoutAction; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import org.joda.time.DateTime; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; +import javax.servlet.http.HttpServletRequest; + +/** + * Dagger module for backup package. + * + * @see "com.google.domain.registry.module.backend.BackendComponent" + */ +@Module +public final class BackupModule { + + /** Dagger qualifier for backups. */ + @Qualifier + @Documented + public static @interface Backups {} + + /** Number of threads in the threaded executor. */ + private static final int NUM_THREADS = 10; + + @Provides + @Parameter("bucket") + static int provideBucket(HttpServletRequest req) { + String param = extractRequiredParameter(req, CommitLogFanoutAction.BUCKET_PARAM); + Integer bucket = Ints.tryParse(param); + if (bucket == null) { + throw new BadRequestException("Bad bucket id"); + } + return bucket; + } + + @Provides + @Parameter(LOWER_CHECKPOINT_TIME_PARAM) + static DateTime provideLowerCheckpointKey(HttpServletRequest req) { + return extractRequiredDatetimeParameter(req, LOWER_CHECKPOINT_TIME_PARAM); + } + + @Provides + @Parameter(UPPER_CHECKPOINT_TIME_PARAM) + static DateTime provideUpperCheckpointKey(HttpServletRequest req) { + return extractRequiredDatetimeParameter(req, UPPER_CHECKPOINT_TIME_PARAM); + } + + @Provides + @Parameter(FROM_TIME_PARAM) + static DateTime provideFromTime(HttpServletRequest req) { + return extractRequiredDatetimeParameter(req, FROM_TIME_PARAM); + } + + @Provides + @Backups + static ListeningExecutorService provideListeningExecutorService() { + return listeningDecorator(newFixedThreadPool(NUM_THREADS, currentRequestThreadFactory())); + } +} diff --git a/java/com/google/domain/registry/backup/BackupUtils.java b/java/com/google/domain/registry/backup/BackupUtils.java new file mode 100644 index 000000000..2802019d5 --- /dev/null +++ b/java/com/google/domain/registry/backup/BackupUtils.java @@ -0,0 +1,75 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.appengine.api.datastore.EntityTranslator; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; +import com.google.storage.onestore.v3.OnestoreEntity.EntityProto; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; + +/** Utilities for working with backups. */ +public class BackupUtils { + + /** Keys for user metadata fields on commit log files in GCS. */ + public static final class GcsMetadataKeys { + + private GcsMetadataKeys() {} + + public static final String NUM_TRANSACTIONS = "num_transactions"; + public static final String LOWER_BOUND_CHECKPOINT = "lower_bound_checkpoint"; + public static final String UPPER_BOUND_CHECKPOINT = "upper_bound_checkpoint"; + } + + /** + * Converts the given {@link ImmutableObject} to a raw datastore entity and write it to an + * {@link OutputStream} in delimited protocol buffer format. + */ + static void serializeEntity(ImmutableObject entity, OutputStream stream) throws IOException { + EntityTranslator.convertToPb(ofy().save().toEntity(entity)).writeDelimitedTo(stream); + } + + /** + * Return an iterator of {@link ImmutableObject} instances deserialized from the given stream. + * + *

This parses out delimited protocol buffers for raw datastore entities and then Ofy-loads + * those as {@link ImmutableObject}. + * + *

The iterator reads from the stream on demand, and as such will fail if the stream is closed. + */ + public static Iterator createDeserializingIterator(final InputStream input) { + return new AbstractIterator() { + @Override + protected ImmutableObject computeNext() { + EntityProto proto = new EntityProto(); + if (proto.parseDelimitedFrom(input)) { // False means end of stream; other errors throw. + return ofy().load().fromEntity(EntityTranslator.createFromPb(proto)); + } + return endOfData(); + }}; + } + + public static ImmutableList deserializeEntities(byte[] bytes) { + return ImmutableList.copyOf(createDeserializingIterator(new ByteArrayInputStream(bytes))); + } +} diff --git a/java/com/google/domain/registry/backup/CommitLogCheckpointAction.java b/java/com/google/domain/registry/backup/CommitLogCheckpointAction.java new file mode 100644 index 000000000..2c6a55228 --- /dev/null +++ b/java/com/google/domain/registry/backup/CommitLogCheckpointAction.java @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.domain.registry.backup.ExportCommitLogDiffAction.LOWER_CHECKPOINT_TIME_PARAM; +import static com.google.domain.registry.backup.ExportCommitLogDiffAction.UPPER_CHECKPOINT_TIME_PARAM; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; +import static com.google.domain.registry.util.FormattingLogger.getLoggerForCallerClass; + +import com.google.domain.registry.model.ofy.CommitLogCheckpoint; +import com.google.domain.registry.model.ofy.CommitLogCheckpointRoot; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.TaskEnqueuer; + +import com.googlecode.objectify.VoidWork; + +import org.joda.time.DateTime; + +import javax.inject.Inject; + +/** + * Action that saves commit log checkpoints to datastore and kicks off a diff export task. + * + *

We separate computing and saving the checkpoint from exporting it because the export to GCS + * is retryable but should not require the computation of a new checkpoint. Saving the checkpoint + * and enqueuing the export task are done transactionally, so any checkpoint that is saved will be + * exported to GCS very soon. + * + *

This action's supported method is GET rather than POST because it gets invoked via cron. + */ +@Action( + path = "/_dr/cron/commitLogCheckpoint", + method = Action.Method.GET, + automaticallyPrintOk = true) +public final class CommitLogCheckpointAction implements Runnable { + + private static final FormattingLogger logger = getLoggerForCallerClass(); + + private static final String QUEUE_NAME = "export-commits"; + + @Inject Clock clock; + @Inject CommitLogCheckpointStrategy strategy; + @Inject TaskEnqueuer taskEnqueuer; + @Inject CommitLogCheckpointAction() {} + + @Override + public void run() { + final CommitLogCheckpoint checkpoint = strategy.computeCheckpoint(); + logger.info("Generated candidate checkpoint for time " + checkpoint.getCheckpointTime()); + ofy().transact(new VoidWork() { + @Override + public void vrun() { + DateTime lastWrittenTime = CommitLogCheckpointRoot.loadRoot().getLastWrittenTime(); + if (isBeforeOrAt(checkpoint.getCheckpointTime(), lastWrittenTime)) { + logger.info("Newer checkpoint already written at time: " + lastWrittenTime); + return; + } + ofy().saveWithoutBackup().entities( + checkpoint, + CommitLogCheckpointRoot.create(checkpoint.getCheckpointTime())); + // Enqueue a diff task between previous and current checkpoints. + taskEnqueuer.enqueue( + getQueue(QUEUE_NAME), + withUrl(ExportCommitLogDiffAction.PATH) + .param(LOWER_CHECKPOINT_TIME_PARAM, lastWrittenTime.toString()) + .param(UPPER_CHECKPOINT_TIME_PARAM, checkpoint.getCheckpointTime().toString())); + }}); + } +} diff --git a/java/com/google/domain/registry/backup/CommitLogCheckpointStrategy.java b/java/com/google/domain/registry/backup/CommitLogCheckpointStrategy.java new file mode 100644 index 000000000..e032e134f --- /dev/null +++ b/java/com/google/domain/registry/backup/CommitLogCheckpointStrategy.java @@ -0,0 +1,180 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static com.google.common.collect.Maps.transformValues; +import static com.google.domain.registry.model.ofy.CommitLogBucket.getBucketKey; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.earliestOf; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.model.ofy.CommitLogCheckpoint; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.Ofy; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; + +import java.util.List; +import java.util.Map.Entry; + +import javax.inject.Inject; + +/** + * Implementation of the procedure for determining point-in-time consistent commit log checkpoint. + * + *

This algorithm examines the recently written commit log data and uses a dual-read approach + * to determine a point-in-time consistent set of checkpoint times for the commit log buckets. By + * "consistent" we mean, generally speaking, that if the datastore were restored by replaying all + * the commit logs up to the checkpoint times of the buckets, the result would be transactionally + * correct; there must be no "holes" where restored state depends on non-restored state. + * + *

The consistency guarantee really has two parts, only one of which is provided by this + * algorithm. The procedure below guarantees only that if the resulting checkpoint includes any + * given commit log, it will also include all the commit logs that were both 1) actually written + * before that commit log "in real life", and 2) have an earlier timestamp than that commit log. + * (These criteria do not necessarily imply each other, due to the lack of a global shared clock.) + * The rest of the guarantee comes from our Ofy customizations, which ensure that any transaction + * that depends on state from a previous transaction does indeed have a later timestamp. + * + *

Procedure description

+ *
+ * {@code
+ * ComputeCheckpoint() -> returns a set consisting of a timestamp c(b_i) for every bucket b_i
+ *
+ * 1) read off the latest commit timestamp t(b_i) for every bucket b_i
+ * 2) iterate over the buckets b_i a second time, and
+ *   a) do a consistent query for the next commit timestamp t'(b_i) where t'(b_i) > t(b_i)
+ *   b) if present, add this timestamp t'(b_i) to a set S
+ * 3) compute a threshold time T* representing a time before all commits in S, as follows:
+ *   a) if S is empty, let T* = +∞ (or the "end of time")
+ *   b) else, let T* = T - Δ, for T = min(S) and some small Δ > 0
+ * 4) return the set given by: min(t(b_i), T*) for all b_i
+ * }
+ * 
+ * + *

Correctness proof of algorithm

+ * + *

{@literal + * As described above, the algorithm is correct as long as it can ensure the following: given a + * commit log X written at time t(X) to bucket b_x, and another commit log Y that was written "in + * real life" before X and for which t(Y) < t(X), then if X is included in the checkpoint, so is Y; + * that is, t(X) <= c(b_x) implies t(Y) <= c(b_y). + * } + * + *

{@literal + * To prove this, first note that we always have c(b_i) <= t(b_i) for every b_i, i.e. every commit + * log included in the checkpoint must have been seen in the first pass. Hence if X was included, + * then X must have been written by the time we started the second pass. But since Y was written + * "in real life" prior to X, we must have seen Y by the second pass too. + * } + * + *

{@literal + * Now assume towards a contradiction that X is indeed included but Y is not, i.e. that we have + * t(X) <= c(b_x) but t(Y) > c(b_y). If Y was seen in the first pass, i.e. t(Y) <= t(b_y), then by + * our assumption c(b_y) < t(Y) <= t(b_y), and therefore c(b_y) != t(b_y). By the definition of + * c(b_y) it must then equal T*, so we have T* < t(Y). However, this is a contradiction since + * t(Y) < t(X) and t(X) <= c(b_x) <= T*. If instead Y was seen in the second pass but not the + * first, t'(b_y) exists and we must have t'(b_y) <= t(Y), but then since T* < T <= t'(b_y) by + * definition, we again reach the contradiction T* < t(Y). + * } + */ +class CommitLogCheckpointStrategy { + + @Inject Ofy ofy; + @Inject Clock clock; + @Inject CommitLogCheckpointStrategy() {} + + /** Compute and return a new CommitLogCheckpoint for the current point in time. */ + public CommitLogCheckpoint computeCheckpoint() { + DateTime checkpointTime = clock.nowUtc(); + ImmutableMap firstPassTimes = readBucketTimestamps(); + DateTime threshold = readNewCommitLogsAndFindThreshold(firstPassTimes); + return CommitLogCheckpoint.create( + checkpointTime, + computeBucketCheckpointTimes(firstPassTimes, threshold)); + } + + /** + * Returns a map from all bucket IDs to their current last written time values, fetched without + * a transaction so with no guarantee of consistency across buckets. + */ + @VisibleForTesting + ImmutableMap readBucketTimestamps() { + // Use a fresh session cache so that we get the latest data from datastore. + return ofy.doWithFreshSessionCache(new Work>() { + @Override + public ImmutableMap run() { + ImmutableMap.Builder results = new ImmutableMap.Builder<>(); + for (CommitLogBucket bucket : CommitLogBucket.loadAllBuckets()) { + results.put(bucket.getBucketNum(), bucket.getLastWrittenTime()); + } + return results.build(); + }}); + } + + /** + * Returns a threshold value defined as the latest timestamp that is before all new commit logs, + * where "new" means having a commit time after the per-bucket timestamp in the given map. + * When no such commit logs exist, the threshold value is set to END_OF_TIME. + */ + @VisibleForTesting + DateTime readNewCommitLogsAndFindThreshold(ImmutableMap bucketTimes) { + DateTime timeBeforeAllNewCommits = END_OF_TIME; + for (Entry entry : bucketTimes.entrySet()) { + Key bucketKey = getBucketKey(entry.getKey()); + DateTime bucketTime = entry.getValue(); + // Add 1 to handle START_OF_TIME since 0 isn't a valid id - filter then uses >= instead of >. + Key keyForFilter = + Key.create(CommitLogManifest.create(bucketKey, bucketTime.plusMillis(1), null)); + List> manifestKeys = + ofy.load() + .type(CommitLogManifest.class) + .ancestor(bucketKey) + .filterKey(">=", keyForFilter) + .limit(1) + .keys() + .list(); + if (!manifestKeys.isEmpty()) { + timeBeforeAllNewCommits = earliestOf( + timeBeforeAllNewCommits, + CommitLogManifest.extractCommitTime(getOnlyElement(manifestKeys)).minusMillis(1)); + } + } + return timeBeforeAllNewCommits; + } + + /** + * Returns the bucket checkpoint times produced by clamping the given set of bucket timestamps to + * at most the given threshold value. + */ + @VisibleForTesting + ImmutableMap computeBucketCheckpointTimes( + ImmutableMap firstPassTimes, + final DateTime threshold) { + return ImmutableMap.copyOf(transformValues(firstPassTimes, new Function() { + @Override + public DateTime apply(DateTime firstPassTime) { + return earliestOf(firstPassTime, threshold); + }})); + } +} diff --git a/java/com/google/domain/registry/backup/DeleteOldCommitLogsAction.java b/java/com/google/domain/registry/backup/DeleteOldCommitLogsAction.java new file mode 100644 index 000000000..229aeeb01 --- /dev/null +++ b/java/com/google/domain/registry/backup/DeleteOldCommitLogsAction.java @@ -0,0 +1,160 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.common.collect.ImmutableList.copyOf; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.transform; +import static com.google.domain.registry.model.ofy.CommitLogBucket.getBucketKey; +import static com.google.domain.registry.request.Action.Method.POST; + +import com.google.common.base.Function; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.CommitLogMutation; +import com.google.domain.registry.model.ofy.Ofy; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.cmd.Loader; +import com.googlecode.objectify.cmd.Query; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.List; + +import javax.inject.Inject; + +/** + * Task that garbage collects old {@link CommitLogManifest} entities. + * + *

Once commit logs have been written to GCS, we don't really need them in datastore anymore, + * except to reconstruct point-in-time snapshots of the database. But that functionality is not + * useful after a certain amount of time, e.g. thirty days. So this task runs periodically to delete + * the old data. + * + *

This task should be invoked in a fanout style for each {@link CommitLogBucket} ID. It then + * queries {@code CommitLogManifest} entities older than the threshold, using an ancestor query + * operating under the assumption under the assumption that the ID is the transaction timestamp in + * milliseconds since the UNIX epoch. It then deletes them inside a transaction, along with their + * associated {@link CommitLogMutation} entities. + * + *

If additional data is leftover, we show a warning at the INFO level, because it's not + * actionable. If anything, it just shows that the system was under high load thirty days ago, and + * therefore serves little use as an early warning to increase the number of buckets. + * + *

Before running, this task will perform an eventually consistent count query outside of a + * transaction to see how much data actually exists to delete. If it's less than a tenth of + * {@link #maxDeletes}, then we don't bother running the task. This is to minimize contention on the + * bucket and avoid wasting resources. + * + *

Dimensioning

+ * + *

This entire operation operates on a single entity group, within a single transaction. Since + * there's a 10mB upper bound on transaction size and a four minute time limit, we can only delete + * so many commit logs at once. So given the above constraints, five hundred would make a safe + * default value for {@code maxDeletes}. See {@linkplain + * com.google.domain.registry.config.ConfigModule#provideCommitLogMaxDeletes() commitLogMaxDeletes} + * for further documentation on this matter. + * + *

Finally, we need to pick an appropriate cron interval time for this task. Since a bucket + * represents a single datastore entity group, it's only guaranteed to have one transaction per + * second. So we just need to divide {@code maxDeletes} by sixty to get an appropriate minute + * interval. Assuming {@code maxDeletes} is five hundred, this rounds up to ten minutes, which we'll + * double, since this task can always catch up in off-peak hours. + * + *

There's little harm in keeping the data around a little longer, since this task is engaged in + * a zero-sum resource struggle with the EPP transactions. Each transaction we perform here, is one + * less transaction that's available to EPP. Furthermore, a well-administered system should have + * enough buckets that we'll never brush up against the 1/s entity group transaction SLA. + */ +@Action(path = "/_dr/task/deleteOldCommitLogs", method = POST, automaticallyPrintOk = true) +public final class DeleteOldCommitLogsAction implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject Clock clock; + @Inject Ofy ofy; + @Inject @Parameter("bucket") int bucketNum; + @Inject @Config("commitLogDatastoreRetention") Duration maxAge; + @Inject @Config("commitLogMaxDeletes") int maxDeletes; + @Inject DeleteOldCommitLogsAction() {} + + @Override + public void run() { + if (!doesEnoughDataExistThatThisTaskIsWorthRunning()) { + return; + } + Integer deleted = ofy.transact(new Work() { + @Override + public Integer run() { + // Load at most maxDeletes manifest keys of commit logs older than the deletion threshold. + List> manifestKeys = + queryManifests(ofy.load()) + .limit(maxDeletes) + .keys() + .list(); + // transform() is lazy so copyOf() ensures all the subqueries happen in parallel, because + // the queries are launched by iterable(), put into a list, and then the list of iterables + // is consumed and concatenated. + ofy.deleteWithoutBackup().keys(concat(copyOf(transform(manifestKeys, + new Function, Iterable>>() { + @Override + public Iterable> apply(Key manifestKey) { + return ofy.load() + .type(CommitLogMutation.class) + .ancestor(manifestKey) + .keys() + .iterable(); // launches the query asynchronously + }})))); + ofy.deleteWithoutBackup().keys(manifestKeys); + return manifestKeys.size(); + }}); + if (deleted == maxDeletes) { + logger.infofmt("Additional old commit logs might exist in bucket %d", bucketNum); + } + } + + /** Returns the point in time at which commit logs older than that point will be deleted. */ + private DateTime getDeletionThreshold() { + return clock.nowUtc().minus(maxAge); + } + + private boolean doesEnoughDataExistThatThisTaskIsWorthRunning() { + int tenth = Math.max(1, maxDeletes / 10); + int count = queryManifests(ofy.loadEventuallyConsistent()) + .limit(tenth) + .count(); + if (0 < count && count < tenth) { + logger.infofmt("Not enough old commit logs to bother running: %d < %d", count, tenth); + } + return count >= tenth; + } + + private Query queryManifests(Loader loader) { + long thresholdMillis = getDeletionThreshold().getMillis(); + Key bucketKey = getBucketKey(bucketNum); + return loader + .type(CommitLogManifest.class) + .ancestor(bucketKey) + .filterKey("<", Key.create(bucketKey, CommitLogManifest.class, thresholdMillis)); + } +} diff --git a/java/com/google/domain/registry/backup/ExportCommitLogDiffAction.java b/java/com/google/domain/registry/backup/ExportCommitLogDiffAction.java new file mode 100644 index 000000000..34577b46d --- /dev/null +++ b/java/com/google/domain/registry/backup/ExportCommitLogDiffAction.java @@ -0,0 +1,219 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Lists.partition; +import static com.google.domain.registry.backup.BackupUtils.GcsMetadataKeys.LOWER_BOUND_CHECKPOINT; +import static com.google.domain.registry.backup.BackupUtils.GcsMetadataKeys.NUM_TRANSACTIONS; +import static com.google.domain.registry.backup.BackupUtils.GcsMetadataKeys.UPPER_BOUND_CHECKPOINT; +import static com.google.domain.registry.backup.BackupUtils.serializeEntity; +import static com.google.domain.registry.model.ofy.CommitLogBucket.getBucketKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; +import static com.google.domain.registry.util.FormattingLogger.getLoggerForCallerClass; +import static java.nio.channels.Channels.newOutputStream; +import static java.util.Arrays.asList; + +import com.google.appengine.tools.cloudstorage.GcsFileOptions; +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.appengine.tools.cloudstorage.GcsService; +import com.google.common.base.Function; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.model.ofy.CommitLogCheckpoint; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.CommitLogMutation; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.Key; + +import org.joda.time.DateTime; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +/** Action that exports the diff between two commit log checkpoints to GCS. */ +@Action( + path = ExportCommitLogDiffAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true) +public final class ExportCommitLogDiffAction implements Runnable { + + private static final FormattingLogger logger = getLoggerForCallerClass(); + + static final String PATH = "/_dr/task/exportCommitLogDiff"; + static final String UPPER_CHECKPOINT_TIME_PARAM = "upperCheckpointTime"; + static final String LOWER_CHECKPOINT_TIME_PARAM = "lowerCheckpointTime"; + + public static final String DIFF_FILE_PREFIX = "commit_diff_until_"; + + @Inject GcsService gcsService; + @Inject @Config("commitLogGcsBucket") String gcsBucket; + @Inject @Config("commitLogDiffExportBatchSize") int batchSize; + @Inject @Parameter(LOWER_CHECKPOINT_TIME_PARAM) DateTime lowerCheckpointTime; + @Inject @Parameter(UPPER_CHECKPOINT_TIME_PARAM) DateTime upperCheckpointTime; + @Inject ExportCommitLogDiffAction() {} + + @Override + public void run() { + checkArgument(isAtOrAfter(lowerCheckpointTime, START_OF_TIME)); + checkArgument(lowerCheckpointTime.isBefore(upperCheckpointTime)); + // Load the boundary checkpoints - lower is exclusive and may not exist (on the first export, + // when lowerCheckpointTime is START_OF_TIME), whereas the upper is inclusive and must exist. + CommitLogCheckpoint lowerCheckpoint = lowerCheckpointTime.isAfter(START_OF_TIME) + ? verifyNotNull(ofy().load().key(CommitLogCheckpoint.createKey(lowerCheckpointTime)).now()) + : null; + CommitLogCheckpoint upperCheckpoint = + verifyNotNull(ofy().load().key(CommitLogCheckpoint.createKey(upperCheckpointTime)).now()); + + // Load the keys of all the manifests to include in this diff. + List> sortedKeys = loadAllDiffKeys(lowerCheckpoint, upperCheckpoint); + logger.infofmt("Found %d manifests to export", sortedKeys.size()); + // Open an output channel to GCS, wrapped in a stream for convenience. + try (OutputStream gcsStream = newOutputStream(gcsService.createOrReplace( + new GcsFilename(gcsBucket, DIFF_FILE_PREFIX + upperCheckpointTime), + new GcsFileOptions.Builder() + .addUserMetadata(LOWER_BOUND_CHECKPOINT, lowerCheckpointTime.toString()) + .addUserMetadata(UPPER_BOUND_CHECKPOINT, upperCheckpointTime.toString()) + .addUserMetadata(NUM_TRANSACTIONS, Integer.toString(sortedKeys.size())) + .build()))) { + // Export the upper checkpoint itself. + serializeEntity(upperCheckpoint, gcsStream); + // If there are no manifests to export, stop early, now that we've written out the file with + // the checkpoint itself (which is needed for restores, even if it's empty). + if (sortedKeys.isEmpty()) { + return; + } + // Export to GCS in chunks, one per fixed batch of commit logs. While processing one batch, + // asynchronously load the entities for the next one. + List>> keyChunks = partition(sortedKeys, batchSize); + // Objectify's map return type is asynchronous. Calling .values() will block until it loads. + Map nextChunkToExport = ofy().load().keys(keyChunks.get(0)); + for (int i = 0; i < keyChunks.size(); i++) { + // Force the async load to finish. + Collection chunkValues = nextChunkToExport.values(); + logger.infofmt("Loaded %d manifests", chunkValues.size()); + // Since there is no hard bound on how much data this might be, take care not to let the + // Objectify session cache fill up and potentially run out of memory. This is the only safe + // point to do this since at this point there is no async load in progress. + ofy().clearSessionCache(); + // Kick off the next async load, which can happen in parallel to the current GCS export. + if (i + 1 < keyChunks.size()) { + nextChunkToExport = ofy().load().keys(keyChunks.get(i + 1)); + } + exportChunk(gcsStream, chunkValues); + logger.infofmt("Exported %d manifests", chunkValues.size()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + logger.infofmt("Exported %d manifests in total", sortedKeys.size()); + } + + /** + * Loads all the diff keys, sorted in a transaction-consistent chronological order. + * + * @param lowerCheckpoint exclusive lower bound on keys in this diff, or null if no lower bound + * @param upperCheckpoint inclusive upper bound on keys in this diff + */ + private ImmutableList> loadAllDiffKeys( + @Nullable final CommitLogCheckpoint lowerCheckpoint, + final CommitLogCheckpoint upperCheckpoint) { + // Fetch the keys (no data) between these checkpoints, and sort by timestamp. This ordering is + // transaction-consistent by virtue of our checkpoint strategy and our customized Ofy; see + // CommitLogCheckpointStrategy for the proof. We break ties by sorting on bucket ID to ensure + // a deterministic order. + return FluentIterable.from(upperCheckpoint.getBucketTimestamps().keySet()) + .transformAndConcat(new Function>>() { + @Override + public Iterable> apply(Integer bucketNum) { + return loadDiffKeysFromBucket(lowerCheckpoint, upperCheckpoint, bucketNum); + }}) + .toSortedList(new Comparator>() { + @Override + public int compare(Key a, Key b) { + // Compare keys by timestamp (which is encoded in the id as millis), then by bucket id. + return ComparisonChain.start() + .compare(a.getId(), b.getId()) + .compare(a.getParent().getId(), b.getParent().getId()) + .result(); + }}); + } + + /** + * Loads the diff keys for one bucket. + * + * @param lowerCheckpoint exclusive lower bound on keys in this diff, or null if no lower bound + * @param upperCheckpoint inclusive upper bound on keys in this diff + * @param bucketNum the bucket to load diff keys from + */ + private Iterable> loadDiffKeysFromBucket( + @Nullable CommitLogCheckpoint lowerCheckpoint, + CommitLogCheckpoint upperCheckpoint, + int bucketNum) { + // If no lower checkpoint exists, use START_OF_TIME as the effective exclusive lower bound. + DateTime lowerCheckpointBucketTime = lowerCheckpoint == null + ? START_OF_TIME + : lowerCheckpoint.getBucketTimestamps().get(bucketNum); + // Since START_OF_TIME=0 is not a valid id in a key, add 1 to both bounds. Then instead of + // loading lowerBound < x <= upperBound, we can load lowerBound <= x < upperBound. + DateTime lowerBound = lowerCheckpointBucketTime.plusMillis(1); + DateTime upperBound = upperCheckpoint.getBucketTimestamps().get(bucketNum).plusMillis(1); + // If the lower and upper bounds are equal, there can't be any results, so skip the query. + if (lowerBound.equals(upperBound)) { + return ImmutableSet.of(); + } + Key bucketKey = getBucketKey(bucketNum); + return ofy().load() + .type(CommitLogManifest.class) + .ancestor(bucketKey) + .filterKey(">=", CommitLogManifest.createKey(bucketKey, lowerBound)) + .filterKey("<", CommitLogManifest.createKey(bucketKey, upperBound)) + .keys(); + } + + /** Writes a chunks-worth of manifests and associated mutations to GCS. */ + private void exportChunk(OutputStream gcsStream, Collection chunk) + throws IOException { + // Kickoff async loads for all the manifests in the chunk. + ImmutableList.Builder> entities = + new ImmutableList.Builder<>(); + for (CommitLogManifest manifest : chunk) { + entities.add(asList(manifest)); + entities.add(ofy().load().type(CommitLogMutation.class).ancestor(manifest)); + } + for (ImmutableObject entity : concat(entities.build())) { + serializeEntity(entity, gcsStream); + } + } +} diff --git a/java/com/google/domain/registry/backup/GcsDiffFileLister.java b/java/com/google/domain/registry/backup/GcsDiffFileLister.java new file mode 100644 index 000000000..8166686e5 --- /dev/null +++ b/java/com/google/domain/registry/backup/GcsDiffFileLister.java @@ -0,0 +1,128 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.backup.BackupUtils.GcsMetadataKeys.LOWER_BOUND_CHECKPOINT; +import static com.google.domain.registry.backup.ExportCommitLogDiffAction.DIFF_FILE_PREFIX; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; +import static com.google.domain.registry.util.DateTimeUtils.latestOf; + +import com.google.appengine.tools.cloudstorage.GcsFileMetadata; +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.appengine.tools.cloudstorage.GcsService; +import com.google.appengine.tools.cloudstorage.ListItem; +import com.google.appengine.tools.cloudstorage.ListOptions; +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.domain.registry.backup.BackupModule.Backups; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.DateTime; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +import javax.inject.Inject; + +/** Utility class to list commit logs diff files stored on GCS. */ +class GcsDiffFileLister { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject GcsService gcsService; + @Inject @Config("commitLogGcsBucket") String gcsBucket; + @Inject @Backups ListeningExecutorService executor; + @Inject GcsDiffFileLister() {} + + List listDiffFiles(DateTime fromTime) { + logger.info("Requested restore from time: " + fromTime); + // List all of the diff files on GCS and build a map from each file's upper checkpoint time + // (extracted from the filename) to its asynchronously-loaded metadata, keeping only files with + // an upper checkpoint time > fromTime. + Map> upperBoundTimesToMetadata = new HashMap<>(); + Iterator listItems; + try { + // TODO(b/23554360): Use a smarter prefixing strategy to speed this up. + listItems = gcsService.list( + gcsBucket, + new ListOptions.Builder().setPrefix(DIFF_FILE_PREFIX).build()); + } catch (IOException e) { + throw new RuntimeException(e); + } + DateTime lastUpperBoundTime = START_OF_TIME; + while (listItems.hasNext()) { + final String filename = listItems.next().getName(); + DateTime upperBoundTime = DateTime.parse(filename.substring(DIFF_FILE_PREFIX.length())); + if (isBeforeOrAt(fromTime, upperBoundTime)) { + upperBoundTimesToMetadata.put(upperBoundTime, executor.submit( + new Callable() { + @Override + public GcsFileMetadata call() throws Exception { + return getMetadata(filename); + }})); + } + lastUpperBoundTime = latestOf(upperBoundTime, lastUpperBoundTime); + } + if (upperBoundTimesToMetadata.isEmpty()) { + logger.info("No files found"); + return ImmutableList.of(); + } + // GCS file listing is eventually consistent, so it's possible that we are missing a file. The + // metadata of a file is sufficient to identify the preceding file, so if we start from the + // last file and work backwards we can verify that we have no holes in our chain (although we + // may be missing files at the end). + ImmutableList.Builder filesBuilder = new ImmutableList.Builder<>(); + logger.info("Restoring until: " + lastUpperBoundTime); + DateTime checkpointTime = lastUpperBoundTime; + while (checkpointTime.isAfter(fromTime)) { + GcsFileMetadata metadata; + if (upperBoundTimesToMetadata.containsKey(checkpointTime)) { + metadata = Futures.getUnchecked(upperBoundTimesToMetadata.get(checkpointTime)); + } else { + String filename = DIFF_FILE_PREFIX + checkpointTime; + logger.info("Patching GCS list; discovered file " + filename); + metadata = getMetadata(filename); + checkState(metadata != null, "Could not read metadata for file %s", filename); + } + filesBuilder.add(metadata); + checkpointTime = getLowerBoundTime(metadata); + } + ImmutableList files = filesBuilder.build().reverse(); + logger.info("Actual restore from time: " + getLowerBoundTime(files.get(0))); + logger.infofmt("Found %d files to restore", files.size()); + return files; + } + + private DateTime getLowerBoundTime(GcsFileMetadata metadata) { + return DateTime.parse(metadata.getOptions().getUserMetadata().get(LOWER_BOUND_CHECKPOINT)); + } + + private GcsFileMetadata getMetadata(String filename) { + try { + return gcsService.getMetadata(new GcsFilename(gcsBucket, filename)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/backup/RestoreCommitLogsAction.java b/java/com/google/domain/registry/backup/RestoreCommitLogsAction.java new file mode 100644 index 000000000..1bfffe346 --- /dev/null +++ b/java/com/google/domain/registry/backup/RestoreCommitLogsAction.java @@ -0,0 +1,207 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.backup; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterators.peekingIterator; +import static com.google.domain.registry.backup.BackupUtils.createDeserializingIterator; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static java.util.Arrays.asList; + +import com.google.appengine.api.datastore.DatastoreService; +import com.google.appengine.api.datastore.Entity; +import com.google.appengine.api.datastore.EntityTranslator; +import com.google.appengine.tools.cloudstorage.GcsFileMetadata; +import com.google.appengine.tools.cloudstorage.GcsService; +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Lists; +import com.google.common.collect.PeekingIterator; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.model.ofy.CommitLogCheckpoint; +import com.google.domain.registry.model.ofy.CommitLogCheckpointRoot; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.CommitLogMutation; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.Retrier; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Result; +import com.googlecode.objectify.util.ResultNow; + +import org.joda.time.DateTime; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.Callable; + +import javax.inject.Inject; + +/** Restore Registry 2 commit logs from GCS to datastore. */ +@Action( + path = RestoreCommitLogsAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true) +public class RestoreCommitLogsAction implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + static final int BLOCK_SIZE = 1024 * 1024; // Buffer 1mb at a time, for no particular reason. + + static final String PATH = "/_dr/task/restoreCommitLogs"; + static final String DRY_RUN_PARAM = "dryRun"; + static final String FROM_TIME_PARAM = "fromTime"; + + @Inject GcsService gcsService; + @Inject @Parameter(DRY_RUN_PARAM) boolean dryRun; + @Inject @Parameter(FROM_TIME_PARAM) DateTime fromTime; + @Inject DatastoreService datastoreService; + @Inject GcsDiffFileLister diffLister; + @Inject Retrier retrier; + @Inject RestoreCommitLogsAction() {} + + @Override + public void run() { + checkArgument( // safety + RegistryEnvironment.get() == RegistryEnvironment.ALPHA + || RegistryEnvironment.get() == RegistryEnvironment.UNITTEST, + "DO NOT RUN ANYWHERE ELSE EXCEPT ALPHA OR TESTS."); + if (dryRun) { + logger.info("Running in dryRun mode"); + } + List diffFiles = diffLister.listDiffFiles(fromTime); + if (diffFiles.isEmpty()) { + logger.info("Nothing to restore"); + return; + } + Map bucketTimestamps = new HashMap<>(); + CommitLogCheckpoint lastCheckpoint = null; + for (GcsFileMetadata metadata : diffFiles) { + logger.info("Restoring: " + metadata.getFilename().getObjectName()); + try (InputStream input = Channels.newInputStream( + gcsService.openPrefetchingReadChannel(metadata.getFilename(), 0, BLOCK_SIZE))) { + PeekingIterator commitLogs = + peekingIterator(createDeserializingIterator(input)); + lastCheckpoint = (CommitLogCheckpoint) commitLogs.next(); + saveOfy(asList(lastCheckpoint)); // Save the checkpoint itself. + while (commitLogs.hasNext()) { + CommitLogManifest manifest = restoreOneTransaction(commitLogs); + bucketTimestamps.put(manifest.getBucketId(), manifest.getCommitTime()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + // Restore the CommitLogCheckpointRoot and CommitLogBuckets. + saveOfy(FluentIterable.from(bucketTimestamps.entrySet()) + .transform(new Function, ImmutableObject> () { + @Override + public ImmutableObject apply(Entry entry) { + return new CommitLogBucket.Builder() + .setBucketNum(entry.getKey()) + .setLastWrittenTime(entry.getValue()) + .build(); + }}) + .append(CommitLogCheckpointRoot.create(lastCheckpoint.getCheckpointTime()))); + } + + /** + * Restore the contents of one transaction to datastore. + * + *

The objects to delete are listed in the {@link CommitLogManifest}, which will be the first + * object in the iterable. The objects to save follow, each as a {@link CommitLogMutation}. We + * restore by deleting the deletes and recreating the saves from their proto form. We also save + * the commit logs themselves back to datastore, so that the commit log system itself is + * transparently restored alongside the data. + * + * @return the manifest, for use in restoring the {@link CommitLogBucket}. + */ + private CommitLogManifest restoreOneTransaction(PeekingIterator commitLogs) { + final CommitLogManifest manifest = (CommitLogManifest) commitLogs.next(); + Result deleteResult = deleteAsync(manifest.getDeletions()); + List entitiesToSave = Lists.newArrayList(ofy().save().toEntity(manifest)); + while (commitLogs.hasNext() && commitLogs.peek() instanceof CommitLogMutation) { + CommitLogMutation mutation = (CommitLogMutation) commitLogs.next(); + entitiesToSave.add(ofy().save().toEntity(mutation)); + entitiesToSave.add(EntityTranslator.createFromPbBytes(mutation.getEntityProtoBytes())); + } + saveRaw(entitiesToSave); + try { + deleteResult.now(); + } catch (Exception e) { + retry(new Runnable() { + @Override + public void run() { + deleteAsync(manifest.getDeletions()).now(); + }}); + } + return manifest; + } + + private void saveRaw(final List entitiesToSave) { + if (dryRun) { + logger.info("Would have saved " + entitiesToSave); + return; + } + retry(new Runnable() { + @Override + public void run() { + datastoreService.put(entitiesToSave); + }}); + } + + private void saveOfy(final Iterable objectsToSave) { + if (dryRun) { + logger.info("Would have saved " + asList(objectsToSave)); + return; + } + retry(new Runnable() { + @Override + public void run() { + ofy().saveWithoutBackup().entities(objectsToSave).now(); + }}); + } + + private Result deleteAsync(Set> keysToDelete) { + if (dryRun) { + logger.info("Would have deleted " + keysToDelete); + } + return dryRun || keysToDelete.isEmpty() + ? new ResultNow(null) + : ofy().deleteWithoutBackup().entities(keysToDelete); + } + + /** Retrier for saves and deletes, since we can't proceed with any failures. */ + private void retry(final Runnable runnable) { + retrier.callWithRetry( + new Callable() { + @Override + public Void call() throws Exception { + runnable.run(); + return null; + }}, + RuntimeException.class); + } +} diff --git a/java/com/google/domain/registry/backup/package-info.java b/java/com/google/domain/registry/backup/package-info.java new file mode 100644 index 000000000..2e6446761 --- /dev/null +++ b/java/com/google/domain/registry/backup/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.backup; diff --git a/java/com/google/domain/registry/bigquery/BUILD b/java/com/google/domain/registry/bigquery/BUILD new file mode 100644 index 000000000..507855cdc --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BUILD @@ -0,0 +1,30 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "bigquery", + srcs = glob(["*.java"]), + deps = [ + "//apiserving/discoverydata/bigquery:bigqueryv2", + "//java/com/google/api/client/extensions/appengine/http", + "//java/com/google/api/client/googleapis/auth/oauth2", + "//java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2", + "//java/com/google/api/client/googleapis/json", + "//java/com/google/api/client/http", + "//java/com/google/api/client/json", + "//java/com/google/api/client/json/jackson2", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/common/util/concurrent", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + ], +) diff --git a/java/com/google/domain/registry/bigquery/BigqueryConnection.java b/java/com/google/domain/registry/bigquery/BigqueryConnection.java new file mode 100644 index 000000000..98e43a79b --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryConnection.java @@ -0,0 +1,775 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.base.Verify.verify; +import static com.google.domain.registry.bigquery.BigqueryUtils.toJobReferenceString; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.client.http.AbstractInputStreamContent; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.model.Dataset; +import com.google.api.services.bigquery.model.DatasetReference; +import com.google.api.services.bigquery.model.ErrorProto; +import com.google.api.services.bigquery.model.GetQueryResultsResponse; +import com.google.api.services.bigquery.model.Job; +import com.google.api.services.bigquery.model.JobConfiguration; +import com.google.api.services.bigquery.model.JobConfigurationExtract; +import com.google.api.services.bigquery.model.JobConfigurationLoad; +import com.google.api.services.bigquery.model.JobConfigurationQuery; +import com.google.api.services.bigquery.model.JobReference; +import com.google.api.services.bigquery.model.JobStatistics; +import com.google.api.services.bigquery.model.JobStatus; +import com.google.api.services.bigquery.model.Table; +import com.google.api.services.bigquery.model.TableCell; +import com.google.api.services.bigquery.model.TableFieldSchema; +import com.google.api.services.bigquery.model.TableReference; +import com.google.api.services.bigquery.model.TableRow; +import com.google.api.services.bigquery.model.ViewDefinition; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableTable; +import com.google.common.io.BaseEncoding; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.domain.registry.bigquery.BigqueryUtils.DestinationFormat; +import com.google.domain.registry.bigquery.BigqueryUtils.SourceFormat; +import com.google.domain.registry.bigquery.BigqueryUtils.TableType; +import com.google.domain.registry.bigquery.BigqueryUtils.WriteDisposition; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.Sleeper; +import com.google.domain.registry.util.SqlTemplate; +import com.google.domain.registry.util.SystemSleeper; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; + +import javax.annotation.Nullable; + +/** Class encapsulating parameters and state for accessing the Bigquery API. */ +public class BigqueryConnection implements AutoCloseable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final Duration MIN_POLL_INTERVAL = Duration.millis(500); + + @NonFinalForTesting + private static Sleeper sleeper = new SystemSleeper(); + + /** Default name of the default dataset to use for requests to the API. */ + public static final String DEFAULT_DATASET_NAME = "testing"; + + /** Default dataset to use for storing temporary tables. */ + private static final String TEMP_DATASET_NAME = "__temp__"; + + /** Default time to live for temporary tables. */ + private static final Duration TEMP_TABLE_TTL = Duration.standardHours(24); + + /** Bigquery client instance wrapped by this class. */ + private Bigquery bigquery; + + /** Executor service for bigquery jobs. */ + private ListeningExecutorService service; + + /** Credential object to use for initializing HTTP requests to the bigquery API. */ + private HttpRequestInitializer credential; + + /** HTTP transport object to use for accessing bigquery API. */ + private HttpTransport httpTransport; + + /** JSON factory object to use for accessing bigquery API. */ + private JsonFactory jsonFactory; + + /** Pseudo-randomness source to use for creating random table names. */ + private Random random = new Random(); + + /** Name of the default dataset to use for inserting tables. */ + private String datasetId = DEFAULT_DATASET_NAME; + + /** Whether to automatically overwrite existing tables and views. */ + private boolean overwrite = false; + + /** Duration to wait between polls for job status. */ + private Duration pollInterval = Duration.millis(1000); + + /** Builder for a {@link BigqueryConnection}, since the latter is immutable once created. */ + public static class Builder { + private BigqueryConnection instance; + + public Builder() { + instance = new BigqueryConnection(); + } + + /** + * The BigqueryConnection takes ownership of this {@link ExecutorService} and will + * shut it down when the BigqueryConnection is closed. + */ + public Builder setExecutorService(ExecutorService executorService) { + instance.service = MoreExecutors.listeningDecorator(executorService); + return this; + } + + public Builder setCredential(GoogleCredential credential) { + instance.credential = checkNotNull(credential); + instance.httpTransport = credential.getTransport(); + instance.jsonFactory = credential.getJsonFactory(); + return this; + } + + public Builder setDatasetId(String datasetId) { + instance.datasetId = checkNotNull(datasetId); + return this; + } + + public Builder setOverwrite(boolean overwrite) { + instance.overwrite = overwrite; + return this; + } + + public Builder setPollInterval(Duration pollInterval) { + checkArgument( + !pollInterval.isShorterThan(MIN_POLL_INTERVAL), + "poll interval must be at least %ldms", MIN_POLL_INTERVAL.getMillis()); + instance.pollInterval = pollInterval; + return this; + } + + public BigqueryConnection build() { + try { + checkNotNull(instance.service, "Must provide executor service"); + return instance; + } finally { + // Clear the internal instance so you can't accidentally mutate it through this builder. + instance = null; + } + } + } + + /** + * Class that wraps a normal Bigquery API Table object to make it immutable from the client side + * and give it additional semantics as a "destination" for load or query jobs, with an overwrite + * flag set by the client upon creation. + *

+ * Additionally provides encapsulation so that clients of BigqueryConnection don't need to take + * any direct dependencies on Bigquery API classes and can instead use DestinationTable. + */ + public static class DestinationTable { + /** The wrapped Bigquery API Table object. */ + private final Table table; + + /** The type of this table. */ + private final TableType type; + + /** The write disposition for jobs writing to this destination table. */ + private final WriteDisposition writeDisposition; + + /** + * A query to package with this table if the type is VIEW; not immutable but also not visible + * to clients. + */ + private String query; + + /** A builder for DestinationTable. */ + public static final class Builder { + private final Table table = new Table(); + private final TableReference tableRef = new TableReference(); + private TableType type = TableType.TABLE; + private WriteDisposition writeDisposition = WriteDisposition.WRITE_EMPTY; + + public Builder datasetId(String datasetId) { + tableRef.setDatasetId(datasetId); + return this; + } + + public Builder name(String name) { + tableRef.setTableId(name); + return this; + } + + public Builder description(String description) { + table.setDescription(description); + return this; + } + + public Builder type(TableType type) { + this.type = type; + return this; + } + + public Builder timeToLive(Duration duration) { + this.table.setExpirationTime(new DateTime(UTC).plus(duration).getMillis()); + return this; + } + + public Builder overwrite(boolean overwrite) { + if (overwrite) { + this.writeDisposition = WriteDisposition.WRITE_TRUNCATE; + } + return this; + } + + public Builder append(boolean append) { + if (append) { + this.writeDisposition = WriteDisposition.WRITE_APPEND; + } + return this; + } + + public DestinationTable build() { + tableRef.setProjectId(getEnvironmentProjectId()); + table.setTableReference(tableRef); + checkState(!isNullOrEmpty(table.getTableReference().getDatasetId())); + checkState(!isNullOrEmpty(table.getTableReference().getTableId())); + return new DestinationTable(this); + } + } + + /** Constructs a new DestinationTable from its Builder. */ + private DestinationTable(Builder b) { + table = b.table.clone(); + type = b.type; + writeDisposition = b.writeDisposition; + } + + /** + * Stores the provided query with this DestinationTable and returns it; used for packaging + * a query along with the DestinationTable before sending it to the table update logic. + */ + private DestinationTable withQuery(String query) { + checkState(type == TableType.VIEW); + this.query = query; + return this; + } + + /** Returns a new copy of the Bigquery API Table object wrapped by this DestinationTable. */ + private Table getTable() { + Table tableCopy = table.clone(); + if (type == TableType.VIEW) { + tableCopy.setView(new ViewDefinition().setQuery(query)); + } + return tableCopy; + } + + /** Returns the write disposition that should be used for jobs writing to this table. */ + private WriteDisposition getWriteDisposition() { + return writeDisposition; + } + + /** Returns a new copy of the TableReference for the Table wrapped by this DestinationTable. */ + private TableReference getTableReference() { + return table.getTableReference().clone(); + } + + /** Returns a string representation of the TableReference for the wrapped table. */ + public String getStringReference() { + return tableReferenceToString(table.getTableReference()); + } + + /** Returns a string representation of the given TableReference. */ + private static String tableReferenceToString(TableReference tableRef) { + return String.format( + "%s:%s.%s", + tableRef.getProjectId(), + tableRef.getDatasetId(), + tableRef.getTableId()); + } + } + + /** + * Initializes the BigqueryConnection object by setting up the API client and creating the + * default dataset if it doesn't exist. + */ + public BigqueryConnection initialize() throws Exception { + bigquery = new Bigquery.Builder(httpTransport, jsonFactory, credential) + .setApplicationName(getClass().getSimpleName()) + .build(); + createDatasetIfNeeded(datasetId); + createDatasetIfNeeded(TEMP_DATASET_NAME); + return this; + } + + /** + * Closes the BigqueryConnection object by shutting down the executor service. Clients + * should only call this after all ListenableFutures obtained from BigqueryConnection methods + * have resolved; this method does not block on their completion. + */ + @Override + public void close() { + service.shutdown(); + } + + /** Returns a partially built DestinationTable with the default dataset and overwrite behavior. */ + public DestinationTable.Builder buildDestinationTable(String tableName) { + return new DestinationTable.Builder() + .datasetId(datasetId) + .type(TableType.TABLE) + .name(tableName) + .overwrite(overwrite); + } + + /** + * Returns a partially built DestinationTable with a randomly generated name under the default + * temporary table dataset, with the default TTL and overwrite behavior. + */ + public DestinationTable.Builder buildTemporaryTable() { + return new DestinationTable.Builder() + .datasetId(TEMP_DATASET_NAME) + .type(TableType.TABLE) + .name(getRandomTableName()) + .timeToLive(TEMP_TABLE_TTL) + .overwrite(overwrite); + } + + /** Returns a random table name consisting only of the chars {@code [a-v0-9_]}. */ + private String getRandomTableName() { + byte[] randBytes = new byte[8]; // 64 bits of randomness ought to be plenty. + random.nextBytes(randBytes); + return "_" + BaseEncoding.base32Hex().lowerCase().omitPadding().encode(randBytes); + } + + /** + * A function that updates the specified Bigquery table to reflect the metadata from the input + * DestinationTable, passing the same DestinationTable through as the output. If the specified + * table does not already exist, it will be inserted into the dataset. + *

+ * Clients can call this function directly to update a table on demand, or can pass it to + * Futures.transform() to update a table produced as the asynchronous result of a load or query + * job (e.g. to add a description to it). + */ + private class UpdateTableFunction implements Function { + @Override + public DestinationTable apply(final DestinationTable destinationTable) { + Table table = destinationTable.getTable(); + TableReference ref = table.getTableReference(); + try { + if (checkTableExists(ref.getDatasetId(), ref.getTableId())) { + bigquery.tables() + .update(ref.getProjectId(), ref.getDatasetId(), ref.getTableId(), table) + .execute(); + } else { + bigquery.tables() + .insert(ref.getProjectId(), ref.getDatasetId(), table) + .execute(); + } + return destinationTable; + } catch (IOException e) { + throw BigqueryJobFailureException.create(e); + } + } + } + + /** + * Starts an asynchronous load job to populate the specified destination table with the given + * source URIs and source format. Returns a ListenableFuture that holds the same destination + * table object on success. + */ + public ListenableFuture load( + DestinationTable dest, + SourceFormat sourceFormat, + Iterable sourceUris) throws Exception { + Job job = new Job() + .setConfiguration(new JobConfiguration() + .setLoad(new JobConfigurationLoad() + .setWriteDisposition(dest.getWriteDisposition().toString()) + .setSourceFormat(sourceFormat.toString()) + .setSourceUris(ImmutableList.copyOf(sourceUris)) + .setDestinationTable(dest.getTableReference()))); + return Futures.transform(runJobToCompletion(job, dest), new UpdateTableFunction()); + } + + /** + * Starts an asynchronous query job to populate the specified destination table with the results + * of the specified query, or if the table is a view, to update the view to reflect that query. + * Returns a ListenableFuture that holds the same destination table object on success. + */ + public ListenableFuture query( + String querySql, + DestinationTable dest) { + if (dest.type == TableType.VIEW) { + // Use Futures.transform() rather than calling apply() directly so that any exceptions thrown + // by calling UpdateTableFunction will be propagated on the get() call, not from here. + return Futures.transform( + Futures.immediateFuture(dest.withQuery(querySql)), new UpdateTableFunction()); + } else { + Job job = new Job() + .setConfiguration(new JobConfiguration() + .setQuery(new JobConfigurationQuery() + .setQuery(querySql) + .setDefaultDataset(getDataset()) + .setWriteDisposition(dest.getWriteDisposition().toString()) + .setDestinationTable(dest.getTableReference()))); + return Futures.transform(runJobToCompletion(job, dest), new UpdateTableFunction()); + } + } + + /** + * Starts an asynchronous query job to dump the results of the specified query into a local + * ImmutableTable object, row-keyed by the row number (indexed from 1), column-keyed by the + * TableFieldSchema for that column, and with the value object as the cell value. Note that null + * values will not actually be null, but they can be checked for using Data.isNull(). + *

+ * Returns a ListenableFuture that holds the ImmutableTable on success. + */ + public ListenableFuture> + queryToLocalTable(String querySql) throws Exception { + Job job = new Job() + .setConfiguration(new JobConfiguration() + .setQuery(new JobConfigurationQuery() + .setQuery(querySql) + .setDefaultDataset(getDataset()))); + return Futures.transform( + runJobToCompletion(job), + new Function>() { + @Override + public ImmutableTable apply(Job job) { + return getQueryResults(job); + }}); + } + + /** + * Returns the query results for the given job as an ImmutableTable, row-keyed by row number + * (indexed from 1), column-keyed by the TableFieldSchema for that field, and with the value + * object as the cell value. Note that null values will not actually be null (since we're using + * ImmutableTable) but they can be checked for using Data.isNull(). + *

+ * This table is fully materialized in memory (not lazily loaded), so it should not be used with + * queries expected to return large results. + */ + private ImmutableTable getQueryResults(Job job) { + try { + ImmutableTable.Builder builder = + new ImmutableTable.Builder<>(); + String pageToken = null; + int rowNumber = 1; + while (true) { + GetQueryResultsResponse queryResults = bigquery.jobs() + .getQueryResults(getProjectId(), job.getJobReference().getJobId()) + .setPageToken(pageToken) + .execute(); + // If the job isn't complete yet, retry; getQueryResults() waits for up to 10 seconds on + // each invocation so this will effectively poll for completion. + if (queryResults.getJobComplete()) { + List schemaFields = queryResults.getSchema().getFields(); + for (TableRow row : queryResults.getRows()) { + Iterator fieldIterator = schemaFields.iterator(); + Iterator cellIterator = row.getF().iterator(); + while (fieldIterator.hasNext() && cellIterator.hasNext()) { + builder.put(rowNumber, fieldIterator.next(), cellIterator.next().getV()); + } + rowNumber++; + } + pageToken = queryResults.getPageToken(); + if (pageToken == null) { + break; + } + } + } + return builder.build(); + } catch (IOException e) { + throw BigqueryJobFailureException.create(e); + } + } + + /** + * Starts an asynchronous job to extract the specified source table and output it to the + * given GCS filepath in the specified destination format, optionally printing headers. + * Returns a ListenableFuture that holds the destination GCS URI on success. + */ + private ListenableFuture extractTable( + DestinationTable sourceTable, + String destinationUri, + DestinationFormat destinationFormat, + boolean printHeader) { + checkArgument(sourceTable.type == TableType.TABLE); + Job job = new Job() + .setConfiguration(new JobConfiguration() + .setExtract(new JobConfigurationExtract() + .setSourceTable(sourceTable.getTableReference()) + .setDestinationFormat(destinationFormat.toString()) + .setDestinationUris(ImmutableList.of(destinationUri)) + .setPrintHeader(printHeader))); + return runJobToCompletion(job, destinationUri); + } + + /** + * Starts an asynchronous job to extract the specified source table or view and output it to the + * given GCS filepath in the specified destination format, optionally printing headers. + * Returns a ListenableFuture that holds the destination GCS URI on success. + */ + public ListenableFuture extract( + DestinationTable sourceTable, + String destinationUri, + DestinationFormat destinationFormat, + boolean printHeader) { + if (sourceTable.type == TableType.TABLE) { + return extractTable(sourceTable, destinationUri, destinationFormat, printHeader); + } else { + // We can't extract directly from a view, so instead extract from a query dumping that view. + return extractQuery( + SqlTemplate + .create("SELECT * FROM [%DATASET%.%TABLE%]") + .put("DATASET", sourceTable.getTableReference().getDatasetId()) + .put("TABLE", sourceTable.getTableReference().getTableId()) + .build(), + destinationUri, + destinationFormat, + printHeader); + } + } + + /** + * Starts an asynchronous job to run the provided query, store the results in a temporary table, + * and then extract the contents of that table to the given GCS filepath in the specified + * destination format, optionally printing headers. + *

+ * Returns a ListenableFuture that holds the destination GCS URI on success. + */ + public ListenableFuture extractQuery( + String querySql, + final String destinationUri, + final DestinationFormat destinationFormat, + final boolean printHeader) { + // Note: although BigQuery queries save their results to an auto-generated anonymous table, + // we can't rely on that for running the extract job because it may not be fully replicated. + // Tracking bug for query-to-GCS support is b/13777340. + DestinationTable tempTable = buildTemporaryTable().build(); + return Futures.transformAsync( + query(querySql, tempTable), new AsyncFunction() { + @Override + public ListenableFuture apply(DestinationTable tempTable) { + return extractTable(tempTable, destinationUri, destinationFormat, printHeader); + } + }); + } + + /** @see #runJob(Job, AbstractInputStreamContent) */ + public Job runJob(Job job) { + return runJob(job, null); + } + + /** + * Lanuch a job, wait for it to complete, but do not check for errors. + * + * @throws BigqueryJobFailureException + */ + public Job runJob(Job job, @Nullable AbstractInputStreamContent data) { + return checkJob(waitForJob(launchJob(job, data))); + } + + /** + * Lanuch a job, but do not wait for it to complete. + * + * @throws BigqueryJobFailureException + */ + private Job launchJob(Job job, @Nullable AbstractInputStreamContent data) { + verify(job.getStatus() == null); + try { + return data != null + ? bigquery.jobs().insert(getProjectId(), job, data).execute() + : bigquery.jobs().insert(getProjectId(), job).execute(); + } catch (IOException e) { + throw BigqueryJobFailureException.create(e); + } + } + + /** + * Synchronously waits for a job to complete that's already been launched. + * + * @throws BigqueryJobFailureException + */ + private Job waitForJob(Job job) { + verify(job.getStatus() != null); + while (!job.getStatus().getState().equals("DONE")) { + sleeper.sleepUninterruptibly(pollInterval); + JobReference ref = job.getJobReference(); + try { + job = bigquery.jobs().get(ref.getProjectId(), ref.getJobId()).execute(); + } catch (IOException e) { + throw BigqueryJobFailureException.create(e); + } + } + return job; + } + + /** + * Checks completed job for errors. + * + * @throws BigqueryJobFailureException + */ + private static Job checkJob(Job job) { + verify(job.getStatus() != null); + JobStatus jobStatus = job.getStatus(); + if (jobStatus.getErrorResult() != null) { + throw BigqueryJobFailureException.create(jobStatus); + } else { + logger.info(summarizeCompletedJob(job)); + if (jobStatus.getErrors() != null) { + for (ErrorProto error : jobStatus.getErrors()) { + logger.warning(String.format("%s: %s", error.getReason(), error.getMessage())); + } + } + return job; + } + } + + /** Returns a summarization of a completed job's statistics for logging. */ + private static String summarizeCompletedJob(Job job) { + JobStatistics stats = job.getStatistics(); + return String.format( + "Job took %,.3f seconds after a %,.3f second delay and processed %,d bytes (%s)", + (stats.getEndTime() - stats.getStartTime()) / 1000.0, + (stats.getStartTime() - stats.getCreationTime()) / 1000.0, + stats.getTotalBytesProcessed(), + toJobReferenceString(job.getJobReference())); + } + + private ListenableFuture runJobToCompletion(Job job, T result) { + return runJobToCompletion(job, result, null); + } + + /** Runs job and returns a future that yields {@code result} when {@code job} is completed. */ + private ListenableFuture runJobToCompletion( + final Job job, + final T result, + @Nullable final AbstractInputStreamContent data) { + return service.submit(new Callable() { + @Override + public T call() { + runJob(job, data); + return result; + }}); + } + + private ListenableFuture runJobToCompletion(final Job job) { + return service.submit(new Callable() { + @Override + public Job call() { + return runJob(job, null); + }}); + } + + /** Helper that returns true if a dataset with this name exists. */ + public boolean checkDatasetExists(String datasetName) throws IOException { + try { + bigquery.datasets().get(getProjectId(), datasetName).execute(); + return true; + } catch (GoogleJsonResponseException e) { + if (e.getDetails().getCode() == 404) { + return false; + } + throw e; + } + } + + /** Helper that returns true if a table with this name and dataset name exists. */ + public boolean checkTableExists(String datasetName, String tableName) throws IOException { + try { + bigquery.tables().get(getProjectId(), datasetName, tableName).execute(); + return true; + } catch (GoogleJsonResponseException e) { + if (e.getDetails().getCode() == 404) { + return false; + } + throw e; + } + } + + /** Returns the projectId set by the environment, or {@code null} if none is set. */ + public static String getEnvironmentProjectId() { + return RegistryEnvironment.get().config().getProjectId(); + } + + /** Returns the projectId associated with this bigquery connection. */ + public String getProjectId() { + return getEnvironmentProjectId(); + } + + /** Returns the dataset name that this bigquery connection uses by default. */ + public String getDatasetId() { + return datasetId; + } + + /** Returns dataset reference that can be used to avoid having to specify dataset in SQL code. */ + public DatasetReference getDataset() { + return new DatasetReference() + .setProjectId(getProjectId()) + .setDatasetId(getDatasetId()); + } + + /** Returns table reference with the projectId and datasetId filled out for you. */ + public TableReference getTable(String tableName) { + return new TableReference() + .setProjectId(getProjectId()) + .setDatasetId(getDatasetId()) + .setTableId(tableName); + } + + /** + * Helper that creates a dataset with this name if it doesn't already exist, and returns true + * if creation took place. + */ + public boolean createDatasetIfNeeded(String datasetName) throws IOException { + if (!checkDatasetExists(datasetName)) { + bigquery.datasets() + .insert(getProjectId(), new Dataset().setDatasetReference(new DatasetReference() + .setProjectId(getProjectId()) + .setDatasetId(datasetName))) + .execute(); + System.err.printf("Created dataset: %s:%s\n", getProjectId(), datasetName); + return true; + } + return false; + } + + /** Create a table from a SQL query if it doesn't already exist. */ + public TableReference ensureTable(TableReference table, String sqlQuery) { + try { + runJob(new Job() + .setConfiguration(new JobConfiguration() + .setQuery(new JobConfigurationQuery() + .setQuery(sqlQuery) + .setDefaultDataset(getDataset()) + .setDestinationTable(table)))); + } catch (BigqueryJobFailureException e) { + if (e.getReason().equals("duplicate")) { + // Table already exists. + } else { + throw e; + } + } + return table; + } +} diff --git a/java/com/google/domain/registry/bigquery/BigqueryFactory.java b/java/com/google/domain/registry/bigquery/BigqueryFactory.java new file mode 100644 index 000000000..15c3acc8d --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryFactory.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.services.bigquery.Bigquery; + +/** Factory for returning {@link Bigquery} instances. */ +public class BigqueryFactory { + public Bigquery create( + String applicationName, + HttpTransport transport, + JsonFactory jsonFactory, + HttpRequestInitializer httpRequestInitializer) { + return new Bigquery.Builder(transport, jsonFactory, httpRequestInitializer) + .setApplicationName(applicationName) + .build(); + } +} diff --git a/java/com/google/domain/registry/bigquery/BigqueryHelper.java b/java/com/google/domain/registry/bigquery/BigqueryHelper.java new file mode 100644 index 000000000..5c7d4df05 --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryHelper.java @@ -0,0 +1,75 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + + +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.model.Dataset; +import com.google.api.services.bigquery.model.DatasetReference; +import com.google.api.services.bigquery.model.Table; +import com.google.api.services.bigquery.model.TableFieldSchema; +import com.google.api.services.bigquery.model.TableReference; +import com.google.api.services.bigquery.model.TableSchema; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; + +/** Helpers for Bigquery. */ +public class BigqueryHelper { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * Ensures the dataset exists by trying to create it. Note that it's not appreciably cheaper + * to check for dataset existence than it is to try to create it and check for exceptions. + */ + // Note that these are not static so they can be mocked for testing. + public void ensureDataset(Bigquery bigquery, String projectId, String datasetId) + throws IOException { + try { + bigquery.datasets() + .insert(projectId, + new Dataset().setDatasetReference( + new DatasetReference() + .setProjectId(projectId) + .setDatasetId(datasetId))) + .execute(); + } catch (IOException e) { + // Swallow errors about a duplicate dataset, and throw any other ones. + if (!BigqueryJobFailureException.create(e).getReason().equals("duplicate")) { + throw e; + } + } + } + + /** Ensures the table exists in Bigquery. */ + public void ensureTable(Bigquery bigquery, TableReference table, + ImmutableList schema) throws IOException { + try { + bigquery.tables().insert(table.getProjectId(), table.getDatasetId(), new Table() + .setSchema(new TableSchema().setFields(schema)) + .setTableReference(table)) + .execute(); + logger.infofmt("Created BigQuery table %s:%s.%s", table.getProjectId(), table.getDatasetId(), + table.getTableId()); + } catch (IOException e) { + // Swallow errors about a table that exists, and throw any other ones. + if (!BigqueryJobFailureException.create(e).getReason().equals("duplicate")) { + throw e; + } + } + } +} diff --git a/java/com/google/domain/registry/bigquery/BigqueryJobFailureException.java b/java/com/google/domain/registry/bigquery/BigqueryJobFailureException.java new file mode 100644 index 000000000..1882d073b --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryJobFailureException.java @@ -0,0 +1,120 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.bigquery.model.ErrorProto; +import com.google.api.services.bigquery.model.JobStatus; +import com.google.common.collect.Iterables; + +import java.io.IOException; + +import javax.annotation.Nullable; + +/** Generic exception to throw if a Bigquery job fails. */ +public final class BigqueryJobFailureException extends RuntimeException { + + /** Delegate {@link IOException} errors, checking for {@link GoogleJsonResponseException} */ + public static BigqueryJobFailureException create(IOException cause) { + if (cause instanceof GoogleJsonResponseException) { + return create(((GoogleJsonResponseException) cause).getDetails()); + } else { + return new BigqueryJobFailureException(cause.getMessage(), cause, null, null); + } + } + + /** Create an error for JSON server response errors. */ + public static BigqueryJobFailureException create(GoogleJsonError error) { + return new BigqueryJobFailureException(error.getMessage(), null, null, error); + } + + /** Create an error from a failed job. */ + public static BigqueryJobFailureException create(JobStatus jobStatus) { + checkArgument(jobStatus.getErrorResult() != null, "this job didn't fail!"); + return new BigqueryJobFailureException( + describeError(jobStatus.getErrorResult()), null, jobStatus, null); + } + + @Nullable + private final JobStatus jobStatus; + + @Nullable + private final GoogleJsonError jsonError; + + private BigqueryJobFailureException( + String message, + @Nullable Throwable cause, + @Nullable JobStatus jobStatus, + @Nullable GoogleJsonError jsonError) { + super(message, cause); + this.jobStatus = jobStatus; + this.jsonError = jsonError; + } + + /** + * Returns a short error code describing why this job failed. + * + *

Sample Reasons

+ * + *
    + *
  • {@code "duplicate"}: The table you're trying to create already exists. + *
  • {@code "invalidQuery"}: Query syntax error of some sort. + *
  • {@code "unknown"}: Non-Bigquery errors. + *
+ * + * @see "https://cloud.google.com/bigquery/troubleshooting-errors" + */ + public String getReason() { + if (jobStatus != null) { + return jobStatus.getErrorResult().getReason(); + } else if (jsonError != null) { + return Iterables.getLast(jsonError.getErrors()).getReason(); + } else { + return "unknown"; + } + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append(String.format("%s: %s", getClass().getSimpleName(), getMessage())); + try { + if (jobStatus != null) { + for (ErrorProto error : jobStatus.getErrors()) { + result.append("\n---------------------------------- BEGIN DEBUG INFO\n"); + result.append(describeError(error)); + result.append('\n'); + result.append(error.getDebugInfo()); + result.append("\n---------------------------------- END DEBUG INFO"); + } + } + if (jsonError != null) { + String extraInfo = jsonError.toPrettyString(); + result.append('\n'); + result.append(extraInfo); + } + } catch (IOException e) { + result.append(e); + } + return result.toString(); + } + + private static String describeError(ErrorProto error) { + return String.format("%s: %s", error.getReason(), error.getMessage()); + } +} diff --git a/java/com/google/domain/registry/bigquery/BigqueryModule.java b/java/com/google/domain/registry/bigquery/BigqueryModule.java new file mode 100644 index 000000000..bc4c6edfa --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryModule.java @@ -0,0 +1,61 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + +import static dagger.Provides.Type.SET_VALUES; + +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.BigqueryScopes; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.OAuthScopes; + +import dagger.Module; +import dagger.Provides; + +import java.util.Set; + +/** + * Dagger module for Google {@link Bigquery} connection objects. + * + * @see com.google.domain.registry.config.ConfigModule + * @see com.google.domain.registry.request.Modules.UrlFetchTransportModule + * @see com.google.domain.registry.request.Modules.Jackson2Module + * @see com.google.domain.registry.request.Modules.AppIdentityCredentialModule + * @see com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule + */ +@Module +public final class BigqueryModule { + + /** Provides OAuth2 scopes for the Bigquery service needed by Domain Registry. */ + @Provides(type = SET_VALUES) + @OAuthScopes + static Set provideBigqueryOAuthScopes() { + return BigqueryScopes.all(); + } + + @Provides + static Bigquery provideBigquery( + HttpTransport transport, + JsonFactory jsonFactory, + HttpRequestInitializer httpRequestInitializer, + @Config("projectId") String projectId) { + return new Bigquery.Builder(transport, jsonFactory, httpRequestInitializer) + .setApplicationName(projectId) + .build(); + } +} diff --git a/java/com/google/domain/registry/bigquery/BigqueryUtils.java b/java/com/google/domain/registry/bigquery/BigqueryUtils.java new file mode 100644 index 000000000..183f5121a --- /dev/null +++ b/java/com/google/domain/registry/bigquery/BigqueryUtils.java @@ -0,0 +1,169 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.bigquery; + +import com.google.api.services.bigquery.model.JobReference; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.DateTimeParser; +import org.joda.time.format.ISODateTimeFormat; + +import java.util.concurrent.TimeUnit; + +/** Utilities related to Bigquery. */ +public class BigqueryUtils { + + /** Bigquery modes for schema fields. */ + public enum FieldMode { + NULLABLE, + REQUIRED, + REPEATED; + + /** Return the name of the field mode as it should appear in the Bigquery schema. */ + public String schemaName() { + return name(); + } + } + + /** Bigquery schema field types. */ + public enum FieldType { + STRING, + INTEGER, + FLOAT, + TIMESTAMP, + RECORD, + BOOLEAN; + + /** Return the name of the field type as it should appear in the Bigquery schema. */ + public String schemaName() { + return name(); + } + } + + /** Source formats for Bigquery load jobs. */ + public enum SourceFormat { + CSV, + NEWLINE_DELIMITED_JSON, + DATASTORE_BACKUP + } + + /** Destination formats for Bigquery extract jobs. */ + public enum DestinationFormat { + CSV, + NEWLINE_DELIMITED_JSON + } + + /** Bigquery table types (i.e. regular table or view). */ + public enum TableType { + TABLE, + VIEW + } + + /** + * Bigquery write dispositions (i.e. what to do about writing to an existing table). + * + * @see API docs + */ + public enum WriteDisposition { + /** Only write to the table if there is no existing table or if it is empty. */ + WRITE_EMPTY, + /** If the table already exists, overwrite it with the new data. */ + WRITE_TRUNCATE, + /** If the table already exists, append the data to the table. */ + WRITE_APPEND + } + + /** + * A {@code DateTimeFormatter} that defines how to print DateTimes in a string format that + * BigQuery can interpret and how to parse the string formats that BigQuery emits into DateTimes. + *

+ * The general format definition is "YYYY-MM-DD HH:MM:SS.SSS[ ZZ]", where the fractional seconds + * portion can have 0-6 decimal places (although we restrict it to 0-3 here since Joda DateTime + * only supports up to millisecond precision) and the zone if not specified defaults to UTC. + *

+ * Although we expect a zone specification of "UTC" when parsing, we don't emit it when printing + * because in some cases BigQuery does not allow any time zone specification (instead it assumes + * UTC for whatever input you provide) for input timestamp strings (see b/16380363). + * + * @see "https://developers.google.com/bigquery/timestamp" + */ + public static final DateTimeFormatter BIGQUERY_TIMESTAMP_FORMAT = new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.date()) + .appendLiteral(' ') + .append( + // For printing, always print out the milliseconds. + ISODateTimeFormat.hourMinuteSecondMillis().getPrinter(), + // For parsing, we need a series of parsers to correctly handle the milliseconds. + new DateTimeParser[] { + // Try to parse the time with milliseconds first, which requires at least one + // fractional second digit, and if that fails try to parse without milliseconds. + ISODateTimeFormat.hourMinuteSecondMillis().getParser(), + ISODateTimeFormat.hourMinuteSecond().getParser()}) + // Print UTC as the empty string since BigQuery's TIMESTAMP() function does not accept any + // time zone specification, but require "UTC" on parsing. Since we force this formatter to + // always use UTC below, the other arguments do not matter. + // + // TODO(b/26162667): replace this with appendLiteral(" UTC") if b/16380363 gets resolved. + .appendTimeZoneOffset("", " UTC", false, 1, 1) + .toFormatter() + .withZoneUTC(); + + /** + * Returns the human-readable string version of the given DateTime, suitable for conversion + * within BigQuery from a string literal into a BigQuery timestamp type. + */ + public static String toBigqueryTimestampString(DateTime dateTime) { + return BIGQUERY_TIMESTAMP_FORMAT.print(dateTime); + } + + /** Returns the DateTime for a given human-readable string-formatted BigQuery timestamp. */ + public static DateTime fromBigqueryTimestampString(String timestampString) { + return BIGQUERY_TIMESTAMP_FORMAT.parseDateTime(timestampString); + } + + /** + * Converts a time (in TimeUnits since the epoch) into a numeric string that BigQuery understands + * as a timestamp: the decimal number of seconds since the epoch, precise up to microseconds. + * + * @see "https://developers.google.com/bigquery/timestamp" + */ + public static String toBigqueryTimestamp(long timestamp, TimeUnit unit) { + long seconds = unit.toSeconds(timestamp); + long fractionalSeconds = unit.toMicros(timestamp) % 1000000; + return String.format("%d.%06d", seconds, fractionalSeconds); + } + + /** + * Converts a {@link DateTime} into a numeric string that BigQuery understands as a timestamp: + * the decimal number of seconds since the epoch, precise up to microseconds. + * + *

Note that since {@code DateTime} only stores milliseconds, the last 3 digits will be zero. + * + * @see "https://developers.google.com/bigquery/timestamp" + */ + public static String toBigqueryTimestamp(DateTime dateTime) { + return toBigqueryTimestamp(dateTime.getMillis(), TimeUnit.MILLISECONDS); + } + + /** + * Returns the canonical string format for a JobReference object (the project ID and then job ID, + * delimited by a single colon) since JobReference.toString() is not customized to return it. + */ + public static String toJobReferenceString(JobReference jobRef) { + return jobRef.getProjectId() + ":" + jobRef.getJobId(); + } +} diff --git a/java/com/google/domain/registry/bigquery/package-info.java b/java/com/google/domain/registry/bigquery/package-info.java new file mode 100644 index 000000000..0de145c40 --- /dev/null +++ b/java/com/google/domain/registry/bigquery/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.bigquery; diff --git a/java/com/google/domain/registry/braintree/BUILD b/java/com/google/domain/registry/braintree/BUILD new file mode 100644 index 000000000..0ee31794a --- /dev/null +++ b/java/com/google/domain/registry/braintree/BUILD @@ -0,0 +1,15 @@ +package(default_visibility = ["//java/com/google/domain/registry:registry_project"]) + + +java_library( + name = "braintree", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/keyring/api", + "//third_party/java/braintree", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + ], +) diff --git a/java/com/google/domain/registry/braintree/BraintreeModule.java b/java/com/google/domain/registry/braintree/BraintreeModule.java new file mode 100644 index 000000000..72c7357c9 --- /dev/null +++ b/java/com/google/domain/registry/braintree/BraintreeModule.java @@ -0,0 +1,47 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.braintree; + +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.keyring.api.KeyModule.Key; + +import com.braintreegateway.BraintreeGateway; + +import dagger.Module; +import dagger.Provides; + +import javax.inject.Singleton; + +/** Dagger module for Braintree Payments API. */ +@Module +public final class BraintreeModule { + + @Provides + @Singleton + static BraintreeGateway provideBraintreeGateway( + RegistryEnvironment environment, + @Config("braintreeMerchantId") String merchantId, + @Config("braintreePublicKey") String publicKey, + @Key("braintreePrivateKey") String privateKey) { + return new BraintreeGateway( + environment == RegistryEnvironment.PRODUCTION + ? com.braintreegateway.Environment.PRODUCTION + : com.braintreegateway.Environment.SANDBOX, + merchantId, + publicKey, + privateKey); + } +} diff --git a/java/com/google/domain/registry/braintree/package-info.java b/java/com/google/domain/registry/braintree/package-info.java new file mode 100644 index 000000000..b5601c17e --- /dev/null +++ b/java/com/google/domain/registry/braintree/package-info.java @@ -0,0 +1,17 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +/** Braintree payment gateway utilities. */ +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.braintree; diff --git a/java/com/google/domain/registry/config/BUILD b/java/com/google/domain/registry/config/BUILD new file mode 100644 index 000000000..fb4e17cb5 --- /dev/null +++ b/java/com/google/domain/registry/config/BUILD @@ -0,0 +1,18 @@ +package(default_visibility = ["//java/com/google/domain/registry:registry_project"]) + + +java_library( + name = "config", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_money", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + ], +) diff --git a/java/com/google/domain/registry/config/ConfigModule.java b/java/com/google/domain/registry/config/ConfigModule.java new file mode 100644 index 000000000..e3686fbd1 --- /dev/null +++ b/java/com/google/domain/registry/config/ConfigModule.java @@ -0,0 +1,558 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.config; + +import static com.google.domain.registry.config.ConfigUtils.makeUrl; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; + +import dagger.Module; +import dagger.Provides; + +import org.joda.money.CurrencyUnit; +import org.joda.time.DateTimeConstants; +import org.joda.time.Duration; + +import java.lang.annotation.Documented; +import java.net.URI; +import java.net.URL; + +import javax.inject.Qualifier; + +/** Dagger module for injecting configuration settings. */ +@Module +public final class ConfigModule { + + /** Dagger qualifier for configuration settings. */ + @Qualifier + @Documented + public static @interface Config { + String value() default ""; + } + + private static final RegistryEnvironment registryEnvironment = RegistryEnvironment.get(); + + @Provides + public static RegistryEnvironment provideRegistryEnvironment() { + return registryEnvironment; + } + + @Provides + public static RegistryConfig provideConfig(RegistryEnvironment environment) { + return environment.config(); + } + + @Provides + @Config("projectId") + public static String provideProjectId(RegistryConfig config) { + return config.getProjectId(); + } + + /** @see RegistryConfig#getZoneFilesBucket() */ + @Provides + @Config("zoneFilesBucket") + public static String provideZoneFilesBucket(RegistryConfig config) { + return config.getZoneFilesBucket(); + } + + /** @see RegistryConfig#getCommitsBucket() */ + @Provides + @Config("commitLogGcsBucket") + public static String provideCommitLogGcsBucket(RegistryConfig config) { + return config.getCommitsBucket(); + } + + /** @see RegistryConfig#getCommitLogDatastoreRetention() */ + @Provides + @Config("commitLogDatastoreRetention") + public static Duration provideCommitLogDatastoreRetention(RegistryConfig config) { + return config.getCommitLogDatastoreRetention(); + } + + /** + * Maximum number of commit logs to delete per transaction. + * + *

If we assume that the average key size is 256 bytes and that each manifest has six + * mutations, we can do about 5,000 deletes in a single transaction before hitting the 10mB limit. + * Therefore 500 should be a safe number, since it's an order of a magnitude less space than we + * need. + * + *

Transactions also have a four minute time limit. Since we have to perform N subqueries to + * fetch mutation keys, 500 would be a safe number if those queries were performed in serial, + * since each query would have about 500ms to complete, which is an order a magnitude more time + * than we need. However this does not apply, since the subqueries are performed asynchronously. + * + * @see com.google.domain.registry.backup.DeleteOldCommitLogsAction + */ + @Provides + @Config("commitLogMaxDeletes") + public static int provideCommitLogMaxDeletes() { + return 500; + } + + /** + * Batch size for the number of transactions' worth of commit log data to process at once when + * exporting a commit log diff. + * + * @see com.google.domain.registry.backup.ExportCommitLogDiffAction + */ + @Provides + @Config("commitLogDiffExportBatchSize") + public static int provideCommitLogDiffExportBatchSize() { + return 100; + } + + /** + * Returns the Google Cloud Storage bucket for staging BRDA escrow deposits. + * + * @see com.google.domain.registry.rde.PendingDepositChecker + */ + @Provides + @Config("brdaBucket") + public static String provideBrdaBucket(@Config("projectId") String projectId) { + return projectId + "-icann-brda"; + } + + /** @see com.google.domain.registry.rde.BrdaCopyTask */ + @Provides + @Config("brdaDayOfWeek") + public static int provideBrdaDayOfWeek() { + return DateTimeConstants.TUESDAY; + } + + /** Amount of time between BRDA deposits. */ + @Provides + @Config("brdaInterval") + public static Duration provideBrdaInterval() { + return Duration.standardDays(7); + } + + /** Maximum amount of time generating an BRDA deposit for a TLD could take, before killing. */ + @Provides + @Config("brdaLockTimeout") + public static Duration provideBrdaLockTimeout() { + return Duration.standardHours(5); + } + + /** Returns {@code true} if the target zone should be created in DNS if it does not exist. */ + @Provides + @Config("dnsCreateZone") + public static boolean provideDnsCreateZone(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return false; + default: + return true; + } + } + + /** + * The maximum number of domain and host updates to batch together to send to + * PublishDnsUpdatesAction, to avoid exceeding AppEngine's limits. + * */ + @Provides + @Config("dnsTldUpdateBatchSize") + public static int provideDnsTldUpdateBatchSize() { + return 100; + } + + /** The maximum interval (seconds) to lease tasks from the dns-pull queue. */ + @Provides + @Config("dnsWriteLockTimeout") + public static Duration provideDnsWriteLockTimeout() { + // Optimally, we would set this to a little less than the length of the DNS refresh cycle, since + // otherwise, a new PublishDnsUpdatesAction could get kicked off before the current one has + // finished, which will try and fail to acquire the lock. However, it is more important that it + // be greater than the DNS write timeout, so that if that timeout occurs, it will be cleaned up + // gracefully, rather than having the lock time out. So we have to live with the possible lock + // failures. + return Duration.standardSeconds(75); + } + + /** Returns the default time to live for DNS records. */ + @Provides + @Config("dnsDefaultTtl") + public static Duration provideDnsDefaultTtl() { + return Duration.standardSeconds(180); + } + + /** + * Number of sharded entity group roots used for performing strongly consistent scans. + * + *

Warning: This number may increase but never decrease. + * + * @see com.google.domain.registry.model.index.EppResourceIndex + */ + @Provides + @Config("eppResourceIndexBucketCount") + public static int provideEppResourceIndexBucketCount(RegistryConfig config) { + return config.getEppResourceIndexBucketCount(); + } + + /** + * Returns size of Google Cloud Storage client connection buffer in bytes. + * + * @see com.google.domain.registry.gcs.GcsUtils + */ + @Provides + @Config("gcsBufferSize") + public static int provideGcsBufferSize() { + return 1024 * 1024; + } + + /** + * Gets the email address of the admin account for the Google App. + * + * @see com.google.domain.registry.groups.DirectoryGroupsConnection + */ + @Provides + @Config("googleAppsAdminEmailAddress") + public static String provideGoogleAppsAdminEmailAddress(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return "admin@googleregistry.co"; + default: + return "admin@domainregistry-sandbox.co"; + } + } + + /** + * Returns the publicly accessible domain name for the running Google Apps instance. + * + * @see com.google.domain.registry.export.SyncGroupMembersTask + * @see com.google.domain.registry.tools.server.CreateGroupsTask + */ + @Provides + @Config("publicDomainName") + public static String providePublicDomainName(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return "googleregistry.co"; + default: + return "domainregistry-sandbox.co"; + } + } + + @Provides + @Config("tmchCaTestingMode") + public static boolean provideTmchCaTestingMode(RegistryConfig config) { + return config.getTmchCaTestingMode(); + } + + /** + * ICANN TMCH Certificate Revocation List URL. + * + *

This file needs to be downloaded at least once a day and verified to make sure it was + * signed by {@code icann-tmch.crt}. + * + * @see com.google.domain.registry.tmch.TmchCrlTask + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-5.2.3.2" + */ + @Provides + @Config("tmchCrlUrl") + public static URL provideTmchCrlUrl(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return makeUrl("http://crl.icann.org/tmch.crl"); + default: + return makeUrl("http://crl.icann.org/tmch_pilot.crl"); + } + } + + @Provides + @Config("tmchMarksdbUrl") + public static String provideTmchMarksdbUrl(RegistryConfig config) { + return config.getTmchMarksdbUrl(); + } + + /** + * Returns the Google Cloud Storage bucket for staging escrow deposits pending upload. + * + * @see com.google.domain.registry.rde.RdeStagingAction + */ + @Provides + @Config("rdeBucket") + public static String provideRdeBucket(@Config("projectId") String projectId) { + return projectId + "-rde"; + } + + /** + * Size of Ghostryde buffer in bytes for each layer in the pipeline. + * + * @see com.google.domain.registry.rde.Ghostryde + */ + @Provides + @Config("rdeGhostrydeBufferSize") + public static Integer provideRdeGhostrydeBufferSize() { + return 64 * 1024; + } + + /** Amount of time between RDE deposits. */ + @Provides + @Config("rdeInterval") + public static Duration provideRdeInterval() { + return Duration.standardDays(1); + } + + /** Maximum amount of time for sending a small XML file to ICANN via HTTP, before killing. */ + @Provides + @Config("rdeReportLockTimeout") + public static Duration provideRdeReportLockTimeout() { + return Duration.standardSeconds(60); + } + + /** + * URL of ICANN's HTTPS server to which the RDE report should be {@code PUT}. + * + *

You must append {@code "/TLD/ID"} to this URL. + * + * @see com.google.domain.registry.rde.RdeReportTask + */ + @Provides + @Config("rdeReportUrlPrefix") + public static String provideRdeReportUrlPrefix(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return "https://ry-api.icann.org/report/registry-escrow-report"; + default: + return "https://test-ry-api.icann.org:8543/report/registry-escrow-report"; + } + } + + /** + * Size of RYDE generator buffer in bytes for each of the five layers. + * + * @see com.google.domain.registry.rde.RydePgpCompressionOutputStream + * @see com.google.domain.registry.rde.RydePgpFileOutputStream + * @see com.google.domain.registry.rde.RydePgpSigningOutputStream + * @see com.google.domain.registry.rde.RydeTarOutputStream + */ + @Provides + @Config("rdeRydeBufferSize") + public static Integer provideRdeRydeBufferSize() { + return 64 * 1024; + } + + /** Maximum amount of time generating an escrow deposit for a TLD could take, before killing. */ + @Provides + @Config("rdeStagingLockTimeout") + public static Duration provideRdeStagingLockTimeout() { + return Duration.standardHours(5); + } + + /** Maximum amount of time it should ever take to upload an escrow deposit, before killing. */ + @Provides + @Config("rdeUploadLockTimeout") + public static Duration provideRdeUploadLockTimeout() { + return Duration.standardMinutes(30); + } + + /** + * Minimum amount of time to wait between consecutive SFTP uploads on a single TLD. + * + *

This value was communicated to us by the escrow provider. + */ + @Provides + @Config("rdeUploadSftpCooldown") + public static Duration provideRdeUploadSftpCooldown() { + return Duration.standardHours(2); + } + + /** + * Returns SFTP URL containing a username, hostname, port (optional), and directory (optional) to + * which cloud storage files are uploaded. The password should not be included, as it's better to + * use public key authentication. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + @Provides + @Config("rdeUploadUrl") + public static URI provideRdeUploadUrl(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return URI.create("sftp://GoogleTLD@sftpipm2.ironmountain.com/Outbox"); + default: + return URI.create("sftp://google@ppftpipm.ironmountain.com/Outbox"); + } + } + + /** Maximum amount of time for syncing a spreadsheet, before killing. */ + @Provides + @Config("sheetLockTimeout") + public static Duration provideSheetLockTimeout() { + return Duration.standardHours(1); + } + + /** + * Returns ID of Google Spreadsheet to which Registrar entities should be synced. + * + *

This ID, as you'd expect, comes from the URL of the spreadsheet. + * + * @see com.google.domain.registry.export.sheet.SyncRegistrarsSheetTask + */ + @Provides + @Config("sheetRegistrarId") + public static Optional provideSheetRegistrarId(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return Optional.of("1n2Gflqsgo9iDXcdt9VEskOVySZ8qIhQHJgjqsleCKdE"); + case ALPHA: + case CRASH: + return Optional.of("16BwRt6v11Iw-HujCbAkmMxqw3sUG13B8lmXLo-uJTsE"); + case SANDBOX: + return Optional.of("1TlR_UMCtfpkxT9oUEoF5JEbIvdWNkLRuURltFkJ_7_8"); + case QA: + return Optional.of("1RoY1XZhLLwqBkrz0WbEtaT9CU6c8nUAXfId5BtM837o"); + default: + return Optional.absent(); + } + } + + /** Amount of time between synchronizations of the Registrar spreadsheet. */ + @Provides + @Config("sheetRegistrarInterval") + public static Duration provideSheetRegistrarInterval() { + return Duration.standardHours(1); + } + + /** + * Returns SSH client connection and read timeout. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + @Provides + @Config("sshTimeout") + public static Duration provideSshTimeout() { + return Duration.standardSeconds(30); + } + + /** Duration after watermark where we shouldn't deposit, because transactions might be pending. */ + @Provides + @Config("transactionCooldown") + public static Duration provideTransactionCooldown() { + return Duration.standardMinutes(5); + } + + /** + * Number of times to retry a GAE operation when {@code TransientFailureException} is thrown. + * + *

The number of milliseconds it'll sleep before giving up is {@code 2^n - 2}. + * + * @see com.google.domain.registry.util.TaskEnqueuer + */ + @Provides + @Config("transientFailureRetries") + public static int provideTransientFailureRetries() { + return 12; // Four seconds. + } + + /** + * Amount of time public HTTP proxies are permitted to cache our WHOIS responses. + * + * @see com.google.domain.registry.whois.WhoisHttpServer + */ + @Provides + @Config("whoisHttpExpires") + public static Duration provideWhoisHttpExpires() { + return Duration.standardDays(1); + } + + /** + * Maximum number of results to return for an RDAP search query + * + * @see com.google.domain.registry.rdap.RdapActionBase + */ + @Provides + @Config("rdapResultSetMaxSize") + public static int provideRdapResultSetMaxSize() { + return 100; + } + + /** + * Base for RDAP link paths. + * + * @see com.google.domain.registry.rdap.RdapActionBase + */ + @Provides + @Config("rdapLinkBase") + public static String provideRdapLinkBase() { + return "https://nic.google/rdap/"; + } + + /** + * WHOIS server displayed in RDAP query responses. + * + * @see com.google.domain.registry.rdap.RdapActionBase + */ + @Provides + @Config("rdapWhoisServer") + public static String provideRdapWhoisServer() { + return "whois.nic.google"; + } + + /** Returns Braintree Merchant Account IDs for each supported currency. */ + @Provides + @Config("braintreeMerchantAccountIds") + public static ImmutableMap provideBraintreeMerchantAccountId( + RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return ImmutableMap.of( + CurrencyUnit.USD, "charlestonregistryUSD", + CurrencyUnit.JPY, "charlestonregistryJPY"); + default: + return ImmutableMap.of( + CurrencyUnit.USD, "google", + CurrencyUnit.JPY, "google-jpy"); + } + } + + /** + * Returns Braintree Merchant ID of Registry, used for accessing Braintree API. + * + *

This is a base32 value copied from the Braintree website. + */ + @Provides + @Config("braintreeMerchantId") + public static String provideBraintreeMerchantId(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return "TODO(b/25619518): Add production Braintree API credentials"; + default: + // Valentine: Domain Registry Braintree Sandbox + return "vqgn8khkq2cs6y9s"; + } + } + + /** + * Returns Braintree Public Key of Registry, used for accessing Braintree API. + * + *

This is a base32 value copied from the Braintree website. + * + * @see com.google.domain.registry.keyring.api.Keyring#getBraintreePrivateKey() + */ + @Provides + @Config("braintreePublicKey") + public static String provideBraintreePublicKey(RegistryEnvironment environment) { + switch (environment) { + case PRODUCTION: + return "tzcfxggzgbh2jg5x"; + default: + // Valentine: Domain Registry Braintree Sandbox + return "tzcyzvm3mn7zkdnx"; + } + } +} diff --git a/java/com/google/domain/registry/config/ConfigUtils.java b/java/com/google/domain/registry/config/ConfigUtils.java new file mode 100644 index 000000000..f63137d4b --- /dev/null +++ b/java/com/google/domain/registry/config/ConfigUtils.java @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.config; + +import java.net.MalformedURLException; +import java.net.URL; + +/** Helper methods for configuration classes. */ +final class ConfigUtils { + + /** + * Creates a URL instance. + * + * @throws RuntimeException to rethrow {@link MalformedURLException} + */ + static URL makeUrl(String url) { + try { + return new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + private ConfigUtils() {} +} diff --git a/java/com/google/domain/registry/config/RegistryConfig.java b/java/com/google/domain/registry/config/RegistryConfig.java new file mode 100644 index 000000000..ef8a65119 --- /dev/null +++ b/java/com/google/domain/registry/config/RegistryConfig.java @@ -0,0 +1,252 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.config; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.net.HostAndPort; + +import org.joda.time.Duration; + +import java.net.URL; + +/** + * Domain Registry configuration. + * + *

The goal of this custom configuration system is to have our project environments configured + * in type-safe Java code that can be refactored, rather than XML files and system properties. + * + *

Note: This interface is deprecated by {@link ConfigModule}. + */ +public interface RegistryConfig { + + /** + * Returns the App Engine project ID, which is based off the environment name. + */ + public String getProjectId(); + + /** + * Returns the Google Cloud Storage bucket for storing backup snapshots. + * + * @see com.google.domain.registry.export.ExportSnapshotServlet + */ + public String getSnapshotsBucket(); + + /** + * Returns the BigQuery dataset for storing directly imported datastore snapshots. + * + * @see com.google.domain.registry.export.LoadSnapshotServlet + */ + public String getSnapshotsDataset(); + + /** + * Returns the BigQuery dataset for storing views pointing to the latest datastore snapshot. + * + * @see com.google.domain.registry.export.UpdateSnapshotViewServlet + */ + public String getLatestSnapshotDataset(); + + /** + * Number of sharded commit log buckets. + * + *

This number is crucial for determining how much transactional throughput the system can + * allow, because it determines how many entity groups are available for writing commit logs. + * Since entity groups have a one transaction per second SLA (which is actually like ten in + * practice), a registry that wants to be able to handle one hundred transactions per second + * should have one hundred buckets. + * + *

Warning: This can be raised but never lowered. + * + * @see com.google.domain.registry.model.ofy.CommitLogBucket + */ + public int getCommitLogBucketCount(); + + /** + * Returns the length of time before commit logs should be deleted from datastore. + * + *

The only reason you'll want to retain this commit logs in datastore is for performing + * point-in-time restoration queries for subsystems like RDE. + * + * @see com.google.domain.registry.backup.DeleteOldCommitLogsAction + * @see com.google.domain.registry.model.translators.CommitLogRevisionsTranslatorFactory + */ + public Duration getCommitLogDatastoreRetention(); + + /** + * Returns the Google Cloud Storage bucket for storing commit logs. + * + * @see com.google.domain.registry.backup.ExportCommitLogDiffAction + */ + public String getCommitsBucket(); + + /** + * Returns the Google Cloud Storage bucket for storing zone files. + * + * @see com.google.domain.registry.backup.ExportCommitLogDiffAction + */ + public String getZoneFilesBucket(); + + /** + * Returns {@code true} if TMCH certificate authority should be in testing mode. + * + * @see com.google.domain.registry.tmch.TmchCertificateAuthority + */ + public boolean getTmchCaTestingMode(); + + /** + * URL prefix for communicating with MarksDB ry interface. + * + *

This URL is used for DNL, SMDRL, and LORDN. + * + * @see com.google.domain.registry.tmch.Marksdb + * @see com.google.domain.registry.tmch.NordnUploadAction + */ + public String getTmchMarksdbUrl(); + + public Optional getECatcherAddress(); + + /** + * Returns the address of the Domain Registry app HTTP server. + * + *

This is used by {@code registry_tool} to connect to the App Engine remote API. + */ + public HostAndPort getServer(); + + /** Returns the amount of time a singleton should be cached, before expiring. */ + public Duration getSingletonCacheRefreshDuration(); + + /** + * Returns the amount of time a domain label list should be cached in memory before expiring. + * + * @see com.google.domain.registry.model.registry.label.ReservedList + * @see com.google.domain.registry.model.registry.label.PremiumList + */ + public Duration getDomainLabelListCacheDuration(); + + /** Returns the amount of time a singleton should be cached in persist mode, before expiring. */ + public Duration getSingletonCachePersistDuration(); + + /** + * Returns the header text at the top of the reserved terms exported list. + * + * @see com.google.domain.registry.export.ExportUtils#exportReservedTerms + */ + public String getReservedTermsExportDisclaimer(); + + /** + * Returns a display name that is used on outgoing emails sent by Domain Registry. + * + * @see com.google.domain.registry.util.SendEmailUtils + */ + public String getGoogleAppsAdminEmailDisplayName(); + + /** + * Returns the email address that outgoing emails from the app are sent from. + * + * @see com.google.domain.registry.util.SendEmailUtils + */ + public String getGoogleAppsSendFromEmailAddress(); + + /** + * Returns the roid suffix to be used for the roids of all contacts and hosts. E.g. a value of + * "ROID" would end up creating roids that look like "ABC123-ROID". + * + * @see + * Extensible Provisioning Protocol (EPP) Repository Identifiers + */ + public String getContactAndHostRepositoryIdentifier(); + + /** + * Returns the email address(es) that notifications of registrar and/or registrar contact updates + * should be sent to, or the empty list if updates should not be sent. + * + * @see com.google.domain.registry.ui.server.registrar.RegistrarServlet + */ + public ImmutableList getRegistrarChangesNotificationEmailAddresses(); + + /** + * Returns the relativeURL path to the admin servlet, e.g. "/_dr/admin". + */ + public String getAdminServletPathPrefix(); + + /** + * Returns default WHOIS server to use when {@code Registrar#getWhoisServer()} is {@code null}. + * + * @see "com.google.domain.registry.whois.DomainWhoisResponse" + * @see "com.google.domain.registry.whois.RegistrarWhoisResponse" + */ + public String getRegistrarDefaultWhoisServer(); + + /** + * Returns the default referral URL that is used unless registrars have specified otherwise. + */ + public URL getRegistrarDefaultReferralUrl(); + + /** + * Returns whether the registrar console is enabled. + */ + public boolean isRegistrarConsoleEnabled(); + + /** + * Returns the title of the project used in generating documentation. + */ + public String getDocumentationProjectTitle(); + + /** + * Returns the maximum number of entities that can be checked at one time in an EPP check flow. + */ + public int getMaxChecks(); + + /** + * Returns the number of EppResourceIndex buckets to be used. + */ + public int getEppResourceIndexBucketCount(); + + /** + * Returns the base duration that gets doubled on each retry within {@code Ofy}. + */ + public Duration getBaseOfyRetryDuration(); + + /** + * Returns the global automatic transfer length for contacts. After this amount of time has + * elapsed, the transfer is automatically improved. + */ + public Duration getContactAutomaticTransferLength(); + + /** + * Returns the clientId of the registrar used by the {@code CheckApiServlet}. + */ + public String getCheckApiServletRegistrarClientId(); + + /** + * Returns the delay before executing async delete flow mapreduces. + * + *

This delay should be sufficiently longer than a transaction, to solve the following problem: + *

    + *
  • a domain mutation flow starts a transaction + *
  • the domain flow non-transactionally reads a resource and sees that it's not in + * PENDING_DELETE + *
  • the domain flow creates a new reference to this resource + *
  • a contact/host delete flow runs and marks the resource PENDING_DELETE and commits + *
  • the domain flow commits + *
+ * + *

Although we try not to add references to a PENDING_DELETE resource, strictly speaking that + * is ok as long as the mapreduce eventually sees the new reference (and therefore asynchronously + * fails the delete). Without this delay, the mapreduce might have started before the domain flow + * committed, and could potentially miss the reference. + */ + public Duration getAsyncDeleteFlowMapreduceDelay(); +} diff --git a/java/com/google/domain/registry/config/RegistryEnvironment.java b/java/com/google/domain/registry/config/RegistryEnvironment.java new file mode 100644 index 000000000..6cec55de6 --- /dev/null +++ b/java/com/google/domain/registry/config/RegistryEnvironment.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.config; + +import com.google.common.annotations.VisibleForTesting; + +import javax.annotation.Nullable; + +/** Registry environments. */ +public enum RegistryEnvironment { + + /** Production environment. */ + PRODUCTION, + + /** Development environment. */ + ALPHA, + + /** Load/Backup/Restore Testing environment. */ + CRASH, + + /** Local machine environment. */ + LOCAL, + + /** Quality Assurance environment. */ + QA, + + /** Sandbox environment. */ + SANDBOX, + + /** + * Unit testing environment. + * + *

This is the default enum value. This is because it's non-trivial to configure the system + * property that specifies the environment in our unit tests. + * + *

Do not use this environment outside of unit tests. + */ + UNITTEST; + + /** Returns environment configured by system property {@value #PROPERTY}. */ + public static RegistryEnvironment get() { + return valueOf(System.getProperty(PROPERTY, UNITTEST.name()).toUpperCase()); + } + + /** + * Returns configuration for this Domain Registry environment. + * + *

WARNING: Do not store this value to a static field, otherwise you won't be able to + * override it for testing. You should instead store the environment object to a static field. + */ + public RegistryConfig config() { + if (configOverride != null) { + return configOverride; + } else if (this == UNITTEST) { + return testingConfig; + } else { + return config; + } + } + + /** Globally override registry configuration from within a unit test. */ + @VisibleForTesting + public static void overrideConfigurationForTesting(@Nullable RegistryConfig newConfig) { + configOverride = newConfig; + } + + @Nullable + private static RegistryConfig configOverride; + + // TODO(b/19247780) Use true dependency injection for this. In the mean time, if you're not + // Google, you'll need to change this to include your own config class implementation at compile + // time. + private static final RegistryConfig testingConfig = new TestRegistryConfig(); + private final RegistryConfig config = new TestRegistryConfig(); + + /** System property for configuring which environment we should use. */ + public static final String PROPERTY = "com.google.domain.registry.environment"; +} diff --git a/java/com/google/domain/registry/config/TestRegistryConfig.java b/java/com/google/domain/registry/config/TestRegistryConfig.java new file mode 100644 index 000000000..ec4576c70 --- /dev/null +++ b/java/com/google/domain/registry/config/TestRegistryConfig.java @@ -0,0 +1,191 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.config; + +import static com.google.domain.registry.config.ConfigUtils.makeUrl; +import static org.joda.time.Duration.standardDays; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.net.HostAndPort; + +import org.joda.time.Duration; + +import java.net.URL; + +/** + * An implementation of RegistryConfig for unit testing that contains suitable testing data. + */ +public class TestRegistryConfig implements RegistryConfig { + + public TestRegistryConfig() {} + + @Override + public String getProjectId() { + return "domain-registry"; + } + + @Override + public int getCommitLogBucketCount() { + return 1; + } + + @Override + public Duration getCommitLogDatastoreRetention() { + return Duration.standardDays(30); + } + + @Override + public String getSnapshotsBucket() { + return getProjectId() + "-snapshots"; + } + + @Override + public String getSnapshotsDataset() { + return "snapshots"; + } + + @Override + public String getLatestSnapshotDataset() { + return "latest_snapshot"; + } + + @Override + public String getCommitsBucket() { + return getProjectId() + "-commits"; + } + + @Override + public String getZoneFilesBucket() { + return getProjectId() + "-zonefiles"; + } + + @Override + public boolean getTmchCaTestingMode() { + return true; + } + + @Override + public String getTmchMarksdbUrl() { + return "https://ry.marksdb.org"; + } + + @Override + public Optional getECatcherAddress() { + throw new UnsupportedOperationException(); + } + + @Override + public HostAndPort getServer() { + throw new UnsupportedOperationException(); + } + + @Override + public Duration getSingletonCacheRefreshDuration() { + // All cache durations are set to zero so that unit tests can update and then retrieve data + // immediately without failure. + return Duration.ZERO; + } + + @Override + public Duration getDomainLabelListCacheDuration() { + return Duration.ZERO; + } + + @Override + public Duration getSingletonCachePersistDuration() { + return Duration.ZERO; + } + + @Override + public String getReservedTermsExportDisclaimer() { + return "This is a disclaimer.\n"; + } + + @Override + public String getGoogleAppsAdminEmailDisplayName() { + return "Testing Domain Registry"; + } + + @Override + public String getGoogleAppsSendFromEmailAddress() { + return "noreply@testing.example"; + } + + @Override + public ImmutableList getRegistrarChangesNotificationEmailAddresses() { + return ImmutableList.of("notification@test.example", "notification2@test.example"); + } + + @Override + public String getAdminServletPathPrefix() { + return "/_dr/admin"; + } + + @Override + public String getRegistrarDefaultWhoisServer() { + return "whois.nic.fakewhois.example"; + } + + @Override + public URL getRegistrarDefaultReferralUrl() { + return makeUrl("http://www.referral.example/path"); + } + + @Override + public boolean isRegistrarConsoleEnabled() { + return true; + } + + @Override + public String getDocumentationProjectTitle() { + return "Domain Registry"; + } + + @Override + public int getMaxChecks() { + return 50; + } + + @Override + public int getEppResourceIndexBucketCount() { + return 2; + } + + @Override + public Duration getBaseOfyRetryDuration() { + return Duration.ZERO; + } + + @Override + public String getContactAndHostRepositoryIdentifier() { + return "ROID"; + } + + @Override + public Duration getContactAutomaticTransferLength() { + return standardDays(5); + } + + @Override + public String getCheckApiServletRegistrarClientId() { + return "TheRegistrar"; + } + + @Override + public Duration getAsyncDeleteFlowMapreduceDelay() { + return Duration.standardSeconds(90); + } +} diff --git a/java/com/google/domain/registry/config/package-info.java b/java/com/google/domain/registry/config/package-info.java new file mode 100644 index 000000000..93c3e4d08 --- /dev/null +++ b/java/com/google/domain/registry/config/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.config; diff --git a/java/com/google/domain/registry/cron/BUILD b/java/com/google/domain/registry/cron/BUILD new file mode 100644 index 000000000..ffb388d06 --- /dev/null +++ b/java/com/google/domain/registry/cron/BUILD @@ -0,0 +1,25 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "cron", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/cron/CommitLogFanoutAction.java b/java/com/google/domain/registry/cron/CommitLogFanoutAction.java new file mode 100644 index 000000000..5646e9e11 --- /dev/null +++ b/java/com/google/domain/registry/cron/CommitLogFanoutAction.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.cron; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static java.util.concurrent.TimeUnit.SECONDS; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.common.base.Optional; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.TaskEnqueuer; + +import java.util.Random; + +import javax.inject.Inject; + +/** Action for fanning out cron tasks for each commit log bucket. */ +@Action(path = "/_dr/cron/commitLogFanout", automaticallyPrintOk = true) +public final class CommitLogFanoutAction implements Runnable { + + public static final String BUCKET_PARAM = "bucket"; + + private static final Random random = new Random(); + + @Inject TaskEnqueuer taskEnqueuer; + @Inject @Parameter("endpoint") String endpoint; + @Inject @Parameter("queue") String queue; + @Inject @Parameter("jitterSeconds") Optional jitterSeconds; + @Inject CommitLogFanoutAction() {} + + @Override + public void run() { + Queue taskQueue = getQueue(queue); + for (int bucketId : CommitLogBucket.getBucketIds()) { + TaskOptions taskOptions = TaskOptions.Builder.withUrl(endpoint) + .param(BUCKET_PARAM, Integer.toString(bucketId)) + .countdownMillis(jitterSeconds.isPresent() + ? random.nextInt((int) SECONDS.toMillis(jitterSeconds.get())) + : 0); + taskEnqueuer.enqueue(taskQueue, taskOptions); + } + } +} diff --git a/java/com/google/domain/registry/cron/CronModule.java b/java/com/google/domain/registry/cron/CronModule.java new file mode 100644 index 000000000..130de9e09 --- /dev/null +++ b/java/com/google/domain/registry/cron/CronModule.java @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.cron; + +import static com.google.domain.registry.request.RequestParameters.extractBooleanParameter; +import static com.google.domain.registry.request.RequestParameters.extractOptionalIntParameter; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; +import static com.google.domain.registry.request.RequestParameters.extractSetOfParameters; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the cron package. */ +@Module +public final class CronModule { + + @Provides + @Parameter("endpoint") + static String provideEndpoint(HttpServletRequest req) { + return extractRequiredParameter(req, "endpoint"); + } + + @Provides + @Parameter("exclude") + static ImmutableSet provideExcludes(HttpServletRequest req) { + return extractSetOfParameters(req, "exclude"); + } + + @Provides + @Parameter("queue") + static String provideQueue(HttpServletRequest req) { + return extractRequiredParameter(req, "queue"); + } + + @Provides + @Parameter("runInEmpty") + static boolean provideRunInEmpty(HttpServletRequest req) { + return extractBooleanParameter(req, "runInEmpty"); + } + + @Provides + @Parameter("forEachRealTld") + static boolean provideForEachRealTld(HttpServletRequest req) { + return extractBooleanParameter(req, "forEachRealTld"); + } + + @Provides + @Parameter("forEachTestTld") + static boolean provideForEachTestTld(HttpServletRequest req) { + return extractBooleanParameter(req, "forEachTestTld"); + } + + @Provides + @Parameter("jitterSeconds") + static Optional provideJitterSeconds(HttpServletRequest req) { + return extractOptionalIntParameter(req, "jitterSeconds"); + } +} diff --git a/java/com/google/domain/registry/cron/TldFanoutAction.java b/java/com/google/domain/registry/cron/TldFanoutAction.java new file mode 100644 index 000000000..704ff8e36 --- /dev/null +++ b/java/com/google/domain/registry/cron/TldFanoutAction.java @@ -0,0 +1,134 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.cron; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.common.base.Predicates.in; +import static com.google.common.base.Predicates.not; +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Multimaps.filterKeys; +import static com.google.common.collect.Sets.difference; +import static com.google.domain.registry.model.registry.Registries.getTldsOfType; +import static com.google.domain.registry.model.registry.Registry.TldType.REAL; +import static com.google.domain.registry.model.registry.Registry.TldType.TEST; +import static java.util.concurrent.TimeUnit.SECONDS; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.ParameterMap; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.TaskEnqueuer; + +import java.util.Random; +import java.util.Set; + +import javax.inject.Inject; + +/** + * Action for fanning out cron tasks shared by TLD. + * + *

Parameters Reference

+ * + *
    + *
  • {@code endpoint} (Required) URL path of servlet to launch. This may contain pathargs. + *
  • {@code queue} (Required) Name of the App Engine push queue to which this task should be sent. + *
  • {@code forEachRealTld} Launch the task in each real TLD namespace. + *
  • {@code forEachTestTld} Launch the task in each test TLD namespace. + *
  • {@code runInEmpty} Launch the task in the empty namespace. + *
  • {@code exclude} TLDs to exclude. + *
  • {@code jitterSeconds} Randomly delay each task by up to this many seconds. + *
  • Any other parameters specified will be passed through as POST parameters to the called task. + *
+ * + *

Patharg Reference

+ * + *

The following values may be specified inside the "endpoint" param. + *

    + *
  • {@code :tld} Substituted with an ASCII tld, if tld fanout is enabled. + * This patharg is mostly useful for aesthetic purposes, since tasks are already namespaced. + *
+ */ +@Action(path = "/_dr/cron/fanout", automaticallyPrintOk = true) +public final class TldFanoutAction implements Runnable { + + private static final String ENDPOINT_PARAM = "endpoint"; + private static final String QUEUE_PARAM = "queue"; + private static final String FOR_EACH_REAL_TLD_PARAM = "forEachRealTld"; + private static final String FOR_EACH_TEST_TLD_PARAM = "forEachTestTld"; + private static final String RUN_IN_EMPTY_PARAM = "runInEmpty"; + private static final String EXCLUDE_PARAM = "exclude"; + private static final String JITTER_SECONDS_PARAM = "jitterSeconds"; + + /** A set of control params to TldFanoutAction that aren't passed down to the executing action. */ + private static final Set CONTROL_PARAMS = ImmutableSet.of( + ENDPOINT_PARAM, + QUEUE_PARAM, + FOR_EACH_REAL_TLD_PARAM, + FOR_EACH_TEST_TLD_PARAM, + RUN_IN_EMPTY_PARAM, + EXCLUDE_PARAM, + JITTER_SECONDS_PARAM); + + private static final String TLD_PATHARG = ":tld"; + private static final Random random = new Random(); + + @Inject TaskEnqueuer taskEnqueuer; + @Inject @Parameter(ENDPOINT_PARAM) String endpoint; + @Inject @Parameter(QUEUE_PARAM) String queue; + @Inject @Parameter(FOR_EACH_REAL_TLD_PARAM) boolean forEachRealTld; + @Inject @Parameter(FOR_EACH_TEST_TLD_PARAM) boolean forEachTestTld; + @Inject @Parameter(RUN_IN_EMPTY_PARAM) boolean runInEmpty; + @Inject @Parameter(EXCLUDE_PARAM) ImmutableSet excludes; + @Inject @Parameter(JITTER_SECONDS_PARAM) Optional jitterSeconds; + @Inject @ParameterMap ImmutableListMultimap params; + @Inject TldFanoutAction() {} + + @Override + public void run() { + Set namespaces = ImmutableSet.copyOf(concat( + runInEmpty ? ImmutableSet.of("") : ImmutableSet.of(), + forEachRealTld ? getTldsOfType(REAL) : ImmutableSet.of(), + forEachTestTld ? getTldsOfType(TEST) : ImmutableSet.of())); + Multimap flowThruParams = filterKeys(params, not(in(CONTROL_PARAMS))); + Queue taskQueue = getQueue(queue); + for (String namespace : difference(namespaces, excludes)) { + taskEnqueuer.enqueue(taskQueue, createTaskOptions(namespace, flowThruParams)); + } + } + + private TaskOptions createTaskOptions(String tld, Multimap params) { + TaskOptions options = + withUrl(endpoint.replace(TLD_PATHARG, String.valueOf(tld))) + .countdownMillis( + jitterSeconds.isPresent() + ? random.nextInt((int) SECONDS.toMillis(jitterSeconds.get())) + : 0); + options.param(RequestParameters.PARAM_TLD, tld); + for (String param : params.keySet()) { + // TaskOptions.param() does not accept null values. + options.param(param, nullToEmpty((getFirst(params.get(param), null)))); + } + return options; + } +} diff --git a/java/com/google/domain/registry/cron/package-info.java b/java/com/google/domain/registry/cron/package-info.java new file mode 100644 index 000000000..f840e11cb --- /dev/null +++ b/java/com/google/domain/registry/cron/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.cron; diff --git a/java/com/google/domain/registry/dns/BUILD b/java/com/google/domain/registry/dns/BUILD new file mode 100644 index 000000000..629362ffe --- /dev/null +++ b/java/com/google/domain/registry/dns/BUILD @@ -0,0 +1,41 @@ +# Description: +# Routines to publish authoritative DNS. + +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "constants", + srcs = ["DnsConstants.java"], +) + +java_library( + name = "dns", + srcs = glob( + ["*.java"], + exclude = ["DnsConstants.java"], + ), + deps = [ + ":constants", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/dns/writer/api", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/dns/DnsConstants.java b/java/com/google/domain/registry/dns/DnsConstants.java new file mode 100644 index 000000000..0a0f44b44 --- /dev/null +++ b/java/com/google/domain/registry/dns/DnsConstants.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +/** Static class for DNS-related constants. */ +public class DnsConstants { + private DnsConstants() {} + + /** The name of the DNS pull queue. */ + public static final String DNS_PULL_QUEUE_NAME = "dns-pull"; // See queue.xml. + + /** The name of the DNS publish push queue. */ + public static final String DNS_PUBLISH_PUSH_QUEUE_NAME = "dns-publish"; // See queue.xml. + + /** The parameter to use for storing the target type ("domain" or "host" or "zone"). */ + public static final String DNS_TARGET_TYPE_PARAM = "Target-Type"; + + /** The parameter to use for storing the target name (domain or host name) with the task. */ + public static final String DNS_TARGET_NAME_PARAM = "Target-Name"; + + /** The possible values of the {@code DNS_TARGET_NAME_PARAM} parameter. */ + public enum TargetType { DOMAIN, HOST, ZONE } +} diff --git a/java/com/google/domain/registry/dns/DnsModule.java b/java/com/google/domain/registry/dns/DnsModule.java new file mode 100644 index 000000000..40ad1be2f --- /dev/null +++ b/java/com/google/domain/registry/dns/DnsModule.java @@ -0,0 +1,93 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.domain.registry.dns.DnsConstants.DNS_PUBLISH_PUSH_QUEUE_NAME; +import static com.google.domain.registry.dns.DnsConstants.DNS_PULL_QUEUE_NAME; +import static com.google.domain.registry.dns.PublishDnsUpdatesAction.DOMAINS_PARAM; +import static com.google.domain.registry.dns.PublishDnsUpdatesAction.HOSTS_PARAM; +import static com.google.domain.registry.dns.ReadDnsQueueAction.KEEP_TASKS_PARAM; +import static com.google.domain.registry.request.RequestParameters.extractBooleanParameter; +import static com.google.domain.registry.request.RequestParameters.extractEnumParameter; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; +import static com.google.domain.registry.request.RequestParameters.extractSetOfParameters; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.QueueFactory; +import com.google.domain.registry.dns.DnsConstants.TargetType; +import com.google.domain.registry.dns.writer.api.DnsWriterZone; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; + +import dagger.Module; +import dagger.Provides; + +import java.util.Set; + +import javax.inject.Named; +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the dns package. */ +@Module +public final class DnsModule { + + @Provides + @DnsWriterZone + static String provideZoneName(@Parameter(RequestParameters.PARAM_TLD) String tld) { + return tld; + } + + @Provides + @Named(DNS_PULL_QUEUE_NAME) + static Queue provideDnsPullQueue() { + return QueueFactory.getQueue(DNS_PULL_QUEUE_NAME); + } + + @Provides + @Named(DNS_PUBLISH_PUSH_QUEUE_NAME) + static Queue provideDnsUpdatePushQueue() { + return QueueFactory.getQueue(DNS_PUBLISH_PUSH_QUEUE_NAME); + } + + @Provides + @Parameter(DOMAINS_PARAM) + static Set provideDomains(HttpServletRequest req) { + return extractSetOfParameters(req, DOMAINS_PARAM); + } + + @Provides + @Parameter(HOSTS_PARAM) + static Set provideHosts(HttpServletRequest req) { + return extractSetOfParameters(req, HOSTS_PARAM); + } + + @Provides + @Parameter(KEEP_TASKS_PARAM) + static boolean provideKeepTasks(HttpServletRequest req) { + return extractBooleanParameter(req, KEEP_TASKS_PARAM); + } + + @Provides + @Parameter("name") + static String provideName(HttpServletRequest req) { + return extractRequiredParameter(req, "name"); + } + + @Provides + @Parameter("type") + static TargetType provideType(HttpServletRequest req) { + return extractEnumParameter(req, TargetType.class, "type"); + } +} diff --git a/java/com/google/domain/registry/dns/DnsQueue.java b/java/com/google/domain/registry/dns/DnsQueue.java new file mode 100644 index 000000000..0fb8d3fcc --- /dev/null +++ b/java/com/google/domain/registry/dns/DnsQueue.java @@ -0,0 +1,161 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.dns.DnsConstants.DNS_PULL_QUEUE_NAME; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_NAME_PARAM; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_TYPE_PARAM; +import static com.google.domain.registry.model.domain.DomainUtils.getTldFromDomainName; +import static com.google.domain.registry.model.registry.Registries.assertTldExists; +import static com.google.domain.registry.request.RequestParameters.PARAM_TLD; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.QueueConstants; +import com.google.appengine.api.taskqueue.QueueFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.appengine.api.taskqueue.TransientFailureException; +import com.google.apphosting.api.DeadlineExceededException; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.dns.DnsConstants.TargetType; +import com.google.domain.registry.model.registry.Registries; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.Duration; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Named; + +/** Methods for manipulating the queue used for DNS write tasks. */ +public class DnsQueue { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject @Config("dnsWriteLockTimeout") Duration writeLockTimeout; + @Inject @Named(DNS_PULL_QUEUE_NAME) Queue queue; + @Inject DnsQueue() {} + + long writeBatchSize = QueueConstants.maxLeaseCount(); + + /** + * Enqueues the given task type with the given target name to the DNS queue, tagged with the + * specified TLD. + */ + private TaskHandle addToQueue(TargetType targetType, String targetName, String tld) { + return queue.add(TaskOptions.Builder + // TODO(b/24564175): don't set the tag + .withTag(tld) + .method(Method.PULL) + .param(DNS_TARGET_TYPE_PARAM, targetType.toString()) + .param(DNS_TARGET_NAME_PARAM, targetName) + .param(PARAM_TLD, tld)); + } + + /** + * Adds a task to the queue to refresh the DNS information for the specified subordinate host. + */ + public TaskHandle addHostRefreshTask(String fullyQualifiedHostName) { + Optional tld = + Registries.findTldForName(InternetDomainName.from(fullyQualifiedHostName)); + checkArgument(tld.isPresent(), + String.format("%s is not a subordinate host to a known tld", fullyQualifiedHostName)); + return addToQueue(TargetType.HOST, fullyQualifiedHostName, tld.get().toString()); + } + + /** Adds a task to the queue to refresh the DNS information for the specified domain. */ + public TaskHandle addDomainRefreshTask(String fullyQualifiedDomainName) { + return addToQueue( + TargetType.DOMAIN, + fullyQualifiedDomainName, + assertTldExists(getTldFromDomainName(fullyQualifiedDomainName))); + } + + /** Adds a task to the queue to refresh the DNS information for the specified zone. */ + public TaskHandle addZoneRefreshTask(String fullyQualifiedZoneName) { + return addToQueue(TargetType.ZONE, fullyQualifiedZoneName, fullyQualifiedZoneName); + } + + /** + * Returns a batch of pending tasks. + */ + public List leaseTasks() { + return leaseTasks(null); + } + + /** + * Returns a batch of pending tasks. + * + * @param tag the filter used to lease only those tasks that match + */ + public List leaseTasks(@Nullable String tag) { + try { + return isNullOrEmpty(tag) + ? queue.leaseTasks(writeLockTimeout.getMillis(), MILLISECONDS, writeBatchSize) + : queue.leaseTasksByTag(writeLockTimeout.getMillis(), MILLISECONDS, writeBatchSize, tag); + } catch (TransientFailureException | DeadlineExceededException e) { + logger.severe(e, "Failed leasing tasks too fast"); + return ImmutableList.of(); + } + } + + /** Reduce the task lease time to zero, making it immediately available to be leased again. */ + public void dropTaskLease(TaskHandle task) { + try { + queue.modifyTaskLease(task, 0, TimeUnit.SECONDS); + } catch (IllegalStateException e) { + logger.warningfmt(e, "Failed dropping expired lease: %s", task.getName()); + } catch (TransientFailureException | DeadlineExceededException e) { + logger.severe(e, "Failed dropping task leases too fast"); + } + } + + /** Delete the task, removing it from the queue permanently. */ + public void deleteTask(TaskHandle task) { + try { + queue.deleteTask(task); + } catch (TransientFailureException | DeadlineExceededException e) { + logger.severe(e, "Failed deleting tasks too fast"); + } + } + + /** Delete a list of tasks, removing them from the queue permanently. */ + public void deleteTasks(List tasks) { + try { + queue.deleteTask(tasks); + } catch (TransientFailureException | DeadlineExceededException e) { + logger.severe(e, "Failed deleting tasks too fast"); + } + } + + // TODO(b/19483428): Remove me when flows package is ported to Dagger. + /** Creates a new instance. */ + public static DnsQueue create() { + DnsQueue result = new DnsQueue(); + result.writeLockTimeout = Duration.standardSeconds(120); + result.queue = QueueFactory.getQueue(DNS_PULL_QUEUE_NAME); + return result; + } +} diff --git a/java/com/google/domain/registry/dns/PublishDnsUpdatesAction.java b/java/com/google/domain/registry/dns/PublishDnsUpdatesAction.java new file mode 100644 index 000000000..508cdfb1b --- /dev/null +++ b/java/com/google/domain/registry/dns/PublishDnsUpdatesAction.java @@ -0,0 +1,98 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.domain.registry.model.server.Lock.executeWithLocks; +import static com.google.domain.registry.request.Action.Method.POST; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.dns.writer.api.DnsWriter; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.ServiceUnavailableException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.DomainNameUtils; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.Duration; + +import java.util.Set; +import java.util.concurrent.Callable; + +import javax.inject.Inject; +import javax.inject.Provider; + +/** Task that sends domain and host updates to the DNS server. */ +@Action(path = PublishDnsUpdatesAction.PATH, method = POST, automaticallyPrintOk = true) +public final class PublishDnsUpdatesAction implements Runnable, Callable { + + public static final String PATH = "/_dr/task/publishDnsUpdates"; + public static final String DOMAINS_PARAM = "domains"; + public static final String HOSTS_PARAM = "hosts"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject DnsQueue dnsQueue; + @Inject Provider writerProvider; + @Inject @Config("dnsWriteLockTimeout") Duration timeout; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject @Parameter(DOMAINS_PARAM) Set domains; + @Inject @Parameter(HOSTS_PARAM) Set hosts; + @Inject PublishDnsUpdatesAction() {} + + /** Runs the task. */ + @Override + public void run() { + String lockName = String.format("DNS zone %s", tld); + // If executeWithLocks fails to get the lock, it does not throw an exception, simply returns + // false. We need to make sure to take note of this error; otherwise, a failed lock might result + // in the update task being dequeued and dropped. A message will already have been logged + // to indicate the problem. + if (!executeWithLocks(this, getClass(), tld, timeout, lockName)) { + throw new ServiceUnavailableException("Lock failure"); + } + } + + /** Runs the task, with the lock. */ + @Override + public Void call() { + processBatch(); + return null; + } + + /** Steps through the domain and host refreshes contained in the parameters and processes them. */ + private void processBatch() { + try (DnsWriter writer = writerProvider.get()) { + for (String domain : nullToEmpty(domains)) { + if (!DomainNameUtils.isUnder( + InternetDomainName.from(domain), InternetDomainName.from(tld))) { + logger.severefmt("%s: skipping domain %s not under tld", tld, domain); + } else { + writer.publishDomain(domain); + } + } + for (String host : nullToEmpty(hosts)) { + if (!DomainNameUtils.isUnder( + InternetDomainName.from(host), InternetDomainName.from(tld))) { + logger.severefmt("%s: skipping host %s not under tld", tld, host); + } else { + writer.publishHost(host); + } + } + } + } +} diff --git a/java/com/google/domain/registry/dns/ReadDnsQueueAction.java b/java/com/google/domain/registry/dns/ReadDnsQueueAction.java new file mode 100644 index 000000000..3e514cb59 --- /dev/null +++ b/java/com/google/domain/registry/dns/ReadDnsQueueAction.java @@ -0,0 +1,204 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.common.collect.Sets.difference; +import static com.google.domain.registry.dns.DnsConstants.DNS_PUBLISH_PUSH_QUEUE_NAME; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_NAME_PARAM; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_TYPE_PARAM; +import static com.google.domain.registry.model.registry.Registries.getTlds; +import static java.util.concurrent.TimeUnit.SECONDS; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.common.base.Optional; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.TreeMultimap; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.dns.DnsConstants.TargetType; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.TaskEnqueuer; + +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Action for fanning out DNS refresh tasks by TLD, using data taken from the DNS pull queue. + * + *

Parameters Reference

+ * + *
    + *
  • {@code jitterSeconds} Randomly delay each task by up to this many seconds. + *
  • {@code keepTasks} Do not delete any tasks from the pull queue, whether they are processed or + * not. + *
+ */ +@Action(path = "/_dr/cron/readDnsQueue", automaticallyPrintOk = true) +public final class ReadDnsQueueAction implements Runnable { + + public static final String KEEP_TASKS_PARAM = "keepTasks"; + + private static final String JITTER_SECONDS_PARAM = "jitterSeconds"; + private static final Random random = new Random(); + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject @Config("dnsTldUpdateBatchSize") int tldUpdateBatchSize; + @Inject @Named(DNS_PUBLISH_PUSH_QUEUE_NAME) Queue dnsPublishPushQueue; + @Inject @Parameter(JITTER_SECONDS_PARAM) Optional jitterSeconds; + @Inject @Parameter(KEEP_TASKS_PARAM) boolean keepTasks; + @Inject DnsQueue dnsQueue; + @Inject TaskEnqueuer taskEnqueuer; + @Inject ReadDnsQueueAction() {} + + /** Container for items we pull out of the DNS pull queue and process for fanout. */ + private class RefreshItem implements Comparable { + final TargetType type; + final String name; + + public RefreshItem(final TargetType type, final String name) { + this.type = type; + this.name = name; + } + + @Override + public int compareTo(RefreshItem other) { + return ComparisonChain.start() + .compare(this.type, other.type) + .compare(this.name, other.name) + .result(); + } + } + + /** Leases all tasks from the pull queue and creates per-tld update actions for them. */ + @Override + public void run() { + Set tldsOfInterest = getTlds(); + + List tasks = dnsQueue.leaseTasks(); + if (tasks.isEmpty()) { + return; + } + logger.infofmt("leased %d tasks", tasks.size()); + // Normally, all tasks will be deleted from the pull queue. But some might have to remain if + // we are not interested in the associated TLD, or if the TLD is paused. Remember which these + // are. + Set tasksToKeep = new HashSet<>(); + // The paused TLDs for which we found at least one refresh request. + Set pausedTlds = new HashSet<>(); + // Create a sorted multimap into which we will insert the refresh items, so that the items for + // each TLD will be grouped together, and domains and hosts will be grouped within a TLD. The + // grouping and ordering of domains and hosts is not technically necessary, but a predictable + // ordering makes it possible to write detailed tests. + TreeMultimap refreshItemMultimap = TreeMultimap.create(); + // Read all tasks on the DNS pull queue and load them into the refresh item multimap. + for (TaskHandle task : tasks) { + try { + Map params = ImmutableMap.copyOf(task.extractParams()); + // Dual-read the TLD from either the parameter (new methodology) or the tag (old way). + // TODO(b/24564175): get the TLD from the regular parameter only. + String tld = task.getTag(); + if (tld == null) { + tld = params.get(RequestParameters.PARAM_TLD); + } + if (tld == null) { + logger.severe("discarding invalid DNS refresh request; no TLD specified"); + } else if (!tldsOfInterest.contains(tld)) { + tasksToKeep.add(task); + } else if (Registry.get(tld).getDnsPaused()) { + tasksToKeep.add(task); + pausedTlds.add(tld); + } else { + String typeString = params.get(DNS_TARGET_TYPE_PARAM); + String name = params.get(DNS_TARGET_NAME_PARAM); + if (typeString == null) { + logger.severe("discarding invalid DNS refresh request; no type specified"); + } else if (name == null) { + logger.severe("discarding invalid DNS refresh request; no name specified"); + } else { + TargetType type = TargetType.valueOf(typeString); + switch (type) { + case DOMAIN: + case HOST: + refreshItemMultimap.put(tld, new RefreshItem(type, name)); + break; + default: + logger.severefmt("discarding DNS refresh request of type %s", typeString); + break; + } + } + } + } catch (UnsupportedEncodingException e) { + logger.severefmt(e, "discarding invalid DNS refresh request (task %s)", task); + } + } + if (!pausedTlds.isEmpty()) { + logger.infofmt("the dns-pull queue is paused for tlds: %s", pausedTlds); + } + // Loop through the multimap by TLD and generate refresh tasks for the hosts and domains. + for (Map.Entry> tldRefreshItemsEntry + : refreshItemMultimap.asMap().entrySet()) { + for (List chunk : Iterables.partition( + tldRefreshItemsEntry.getValue(), tldUpdateBatchSize)) { + TaskOptions options = withUrl(PublishDnsUpdatesAction.PATH) + .countdownMillis(jitterSeconds.isPresent() + ? random.nextInt((int) SECONDS.toMillis(jitterSeconds.get())) + : 0) + .param(RequestParameters.PARAM_TLD, tldRefreshItemsEntry.getKey()); + for (RefreshItem refreshItem : chunk) { + options.param( + (refreshItem.type == TargetType.HOST) + ? PublishDnsUpdatesAction.HOSTS_PARAM : PublishDnsUpdatesAction.DOMAINS_PARAM, + refreshItem.name); + } + taskEnqueuer.enqueue(dnsPublishPushQueue, options); + } + } + Set tasksToDelete = difference(ImmutableSet.copyOf(tasks), tasksToKeep); + // In keepTasks mode, never delete any tasks. + if (keepTasks) { + logger.infofmt("would have deleted %d tasks", tasksToDelete.size()); + for (TaskHandle task : tasks) { + dnsQueue.dropTaskLease(task); + } + // Otherwise, either delete or drop the lease of each task. + } else { + logger.infofmt("deleting %d tasks", tasksToDelete.size()); + dnsQueue.deleteTasks(ImmutableList.copyOf(tasksToDelete)); + logger.infofmt("dropping %d tasks", tasksToKeep.size()); + for (TaskHandle task : tasksToKeep) { + dnsQueue.dropTaskLease(task); + } + logger.infofmt("done"); + } + } +} diff --git a/java/com/google/domain/registry/dns/RefreshDns.java b/java/com/google/domain/registry/dns/RefreshDns.java new file mode 100644 index 000000000..208f6bdba --- /dev/null +++ b/java/com/google/domain/registry/dns/RefreshDns.java @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; + +import com.google.domain.registry.dns.DnsConstants.TargetType; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.Clock; + +import javax.inject.Inject; + +/** Endpoint for manually triggering refresh of DNS information. */ +@Action(path = "/_dr/dnsRefresh", automaticallyPrintOk = true) +public final class RefreshDns implements Runnable { + + @Inject Clock clock; + @Inject DnsQueue dnsQueue; + @Inject @Parameter("name") String domainOrHostName; + @Inject @Parameter("type") TargetType type; + @Inject RefreshDns() {} + + @Override + public void run() { + if (!domainOrHostName.contains(".")) { + throw new BadRequestException("URL parameter 'name' must be fully qualified"); + } + + boolean domainLookup; + Class clazz; + switch (type) { + case DOMAIN: + domainLookup = true; + clazz = DomainResource.class; + break; + case HOST: + domainLookup = false; + clazz = HostResource.class; + break; + default: + throw new BadRequestException("Unsupported type: " + type); + } + + EppResource eppResource = loadByUniqueId(clazz, domainOrHostName, clock.nowUtc()); + if (eppResource == null) { + throw new NotFoundException( + String.format("%s %s not found", type, domainOrHostName)); + } + + if (domainLookup) { + dnsQueue.addDomainRefreshTask(domainOrHostName); + } else { + if (((HostResource) eppResource).getSuperordinateDomain() == null) { + throw new BadRequestException( + String.format("%s isn't a subordinate hostname", domainOrHostName)); + } else { + // Don't enqueue host refresh tasks for external hosts. + dnsQueue.addHostRefreshTask(domainOrHostName); + } + } + } +} diff --git a/java/com/google/domain/registry/dns/WriteDnsTask.java b/java/com/google/domain/registry/dns/WriteDnsTask.java new file mode 100644 index 000000000..51832eb2f --- /dev/null +++ b/java/com/google/domain/registry/dns/WriteDnsTask.java @@ -0,0 +1,158 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_NAME_PARAM; +import static com.google.domain.registry.dns.DnsConstants.DNS_TARGET_TYPE_PARAM; +import static com.google.domain.registry.model.server.Lock.executeWithLocks; +import static com.google.domain.registry.request.Action.Method.POST; + +import com.google.appengine.api.LifecycleManager; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.common.base.Throwables; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.dns.DnsConstants.TargetType; +import com.google.domain.registry.dns.writer.api.DnsWriter; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.DomainNameUtils; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.Duration; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +import javax.inject.Inject; +import javax.inject.Provider; + +/** Task that consumes pull-queue for zone updates to write to the DNS server. */ +@Action(path = "/_dr/task/writeDns", method = POST, automaticallyPrintOk = true) +public final class WriteDnsTask implements Runnable, Callable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject DnsQueue dnsQueue; + @Inject Provider writerProvider; + @Inject @Config("dnsWriteLockTimeout") Duration timeout; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject WriteDnsTask() {} + + /** Runs the task. */ + @Override + public void run() { + String lockName = String.format("DNS zone %s", tld); + executeWithLocks(this, getClass(), tld, timeout, lockName); + } + + /** Runs the task, with the lock. */ + @Override + public Void call() { + processBatch(); + return null; + } + + /** Leases a batch of tasks tagged with the zone name from the pull queue and processes them. */ + private void processBatch() { + if (LifecycleManager.getInstance().isShuttingDown()) { + logger.infofmt("%s: lifecycle manager is shutting down", tld); + return; + } + if (Registry.get(tld).getDnsPaused()) { + logger.infofmt("%s: the dns-pull queue is paused", tld); + return; + } + // Make a defensive copy to allow mutations. + List tasks = new ArrayList<>(dnsQueue.leaseTasks(tld)); + if (tasks.isEmpty()) { + logger.infofmt("%s: no tasks in the dns-pull queue", tld); + return; + } + try (DnsWriter writer = writerProvider.get()) { + Iterator it = tasks.iterator(); + while (it.hasNext()) { + TaskHandle task = it.next(); + try { + processTask(writer, task, tld); + } catch (UnsupportedOperationException e) { + // Handle fatal errors by deleting the task. + logger.severefmt(e, "%s: deleting unsupported task %s", tld, task.toString()); + dnsQueue.deleteTask(task); + it.remove(); + } + } + } catch (RuntimeException e) { + Throwables.propagateIfInstanceOf(e, HttpException.class); + // Handle transient errors by dropping the task leases. + logger.severefmt(e, "%s: dropping leases of failed tasks", tld); + for (TaskHandle task : tasks) { + dnsQueue.dropTaskLease(task); + } + return; + } + for (TaskHandle task : tasks) { + dnsQueue.deleteTask(task); + } + logger.infofmt("%s: batch of %s tasks processed", tld, tasks.size()); + } + + /** Stages a write to authoritative DNS for this task. */ + private static void processTask(DnsWriter writer, TaskHandle task, String tld) { + Map params = new HashMap<>(); + try { + for (Map.Entry entry : task.extractParams()) { + params.put(entry.getKey(), entry.getValue()); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + TargetType type = TargetType.valueOf(params.get(DNS_TARGET_TYPE_PARAM)); + String name = checkNotNull(params.get(DNS_TARGET_NAME_PARAM)); + switch (type) { + case DOMAIN: + checkRequestArgument( + DomainNameUtils.isUnder(InternetDomainName.from(name), InternetDomainName.from(tld)), + "domain name %s is not under tld %s", name, tld); + writer.publishDomain(name); + break; + case HOST: + checkRequestArgument( + DomainNameUtils.isUnder(InternetDomainName.from(name), InternetDomainName.from(tld)), + "host name %s is not under tld %s", name, tld); + writer.publishHost(name); + break; + default: + // TODO(b/11592394): Write a full zone. + throw new UnsupportedOperationException(String.format("unexpected Type: %s", type)); + } + } + + private static void checkRequestArgument(boolean condition, String format, Object... args) { + if (!condition) { + throw new BadRequestException(String.format(format, args)); + } + } +} diff --git a/java/com/google/domain/registry/dns/writer/api/BUILD b/java/com/google/domain/registry/dns/writer/api/BUILD new file mode 100644 index 000000000..cf8e2df78 --- /dev/null +++ b/java/com/google/domain/registry/dns/writer/api/BUILD @@ -0,0 +1,15 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "api", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + ], +) diff --git a/java/com/google/domain/registry/dns/writer/api/DnsWriter.java b/java/com/google/domain/registry/dns/writer/api/DnsWriter.java new file mode 100644 index 000000000..6b1487f20 --- /dev/null +++ b/java/com/google/domain/registry/dns/writer/api/DnsWriter.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns.writer.api; + +/** + * Transaction object for sending an atomic batch of updates for a single zone to the DNS server. + * + *

Here's an example of how you would publish updates for a domain and host: + *

+ * @Inject Provider<DnsWriter> dnsWriter;
+ * try (DnsWriter writer = dnsWriter.get()) {
+ *   writer.publishDomain(domainName);
+ *   writer.publishHost(hostName);
+ * }
+ * 
+ */ +public interface DnsWriter extends AutoCloseable { + + /** + * Loads {@code domainName} from datastore and publishes its NS/DS records to the DNS server. + * + * @param domainName the fully qualified domain name + */ + void publishDomain(String domainName); + + /** + * Loads {@code hostName} from datastore and publishes its A/AAAA glue records to the DNS server. + * + * @param hostName the fully qualified host name + */ + void publishHost(String hostName); + + /** Commits the updates to the DNS server atomically. */ + @Override + void close(); +} diff --git a/java/com/google/domain/registry/dns/writer/api/DnsWriterZone.java b/java/com/google/domain/registry/dns/writer/api/DnsWriterZone.java new file mode 100644 index 000000000..9fe0def10 --- /dev/null +++ b/java/com/google/domain/registry/dns/writer/api/DnsWriterZone.java @@ -0,0 +1,24 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns.writer.api; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** Dagger qualifier for the fully-qualified zone name that's being updated. */ +@Qualifier +@Documented +public @interface DnsWriterZone {} diff --git a/java/com/google/domain/registry/dns/writer/api/VoidDnsWriter.java b/java/com/google/domain/registry/dns/writer/api/VoidDnsWriter.java new file mode 100644 index 000000000..17a7f739b --- /dev/null +++ b/java/com/google/domain/registry/dns/writer/api/VoidDnsWriter.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns.writer.api; + +import com.google.common.base.Joiner; + +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + +/** + * {@link DnsWriter} that doesn't actually update records in a DNS server. + * + *

All this class does is write its displeasure to the logs. + */ +public final class VoidDnsWriter implements DnsWriter { + + private static final Logger logger = Logger.getLogger(VoidDnsWriter.class.getName()); + + private final Set names = new HashSet<>(); + + @Override + public void publishDomain(String domainName) { + names.add(domainName); + } + + @Override + public void publishHost(String hostName) { + names.add(hostName); + } + + @Override + public void close() { + logger.warning("Ignoring DNS zone updates! No DnsWriterFactory implementation specified!\n" + + Joiner.on('\n').join(names)); + } +} diff --git a/java/com/google/domain/registry/dns/writer/api/VoidDnsWriterModule.java b/java/com/google/domain/registry/dns/writer/api/VoidDnsWriterModule.java new file mode 100644 index 000000000..0567da819 --- /dev/null +++ b/java/com/google/domain/registry/dns/writer/api/VoidDnsWriterModule.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.dns.writer.api; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module that disables DNS updates. */ +@Module +public final class VoidDnsWriterModule { + + @Provides + static DnsWriter provideDnsWriter() { + return new VoidDnsWriter(); + } +} diff --git a/java/com/google/domain/registry/env/BUILD b/java/com/google/domain/registry/env/BUILD new file mode 100644 index 000000000..17f9f5013 --- /dev/null +++ b/java/com/google/domain/registry/env/BUILD @@ -0,0 +1,4 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + diff --git a/java/com/google/domain/registry/env/common/BUILD b/java/com/google/domain/registry/env/common/BUILD new file mode 100644 index 000000000..304557a76 --- /dev/null +++ b/java/com/google/domain/registry/env/common/BUILD @@ -0,0 +1,5 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + diff --git a/java/com/google/domain/registry/env/common/META-INF/appengine-application.xml b/java/com/google/domain/registry/env/common/META-INF/appengine-application.xml new file mode 100644 index 000000000..80e311d68 --- /dev/null +++ b/java/com/google/domain/registry/env/common/META-INF/appengine-application.xml @@ -0,0 +1,4 @@ + + + domain-registry + diff --git a/java/com/google/domain/registry/env/common/META-INF/application.xml b/java/com/google/domain/registry/env/common/META-INF/application.xml new file mode 100644 index 000000000..485557063 --- /dev/null +++ b/java/com/google/domain/registry/env/common/META-INF/application.xml @@ -0,0 +1,34 @@ + + + + + Google Registry + Google Registry + + + + + + default + default + + + + + backend + backend + + + + + tools + tools + + + diff --git a/java/com/google/domain/registry/env/common/backend/BUILD b/java/com/google/domain/registry/env/common/backend/BUILD new file mode 100644 index 000000000..c1c5eb0e3 --- /dev/null +++ b/java/com/google/domain/registry/env/common/backend/BUILD @@ -0,0 +1,7 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + +exports_files(glob(["WEB-INF/*"])) + + diff --git a/java/com/google/domain/registry/env/common/backend/WEB-INF/logging.properties b/java/com/google/domain/registry/env/common/backend/WEB-INF/logging.properties new file mode 100644 index 000000000..064aa4905 --- /dev/null +++ b/java/com/google/domain/registry/env/common/backend/WEB-INF/logging.properties @@ -0,0 +1,13 @@ +# A default java.util.logging configuration. +# (All App Engine logging is through java.util.logging by default). +# +# To use this configuration, copy it into your application's WEB-INF +# folder and add the following to your appengine-web.xml: +# +# +# +# +# + +# Set the default logging level for all loggers to INFO. +.level = INFO diff --git a/java/com/google/domain/registry/env/common/backend/WEB-INF/web.xml b/java/com/google/domain/registry/env/common/backend/WEB-INF/web.xml new file mode 100644 index 000000000..2af431f57 --- /dev/null +++ b/java/com/google/domain/registry/env/common/backend/WEB-INF/web.xml @@ -0,0 +1,499 @@ + + + + + + + + + Responsible for scanning the database to create a full deposit for a single TLD + and streaming it to cloud storage. Requests are sent here by App Engine after + `RdeCreateCronServlet` enqueues a task specifying a URL that points to this servlet. + + RDE Staging Task + rdeStagingTask + com.google.domain.registry.module.backend.BackendServlet + + + rdeStagingTask + /_dr/task/rdeStaging + + + + + Once `rdeCreateFullCron` finishes writing a deposit file to cloud storage, it'll + launch this task with the cloud filename so it can be uploaded to Iron Mountain + via SFTP. The file is deleted once the upload completes. This should be run via + `rde-upload-backend`. + + RDE Upload Task + rdeUploadTask + com.google.domain.registry.module.backend.BackendServlet + + + rdeUploadTask + /_dr/task/rdeUpload + + + + + Sends an XML RDE report to ICANN's HTTP server after rdeUploadTask finishes. + + RDE Report Task + rdeReportTask + com.google.domain.registry.module.backend.BackendServlet + + + rdeReportTask + /_dr/task/rdeReport + + + + + Bulk Registration Data Access. This task creates a thin escrow deposit + and saves it to cloud storage, where a separate script owned by the SREs + uploads it to ICANN. + + BRDA Copy Task + brdaCopyTask + com.google.domain.registry.module.backend.BackendServlet + + + brdaCopyTask + /_dr/task/brdaCopy + + + + + + Downloads TMCH DNL data from MarksDB. + DNL Downloader + tmchDnl + com.google.domain.registry.module.backend.BackendServlet + + + tmchDnl + /_dr/task/tmchDnl + + + + Downloads TMCH SMDRL data from MarksDB. + SMDRL Downloader + tmchSmdrl + com.google.domain.registry.module.backend.BackendServlet + + + tmchSmdrl + /_dr/task/tmchSmdrl + + + + Downloads TMCH CRL data from MarksDB. + CRL Downloader + tmchCrl + com.google.domain.registry.module.backend.BackendServlet + + + tmchCrl + /_dr/task/tmchCrl + + + + + Reads the LORDN queues and uploads CSV data for sunrise and claims marks to MarksDB. + + NORDN Upload Task + nordnUploadTask + com.google.domain.registry.module.backend.BackendServlet + + + nordnUploadTask + /_dr/task/nordnUpload + + + + Verifies upload of LORDN data to MarksDB. + NORDN Verify Task + nordnVerifyTask + com.google.domain.registry.module.backend.BackendServlet + + + nordnVerifyTask + /_dr/task/nordnVerify + + + + + Write DNS updates. + WriteDnsServlet + writeDns + com.google.domain.registry.module.backend.BackendServlet + + + writeDns + /_dr/task/writeDns + + + + + Read the DNS push and pull queues and kick off the appropriate tasks to update zone. + Read DNS Queue + readDnsQueue + com.google.domain.registry.module.backend.BackendServlet + + + readDnsQueue + /_dr/cron/readDnsQueue + + + + Publish DNS updates. + Publish DNS Updates + publishDnsUpdates + com.google.domain.registry.module.backend.BackendServlet + + + publishDnsUpdates + /_dr/task/publishDnsUpdates + + + + + Endpoint to manually refresh DNS information. + + DNS Refresh + dns-refresh + com.google.domain.registry.module.backend.BackendServlet + 1 + + + dns-refresh + /_dr/dnsRefresh + + + + Export a datastore backup snapshot to GCS. + Export snapshot to GCS + exportSnapshot + com.google.domain.registry.export.ExportSnapshotServlet + + + exportSnapshot + /_dr/task/exportSnapshot + + + + Check the completion of a datastore backup snapshot. + Check on snapshot status + checkSnapshot + com.google.domain.registry.export.CheckSnapshotServlet + + + checkSnapshot + /_dr/task/checkSnapshot + + + + Load a datastore backup snapshot into BigQuery. + Load snapshot into BigQuery + loadSnapshot + com.google.domain.registry.export.LoadSnapshotServlet + + + loadSnapshot + /_dr/task/loadSnapshot + + + + Update a view to point at a certain snapshot in BigQuery. + Update snapshot view in BigQuery + updateSnapshotView + com.google.domain.registry.export.UpdateSnapshotViewServlet + + + updateSnapshotView + /_dr/task/updateSnapshotView + + + + Polls state of jobs in Bigquery + Bigquery Job Poll Task + poll-bigquery-job + com.google.domain.registry.module.backend.BackendServlet + + + poll-bigquery-job + /_dr/task/pollBigqueryJob + + + + Fan out a cron task over an adjustable range of TLDs. + TLD Cron Fanout + tld-fanout + com.google.domain.registry.module.backend.BackendServlet + + + tld-fanout + /_dr/cron/fanout + + + + + + Fan out a cron task over all commit log buckets. + Commit Log Bucket Cron Fanout + commit-log-fanout + com.google.domain.registry.module.backend.BackendServlet + + + commit-log-fanout + /_dr/cron/commitLogFanout + + + + Deletes old commit logs from datastore. + Delete Old Commit Logs + delete-commits + com.google.domain.registry.module.backend.BackendServlet + + + delete-commits + /_dr/task/deleteOldCommitLogs + + + + Checkpoint commit logs. + checkpoint-commit-logs + com.google.domain.registry.module.backend.BackendServlet + + + checkpoint-commit-logs + /_dr/cron/commitLogCheckpoint + + + + Export commit log diff. + export-commit-log-diff + com.google.domain.registry.module.backend.BackendServlet + + + export-commit-log-diff + /_dr/task/exportCommitLogDiff + + + + Delete EppResources, children, and indices. + kill-epp-resources + com.google.domain.registry.module.backend.BackendServlet + + + kill-epp-resources + /_dr/task/killAllEppResources + + + + Restore commit logs. + restore-commit-logs + com.google.domain.registry.module.backend.BackendServlet + + + restore-commit-logs + /_dr/task/restoreCommitLogs + + + + Delete commit logs. + kill-commit-logs + com.google.domain.registry.module.backend.BackendServlet + + + kill-commit-logs + /_dr/task/killCommitLogs + + + + + mapreduce + com.google.appengine.tools.mapreduce.MapReduceServlet + + + mapreduce + /_dr/mapreduce/* + + + + + pipeline + com.google.appengine.tools.pipeline.impl.servlets.PipelineServlet + + + pipeline + /_ah/pipeline/* + + + + + sync-registrars-sheet + com.google.domain.registry.module.backend.BackendServlet + + + sync-registrars-sheet + /_dr/task/syncRegistrarsSheet + + + + + export-reserved-terms + com.google.domain.registry.module.backend.BackendServlet + + + export-reserved-terms + /_dr/task/exportReservedTerms + + + + + sync-group-members + com.google.domain.registry.module.backend.BackendServlet + + + sync-group-members + /_dr/task/syncGroupMembers + + + + + + Deletes the specified contact resource if it is not referenced by any domains. + + Delete Contact Resource + delete-contact-resource + com.google.domain.registry.module.backend.BackendServlet + 1 + + + delete-contact-resource + /_dr/task/deleteContactResource + + + + + + Deletes the specified host resource if it is not referenced by any domains. + + Delete Host Resource + delete-host-resource + com.google.domain.registry.module.backend.BackendServlet + 1 + + + delete-host-resource + /_dr/task/deleteHostResource + + + + + + Enqueues DNS update tasks following a host rename + + DNS Refresh For Host Rename + dns-refresh-for-host-rename + com.google.domain.registry.module.backend.BackendServlet + 1 + + + dns-refresh-for-host-rename + /_dr/task/dnsRefreshForHostRename + + + + + + Internal + + Any request path starting with `/_dr/` will be restricted to requests originating + from the backend or by anyone authenticated to a Google account that's listed in + the AppEngine control panel settings for this project as a Viewer/Owner/Developer. + The `_dr` is short for Domain Registry to follow AppEngine naming conventions. + + /_dr/* + + + admin + + + CONFIDENTIAL + + + + + + + Secure + + Require encryption for all paths. http URLs will be redirected to https. + + /* + + + CONFIDENTIAL + + + + + + + Internal + + Go home rogue registrar! + + /registrar* + + + admin + + + CONFIDENTIAL + + + + + + + + Internal + No soup for you! + /assets/sources/* + + + admin + + + CONFIDENTIAL + + + + + + ObjectifyFilter + com.googlecode.objectify.ObjectifyFilter + + + ObjectifyFilter + /* + + + + + OfyFilter + com.google.domain.registry.model.ofy.OfyFilter + + + OfyFilter + /* + + + diff --git a/java/com/google/domain/registry/env/common/default/BUILD b/java/com/google/domain/registry/env/common/default/BUILD new file mode 100644 index 000000000..c1c5eb0e3 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/BUILD @@ -0,0 +1,7 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + +exports_files(glob(["WEB-INF/*"])) + + diff --git a/java/com/google/domain/registry/env/common/default/WEB-INF/datastore-indexes.xml b/java/com/google/domain/registry/env/common/default/WEB-INF/datastore-indexes.xml new file mode 100644 index 000000000..7fcad1d41 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/WEB-INF/datastore-indexes.xml @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com/google/domain/registry/env/common/default/WEB-INF/dos.xml b/java/com/google/domain/registry/env/common/default/WEB-INF/dos.xml new file mode 100644 index 000000000..14af3ba15 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/WEB-INF/dos.xml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/java/com/google/domain/registry/env/common/default/WEB-INF/logging.properties b/java/com/google/domain/registry/env/common/default/WEB-INF/logging.properties new file mode 100644 index 000000000..064aa4905 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/WEB-INF/logging.properties @@ -0,0 +1,13 @@ +# A default java.util.logging configuration. +# (All App Engine logging is through java.util.logging by default). +# +# To use this configuration, copy it into your application's WEB-INF +# folder and add the following to your appengine-web.xml: +# +# +# +# +# + +# Set the default logging level for all loggers to INFO. +.level = INFO diff --git a/java/com/google/domain/registry/env/common/default/WEB-INF/queue.xml b/java/com/google/domain/registry/env/common/default/WEB-INF/queue.xml new file mode 100644 index 000000000..f7c1601e3 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/WEB-INF/queue.xml @@ -0,0 +1,288 @@ + + + + + default + 1/s + 5 + + + + dns-cron + + 10/s + 100 + + 1 + + + + + dns-pull + pull + + + + dns-publish + 100/s + 100 + + + + export + 10/s + 100 + + 1 + + + + + + flows-async + + 1/m + + backend + + + + delete-commits + 10/s + 100 + + 1 + + + + + export-commits + 10/s + 100 + + + 1 + 60 + + + + + + + export-reserved-terms + 1/s + 100 + + 3 + + + + + + group-members-sync + 1/s + 100 + + 3 + + + + + + export-bigquery-poll + + 5/s + 5 + 5 + + + 20 + 300 + 2 + + + + + + export-snapshot + 5/m + + + 22h + + 300 + 1800 + 10 + + + + + + export-snapshot-poll + 5/m + + + 22h + + 60 + 300 + + + + + + export-snapshot-update-view + 1/s + + + 22h + + 10 + 60 + 10 + + + + + mail + 5/m + 10 + + + + rde-upload + 1/m + 1 + + 4h + + + + + rde-report + 1/s + 1 + + 4h + + + + + rde-staging + 1/m + 10 + + 4h + + + + + brda + 1/m + 10 + + 23h + + + + + + + marksdb + 1/m + 1 + + 11h + + + + + + nordn + 1/s + 10 + + 11h + + + + + + lordn-claims + pull + + + + + lordn-sunrise + pull + + + + + mapreduce + + 500/s + 100 + + + + + sheet + 1/s + + + 1h + + + + + + bigquery-streaming-metrics + 500/s + 500 + + 1 + 1m + + + + + load0 + 500/s + 500 + + + + load1 + 500/s + 500 + + + + load2 + 500/s + 500 + + + + load3 + 500/s + 500 + + + + load4 + 500/s + 500 + + + diff --git a/java/com/google/domain/registry/env/common/default/WEB-INF/web.xml b/java/com/google/domain/registry/env/common/default/WEB-INF/web.xml new file mode 100644 index 000000000..a51046c31 --- /dev/null +++ b/java/com/google/domain/registry/env/common/default/WEB-INF/web.xml @@ -0,0 +1,375 @@ + + + + + + This is the primary EPP endpoint for the Registry. It accepts + EPP XHRs from our TLS proxy. + + EPP + epp + com.google.domain.registry.flows.EppTlsServlet + 1 + + + epp + /_dr/epp + + + + + + Registrar Console UI servlet. + + Registrar Console UI + registrar-ui + com.google.domain.registry.ui.server.registrar.ConsoleUiServlet + 1 + + + registrar-ui + /registrar + + + + + Registrar Console XHR servlet. Accepts EPP XHRs from GAE GAIA-authenticated frontend sessions. + + Registrar Console XHR + registrar-xhr + com.google.domain.registry.flows.EppConsoleServlet + 1 + + + registrar-xhr + /registrar-xhr + + + + Registrar Self-serve Settings + registrar-settings + com.google.domain.registry.ui.server.registrar.RegistrarServlet + 1 + + + registrar-settings + /registrar-settings + + + + Registrar Braintree Payment Form Setup + registrar-payment-setup + com.google.domain.registry.module.frontend.FrontendServlet + 1 + + + registrar-payment-setup + /registrar-payment-setup + + + + Registrar Braintree Payment + registrar-payment + com.google.domain.registry.module.frontend.FrontendServlet + 1 + + + registrar-payment + /registrar-payment + + + + + Admin UI Servlet + admin-ui + com.google.domain.registry.ui.server.admin.AdminUiServlet + 1 + + + admin-ui + /_dr/admin + + + + Registry Admin + registry-admin + com.google.domain.registry.ui.server.admin.RegistryServlet + 1 + + + registry-admin + /_dr/admin/registry/* + + + + Registrar Admin + registrar-admin + com.google.domain.registry.ui.server.admin.RegistrarServlet + 1 + + + registrar-admin + /_dr/admin/registrar/* + + + + + + HTTP WHOIS API. + + WHOIS + whois + com.google.domain.registry.module.frontend.FrontendServlet + 1 + + + whois + /whois/* + + + + + WHOIS Protocol API. + + WHOIS Protocol + whois-protocol + com.google.domain.registry.module.frontend.FrontendServlet + 1 + + + whois-protocol + /_dr/whois + + + + + + RDAP API. + + RDAP + rdap + com.google.domain.registry.module.frontend.FrontendServlet + 1 + + + rdap + /rdap/* + + + + + + Availability Check API. + + Availability Check + check + com.google.domain.registry.ui.server.api.CheckApiServlet + 1 + + + check + /check + + + + + metrics + com.google.domain.registry.monitoring.whitebox.MetricsTaskServlet + + + metrics + /_dr/task/metrics + + + + + + Internal + + Any request path starting with `/_dr/` will be restricted to requests originating + from the backend or by anyone authenticated to a Google account that's listed in + the AppEngine control panel settings for this project as a Viewer/Owner/Developer. + The `_dr` is short for Domain Registry to follow AppEngine naming conventions. + + /_dr/* + + + admin + + + + + profile-registrar-xhr + + Only allow logged-in users to even try to issue EPP commands. This is an additional + layer of safety on top of in-servlet authentication and XSRF protection. + + /registrar-xhr + + + * + + + + + profile-registrar-settings + + Only allow logged-in users to even try to change registrar settings. This is an additional + layer of safety on top of in-servlet authentication and XSRF protection. + + /registrar-settings + + + * + + + + + profile-registrar-payment + + Only allow logged-in users to even try to change registrar settings. This is an additional + layer of safety on top of in-servlet authentication and XSRF protection. + + /registrar-payment + + + * + + + + + profile-registrar-payment-token + + Only allow logged-in users to even try to change registrar settings. This is an additional + layer of safety on top of in-servlet authentication and XSRF protection. + + /registrar-payment-token + + + * + + + + + + + Secure + + Require encryption for all paths. http URLs will be redirected to https. + + /* + + + CONFIDENTIAL + + + + + + + + internal-sources + No soup for you! + /assets/sources/* + + + admin + + + + + + + admin-bin-js-map + No soup for you! + /assets/js/admin_bin.js.map + + + admin + + + + + admin-dbg-js + No soup for you! + /assets/js/admin_dbg.js + + + admin + + + + + registrar-bin-js-map + No soup for you! + /assets/js/registrar_bin.js.map + + + admin + + + + + registrar-dbg-js + No soup for you! + /assets/js/registrar_dbg.js + + + admin + + + + + brain-bin-js-map + No soup for you! + /assets/js/brain_bin.js.map + + + admin + + + + + admin-dbg-css + No soup for you! + /assets/css/admin_dbg.css + + + admin + + + + + registrar-dbg-css + No soup for you! + /assets/css/registrar_dbg.css + + + admin + + + + + + ObjectifyFilter + com.googlecode.objectify.ObjectifyFilter + + + ObjectifyFilter + /* + + + + + OfyFilter + com.google.domain.registry.model.ofy.OfyFilter + + + OfyFilter + /* + + + diff --git a/java/com/google/domain/registry/env/common/tools/BUILD b/java/com/google/domain/registry/env/common/tools/BUILD new file mode 100644 index 000000000..c1c5eb0e3 --- /dev/null +++ b/java/com/google/domain/registry/env/common/tools/BUILD @@ -0,0 +1,7 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + +exports_files(glob(["WEB-INF/*"])) + + diff --git a/java/com/google/domain/registry/env/common/tools/WEB-INF/logging.properties b/java/com/google/domain/registry/env/common/tools/WEB-INF/logging.properties new file mode 100644 index 000000000..064aa4905 --- /dev/null +++ b/java/com/google/domain/registry/env/common/tools/WEB-INF/logging.properties @@ -0,0 +1,13 @@ +# A default java.util.logging configuration. +# (All App Engine logging is through java.util.logging by default). +# +# To use this configuration, copy it into your application's WEB-INF +# folder and add the following to your appengine-web.xml: +# +# +# +# +# + +# Set the default logging level for all loggers to INFO. +.level = INFO diff --git a/java/com/google/domain/registry/env/common/tools/WEB-INF/web.xml b/java/com/google/domain/registry/env/common/tools/WEB-INF/web.xml new file mode 100644 index 000000000..c170c6aac --- /dev/null +++ b/java/com/google/domain/registry/env/common/tools/WEB-INF/web.xml @@ -0,0 +1,284 @@ + + + + + + Verify OTE + verify-ote + com.google.domain.registry.ui.server.admin.VerifyOteServlet + 1 + + + verify-ote + /_dr/admin/verifyOte + + + + Create Groups for Registrar + create-groups + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + create-groups + /_dr/admin/createGroups + + + + Create Premium List + create-premium-list + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + create-premium-list + /_dr/admin/createPremiumList + + + + List Entities + list-entities + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + list-entities + /_dr/admin/list/* + + + + Delete Entity + delete-entity + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + delete-entity + /_dr/admin/deleteEntity + + + + Update Premium List + update-premium-list + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + update-premium-list + /_dr/admin/updatePremiumList + + + + Backend endpoint to initate loadtests. + Load Test + loadtest + com.google.domain.registry.module.tools.ToolsServlet + + + loadtest + /_dr/loadtest + + + + + Remote API Servlet + RemoteApiServlet + com.google.apphosting.utils.remoteapi.RemoteApiServlet + 1 + + + RemoteApiServlet + /remote_api + + + + + + Execute epp from the registry tool. + + Registry tool EPP endpoint + epptool + com.google.domain.registry.flows.EppToolServlet + 1 + + + epptool + /_dr/epptool + + + + + + Deletes all billing events, history entries, domains, poll messages, foreign key indexes, and eCatcher entities in prober namespaces. + + Delete Prober Data Mapreduce + delete-prober-data + + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + delete-prober-data + /_dr/task/deleteProberData + + + + + + Deletes entities in non-default namespaces. + + Annihilate Non-Default Namespaces Mapreduce + annihilate-non-default-namespaces + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + annihilate-non-default-namespaces + /_dr/task/annihilateNonDefaultNamespaces + + + + + + Re-saves all EppResources. + + Re-Save All EPP Resources + resave-all-eppresources + com.google.domain.registry.module.tools.ToolsServlet + 1 + + + resave-all-eppresources + /_dr/task/resaveAllEppResources + + + + + mapreduce + com.google.appengine.tools.mapreduce.MapReduceServlet + + + mapreduce + /_dr/mapreduce/* + + + + + pipeline + com.google.appengine.tools.pipeline.impl.servlets.PipelineServlet + + + pipeline + /_ah/pipeline/* + + + + + publish-detail-report + com.google.domain.registry.module.tools.ToolsServlet + + + publish-detail-report + /_dr/publishDetailReport + + + + generate-zone-files + com.google.domain.registry.module.tools.ToolsServlet + + + generate-zone-files + /_dr/task/generateZoneFiles + + + + + + Internal + + Any request path starting with `/_dr/` will be restricted to requests originating + from the backend or by anyone authenticated to a Google account that's listed in + the AppEngine control panel settings for this project as a Viewer/Owner/Developer. + The `_dr` is short for Domain Registry to follow AppEngine naming conventions. + + /_dr/* + + + admin + + + CONFIDENTIAL + + + + + + + Secure + + Require encryption for all paths. http URLs will be redirected to https. + + /* + + + CONFIDENTIAL + + + + + + + Internal + + Go home rogue registrar! + + /registrar* + + + admin + + + CONFIDENTIAL + + + + + + + + Internal + No soup for you! + /assets/sources/* + + + admin + + + CONFIDENTIAL + + + + + + ObjectifyFilter + com.googlecode.objectify.ObjectifyFilter + + + ObjectifyFilter + /* + + + + + OfyFilter + com.google.domain.registry.model.ofy.OfyFilter + + + OfyFilter + /* + + + diff --git a/java/com/google/domain/registry/env/production/BUILD b/java/com/google/domain/registry/env/production/BUILD new file mode 100644 index 000000000..17f9f5013 --- /dev/null +++ b/java/com/google/domain/registry/env/production/BUILD @@ -0,0 +1,4 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + diff --git a/java/com/google/domain/registry/env/production/backend/BUILD b/java/com/google/domain/registry/env/production/backend/BUILD new file mode 100644 index 000000000..304557a76 --- /dev/null +++ b/java/com/google/domain/registry/env/production/backend/BUILD @@ -0,0 +1,5 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + diff --git a/java/com/google/domain/registry/env/production/backend/WEB-INF/appengine-web.xml b/java/com/google/domain/registry/env/production/backend/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..f1c19a1db --- /dev/null +++ b/java/com/google/domain/registry/env/production/backend/WEB-INF/appengine-web.xml @@ -0,0 +1,33 @@ + + + + domain-registry + 1 + backend + true + true + B4_1G + + 50 + 10m + + + + + + + + + + + + + + + + + + + diff --git a/java/com/google/domain/registry/env/production/default/BUILD b/java/com/google/domain/registry/env/production/default/BUILD new file mode 100644 index 000000000..304557a76 --- /dev/null +++ b/java/com/google/domain/registry/env/production/default/BUILD @@ -0,0 +1,5 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + diff --git a/java/com/google/domain/registry/env/production/default/WEB-INF/appengine-web.xml b/java/com/google/domain/registry/env/production/default/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..bd46ddc34 --- /dev/null +++ b/java/com/google/domain/registry/env/production/default/WEB-INF/appengine-web.xml @@ -0,0 +1,34 @@ + + + + domain-registry + 1 + default + true + true + B4_1G + + 50 + 10m + + + + + + + + + + + + + + + + + + + + diff --git a/java/com/google/domain/registry/env/production/default/WEB-INF/cron.xml b/java/com/google/domain/registry/env/production/default/WEB-INF/cron.xml new file mode 100644 index 000000000..601912cbc --- /dev/null +++ b/java/com/google/domain/registry/env/production/default/WEB-INF/cron.xml @@ -0,0 +1,193 @@ + + + + + + + /_dr/task/rdeStaging + + This job generates a full RDE escrow deposit as a single gigantic XML document + and streams it to cloud storage. When this job has finished successfully, it'll + launch a separate task that uploads the deposit file to Iron Mountain via SFTP. + + + every 4 hours from 00:07 to 20:00 + backend + + + + + + This job is a no-op unless RdeUploadCursor falls behind for some reason. + + every 4 hours synchronized + backend + + + + + + This job is a no-op unless RdeReportCursor falls behind for some reason. + + every 4 hours synchronized + backend + + + + + + This job downloads the latest DNL from MarksDB and inserts it into the database. + (See: TmchDnlServlet, ClaimsList) + + every 12 hours synchronized + backend + + + + + + This job downloads the latest SMDRL from MarksDB and inserts it into the database. + (See: TmchSmdrlServlet, SignedMarkRevocationList) + + every 12 hours synchronized + backend + + + + + + This job downloads the latest CRL from MarksDB and inserts it into the database. + (See: TmchCrlServlet) + + every 12 hours synchronized + backend + + + + + + Syncs RegistrarContact changes in the past hour to Google Groups. + + every 1 hours synchronized + backend + + + + + + Synchronize Registrar entities to Google Spreadsheets. + + every 1 hours synchronized + backend + + + + + + + + This job checkpoints the commit log buckets and exports the diff since last checkpoint to GCS. + + every 1 minutes synchronized + backend + + + + + + This job fires off a datastore backup-as-a-service job that generates snapshot files in GCS. + It also enqueues a new task to wait on the completion of that job and then load the resulting + snapshot into bigquery. + + + every day 06:00 + backend + + + + + + This job uploads LORDN Sunrise CSV files for each TLD to MarksDB. It should be + run at most every three hours, or at absolute minimum every 26 hours. + + + every 12 hours synchronized + UTC + backend + + + + + + This job uploads LORDN Claims CSV files for each TLD to MarksDB. It should be + run at most every three hours, or at absolute minimum every 26 hours. + + + every 12 hours synchronized + UTC + backend + + + + + + This job clears out data from probers and runs once a week. + + every monday 14:00 + UTC + + tools + + + + + + Reserved terms export to Google Drive job for creating once-daily exports. + + every day 05:30 + backend + + + + + + Write updates to the DNS system. Lease tasks from the dns-pull queue until empty. + + every 1 minutes synchronized + backend + + + + diff --git a/java/com/google/domain/registry/env/production/tools/BUILD b/java/com/google/domain/registry/env/production/tools/BUILD new file mode 100644 index 000000000..304557a76 --- /dev/null +++ b/java/com/google/domain/registry/env/production/tools/BUILD @@ -0,0 +1,5 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + diff --git a/java/com/google/domain/registry/env/production/tools/WEB-INF/appengine-web.xml b/java/com/google/domain/registry/env/production/tools/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..a0d77a8a3 --- /dev/null +++ b/java/com/google/domain/registry/env/production/tools/WEB-INF/appengine-web.xml @@ -0,0 +1,33 @@ + + + + domain-registry + 1 + tools + true + true + B4_1G + + 50 + 10m + + + + + + + + + + + + + + + + + + + diff --git a/java/com/google/domain/registry/export/BUILD b/java/com/google/domain/registry/export/BUILD new file mode 100644 index 000000000..2f7dea5c6 --- /dev/null +++ b/java/com/google/domain/registry/export/BUILD @@ -0,0 +1,44 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "export", + srcs = glob(["*.java"]), + deps = [ + "//apiserving/discoverydata/bigquery:bigqueryv2", + "//apiserving/discoverydata/drive", + "//java/com/google/api/client/extensions/appengine/http", + "//java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2", + "//java/com/google/api/client/googleapis/json", + "//java/com/google/api/client/http", + "//java/com/google/api/client/json", + "//java/com/google/api/client/json/jackson2", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/bigquery", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/flows", + "//java/com/google/domain/registry/gcs", + "//java/com/google/domain/registry/groups", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/security:servlets", + "//java/com/google/domain/registry/storage/drive", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_gcs_client", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/export/BigqueryPollJobAction.java b/java/com/google/domain/registry/export/BigqueryPollJobAction.java new file mode 100644 index 000000000..71d32fe62 --- /dev/null +++ b/java/com/google/domain/registry/export/BigqueryPollJobAction.java @@ -0,0 +1,173 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.domain.registry.bigquery.BigqueryUtils.toJobReferenceString; + +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.model.Job; +import com.google.api.services.bigquery.model.JobReference; +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Header; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotModifiedException; +import com.google.domain.registry.request.Payload; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.TaskEnqueuer; + +import dagger.Lazy; + +import org.joda.time.Duration; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import javax.inject.Inject; + +/** + * An action which polls the state of a bigquery job. If it is completed then it will log its + * completion state; otherwise it will return a failure code so that the task will be retried. + */ +@Action( + path = BigqueryPollJobAction.PATH, + method = {Action.Method.GET, Action.Method.POST}, + automaticallyPrintOk = true) +public class BigqueryPollJobAction implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + static final String QUEUE = "export-bigquery-poll"; // See queue.xml + static final String PATH = "/_dr/task/pollBigqueryJob"; // See web.xml + static final String CHAINED_TASK_QUEUE_HEADER = "X-DomainRegistry-ChainedTaskQueue"; + static final String PROJECT_ID_HEADER = "X-DomainRegistry-ProjectId"; + static final String JOB_ID_HEADER = "X-DomainRegistry-JobId"; + static final Duration POLL_COUNTDOWN = Duration.standardSeconds(20); + + @Inject Bigquery bigquery; + @Inject TaskEnqueuer enqueuer; + @Inject @Header(CHAINED_TASK_QUEUE_HEADER) Lazy chainedQueueName; + @Inject @Header(PROJECT_ID_HEADER) String projectId; + @Inject @Header(JOB_ID_HEADER) String jobId; + @Inject @Payload byte[] payload; + @Inject BigqueryPollJobAction() {} + + @Override + public void run() { + checkJobOutcome(); // Throws a NotModifiedException if the job hasn't completed. + if (payload == null || payload.length == 0) { + return; + } + // If there is a payload, it's a chained task, so enqueue it. + TaskOptions task; + try { + task = (TaskOptions) new ObjectInputStream(new ByteArrayInputStream(payload)).readObject(); + } catch (ClassNotFoundException | IOException e) { + logger.severe(e, e.toString()); + throw new BadRequestException("Cannot deserialize task from payload", e); + } + String taskName = enqueuer.enqueue(getQueue(chainedQueueName.get()), task).getName(); + logger.infofmt( + "Added chained task %s for %s to queue %s: %s", + taskName, + task.getUrl(), + chainedQueueName.get(), + task.toString()); + } + + /** + * Returns true if the provided job succeeded, false if it failed, and throws an exception if it + * is still pending. + */ + private boolean checkJobOutcome() { + Job job = null; + String jobRefString = + toJobReferenceString(new JobReference().setProjectId(projectId).setJobId(jobId)); + + try { + job = bigquery.jobs().get(projectId, jobId).execute(); + } catch (IOException e) { + // We will throw a new exception because done==false, but first log this exception. + logger.warning(e, e.getMessage()); + } + // If job is not yet done, then throw an exception so that we'll return a failing HTTP status + // code and the task will be retried. + if (job == null || !job.getStatus().getState().equals("DONE")) { + throw new NotModifiedException(jobRefString); + } + + // Check if the job ended with an error. + if (job.getStatus().getErrorResult() != null) { + logger.severefmt("Bigquery job failed - %s - %s", jobRefString, job); + return false; + } + logger.infofmt("Bigquery job succeeded - %s", jobRefString); + return true; + } + + + /** Helper class to enqueue a bigquery poll job. */ + public static class BigqueryPollJobEnqueuer { + + private final TaskEnqueuer enqueuer; + + @Inject + BigqueryPollJobEnqueuer(TaskEnqueuer enqueuer) { + this.enqueuer = enqueuer; + } + + /** Enqueue a task to poll for the success or failure of the referenced BigQuery job. */ + public TaskHandle enqueuePollTask(JobReference jobRef) { + return enqueuer.enqueue(getQueue(QUEUE), createCommonPollTask(jobRef).method(Method.GET)); + } + + /** + * Enqueue a task to poll for the success or failure of the referenced BigQuery job and to + * launch the provided task in the specified queue if the job succeeds. + */ + public TaskHandle enqueuePollTask( + JobReference jobRef, TaskOptions chainedTask, Queue chainedTaskQueue) throws IOException { + // Serialize the chainedTask into a byte array to put in the task payload. + ByteArrayOutputStream taskBytes = new ByteArrayOutputStream(); + new ObjectOutputStream(taskBytes).writeObject(chainedTask); + return enqueuer.enqueue( + getQueue(QUEUE), + createCommonPollTask(jobRef) + .method(Method.POST) + .header(CHAINED_TASK_QUEUE_HEADER, chainedTaskQueue.getQueueName()) + .payload(taskBytes.toByteArray())); + } + + /** + * Enqueue a task to poll for the success or failure of the referenced BigQuery job and to + * launch the provided task in the specified queue if the job succeeds. + */ + private static TaskOptions createCommonPollTask(JobReference jobRef) { + // Omit host header so that task will be run on the current backend/module. + return withUrl(PATH) + .countdownMillis(POLL_COUNTDOWN.getMillis()) + .header(PROJECT_ID_HEADER, jobRef.getProjectId()) + .header(JOB_ID_HEADER, jobRef.getJobId()); + } + } +} diff --git a/java/com/google/domain/registry/export/BigquerySchemas.java b/java/com/google/domain/registry/export/BigquerySchemas.java new file mode 100644 index 000000000..82ea87ca5 --- /dev/null +++ b/java/com/google/domain/registry/export/BigquerySchemas.java @@ -0,0 +1,148 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.bigquery.model.TableFieldSchema; +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.bigquery.BigqueryUtils.FieldMode; +import com.google.domain.registry.bigquery.BigqueryUtils.FieldType; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** Helper class which acts as a container for Bigquery table schemas. */ +class BigquerySchemas { + private BigquerySchemas() {} + + /** The fields in the "Logs" table. */ + enum LogsTableField { + + // These fields appear in nested APP_LOG_LINES records. + LOG_LEVEL(FieldType.STRING, FieldMode.NULLABLE), + LOG_MESSAGE(FieldType.STRING, FieldMode.NULLABLE), + TIME(FieldType.TIMESTAMP, FieldMode.NULLABLE), + + // These fields appear in records at top level of the table. + START_TIME(FieldType.TIMESTAMP, FieldMode.NULLABLE), + END_TIME(FieldType.TIMESTAMP, FieldMode.NULLABLE), + RELEASE(FieldType.STRING, FieldMode.NULLABLE), + APPID(FieldType.STRING, FieldMode.NULLABLE), + COST(FieldType.FLOAT, FieldMode.NULLABLE), + EPP_CLIENT_ID(FieldType.STRING, FieldMode.NULLABLE), + EPP_COMMAND(FieldType.STRING, FieldMode.NULLABLE), + EPP_RESULT(FieldType.BOOLEAN, FieldMode.NULLABLE), + EPP_TARGET(FieldType.STRING, FieldMode.REPEATED), + EPP_TLD(FieldType.STRING, FieldMode.NULLABLE), + HOST(FieldType.STRING, FieldMode.NULLABLE), + HTTP_VERSION(FieldType.STRING, FieldMode.NULLABLE), + INSTANCE_KEY(FieldType.STRING, FieldMode.NULLABLE), + IP(FieldType.STRING, FieldMode.NULLABLE), + LATENCY_USEC(FieldType.INTEGER, FieldMode.NULLABLE), + MCYCLES(FieldType.INTEGER, FieldMode.NULLABLE), + METHOD(FieldType.STRING, FieldMode.NULLABLE), + MODULE_ID(FieldType.STRING, FieldMode.NULLABLE), + NICKNAME(FieldType.STRING, FieldMode.NULLABLE), + OFFSET(FieldType.STRING, FieldMode.NULLABLE), + PENDING_TIME_USEC(FieldType.INTEGER, FieldMode.NULLABLE), + REFERRER(FieldType.STRING, FieldMode.NULLABLE), + REPLICA_INDEX(FieldType.INTEGER, FieldMode.NULLABLE), + REQUEST_ID(FieldType.STRING, FieldMode.NULLABLE), + RESOURCE(FieldType.STRING, FieldMode.NULLABLE), + RESPONSE_SIZE(FieldType.INTEGER, FieldMode.NULLABLE), + STATUS(FieldType.INTEGER, FieldMode.NULLABLE), + TASK_NAME(FieldType.STRING, FieldMode.NULLABLE), + TASK_QUEUE_NAME(FieldType.STRING, FieldMode.NULLABLE), + URL_MAP_ENTRY(FieldType.STRING, FieldMode.NULLABLE), + USER_AGENT(FieldType.STRING, FieldMode.NULLABLE), + VERSION_ID(FieldType.STRING, FieldMode.NULLABLE), + APP_LOG_LINES(FieldType.RECORD, FieldMode.REPEATED, + ImmutableList.of(LOG_LEVEL, LOG_MESSAGE, TIME)); + + private final FieldType fieldType; + private final FieldMode fieldMode; + private final ImmutableList childFields; + + LogsTableField(FieldType fieldType, FieldMode fieldMode) { + this(fieldType, fieldMode, ImmutableList.of()); + } + + LogsTableField( + FieldType fieldType, FieldMode fieldMode, ImmutableList childFields) { + this.fieldType = checkNotNull(fieldType); + this.fieldMode = checkNotNull(fieldMode); + this.childFields = checkNotNull(childFields); + } + + /** Return the name of the field as it should appear in the Bigquery schema. */ + String schemaName() { + return UPPER_UNDERSCORE.to(LOWER_UNDERSCORE, name()); + } + + /** Return the {@link TableFieldSchema} of this field for use in a Bigquery table. */ + private TableFieldSchema getTableFieldSchema() { + TableFieldSchema tableFieldSchema = new TableFieldSchema() + .setName(schemaName()) + .setType(fieldType.schemaName()) + .setMode(fieldMode.schemaName()); + if (!childFields.isEmpty()) { + tableFieldSchema.setFields(getSchema(childFields)); + } + return tableFieldSchema; + } + + /** + * Return the schema of a list of {@link TableFieldSchema} objects for use in a Bigquery table. + */ + private static List getSchema(Iterable fields) { + return FluentIterable.from(fields) + .transform(new Function() { + @Override + public TableFieldSchema apply(LogsTableField field) { + return field.getTableFieldSchema(); + }}) + .toList(); + } + + /** + * Return the schema of this table for use in a Bigquery table. + */ + static List getTableSchema() { + List allFields = Arrays.asList(LogsTableField.values()); + + // Collect the list of all child fields so we can exclude them from the list of fields at the + // top level of the schema. + Set childFields = FluentIterable.from(allFields) + .transformAndConcat(new Function>() { + @Override + public List apply(LogsTableField field) { + return field.childFields; + }}) + .toSet(); + + Set topLevelFields = + Sets.difference(ImmutableSet.copyOf(allFields), childFields); + return getSchema(topLevelFields); + } + } +} diff --git a/java/com/google/domain/registry/export/CheckSnapshotServlet.java b/java/com/google/domain/registry/export/CheckSnapshotServlet.java new file mode 100644 index 000000000..a0e2fbde1 --- /dev/null +++ b/java/com/google/domain/registry/export/CheckSnapshotServlet.java @@ -0,0 +1,170 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.html.HtmlEscapers.htmlEscaper; +import static com.google.domain.registry.util.HttpServletUtils.getRequiredParameterValue; +import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.appengine.api.taskqueue.QueueFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.common.net.MediaType; +import com.google.domain.registry.export.DatastoreBackupInfo.BackupStatus; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; + +import org.joda.time.Duration; +import org.joda.time.PeriodType; +import org.joda.time.format.PeriodFormat; + +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Check the status of a snapshot, and if complete, trigger loading it into BigQuery. */ +public class CheckSnapshotServlet extends HttpServlet { + + /** Parameter names for passing parameters into this servlet. */ + static final String SNAPSHOT_NAME_PARAM = "name"; + static final String SNAPSHOT_KINDS_TO_LOAD_PARAM = "kindsToLoad"; + + /** Servlet-specific details needed for enqueuing tasks against itself. */ + static final String QUEUE = "export-snapshot-poll"; // See queue.xml. + static final String PATH = "/_dr/task/checkSnapshot"; // See web.xml. + static final Duration POLL_COUNTDOWN = Duration.standardMinutes(2); + + /** The maximum amount of time we allow a backup to run before abandoning it. */ + static final Duration MAXIMUM_BACKUP_RUNNING_TIME = Duration.standardHours(20); + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static DatastoreBackupService backupService = DatastoreBackupService.get(); + + @NonFinalForTesting + private static LoadSnapshotServlet loadSnapshotServlet = new LoadSnapshotServlet(); + + @Override + public void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + try { + rsp.setStatus(SC_OK); + rsp.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString()); + rsp.getWriter().write("OK\n\n"); + super.service(req, rsp); + } catch (Throwable e) { + logger.severe(e, e.toString()); + rsp.sendError( + e instanceof IllegalArgumentException ? SC_BAD_REQUEST : SC_INTERNAL_SERVER_ERROR, + htmlEscaper().escape(firstNonNull(e.getMessage(), e.toString()))); + } + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + String snapshotName = getRequiredParameterValue(req, SNAPSHOT_NAME_PARAM); + rsp.getWriter().write(backupService.findByName(snapshotName).getInformation()); + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + String snapshotName = getRequiredParameterValue(req, SNAPSHOT_NAME_PARAM); + // TODO(b/19237926): make this non-optional once all new tasks will have this parameter. + String kindsToLoadParam = req.getParameter(SNAPSHOT_KINDS_TO_LOAD_PARAM); + Optional> kindsToLoad = Optional.fromNullable( + kindsToLoadParam == null ? null + : ImmutableSet.copyOf(Splitter.on(',').split(kindsToLoadParam))); + + // Look up the backup by the provided name, stopping if we can't find it. + DatastoreBackupInfo backup; + try { + backup = backupService.findByName(snapshotName); + } catch (IllegalArgumentException e) { + String message = String.format("Bad backup name %s: %s", snapshotName, e.getMessage()); + logger.severe(e, message); + // TODO(b/19081569): Ideally this would return a 2XX error so the task would not be retried, + // but we might abandon backups that start late and haven't yet written to datastore. + // We could fix that by replacing this with a two-phase polling strategy. + rsp.sendError(SC_BAD_REQUEST, htmlEscaper().escape(message)); + return; + } + // Stop now if the backup is not complete. + if (!backup.getStatus().equals(BackupStatus.COMPLETE)) { + Duration runningTime = backup.getRunningTime(); + if (runningTime.isShorterThan(MAXIMUM_BACKUP_RUNNING_TIME)) { + // Backup might still be running, so send a 304 to have the task retry. + rsp.sendError(SC_NOT_MODIFIED, + htmlEscaper().escape(String.format("Datastore backup %s still pending", snapshotName))); + } else { + // Declare the backup a lost cause, and send 202 Accepted so the task will not be retried. + String message = String.format("Datastore backup %s abandoned - not complete after %s", + snapshotName, + PeriodFormat.getDefault().print( + runningTime.toPeriod().normalizedStandard( + PeriodType.dayTime().withMillisRemoved()))); + logger.severe(message); + rsp.sendError(SC_ACCEPTED, htmlEscaper().escape(message)); + } + return; + } + // Get a compact string to identify this snapshot in BigQuery by trying to parse the unique + // suffix out of the snapshot name and falling back to the start time as a string. + String snapshotId = snapshotName.startsWith(ExportSnapshotServlet.SNAPSHOT_PREFIX) + ? snapshotName.substring(ExportSnapshotServlet.SNAPSHOT_PREFIX.length()) + : backup.getStartTime().toString("YYYYMMdd_HHmmss"); + // Log a warning if kindsToLoad is specified and not a subset of the exported snapshot kinds. + if (kindsToLoad.isPresent() && !backup.getKinds().containsAll(kindsToLoad.get())) { + logger.warningfmt("Kinds to load included non-exported kinds: %s", + Sets.difference(kindsToLoad.get(), backup.getKinds())); + } + // Load kinds from the snapshot, limited to those also in kindsToLoad (if it's present). + ImmutableSet exportedKindsToLoad = ImmutableSet.copyOf(kindsToLoad.isPresent() + ? Sets.intersection(backup.getKinds(), kindsToLoad.get()) + : backup.getKinds()); + String message = String.format("Datastore backup %s complete - ", snapshotName); + if (exportedKindsToLoad.isEmpty()) { + message += "no kinds to load into BigQuery"; + } else { + loadSnapshotServlet.enqueueLoadTask( + snapshotId, backup.getGcsFilename().get(), exportedKindsToLoad); + message += "BigQuery load task enqueued"; + } + logger.info(message); + rsp.getWriter().write(message); + } + + /** Enqueue a poll task to monitor the named snapshot for completion. */ + TaskHandle enqueuePollTask(String snapshotName, ImmutableSet kindsToLoad) { + return QueueFactory.getQueue(QUEUE).add( + TaskOptions.Builder.withUrl(PATH) + .method(Method.POST) + .countdownMillis(POLL_COUNTDOWN.getMillis()) + .param(SNAPSHOT_NAME_PARAM, snapshotName) + .param(SNAPSHOT_KINDS_TO_LOAD_PARAM, Joiner.on(',').join(kindsToLoad))); + } +} diff --git a/java/com/google/domain/registry/export/DatastoreBackupInfo.java b/java/com/google/domain/registry/export/DatastoreBackupInfo.java new file mode 100644 index 000000000..c3e4af760 --- /dev/null +++ b/java/com/google/domain/registry/export/DatastoreBackupInfo.java @@ -0,0 +1,150 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.appengine.api.datastore.Entity; +import com.google.appengine.api.datastore.Text; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.Date; +import java.util.List; + +/** Container for information about a datastore backup. */ +public class DatastoreBackupInfo { + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + /** The possible status values for a datastore backup. */ + public enum BackupStatus { PENDING, COMPLETE } + + /** The name of the datastore backup. */ + private final String backupName; + + /** The entity kinds included in this datastore backup. */ + private final ImmutableSet kinds; + + /** The start time of the datastore backup. */ + private final DateTime startTime; + + /** The completion time of the datastore backup, present if it has completed. */ + private final Optional completeTime; + + /** + * The GCS filename to which the backup's top-level .backup_info manifest file has been written, + * present if the backup has completed. + */ + private final Optional gcsFilename; + + /** DatastoreBackupInfo instances should only be obtained via DatastoreBackupService. */ + DatastoreBackupInfo(Entity backupEntity) { + backupName = (String) checkNotNull(backupEntity.getProperty("name"), "name"); + @SuppressWarnings("unchecked") + List rawKinds = (List) checkNotNull(backupEntity.getProperty("kinds"), "kinds"); + Date rawStartTime = (Date) checkNotNull(backupEntity.getProperty("start_time"), "start_time"); + Date rawCompleteTime = (Date) backupEntity.getProperty("complete_time"); + Text rawGcsFilename = (Text) backupEntity.getProperty("gs_handle"); + + kinds = ImmutableSet.copyOf(rawKinds); + startTime = new DateTime(rawStartTime).withZone(UTC); + completeTime = Optional.fromNullable( + rawCompleteTime == null ? null : new DateTime(rawCompleteTime).withZone(UTC)); + gcsFilename = Optional.fromNullable( + rawGcsFilename == null ? null : gcsPathToUri(rawGcsFilename.getValue())); + } + + /** This constructor is only exposed for test purposes. */ + @VisibleForTesting + DatastoreBackupInfo( + String backupName, + DateTime startTime, + Optional completeTime, + ImmutableSet kinds, + Optional gcsFilename) { + this.backupName = backupName; + this.startTime = startTime; + this.completeTime = completeTime; + this.kinds = kinds; + this.gcsFilename = gcsFilename; + } + + /** + * Rewrite a GCS path as stored by Datastore Admin (with a "/gs/" prefix) to the more standard + * URI format that uses a "gs://" scheme prefix. + */ + private static String gcsPathToUri(String backupGcsPath) { + checkArgument(backupGcsPath.startsWith("/gs/"), "GCS path not in expected format"); + return backupGcsPath.replaceFirst("/gs/", "gs://"); + } + + public String getName() { + return backupName; + } + + public ImmutableSet getKinds() { + return kinds; + } + + public BackupStatus getStatus() { + return completeTime.isPresent() ? BackupStatus.COMPLETE : BackupStatus.PENDING; + } + + public DateTime getStartTime() { + return startTime; + } + + public Optional getCompleteTime() { + return completeTime; + } + + /** + * Returns the length of time the backup ran for (if completed) or the length of time since the + * backup started (if it has not completed). + */ + public Duration getRunningTime() { + return new Duration(startTime, completeTime.or(clock.nowUtc())); + } + + public Optional getGcsFilename() { + return gcsFilename; + } + + /** Returns a string version of key information about the backup. */ + public String getInformation() { + return Joiner.on('\n') + .join( + "Backup name: " + backupName, + "Status: " + getStatus(), + "Started: " + startTime, + "Ended: " + completeTime.orNull(), + "Duration: " + getRunningTime().toPeriod().toString().substring(2).toLowerCase(), + "GCS: " + gcsFilename.orNull(), + "Kinds: " + kinds, + ""); + } +} diff --git a/java/com/google/domain/registry/export/DatastoreBackupService.java b/java/com/google/domain/registry/export/DatastoreBackupService.java new file mode 100644 index 000000000..b6eeda043 --- /dev/null +++ b/java/com/google/domain/registry/export/DatastoreBackupService.java @@ -0,0 +1,123 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService; +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.common.base.Strings.nullToEmpty; + +import com.google.appengine.api.datastore.Entity; +import com.google.appengine.api.datastore.Query; +import com.google.appengine.api.modules.ModulesService; +import com.google.appengine.api.modules.ModulesServiceFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.domain.registry.util.NonFinalForTesting; + +import java.util.NoSuchElementException; + +/** An object providing methods for starting and querying datastore backups. */ +public class DatastoreBackupService { + + /** The internal kind name used for entities storing information about datastore backups. */ + static final String BACKUP_INFO_KIND = "_AE_Backup_Information"; + + /** The name of the app version used for hosting the Datastore Admin functionality. */ + static final String DATASTORE_ADMIN_VERSION_NAME = "ah-builtin-python-bundle"; + + @NonFinalForTesting + private static ModulesService modulesService = ModulesServiceFactory.getModulesService(); + + /** + * Returns an instance of this service. + * + *

This method exists to allow for making the service a singleton object if desired at some + * future point; the choice is meaningless right now because the service maintains no state. + * That means its client-facing methods could in theory be static methods, but they are not + * because that makes it difficult to mock this service in clients. + */ + public static DatastoreBackupService get() { + return new DatastoreBackupService(); + } + + /** + * Generates the TaskOptions needed to trigger an AppEngine datastore backup job. + * + * @see "https://developers.google.com/appengine/articles/scheduled_backups" + */ + private static TaskOptions makeTaskOptions( + String queue, String name, String gcsBucket, ImmutableSet kinds) { + String hostname = modulesService.getVersionHostname("default", DATASTORE_ADMIN_VERSION_NAME); + TaskOptions options = TaskOptions.Builder.withUrl("/_ah/datastore_admin/backup.create") + .header("Host", hostname) + .method(Method.GET) + .param("name", name + "_") // Add underscore since the name will be used as a prefix. + .param("filesystem", "gs") + .param("gs_bucket_name", gcsBucket) + .param("queue", queue) + .param("run_as_a_service", String.valueOf(true)); + for (String kind : kinds) { + options.param("kind", kind); + } + return options; + } + + /** + * Launches a new datastore backup with the given name, GCS bucket, and set of kinds by + * submitting a task to the given task queue, and returns a handle to that task. + */ + public TaskHandle launchNewBackup( + String queue, String name, String gcsBucket, ImmutableSet kinds) { + return getQueue(queue).add(makeTaskOptions(queue, name, gcsBucket, kinds)); + } + + /** Return an iterable of all datastore backups whose names have the given string prefix. */ + public Iterable findAllByNamePrefix(final String namePrefix) { + // Need the raw DatastoreService to access the internal _AE_Backup_Information entities. + // TODO(b/19081037): make an Objectify entity class for these raw datastore entities instead. + return FluentIterable + .from(getDatastoreService().prepare(new Query(BACKUP_INFO_KIND)).asIterable()) + .filter(new Predicate() { + @Override + public boolean apply(Entity entity) { + return nullToEmpty((String) entity.getProperty("name")).startsWith(namePrefix); + }}) + .transform(new Function() { + @Override + public DatastoreBackupInfo apply(Entity entity) { + return new DatastoreBackupInfo(entity); + }}); + } + + /** + * Return a single DatastoreBackup that uniquely matches this name prefix. Throws an IAE + * if no backups match or if more than one backup matches. + */ + public DatastoreBackupInfo findByName(final String namePrefix) { + try { + return Iterables.getOnlyElement(findAllByNamePrefix(namePrefix)); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("More than one backup with name prefix " + namePrefix, e); + } catch (NoSuchElementException e) { + throw new IllegalArgumentException("No backup found with name prefix " + namePrefix, e); + } + } +} diff --git a/java/com/google/domain/registry/export/DriveModule.java b/java/com/google/domain/registry/export/DriveModule.java new file mode 100644 index 000000000..306c59cbb --- /dev/null +++ b/java/com/google/domain/registry/export/DriveModule.java @@ -0,0 +1,61 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static dagger.Provides.Type.SET_VALUES; + +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.services.drive.Drive; +import com.google.api.services.drive.DriveScopes; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.OAuthScopes; + +import dagger.Module; +import dagger.Provides; + +import java.util.Set; + +/** + * Dagger module for Google {@link Drive} service connection objects. + * + * @see com.google.domain.registry.config.ConfigModule + * @see com.google.domain.registry.request.Modules.UrlFetchTransportModule + * @see com.google.domain.registry.request.Modules.Jackson2Module + * @see com.google.domain.registry.request.Modules.AppIdentityCredentialModule + * @see com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule + */ +@Module +public final class DriveModule { + + /** Provides OAuth2 scopes for the Drive service needed by Domain Registry. */ + @Provides(type = SET_VALUES) + @OAuthScopes + static Set provideDriveOAuthScopes() { + return DriveScopes.all(); + } + + @Provides + static Drive provideDrive( + HttpTransport transport, + JsonFactory jsonFactory, + HttpRequestInitializer httpRequestInitializer, + @Config("projectId") String projectId) { + return new Drive.Builder(transport, jsonFactory, httpRequestInitializer) + .setApplicationName(projectId) + .build(); + } +} diff --git a/java/com/google/domain/registry/export/ExportConstants.java b/java/com/google/domain/registry/export/ExportConstants.java new file mode 100644 index 000000000..f2114df71 --- /dev/null +++ b/java/com/google/domain/registry/export/ExportConstants.java @@ -0,0 +1,96 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.Predicates.not; +import static com.google.domain.registry.model.EntityClasses.CLASS_TO_KIND_FUNCTION; +import static com.google.domain.registry.util.TypeUtils.hasAnnotation; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.EntityClasses; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.VirtualEntity; +import com.google.domain.registry.model.billing.BillingEvent.Cancellation; +import com.google.domain.registry.model.billing.BillingEvent.Modification; +import com.google.domain.registry.model.billing.BillingEvent.OneTime; +import com.google.domain.registry.model.billing.BillingEvent.Recurring; +import com.google.domain.registry.model.billing.RegistrarCredit; +import com.google.domain.registry.model.billing.RegistrarCreditBalance; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.index.DomainApplicationIndex; +import com.google.domain.registry.model.index.EppResourceIndex; +import com.google.domain.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex; +import com.google.domain.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex; +import com.google.domain.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.label.PremiumList; +import com.google.domain.registry.model.registry.label.PremiumList.PremiumListEntry; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** Constants related to export code. */ +public final class ExportConstants { + + /** Set of entity classes to export into BigQuery for reporting purposes. */ + @VisibleForTesting + @SuppressWarnings("unchecked") // varargs + static final ImmutableSet> REPORTING_ENTITY_CLASSES = + ImmutableSet.of( + Cancellation.class, + ContactResource.class, + DomainApplicationIndex.class, + DomainBase.class, + EppResourceIndex.class, + ForeignKeyContactIndex.class, + ForeignKeyDomainIndex.class, + ForeignKeyHostIndex.class, + HistoryEntry.class, + HostResource.class, + Modification.class, + OneTime.class, + PremiumList.class, + PremiumListEntry.class, + Recurring.class, + Registrar.class, + RegistrarContact.class, + RegistrarCredit.class, + RegistrarCreditBalance.class, + Registry.class); + + /** Returns the names of kinds to include in datastore backups. */ + public static ImmutableSet getBackupKinds() { + // Back up all entity classes that aren't annotated with @VirtualEntity (never even persisted + // to datastore, so they can't be backed up) or @NotBackedUp (intentionally omitted). + return FluentIterable.from(EntityClasses.ALL_CLASSES) + .filter(not(hasAnnotation(VirtualEntity.class))) + .filter(not(hasAnnotation(NotBackedUp.class))) + .transform(CLASS_TO_KIND_FUNCTION) + .toSortedSet(Ordering.natural()); + } + + /** Returns the names of kinds to import into reporting tools (e.g. BigQuery). */ + public static ImmutableSet getReportingKinds() { + return FluentIterable.from(REPORTING_ENTITY_CLASSES) + .transform(CLASS_TO_KIND_FUNCTION) + .toSortedSet(Ordering.natural()); + } +} diff --git a/java/com/google/domain/registry/export/ExportRequestModule.java b/java/com/google/domain/registry/export/ExportRequestModule.java new file mode 100644 index 000000000..d7a9b3394 --- /dev/null +++ b/java/com/google/domain/registry/export/ExportRequestModule.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.domain.registry.export.BigqueryPollJobAction.CHAINED_TASK_QUEUE_HEADER; +import static com.google.domain.registry.export.BigqueryPollJobAction.JOB_ID_HEADER; +import static com.google.domain.registry.export.BigqueryPollJobAction.PROJECT_ID_HEADER; +import static com.google.domain.registry.request.RequestParameters.extractRequiredHeader; + +import com.google.domain.registry.request.Header; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for data export tasks. */ +@Module +public final class ExportRequestModule { + @Provides + @Header(CHAINED_TASK_QUEUE_HEADER) + static String provideChainedTaskQueue(HttpServletRequest req) { + return extractRequiredHeader(req, CHAINED_TASK_QUEUE_HEADER); + } + + @Provides + @Header(JOB_ID_HEADER) + static String provideJobId(HttpServletRequest req) { + return extractRequiredHeader(req, JOB_ID_HEADER); + } + + @Provides + @Header(PROJECT_ID_HEADER) + static String provideProjectId(HttpServletRequest req) { + return extractRequiredHeader(req, PROJECT_ID_HEADER); + } +} diff --git a/java/com/google/domain/registry/export/ExportReservedTermsTask.java b/java/com/google/domain/registry/export/ExportReservedTermsTask.java new file mode 100644 index 000000000..4abaa188e --- /dev/null +++ b/java/com/google/domain/registry/export/ExportReservedTermsTask.java @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; +import static com.google.domain.registry.export.ExportUtils.exportReservedTerms; +import static com.google.domain.registry.request.Action.Method.POST; +import static java.nio.charset.StandardCharsets.UTF_8; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.net.MediaType; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.storage.drive.DriveConnection; +import com.google.domain.registry.util.FormattingLogger; + +import javax.inject.Inject; + +/** Exports the publicly viewable reserved terms list for a TLD to Google Drive. */ +@Action(path = "/_dr/task/exportReservedTerms", method = POST) +public class ExportReservedTermsTask implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + static final MediaType EXPORT_MIME_TYPE = MediaType.PLAIN_TEXT_UTF_8; + static final String RESERVED_TERMS_FILENAME = "reserved_terms.txt"; + + @Inject DriveConnection driveConnection; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject Response response; + @Inject ExportReservedTermsTask() {} + + /** + * Exports the reserved terms for the TLD specified via the "tld" param to a newline-delimited + * UTF-8-formatted CSV file (with one column) named "reserved_terms.txt" in the Google Drive + * folder with the id specified for that TLD. + * + *

This servlet prints the ID of the file in GoogleDrive that was created/updated. + */ + @Override + public void run() { + response.setContentType(PLAIN_TEXT_UTF_8); + try { + Registry registry = Registry.get(tld); + String resultMsg; + if (registry.getReservedLists().isEmpty() && isNullOrEmpty(registry.getDriveFolderId())) { + resultMsg = "No reserved lists configured"; + logger.infofmt("No reserved terms to export for TLD %s", tld); + } else { + checkNotNull(registry.getDriveFolderId(), "No drive folder associated with this TLD"); + resultMsg = driveConnection.createOrUpdateFile( + RESERVED_TERMS_FILENAME, + EXPORT_MIME_TYPE, + registry.getDriveFolderId(), + exportReservedTerms(registry).getBytes(UTF_8)); + logger.infofmt("Exporting reserved terms succeeded for TLD %s, response was: %s", + tld, resultMsg); + } + response.setStatus(SC_OK); + response.setPayload(resultMsg); + } catch (Throwable e) { + response.setStatus(SC_INTERNAL_SERVER_ERROR); + response.setPayload(e.getMessage()); + throw new RuntimeException( + String.format("Exception occurred while exporting reserved terms for TLD %s.", tld), e); + } + } +} diff --git a/java/com/google/domain/registry/export/ExportSnapshotServlet.java b/java/com/google/domain/registry/export/ExportSnapshotServlet.java new file mode 100644 index 000000000..4c43a48f2 --- /dev/null +++ b/java/com/google/domain/registry/export/ExportSnapshotServlet.java @@ -0,0 +1,82 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.html.HtmlEscapers.htmlEscaper; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.net.MediaType; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; + +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Trigger a backup-as-a-service job that writes a snapshot to Google Cloud Storage. */ +public class ExportSnapshotServlet extends HttpServlet { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** Queue to use for enqueuing the task that will actually launch the backup. */ + static final String QUEUE = "export-snapshot"; // See queue.xml. + + /** Prefix to use for naming all snapshots that are started by this servlet. */ + static final String SNAPSHOT_PREFIX = "auto_snapshot_"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + @NonFinalForTesting + private static DatastoreBackupService backupService = DatastoreBackupService.get(); + + @NonFinalForTesting + private static CheckSnapshotServlet checkSnapshotServlet = new CheckSnapshotServlet(); + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + try { + // Use a unique name for the snapshot so we can explicitly check its completion later. + String snapshotName = SNAPSHOT_PREFIX + clock.nowUtc().toString("YYYYMMdd_HHmmss"); + backupService.launchNewBackup( + QUEUE, + snapshotName, + ENVIRONMENT.config().getSnapshotsBucket(), + ExportConstants.getBackupKinds()); + // Enqueue a poll task to monitor the backup and load reporting-related kinds into bigquery. + checkSnapshotServlet.enqueuePollTask(snapshotName, ExportConstants.getReportingKinds()); + String message = "Datastore backup started with name: " + snapshotName; + logger.info(message); + rsp.setStatus(SC_OK); + rsp.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString()); + rsp.getWriter().write("OK\n\n" + message); + } catch (Throwable e) { + logger.severe(e, e.toString()); + rsp.sendError( + e instanceof IllegalArgumentException ? SC_BAD_REQUEST : SC_INTERNAL_SERVER_ERROR, + htmlEscaper().escape(firstNonNull(e.getMessage(), e.toString()))); + } + } +} diff --git a/java/com/google/domain/registry/export/ExportUtils.java b/java/com/google/domain/registry/export/ExportUtils.java new file mode 100644 index 000000000..109169da9 --- /dev/null +++ b/java/com/google/domain/registry/export/ExportUtils.java @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.domain.registry.model.registry.label.ReservationType.UNRESERVED; + +import com.google.common.base.Joiner; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.label.ReservedList; +import com.google.domain.registry.model.registry.label.ReservedList.ReservedListEntry; + +import com.googlecode.objectify.Key; + +import java.util.Set; +import java.util.TreeSet; + +/** Container class for exported-related static utility methods. */ +public class ExportUtils { + + private ExportUtils() {} + + /** Returns the file contents of the auto-export reserved terms document for the given TLD. */ + public static String exportReservedTerms(Registry registry) { + StringBuilder termsBuilder = + new StringBuilder(RegistryEnvironment.get().config().getReservedTermsExportDisclaimer()); + Set reservedTerms = new TreeSet<>(); + for (Key key : registry.getReservedLists()) { + ReservedList reservedList = ReservedList.load(key).get(); + if (reservedList.getShouldPublish()) { + for (ReservedListEntry entry : reservedList.getReservedListEntries().values()) { + if (entry.getValue() != UNRESERVED) { + reservedTerms.add(entry.getLabel()); + } + } + } + } + Joiner.on("\n").appendTo(termsBuilder, reservedTerms); + return termsBuilder.append("\n").toString(); + } +} diff --git a/java/com/google/domain/registry/export/LoadSnapshotServlet.java b/java/com/google/domain/registry/export/LoadSnapshotServlet.java new file mode 100644 index 000000000..b86db60b0 --- /dev/null +++ b/java/com/google/domain/registry/export/LoadSnapshotServlet.java @@ -0,0 +1,207 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.html.HtmlEscapers.htmlEscaper; +import static com.google.domain.registry.util.HttpServletUtils.getRequiredParameterValue; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.api.client.extensions.appengine.http.UrlFetchTransport; +import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.BigqueryScopes; +import com.google.api.services.bigquery.model.Dataset; +import com.google.api.services.bigquery.model.DatasetReference; +import com.google.api.services.bigquery.model.Job; +import com.google.api.services.bigquery.model.JobConfiguration; +import com.google.api.services.bigquery.model.JobConfigurationLoad; +import com.google.api.services.bigquery.model.JobReference; +import com.google.api.services.bigquery.model.TableReference; +import com.google.appengine.api.taskqueue.QueueFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.MediaType; +import com.google.domain.registry.bigquery.BigqueryFactory; +import com.google.domain.registry.bigquery.BigqueryJobFailureException; +import com.google.domain.registry.bigquery.BigqueryUtils.SourceFormat; +import com.google.domain.registry.bigquery.BigqueryUtils.WriteDisposition; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.export.BigqueryPollJobAction.BigqueryPollJobEnqueuer; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.Retrier; +import com.google.domain.registry.util.SystemClock; +import com.google.domain.registry.util.SystemSleeper; +import com.google.domain.registry.util.TaskEnqueuer; + +import org.joda.time.DateTime; + +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Load a datastore snapshot from Google Cloud Storage into BigQuery. */ +public class LoadSnapshotServlet extends HttpServlet { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** Parameter names for passing parameters into the servlet. */ + static final String SNAPSHOT_ID_PARAM = "id"; + static final String SNAPSHOT_FILE_PARAM = "file"; + static final String SNAPSHOT_KINDS_PARAM = "kinds"; + + /** Servlet-specific details needed for enqueuing tasks against itself. */ + static final String QUEUE = "export-snapshot"; // See queue.xml. + static final String PATH = "/_dr/task/loadSnapshot"; // See web.xml. + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + @NonFinalForTesting + private static BigqueryFactory bigqueryFactory = new BigqueryFactory(); + + @NonFinalForTesting + private static BigqueryPollJobEnqueuer bigqueryPollEnqueuer = new BigqueryPollJobEnqueuer( + new TaskEnqueuer(new Retrier(new SystemSleeper(), 5))); + + /** Enqueue a task for starting a backup load. Not static for better testability. */ + public TaskHandle enqueueLoadTask( + String snapshotId, String gcsFile, ImmutableSet kinds) { + return QueueFactory.getQueue(QUEUE).add( + TaskOptions.Builder.withUrl(PATH) + .method(Method.POST) + .param(SNAPSHOT_ID_PARAM, snapshotId) + .param(SNAPSHOT_FILE_PARAM, gcsFile) + .param(SNAPSHOT_KINDS_PARAM, Joiner.on(',').join(kinds))); + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + try { + String snapshotId = getRequiredParameterValue(req, SNAPSHOT_ID_PARAM); + String gcsFilename = getRequiredParameterValue(req, SNAPSHOT_FILE_PARAM); + ImmutableList kinds = ImmutableList.copyOf( + Splitter.on(',').splitToList(getRequiredParameterValue(req, SNAPSHOT_KINDS_PARAM))); + + String message = loadSnapshot(snapshotId, gcsFilename, kinds); + + rsp.setStatus(SC_OK); + rsp.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString()); + rsp.getWriter().write("OK\n\n" + message); + } catch (Throwable e) { + logger.severe(e, e.toString()); + rsp.sendError( + e instanceof IllegalArgumentException ? SC_BAD_REQUEST : SC_INTERNAL_SERVER_ERROR, + htmlEscaper().escape(firstNonNull(e.getMessage(), e.toString()))); + } + } + + private String loadSnapshot(String snapshotId, String gcsFilename, ImmutableList kinds) + throws IOException { + Bigquery bigquery = bigqueryFactory.create( + getClass().getSimpleName(), + new UrlFetchTransport(), + new JacksonFactory(), + new AppIdentityCredential(BigqueryScopes.all())); + String projectId = ENVIRONMENT.config().getProjectId(); + DateTime now = clock.nowUtc(); + + ensureDataset(bigquery, projectId, ENVIRONMENT.config().getSnapshotsDataset()); + + String loadMessage = + String.format("Loading datastore snapshot %s from %s...", snapshotId, gcsFilename); + logger.info(loadMessage); + StringBuilder builder = new StringBuilder(loadMessage + "\n"); + builder.append("Load jobs:\n"); + + for (String kindName : kinds) { + String jobId = String.format("load-snapshot-%s-%s-%d", snapshotId, kindName, now.getMillis()); + JobReference jobRef = new JobReference().setProjectId(projectId).setJobId(jobId); + String sourceUri = getBackupInfoFileForKind(gcsFilename, kindName); + String tableId = String.format("%s_%s", snapshotId, kindName); + + // Launch the load job. + Job job = makeLoadJob(jobRef, sourceUri, tableId); + bigquery.jobs().insert(projectId, job).execute(); + + // Enqueue a task to check on the load job's completion, and if it succeeds, to update a + // well-known view in BigQuery to point at the newly loaded snapshot table for this kind. + bigqueryPollEnqueuer.enqueuePollTask( + jobRef, + UpdateSnapshotViewServlet.createViewUpdateTask( + ENVIRONMENT.config().getSnapshotsDataset(), tableId, kindName), + QueueFactory.getQueue(UpdateSnapshotViewServlet.QUEUE)); + + builder.append(String.format(" - %s:%s\n", projectId, jobId)); + logger.infofmt("Submitted load job %s:%s", projectId, jobId); + } + return builder.toString(); + } + + private static void ensureDataset(Bigquery bigquery, String projectId, String datasetId) + throws IOException { + try { + bigquery.datasets() + .insert(projectId, + new Dataset().setDatasetReference( + new DatasetReference() + .setProjectId(projectId) + .setDatasetId(datasetId))) + .execute(); + } catch (IOException e) { + // Swallow errors about a duplicate dataset, and throw any other ones. + if (!BigqueryJobFailureException.create(e).getReason().equals("duplicate")) { + throw e; + } + } + } + + private static String getBackupInfoFileForKind(String backupInfoFile, String kindName) { + String extension = ".backup_info"; + checkArgument(backupInfoFile.endsWith(extension), "backup info file extension missing"); + String prefix = backupInfoFile.substring(0, backupInfoFile.length() - extension.length()); + return Joiner.on('.').join(prefix, kindName, extension.substring(1)); + } + + private static Job makeLoadJob(JobReference jobRef, String sourceUri, String tableId) { + TableReference tableReference = new TableReference() + .setProjectId(jobRef.getProjectId()) + .setDatasetId(ENVIRONMENT.config().getSnapshotsDataset()) + .setTableId(tableId); + return new Job() + .setJobReference(jobRef) + .setConfiguration(new JobConfiguration() + .setLoad(new JobConfigurationLoad() + .setWriteDisposition(WriteDisposition.WRITE_EMPTY.toString()) + .setSourceFormat(SourceFormat.DATASTORE_BACKUP.toString()) + .setSourceUris(ImmutableList.of(sourceUri)) + .setDestinationTable(tableReference))); + } +} diff --git a/java/com/google/domain/registry/export/PublishDetailReportAction.java b/java/com/google/domain/registry/export/PublishDetailReportAction.java new file mode 100644 index 000000000..72f288ebf --- /dev/null +++ b/java/com/google/domain/registry/export/PublishDetailReportAction.java @@ -0,0 +1,124 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.ByteStreams; +import com.google.common.net.MediaType; +import com.google.domain.registry.gcs.GcsUtils; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.InternalServerErrorException; +import com.google.domain.registry.request.JsonActionRunner; +import com.google.domain.registry.request.JsonActionRunner.JsonAction; +import com.google.domain.registry.storage.drive.DriveConnection; +import com.google.domain.registry.util.FormattingLogger; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.Map; + +import javax.inject.Inject; + +/** Publish a single registrar detail report from GCS to Drive. */ +@Action( + path = PublishDetailReportAction.PATH, + method = Action.Method.POST, + xsrfProtection = true, + xsrfScope = "admin") +public final class PublishDetailReportAction implements Runnable, JsonAction { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** MIME type to use for deposited report files in Drive. */ + private static final MediaType REPORT_MIME_TYPE = MediaType.CSV_UTF_8; + + /** Endpoint to which JSON should be sent for this servlet. See {@code web.xml}. */ + public static final String PATH = "/_dr/publishDetailReport"; + + /** Name of parameter indicating the registrar for which this report will be published. */ + public static final String REGISTRAR_ID_PARAM = "registrar"; + + /** Name of parameter providing a name for the report file placed in Drive (the base name). */ + public static final String DETAIL_REPORT_NAME_PARAM = "report"; + + /** + * Name of parameter giving the prefix of the GCS object name to use as the report contents. + * Concatenating this value with the value of the "report" parameter gives the full object name. + */ + public static final String GCS_FOLDER_PREFIX_PARAM = "gcsFolder"; + + /** Name of parameter giving the GCS bucket name for the file to use as the report contents. */ + public static final String GCS_BUCKET_PARAM = "bucket"; + + @Inject DriveConnection driveConnection; + @Inject GcsUtils gcsUtils; + @Inject JsonActionRunner runner; + @Inject PublishDetailReportAction() {} + + @Override + public void run() { + runner.run(this); + } + + /** Copy a detail report from Cloud Storage to Drive. */ + @Override + public Map handleJsonRequest(Map json) { + try { + logger.infofmt("Publishing detail report for parameters: %s", json); + String registrarId = getParam(json, REGISTRAR_ID_PARAM); + Registrar registrar = checkArgumentNotNull(Registrar.loadByClientId(registrarId), + "Registrar %s not found", registrarId); + String driveFolderId = checkArgumentNotNull(registrar.getDriveFolderId(), + "No drive folder associated with registrar " + registrarId); + String gcsBucketName = getParam(json, GCS_BUCKET_PARAM); + String gcsObjectName = + getParam(json, GCS_FOLDER_PREFIX_PARAM) + getParam(json, DETAIL_REPORT_NAME_PARAM); + try (InputStream input = + gcsUtils.openInputStream(new GcsFilename(gcsBucketName, gcsObjectName))) { + String driveId = + driveConnection.createFile( + getParam(json, DETAIL_REPORT_NAME_PARAM), + REPORT_MIME_TYPE, + driveFolderId, + ByteStreams.toByteArray(input)); + logger.infofmt("Published detail report for %s to folder %s using GCS file gs://%s/%s.", + registrarId, + driveFolderId, + gcsBucketName, + gcsObjectName); + return ImmutableMap.of("driveId", driveId); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } catch (Throwable e) { + logger.severe(e, e.toString()); + String message = firstNonNull(e.getMessage(), e.toString()); + throw e instanceof IllegalArgumentException + ? new BadRequestException(message) : new InternalServerErrorException(message); + } + } + + private String getParam(Map json, String paramName) { + return (String) checkArgumentNotNull( + json.get(paramName), + "Missing required parameter: %s", paramName); + } +} diff --git a/java/com/google/domain/registry/export/SyncGroupMembersTask.java b/java/com/google/domain/registry/export/SyncGroupMembersTask.java new file mode 100644 index 000000000..c2128f6c6 --- /dev/null +++ b/java/com/google/domain/registry/export/SyncGroupMembersTask.java @@ -0,0 +1,235 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.request.Action.Method.POST; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.RegistrarUtils.normalizeClientId; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Sets; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.groups.GroupsConnection; +import com.google.domain.registry.groups.GroupsConnection.Role; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.Concurrent; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.VoidWork; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +/** + * Syncs changes to {@link RegistrarContact} entities with Google Groups using the Directory API. + */ +@Action(path = "/_dr/task/syncGroupMembers", method = POST) +public final class SyncGroupMembersTask implements Runnable { + + /** + * The number of threads to run simultaneously (one per registrar) while processing group syncs. + * This number is purposefully low because App Engine will complain about a large number of + * requests per second, so it's better to spread the work out (as we are only running this servlet + * once per hour anyway). + */ + private static final int NUM_WORK_THREADS = 2; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + + private enum Result { + OK(SC_OK, "Group memberships successfully updated."), + NOT_MODIFIED(SC_OK, "No registrar contacts have been updated since the last time servlet ran."), + FAILED(SC_INTERNAL_SERVER_ERROR, "Error occurred while updating registrar contacts.") { + @Override + protected void log(Throwable cause) { + logger.severefmt(cause, "%s", message); + }}; + + final int statusCode; + final String message; + + private Result(int statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + } + + /** Log an error message. Results that use log levels other than info should override this. */ + void log(@Nullable Throwable cause) { + logger.infofmt(cause, "%s", message); + } + } + + @Inject GroupsConnection groupsConnection; + @Inject Response response; + @Inject @Config("publicDomainName") String publicDomainName; + @Inject SyncGroupMembersTask() {} + + private void sendResponse(Result result, @Nullable List causes) { + for (Throwable cause : nullToEmpty(causes)) { + result.log(cause); + } + response.setStatus(result.statusCode); + response.setPayload(String.format("%s %s\n", result.name(), result.message)); + } + + /** + * Returns the Google Groups email address for the given registrar clientId and + * RegistrarContact.Type + */ + public static String getGroupEmailAddressForContactType( + String clientId, + RegistrarContact.Type type, + String publicDomainName) { + // Take the registrar's clientId, make it lowercase, and remove all characters that aren't + // alphanumeric, hyphens, or underscores. + return String.format( + "%s-%s-contacts@%s", normalizeClientId(clientId), type.getDisplayName(), publicDomainName); + } + + /** + * Loads all Registrars, and for each one that is marked dirty, grabs the existing group + * memberships and updates them to reflect the current state of the RegistrarContacts. + */ + @Override + public void run() { + List dirtyRegistrars = Registrar + .loadAllActive() + .filter(new Predicate() { + @Override + public boolean apply(Registrar registrar) { + // Only grab registrars that require syncing and are of the correct type. + return registrar.getContactsRequireSyncing() + && registrar.getType() == Registrar.Type.REAL; + }}) + .toList(); + if (dirtyRegistrars.isEmpty()) { + sendResponse(Result.NOT_MODIFIED, null); + return; + } + + // Run multiple threads to communicate with Google Groups simultaneously. + ImmutableList> results = Concurrent.transform( + dirtyRegistrars, + NUM_WORK_THREADS, + new Function>() { + @Override + public Optional apply(final Registrar registrar) { + try { + syncRegistrarContacts(registrar); + return Optional. absent(); + } catch (Throwable e) { + logger.severe(e, e.getMessage()); + return Optional.of(e); + } + }}); + + List errors = getErrorsAndUpdateFlagsForSuccesses(dirtyRegistrars, results); + // If there were no errors, return success; otherwise return a failed status and log the errors. + if (errors.isEmpty()) { + sendResponse(Result.OK, null); + } else { + sendResponse(Result.FAILED, errors); + } + } + + /** + * Parses the results from Google Groups for each registrar, setting the dirty flag to false in + * Datastore for the calls that succeeded and accumulating the errors for the calls that failed. + */ + private List getErrorsAndUpdateFlagsForSuccesses( + List registrars, + List> results) { + final ImmutableList.Builder registrarsToSave = new ImmutableList.Builder<>(); + List errors = new ArrayList<>(); + for (int i = 0; i < results.size(); i++) { + Optional opt = results.get(i); + if (opt.isPresent()) { + errors.add(opt.get()); + } else { + registrarsToSave.add( + registrars.get(i).asBuilder().setContactsRequireSyncing(false).build()); + } + } + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().save().entities(registrarsToSave.build()); + }}); + return errors; + } + + /** Syncs the contacts for an individual registrar to Google Groups. */ + private void syncRegistrarContacts(Registrar registrar) { + String groupKey = ""; + try { + Set registrarContacts = registrar.getContacts(); + long totalAdded = 0; + long totalRemoved = 0; + for (final RegistrarContact.Type type : RegistrarContact.Type.values()) { + groupKey = getGroupEmailAddressForContactType( + registrar.getClientIdentifier(), type, publicDomainName); + Set currentMembers = groupsConnection.getMembersOfGroup(groupKey); + Set desiredMembers = FluentIterable.from(registrarContacts) + .filter(new Predicate() { + @Override + public boolean apply(RegistrarContact contact) { + return contact.getTypes().contains(type); + }}) + .transform(new Function() { + @Override + public String apply(RegistrarContact contact) { + return contact.getEmailAddress(); + }}) + .toSet(); + for (String email : Sets.difference(desiredMembers, currentMembers)) { + groupsConnection.addMemberToGroup(groupKey, email, Role.MEMBER); + totalAdded++; + } + for (String email : Sets.difference(currentMembers, desiredMembers)) { + groupsConnection.removeMemberFromGroup(groupKey, email); + totalRemoved++; + } + } + logger.infofmt("Successfully synced contacts for registrar %s: added %d and removed %d", + registrar.getClientIdentifier(), + totalAdded, + totalRemoved); + } catch (IOException e) { + // Bail out of the current sync job if an error occurs. This is OK because (a) errors usually + // indicate that retrying won't succeed at all, or at least not immediately, and (b) the sync + // job will run within an hour anyway and effectively resume where it left off if this was a + // transient error. + String msg = String.format("Couldn't sync contacts for registrar %s to group %s", + registrar.getClientIdentifier(), groupKey); + throw new RuntimeException(msg, e); + } + } +} diff --git a/java/com/google/domain/registry/export/UpdateSnapshotViewServlet.java b/java/com/google/domain/registry/export/UpdateSnapshotViewServlet.java new file mode 100644 index 000000000..3fc891b21 --- /dev/null +++ b/java/com/google/domain/registry/export/UpdateSnapshotViewServlet.java @@ -0,0 +1,142 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.html.HtmlEscapers.htmlEscaper; +import static com.google.domain.registry.util.HttpServletUtils.getRequiredParameterValue; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.api.client.extensions.appengine.http.UrlFetchTransport; +import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.BigqueryScopes; +import com.google.api.services.bigquery.model.Table; +import com.google.api.services.bigquery.model.TableReference; +import com.google.api.services.bigquery.model.ViewDefinition; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.net.MediaType; +import com.google.domain.registry.bigquery.BigqueryFactory; +import com.google.domain.registry.bigquery.BigqueryHelper; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SqlTemplate; + +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Update a well-known view to point at a certain datastore snapshot table in BigQuery. */ +public class UpdateSnapshotViewServlet extends HttpServlet { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** Headers for passing parameters into the servlet. */ + static final String SNAPSHOT_DATASET_ID_PARAM = "dataset"; + static final String SNAPSHOT_TABLE_ID_PARAM = "table"; + static final String SNAPSHOT_KIND_PARAM = "kind"; + + /** Servlet-specific details needed for enqueuing tasks against itself. */ + static final String QUEUE = "export-snapshot-update-view"; // See queue.xml. + static final String PATH = "/_dr/task/updateSnapshotView"; // See web.xml. + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final BigqueryHelper bigqueryHelper = new BigqueryHelper(); + + @NonFinalForTesting + private static BigqueryFactory bigqueryFactory = new BigqueryFactory(); + + /** Create a task for updating a snapshot view. */ + public static TaskOptions createViewUpdateTask( + String datasetId, String tableId, String kindName) { + return TaskOptions.Builder.withUrl(PATH) + .method(Method.POST) + .param(SNAPSHOT_DATASET_ID_PARAM, datasetId) + .param(SNAPSHOT_TABLE_ID_PARAM, tableId) + .param(SNAPSHOT_KIND_PARAM, kindName); + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + try { + String datasetId = getRequiredParameterValue(req, SNAPSHOT_DATASET_ID_PARAM); + String tableId = getRequiredParameterValue(req, SNAPSHOT_TABLE_ID_PARAM); + String kindName = getRequiredParameterValue(req, SNAPSHOT_KIND_PARAM); + + String message = updateSnapshotView(datasetId, tableId, kindName); + + rsp.setStatus(SC_OK); + rsp.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString()); + rsp.getWriter().write("OK\n\n" + message); + } catch (Throwable e) { + logger.severe(e, e.toString()); + rsp.sendError( + e instanceof IllegalArgumentException ? SC_BAD_REQUEST : SC_INTERNAL_SERVER_ERROR, + htmlEscaper().escape(firstNonNull(e.getMessage(), e.toString()))); + } + } + + private String updateSnapshotView(String datasetId, String tableId, String kindName) + throws IOException { + Bigquery bigquery = bigqueryFactory.create( + getClass().getSimpleName(), + new UrlFetchTransport(), + new JacksonFactory(), + new AppIdentityCredential(BigqueryScopes.all())); + String projectId = ENVIRONMENT.config().getProjectId(); + + bigqueryHelper.ensureDataset( + bigquery, projectId, ENVIRONMENT.config().getLatestSnapshotDataset()); + + updateTable(bigquery, new Table() + .setTableReference(new TableReference() + .setProjectId(projectId) + .setDatasetId(ENVIRONMENT.config().getLatestSnapshotDataset()) + .setTableId(kindName)) + .setView(new ViewDefinition().setQuery( + SqlTemplate.create("SELECT * FROM [%DATASET%.%TABLE%]") + .put("DATASET", datasetId) + .put("TABLE", tableId) + .build()))); + + String message = String.format( + "Updated view %s:%s to point at snapshot table %s:%s.", + ENVIRONMENT.config().getLatestSnapshotDataset(), kindName, datasetId, tableId); + logger.info(message); + return message; + } + + private static void updateTable(Bigquery bigquery, Table table) throws IOException { + TableReference ref = table.getTableReference(); + try { + bigquery.tables() + .update(ref.getProjectId(), ref.getDatasetId(), ref.getTableId(), table) + .execute(); + } catch (GoogleJsonResponseException e) { + if (e.getDetails().getCode() == 404) { + bigquery.tables().insert(ref.getProjectId(), ref.getDatasetId(), table).execute(); + } + } + } +} diff --git a/java/com/google/domain/registry/export/package-info.java b/java/com/google/domain/registry/export/package-info.java new file mode 100644 index 000000000..cd0c1b29d --- /dev/null +++ b/java/com/google/domain/registry/export/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.export; diff --git a/java/com/google/domain/registry/export/sheet/BUILD b/java/com/google/domain/registry/export/sheet/BUILD new file mode 100644 index 000000000..9926cd258 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//java/com/google/domain/registry:registry_project"]) + + +java_library( + name = "sheet", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/api/client/googleapis/auth/oauth2", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//java/com/google/gdata", + "//java/com/google/gdata:spreadsheet", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/export/sheet/SheetModule.java b/java/com/google/domain/registry/export/sheet/SheetModule.java new file mode 100644 index 000000000..a65ab4603 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/SheetModule.java @@ -0,0 +1,36 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export.sheet; + +import static com.google.common.base.Strings.emptyToNull; + +import com.google.common.base.Optional; +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the sheet package. */ +@Module +public final class SheetModule { + + @Provides + @Parameter("id") + static Optional provideId(HttpServletRequest req) { + return Optional.fromNullable(emptyToNull(req.getParameter("id"))); + } +} diff --git a/java/com/google/domain/registry/export/sheet/SheetSynchronizer.java b/java/com/google/domain/registry/export/sheet/SheetSynchronizer.java new file mode 100644 index 000000000..8a13989c4 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/SheetSynchronizer.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export.sheet; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gdata.client.spreadsheet.SpreadsheetService; +import com.google.gdata.data.spreadsheet.CustomElementCollection; +import com.google.gdata.data.spreadsheet.ListEntry; +import com.google.gdata.data.spreadsheet.ListFeed; +import com.google.gdata.data.spreadsheet.SpreadsheetEntry; +import com.google.gdata.data.spreadsheet.WorksheetEntry; +import com.google.gdata.util.ServiceException; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import javax.inject.Inject; + +/** Generic data synchronization utility for Google Spreadsheets. */ +class SheetSynchronizer { + + private static final String SPREADSHEET_URL_PREFIX = + "https://spreadsheets.google.com/feeds/spreadsheets/"; + + @Inject SpreadsheetService spreadsheetService; + @Inject SheetSynchronizer() {} + + /** + * Replace the contents of a Google Spreadsheet with {@code data}. + * + *

In order for this to work, you must create a spreadsheet with a header row, each containing + * the column name, without any spaces. All subsequent rows are considered data, so long as + * they're not blank. If you have a blank row in the middle of your data, you're going to have + * problems. You must also make sure that the spreadsheet has been shared with the API client + * credential email address. + * + *

The algorithm works by first assuming that the spreadsheet is sorted in the same way that + * {@code data} is sorted. It then iterates through the existing rows and comparing them to the + * items in {@code data}. Iteration continues until we either run out of rows, or items in + * {@code data}. If there's any rows remaining, they'll be deleted. If instead, items remain in + * data, they'll be inserted. + * + * @param spreadsheetId The ID of your spreadsheet. This can be obtained by opening the Google + * spreadsheet in your browser and copying the ID from the URL. + * @param data This should be a sorted list of rows containing the enterity of the + * spreadsheet. Each row is a map, where the key must be exactly the same as the column header + * cell in the spreadsheet, and value is an arbitrary object which will be converted to a + * string before storing it in the spreadsheet. + * @throws IOException error communicating with the GData service. + * @throws ServiceException if a system error occurred when retrieving the entry. + * @throws com.google.gdata.util.ParseException error parsing the returned entry. + * @throws com.google.gdata.util.ResourceNotFoundException if an entry URL is not valid. + * @throws com.google.gdata.util.ServiceForbiddenException if the GData service cannot get the + * entry resource due to access constraints. + * @see "https://developers.google.com/google-apps/spreadsheets/" + */ + void synchronize(String spreadsheetId, ImmutableList> data) + throws IOException, ServiceException { + URL url = new URL(SPREADSHEET_URL_PREFIX + spreadsheetId); + SpreadsheetEntry spreadsheet = spreadsheetService.getEntry(url, SpreadsheetEntry.class); + WorksheetEntry worksheet = spreadsheet.getWorksheets().get(0); + worksheet.setRowCount(data.size()); + worksheet = worksheet.update(); + ListFeed listFeed = spreadsheetService.getFeed(worksheet.getListFeedUrl(), ListFeed.class); + List entries = listFeed.getEntries(); + int commonSize = Math.min(entries.size(), data.size()); + for (int i = 0; i < commonSize; i++) { + ListEntry entry = entries.get(i); + CustomElementCollection elements = entry.getCustomElements(); + boolean mutated = false; + for (ImmutableMap.Entry cell : data.get(i).entrySet()) { + if (!cell.getValue().equals(elements.getValue(cell.getKey()))) { + mutated = true; + elements.setValueLocal(cell.getKey(), cell.getValue()); + } + } + if (mutated) { + entry.update(); + } + } + if (data.size() > entries.size()) { + for (int i = entries.size(); i < data.size(); i++) { + ListEntry entry = listFeed.createEntry(); + CustomElementCollection elements = entry.getCustomElements(); + for (ImmutableMap.Entry cell : data.get(i).entrySet()) { + elements.setValueLocal(cell.getKey(), cell.getValue()); + } + listFeed.insert(entry); + } + } + } +} diff --git a/java/com/google/domain/registry/export/sheet/SpreadsheetServiceModule.java b/java/com/google/domain/registry/export/sheet/SpreadsheetServiceModule.java new file mode 100644 index 000000000..5fc480797 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/SpreadsheetServiceModule.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export.sheet; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.common.collect.ImmutableList; +import com.google.gdata.client.spreadsheet.SpreadsheetService; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module for {@link SpreadsheetService}. */ +@Module +public final class SpreadsheetServiceModule { + + private static final String APPLICATION_NAME = "google-registry-v1"; + private static final ImmutableList SCOPES = ImmutableList.of( + "https://spreadsheets.google.com/feeds", + "https://docs.google.com/feeds"); + + @Provides + static SpreadsheetService provideSpreadsheetService(GoogleCredential credential) { + SpreadsheetService service = new SpreadsheetService(APPLICATION_NAME); + service.setOAuth2Credentials(credential.createScoped(SCOPES)); + return service; + } +} diff --git a/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheet.java b/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheet.java new file mode 100644 index 000000000..4bd498eb3 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheet.java @@ -0,0 +1,211 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export.sheet; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.ABUSE; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.ADMIN; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.BILLING; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.LEGAL; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.MARKETING; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.TECH; +import static com.google.domain.registry.model.registrar.RegistrarContact.Type.WHOIS; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarAddress; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.DateTimeUtils; +import com.google.gdata.util.ServiceException; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.IOException; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +/** + * Class for synchronizing all {@link Registrar} datastore objects to a Google Spreadsheet. + * + * @see SyncRegistrarsSheetTask + */ +class SyncRegistrarsSheet { + + @Inject Clock clock; + @Inject SheetSynchronizer sheetSynchronizer; + @Inject SyncRegistrarsSheet() {} + + /** Returns true if a {@link Registrar} entity was modified in past {@code duration}. */ + boolean wasRegistrarsModifiedInLast(Duration duration) { + DateTime watermark = clock.nowUtc().minus(duration); + for (Registrar registrar : Registrar.loadAll()) { + if (DateTimeUtils.isAtOrAfter(registrar.getLastUpdateTime(), watermark)) { + return true; + } + } + return false; + } + + /** Performs the synchronization operation. */ + void run(String spreadsheetId) throws IOException, ServiceException { + sheetSynchronizer.synchronize( + spreadsheetId, + FluentIterable + .from( + new Ordering() { + @Override + public int compare(Registrar left, Registrar right) { + return left.getClientIdentifier().compareTo(right.getClientIdentifier()); + } + }.immutableSortedCopy(Registrar.loadAll())) + .filter( + new Predicate() { + @Override + public boolean apply(Registrar registrar) { + return registrar.getType() == Registrar.Type.REAL + || registrar.getType() == Registrar.Type.OTE; + } + }) + .transform( + new Function>() { + @Override + public ImmutableMap apply(Registrar registrar) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + ImmutableSortedSet contacts = registrar.getContacts(); + RegistrarAddress address = + firstNonNull( + registrar.getLocalizedAddress(), + firstNonNull( + registrar.getInternationalizedAddress(), + new RegistrarAddress.Builder() + .setStreet(ImmutableList.of("UNKNOWN")) + .setCity("UNKNOWN") + .setCountryCode("US") + .build())); + // + // (╯°□°)╯ WARNING WARNING WARNING + // + // Do not change these mappings simply because the Registrar model changed. Only + // change these mappings if the people who use the spreadsheet requested it be + // changed. + // + // These values are hard-coded because they correspond to actual spreadsheet + // columns. If you change this dictionary, then you'll need to manually add new + // columns to the registrar spreadsheets for all environments before deployment, + // and you'll need to remove deleted columns probably like a week after + // deployment. + // + builder.put("clientIdentifier", convert(registrar.getClientIdentifier())); + builder.put("registrarName", convert(registrar.getRegistrarName())); + builder.put("state", convert(registrar.getState())); + builder.put("ianaIdentifier", convert(registrar.getIanaIdentifier())); + builder.put("billingIdentifier", convert(registrar.getBillingIdentifier())); + builder.put("primaryContacts", convertContacts(contacts, byType(ADMIN))); + builder.put("techContacts", convertContacts(contacts, byType(TECH))); + builder.put("marketingContacts", convertContacts(contacts, byType(MARKETING))); + builder.put("abuseContacts", convertContacts(contacts, byType(ABUSE))); + builder.put("whoisInquiryContacts", convertContacts(contacts, byType(WHOIS))); + builder.put("legalContacts", convertContacts(contacts, byType(LEGAL))); + builder.put("billingContacts", convertContacts(contacts, byType(BILLING))); + builder.put( + "contactsMarkedAsWhoisAdmin", + convertContacts( + contacts, + new Predicate() { + @Override + public boolean apply(RegistrarContact contact) { + return contact.getVisibleInWhoisAsAdmin(); + } + })); + builder.put( + "contactsMarkedAsWhoisTech", + convertContacts( + contacts, + new Predicate() { + @Override + public boolean apply(RegistrarContact contact) { + return contact.getVisibleInWhoisAsTech(); + } + })); + builder.put("emailAddress", convert(registrar.getEmailAddress())); + builder.put("address.street", convert(address.getStreet())); + builder.put("address.city", convert(address.getCity())); + builder.put("address.state", convert(address.getState())); + builder.put("address.zip", convert(address.getZip())); + builder.put("address.countryCode", convert(address.getCountryCode())); + builder.put("phoneNumber", convert(registrar.getPhoneNumber())); + builder.put("faxNumber", convert(registrar.getFaxNumber())); + builder.put("creationTime", convert(registrar.getCreationTime())); + builder.put("lastUpdateTime", convert(registrar.getLastUpdateTime())); + builder.put("allowedTlds", convert(registrar.getAllowedTlds())); + builder.put("whoisServer", convert(registrar.getWhoisServer())); + builder.put("blockPremiumNames", convert(registrar.getBlockPremiumNames())); + builder.put("ipAddressWhitelist", convert(registrar.getIpAddressWhitelist())); + builder.put("url", convert(registrar.getUrl())); + builder.put("referralUrl", convert(registrar.getReferralUrl())); + builder.put("icannReferralEmail", convert(registrar.getIcannReferralEmail())); + return builder.build(); + } + }) + .toList()); + } + + private static String convertContacts( + Iterable contacts, Predicate filter) { + StringBuilder result = new StringBuilder(); + boolean first = true; + for (RegistrarContact contact : contacts) { + if (!filter.apply(contact)) { + continue; + } + if (first) { + first = false; + } else { + result.append("\n"); + } + result.append(contact.toStringMultilinePlainText()); + } + return result.toString(); + } + + private static Predicate byType(final RegistrarContact.Type type) { + return new Predicate() { + @Override + public boolean apply(RegistrarContact contact) { + return contact.getTypes().contains(type); + }}; + } + + /** Converts a value to a string representation that can be stored in a spreadsheet cell. */ + private static String convert(@Nullable Object value) { + if (value == null) { + return ""; + } else if (value instanceof Iterable) { + return Joiner.on('\n').join((Iterable) value); + } else { + return value.toString(); + } + } +} diff --git a/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTask.java b/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTask.java new file mode 100644 index 000000000..67eaf31f0 --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/SyncRegistrarsSheetTask.java @@ -0,0 +1,162 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.export.sheet; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; +import static com.google.domain.registry.request.Action.Method.POST; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.appengine.api.modules.ModulesService; +import com.google.appengine.api.modules.ModulesServiceFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.base.Optional; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.server.Lock; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.gdata.util.ServiceException; + +import org.joda.time.Duration; + +import java.io.IOException; +import java.util.concurrent.Callable; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +/** + * Task for synchronizing the registrars spreadsheet. + * + *

You can specify the spreadsheet ID by passing the "id" parameter. If this parameter is not + * specified, then the spreadsheet ID will be obtained from the registry configuration. + * + *

Cron will run this task hourly. So in order to minimize Google Spreadsheets I/O, this task + * will iterate through all registrars and check if any entries were modified in the past hour. If + * no modifications were made, the task will exit without performing any syncing. + * + *

Note: Setting the "id" parameter will disable the registrar update check. + * + *

Before using this service, you should make sure all the column headers listed in this source + * file are present. You also need to share the spreadsheet with the email address from the JSON + * credential file and give it edit permission. + * + * @see SyncRegistrarsSheet + */ +@Action(path = SyncRegistrarsSheetTask.PATH, method = POST) +public class SyncRegistrarsSheetTask implements Runnable { + + private enum Result { + OK(SC_OK, "Sheet successfully updated."), + NOTMODIFIED(SC_OK, "Registrars table hasn't been modified in past hour."), + LOCKED(SC_NO_CONTENT, "Another task is currently writing to this sheet; dropping task."), + MISSINGNO(SC_BAD_REQUEST, "No sheet ID specified or configured; dropping task.") { + @Override + protected void log(Exception cause) { + logger.warningfmt(cause, "%s", message); + }}, + FAILED(SC_INTERNAL_SERVER_ERROR, "Spreadsheet synchronization failed") { + @Override + protected void log(Exception cause) { + logger.severefmt(cause, "%s", message); + }}; + + private final int statusCode; + protected final String message; + + private Result(int statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + } + + /** Log an error message. Results that use log levels other than info should override this. */ + protected void log(@Nullable Exception cause) { + logger.infofmt(cause, "%s", message); + } + + private void send(Response response, @Nullable Exception cause) { + log(cause); + response.setStatus(statusCode); + response.setContentType(PLAIN_TEXT_UTF_8); + response.setPayload(String.format("%s %s\n", name(), message)); + } + } + + public static final String PATH = "/_dr/task/syncRegistrarsSheet"; + private static final String QUEUE = "sheet"; + private static final String LOCK_NAME = "Synchronize registrars sheet"; + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static ModulesService modulesService = ModulesServiceFactory.getModulesService(); + + @Inject Response response; + @Inject SyncRegistrarsSheet syncRegistrarsSheet; + @Inject @Config("sheetLockTimeout") Duration timeout; + @Inject @Config("sheetRegistrarId") Optional idConfig; + @Inject @Config("sheetRegistrarInterval") Duration interval; + @Inject @Parameter("id") Optional idParam; + @Inject SyncRegistrarsSheetTask() {} + + @Override + public void run() { + final Optional sheetId = idParam.or(idConfig); + if (!sheetId.isPresent()) { + Result.MISSINGNO.send(response, null); + return; + } + if (!idParam.isPresent()) { + // TODO(b/19082368): Use a cursor. + if (!syncRegistrarsSheet.wasRegistrarsModifiedInLast(interval)) { + Result.NOTMODIFIED.send(response, null); + return; + } + } + String sheetLockName = String.format("%s: %s", LOCK_NAME, sheetId.get()); + Callable runner = new Callable() { + @Nullable + @Override + public Void call() throws IOException { + try { + syncRegistrarsSheet.run(sheetId.get()); + Result.OK.send(response, null); + } catch (IOException | ServiceException e) { + Result.FAILED.send(response, e); + } + return null; + } + }; + if (!Lock.executeWithLocks(runner, getClass(), "", timeout, sheetLockName)) { + // If we fail to acquire the lock, it probably means lots of updates are happening at once, in + // which case it should be safe to not bother. The task queue definition should *not* specify + // max-concurrent-requests for this very reason. + Result.LOCKED.send(response, null); + } + } + + /** Creates, enqueues, and returns a new backend task to sync registrar spreadsheets. */ + public static TaskHandle enqueueBackendTask() { + String hostname = modulesService.getVersionHostname("backend", null); + return getQueue(QUEUE).add(withUrl(PATH).method(Method.GET).header("Host", hostname)); + } +} diff --git a/java/com/google/domain/registry/export/sheet/package-info.java b/java/com/google/domain/registry/export/sheet/package-info.java new file mode 100644 index 000000000..f5248723b --- /dev/null +++ b/java/com/google/domain/registry/export/sheet/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.export.sheet; diff --git a/java/com/google/domain/registry/flows/BUILD b/java/com/google/domain/registry/flows/BUILD new file mode 100644 index 000000000..70135c484 --- /dev/null +++ b/java/com/google/domain/registry/flows/BUILD @@ -0,0 +1,47 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +filegroup( + name = "flows_files", + srcs = glob([ + "*.java", + "**/*.java", + ]), +) + +java_library( + name = "flows", + srcs = glob([ + "*.java", + "**/*.java", + ]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/dns", + "//java/com/google/domain/registry/mapreduce", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/monitoring/whitebox", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/security:servlets", + "//java/com/google/domain/registry/tldconfig/idn", + "//java/com/google/domain/registry/tmch", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/xml", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_mapreduce2:appengine_mapreduce", + "//third_party/java/dagger", + "//third_party/java/joda_money", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/flows/EppConsoleServlet.java b/java/com/google/domain/registry/flows/EppConsoleServlet.java new file mode 100644 index 000000000..0d20224e4 --- /dev/null +++ b/java/com/google/domain/registry/flows/EppConsoleServlet.java @@ -0,0 +1,119 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.appengine.api.users.UserServiceFactory.getUserService; +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.domain.registry.flows.EppServletUtils.handleEppCommandAndWriteResponse; +import static java.lang.System.identityHashCode; + +import com.google.appengine.api.users.User; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.io.ByteStreams; +import com.google.domain.registry.flows.EppException.AuthenticationErrorException; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.security.XsrfProtectedServlet; + +import org.joda.time.Duration; + +import java.io.IOException; + +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** The {@link EppConsoleServlet} runs EPP from the console. It requires GAE user authentication. */ +public class EppConsoleServlet extends XsrfProtectedServlet { + + /** + * Credentials provided by the GAE User service. + * + * @see com.google.appengine.api.users.UserService + */ + public static final class GaeUserCredentials implements TransportCredentials { + + /** User is not logged in as a GAE user. */ + public static class UserNotLoggedInException extends AuthenticationErrorException { + public UserNotLoggedInException() { + super("User is not logged in"); + } + } + + /** GAE user id is not allowed to login as requested registrar. */ + public static class BadGaeUserIdException extends AuthenticationErrorException { + public BadGaeUserIdException(User user) { + super( + "User id is not allowed to login as requested registrar: " + + (nullToEmpty(user.getEmail()))); + } + } + + final User gaeUser; + + @VisibleForTesting + public GaeUserCredentials(@Nullable User gaeUser) { + this.gaeUser = gaeUser; + } + + @Override + public boolean performsLoginCheck() { + return true; + } + + @Override + public void validate(Registrar r) throws AuthenticationErrorException { + if (gaeUser == null) { + throw new UserNotLoggedInException(); + } + // Allow admins to act as any registrar. + if (getUserService().isUserAdmin()) { + return; + } + // Check Registrar's contacts to see if any are associated with this gaeUserId. + final String gaeUserId = gaeUser.getUserId(); + for (RegistrarContact rc : r.getContacts()) { + if (gaeUserId.equals(rc.getGaeUserId())) { + return; + } + } + throw new BadGaeUserIdException(gaeUser); + } + + @Override + public String toString() { + return String.format("GaeUserCredentials@%s{gaeUser: %s}", identityHashCode(this), gaeUser); + } + } + + /** Used by related UI servlets to generate matching XSRF tokens. */ + public static final String XSRF_SCOPE = "console"; + + /** How long generated XSRF tokens for this scope remain valid. */ + public static final Duration XSRF_LIFETIME = Duration.standardDays(1); + + public EppConsoleServlet() { + super(XSRF_SCOPE, false); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + handleEppCommandAndWriteResponse( + ByteStreams.toByteArray(req.getInputStream()), + rsp, + new HttpSessionMetadata( + new GaeUserCredentials(getUserService().getCurrentUser()), req.getSession(true))); + } +} diff --git a/java/com/google/domain/registry/flows/EppController.java b/java/com/google/domain/registry/flows/EppController.java new file mode 100644 index 000000000..e70cab9dc --- /dev/null +++ b/java/com/google/domain/registry/flows/EppController.java @@ -0,0 +1,114 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.EppXmlTransformer.marshalWithLenientRetry; +import static com.google.domain.registry.flows.EppXmlTransformer.unmarshal; +import static com.google.domain.registry.flows.FlowRegistry.getFlowClass; + +import com.google.apphosting.api.ApiProxy; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.FlowRunner.CommitMode; +import com.google.domain.registry.flows.FlowRunner.UserPrivileges; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response; +import com.google.domain.registry.model.eppoutput.Result; +import com.google.domain.registry.model.eppoutput.Result.Code; +import com.google.domain.registry.monitoring.whitebox.EppMetrics; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.SystemClock; + +/** + * The EppController class, which implements the state machine for the EPP command/response + * protocol. + * + * @see "http://tools.ietf.org/html/rfc5730" + */ +public final class EppController { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final Clock clock = new SystemClock(); + + /** + * Read an EPP envelope from the client, find the matching flow, execute it, and return + * the response marshalled to a byte array. + */ + public static byte[] handleEppCommand(byte[] inputXmlBytes, SessionMetadata sessionMetadata) { + Trid trid = null; + EppMetrics metrics = new EppMetrics(); + metrics.setRequestId( + ApiProxy.getCurrentEnvironment().getAttributes().get( + "com.google.appengine.runtime.request_log_id").toString()); + try { + EppInput eppInput = unmarshal(inputXmlBytes); + trid = Trid.create(eppInput.getCommandWrapper().getClTrid()); + ImmutableList targetIds = eppInput.getTargetIds(); + metrics.setCommandName(eppInput.getCommandName()); + metrics.setClientId(sessionMetadata.getClientId()); + metrics.setPrivilegeLevel( + sessionMetadata.isSuperuser() + ? UserPrivileges.SUPERUSER.toString() + : UserPrivileges.NORMAL.toString()); + if (!targetIds.isEmpty()) { + metrics.setEppTarget(Joiner.on(",").join(targetIds)); + } + + FlowRunner flowRunner = new FlowRunner( + getFlowClass(eppInput), + eppInput, + trid, + sessionMetadata, + inputXmlBytes, + metrics); + EppOutput eppOutput = flowRunner.run( + sessionMetadata.isDryRun() ? CommitMode.DRY_RUN : CommitMode.LIVE, + sessionMetadata.isSuperuser() ? UserPrivileges.SUPERUSER : UserPrivileges.NORMAL); + if (eppOutput.isResponse()) { + metrics.setEppStatus(eppOutput.getResponse().getResult().getCode()); + } + return marshalWithLenientRetry(eppOutput); + } catch (EppException e) { + // The command failed. Send the client an error message. + metrics.setEppStatus(e.getResult().getCode()); + return marshalWithLenientRetry(getErrorResponse(e.getResult(), trid)); + } catch (Throwable e) { + // Something bad and unexpected happened. Send the client a generic error, and log it. + logger.severe(e, "Unexpected failure"); + metrics.setEppStatus(Code.CommandFailed); + return marshalWithLenientRetry(getErrorResponse(Result.create(Code.CommandFailed), trid)); + } finally { + metrics.export(); + } + } + + /** Create a response indicating an Epp failure. */ + @VisibleForTesting + static EppOutput getErrorResponse(Result result, Trid trid) { + // Create TRID (without a clTRID) if one hasn't been created yet, as it's necessary to construct + // a valid response. This can happen if the error occurred before we could even parse out the + // clTRID (e.g. if a syntax error occurred parsing the supplied XML). + return EppOutput.create(new Response.Builder() + .setTrid(trid == null ? Trid.create(null) : trid) + .setResult(result) + .setExecutionTime(clock.nowUtc()) + .build()); + } +} diff --git a/java/com/google/domain/registry/flows/EppException.java b/java/com/google/domain/registry/flows/EppException.java new file mode 100644 index 000000000..c06a145fa --- /dev/null +++ b/java/com/google/domain/registry/flows/EppException.java @@ -0,0 +1,240 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.common.base.Preconditions; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.eppinput.EppInput.InnerCommand; +import com.google.domain.registry.model.eppinput.ResourceCommand; +import com.google.domain.registry.model.eppoutput.Result; +import com.google.domain.registry.model.eppoutput.Result.Code; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** Exception used to propagate all failures containing one or more EPP responses. */ +public abstract class EppException extends Exception { + + private final Result result; + + /** Create an EppException with a custom message. */ + private EppException(String message) { + super(message); + Code code = getClass().getAnnotation(EppResultCode.class).value(); + Preconditions.checkState(!code.isSuccess()); + this.result = Result.create(code, message); + } + + /** Create an EppException with the default message for this code. */ + private EppException() { + this(null); + } + + public Result getResult() { + return result; + } + + /** Annotation for associating an EPP Result.Code value with an EppException subclass. */ + @Documented + @Inherited + @Retention(RUNTIME) + @Target(TYPE) + public @interface EppResultCode { + /** The Code value associated with this exception. */ + Code value(); + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.AuthenticationError) + public abstract static class AuthenticationErrorException extends EppException { + public AuthenticationErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.AuthenticationErrorClosingConnection) + public abstract static class AuthenticationErrorClosingConnectionException extends EppException { + public AuthenticationErrorClosingConnectionException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.AuthorizationError) + public abstract static class AuthorizationErrorException extends EppException { + public AuthorizationErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.InvalidAuthorizationInformationError) + public abstract static class InvalidAuthorizationInformationErrorException extends EppException { + public InvalidAuthorizationInformationErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.CommandUseError) + public abstract static class CommandUseErrorException extends EppException { + public CommandUseErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ObjectExists) + public abstract static class ObjectAlreadyExistsException extends EppException { + public ObjectAlreadyExistsException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ObjectDoesNotExist) + public abstract static class ObjectDoesNotExistException extends EppException { + public ObjectDoesNotExistException(Class type, String id) { + super( + String.format( + "The %s with given ID (%s) doesn't exist.", + !type.isAnnotationPresent(ExternalMessagingName.class) + ? "object" + : type.getAnnotation(ExternalMessagingName.class).value(), + id)); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ObjectPendingTransfer) + public abstract static class ObjectPendingTransferException extends EppException { + public ObjectPendingTransferException(String id) { + super(String.format("Object with given ID (%s) already has a pending transfer.", id)); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ObjectNotPendingTransfer) + public abstract static class ObjectNotPendingTransferException extends EppException { + public ObjectNotPendingTransferException(String id) { + super(String.format("Object with given ID (%s) does not have a pending transfer.", id)); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.AssociationProhibitsOperation) + public abstract static class AssociationProhibitsOperationException extends EppException { + public AssociationProhibitsOperationException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ParameterValuePolicyError) + public abstract static class ParameterValuePolicyErrorException extends EppException { + public ParameterValuePolicyErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ParameterValueRangeError) + public abstract static class ParameterValueRangeErrorException extends EppException { + public ParameterValueRangeErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.ParameterValueSyntaxError) + public abstract static class ParameterValueSyntaxErrorException extends EppException { + public ParameterValueSyntaxErrorException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.RequiredParameterMissing) + public abstract static class RequiredParameterMissingException extends EppException { + public RequiredParameterMissingException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.StatusProhibitsOperation) + public abstract static class StatusProhibitsOperationException extends EppException { + public StatusProhibitsOperationException(String message) { + super(message); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.SyntaxError) + public abstract static class SyntaxErrorException extends EppException { + public SyntaxErrorException(String message) { + super(message); + } + } + + /** Specified command is not implemented. */ + @EppResultCode(Code.UnimplementedCommand) + public static class UnimplementedCommandException extends EppException { + public UnimplementedCommandException(InnerCommand command, ResourceCommand resourceCommand) { + super(String.format( + "No flow found for %s with extension %s", + command.getClass().getSimpleName(), + resourceCommand == null ? null : resourceCommand.getClass().getSimpleName())); + } + } + + /** Abstract exception class. Do not throw this directly or catch in tests. */ + @EppResultCode(Code.UnimplementedOption) + public abstract static class UnimplementedOptionException extends EppException { + public UnimplementedOptionException(String message) { + super(message); + } + } + + /** Specified extension is not implemented. */ + @EppResultCode(Code.UnimplementedExtension) + public static class UnimplementedExtensionException extends EppException { + public UnimplementedExtensionException() { + super("Specified extension is not implemented"); + } + } + + /** Specified object service is not implemented. */ + @EppResultCode(Code.UnimplementedObjectService) + public static class UnimplementedObjectServiceException extends EppException { + public UnimplementedObjectServiceException() { + super("Specified object service is not implemented"); + } + } + + /** Specified protocol version is not implemented. */ + @EppResultCode(Code.UnimplementedProtocolVersion) + public static class UnimplementedProtocolVersionException extends EppException { + public UnimplementedProtocolVersionException() { + super("Specified protocol version is not implemented"); + } + } +} diff --git a/java/com/google/domain/registry/flows/EppServletUtils.java b/java/com/google/domain/registry/flows/EppServletUtils.java new file mode 100644 index 000000000..f6ff2d31a --- /dev/null +++ b/java/com/google/domain/registry/flows/EppServletUtils.java @@ -0,0 +1,67 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.EppController.handleEppCommand; +import static java.nio.charset.StandardCharsets.UTF_8; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.net.MediaType; +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.http.HttpServletResponse; + +/** Utility methods for Epp servlet classes. */ +public final class EppServletUtils { + + public static final MediaType APPLICATION_EPP_XML_UTF8 = + MediaType.create("application", "epp+xml").withCharset(UTF_8); + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * Handle an EPP request and write out a servlet response. + * + * @throws IOException upon failure writing to {@code rsp} + */ + static void handleEppCommandAndWriteResponse( + byte[] inputXmlBytes, HttpServletResponse rsp, SessionMetadata sessionMetadata) + throws IOException { + byte[] response; + try { + response = handleEppCommand(inputXmlBytes, sessionMetadata); + } catch (Exception e) { + logger.warning(e, "handleEppCommand general exception"); + rsp.setStatus(SC_BAD_REQUEST); + return; + } + // Note that we always return 200 (OK) even if the EppController returns an error response. + // This is because returning an non-OK HTTP status code will cause the proxy server to + // silently close the connection without returning any data. The only time we will ever return + // a non-OK status (400) is if we fail to muster even an EPP error response message. In that + // case it's better to close the connection than to return garbage. + rsp.setStatus(SC_OK); + rsp.setContentType(APPLICATION_EPP_XML_UTF8.toString()); + try (OutputStream output = rsp.getOutputStream()) { + output.write(response); + } + } + + private EppServletUtils() {} +} diff --git a/java/com/google/domain/registry/flows/EppTlsServlet.java b/java/com/google/domain/registry/flows/EppTlsServlet.java new file mode 100644 index 000000000..843a826cd --- /dev/null +++ b/java/com/google/domain/registry/flows/EppTlsServlet.java @@ -0,0 +1,72 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.io.ByteStreams.toByteArray; +import static com.google.domain.registry.flows.EppServletUtils.handleEppCommandAndWriteResponse; + +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * The {@link EppTlsServlet} class establishes a transport for EPP+TLS over* HTTP. All commands and + * responses are EPP XML according to RFC 5730. Commands must must requested via POST. + *

+ * There are a number of expected headers to this endpoint: + *

+ *
{@value #SSL_CLIENT_CERTIFICATE_HASH_FIELD} + *
+ * This field should contain a base64 encoded digest of the client's TLS certificate. It is + * validated during an EPP login command against a known good value that is transmitted out of + * band. + *
{@value #FORWARDED_FOR_FIELD} + *
+ * This field should contain the host and port of the connecting client. It is validated during + * an EPP login command against an IP whitelist that is transmitted out of band. + *
{@value #REQUESTED_SERVERNAME_VIA_SNI_FIELD} + *
+ * This field should contain the servername that the client requested during the TLS handshake. + * It is unused, but expected to be present in the GFE-proxied configuration. + *
+ */ +public class EppTlsServlet extends HttpServlet { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + static final String REQUESTED_SERVERNAME_VIA_SNI_FIELD = "X-GFE-Requested-Servername-SNI"; + static final String FORWARDED_FOR_FIELD = "X-Forwarded-For"; + static final String SSL_CLIENT_CERTIFICATE_HASH_FIELD = "X-GFE-SSL-Certificate"; + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + // Check that SNI header is present. This is a signal that we're receiving traffic proxied by a + // GFE, which is the expectation of this servlet. The value is unused. + TlsCredentials tlsCredentials = new TlsCredentials(req); + if (!tlsCredentials.hasSni()) { + logger.warning("Request did not include required SNI header."); + } + SessionMetadata sessionMetadata = new HttpSessionMetadata(tlsCredentials, req.getSession(true)); + // Note that we are using the raw input stream rather than the reader, which implies that we are + // ignoring the HTTP-specified charset (if any) in favor of whatever charset the XML declares. + // This is ok because this code is only called from the proxy, which can't specify a charset + // (it blindly copies bytes off a socket). + handleEppCommandAndWriteResponse(toByteArray(req.getInputStream()), rsp, sessionMetadata); + } +} diff --git a/java/com/google/domain/registry/flows/EppToolServlet.java b/java/com/google/domain/registry/flows/EppToolServlet.java new file mode 100644 index 000000000..2164a437d --- /dev/null +++ b/java/com/google/domain/registry/flows/EppToolServlet.java @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.EppServletUtils.handleEppCommandAndWriteResponse; + +import com.google.common.io.ByteStreams; +import com.google.domain.registry.flows.SessionMetadata.SessionSource; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition; +import com.google.domain.registry.security.XsrfProtectedServlet; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * This servlet runs EPP commands directly without logging in. It verifies an XSRF token that could + * only come from the tool. + */ +public class EppToolServlet extends XsrfProtectedServlet { + + /** Used to verify XSRF tokens. */ + public static final String XSRF_SCOPE = "admin"; + + public EppToolServlet() { + super(XSRF_SCOPE, true); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + byte[] xml = ByteStreams.toByteArray(req.getInputStream()); + handleEppCommandAndWriteResponse( + xml, rsp, new StatelessRequestSessionMetadata( + req.getParameter("clientIdentifier"), + Boolean.parseBoolean(req.getParameter("superuser")), + Boolean.parseBoolean(req.getParameter("dryRun")), + ProtocolDefinition.getVisibleServiceExtensionUris(), + SessionSource.TOOL)); + } +} diff --git a/java/com/google/domain/registry/flows/EppXmlTransformer.java b/java/com/google/domain/registry/flows/EppXmlTransformer.java new file mode 100644 index 000000000..96a38374b --- /dev/null +++ b/java/com/google/domain/registry/flows/EppXmlTransformer.java @@ -0,0 +1,170 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.xml.ValidationMode.LENIENT; +import static com.google.domain.registry.xml.ValidationMode.STRICT; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.flows.EppException.SyntaxErrorException; +import com.google.domain.registry.flows.EppException.UnimplementedProtocolVersionException; +import com.google.domain.registry.model.EppResourceUtils.InvalidRepoIdException; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppinput.EppInput.WrongProtocolVersionException; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.host.InetAddressAdapter.IpVersionMismatchException; +import com.google.domain.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.xml.ValidationMode; +import com.google.domain.registry.xml.XmlException; +import com.google.domain.registry.xml.XmlTransformer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** {@link XmlTransformer} for marshalling to and from the Epp model classes. */ +public class EppXmlTransformer { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + // Hardcoded XML schemas, ordered with respect to dependency. + private static final ImmutableList SCHEMAS = ImmutableList.of( + "eppcom.xsd", + "epp.xsd", + "contact.xsd", + "host.xsd", + "domain.xsd", + "rgp.xsd", + "secdns.xsd", + "fee.xsd", + "metadata.xsd", + "mark.xsd", + "dsig.xsd", + "smd.xsd", + "launch.xsd", + "allocate.xsd"); + + private static final XmlTransformer INPUT_TRANSFORMER = + new XmlTransformer(SCHEMAS, EppInput.class); + + private static final XmlTransformer OUTPUT_TRANSFORMER = + new XmlTransformer(SCHEMAS, EppOutput.class); + + public static void validateOutput(String xml) throws XmlException { + OUTPUT_TRANSFORMER.validate(xml); + } + + public static T unmarshal(byte[] bytes) throws EppException { + try { + return INPUT_TRANSFORMER.unmarshal(new ByteArrayInputStream(bytes)); + } catch (XmlException e) { + // If this XmlException is wrapping a known type find it. If not, it's a syntax error. + FluentIterable causalChain = FluentIterable.from(Throwables.getCausalChain(e)); + if (!(causalChain.filter(IpVersionMismatchException.class).isEmpty())) { + throw new IpAddressVersionMismatchException(); + } + if (!(causalChain.filter(WrongProtocolVersionException.class).isEmpty())) { + throw new UnimplementedProtocolVersionException(); + } + if (!(causalChain.filter(InvalidRepoIdException.class).isEmpty())) { + throw new InvalidRepoIdEppException(); + } + if (!(causalChain.filter(UnknownCurrencyException.class).isEmpty())) { + throw new UnknownCurrencyEppException(); + } + throw new GenericSyntaxErrorException(e.getMessage()); + } + } + + private static byte[] marshal( + XmlTransformer transformer, + ImmutableObject root, + ValidationMode validation) throws XmlException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + transformer.marshal(root, byteArrayOutputStream, UTF_8, validation); + return byteArrayOutputStream.toByteArray(); + } + + public static byte[] marshal(EppOutput root, ValidationMode validation) throws XmlException { + return marshal(OUTPUT_TRANSFORMER, root, validation); + } + + public static byte[] marshalWithLenientRetry(EppOutput eppOutput) { + checkState(eppOutput != null); + // We need to marshal to a string instead of writing the response directly to the servlet's + // response writer, so that partial results don't get written on failure. + try { + return EppXmlTransformer.marshal(eppOutput, STRICT); + } catch (XmlException e) { + // We failed to marshal with validation. This is very bad, but we can potentially still send + // back slightly invalid xml, so try again without validation. + try { + byte[] lenient = EppXmlTransformer.marshal(eppOutput, LENIENT); + // Marshaling worked even though the results didn't validate against the schema. + logger.severe(e, "Result marshaled but did not validate: " + new String(lenient, UTF_8)); + return lenient; + } catch (XmlException e2) { + throw new RuntimeException(e2); // Failing to marshal at all is not recoverable. + } + } + } + + @VisibleForTesting + public static byte[] marshalInput(EppInput root, ValidationMode validation) throws XmlException { + return marshal(INPUT_TRANSFORMER, root, validation); + } + + @VisibleForTesting + public static void validateInput(String xml) throws XmlException { + INPUT_TRANSFORMER.validate(xml); + } + + /** IP address version mismatch. */ + public static class IpAddressVersionMismatchException extends ParameterValueRangeErrorException { + public IpAddressVersionMismatchException() { + super("IP adddress version mismatch"); + } + } + + /** Invalid format for repository id. */ + public static class InvalidRepoIdEppException extends ParameterValueSyntaxErrorException { + public InvalidRepoIdEppException() { + super("Invalid format for repository id"); + } + } + + /** Unknown currency. */ + static class UnknownCurrencyEppException extends ParameterValueRangeErrorException { + public UnknownCurrencyEppException() { + super("Unknown currency."); + } + } + + /** Generic syntax error that can be thrown by any flow. */ + static class GenericSyntaxErrorException extends SyntaxErrorException { + public GenericSyntaxErrorException(String message) { + super(message); + } + } +} + diff --git a/java/com/google/domain/registry/flows/Flow.java b/java/com/google/domain/registry/flows/Flow.java new file mode 100644 index 000000000..a6df8adda --- /dev/null +++ b/java/com/google/domain/registry/flows/Flow.java @@ -0,0 +1,130 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.eppoutput.Result; + +import org.joda.time.DateTime; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * An abstract EPP flow. + *

+ * This class also contains static methods for loading an appropriate flow based on model classes. + */ +public abstract class Flow { + + protected EppInput eppInput; + protected SessionMetadata sessionMetadata; + protected Trid trid; + protected DateTime now; + protected byte[] inputXmlBytes; + + /** Whether this flow is being run in a superuser mode that can skip some checks. */ + protected boolean superuser; + + /** The collection of allowed extensions for the flow. */ + private Set> validExtensions = new HashSet<>(); + + /** Flows can override this for custom initialization. */ + @SuppressWarnings("unused") + protected void initFlow() throws EppException {} + + /** Execute the business logic for this flow. */ + protected abstract EppOutput run() throws EppException; + + /** + * Subclasses that create a resource should override this to return the repoId of the new + * resource. + */ + protected String getCreatedRepoId() { + return null; + } + + protected String getClientId() { + return sessionMetadata.getClientId(); + } + + protected EppOutput createOutput(Result.Code code) { + return createOutput(code, null); + } + + protected EppOutput createOutput(Result.Code code, ResponseData responseData) { + return createOutput(code, responseData, null); + } + + protected EppOutput createOutput( + Result.Code code, + ResponseData responseData, + ImmutableList extensions) { + return EppOutput.create(new Response.Builder() + .setTrid(trid) + .setResult(Result.create(code)) + .setExecutionTime(now) + .setCreatedRepoId(getCreatedRepoId()) + .setResData(responseData == null ? null : ImmutableList.of(responseData)) + .setExtensions(extensions) + .build()); + } + + /** + * Using an init function instead of a constructor avoids duplicating constructors across the + * entire hierarchy of flow classes + */ + public final Flow init( + EppInput eppInput, + Trid trid, + SessionMetadata sessionMetadata, + boolean superuser, + DateTime now, + byte[] inputXmlBytes) throws EppException { + this.eppInput = eppInput; + this.trid = trid; + this.sessionMetadata = sessionMetadata; + this.now = now; + this.superuser = superuser; + this.inputXmlBytes = inputXmlBytes; + initFlow(); + validExtensions = ImmutableSet.copyOf(validExtensions); + return this; + } + + /** + * Add an extension class as a valid extension for a flow. + * Must be called in the init series of methods, as the validExtensions + * becomes immutable once init is complete. + */ + @SafeVarargs + protected final void registerExtensions(Class... extensions) { + Collections.addAll(validExtensions, extensions); + } + + /** Get the legal command extension types for this flow. */ + protected final Set> getValidRequestExtensions() { + return ImmutableSet.copyOf(validExtensions); + } +} diff --git a/java/com/google/domain/registry/flows/FlowRegistry.java b/java/com/google/domain/registry/flows/FlowRegistry.java new file mode 100644 index 000000000..bf58df928 --- /dev/null +++ b/java/com/google/domain/registry/flows/FlowRegistry.java @@ -0,0 +1,334 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.domain.launch.LaunchCreateExtension.CreateType.APPLICATION; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import com.google.domain.registry.flows.EppException.SyntaxErrorException; +import com.google.domain.registry.flows.EppException.UnimplementedCommandException; +import com.google.domain.registry.flows.contact.ContactCheckFlow; +import com.google.domain.registry.flows.contact.ContactCreateFlow; +import com.google.domain.registry.flows.contact.ContactDeleteFlow; +import com.google.domain.registry.flows.contact.ContactInfoFlow; +import com.google.domain.registry.flows.contact.ContactTransferApproveFlow; +import com.google.domain.registry.flows.contact.ContactTransferCancelFlow; +import com.google.domain.registry.flows.contact.ContactTransferQueryFlow; +import com.google.domain.registry.flows.contact.ContactTransferRejectFlow; +import com.google.domain.registry.flows.contact.ContactTransferRequestFlow; +import com.google.domain.registry.flows.contact.ContactUpdateFlow; +import com.google.domain.registry.flows.domain.ClaimsCheckFlow; +import com.google.domain.registry.flows.domain.DomainAllocateFlow; +import com.google.domain.registry.flows.domain.DomainApplicationCreateFlow; +import com.google.domain.registry.flows.domain.DomainApplicationDeleteFlow; +import com.google.domain.registry.flows.domain.DomainApplicationInfoFlow; +import com.google.domain.registry.flows.domain.DomainApplicationUpdateFlow; +import com.google.domain.registry.flows.domain.DomainCheckFlow; +import com.google.domain.registry.flows.domain.DomainCreateFlow; +import com.google.domain.registry.flows.domain.DomainDeleteFlow; +import com.google.domain.registry.flows.domain.DomainInfoFlow; +import com.google.domain.registry.flows.domain.DomainRenewFlow; +import com.google.domain.registry.flows.domain.DomainRestoreRequestFlow; +import com.google.domain.registry.flows.domain.DomainTransferApproveFlow; +import com.google.domain.registry.flows.domain.DomainTransferCancelFlow; +import com.google.domain.registry.flows.domain.DomainTransferQueryFlow; +import com.google.domain.registry.flows.domain.DomainTransferRejectFlow; +import com.google.domain.registry.flows.domain.DomainTransferRequestFlow; +import com.google.domain.registry.flows.domain.DomainUpdateFlow; +import com.google.domain.registry.flows.host.HostCheckFlow; +import com.google.domain.registry.flows.host.HostCreateFlow; +import com.google.domain.registry.flows.host.HostDeleteFlow; +import com.google.domain.registry.flows.host.HostInfoFlow; +import com.google.domain.registry.flows.host.HostUpdateFlow; +import com.google.domain.registry.flows.poll.PollAckFlow; +import com.google.domain.registry.flows.poll.PollRequestFlow; +import com.google.domain.registry.flows.session.HelloFlow; +import com.google.domain.registry.flows.session.LoginFlow; +import com.google.domain.registry.flows.session.LogoutFlow; +import com.google.domain.registry.model.contact.ContactCommand; +import com.google.domain.registry.model.domain.DomainCommand; +import com.google.domain.registry.model.domain.allocate.AllocateCreateExtension; +import com.google.domain.registry.model.domain.launch.ApplicationIdTargetExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckExtension.CheckType; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchPhase; +import com.google.domain.registry.model.domain.rgp.RestoreCommand.RestoreOp; +import com.google.domain.registry.model.domain.rgp.RgpUpdateExtension; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppinput.EppInput.Hello; +import com.google.domain.registry.model.eppinput.EppInput.InnerCommand; +import com.google.domain.registry.model.eppinput.EppInput.Login; +import com.google.domain.registry.model.eppinput.EppInput.Logout; +import com.google.domain.registry.model.eppinput.EppInput.Poll; +import com.google.domain.registry.model.eppinput.EppInput.ResourceCommandWrapper; +import com.google.domain.registry.model.eppinput.EppInput.Transfer; +import com.google.domain.registry.model.eppinput.EppInput.Transfer.TransferOp; +import com.google.domain.registry.model.eppinput.ResourceCommand; +import com.google.domain.registry.model.host.HostCommand; + +import java.util.Map; +import java.util.Set; + +/** Registry that can select a flow to handle a given Epp command. */ +public class FlowRegistry { + + /** Marker class for unimplemented flows. */ + private abstract static class UnimplementedFlow extends Flow {} + + /** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */ + private abstract static class FlowProvider { + /** Get the flow associated with this {@link EppInput} or return null to signal no match. */ + Class get(EppInput eppInput) { + InnerCommand innerCommand = eppInput.getCommandWrapper().getCommand(); + return get(eppInput, innerCommand, (innerCommand instanceof ResourceCommandWrapper) + ? ((ResourceCommandWrapper) innerCommand).getResourceCommand() : null); + } + + /** + * Subclasses need to implement this to examine the parameters and choose a flow (or null if + * the subclass doesn't know of an appropriate flow. + */ + abstract Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand); + } + + /** The hello flow is keyed on a special {@code CommandWrapper} type. */ + private static final FlowProvider HELLO_FLOW_PROVIDER = new FlowProvider() { + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + return eppInput.getCommandWrapper() instanceof Hello ? HelloFlow.class : null; + }}; + + /** Session flows like login and logout are keyed only on the {@link InnerCommand} type. */ + private static final FlowProvider SESSION_FLOW_PROVIDER = new FlowProvider() { + private final Map, Class> commandFlows = + ImmutableMap., Class>of( + Login.class, LoginFlow.class, + Logout.class, LogoutFlow.class); + + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + return innerCommand == null ? null : commandFlows.get(innerCommand.getClass()); + }}; + + /** Poll flows have an {@link InnerCommand} of type {@link Poll}. */ + private static final FlowProvider POLL_FLOW_PROVIDER = new FlowProvider() { + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + if (!(innerCommand instanceof Poll)) { + return null; + } + switch (((Poll) innerCommand).getPollOp()) { + case ACK: + return PollAckFlow.class; + case REQUEST: + return PollRequestFlow.class; + default: + return UnimplementedFlow.class; + } + }}; + + /** + * The domain restore command is technically a domain {@literal }, but logically a totally + * separate flow. + *

+ * This provider must be tried before {@link #RESOURCE_CRUD_FLOW_PROVIDER}. Otherwise, the regular + * domain update flow will match first. + */ + private static final FlowProvider DOMAIN_RESTORE_FLOW_PROVIDER = new FlowProvider() { + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + if (!(resourceCommand instanceof DomainCommand.Update)) { + return null; + } + RgpUpdateExtension rgpUpdateExtension = eppInput.getSingleExtension(RgpUpdateExtension.class); + if (rgpUpdateExtension == null) { + return null; + } + // Restore command with an op of "report" is not currently supported. + return (rgpUpdateExtension.getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST) + ? DomainRestoreRequestFlow.class + : UnimplementedFlow.class; + }}; + + /** + * The claims check flow is keyed on the type of the {@link ResourceCommand} and on having the + * correct extension with a specific phase value. + */ + private static final FlowProvider DOMAIN_CHECK_FLOW_PROVIDER = new FlowProvider() { + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + if (!(resourceCommand instanceof DomainCommand.Check)) { + return null; + } + LaunchCheckExtension extension = eppInput.getSingleExtension(LaunchCheckExtension.class); + if (extension == null || CheckType.AVAILABILITY.equals(extension.getCheckType())) { + // We don't distinguish between registry phases for "avail", so don't bother checking phase. + return DomainCheckFlow.class; + } + if (CheckType.CLAIMS.equals(extension.getCheckType()) + && LaunchPhase.CLAIMS.equals(extension.getPhase())) { + return ClaimsCheckFlow.class; + } + return null; + }}; + + /** General resource CRUD flows are keyed on the type of their {@link ResourceCommand}. */ + private static final FlowProvider RESOURCE_CRUD_FLOW_PROVIDER = new FlowProvider() { + private final Map, Class> resourceCrudFlows = + new ImmutableMap.Builder, Class>() + .put(ContactCommand.Check.class, ContactCheckFlow.class) + .put(ContactCommand.Create.class, ContactCreateFlow.class) + .put(ContactCommand.Delete.class, ContactDeleteFlow.class) + .put(ContactCommand.Info.class, ContactInfoFlow.class) + .put(ContactCommand.Update.class, ContactUpdateFlow.class) + .put(DomainCommand.Create.class, DomainCreateFlow.class) + .put(DomainCommand.Delete.class, DomainDeleteFlow.class) + .put(DomainCommand.Info.class, DomainInfoFlow.class) + .put(DomainCommand.Renew.class, DomainRenewFlow.class) + .put(DomainCommand.Update.class, DomainUpdateFlow.class) + .put(HostCommand.Check.class, HostCheckFlow.class) + .put(HostCommand.Create.class, HostCreateFlow.class) + .put(HostCommand.Delete.class, HostDeleteFlow.class) + .put(HostCommand.Info.class, HostInfoFlow.class) + .put(HostCommand.Update.class, HostUpdateFlow.class) + .build(); + + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + return resourceCommand == null ? null : resourceCrudFlows.get(resourceCommand.getClass()); + }}; + + /** The domain allocate flow has a specific extension. */ + private static final FlowProvider ALLOCATE_FLOW_PROVIDER = new FlowProvider() { + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + return (resourceCommand instanceof DomainCommand.Create + && eppInput.getSingleExtension(AllocateCreateExtension.class) != null) + ? DomainAllocateFlow.class : null; + }}; + + /** + * Application CRUD flows have an extension and are keyed on the type of their + * {@link ResourceCommand}. + */ + private static final FlowProvider APPLICATION_CRUD_FLOW_PROVIDER = new FlowProvider() { + + private final Map, Class> applicationFlows = + ImmutableMap., Class>of( + DomainCommand.Create.class, DomainApplicationCreateFlow.class, + DomainCommand.Delete.class, DomainApplicationDeleteFlow.class, + DomainCommand.Info.class, DomainApplicationInfoFlow.class, + DomainCommand.Update.class, DomainApplicationUpdateFlow.class); + + private final Set launchPhases = ImmutableSet.of( + LaunchPhase.SUNRISE, LaunchPhase.SUNRUSH, LaunchPhase.LANDRUSH); + + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + if (eppInput.getSingleExtension(ApplicationIdTargetExtension.class) != null) { + return applicationFlows.get(resourceCommand.getClass()); + } + LaunchCreateExtension createExtension = + eppInput.getSingleExtension(LaunchCreateExtension.class); + // Return a flow if the type is APPLICATION, or if it's null and we are in a launch phase. + // If the type is specified as REGISTRATION, return null. + if (createExtension != null) { + LaunchPhase launchPhase = createExtension.getPhase(); + if (APPLICATION.equals(createExtension.getCreateType()) + || (createExtension.getCreateType() == null && launchPhases.contains(launchPhase))) { + return applicationFlows.get(resourceCommand.getClass()); + } + } + return null; + }}; + + /** Transfer flows have an {@link InnerCommand} of type {@link Transfer}. */ + private static final FlowProvider TRANSFER_FLOW_PROVIDER = new FlowProvider() { + private final Table, TransferOp, Class> transferFlows = ImmutableTable + ., TransferOp, Class>builder() + .put(ContactCommand.Transfer.class, TransferOp.APPROVE, ContactTransferApproveFlow.class) + .put(ContactCommand.Transfer.class, TransferOp.CANCEL, ContactTransferCancelFlow.class) + .put(ContactCommand.Transfer.class, TransferOp.QUERY, ContactTransferQueryFlow.class) + .put(ContactCommand.Transfer.class, TransferOp.REJECT, ContactTransferRejectFlow.class) + .put(ContactCommand.Transfer.class, TransferOp.REQUEST, ContactTransferRequestFlow.class) + .put(DomainCommand.Transfer.class, TransferOp.APPROVE, DomainTransferApproveFlow.class) + .put(DomainCommand.Transfer.class, TransferOp.CANCEL, DomainTransferCancelFlow.class) + .put(DomainCommand.Transfer.class, TransferOp.QUERY, DomainTransferQueryFlow.class) + .put(DomainCommand.Transfer.class, TransferOp.REJECT, DomainTransferRejectFlow.class) + .put(DomainCommand.Transfer.class, TransferOp.REQUEST, DomainTransferRequestFlow.class) + .build(); + + @Override + Class get( + EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { + return resourceCommand != null && innerCommand instanceof Transfer + ? transferFlows.get(resourceCommand.getClass(), ((Transfer) innerCommand).getTransferOp()) + : null; + }}; + + /** Return the appropriate flow to handle this EPP command. */ + public static Class getFlowClass(EppInput eppInput) throws EppException { + // Do some sanity checking on the input; anything but Hello must have a command type. + InnerCommand innerCommand = eppInput.getCommandWrapper().getCommand(); + if (innerCommand == null && !(eppInput.getCommandWrapper() instanceof Hello)) { + throw new MissingCommandException(); + } + // Try the FlowProviders until we find a match. The order matters because it's possible to + // match multiple FlowProviders and so more specific matches are tried first. + for (FlowProvider flowProvider : new FlowProvider[] { + HELLO_FLOW_PROVIDER, + SESSION_FLOW_PROVIDER, + POLL_FLOW_PROVIDER, + DOMAIN_RESTORE_FLOW_PROVIDER, + ALLOCATE_FLOW_PROVIDER, + APPLICATION_CRUD_FLOW_PROVIDER, + DOMAIN_CHECK_FLOW_PROVIDER, + RESOURCE_CRUD_FLOW_PROVIDER, + TRANSFER_FLOW_PROVIDER}) { + Class flowClass = flowProvider.get(eppInput); + if (flowClass == UnimplementedFlow.class) { + break; // We found it, but it's marked as not implemented. + } + if (flowClass != null) { + return flowClass; // We found it! + } + } + // Nothing usable was found, so throw an exception. + throw new UnimplementedCommandException( + innerCommand, + innerCommand instanceof ResourceCommandWrapper + ? ((ResourceCommandWrapper) innerCommand).getResourceCommand() : null); + } + + /** Command missing. */ + static class MissingCommandException extends SyntaxErrorException { + public MissingCommandException() { + super("Command missing"); + } + } +} diff --git a/java/com/google/domain/registry/flows/FlowRunner.java b/java/com/google/domain/registry/flows/FlowRunner.java new file mode 100644 index 000000000..bda05e152 --- /dev/null +++ b/java/com/google/domain/registry/flows/FlowRunner.java @@ -0,0 +1,191 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Throwables.getStackTraceAsString; +import static com.google.common.base.Throwables.propagateIfInstanceOf; +import static com.google.common.io.BaseEncoding.base64; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.xml.XmlTransformer.prettyPrint; + +import com.google.common.base.Strings; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.monitoring.whitebox.EppMetrics; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; +import com.google.domain.registry.util.TypeUtils; + +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; + +/** Run a flow, either transactionally or not, with logging and retrying as needed. */ +public class FlowRunner { + + private static final String COMMAND_LOG_FORMAT = "EPP Command" + Strings.repeat("\n\t%s", 4); + + /** Whether to actually write to the datastore or just simulate. */ + public enum CommitMode { LIVE, DRY_RUN } + + /** Whether to run in normal or superuser mode. */ + public enum UserPrivileges { NORMAL, SUPERUSER } + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + private final Class flowClass; + private final EppInput eppInput; + private final Trid trid; + private final SessionMetadata sessionMetadata; + private final byte[] inputXmlBytes; + private final EppMetrics metrics; + + public FlowRunner( + Class flowClass, + EppInput eppInput, + Trid trid, + SessionMetadata sessionMetadata, + byte[] inputXmlBytes, + final EppMetrics metrics) { + this.flowClass = flowClass; + this.eppInput = eppInput; + this.trid = trid; + this.sessionMetadata = sessionMetadata; + this.inputXmlBytes = inputXmlBytes; + this.metrics = metrics; + } + + public EppOutput run( + final CommitMode commitMode, final UserPrivileges userPrivileges) throws EppException { + String clientId = sessionMetadata.getClientId(); + final boolean isSuperuser = UserPrivileges.SUPERUSER.equals(userPrivileges); + logger.infofmt( + COMMAND_LOG_FORMAT, + trid.getServerTransactionId(), + clientId, + sessionMetadata, + prettyPrint(inputXmlBytes).replaceAll("\n", "\n\t")); + if (!isTransactional()) { + if (metrics != null) { + metrics.incrementAttempts(); + } + return createAndInitFlow(isSuperuser, clock.nowUtc()).run(); + } + // We log the command in a structured format. Note that we do this before the transaction; + // if we did it after, we might miss a transaction that committed successfully but then crashed + // before it could log. + logger.info("EPP_Mutation " + new JsonLogStatement(trid) + .add("client", clientId) + .add("privileges", userPrivileges.toString()) + .add("xmlBytes", base64().encode(inputXmlBytes))); + try { + EppOutput flowResult = ofy().transact(new Work() { + @Override + public EppOutput run() { + if (metrics != null) { + metrics.incrementAttempts(); + } + try { + EppOutput output = createAndInitFlow(isSuperuser, ofy().getTransactionTime()).run(); + if (CommitMode.DRY_RUN.equals(commitMode)) { + throw new DryRunException(output); + } + return output; + } catch (EppException e) { + throw new RuntimeException(e); + } + }}); + logger.info("EPP_Mutation_Committed " + new JsonLogStatement(trid) + .add("createdRepoId", flowResult.getResponse().getCreatedRepoId()) + .add("executionTime", flowResult.getResponse().getExecutionTime().getMillis())); + return flowResult; + } catch (DryRunException e) { + return e.output; + } catch (RuntimeException e) { + logger.warning("EPP_Mutation_Failed " + new JsonLogStatement(trid)); + logger.warning(getStackTraceAsString(e)); + propagateIfInstanceOf(e.getCause(), EppException.class); + throw e; + } + } + + private Flow createAndInitFlow(boolean superuser, DateTime now) throws EppException { + return TypeUtils.instantiate(flowClass).init( + eppInput, + trid, + sessionMetadata, + superuser, + now, + inputXmlBytes); + } + + public boolean isTransactional() { + return TransactionalFlow.class.isAssignableFrom(flowClass); + } + + /** + * Helper for logging in json format. + *

+ * This is needed because the usual json outputters perform normalizations that we don't want or + * need, since we know that our values never need to be escaped - there are only strings and + * numbers, and the strings are not allowed to contain quote characters. + *

+ * An example output for an EPP_Mutation: + * {"trid":"abc-123", "client":"some_registrar", "tld":"com", "xmlBytes":"abc123DEF"} + *

+ * An example output for an EPP_Mutation_Committed that doesn't create a new resource: + * {"trid":"abc-123", "executionTime":123456789} + *

+ * An example output for an EPP_Mutation_Committed that creates a new resource: + * {"trid":"abc-123", "executionRepoId":123, "executionTime":123456789} + */ + private static class JsonLogStatement { + + StringBuilder message; + + JsonLogStatement(Trid trid) { + message = + new StringBuilder("{\"trid\":\"").append(trid.getServerTransactionId()).append('\"'); + } + + JsonLogStatement add(String key, Object value) { + if (value != null) { + String quote = value instanceof String ? "\"" : ""; + message.append(String.format(", \"%s\":%s%s%s", key, quote, value, quote)); + } + return this; + } + + @Override + public String toString() { + return message + "}"; + } + } + + /** Exception for canceling a transaction while capturing what the output would have been. */ + private class DryRunException extends RuntimeException { + final EppOutput output; + + DryRunException(EppOutput output) { + this.output = output; + } + } +} diff --git a/java/com/google/domain/registry/flows/HttpSessionMetadata.java b/java/com/google/domain/registry/flows/HttpSessionMetadata.java new file mode 100644 index 000000000..ca5436b6f --- /dev/null +++ b/java/com/google/domain/registry/flows/HttpSessionMetadata.java @@ -0,0 +1,61 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Preconditions.checkState; + +import javax.servlet.http.HttpSession; + +/** A metadata class that is a wrapper around {@link HttpSession}. */ +public class HttpSessionMetadata extends SessionMetadata { + + private final HttpSession session; + private boolean isValid = true; + + public HttpSessionMetadata(TransportCredentials credentials, HttpSession session) { + this.session = session; + setTransportCredentials(credentials); + } + + @Override + protected void checkValid() { + checkState(isValid, "This session has been invalidated."); + } + + @Override + public void invalidate() { + session.invalidate(); + isValid = false; + } + + @Override + protected void setProperty(String key, Object value) { + if (value == null) { + session.removeAttribute(key); + } else { + session.setAttribute(key, value); + } + } + + @Override + protected Object getProperty(String key) { + return session.getAttribute(key); + } + + @Override + public SessionSource getSessionSource() { + return SessionSource.HTTP; + } +} diff --git a/java/com/google/domain/registry/flows/LoggedInFlow.java b/java/com/google/domain/registry/flows/LoggedInFlow.java new file mode 100644 index 000000000..3ac451682 --- /dev/null +++ b/java/com/google/domain/registry/flows/LoggedInFlow.java @@ -0,0 +1,135 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.intersection; +import static com.google.domain.registry.model.registry.Registries.getTlds; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.SyntaxErrorException; +import com.google.domain.registry.flows.EppException.UnimplementedExtensionException; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.util.FormattingLogger; + +import java.util.Set; + +/** A flow that requires being logged in. */ +public abstract class LoggedInFlow extends Flow { + + static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * A blacklist of service extension URIs that will cause an error if they are used without being + * declared on login. + */ + private static final ImmutableSet UNDECLARED_URIS_BLACKLIST = + ImmutableSet.of(ServiceExtension.FEE_0_6.getUri()); + + /** + * The TLDs on which the logged-in registrar is allowed access domains. + */ + private ImmutableSet allowedTlds; + + protected ImmutableSet getAllowedTlds() { + return allowedTlds; + } + + @Override + public final void initFlow() throws EppException { + if (getClientId() == null) { + throw new NotLoggedInException(); + } + // Validate that the extensions in the input match what this flow expects. + ImmutableSet> extensionClasses = FluentIterable + .from(eppInput.getCommandWrapper().getExtensions()) + .transform(new Function>() { + @Override + public Class apply(CommandExtension extension) { + return extension.getClass(); + }}) + .toSet(); + if (extensionClasses.size() != eppInput.getCommandWrapper().getExtensions().size()) { + throw new UnsupportedRepeatedExtensionException(); + } + // Validate that we did not receive any undeclared extensions. + ImmutableSet extensionUris = FluentIterable + .from(extensionClasses) + .transform(new Function, String>() { + @Override + public String apply(Class clazz) { + return ProtocolDefinition.ServiceExtension.getCommandExtensionUri(clazz); + }}) + .toSet(); + Set undeclaredUris = difference( + extensionUris, nullToEmpty(sessionMetadata.getServiceExtensionUris())); + if (!undeclaredUris.isEmpty()) { + Set undeclaredUrisThatError = intersection(undeclaredUris, UNDECLARED_URIS_BLACKLIST); + if (!undeclaredUrisThatError.isEmpty()) { + throw new UndeclaredServiceExtensionException(undeclaredUrisThatError); + } else { + logger.warningfmt( + "Client (%s) is attempting to run flow (%s) without declaring URIs %s on login", + getClientId(), getClass().getSimpleName(), undeclaredUris); + } + } + if (sessionMetadata.isSuperuser()) { + allowedTlds = getTlds(); + } else { + Registrar registrar = verifyNotNull( + Registrar.loadByClientId(sessionMetadata.getClientId()), + "Could not load registrar %s", sessionMetadata.getClientId()); + allowedTlds = registrar.getAllowedTlds(); + } + initLoggedInFlow(); + if (!difference(extensionClasses, getValidRequestExtensions()).isEmpty()) { + throw new UnimplementedExtensionException(); + } + } + + @SuppressWarnings("unused") + protected void initLoggedInFlow() throws EppException {} + + /** Registrar is not logged in. */ + public static class NotLoggedInException extends CommandUseErrorException { + public NotLoggedInException() { + super("Registrar is not logged in."); + } + } + + /** Unsupported repetition of an extension. */ + static class UnsupportedRepeatedExtensionException extends SyntaxErrorException { + public UnsupportedRepeatedExtensionException() { + super("Unsupported repetition of an extension"); + } + } + + /** Service extension(s) must be declared at login. */ + public static class UndeclaredServiceExtensionException extends CommandUseErrorException { + public UndeclaredServiceExtensionException(Set undeclaredUris) { + super(String.format("Service extension(s) must be declared at login: %s", + Joiner.on(", ").join(undeclaredUris))); + } + } +} diff --git a/java/com/google/domain/registry/flows/OwnedResourceMutateFlow.java b/java/com/google/domain/registry/flows/OwnedResourceMutateFlow.java new file mode 100644 index 000000000..7a846be1b --- /dev/null +++ b/java/com/google/domain/registry/flows/OwnedResourceMutateFlow.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyResourceOwnership; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; + +/** + * An EPP flow that mutates a single stored resource that is owned by the current registrar. + * + * @param the resource type being changed + * @param the command type, marshalled directly from the epp xml + */ +public abstract class OwnedResourceMutateFlow + + extends ResourceMutateFlow { + /** Fail if the object doesn't exist or was deleted. */ + @Override + protected final void verifyMutationAllowed() throws EppException { + if (!superuser) { + verifyResourceOwnership(getClientId(), existingResource); + } + verifyMutationOnOwnedResourceAllowed(); + } + + /** Check invariants before allowing the command to proceed. */ + @SuppressWarnings("unused") + protected void verifyMutationOnOwnedResourceAllowed() throws EppException {} +} diff --git a/java/com/google/domain/registry/flows/OwnedResourceMutatePendingTransferFlow.java b/java/com/google/domain/registry/flows/OwnedResourceMutatePendingTransferFlow.java new file mode 100644 index 000000000..927933b9d --- /dev/null +++ b/java/com/google/domain/registry/flows/OwnedResourceMutatePendingTransferFlow.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyResourceOwnership; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; + +/** + * An EPP flow that acts on an owned resource with a pending transfer on it. + * + * @param the resource type being manipulated + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class OwnedResourceMutatePendingTransferFlow + , C extends SingleResourceCommand> + extends ResourceMutatePendingTransferFlow { + + /** Fail if this command isn't coming from the registrar that currently owns the resource. */ + @Override + protected final void verifyPendingTransferMutationAllowed() throws EppException { + verifyResourceOwnership(getClientId(), existingResource); + verifyOwnedResourcePendingTransferMutationAllowed(); + } + + @SuppressWarnings("unused") + protected void verifyOwnedResourcePendingTransferMutationAllowed() throws EppException {} +} diff --git a/java/com/google/domain/registry/flows/ResourceAsyncDeleteFlow.java b/java/com/google/domain/registry/flows/ResourceAsyncDeleteFlow.java new file mode 100644 index 000000000..7c2dc9a0d --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceAsyncDeleteFlow.java @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithActionPending; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.flows.EppException.AssociationProhibitsOperationException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.Result.Code; +import com.google.domain.registry.model.index.ForeignKeyIndex; + +import com.googlecode.objectify.Work; + +/** + * An EPP flow that deletes a resource asynchronously (i.e. via mapreduce). + * + * @param the resource type being changed + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceAsyncDeleteFlow + , C extends SingleResourceCommand> + extends ResourceDeleteFlow { + + @Override + public void failfast() throws ResourceToDeleteIsReferencedException { + // Enter a transactionless context briefly. + boolean isLinked = ofy().doTransactionless(new Work() { + @Override + public Boolean run() { + ForeignKeyIndex fki = ForeignKeyIndex.load(resourceClass, targetId, now); + if (fki == null) { + // Don't failfast on non-existence. We could, but that would duplicate code paths in a way + // that would be hard to reason about, and there's no real gain in doing so. + return false; + } + return isLinkedForFailfast(ReferenceUnion.create(fki.getReference())); + } + }); + if (isLinked) { + throw new ResourceToDeleteIsReferencedException(); + } + } + + /** Subclasses must override this to check if the supplied reference has incoming links. */ + protected abstract boolean isLinkedForFailfast(ReferenceUnion ref); + + @Override + protected final R createOrMutateResource() { + @SuppressWarnings("unchecked") + B builder = (B) existingResource.asBuilder().addStatusValue(StatusValue.PENDING_DELETE); + return builder.build(); + } + + /** Subclasses can override this to return a different success result code. */ + @Override + protected Code getDeleteResultCode() { + return SuccessWithActionPending; + } + + /** Resource to be deleted has active incoming references. */ + public static class ResourceToDeleteIsReferencedException + extends AssociationProhibitsOperationException { + public ResourceToDeleteIsReferencedException() { + super("Resource to be deleted has active incoming references"); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceCheckFlow.java b/java/com/google/domain/registry/flows/ResourceCheckFlow.java new file mode 100644 index 000000000..a580cfd1d --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceCheckFlow.java @@ -0,0 +1,83 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck; +import com.google.domain.registry.model.eppoutput.CheckData; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import java.util.List; + +/** + * An EPP flow that checks whether resources can be provisioned. + * + * @param the resource type being manipulated + * @param the overall command type doing the manipulation. + */ +public abstract class ResourceCheckFlow + extends ResourceFlow { + + protected List targetIds; + + @Override + protected final void initResourceFlow() throws EppException { + this.targetIds = command.getTargetIds(); + initCheckResourceFlow(); + } + + @Override + protected final EppOutput runResourceFlow() throws EppException { + return createOutput( + Success, + getCheckData(), + getResponseExtensions()); + } + + @Override + protected final void verifyIsAllowed() throws EppException { + if (targetIds.size() > RegistryEnvironment.get().config().getMaxChecks()) { + throw new TooManyResourceChecksException(); + } + } + + @SuppressWarnings("unused") + protected void initCheckResourceFlow() throws EppException {} + + /** Subclasses must implement this to return the check data. */ + protected abstract CheckData getCheckData(); + + /** Subclasses may override this to return extensions. */ + @SuppressWarnings("unused") + protected ImmutableList getResponseExtensions() throws EppException { + return null; + } + + /** Too many resource checks requested in one check command. */ + public static class TooManyResourceChecksException extends ParameterValuePolicyErrorException { + public TooManyResourceChecksException() { + super(String.format( + "No more than %s resources may be checked at a time", + RegistryEnvironment.get().config().getMaxChecks())); + } + } +} + diff --git a/java/com/google/domain/registry/flows/ResourceCreateFlow.java b/java/com/google/domain/registry/flows/ResourceCreateFlow.java new file mode 100644 index 000000000..ab9b152e3 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceCreateFlow.java @@ -0,0 +1,129 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.flows.EppException.ObjectAlreadyExistsException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.index.DomainApplicationIndex; +import com.google.domain.registry.model.index.EppResourceIndex; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import com.googlecode.objectify.Key; + +import javax.annotation.Nullable; + +/** + * An EPP flow that creates a storable resource. + * + * @param the resource type being changed + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceCreateFlow + , + C extends ResourceCreateOrChange & SingleResourceCommand> + extends ResourceCreateOrMutateFlow { + + @Override + protected void initRepoId() { + repoId = createFlowRepoId(); + } + + @Nullable + protected abstract String createFlowRepoId(); + + @Override + protected final void verifyIsAllowed() throws EppException { + if (existingResource != null) { + throw new ResourceAlreadyExistsException(targetId); + } + verifyCreateIsAllowed(); + } + + @Override + protected final R createOrMutateResource() throws EppException { + B builder = new TypeInstantiator(getClass()){}.instantiate(); + command.applyTo(builder); + builder + .setCreationClientId(getClientId()) + .setCurrentSponsorClientId(getClientId()) + .setRepoId(getResourceKey().getName()); + setCreateProperties(builder); + return builder.build(); + } + + /** + * Save a new or updated {@link ForeignKeyIndex} and {@link EppResourceIndex} pointing to what we + * created. + */ + @Override + protected final void modifyRelatedResources() { + if (newResource instanceof ForeignKeyedEppResource) { + ofy().save().entity(ForeignKeyIndex.create(newResource, newResource.getDeletionTime())); + } else if (newResource instanceof DomainApplication) { + ofy().save().entity( + DomainApplicationIndex.createUpdatedInstance((DomainApplication) newResource)); + } + ofy().save().entity(EppResourceIndex.create(Key.create(newResource))); + modifyCreateRelatedResources(); + } + + @Override + protected final String getCreatedRepoId() { + return newResource.getRepoId(); + } + + /** Modify any other resources that need to be informed of this create. */ + protected void modifyCreateRelatedResources() {} + + /** Check resource-specific invariants before allowing the create to proceed. */ + @SuppressWarnings("unused") + protected void verifyCreateIsAllowed() throws EppException {} + + /** Set any resource-specific properties before creating. */ + @SuppressWarnings("unused") + protected void setCreateProperties(B builder) throws EppException {} + + /** Resource with this id already exists. */ + public static class ResourceAlreadyExistsException extends ObjectAlreadyExistsException { + + /** Whether this was thrown from a "failfast" context. Useful for testing. */ + final boolean failfast; + + public ResourceAlreadyExistsException(String resourceId, boolean failfast) { + super(String.format("Object with given ID (%s) already exists", resourceId)); + this.failfast = failfast; + } + + public ResourceAlreadyExistsException(String resourceId) { + this(resourceId, false); + } + + @VisibleForTesting + public boolean isFailfast() { + return failfast; + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceCreateOrMutateFlow.java b/java/com/google/domain/registry/flows/ResourceCreateOrMutateFlow.java new file mode 100644 index 000000000..e9e928393 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceCreateOrMutateFlow.java @@ -0,0 +1,168 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.SessionMetadata.SessionSource; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import com.googlecode.objectify.Key; + +/** + * An EPP flow that creates or mutates a single stored resource. + * + * @param the resource type being changed + * @param the command type, marshalled directly from the epp xml + * + * @error {@link OnlyToolCanPassMetadataException} + */ +public abstract class ResourceCreateOrMutateFlow + extends SingleResourceFlow + implements TransactionalFlow { + + String repoId; + protected R newResource; + protected HistoryEntry historyEntry; + protected MetadataExtension metadataExtension; + + @Override + protected final void initSingleResourceFlow() throws EppException { + metadataExtension = eppInput.getSingleExtension(MetadataExtension.class); + initRepoId(); + initHistoryEntry(); + initResourceCreateOrMutateFlow(); + } + + /** Subclasses can optionally override this for further initialization. */ + @SuppressWarnings("unused") + protected void initResourceCreateOrMutateFlow() throws EppException {} + + /** + * Initializes the repoId on the flow. For mutate flows, the repoId is the same as that of the + * existing resource. For create flows, a new repoId is allocated for the appropriate class. + */ + protected abstract void initRepoId(); + + /** + * Create the history entry associated with this resource create or mutate flow. + */ + private void initHistoryEntry() { + // Don't try to create a historyEntry for mutate flows that are failing because the + // existingResource doesn't actually exist. + historyEntry = (repoId == null) ? null : new HistoryEntry.Builder() + .setType(getHistoryEntryType()) + .setPeriod(getCommandPeriod()) + .setClientId(getClientId()) + .setTrid(trid) + .setModificationTime(now) + .setXmlBytes(storeXmlInHistoryEntry() ? inputXmlBytes : null) + .setBySuperuser(superuser) + .setReason(getHistoryEntryReason()) + .setRequestedByRegistrar(getHistoryEntryRequestedByRegistrar()) + .setParent(getResourceKey()) + .build(); + } + + /** + * Returns a Key pointing to this resource, even if this resource hasn't been initialized or + * persisted yet. + */ + protected Key getResourceKey() { + checkState(repoId != null, + "RepoId hasn't been initialized yet; getResourceKey() called too early"); + Class resourceClazz = new TypeInstantiator(getClass()){}.getExactType(); + return Key.create(null, resourceClazz, repoId); + } + + @Override + protected final EppOutput runResourceFlow() throws EppException { + newResource = createOrMutateResource(); + verifyNewStateIsAllowed(); + validateMetadataExtension(); + modifyRelatedResources(); + enqueueTasks(); + ofy().save().entities(newResource, historyEntry); + return getOutput(); + } + + /** Execute the inner core of the command and returned the created or mutated resource. */ + protected abstract R createOrMutateResource() throws EppException; + + /** Check the new state before writing it. */ + @SuppressWarnings("unused") + protected void verifyNewStateIsAllowed() throws EppException {} + + /** Kick off any tasks that need to happen asynchronously. */ + @SuppressWarnings("unused") + protected void enqueueTasks() throws EppException {} + + /** Modify any other resources that need to be informed of this change. */ + @SuppressWarnings("unused") + protected void modifyRelatedResources() throws EppException {} + + /** Ensure that, if a metadata command exists, it is being passed from a tool-created session. */ + void validateMetadataExtension() throws EppException { + if (!(metadataExtension == null + || sessionMetadata.getSessionSource().equals(SessionSource.TOOL))) { + throw new OnlyToolCanPassMetadataException(); + } + } + + /** Subclasses must override this to specify the type set on the history entry. */ + protected abstract HistoryEntry.Type getHistoryEntryType(); + + /** Subclasses may override this if they do not wish to store the XML of a command. */ + protected boolean storeXmlInHistoryEntry() { return true; } + + /** Retrieve the reason for the history entry. */ + protected String getHistoryEntryReason() { + return metadataExtension != null + ? metadataExtension.getReason() + : null; + } + + /** Retrieve the requested by registrar flag for the history entry. */ + protected Boolean getHistoryEntryRequestedByRegistrar() { + return metadataExtension != null + ? metadataExtension.getRequestedByRegistrar() + : null; + } + + /** + * Subclasses that have a specified period for their command should override this to so that the + * history entry contains the correct data. + */ + protected Period getCommandPeriod() { return null; } + + /** Get the {@link EppOutput} to return. */ + protected abstract EppOutput getOutput() throws EppException; + + /** Only a tool can pass a metadata extension. */ + public static class OnlyToolCanPassMetadataException extends AuthorizationErrorException { + public OnlyToolCanPassMetadataException() { + super("Metadata extensions can only be passed by tools."); + } + } + +} diff --git a/java/com/google/domain/registry/flows/ResourceDeleteFlow.java b/java/com/google/domain/registry/flows/ResourceDeleteFlow.java new file mode 100644 index 000000000..1e9eed6b1 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceDeleteFlow.java @@ -0,0 +1,65 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.eppoutput.Result.Code; + +import java.util.Set; + +/** + * An EPP flow that deletes an {@link EppResource}. + * + * @param the resource type being changed + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceDeleteFlow + extends OwnedResourceMutateFlow { + + private static final Set DELETE_DISALLOWED_STATUSES = ImmutableSet.of( + StatusValue.LINKED, + StatusValue.CLIENT_DELETE_PROHIBITED, + StatusValue.PENDING_DELETE, + StatusValue.SERVER_DELETE_PROHIBITED); + + /** This is intentionally non-final so that subclasses can override the disallowed statuses. */ + @Override + protected Set getDisallowedStatuses() { + return DELETE_DISALLOWED_STATUSES; + } + + @Override + protected final EppOutput getOutput() { + return createOutput(getDeleteResultCode(), null, getDeleteResponseExtensions()); + } + + /** Subclasses can override this to return a different success result code. */ + protected Code getDeleteResultCode() { + return Success; + } + + /** Subclasses can override this to return response extensions. */ + protected ImmutableList getDeleteResponseExtensions() { + return null; + } +} diff --git a/java/com/google/domain/registry/flows/ResourceFlow.java b/java/com/google/domain/registry/flows/ResourceFlow.java new file mode 100644 index 000000000..da322e339 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceFlow.java @@ -0,0 +1,103 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.EppInput.ResourceCommandWrapper; +import com.google.domain.registry.model.eppinput.ResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +/** + * An EPP flow that addresses a stored resource. + * + * @param the resource type being manipulated + * @param the command type doing the manipulation. + */ +public abstract class ResourceFlow + extends LoggedInFlow { + + protected C command; + protected Class resourceClass; + + @Override + @SuppressWarnings("unchecked") + protected final void initLoggedInFlow() throws EppException { + this.command = (C) ((ResourceCommandWrapper) eppInput.getCommandWrapper().getCommand()) + .getResourceCommand(); + this.resourceClass = new TypeInstantiator(getClass()){}.getExactType(); + initResourceFlow(); + } + + /** Resource flows can override this for custom initialization.*/ + protected abstract void initResourceFlow() throws EppException; + + /** + * Loads the target resource and performs authorization and state allowance checks on it before + * delegating to {@link #runResourceFlow()}. + * + * @throws EppException If an error occurred while manipulating the resource. + */ + @Override + public final EppOutput run() throws EppException { + verifyIsAllowed(); + return runResourceFlow(); + } + + /** + * Check that the current action operating within the scope of a single TLD (i.e. an operation on + * a domain) is allowed in the registry phase for the specified TLD that the resource is in. + */ + protected void checkRegistryStateForTld(String tld) throws BadCommandForRegistryPhaseException { + if (!superuser && getDisallowedTldStates().contains(Registry.get(tld).getTldState(now))) { + throw new BadCommandForRegistryPhaseException(); + } + } + + /** + * Get the TLD states during which this command is disallowed. By default all commands can be run + * in any state (except predelegation); Flow subclasses must override this method to disallow any + * further states. + */ + protected ImmutableSet getDisallowedTldStates() { + return Sets.immutableEnumSet(TldState.PREDELEGATION); + } + + /** + * Verifies that the command is allowed on the target resource. + * + * @throws EppException If the command is not allowed on this resource. + */ + protected abstract void verifyIsAllowed() throws EppException; + + /** + * Run the flow. + * + * @throws EppException If something fails while manipulating the resource. + */ + protected abstract EppOutput runResourceFlow() throws EppException; + + /** Command is not allowed in the current registry phase. */ + public static class BadCommandForRegistryPhaseException extends CommandUseErrorException { + public BadCommandForRegistryPhaseException() { + super("Command is not allowed in the current registry phase"); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceFlowUtils.java b/java/com/google/domain/registry/flows/ResourceFlowUtils.java new file mode 100644 index 000000000..f8369fce3 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceFlowUtils.java @@ -0,0 +1,194 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.domain.DomainResource.extendRegistrationWithCap; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.InvalidAuthorizationInformationErrorException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.eppcommon.AuthInfo; +import com.google.domain.registry.model.eppcommon.AuthInfo.BadAuthInfoException; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferResponse; +import com.google.domain.registry.model.transfer.TransferResponse.ContactTransferResponse; +import com.google.domain.registry.model.transfer.TransferResponse.DomainTransferResponse; +import com.google.domain.registry.model.transfer.TransferStatus; + +import org.joda.time.DateTime; + +/** Static utility functions for resource transfer flows. */ +public class ResourceFlowUtils { + + /** Statuses for which an exDate should be added to transfer responses. */ + private static final ImmutableSet ADD_EXDATE_STATUSES = Sets.immutableEnumSet( + TransferStatus.PENDING, TransferStatus.CLIENT_APPROVED, TransferStatus.SERVER_APPROVED); + + /** + * Create a transfer response using the id and type of this resource and the specified + * {@link TransferData}. + */ + public static TransferResponse createTransferResponse( + EppResource eppResource, TransferData transferData, DateTime now) { + assertIsContactOrDomain(eppResource); + TransferResponse.Builder builder; + if (eppResource instanceof ContactResource) { + builder = new ContactTransferResponse.Builder().setContactId(eppResource.getForeignKey()); + } else { + DomainResource domain = (DomainResource) eppResource; + builder = new DomainTransferResponse.Builder() + .setFullyQualifiedDomainNameName(eppResource.getForeignKey()) + .setExtendedRegistrationExpirationTime( + ADD_EXDATE_STATUSES.contains(transferData.getTransferStatus()) + ? extendRegistrationWithCap( + now, + domain.getRegistrationExpirationTime(), + transferData.getExtendedRegistrationYears()) + : null); + } + builder.setGainingClientId(transferData.getGainingClientId()) + .setLosingClientId(transferData.getLosingClientId()) + .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime()) + .setTransferRequestTime(transferData.getTransferRequestTime()) + .setTransferStatus(transferData.getTransferStatus()); + return builder.build(); + } + + /** + * Create a pending action notification response indicating the resolution of a transfer. + *

+ * The returned object will use the id and type of this resource, the trid of the resource's last + * transfer request, and the specified status and date. + */ + public static PendingActionNotificationResponse createPendingTransferNotificationResponse( + EppResource eppResource, + Trid transferRequestTrid, + boolean actionResult, + DateTime processedDate) { + assertIsContactOrDomain(eppResource); + return eppResource instanceof ContactResource + ? ContactPendingActionNotificationResponse.create( + eppResource.getForeignKey(), actionResult, transferRequestTrid, processedDate) + : DomainPendingActionNotificationResponse.create( + eppResource.getForeignKey(), actionResult, transferRequestTrid, processedDate); + } + + private static void assertIsContactOrDomain(EppResource eppResource) { + checkState(eppResource instanceof ContactResource || eppResource instanceof DomainResource); + } + + /** Check that the given clientId corresponds to the owner of given resource. */ + public static void verifyResourceOwnership(String myClientId, EppResource resource) + throws EppException { + if (!myClientId.equals(resource.getCurrentSponsorClientId())) { + throw new ResourceNotOwnedException(); + } + } + + /** + * Performs common deletion operations on an EPP resource and returns a builder for further + * modifications. This is broken out into ResourceFlowUtils in order to expose the functionality + * to async flows (i.e. mapreduces). + */ + @SuppressWarnings("unchecked") + public static Builder> + prepareDeletedResourceAsBuilder(R existingResource, DateTime now) { + Builder> builder = + (Builder>) existingResource.asBuilder() + .setDeletionTime(now) + .setStatusValues(null) + .setTransferData( + existingResource.getStatusValues().contains(StatusValue.PENDING_TRANSFER) + ? existingResource.getTransferData().asBuilder() + .setTransferStatus(TransferStatus.SERVER_CANCELLED) + .setServerApproveEntities(null) + .setServerApproveBillingEvent(null) + .setServerApproveAutorenewEvent(null) + .setServerApproveAutorenewPollMessage(null) + .setPendingTransferExpirationTime(null) + .build() + : existingResource.getTransferData()) + .wipeOut(); + return builder; + } + + /** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */ + public static void updateForeignKeyIndexDeletionTime(R resource) { + if (resource instanceof ForeignKeyedEppResource) { + ofy().save().entity(ForeignKeyIndex.create(resource, resource.getDeletionTime())); + } + } + + /** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */ + public static void handlePendingTransferOnDelete( + R existingResource, R newResource, DateTime now, HistoryEntry historyEntry) { + if (existingResource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { + TransferData oldTransferData = existingResource.getTransferData(); + ofy().delete().keys(oldTransferData.getServerApproveEntities()); + ofy().save().entity(new PollMessage.OneTime.Builder() + .setClientId(oldTransferData.getGainingClientId()) + .setEventTime(now) + .setMsg(TransferStatus.SERVER_CANCELLED.getMessage()) + .setResponseData(ImmutableList.of( + createTransferResponse(newResource, newResource.getTransferData(), now), + createPendingTransferNotificationResponse( + existingResource, oldTransferData.getTransferRequestTrid(), false, now))) + .setParent(historyEntry) + .build()); + } + } + + /** The specified resource belongs to another client. */ + public static class ResourceNotOwnedException extends AuthorizationErrorException { + public ResourceNotOwnedException() { + super("The specified resource belongs to another client"); + } + } + + /** Check that the given AuthInfo is valid for the given resource. */ + public static void verifyAuthInfoForResource(AuthInfo authInfo, EppResource resource) + throws EppException { + try { + authInfo.verifyAuthorizedFor(resource); + } catch (BadAuthInfoException e) { + throw new BadAuthInfoForResourceException(); + } + } + + /** Authorization information for accessing resource is invalid. */ + public static class BadAuthInfoForResourceException + extends InvalidAuthorizationInformationErrorException { + public BadAuthInfoForResourceException() { + super("Authorization information for accessing resource is invalid"); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceInfoFlow.java b/java/com/google/domain/registry/flows/ResourceInfoFlow.java new file mode 100644 index 000000000..9c07764b9 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceInfoFlow.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +/** + * An EPP flow that reads a storable resource. + * + * @param the resource type being manipulated + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceInfoFlow + extends ResourceQueryFlow { + @Override + public EppOutput runResourceFlow() throws EppException { + return createOutput(Success, getResourceInfo(), getResponseExtensions()); + } + + @SuppressWarnings("unused") + protected ResponseData getResourceInfo() throws EppException { + return cloneResourceWithLinkedStatus(existingResource, now); + } + + @SuppressWarnings("unused") + protected ImmutableList getResponseExtensions() throws EppException { + return null; + } +} diff --git a/java/com/google/domain/registry/flows/ResourceMutateFlow.java b/java/com/google/domain/registry/flows/ResourceMutateFlow.java new file mode 100644 index 000000000..f2165571b --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceMutateFlow.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource; + +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +/** + * An EPP flow that mutates a single stored resource. + * + * @param the resource type being changed + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceMutateFlow + extends ResourceCreateOrMutateFlow { + + @Override + protected void initRepoId() { + // existingResource could be null here if the flow is being called to mutate a resource that + // does not exist, in which case don't throw NPE here and allow the non-existence to be handled + // later. + repoId = (existingResource == null) ? null : existingResource.getRepoId(); + } + + /** Fail if the object doesn't exist or was deleted. */ + @Override + protected final void verifyIsAllowed() throws EppException { + if (existingResource == null) { + throw new ResourceToMutateDoesNotExistException( + new TypeInstantiator(getClass()){}.getExactType(), targetId); + } + if (command.getAuthInfo() != null) { + verifyAuthInfoForResource(command.getAuthInfo(), existingResource); + } + verifyMutationAllowed(); + } + + /** Check invariants before allowing the command to proceed. */ + @SuppressWarnings("unused") + protected void verifyMutationAllowed() throws EppException {} + + /** Resource with this id does not exist. */ + public static class ResourceToMutateDoesNotExistException extends ObjectDoesNotExistException { + public ResourceToMutateDoesNotExistException(Class type, String targetId) { + super(type, targetId); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceMutatePendingTransferFlow.java b/java/com/google/domain/registry/flows/ResourceMutatePendingTransferFlow.java new file mode 100644 index 000000000..9e40c9ae1 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceMutatePendingTransferFlow.java @@ -0,0 +1,104 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.flows.EppException.ObjectNotPendingTransferException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; + +/** + * An EPP flow that acts on a resource with a pending transfer on it. + * + * @param the resource type being changed + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceMutatePendingTransferFlow + , C extends SingleResourceCommand> + extends ResourceTransferFlow { + + /** Fail if object doesn't have a pending transfer, or if authinfo doesn't match. */ + @Override + protected final void verifyMutationAllowed() throws EppException { + if (existingResource.getTransferData().getTransferStatus() != TransferStatus.PENDING) { + throw new NotPendingTransferException(targetId); + } + verifyPendingTransferMutationAllowed(); + } + + @SuppressWarnings("unused") + protected void verifyPendingTransferMutationAllowed() throws EppException {} + + @Override + @SuppressWarnings("unchecked") + protected final R createOrMutateResource() { + TransferData transferData = existingResource.getTransferData(); + B builder = (B) existingResource.asBuilder() + .removeStatusValue(StatusValue.PENDING_TRANSFER) + .setTransferData(transferData.asBuilder() + .setTransferStatus(getTransferStatus()) + .setPendingTransferExpirationTime(now) + .setExtendedRegistrationYears(null) + .setServerApproveEntities(null) + .setServerApproveBillingEvent(null) + .setServerApproveAutorenewEvent(null) + .setServerApproveAutorenewPollMessage(null) + .build()); + setTransferMutateProperties(builder); + return builder.build(); + } + + /** Get the new transfer status to set on the resource (and subordinates) after the flow. */ + protected abstract TransferStatus getTransferStatus(); + + /** Set any resource-specific properties for the pending-transfer mutation. */ + protected void setTransferMutateProperties(@SuppressWarnings("unused") B builder) {} + + /** + * Delete the billing event and poll messages that were written in case the transfer would have + * been implicitly server approved. + */ + @Override + protected final void modifyRelatedResources() throws EppException { + modifyRelatedResourcesForMutateTransfer(); + ofy().delete().keys(existingResource.getTransferData().getServerApproveEntities()); + } + + /** Subclasses can override this to make any other model changes that are implied by this flow. */ + @SuppressWarnings("unused") + protected void modifyRelatedResourcesForMutateTransfer() throws EppException {} + + @Override + protected final EppOutput getOutput() throws EppException { + return createOutput( + Success, createTransferResponse(newResource, newResource.getTransferData(), now)); + } + + /** The resource does not have a pending transfer. */ + public static class NotPendingTransferException extends ObjectNotPendingTransferException { + public NotPendingTransferException(String objectId) { + super(objectId); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceQueryFlow.java b/java/com/google/domain/registry/flows/ResourceQueryFlow.java new file mode 100644 index 000000000..c3489798c --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceQueryFlow.java @@ -0,0 +1,55 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource; + +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +/** + * An EPP flow that queries a storable resource. + * + * @param the resource type being queried + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceQueryFlow + extends SingleResourceFlow { + /** Fail if the object doesn't exist or was deleted. */ + @Override + protected final void verifyIsAllowed() throws EppException { + if (existingResource == null) { + throw new ResourceToQueryDoesNotExistException( + new TypeInstantiator(getClass()){}.getExactType(), targetId); + } + if (command.getAuthInfo() != null) { + verifyAuthInfoForResource(command.getAuthInfo(), existingResource); + } + verifyQueryIsAllowed(); + } + + /** Check command- and resource-specific invariants before allowing the query to proceed. */ + @SuppressWarnings("unused") + protected void verifyQueryIsAllowed() throws EppException {} + + /** Resource with this id does not exist. */ + public static class ResourceToQueryDoesNotExistException extends ObjectDoesNotExistException { + public ResourceToQueryDoesNotExistException(Class type, String targetId) { + super(type, targetId); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceSyncDeleteFlow.java b/java/com/google/domain/registry/flows/ResourceSyncDeleteFlow.java new file mode 100644 index 000000000..ee55c9622 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceSyncDeleteFlow.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete; +import static com.google.domain.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder; +import static com.google.domain.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.index.ForeignKeyIndex; + +/** + * An EPP flow that deletes a resource synchronously. + * + * @param the resource type being changed + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceSyncDeleteFlow + , C extends SingleResourceCommand> + extends ResourceDeleteFlow { + + @Override + @SuppressWarnings("unchecked") + protected final R createOrMutateResource() { + B builder = (B) prepareDeletedResourceAsBuilder(existingResource, now); + setDeleteProperties(builder); + return builder.build(); + } + + /** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */ + @Override + protected final void modifyRelatedResources() throws EppException { + updateForeignKeyIndexDeletionTime(newResource); + handlePendingTransferOnDelete(existingResource, newResource, now, historyEntry); + modifySyncDeleteRelatedResources(); + } + + /** Set any resource-specific properties before deleting. */ + @SuppressWarnings("unused") + protected void setDeleteProperties(B builder) {} + + /** Modify any other resources that need to be informed of this delete. */ + protected void modifySyncDeleteRelatedResources() {} +} diff --git a/java/com/google/domain/registry/flows/ResourceTransferApproveFlow.java b/java/com/google/domain/registry/flows/ResourceTransferApproveFlow.java new file mode 100644 index 000000000..822f3706d --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferApproveFlow.java @@ -0,0 +1,73 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse; +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; + +/** + * An EPP flow that approves a transfer on a resource. + * + * @param the resource type being manipulated + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceTransferApproveFlow + , C extends SingleResourceCommand> + extends OwnedResourceMutatePendingTransferFlow { + + @Override + protected final TransferStatus getTransferStatus() { + return TransferStatus.CLIENT_APPROVED; + } + + @Override + protected final void setTransferMutateProperties(B builder) { + builder.setLastTransferTime(now) + .setCurrentSponsorClientId(existingResource.getTransferData().getGainingClientId()); + setTransferApproveProperties(builder); + } + + protected void setTransferApproveProperties(@SuppressWarnings("unused") B builder) {} + + @Override + protected void modifyRelatedResourcesForMutateTransfer() throws EppException { + // Create a poll message for the gaining client. + TransferData oldTransferData = existingResource.getTransferData(); + ofy().save().entity(new PollMessage.OneTime.Builder() + .setClientId(oldTransferData.getGainingClientId()) + .setEventTime(now) + .setMsg(TransferStatus.CLIENT_APPROVED.getMessage()) + .setResponseData(ImmutableList.of( + createTransferResponse(newResource, newResource.getTransferData(), now), + createPendingTransferNotificationResponse( + existingResource, oldTransferData.getTransferRequestTrid(), true, now))) + .setParent(historyEntry) + .build()); + modifyRelatedResourcesForTransferApprove(); + } + + /** Subclasses can override this to modify other transfer-related resources. */ + protected void modifyRelatedResourcesForTransferApprove() {} +} diff --git a/java/com/google/domain/registry/flows/ResourceTransferCancelFlow.java b/java/com/google/domain/registry/flows/ResourceTransferCancelFlow.java new file mode 100644 index 000000000..c8f4eb20b --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferCancelFlow.java @@ -0,0 +1,79 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.transfer.TransferStatus; + +/** + * An EPP flow that cancels a transfer on a resource. + * + * @param the resource type being manipulated + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceTransferCancelFlow + , C extends SingleResourceCommand> + extends ResourceMutatePendingTransferFlow { + + /** Verify that this is the correct client to cancel this pending transfer. */ + @Override + protected final void verifyPendingTransferMutationAllowed() throws EppException { + // TODO(b/18997997): Determine if authInfo is necessary to cancel a transfer. + if (!getClientId().equals(existingResource.getTransferData().getGainingClientId())) { + throw new NotTransferInitiatorException(); + } + verifyTransferCancelMutationAllowed(); + } + + @SuppressWarnings("unused") + protected void verifyTransferCancelMutationAllowed() throws EppException {} + + @Override + protected void modifyRelatedResourcesForMutateTransfer() throws EppException { + ofy().save().entity(new PollMessage.OneTime.Builder() + .setClientId(existingResource.getTransferData().getLosingClientId()) + .setEventTime(now) + .setMsg(TransferStatus.CLIENT_CANCELLED.getMessage()) + .setResponseData(ImmutableList.of( + createTransferResponse(newResource, newResource.getTransferData(), now))) + .setParent(historyEntry) + .build()); + modifyRelatedResourcesForTransferCancel(); + } + + /** Subclasses can override this to modify other cancellation-related resources. */ + protected void modifyRelatedResourcesForTransferCancel() {} + + @Override + protected final TransferStatus getTransferStatus() { + return TransferStatus.CLIENT_CANCELLED; + } + + /** Registrar is not the initiator of this transfer. */ + public static class NotTransferInitiatorException extends AuthorizationErrorException { + public NotTransferInitiatorException() { + super("Registrar is not the initiator of this transfer"); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceTransferFlow.java b/java/com/google/domain/registry/flows/ResourceTransferFlow.java new file mode 100644 index 000000000..b6c481adb --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferFlow.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; + +/** + * An EPP flow that involves a transfer on a resource. + * + * @param the resource type being manipulated + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceTransferFlow + extends ResourceMutateFlow {} diff --git a/java/com/google/domain/registry/flows/ResourceTransferQueryFlow.java b/java/com/google/domain/registry/flows/ResourceTransferQueryFlow.java new file mode 100644 index 000000000..3c0e100c9 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferQueryFlow.java @@ -0,0 +1,72 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; + +/** + * An EPP flow that queries the state of a pending transfer on a resource. + * + * @param the resource type being manipulated + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceTransferQueryFlow extends ResourceQueryFlow { + + @Override + protected final void verifyQueryIsAllowed() throws EppException { + // Most of the fields on the transfer response are required, so there's no way to return valid + // XML if the object has never been transferred (and hence the fields aren't populated). + if (existingResource.getTransferData().getTransferStatus() == null) { + throw new NoTransferHistoryToQueryException(); + } + + // Note that the authorization info on the command (if present) has already been verified by the + // parent class. If it's present, then the other checks are unnecessary. + if (command.getAuthInfo() == null && + !getClientId().equals(existingResource.getTransferData().getGainingClientId()) && + !getClientId().equals(existingResource.getTransferData().getLosingClientId())) { + throw new NotAuthorizedToViewTransferException(); + } + } + + @Override + public final EppOutput runResourceFlow() throws EppException { + return createOutput( + Success, createTransferResponse(existingResource, existingResource.getTransferData(), now)); + } + + /** Registrar is not authorized to view transfer status. */ + public static class NotAuthorizedToViewTransferException + extends AuthorizationErrorException { + public NotAuthorizedToViewTransferException() { + super("Registrar is not authorized to view transfer status"); + } + } + + /** Object has no transfer history. */ + public static class NoTransferHistoryToQueryException extends CommandUseErrorException { + public NoTransferHistoryToQueryException() { + super("Object has no transfer history"); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceTransferRejectFlow.java b/java/com/google/domain/registry/flows/ResourceTransferRejectFlow.java new file mode 100644 index 000000000..8cc96c5e9 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferRejectFlow.java @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse; +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; + +/** + * An EPP flow that rejects a transfer on a resource. + * + * @param the resource type being manipulated + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceTransferRejectFlow + , C extends SingleResourceCommand> + extends OwnedResourceMutatePendingTransferFlow { + + @Override + protected final TransferStatus getTransferStatus() { + return TransferStatus.CLIENT_REJECTED; + } + + @Override + protected void modifyRelatedResourcesForMutateTransfer() throws EppException { + TransferData oldTransferData = existingResource.getTransferData(); + ofy().save().entity(new PollMessage.OneTime.Builder() + .setClientId(oldTransferData.getGainingClientId()) + .setEventTime(now) + .setMsg(TransferStatus.CLIENT_REJECTED.getMessage()) + .setResponseData(ImmutableList.of( + createTransferResponse(newResource, newResource.getTransferData(), now), + createPendingTransferNotificationResponse( + existingResource, oldTransferData.getTransferRequestTrid(), false, now))) + .setParent(historyEntry) + .build()); + modifyRelatedResourcesForTransferReject(); + } + + /** Subclasses can override this to modify other rejection-related resources. */ + protected void modifyRelatedResourcesForTransferReject() {} +} diff --git a/java/com/google/domain/registry/flows/ResourceTransferRequestFlow.java b/java/com/google/domain/registry/flows/ResourceTransferRequestFlow.java new file mode 100644 index 000000000..91352a54f --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceTransferRequestFlow.java @@ -0,0 +1,220 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse; +import static com.google.domain.registry.flows.ResourceFlowUtils.createTransferResponse; +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource; +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithActionPending; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.union; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.ObjectPendingTransferException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferData.TransferServerApproveEntity; +import com.google.domain.registry.model.transfer.TransferStatus; + +import com.googlecode.objectify.Key; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.Set; + +/** + * An EPP flow that requests a transfer on a resource. + * + * @param the resource type being manipulated + * @param the command type, marshalled directly from the epp xml + */ + public abstract class ResourceTransferRequestFlow + extends ResourceTransferFlow { + + private static final Set TRANSFER_DISALLOWED_STATUSES = ImmutableSet.of( + StatusValue.CLIENT_TRANSFER_PROHIBITED, + StatusValue.PENDING_DELETE, + StatusValue.SERVER_TRANSFER_PROHIBITED); + + private DateTime transferExpirationTime; + + /** Helper class to identify the two clients. */ + protected abstract class Client { + public abstract String getId(); + } + + /** The gaining client. */ + protected Client gainingClient = new Client() { + @Override + public String getId() { + return getClientId(); + }}; + + /** The losing client. */ + protected Client losingClient = new Client() { + @Override + public String getId() { + return existingResource.getCurrentSponsorClientId(); + }}; + + @Override + protected final void initResourceCreateOrMutateFlow() { + initResourceTransferRequestFlow(); + } + + protected abstract Duration getAutomaticTransferLength(); + + @Override + protected final void verifyMutationAllowed() throws EppException { + // Verify that the resource does not already have a pending transfer. + if (TransferStatus.PENDING.equals(existingResource.getTransferData().getTransferStatus())) { + throw new AlreadyPendingTransferException(targetId); + } + // Verify that this client doesn't already sponsor this resource. + if (gainingClient.getId().equals(losingClient.getId())) { + throw new ObjectAlreadySponsoredException(); + } + if (command.getAuthInfo() == null) { + throw new MissingTransferRequestAuthInfoException(); + } + verifyAuthInfoForResource(command.getAuthInfo(), existingResource); + verifyTransferRequestIsAllowed(); + } + + private TransferData.Builder createTransferDataBuilder(TransferStatus transferStatus) { + TransferData.Builder builder = new TransferData.Builder() + .setGainingClientId(gainingClient.getId()) + .setTransferRequestTime(now) + .setLosingClientId(losingClient.getId()) + .setPendingTransferExpirationTime(transferExpirationTime) + .setTransferRequestTrid(trid) + .setTransferStatus(transferStatus); + setTransferDataProperties(builder); + return builder; + } + + private PollMessage createPollMessage( + Client client, TransferStatus transferStatus, DateTime eventTime) { + ImmutableList.Builder responseData = new ImmutableList.Builder<>(); + responseData.add(createTransferResponse( + existingResource, createTransferDataBuilder(transferStatus).build(), now)); + if (client.getId().equals(gainingClient.getId())) { + responseData.add(createPendingTransferNotificationResponse( + existingResource, trid, true, now)); + } + return new PollMessage.OneTime.Builder() + .setClientId(client.getId()) + .setEventTime(eventTime) + .setMsg(transferStatus.getMessage()) + .setResponseData(responseData.build()) + .setParent(historyEntry) + .build(); + } + + @Override + @SuppressWarnings("unchecked") + protected final R createOrMutateResource() { + // Figure out transfer expiration time once we've verified that the existingResource does in + // fact exist (otherwise we won't know which TLD to get this figure off of). + transferExpirationTime = now.plus(getAutomaticTransferLength()); + // When a transfer is requested, a poll message is created to notify the losing registrar. + PollMessage requestPollMessage = createPollMessage(losingClient, TransferStatus.PENDING, now); + // If the transfer is server approved, this message will be sent to the gaining registrar. */ + PollMessage serverApproveGainingPollMessage = + createPollMessage(gainingClient, TransferStatus.SERVER_APPROVED, transferExpirationTime); + // If the transfer is server approved, this message will be sent to the losing registrar. */ + PollMessage serverApproveLosingPollMessage = + createPollMessage(losingClient, TransferStatus.SERVER_APPROVED, transferExpirationTime); + ofy().save().entities( + requestPollMessage, serverApproveGainingPollMessage, serverApproveLosingPollMessage); + return (R) existingResource.asBuilder() + .setTransferData(createTransferDataBuilder(TransferStatus.PENDING) + .setServerApproveEntities(union( + getTransferServerApproveEntities(), + Key.create(serverApproveGainingPollMessage), + Key.create(serverApproveLosingPollMessage))) + .build()) + .addStatusValue(StatusValue.PENDING_TRANSFER) + .build(); + } + + /** Subclasses can override this to do further initialization. */ + protected void initResourceTransferRequestFlow() {} + + /** + * Subclasses can override this to return the keys of any entities that need to be deleted if the + * transfer ends in any state other than SERVER_APPROVED. + */ + protected Set> getTransferServerApproveEntities() { + return ImmutableSet.of(); + } + + /** Check resource-specific invariants before allowing the transfer request to proceed. */ + @SuppressWarnings("unused") + protected void verifyTransferRequestIsAllowed() throws EppException {} + + /** Subclasses can override this to modify fields on the transfer data builder. */ + protected void setTransferDataProperties( + @SuppressWarnings("unused") TransferData.Builder builder) {} + + @Override + protected final EppOutput getOutput() throws EppException { + return createOutput( + SuccessWithActionPending, + createTransferResponse(newResource, newResource.getTransferData(), now), + getTransferResponseExtensions()); + } + + /** Subclasses can override this to return response extensions. */ + protected ImmutableList getTransferResponseExtensions() { + return null; + } + + @Override + protected final Set getDisallowedStatuses() { + return TRANSFER_DISALLOWED_STATUSES; + } + + /** Authorization info is required to request a transfer. */ + public static class MissingTransferRequestAuthInfoException extends AuthorizationErrorException { + public MissingTransferRequestAuthInfoException() { + super("Authorization info is required to request a transfer"); + } + } + + /** Registrar already sponsors the object of this transfer request. */ + public static class ObjectAlreadySponsoredException extends CommandUseErrorException { + public ObjectAlreadySponsoredException() { + super("Registrar already sponsors the object of this transfer request"); + } + } + + /** The resource is already pending transfer. */ + public static class AlreadyPendingTransferException extends ObjectPendingTransferException { + public AlreadyPendingTransferException(String targetId) { + super(targetId); + } + } +} diff --git a/java/com/google/domain/registry/flows/ResourceUpdateFlow.java b/java/com/google/domain/registry/flows/ResourceUpdateFlow.java new file mode 100644 index 000000000..af8cd5d75 --- /dev/null +++ b/java/com/google/domain/registry/flows/ResourceUpdateFlow.java @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate; +import com.google.domain.registry.model.eppoutput.EppOutput; + +import java.util.Set; + +/** + * An EPP flow that mutates a single stored resource. + * + * @param the resource type being changed + * @param a builder for the resource + * @param the command type, marshalled directly from the epp xml + */ +public abstract class ResourceUpdateFlow + , C extends ResourceUpdate> + extends OwnedResourceMutateFlow { + + /** + * Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it + * requires special checking, since you must be able to clear the status off the object with an + * update. + */ + private static final Set UPDATE_DISALLOWED_STATUSES = ImmutableSet.of( + StatusValue.PENDING_DELETE, + StatusValue.SERVER_UPDATE_PROHIBITED); + + @Override + protected Set getDisallowedStatuses() { + return UPDATE_DISALLOWED_STATUSES; + } + + @Override + protected final void verifyMutationOnOwnedResourceAllowed() throws EppException { + for (StatusValue statusValue : Sets.union( + command.getInnerAdd().getStatusValues(), + command.getInnerRemove().getStatusValues())) { + if (!superuser && !statusValue.isClientSettable()) { // The superuser can set any status. + throw new StatusNotClientSettableException(statusValue.getXmlName()); + } + } + verifyUpdateIsAllowed(); + } + + @Override + protected final R createOrMutateResource() throws EppException { + @SuppressWarnings("unchecked") + B builder = (B) existingResource.asBuilder(); + try { + command.applyTo(builder); + } catch (AddRemoveSameValueException e) { + throw new AddRemoveSameValueEppException(); + } + builder.setLastEppUpdateTime(now).setLastEppUpdateClientId(getClientId()); + return setUpdateProperties(builder).build(); + } + + @Override + protected final void verifyNewStateIsAllowed() throws EppException { + // If the resource is marked with clientUpdateProhibited, and this update did not clear that + // status, then the update must be disallowed (unless a superuser is requesting the change). + if (!superuser + && existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED) + && newResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) { + throw new ResourceHasClientUpdateProhibitedException(); + } + verifyNewUpdatedStateIsAllowed(); + } + + /** Subclasses may override this to do more specific checks on the new state after the update. */ + @SuppressWarnings("unused") + protected void verifyNewUpdatedStateIsAllowed() throws EppException {} + + @SuppressWarnings("unused") + protected void verifyUpdateIsAllowed() throws EppException {} + + @SuppressWarnings("unused") + protected B setUpdateProperties(B builder) throws EppException { + return builder; + } + + @Override + protected final EppOutput getOutput() { + return createOutput(Success); + } + + /** The specified status value cannot be set by clients. */ + public static class StatusNotClientSettableException extends ParameterValueRangeErrorException { + public StatusNotClientSettableException(String statusValue) { + super(String.format("Status value %s cannot be set by clients", statusValue)); + } + } + + /** This resource has clientUpdateProhibited on it, and the update does not clear that status. */ + public static class ResourceHasClientUpdateProhibitedException + extends StatusProhibitsOperationException { + public ResourceHasClientUpdateProhibitedException() { + super("Operation disallowed by status: clientUpdateProhibited"); + } + } + + /** Cannot add and remove the same value. */ + public static class AddRemoveSameValueEppException extends ParameterValuePolicyErrorException { + public AddRemoveSameValueEppException() { + super("Cannot add and remove the same value"); + } + } +} diff --git a/java/com/google/domain/registry/flows/SessionMetadata.java b/java/com/google/domain/registry/flows/SessionMetadata.java new file mode 100644 index 000000000..b4f008ad6 --- /dev/null +++ b/java/com/google/domain/registry/flows/SessionMetadata.java @@ -0,0 +1,162 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.base.Joiner; +import com.google.common.base.Optional; + +import java.util.Set; + +/** Class to allow setting and retrieving session information in flows. */ +public abstract class SessionMetadata { + + /** + * An enum that identifies the origin of the session. + */ + public enum SessionSource { + /** e.g. {@code EppConsoleServlet} */ + CONSOLE, + + /** e.g. {@code EppTlsServlet} */ + HTTP, + + /** e.g. {@code EppToolServlet} */ + TOOL, + + /** e.g. {@code LoadTestAction} */ + LOADTEST, + + /** Direct flow runs (default for e.g. testing) */ + NONE + } + + private TransportCredentials credentials; + + /** The key used for looking up the current client id on the session object. */ + protected static final String CLIENT_ID_KEY = "CLIENT_ID"; + + /** The key used for looking up the superuser bit on the session object. */ + protected static final String SUPERUSER_KEY = "SUPERUSER"; + + /** The key used for looking up the service extensions on the session object. */ + protected static final String SERVICE_EXTENSIONS_KEY = "SERVICE_EXTENSIONS"; + + /** The key used for looking up the number of failed login attempts. */ + protected static final String FAILED_LOGIN_ATTEMPTS_KEY = "FAILED_LOGIN_ATTEMPTS"; + + protected abstract void setProperty(String key, Object value); + + protected abstract Object getProperty(String key); + + /** + * Invalidates the session. A new instance must be created after this for future sessions. + * Attempts to invoke methods of this class after this method has been called will throw + * {@code IllegalStateException}. + */ + public abstract void invalidate(); + + /** Subclasses can override this to verify that this is a valid session. */ + protected void checkValid() {} + + protected void setPropertyChecked(String key, Object value) { + checkValid(); + setProperty(key, value); + } + + @SuppressWarnings("unchecked") + protected T getPropertyChecked(String key) { + checkValid(); + return (T) getProperty(key); + } + + public TransportCredentials getTransportCredentials() { + checkValid(); + return credentials; + } + + public void setTransportCredentials(TransportCredentials credentials) { + checkValid(); + this.credentials = credentials; + } + + public String getClientId() { + return getPropertyChecked(CLIENT_ID_KEY); + } + + public boolean isSuperuser() { + return Boolean.TRUE.equals(getPropertyChecked(SUPERUSER_KEY)); + } + + public Set getServiceExtensionUris() { + return getPropertyChecked(SERVICE_EXTENSIONS_KEY); + } + + public abstract SessionSource getSessionSource(); + + /** + * Subclasses can override if they present a need to change the session + * source at runtime (e.g. anonymous classes created for testing) + */ + public void setSessionSource(@SuppressWarnings("unused") SessionSource source) { + throw new UnsupportedOperationException(); + } + + public void setClientId(String clientId) { + setPropertyChecked(CLIENT_ID_KEY, clientId); + } + + public void setSuperuser(boolean superuser) { + setPropertyChecked(SUPERUSER_KEY, superuser); + } + + public void setServiceExtensionUris(Set serviceExtensionUris) { + setPropertyChecked(SERVICE_EXTENSIONS_KEY, checkNotNull(serviceExtensionUris)); + } + + public int getFailedLoginAttempts() { + return ((Integer) Optional.fromNullable(getPropertyChecked(FAILED_LOGIN_ATTEMPTS_KEY)).or(0)); + } + + public void incrementFailedLoginAttempts() { + setPropertyChecked(FAILED_LOGIN_ATTEMPTS_KEY, getFailedLoginAttempts() + 1); + } + + public void resetFailedLoginAttempts() { + setPropertyChecked(FAILED_LOGIN_ATTEMPTS_KEY, null); + } + + // These three methods are here to allow special permissions if a derived class overrides them. + + public boolean isDryRun() { + return false; + } + + @Override + public String toString() { + return toStringHelper(getClass()) + .add("system hash code", System.identityHashCode(this)) + .add("clientId", getClientId()) + .add("isSuperuser", isSuperuser()) + .add("failedLoginAttempts", getFailedLoginAttempts()) + .add("sessionSource", getSessionSource()) + .add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris()))) + .add("transportCredentials", getTransportCredentials()) + .toString(); + } +} diff --git a/java/com/google/domain/registry/flows/SingleResourceFlow.java b/java/com/google/domain/registry/flows/SingleResourceFlow.java new file mode 100644 index 000000000..6413a36fa --- /dev/null +++ b/java/com/google/domain/registry/flows/SingleResourceFlow.java @@ -0,0 +1,104 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.domain.launch.ApplicationIdTargetExtension; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; + +import java.util.Set; + +/** + * An EPP flow that manipulates a single stored resource. + * + * @param the resource type being manipulated + * @param the command type doing the manipulation. + */ +public abstract class SingleResourceFlow + extends ResourceFlow { + + protected R existingResource; + protected String targetId; + + @Override + protected final void initResourceFlow() throws EppException { + targetId = getTargetId(); + // In a transactional flow, loading the resource will be expensive because it can't be cached. + // Allow flows to optionally fail fast here before loading. + failfast(); + // Loads the target resource if it exists + // Some flows such as DomainApplicationInfoFlow have the id marked as optional in the schema. + // We require it by policy in the relevant flow, but here we need to make sure not to NPE when + // initializing the (obviously nonexistent) existing resource. + existingResource = (targetId == null || !tryToLoadExisting()) + ? null + : loadByUniqueId(resourceClass, targetId, now); + if (existingResource != null) { + Set problems = Sets.intersection( + existingResource.getStatusValues(), getDisallowedStatuses()); + if (!problems.isEmpty()) { + throw new ResourceStatusProhibitsOperationException(problems); + } + } + initSingleResourceFlow(); + } + + /** + * Returns whether the resource flow should attempt to load an existing resource with the + * matching targetId. Defaults to true, but overriding flows can set to false to bypass loading + * of existing resources. + */ + protected boolean tryToLoadExisting() { + return true; + } + + /** + * Get the target id from {@link SingleResourceCommand}. If there is a launch extension present, + * it overrides that target id with its application id, so return that instead. There will never + * be more than one launch extension. + */ + protected final String getTargetId() { + ApplicationIdTargetExtension extension = + eppInput.getSingleExtension(ApplicationIdTargetExtension.class); + return extension == null ? command.getTargetId() : extension.getApplicationId(); + } + + /** Subclasses can optionally override this to fail before loading {@link #existingResource}. */ + @SuppressWarnings("unused") + protected void failfast() throws EppException {} + + /** Subclasses can optionally override this for further initialization. */ + @SuppressWarnings("unused") + protected void initSingleResourceFlow() throws EppException {} + + protected Set getDisallowedStatuses() { + return ImmutableSet.of(); + } + + /** Resource status prohibits this operation. */ + public static class ResourceStatusProhibitsOperationException + extends StatusProhibitsOperationException { + public ResourceStatusProhibitsOperationException(Set status) { + super("Operation disallowed by status: " + Joiner.on(", ").join(status)); + } + } +} diff --git a/java/com/google/domain/registry/flows/StatelessRequestSessionMetadata.java b/java/com/google/domain/registry/flows/StatelessRequestSessionMetadata.java new file mode 100644 index 000000000..e264c2ac2 --- /dev/null +++ b/java/com/google/domain/registry/flows/StatelessRequestSessionMetadata.java @@ -0,0 +1,87 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import java.util.Set; + +/** A read-only {@link SessionMetadata} that doesn't support login/logout. */ +public class StatelessRequestSessionMetadata extends SessionMetadata { + + private final String clientId; + private final boolean isSuperuser; + private final boolean isDryRun; + private final Set serviceExtensionUris; + private final SessionSource sessionSource; + + public StatelessRequestSessionMetadata( + String clientId, + boolean isSuperuser, + boolean isDryRun, + Set serviceExtensionUris, + SessionSource source) { + this.clientId = clientId; + this.isSuperuser = isSuperuser; + this.isDryRun = isDryRun; + this.serviceExtensionUris = serviceExtensionUris; + this.sessionSource = source; + } + + @Override + public String getClientId() { + return clientId; + } + + @Override + public boolean isSuperuser() { + return isSuperuser; + } + + @Override + public boolean isDryRun() { + return isDryRun; + } + + @Override + public Set getServiceExtensionUris() { + return serviceExtensionUris; + } + + @Override + public SessionSource getSessionSource() { + return sessionSource; + } + + @Override + public void invalidate() { + throw new UnsupportedOperationException(); + } + + @Override + public void setTransportCredentials(TransportCredentials credentials) { + throw new UnsupportedOperationException(); + } + + @Override + protected void setProperty(String key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + protected Object getProperty(String key) { + // We've overridden the getters of all of the properties that we care about. Return null for + // everything else so that toString() continues to work. + return null; + } +} diff --git a/java/com/google/domain/registry/flows/TlsCredentials.java b/java/com/google/domain/registry/flows/TlsCredentials.java new file mode 100644 index 000000000..3d6a9a955 --- /dev/null +++ b/java/com/google/domain/registry/flows/TlsCredentials.java @@ -0,0 +1,180 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.net.HostAndPort; +import com.google.common.net.InetAddresses; +import com.google.domain.registry.flows.EppException.AuthenticationErrorException; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.util.CidrAddressBlock; +import com.google.domain.registry.util.FormattingLogger; + +import java.net.InetAddress; + +import javax.servlet.http.HttpServletRequest; + +/** + * Container and validation for TLS certificate and ip-whitelisting. + */ +public final class TlsCredentials implements TransportCredentials { + + /** Registrar certificate does not match stored certificate. */ + public static class BadRegistrarCertificateException extends AuthenticationErrorException { + public BadRegistrarCertificateException() { + super("Registrar certificate does not match stored certificate"); + } + } + + /** Registrar certificate not present. */ + public static class MissingRegistrarCertificateException extends AuthenticationErrorException { + public MissingRegistrarCertificateException() { + super("Registrar certificate not present"); + } + } + + /** SNI header is required. */ + public static class NoSniException extends AuthenticationErrorException { + public NoSniException() { + super("SNI header is required"); + } + } + + /** Registrar IP address is not in stored whitelist. */ + public static class BadRegistrarIpAddressException extends AuthenticationErrorException { + public BadRegistrarIpAddressException() { + super("Registrar IP address is not in stored whitelist"); + } + } + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private final String clientCertificateHash; + private final InetAddress clientInetAddr; + private final String sni; + + @VisibleForTesting + public TlsCredentials(String clientCertificateHash, InetAddress clientInetAddr, String sni) { + this.clientCertificateHash = clientCertificateHash; + this.clientInetAddr = clientInetAddr; + this.sni = sni; + } + + /** + * Extracts the client TLS certificate and source internet address + * from the given HTTP request. + */ + TlsCredentials(HttpServletRequest req) { + this(req.getHeader(EppTlsServlet.SSL_CLIENT_CERTIFICATE_HASH_FIELD), + parseInetAddress(req.getHeader(EppTlsServlet.FORWARDED_FOR_FIELD)), + req.getHeader(EppTlsServlet.REQUESTED_SERVERNAME_VIA_SNI_FIELD)); + } + + static InetAddress parseInetAddress(String asciiAddr) { + try { + return InetAddresses.forString(HostAndPort.fromString(asciiAddr).getHostText()); + } catch (IllegalArgumentException e) { + return null; + } + } + + @Override + public boolean performsLoginCheck() { + return false; + } + + /** Returns {@code true} if frontend passed us the requested server name. */ + boolean hasSni() { + return !isNullOrEmpty(sni); + } + + @Override + public void validate(Registrar registrar) throws AuthenticationErrorException { + validateIp(registrar); + validateCertificate(registrar); + } + + /** + * Verifies {@link #clientInetAddr} is in CIDR whitelist associated with {@code registrar}. + * + * @throws BadRegistrarIpAddressException If IP address is not in the whitelist provided + */ + private void validateIp(Registrar registrar) throws AuthenticationErrorException { + ImmutableList ipWhitelist = registrar.getIpAddressWhitelist(); + if (ipWhitelist.isEmpty()) { + logger.infofmt("Skipping IP whitelist check because %s doesn't have an IP whitelist", + registrar.getClientIdentifier()); + return; + } + for (CidrAddressBlock cidrAddressBlock : ipWhitelist) { + if (cidrAddressBlock.contains(clientInetAddr)) { + // IP address is in whitelist; return early. + return; + } + } + logger.infofmt("%s not in %s's CIDR whitelist: %s", + clientInetAddr, registrar.getClientIdentifier(), ipWhitelist); + throw new BadRegistrarIpAddressException(); + } + + /** + * Verifies client SSL certificate is permitted to issue commands as {@code registrar}. + * + * @throws NoSniException if frontend didn't send host or certificate hash headers + * @throws MissingRegistrarCertificateException if frontend didn't send certificate hash header + * @throws BadRegistrarCertificateException if registrar requires certificate and it didn't match + */ + private void validateCertificate(Registrar registrar) throws AuthenticationErrorException { + if (isNullOrEmpty(registrar.getClientCertificateHash()) + && isNullOrEmpty(registrar.getFailoverClientCertificateHash())) { + logger.infofmt( + "Skipping SSL certificate check because %s doesn't have any certificate hashes on file", + registrar.getClientIdentifier()); + return; + } + if (isNullOrEmpty(clientCertificateHash)) { + // If there's no SNI header that's probably why we don't have a cert, so send a specific + // message. Otherwise, send a missing certificate message. + if (!hasSni()) { + throw new NoSniException(); + } + logger.infofmt("Request did not include %s", EppTlsServlet.SSL_CLIENT_CERTIFICATE_HASH_FIELD); + throw new MissingRegistrarCertificateException(); + } + if (!clientCertificateHash.equals(registrar.getClientCertificateHash()) + && !clientCertificateHash.equals(registrar.getFailoverClientCertificateHash())) { + logger.warningfmt("bad certificate hash (%s) for %s, wanted either %s or %s", + clientCertificateHash, + registrar.getClientIdentifier(), + registrar.getClientCertificateHash(), + registrar.getFailoverClientCertificateHash()); + throw new BadRegistrarCertificateException(); + } + } + + @Override + public String toString() { + return toStringHelper(getClass()) + .add("system hash code", System.identityHashCode(this)) + .add("clientCertificateHash", clientCertificateHash) + .add("clientInetAddress", clientInetAddr) + .add("sni", sni) + .toString(); + } +} diff --git a/java/com/google/domain/registry/flows/TransactionalFlow.java b/java/com/google/domain/registry/flows/TransactionalFlow.java new file mode 100644 index 000000000..6b1399735 --- /dev/null +++ b/java/com/google/domain/registry/flows/TransactionalFlow.java @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +/** + * Marker interface indicating that a {@link Flow} needs to be run transactionally. + *

+ * Any flow that mutates the datastore should be tagged with this so that {@link FlowRunner} will + * know how to run it. + */ +public interface TransactionalFlow {} diff --git a/java/com/google/domain/registry/flows/TransportCredentials.java b/java/com/google/domain/registry/flows/TransportCredentials.java new file mode 100644 index 000000000..2b964521d --- /dev/null +++ b/java/com/google/domain/registry/flows/TransportCredentials.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows; + +import com.google.domain.registry.flows.EppException.AuthenticationErrorException; +import com.google.domain.registry.model.registrar.Registrar; + +/** + * A marker interface for objects containing registrar credentials provided via an EPP transport. + */ +public interface TransportCredentials { + + /** + * Indicates whether the transport takes the place of EPP login checks, in which case LoginFlow + * will not check the password. Alternatively, if the password should be checked, it MUST match + * the user's and GAE's isUserAdmin should not be used to bypass this check as internal + * connections over RPC will have this property for all registrars. + */ + boolean performsLoginCheck(); + + /** + * Called by {@link com.google.domain.registry.flows.session.LoginFlow LoginFlow} + * to check the transport credentials against the stored registrar's credentials. + * If they do not match, throw an AuthenticationErrorException. + */ + void validate(Registrar r) throws AuthenticationErrorException; +} diff --git a/java/com/google/domain/registry/flows/async/AsyncFlowUtils.java b/java/com/google/domain/registry/flows/async/AsyncFlowUtils.java new file mode 100644 index 000000000..83ce3684f --- /dev/null +++ b/java/com/google/domain/registry/flows/async/AsyncFlowUtils.java @@ -0,0 +1,60 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.domain.registry.request.Actions.getPathForAction; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.QueueFactory; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.mapreduce.MapreduceAction; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.Duration; + +import java.util.Map.Entry; + +/** Utility methods specific to async flows. */ +public final class AsyncFlowUtils { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @VisibleForTesting + public static final String ASYNC_FLOW_QUEUE_NAME = "flows-async"; // See queue.xml. + + private AsyncFlowUtils() {} + + /** Enqueues a mapreduce action to perform an async flow operation. */ + public static TaskHandle enqueueMapreduceAction( + Class action, + ImmutableMap params, + Duration executionDelay) { + Queue queue = QueueFactory.getQueue(ASYNC_FLOW_QUEUE_NAME); + String path = getPathForAction(action); + logger.infofmt("Enqueueing async mapreduce action with path %s and params %s", path, params); + TaskOptions options = TaskOptions.Builder + .withUrl(path) + .countdownMillis(executionDelay.getMillis()) + .method(Method.GET); + for (Entry entry : params.entrySet()) { + options.param(entry.getKey(), entry.getValue()); + } + return queue.add(options); + } +} diff --git a/java/com/google/domain/registry/flows/async/AsyncFlowsModule.java b/java/com/google/domain/registry/flows/async/AsyncFlowsModule.java new file mode 100644 index 000000000..76117eb89 --- /dev/null +++ b/java/com/google/domain/registry/flows/async/AsyncFlowsModule.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.domain.registry.flows.async.DeleteEppResourceAction.PARAM_IS_SUPERUSER; +import static com.google.domain.registry.flows.async.DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID; +import static com.google.domain.registry.flows.async.DeleteEppResourceAction.PARAM_RESOURCE_KEY; +import static com.google.domain.registry.flows.async.DnsRefreshForHostRenameAction.PARAM_HOST_KEY; +import static com.google.domain.registry.request.RequestParameters.extractBooleanParameter; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; + +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the async flows package. */ +@Module +public final class AsyncFlowsModule { + + @Provides + @Parameter(PARAM_IS_SUPERUSER) + static boolean provideIsSuperuser(HttpServletRequest req) { + return extractBooleanParameter(req, PARAM_IS_SUPERUSER); + } + + @Provides + @Parameter(PARAM_REQUESTING_CLIENT_ID) + static String provideRequestingClientId(HttpServletRequest req) { + return extractRequiredParameter(req, PARAM_REQUESTING_CLIENT_ID); + } + + @Provides + @Parameter(PARAM_RESOURCE_KEY) + static String provideResourceKey(HttpServletRequest req) { + return extractRequiredParameter(req, PARAM_RESOURCE_KEY); + } + + @Provides + @Parameter(PARAM_HOST_KEY) + static String provideHostKey(HttpServletRequest req) { + return extractRequiredParameter(req, PARAM_HOST_KEY); + } +} diff --git a/java/com/google/domain/registry/flows/async/DeleteContactResourceAction.java b/java/com/google/domain/registry/flows/async/DeleteContactResourceAction.java new file mode 100644 index 000000000..83c4df94f --- /dev/null +++ b/java/com/google/domain/registry/flows/async/DeleteContactResourceAction.java @@ -0,0 +1,82 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.domain.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete; + +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.reporting.HistoryEntry.Type; +import com.google.domain.registry.request.Action; + +import org.joda.time.DateTime; + +import javax.inject.Inject; + +/** + * A mapreduce to delete the specified ContactResource, but ONLY if it is not referred to by any + * existing DomainBase entity. + */ +@Action(path = "/_dr/task/deleteContactResource") +public class DeleteContactResourceAction extends DeleteEppResourceAction { + + @Inject + public DeleteContactResourceAction() { + super( + new DeleteContactResourceMapper(), + new DeleteContactResourceReducer()); + } + + /** An async deletion mapper for {@link ContactResource}. */ + public static class DeleteContactResourceMapper extends DeleteEppResourceMapper { + + private static final long serialVersionUID = -5904009575877950342L; + + @Override + protected boolean isLinked( + DomainBase domain, ReferenceUnion targetResourceRef) { + return domain.getReferencedContacts().contains(targetResourceRef); + } + } + + /** An async deletion reducer for {@link ContactResource}. */ + public static class DeleteContactResourceReducer + extends DeleteEppResourceReducer { + + private static final long serialVersionUID = -7633644054441045215L; + + @Override + protected Type getHistoryType(boolean successfulDelete) { + return successfulDelete + ? HistoryEntry.Type.CONTACT_DELETE + : HistoryEntry.Type.CONTACT_DELETE_FAILURE; + } + + @Override + protected void performDeleteTasks( + ContactResource targetResource, + ContactResource deletedResource, + DateTime deletionTime, + HistoryEntry historyEntryForDelete) { + handlePendingTransferOnDelete( + targetResource, + deletedResource, + deletionTime, + historyEntryForDelete); + } + } +} diff --git a/java/com/google/domain/registry/flows/async/DeleteEppResourceAction.java b/java/com/google/domain/registry/flows/async/DeleteEppResourceAction.java new file mode 100644 index 000000000..944f8e9dd --- /dev/null +++ b/java/com/google/domain/registry/flows/async/DeleteEppResourceAction.java @@ -0,0 +1,272 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder; +import static com.google.domain.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime; +import static com.google.domain.registry.model.EppResourceUtils.isActive; +import static com.google.domain.registry.model.EppResourceUtils.isDeleted; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.PipelineUtils.createJobPath; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.appengine.tools.mapreduce.Reducer; +import com.google.appengine.tools.mapreduce.ReducerInput; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.domain.registry.mapreduce.EppResourceInputs; +import com.google.domain.registry.mapreduce.MapreduceAction; +import com.google.domain.registry.mapreduce.MapreduceRunner; +import com.google.domain.registry.mapreduce.NullInput; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; + +import javax.inject.Inject; + +/** + * A mapreduce to delete the specified EPP resource, but ONLY if it is not referred to by any + * existing DomainBase entity. + */ +public abstract class DeleteEppResourceAction implements MapreduceAction { + + @NonFinalForTesting + static Clock clock = new SystemClock(); + + /** The HTTP parameter name used to specify the websafe key of the resource to delete. */ + public static final String PARAM_RESOURCE_KEY = "resourceKey"; + public static final String PARAM_REQUESTING_CLIENT_ID = "requestingClientId"; + public static final String PARAM_IS_SUPERUSER = "superuser"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject @Parameter(PARAM_RESOURCE_KEY) String resourceKeyString; + @Inject @Parameter(PARAM_REQUESTING_CLIENT_ID) String requestingClientId; + @Inject @Parameter(PARAM_IS_SUPERUSER) boolean isSuperuser; + @Inject MapreduceRunner mrRunner; + @Inject Response response; + + DeleteEppResourceMapper mapper; + DeleteEppResourceReducer reducer; + + protected DeleteEppResourceAction( + DeleteEppResourceMapper mapper, + DeleteEppResourceReducer reducer) { + this.mapper = mapper; + this.reducer = reducer; + } + + @Override + public void run() { + Key resourceKey = null; + T resource; + try { + resourceKey = Key.create(resourceKeyString); + resource = checkArgumentNotNull(ofy().load().key(resourceKey).now()); + } catch (IllegalArgumentException e) { + throw new BadRequestException(resourceKey == null + ? "Could not parse key string: " + resourceKeyString + : "Could not load resource for key: " + resourceKey); + } + checkArgument( + resource.getClass().equals(new TypeInstantiator(getClass()){}.getExactType()), + String.format("Cannot delete a %s via this action.", resource.getClass().getSimpleName())); + checkState( + !isDeleted(resource, clock.nowUtc()), + "Resource %s is already deleted.", resource.getForeignKey()); + checkState( + resource.getStatusValues().contains(StatusValue.PENDING_DELETE), + "Resource %s is not set as PENDING_DELETE", resource.getForeignKey()); + mapper.setTargetResource(resourceKey); + reducer.setClient(requestingClientId, isSuperuser); + logger.infofmt("Executing Delete EPP resource mapreduce for %s", resourceKey); + response.sendJavaScriptRedirect(createJobPath(mrRunner + .setJobName("Check for EPP resource references and then delete") + .setModuleName("backend") + .runMapreduce( + mapper, + reducer, + ImmutableList.of( + // Add an extra shard that maps over a null domain. See the mapper code for why. + new NullInput(), + EppResourceInputs.createEntityInput(DomainBase.class))))); + } + + /** + * A mapper that iterates over all {@link DomainBase} entities. + * + *

It emits the target key and {@code true} for domains referencing the target resource. For + * the special input of {@code null} it emits the target key and {@code false}. + */ + public abstract static class DeleteEppResourceMapper + extends Mapper, Boolean> { + + private static final long serialVersionUID = -7355145176854995813L; + + private DateTime targetResourceUpdateTimestamp; + private Key targetEppResourceKey; + + private void setTargetResource(Key targetEppResourceKey) { + this.targetEppResourceKey = targetEppResourceKey; + this.targetResourceUpdateTimestamp = + ofy().load().key(targetEppResourceKey).now().getUpdateAutoTimestamp().getTimestamp(); + } + + /** Determine whether the target resource is a linked resource on the domain. */ + protected abstract boolean isLinked(DomainBase domain, ReferenceUnion targetResourceRef); + + @Override + public void map(DomainBase domain) { + // The reducer only runs if at least one value is emitted. We add a null input to the + // mapreduce and always emit 'false' for it to force the reducer to run. We can then emit + // 'true' for linked domains and not emit anything for unlinked domains, which speeds up the + // reducer since it will only receive true keys, of which there will be few (usually none). + if (domain == null) { + emit(targetEppResourceKey, false); + return; + } + // The ReferenceUnion can't be a field on the Mapper, because when a Ref is serialized + // (required for each MapShardTask), it uses the DeadRef version, which contains the Ref's + // value, which isn't serializable. Thankfully, this isn't expensive. + // See: https://github.com/objectify/objectify/blob/master/src/main/java/com/googlecode/objectify/impl/ref/DeadRef.java + if (isActive(domain, targetResourceUpdateTimestamp) + && isLinked(domain, ReferenceUnion.create(Ref.create(targetEppResourceKey)))) { + emit(targetEppResourceKey, true); + } + } + } + + /** + * A reducer that checks if the EPP resource to be deleted is referenced anywhere, and then + * deletes it if not and unmarks it for deletion if so. + */ + public abstract static class DeleteEppResourceReducer + extends Reducer, Boolean, Void> { + + private static final long serialVersionUID = 875017002097945151L; + + private String requestingClientId; + private boolean isSuperuser; + + private void setClient(String requestingClientId, boolean isSuperuser) { + this.requestingClientId = requestingClientId; + this.isSuperuser = isSuperuser; + } + + /** + * Determine the proper history entry type for the delete operation, as a function of + * whether or not the delete was successful. + */ + protected abstract HistoryEntry.Type getHistoryType(boolean successfulDelete); + + /** Perform any type-specific tasks on the resource to be deleted (and/or its dependencies). */ + protected abstract void performDeleteTasks( + T targetResource, + T deletedResource, + DateTime deletionTime, + HistoryEntry historyEntryForDelete); + + @Override + public void reduce(final Key key, final ReducerInput values) { + final boolean hasNoActiveReferences = !Iterators.contains(values, true); + logger.infofmt("Processing delete request for %s", key.toString()); + String pollMessageText = ofy().transactNew(new Work() { + @Override + @SuppressWarnings("unchecked") + public String run() { + DateTime now = ofy().getTransactionTime(); + T targetResource = (T) ofy().load().key(key).now().cloneProjectedAtTime(now); + String resourceName = targetResource.getForeignKey(); + // Double-check that the resource is still active and in PENDING_DELETE within the + // transaction. + checkState( + !isDeleted(targetResource, now), + "Resource %s is already deleted.", resourceName); + checkState( + targetResource.getStatusValues().contains(StatusValue.PENDING_DELETE), + "Resource %s is not in PENDING_DELETE.", resourceName); + + targetResource = (T) targetResource.asBuilder() + .removeStatusValue(StatusValue.PENDING_DELETE) + .build(); + + boolean requestedByCurrentOwner = + targetResource.getCurrentSponsorClientId().equals(requestingClientId); + boolean deleteAllowed = hasNoActiveReferences && (requestedByCurrentOwner || isSuperuser); + + String resourceTypeName = + targetResource.getClass().getAnnotation(ExternalMessagingName.class).value(); + HistoryEntry.Type historyType = getHistoryType(deleteAllowed); + + String pollMessageText = deleteAllowed + ? String.format("Deleted %s %s.", resourceTypeName, resourceName) + : String.format( + "Can't delete %s %s because %s.", + resourceTypeName, + resourceName, + requestedByCurrentOwner + ? "it is referenced by a domain" + : "it was transferred prior to deletion"); + + HistoryEntry historyEntry = new HistoryEntry.Builder() + .setClientId(requestingClientId) + .setModificationTime(now) + .setType(historyType) + .setParent(key) + .build(); + + PollMessage.OneTime deleteResultMessage = new PollMessage.OneTime.Builder() + .setClientId(requestingClientId) + .setMsg(pollMessageText) + .setParent(historyEntry) + .setEventTime(now) + .build(); + + if (deleteAllowed) { + T deletedResource = prepareDeletedResourceAsBuilder(targetResource, now).build(); + performDeleteTasks(targetResource, deletedResource, now, historyEntry); + updateForeignKeyIndexDeletionTime(deletedResource); + ofy().save().entities(deletedResource, historyEntry, deleteResultMessage); + } else { + ofy().save().entities(targetResource, historyEntry, deleteResultMessage); + } + return pollMessageText; + } + }); + logger.infofmt(pollMessageText); + } + } +} diff --git a/java/com/google/domain/registry/flows/async/DeleteHostResourceAction.java b/java/com/google/domain/registry/flows/async/DeleteHostResourceAction.java new file mode 100644 index 000000000..fc9bead8e --- /dev/null +++ b/java/com/google/domain/registry/flows/async/DeleteHostResourceAction.java @@ -0,0 +1,84 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.reporting.HistoryEntry.Type; +import com.google.domain.registry.request.Action; + +import org.joda.time.DateTime; + +import javax.inject.Inject; + +/** + * A mapreduce to delete the specified HostResource, but ONLY if it is not referred to by any + * existing DomainBase entity. + */ +@Action(path = "/_dr/task/deleteHostResource") +public class DeleteHostResourceAction extends DeleteEppResourceAction { + + @Inject + public DeleteHostResourceAction() { + super( + new DeleteHostResourceMapper(), + new DeleteHostResourceReducer()); + } + + /** An async deletion mapper for {@link HostResource}. */ + public static class DeleteHostResourceMapper extends DeleteEppResourceMapper { + + private static final long serialVersionUID = 1941092742903217194L; + + @Override + protected boolean isLinked( + DomainBase domain, ReferenceUnion targetResourceRef) { + return domain.getNameservers().contains(targetResourceRef); + } + } + + /** An async deletion reducer for {@link HostResource}. */ + public static class DeleteHostResourceReducer extends DeleteEppResourceReducer { + + private static final long serialVersionUID = 555457935288867324L; + + @Override + protected Type getHistoryType(boolean successfulDelete) { + return successfulDelete + ? HistoryEntry.Type.HOST_DELETE + : HistoryEntry.Type.HOST_DELETE_FAILURE; + } + + @Override + protected void performDeleteTasks( + HostResource targetResource, + HostResource deletedResource, + DateTime deletionTime, + HistoryEntry historyEntryForDelete) { + if (targetResource.getSuperordinateDomain() != null) { + DnsQueue.create().addHostRefreshTask(targetResource.getFullyQualifiedHostName()); + ofy().save().entity( + targetResource.getSuperordinateDomain().get().asBuilder() + .removeSubordinateHost(targetResource.getFullyQualifiedHostName()) + .build()); + } + } + } +} diff --git a/java/com/google/domain/registry/flows/async/DnsRefreshForHostRenameAction.java b/java/com/google/domain/registry/flows/async/DnsRefreshForHostRenameAction.java new file mode 100644 index 000000000..3237721f3 --- /dev/null +++ b/java/com/google/domain/registry/flows/async/DnsRefreshForHostRenameAction.java @@ -0,0 +1,110 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.async; + +import static com.google.domain.registry.model.EppResourceUtils.isActive; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.PipelineUtils.createJobPath; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.mapreduce.EppResourceInputs; +import com.google.domain.registry.mapreduce.MapreduceAction; +import com.google.domain.registry.mapreduce.MapreduceRunner; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; + +import org.joda.time.DateTime; + +import javax.inject.Inject; + +/** + * Enqueues DNS refreshes for applicable domains following a host rename. + */ +@Action(path = "/_dr/task/dnsRefreshForHostRename") +public class DnsRefreshForHostRenameAction implements MapreduceAction { + + /** The HTTP parameter name used to specify the websafe key of the host to rename. */ + public static final String PARAM_HOST_KEY = "hostKey"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + static DnsQueue dnsQueue = DnsQueue.create(); + + @Inject @Parameter(PARAM_HOST_KEY) String hostKeyString; + @Inject MapreduceRunner mrRunner; + @Inject Response response; + @Inject DnsRefreshForHostRenameAction() {} + + @Override + public void run() { + Key resourceKey = null; + HostResource host; + try { + resourceKey = Key.create(hostKeyString); + host = checkArgumentNotNull(ofy().load().key(resourceKey).now()); + } catch (IllegalArgumentException e) { + throw new BadRequestException(resourceKey == null + ? "Could not parse key string: " + hostKeyString + : "Could not load resource for key: " + resourceKey); + } + response.sendJavaScriptRedirect(createJobPath(mrRunner + .setJobName("Enqueue DNS refreshes for domains following a host rename") + .setModuleName("backend") + .runMapOnly( + new DnsRefreshForHostRenameMapper(host), + ImmutableList.of(EppResourceInputs.createEntityInput(DomainResource.class))))); + } + + /** Map over domains and refresh the dns of those that referenced this host. */ + public static class DnsRefreshForHostRenameMapper extends Mapper { + + private static final long serialVersionUID = -4707015136971008447L; + + private final DateTime hostUpdateTime; + private final Key targetHostKey; + + DnsRefreshForHostRenameMapper(HostResource host) { + this.targetHostKey = Key.create(host); + this.hostUpdateTime = host.getUpdateAutoTimestamp().getTimestamp(); + } + + @Override + public final void map(DomainResource domain) { + if (isActive(domain, hostUpdateTime) + && domain.getNameservers().contains(ReferenceUnion.create(Ref.create(targetHostKey)))) { + try { + dnsQueue.addDomainRefreshTask(domain.getFullyQualifiedDomainName()); + logger.infofmt("Enqueued refresh for domain %s", domain.getFullyQualifiedDomainName()); + } catch (Throwable t) { + logger.severefmt(t, "Error while refreshing DNS for host rename %s", targetHostKey); + } + } + } + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactCheckFlow.java b/java/com/google/domain/registry/flows/contact/ContactCheckFlow.java new file mode 100644 index 000000000..12e0f6f5b --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactCheckFlow.java @@ -0,0 +1,45 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import static com.google.domain.registry.model.EppResourceUtils.checkResourcesExist; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.ResourceCheckFlow; +import com.google.domain.registry.model.contact.ContactCommand.Check; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.eppoutput.CheckData; +import com.google.domain.registry.model.eppoutput.CheckData.ContactCheck; +import com.google.domain.registry.model.eppoutput.CheckData.ContactCheckData; + +import java.util.Set; + +/** + * An EPP flow that checks whether a contact can be provisioned. + * + * @error {@link com.google.domain.registry.flows.ResourceCheckFlow.TooManyResourceChecksException} + */ +public class ContactCheckFlow extends ResourceCheckFlow { + @Override + protected CheckData getCheckData() { + Set existingIds = checkResourcesExist(resourceClass, targetIds, now); + ImmutableList.Builder checks = new ImmutableList.Builder<>(); + for (String id : targetIds) { + boolean unused = !existingIds.contains(id); + checks.add(ContactCheck.create(unused, id, unused ? null : "In use")); + } + return ContactCheckData.create(checks.build()); + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactCreateFlow.java b/java/com/google/domain/registry/flows/contact/ContactCreateFlow.java new file mode 100644 index 000000000..e23a1c469 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactCreateFlow.java @@ -0,0 +1,65 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import static com.google.domain.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; +import static com.google.domain.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; +import static com.google.domain.registry.model.EppResourceUtils.createContactHostRoid; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceCreateFlow; +import com.google.domain.registry.model.contact.ContactCommand.Create; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.eppoutput.CreateData.ContactCreateData; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.ofy.ObjectifyService; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that creates a new contact resource. + * + * @error {@link com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException} + * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} + * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} + */ +public class ContactCreateFlow extends ResourceCreateFlow { + @Override + protected EppOutput getOutput() { + return createOutput(Success, ContactCreateData.create(newResource.getContactId(), now)); + } + + @Override + protected String createFlowRepoId() { + return createContactHostRoid(ObjectifyService.allocateId()); + } + + @Override + protected void verifyNewStateIsAllowed() throws EppException { + validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo()); + validateContactAgainstPolicy(newResource); + } + + @Override + protected boolean storeXmlInHistoryEntry() { + return false; + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_CREATE; + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactDeleteFlow.java b/java/com/google/domain/registry/flows/contact/ContactDeleteFlow.java new file mode 100644 index 000000000..58affbb28 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactDeleteFlow.java @@ -0,0 +1,87 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import static com.google.domain.registry.model.EppResourceUtils.queryDomainsUsingResource; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceAsyncDeleteFlow; +import com.google.domain.registry.flows.async.AsyncFlowUtils; +import com.google.domain.registry.flows.async.DeleteContactResourceAction; +import com.google.domain.registry.flows.async.DeleteEppResourceAction; +import com.google.domain.registry.model.contact.ContactCommand.Delete; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Key; + +/** + * An EPP flow that deletes a contact resource. + * + * @error {@link com.google.domain.registry.flows.ResourceAsyncDeleteFlow.ResourceToDeleteIsReferencedException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + */ +public class ContactDeleteFlow extends ResourceAsyncDeleteFlow { + + /** In {@link #isLinkedForFailfast}, check this (arbitrary) number of resources from the query. */ + private static final int FAILFAST_CHECK_COUNT = 5; + + @Override + protected boolean isLinkedForFailfast(final ReferenceUnion ref) { + // Query for the first few linked domains, and if found, actually load them. The query is + // eventually consistent and so might be very stale, but the direct load will not be stale, + // just non-transactional. If we find at least one actual reference then we can reliably + // fail. If we don't find any, we can't trust the query and need to do the full mapreduce. + return Iterables.any( + ofy().load().keys( + queryDomainsUsingResource( + ContactResource.class, ref.getLinked(), now, FAILFAST_CHECK_COUNT)).values(), + new Predicate() { + @Override + public boolean apply(DomainBase domain) { + return domain.getReferencedContacts().contains(ref); + }}); + } + + /** Enqueues a contact resource deletion on the mapreduce queue. */ + @Override + protected final void enqueueTasks() throws EppException { + AsyncFlowUtils.enqueueMapreduceAction( + DeleteContactResourceAction.class, + ImmutableMap.of( + DeleteEppResourceAction.PARAM_RESOURCE_KEY, + Key.create(existingResource).getString(), + DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID, + getClientId(), + DeleteEppResourceAction.PARAM_IS_SUPERUSER, + Boolean.toString(superuser)), + RegistryEnvironment.get().config().getAsyncDeleteFlowMapreduceDelay()); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_PENDING_DELETE; + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactFlowUtils.java b/java/com/google/domain/registry/flows/contact/ContactFlowUtils.java new file mode 100644 index 000000000..9f293e5b2 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactFlowUtils.java @@ -0,0 +1,77 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import static com.google.domain.registry.model.contact.PostalInfo.Type.INTERNATIONALIZED; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.model.contact.ContactAddress; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.PostalInfo; + +import java.util.Set; + +import javax.annotation.Nullable; + +/** Static utility functions for contact flows. */ +public class ContactFlowUtils { + /** Check that an internationalized postal info has only ascii characters. */ + static void validateAsciiPostalInfo(@Nullable PostalInfo internationalized) throws EppException { + if (internationalized != null) { + Preconditions.checkState(INTERNATIONALIZED.equals(internationalized.getType())); + ContactAddress address = internationalized.getAddress(); + Set fields = Sets.newHashSet( + internationalized.getName(), + internationalized.getOrg(), + address.getCity(), + address.getCountryCode(), + address.getState(), + address.getZip()); + fields.addAll(address.getStreet()); + for (String field : fields) { + if (field != null && !CharMatcher.ascii().matchesAllOf(field)) { + throw new BadInternationalizedPostalInfoException(); + } + } + } + } + + /** Check contact's state against server policy. */ + static void validateContactAgainstPolicy(ContactResource contact) throws EppException { + if (contact.getDisclose() != null && !contact.getDisclose().getFlag()) { + throw new DeclineContactDisclosureFieldDisallowedPolicyException(); + } + } + + /** Declining contact disclosure is disallowed by server policy. */ + static class DeclineContactDisclosureFieldDisallowedPolicyException + extends ParameterValuePolicyErrorException { + public DeclineContactDisclosureFieldDisallowedPolicyException() { + super("Declining contact disclosure is disallowed by server policy."); + } + } + + /** Internationalized postal infos can only contain ASCII characters. */ + static class BadInternationalizedPostalInfoException extends ParameterValueSyntaxErrorException { + public BadInternationalizedPostalInfoException() { + super("Internationalized postal infos can only contain ASCII characters"); + } + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactInfoFlow.java b/java/com/google/domain/registry/flows/contact/ContactInfoFlow.java new file mode 100644 index 000000000..47b32b240 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactInfoFlow.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.flows.ResourceInfoFlow; +import com.google.domain.registry.model.contact.ContactCommand.Info; +import com.google.domain.registry.model.contact.ContactResource; + +/** + * An EPP flow that reads a contact. + * + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + */ +public class ContactInfoFlow extends ResourceInfoFlow {} + diff --git a/java/com/google/domain/registry/flows/contact/ContactTransferApproveFlow.java b/java/com/google/domain/registry/flows/contact/ContactTransferApproveFlow.java new file mode 100644 index 000000000..e1ac90d7a --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactTransferApproveFlow.java @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.flows.ResourceTransferApproveFlow; +import com.google.domain.registry.model.contact.ContactCommand.Transfer; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that approves a pending transfer on a {@link ContactResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + */ +public class ContactTransferApproveFlow + extends ResourceTransferApproveFlow { + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_TRANSFER_APPROVE; + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactTransferCancelFlow.java b/java/com/google/domain/registry/flows/contact/ContactTransferCancelFlow.java new file mode 100644 index 000000000..807bf9620 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactTransferCancelFlow.java @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.flows.ResourceTransferCancelFlow; +import com.google.domain.registry.model.contact.ContactCommand.Transfer; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that cancels a pending transfer on a {@link ContactResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + * @error {@link com.google.domain.registry.flows.ResourceTransferCancelFlow.NotTransferInitiatorException} + */ +public class ContactTransferCancelFlow + extends ResourceTransferCancelFlow { + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_TRANSFER_CANCEL; + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactTransferQueryFlow.java b/java/com/google/domain/registry/flows/contact/ContactTransferQueryFlow.java new file mode 100644 index 000000000..6ec21fe07 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactTransferQueryFlow.java @@ -0,0 +1,30 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.flows.ResourceTransferQueryFlow; +import com.google.domain.registry.model.contact.ContactCommand.Transfer; +import com.google.domain.registry.model.contact.ContactResource; + +/** + * An EPP flow that queries a pending transfer on a {@link ContactResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceTransferQueryFlow.NoTransferHistoryToQueryException} + * @error {@link com.google.domain.registry.flows.ResourceTransferQueryFlow.NotAuthorizedToViewTransferException} + */ +public class ContactTransferQueryFlow extends ResourceTransferQueryFlow { +} diff --git a/java/com/google/domain/registry/flows/contact/ContactTransferRejectFlow.java b/java/com/google/domain/registry/flows/contact/ContactTransferRejectFlow.java new file mode 100644 index 000000000..7e97bfdf2 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactTransferRejectFlow.java @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.flows.ResourceTransferRejectFlow; +import com.google.domain.registry.model.contact.ContactCommand.Transfer; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that rejects a pending transfer on a {@link ContactResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + */ +public class ContactTransferRejectFlow + extends ResourceTransferRejectFlow { + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_TRANSFER_REJECT; + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactTransferRequestFlow.java b/java/com/google/domain/registry/flows/contact/ContactTransferRequestFlow.java new file mode 100644 index 000000000..b8fb739a6 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactTransferRequestFlow.java @@ -0,0 +1,46 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.flows.ResourceTransferRequestFlow; +import com.google.domain.registry.model.contact.ContactCommand.Transfer; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import org.joda.time.Duration; + +/** + * An EPP flow that requests a transfer on a {@link ContactResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.AlreadyPendingTransferException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.MissingTransferRequestAuthInfoException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.ObjectAlreadySponsoredException} + */ +public class ContactTransferRequestFlow + extends ResourceTransferRequestFlow { + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_TRANSFER_REQUEST; + } + + @Override + protected Duration getAutomaticTransferLength() { + return RegistryEnvironment.get().config().getContactAutomaticTransferLength(); + } +} diff --git a/java/com/google/domain/registry/flows/contact/ContactUpdateFlow.java b/java/com/google/domain/registry/flows/contact/ContactUpdateFlow.java new file mode 100644 index 000000000..0e9673186 --- /dev/null +++ b/java/com/google/domain/registry/flows/contact/ContactUpdateFlow.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.contact; + +import static com.google.domain.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; +import static com.google.domain.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceUpdateFlow; +import com.google.domain.registry.model.contact.ContactCommand.Update; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that updates a contact resource. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} + * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} + */ +public class ContactUpdateFlow extends ResourceUpdateFlow { + @Override + protected void verifyNewUpdatedStateIsAllowed() throws EppException { + validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo()); + validateContactAgainstPolicy(newResource); + } + + @Override + protected boolean storeXmlInHistoryEntry() { + return false; + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.CONTACT_UPDATE; + } +} diff --git a/java/com/google/domain/registry/flows/domain/BaseDomainCheckFlow.java b/java/com/google/domain/registry/flows/domain/BaseDomainCheckFlow.java new file mode 100644 index 000000000..26602c2e2 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/BaseDomainCheckFlow.java @@ -0,0 +1,57 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDomainName; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceCheckFlow; +import com.google.domain.registry.model.domain.DomainCommand.Check; +import com.google.domain.registry.model.domain.DomainResource; + +import java.util.Map; + +/** An EPP flow that checks whether a domain can be provisioned. */ +public abstract class BaseDomainCheckFlow extends ResourceCheckFlow { + + protected Map domainNames; + + @Override + protected final void initCheckResourceFlow() throws EppException { + ImmutableMap.Builder domains = new ImmutableMap.Builder<>(); + ImmutableSet.Builder tlds = new ImmutableSet.Builder<>(); + for (String targetId : ImmutableSet.copyOf(targetIds)) { + // This validation is moderately expensive, so cache the results for getCheckData to use too. + InternetDomainName domainName = validateDomainName(targetId); + tlds.add(domainName.parent().toString()); + validateDomainNameWithIdnTables(domainName); + domains.put(targetId, domainName); + } + for (String tld : tlds.build()) { + checkAllowedAccessToTld(getAllowedTlds(), tld); + checkRegistryStateForTld(tld); + } + domainNames = domains.build(); + initDomainCheckFlow(); + } + + @SuppressWarnings("unused") + protected void initDomainCheckFlow() throws EppException {} +} diff --git a/java/com/google/domain/registry/flows/domain/BaseDomainCreateFlow.java b/java/com/google/domain/registry/flows/domain/BaseDomainCreateFlow.java new file mode 100644 index 000000000..202271b46 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/BaseDomainCreateFlow.java @@ -0,0 +1,376 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDomainName; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchPhase; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotReserved; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifySignedMarks; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; +import static com.google.domain.registry.model.EppResourceUtils.createDomainRoid; +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.findTldForName; +import static com.google.domain.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation; + +import com.google.common.base.Optional; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.flows.EppException.UnimplementedOptionException; +import com.google.domain.registry.flows.ResourceCreateFlow; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainBase.Builder; +import com.google.domain.registry.model.domain.DomainCommand.Create; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.fee.FeeCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchNotice; +import com.google.domain.registry.model.domain.launch.LaunchNotice.InvalidChecksumException; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.secdns.SecDnsCreateExtension; +import com.google.domain.registry.model.ofy.ObjectifyService; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.smd.SignedMark; +import com.google.domain.registry.model.tmch.ClaimsListShard; + +import com.googlecode.objectify.Work; + +import org.joda.money.Money; + +import javax.annotation.Nullable; + +/** + * An EPP flow that creates a new domain resource or application. + * + * @param the resource type being created + * @param a builder for the resource + */ +public abstract class BaseDomainCreateFlow> + extends ResourceCreateFlow { + + private SecDnsCreateExtension secDnsCreate; + + protected LaunchCreateExtension launchCreate; + protected String domainLabel; + protected InternetDomainName domainName; + protected String idnTableName; + protected FeeCreateExtension feeCreate; + protected Money createCost; + protected boolean hasSignedMarks; + protected SignedMark signedMark; + protected boolean isAnchorTenantViaReservation; + protected TldState tldState; + + @Override + public final void initResourceCreateOrMutateFlow() throws EppException { + command = cloneAndLinkReferences(command, now); + registerExtensions(SecDnsCreateExtension.class); + secDnsCreate = eppInput.getSingleExtension(SecDnsCreateExtension.class); + launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class); + feeCreate = eppInput.getSingleExtension(FeeCreateExtension.class); + hasSignedMarks = launchCreate != null && !launchCreate.getSignedMarks().isEmpty(); + initDomainCreateFlow(); + } + + @Override + @Nullable + protected String createFlowRepoId() { + // The domain name hasn't been validated yet, so if it's invalid, instead of throwing an error, + // simply leave the repoId blank (it won't be needed anyway as the flow will fail when + // validation fails later). + try { + Optional tldParsed = + findTldForName(InternetDomainName.from(command.getFullyQualifiedDomainName())); + return tldParsed.isPresent() + ? createDomainRoid(ObjectifyService.allocateId(), tldParsed.get().toString()) + : null; + } catch (IllegalArgumentException e) { + return null; + } + } + + /** Subclasses may override this to do more specific initialization. */ + protected void initDomainCreateFlow() {} + + /** + * Returns the tld of the domain being created. + * + *

Update/delete domain-related flows can simply grab the tld using existingResource.getTld(), + * but in the create flows, the resource doesn't exist yet. So we grab it off the domain name + * that the flow is attempting to create. + * + *

Note that it's not always safe to call this until after the domain name has been validated + * in verifyCreateIsAllowed(). + */ + protected String getTld() { + return domainName.parent().toString(); + } + + /** + * Fail the domain or application create very fast if the domain is already registered. + *

+ * Try to load the domain non-transactionally, since this can hit memcache. If we succeed, and the + * domain is not in the ADD grace period (the only state that allows instantaneous transition to + * being deleted), we can assume that the domain will not be deleted (and therefore won't be + * creatable) until its deletion time. For repeated failed creates this means we can avoid the + * datastore lookup, which is very expensive (and first-seen failed creates are no worse than they + * otherwise would be). This comes at the cost of the extra lookup for successful creates (or + * rather, those that don't fail due to the domain existing) and also for failed creates within + * the existing domain's ADD grace period. + */ + @Override + protected final void failfast() throws EppException { + // Enter a transactionless context briefly. + DomainResource domain = ofy().doTransactionless(new Work() { + @Override + public DomainResource run() { + // This is cacheable because we are outside of a transaction. + return loadByUniqueId(DomainResource.class, targetId, now); + }}); + // If the domain exists already and isn't in the ADD grace period then there is no way it will + // be suddenly deleted and therefore the create must fail. + if (domain != null + && !domain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD)) { + throw new ResourceAlreadyExistsException(targetId, true); + } + } + + /** Fail if the create command is somehow invalid. */ + @Override + protected final void verifyCreateIsAllowed() throws EppException { + // Validate that this is actually a legal domain name on a TLD that the registrar has access to. + domainName = validateDomainName(command.getFullyQualifiedDomainName()); + idnTableName = validateDomainNameWithIdnTables(domainName); + String tld = getTld(); + checkAllowedAccessToTld(getAllowedTlds(), tld); + Registry registry = Registry.get(tld); + tldState = registry.getTldState(now); + checkRegistryStateForTld(tld); + domainLabel = domainName.parts().get(0); + createCost = registry.getDomainCreateCost(targetId, command.getPeriod().getValue()); + // The TLD should always be the parent of the requested domain name. + isAnchorTenantViaReservation = matchesAnchorTenantReservation( + domainLabel, tld, command.getAuthInfo().getPw().getValue()); + // Superusers can create reserved domains, force creations on domains that require a claims + // notice without specifying a claims key, and override blocks on registering premium domains. + if (!superuser) { + boolean isSunriseApplication = + launchCreate != null && !launchCreate.getSignedMarks().isEmpty(); + if (!isAnchorTenantViaReservation) { + verifyNotReserved(domainName, isSunriseApplication); + } + boolean isClaimsPeriod = now.isBefore(registry.getClaimsPeriodEnd()); + boolean isClaimsCreate = launchCreate != null && launchCreate.getNotice() != null; + if (isClaimsPeriod) { + boolean labelOnClaimsList = ClaimsListShard.get().getClaimKey(domainLabel) != null; + if (labelOnClaimsList && !isSunriseApplication && !isClaimsCreate) { + throw new MissingClaimsNoticeException(domainName.toString()); + } + if (!labelOnClaimsList && isClaimsCreate) { + throw new UnexpectedClaimsNoticeException(domainName.toString()); + } + } else if (isClaimsCreate) { + throw new ClaimsPeriodEndedException(tld); + } + verifyPremiumNameIsNotBlocked(targetId, tld, getClientId()); + } + verifyUnitIsYears(command.getPeriod()); + verifyNotInPendingDelete( + command.getContacts(), + command.getRegistrant(), + command.getNameservers()); + validateContactsHaveTypes(command.getContacts()); + validateNoDuplicateContacts(command.getContacts()); + validateRequiredContactsPresent(command.getRegistrant(), command.getContacts()); + validateNameservers(command.getNameservers()); + validateLaunchCreateExtension(); + // If a signed mark was provided, then it must match the desired domain label. + // We do this after validating the launch create extension so that flows which don't allow any + // signed marks throw a more useful error message rather than complaining about specific issues + // with the signed marks. + if (hasSignedMarks) { + signedMark = verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now); + } + validateSecDnsExtension(); + verifyDomainCreateIsAllowed(); + } + + /** Validate the secDNS extension, if present. */ + private void validateSecDnsExtension() throws EppException { + if (secDnsCreate != null) { + if (secDnsCreate.getDsData() == null) { + throw new DsDataRequiredException(); + } + if (secDnsCreate.getMaxSigLife() != null) { + throw new MaxSigLifeNotSupportedException(); + } + validateDsData(secDnsCreate.getDsData()); + } + } + + /** + * If a launch create extension was given (always present for application creates, optional for + * domain creates) then validate it. + */ + private void validateLaunchCreateExtension() throws EppException { + if (launchCreate == null) { + return; + } + if (!superuser) { // Superusers can ignore the phase. + verifyLaunchPhase(getTld(), launchCreate, now); + } + if (launchCreate.hasCodeMarks()) { + throw new UnsupportedMarkTypeException(); + } + validateDomainLaunchCreateExtension(); + LaunchNotice notice = launchCreate.getNotice(); + if (notice == null) { + return; + } + if (!notice.getNoticeId().getValidatorId().equals("tmch")) { + throw new InvalidTrademarkValidatorException(); + } + // Superuser can force domain creations regardless of the current date. + if (!superuser) { + if (notice.getExpirationTime().isBefore(now)) { + throw new ExpiredClaimException(); + } + // An acceptance within the past 48 hours is mandated by the TMCH Functional Spec. + if (notice.getAcceptedTime().isBefore(now.minusHours(48))) { + throw new AcceptedTooLongAgoException(); + } + } + try { + notice.validate(domainLabel); + } catch (IllegalArgumentException e) { + throw new MalformedTcnIdException(); + } catch (InvalidChecksumException e) { + throw new InvalidTcnIdChecksumException(); + } + } + + /** Subclasses may override this to do more specific checks. */ + @SuppressWarnings("unused") + protected void verifyDomainCreateIsAllowed() throws EppException {} + + /** Subclasses may override this to do more specific validation of the launchCreate extension. */ + @SuppressWarnings("unused") + protected void validateDomainLaunchCreateExtension() throws EppException {} + + /** Handle the secDNS extension */ + @Override + protected final void setCreateProperties(B builder) throws EppException { + if (secDnsCreate != null) { + builder.setDsData(secDnsCreate.getDsData()); + } + builder.setLaunchNotice(launchCreate == null ? null : launchCreate.getNotice()); + setDomainCreateProperties(builder); + builder.setIdnTableName(idnTableName); + } + + protected abstract void setDomainCreateProperties(B builder) throws EppException; + + /** Requested domain requires a claims notice. */ + static class MissingClaimsNoticeException extends StatusProhibitsOperationException { + public MissingClaimsNoticeException(String domainName) { + super(String.format("%s requires a claims notice", domainName)); + } + } + + /** Requested domain does not require a claims notice. */ + static class UnexpectedClaimsNoticeException extends StatusProhibitsOperationException { + public UnexpectedClaimsNoticeException(String domainName) { + super(String.format("%s does not require a claims notice", domainName)); + } + } + + /** The claims period for this TLD has ended. */ + static class ClaimsPeriodEndedException extends StatusProhibitsOperationException { + public ClaimsPeriodEndedException(String tld) { + super(String.format("The claims period for %s has ended", tld)); + } + } + + /** The specified trademark validator is not supported. */ + static class InvalidTrademarkValidatorException extends ParameterValuePolicyErrorException { + public InvalidTrademarkValidatorException() { + super("The only supported validationID is 'tmch' for the ICANN Trademark Clearinghouse."); + } + } + + /** At least one dsData is required when using the secDNS extension. */ + static class DsDataRequiredException extends ParameterValuePolicyErrorException { + public DsDataRequiredException() { + super("At least one dsData is required when using the secDNS extension"); + } + } + + /** Only encoded signed marks are supported. */ + static class UnsupportedMarkTypeException extends ParameterValuePolicyErrorException { + public UnsupportedMarkTypeException() { + super("Only encoded signed marks are supported"); + } + } + + /** The 'maxSigLife' setting is not supported. */ + static class MaxSigLifeNotSupportedException extends UnimplementedOptionException { + public MaxSigLifeNotSupportedException() { + super("The 'maxSigLife' setting is not supported"); + } + } + + /** The expiration time specified in the claim notice has elapsed. */ + static class ExpiredClaimException extends ParameterValueRangeErrorException { + public ExpiredClaimException() { + super("The expiration time specified in the claim notice has elapsed"); + } + } + + /** The acceptance time specified in the claim notice is more than 48 hours in the past. */ + static class AcceptedTooLongAgoException extends ParameterValueRangeErrorException { + public AcceptedTooLongAgoException() { + super("The acceptance time specified in the claim notice is more than 48 hours in the past"); + } + } + + /** The specified TCNID is invalid. */ + static class MalformedTcnIdException extends ParameterValueSyntaxErrorException { + public MalformedTcnIdException() { + super("The specified TCNID is malformed"); + } + } + + /** The checksum in the specified TCNID does not validate. */ + static class InvalidTcnIdChecksumException extends ParameterValueRangeErrorException { + public InvalidTcnIdChecksumException() { + super("The checksum in the specified TCNID does not validate"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/BaseDomainInfoFlow.java b/java/com/google/domain/registry/flows/domain/BaseDomainInfoFlow.java new file mode 100644 index 000000000..f18d6162b --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/BaseDomainInfoFlow.java @@ -0,0 +1,51 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceInfoFlow; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainBase.Builder; +import com.google.domain.registry.model.domain.DomainCommand; +import com.google.domain.registry.model.domain.secdns.SecDnsInfoExtension; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +/** + * An EPP flow that reads a domain resource or application. + * + * @param the resource type being manipulated + * @param a builder for the resource + */ +public abstract class BaseDomainInfoFlow> + extends ResourceInfoFlow { + @Override + protected final ImmutableList getResponseExtensions() throws EppException { + ImmutableList.Builder builder = new ImmutableList.Builder<>(); + // According to RFC 5910 section 2, we should only return this if the client specified the + // "urn:ietf:params:xml:ns:secDNS-1.1" when logging in. However, this is a "SHOULD" not a "MUST" + // and we are going to ignore it; clients who don't care about secDNS can just ignore it. + if (!existingResource.getDsData().isEmpty()) { + builder.add(SecDnsInfoExtension.create(existingResource.getDsData())); + } + return forceEmptyToNull(builder.addAll(getDomainResponseExtensions()).build()); + } + + /** Subclasses should override this to add their extensions. */ + protected abstract ImmutableList getDomainResponseExtensions() + throws EppException; +} diff --git a/java/com/google/domain/registry/flows/domain/BaseDomainUpdateFlow.java b/java/com/google/domain/registry/flows/domain/BaseDomainUpdateFlow.java new file mode 100644 index 000000000..86521ff69 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/BaseDomainUpdateFlow.java @@ -0,0 +1,154 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.union; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.EppException.UnimplementedOptionException; +import com.google.domain.registry.flows.ResourceUpdateFlow; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainBase.Builder; +import com.google.domain.registry.model.domain.DomainCommand.Update; +import com.google.domain.registry.model.domain.secdns.DelegationSignerData; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension.Add; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension.Remove; + +import java.util.Set; + +/** + * An EPP flow that updates a domain application or resource. + * + * @param the resource type being created + * @param a builder for the resource + */ +public abstract class BaseDomainUpdateFlow> + extends ResourceUpdateFlow { + + @Override + public final void initResourceCreateOrMutateFlow() throws EppException { + command = cloneAndLinkReferences(command, now); + initDomainUpdateFlow(); + } + + @SuppressWarnings("unused") + protected void initDomainUpdateFlow() throws EppException {} + + @Override + public final B setUpdateProperties(B builder) throws EppException { + // Handle the secDNS extension. + SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class); + if (secDnsUpdate != null) { + // We don't support 'urgent' because we do everything as fast as we can anyways. + if (Boolean.TRUE.equals(secDnsUpdate.getUrgent())) { // We allow both false and null. + throw new UrgentAttributeNotSupportedException(); + } + // There must be at least one of add/rem/chg, and chg isn't actually supported. + if (secDnsUpdate.getAdd() == null && secDnsUpdate.getRemove() == null) { + // The only thing you can change is maxSigLife, and we don't support that at all. + throw (secDnsUpdate.getChange() == null) + ? new EmptySecDnsUpdateException() + : new MaxSigLifeChangeNotSupportedException(); + } + Set newDsData = existingResource.getDsData(); + // RFC 5901 specifies that removes are processed before adds. + Remove remove = secDnsUpdate.getRemove(); + if (remove != null) { + if (Boolean.FALSE.equals(remove.getAll())) { // Explicit all=false is meaningless. + throw new SecDnsAllUsageException(); + } + newDsData = (remove.getAll() == null) + ? difference(existingResource.getDsData(), remove.getDsData()) + : ImmutableSet.of(); + } + Add add = secDnsUpdate.getAdd(); + if (add != null) { + newDsData = union(newDsData, add.getDsData()); + } + builder.setDsData(ImmutableSet.copyOf(newDsData)); + } + return setDomainUpdateProperties(builder); + } + + /** Subclasses can override this to do set more specific properties. */ + protected B setDomainUpdateProperties(B builder) { + return builder; + } + + @Override + protected final void verifyUpdateIsAllowed() throws EppException { + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + verifyDomainUpdateIsAllowed(); + verifyNotInPendingDelete( + command.getInnerAdd().getContacts(), + command.getInnerChange().getRegistrant(), + command.getInnerAdd().getNameservers()); + validateContactsHaveTypes(command.getInnerAdd().getContacts()); + validateContactsHaveTypes(command.getInnerRemove().getContacts()); + } + + /** Subclasses can override this to do more specific verification. */ + @SuppressWarnings("unused") + protected void verifyDomainUpdateIsAllowed() throws EppException {} + + @Override + protected final void verifyNewUpdatedStateIsAllowed() throws EppException { + validateNoDuplicateContacts(newResource.getContacts()); + validateRequiredContactsPresent(newResource.getRegistrant(), newResource.getContacts()); + validateDsData(newResource.getDsData()); + validateNameservers(newResource.getNameservers()); + } + + /** The secDNS:all element must have value 'true' if present. */ + static class SecDnsAllUsageException extends ParameterValuePolicyErrorException { + public SecDnsAllUsageException() { + super("The secDNS:all element must have value 'true' if present"); + } + } + + /** At least one of 'add' or 'rem' is required on a secDNS update. */ + static class EmptySecDnsUpdateException extends RequiredParameterMissingException { + public EmptySecDnsUpdateException() { + super("At least one of 'add' or 'rem' is required on a secDNS update"); + } + } + + /** The 'urgent' attribute is not supported. */ + static class UrgentAttributeNotSupportedException extends UnimplementedOptionException { + public UrgentAttributeNotSupportedException() { + super("The 'urgent' attribute is not supported"); + } + } + + /** Changing 'maxSigLife' is not supported. */ + static class MaxSigLifeChangeNotSupportedException extends UnimplementedOptionException { + public MaxSigLifeChangeNotSupportedException() { + super("Changing 'maxSigLife' is not supported"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/ClaimsCheckFlow.java b/java/com/google/domain/registry/flows/domain/ClaimsCheckFlow.java new file mode 100644 index 000000000..ba7d53dad --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/ClaimsCheckFlow.java @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.model.domain.launch.LaunchPhase.CLAIMS; +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.model.domain.launch.LaunchCheckExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckResponseExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheck; +import com.google.domain.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheckName; +import com.google.domain.registry.model.eppoutput.CheckData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.tmch.ClaimsListShard; + +import java.util.Map.Entry; + +/** + * An EPP flow that checks whether strings are trademarked. + * + * @error {@link com.google.domain.registry.flows.ResourceCheckFlow.TooManyResourceChecksException} + * @error {@link com.google.domain.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link DomainFlowUtils.TldDoesNotExistException} + */ +public class ClaimsCheckFlow extends BaseDomainCheckFlow { + + public static final ImmutableSet DISALLOWED_TLD_STATES = Sets.immutableEnumSet( + TldState.PREDELEGATION, TldState.SUNRISE); + + @Override + protected void initDomainCheckFlow() throws EppException { + registerExtensions(LaunchCheckExtension.class); + } + + @Override + protected CheckData getCheckData() { + return null; + } + + @Override + protected ImmutableList getResponseExtensions() throws EppException { + ImmutableList.Builder launchChecksBuilder = new ImmutableList.Builder<>(); + for (Entry entry : domainNames.entrySet()) { + InternetDomainName domainName = entry.getValue(); + if (isAtOrAfter(now, Registry.get(domainName.parent().toString()).getClaimsPeriodEnd())) { + throw new BadCommandForRegistryPhaseException(); + } + String claimKey = ClaimsListShard.get().getClaimKey(domainName.parts().get(0)); + launchChecksBuilder.add(LaunchCheck.create( + LaunchCheckName.create(claimKey != null, entry.getKey()), claimKey)); + } + return ImmutableList.of( + LaunchCheckResponseExtension.create(CLAIMS, launchChecksBuilder.build())); + } + + @Override + protected final ImmutableSet getDisallowedTldStates() { + return DISALLOWED_TLD_STATES; + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainAllocateFlow.java b/java/com/google/domain/registry/flows/domain/DomainAllocateFlow.java new file mode 100644 index 000000000..f1cc63bc9 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainAllocateFlow.java @@ -0,0 +1,223 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.getReservationType; +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.isNullOrEmpty; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Flag; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.allocate.AllocateCreateExtension; +import com.google.domain.registry.model.domain.launch.ApplicationStatus; +import com.google.domain.registry.model.domain.launch.LaunchInfoResponseExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.label.ReservationType; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.tmch.LordnTask; + +import com.googlecode.objectify.Ref; + +/** + * An EPP flow that allocates a new domain resource from a domain application. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link DomainAllocateFlow.HasFinalStatusException} + * @error {@link DomainAllocateFlow.MissingAllocateCreateExtensionException} + * @error {@link DomainAllocateFlow.MissingApplicationException} + * @error {@link DomainAllocateFlow.OnlySuperuserCanAllocateException} + */ +public class DomainAllocateFlow extends DomainCreateOrAllocateFlow { + + protected AllocateCreateExtension allocateCreate; + protected DomainApplication application; + + @Override + protected final void initDomainCreateOrAllocateFlow() { + registerExtensions(AllocateCreateExtension.class); + allocateCreate = eppInput.getSingleExtension(AllocateCreateExtension.class); + } + + @Override + protected final void verifyDomainCreateIsAllowed() throws EppException { + if (!superuser) { + throw new OnlySuperuserCanAllocateException(); + } + if (allocateCreate == null) { + throw new MissingAllocateCreateExtensionException(); + } + String applicationRoid = allocateCreate.getApplicationRoid(); + application = loadByUniqueId(DomainApplication.class, applicationRoid, now); + if (application == null) { + throw new MissingApplicationException(applicationRoid); + } + if (application.getApplicationStatus().isFinalStatus()) { + throw new HasFinalStatusException(); + } + } + + @Override + protected final void setDomainCreateOrAllocateProperties(Builder builder) { + boolean sunrushAddGracePeriod = isNullOrEmpty(command.getNameservers()); + Registry registry = Registry.get(getTld()); + ImmutableSet.Builder billingFlagsBuilder = ImmutableSet.builder(); + if (!application.getEncodedSignedMarks().isEmpty()) { + billingFlagsBuilder.add(Flag.SUNRISE); + } else { + billingFlagsBuilder.add(Flag.LANDRUSH); + } + BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.CREATE) + .setFlags(billingFlagsBuilder.add(Flag.ALLOCATION).build()) + .setTargetId(targetId) + .setClientId(getClientId()) + .setCost(registry.getDomainCreateCost(targetId, command.getPeriod().getValue())) + .setPeriodYears(command.getPeriod().getValue()) + .setEventTime(now) + // If there are no nameservers on the domain, then they get the benefit of the sunrush add + // grace period, which is longer than the standard add grace period. + .setBillingTime(now.plus(sunrushAddGracePeriod + ? registry.getSunrushAddGracePeriodLength() + : registry.getAddGracePeriodLength())) + .setParent(historyEntry) + .build(); + ReservationType reservationType = getReservationType(domainName); + ofy().save().entities( + // Save the billing event + billingEvent, + // Update the application itself. + application.asBuilder() + .setApplicationStatus(ApplicationStatus.ALLOCATED) + .removeStatusValue(StatusValue.PENDING_CREATE) + .build(), + // Create a poll message informing the registrar that the application status was updated. + new PollMessage.OneTime.Builder() + .setClientId(application.getCurrentSponsorClientId()) + .setEventTime(ofy().getTransactionTime()) + .setMsg(reservationType == ReservationType.NAME_COLLISION + // Change the poll message to remind the registrar of the name collision policy. + ? "Domain on the name collision list was allocated. " + + "But by policy, the domain will not be delegated. " + + "Please visit https://www.icann.org/namecollision " + + "for more information on name collision." + : "Domain was allocated") + .setResponseData(ImmutableList.of( + DomainPendingActionNotificationResponse.create( + application.getFullyQualifiedDomainName(), + true, + // If the creation TRID is not present on the application (this can happen for + // older applications written before this field was added), then we must read + // the earliest history entry for the application to retrieve it. + application.getCreationTrid() == null + ? checkNotNull(ofy() + .load() + .type(HistoryEntry.class) + .ancestor(application) + .order("modificationTime") + .first() + .now() + .getTrid()) + : application.getCreationTrid(), + now))) + .setResponseExtensions(ImmutableList.of( + new LaunchInfoResponseExtension.Builder() + .setApplicationId(application.getForeignKey()) + .setPhase(application.getPhase()) + .setApplicationStatus(ApplicationStatus.ALLOCATED) + .build())) + .setParent(historyEntry) + .build(), + // Create a history entry (with no xml or trid) to record that we updated the application. + new HistoryEntry.Builder() + .setType(HistoryEntry.Type.DOMAIN_APPLICATION_STATUS_UPDATE) + .setParent(application) + .setModificationTime(now) + .setClientId(application.getCurrentSponsorClientId()) + .setBySuperuser(true) + .build()); + // Set the properties on the new domain. + builder + .addGracePeriod(GracePeriod.forBillingEvent( + sunrushAddGracePeriod ? GracePeriodStatus.SUNRUSH_ADD : GracePeriodStatus.ADD, + billingEvent)) + .setApplicationTime(allocateCreate.getApplicationTime()) + .setApplication(Ref.create(application)) + .setSmdId(allocateCreate.getSmdId()) + .setLaunchNotice(allocateCreate.getNotice()); + // Names on the collision list will not be delegated. Set server hold. + if (ReservationType.NAME_COLLISION == reservationType) { + builder.addStatusValue(StatusValue.SERVER_HOLD); + } + } + + @Override + protected void enqueueLordnTaskIfNeeded() { + if (allocateCreate.getSmdId() != null || allocateCreate.getNotice() != null) { + LordnTask.enqueueDomainResourceTask(newResource); + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_ALLOCATE; + } + + /** The allocate create extension is required to allocate a domain. */ + static class MissingAllocateCreateExtensionException extends RequiredParameterMissingException { + public MissingAllocateCreateExtensionException() { + super("The allocate create extension is required to allocate a domain"); + } + } + + /** Domain application with specific ROID does not exist. */ + static class MissingApplicationException extends ObjectDoesNotExistException { + public MissingApplicationException(String applicationRoid) { + super(DomainApplication.class, applicationRoid); + } + } + + /** Domain application already has a final status. */ + static class HasFinalStatusException extends StatusProhibitsOperationException { + public HasFinalStatusException() { + super("Domain application already has a final status"); + } + } + + /** Only a superuser can allocate domains. */ + static class OnlySuperuserCanAllocateException extends AuthorizationErrorException { + public OnlySuperuserCanAllocateException() { + super("Only a superuser can allocate domains"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainApplicationCreateFlow.java b/java/com/google/domain/registry/flows/domain/DomainApplicationCreateFlow.java new file mode 100644 index 000000000..0dd6cf3ed --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainApplicationCreateFlow.java @@ -0,0 +1,251 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; +import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.ObjectAlreadyExistsException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainApplication.Builder; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeCreateExtension; +import com.google.domain.registry.model.domain.fee.FeeCreateResponseExtension; +import com.google.domain.registry.model.domain.launch.ApplicationStatus; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateResponseExtension; +import com.google.domain.registry.model.domain.launch.LaunchPhase; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppoutput.CreateData.DomainCreateData; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.smd.AbstractSignedMark; +import com.google.domain.registry.model.smd.EncodedSignedMark; + +import java.util.List; + +/** + * An EPP flow that creates a new application for a domain resource. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException} + * @error {@link BaseDomainCreateFlow.AcceptedTooLongAgoException} + * @error {@link BaseDomainCreateFlow.ClaimsPeriodEndedException} + * @error {@link BaseDomainCreateFlow.ExpiredClaimException} + * @error {@link BaseDomainCreateFlow.InvalidTcnIdChecksumException} + * @error {@link BaseDomainCreateFlow.InvalidTrademarkValidatorException} + * @error {@link BaseDomainCreateFlow.MalformedTcnIdException} + * @error {@link BaseDomainCreateFlow.MaxSigLifeNotSupportedException} + * @error {@link BaseDomainCreateFlow.MissingClaimsNoticeException} + * @error {@link BaseDomainCreateFlow.UnexpectedClaimsNoticeException} + * @error {@link BaseDomainCreateFlow.UnsupportedMarkTypeException} + * @error {@link DomainApplicationCreateFlow.LandrushApplicationDisallowedDuringSunriseException} + * @error {@link DomainApplicationCreateFlow.NoticeCannotBeUsedWithSignedMarkException} + * @error {@link DomainApplicationCreateFlow.SunriseApplicationDisallowedDuringLandrushException} + * @error {@link DomainApplicationCreateFlow.UncontestedSunriseApplicationBlockedInLandrushException} + * @error {@link DomainFlowUtils.BadDomainNameCharacterException} + * @error {@link DomainFlowUtils.BadDomainNamePartsCountException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.Base64RequiredForEncodedSignedMarksException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.CurrencyValueScaleException} + * @error {@link DomainFlowUtils.DashesInThirdAndFourthException} + * @error {@link DomainFlowUtils.DomainLabelTooLongException} + * @error {@link DomainFlowUtils.DomainReservedException} + * @error {@link DomainFlowUtils.DuplicateContactForRoleException} + * @error {@link DomainFlowUtils.EmptyDomainNamePartException} + * @error {@link DomainFlowUtils.FeesMismatchException} + * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} + * @error {@link DomainFlowUtils.InvalidIdnDomainLabelException} + * @error {@link DomainFlowUtils.InvalidPunycodeException} + * @error {@link DomainFlowUtils.LaunchPhaseMismatchException} + * @error {@link DomainFlowUtils.LeadingDashException} + * @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException} + * @error {@link DomainFlowUtils.MissingContactTypeException} + * @error {@link DomainFlowUtils.NoMarksFoundMatchingDomainException} + * @error {@link DomainFlowUtils.PremiumNameBlockedException} + * @error {@link DomainFlowUtils.SignedMarksMustBeEncodedException} + * @error {@link DomainFlowUtils.SignedMarkCertificateExpiredException} + * @error {@link DomainFlowUtils.SignedMarkCertificateInvalidException} + * @error {@link DomainFlowUtils.SignedMarkCertificateNotYetValidException} + * @error {@link DomainFlowUtils.SignedMarkCertificateRevokedException} + * @error {@link DomainFlowUtils.SignedMarkCertificateSignatureException} + * @error {@link DomainFlowUtils.SignedMarkEncodingErrorException} + * @error {@link DomainFlowUtils.SignedMarkParsingErrorException} + * @error {@link DomainFlowUtils.SignedMarkRevokedErrorException} + * @error {@link DomainFlowUtils.SignedMarkSignatureException} + * @error {@link DomainFlowUtils.TldDoesNotExistException} + * @error {@link DomainFlowUtils.TooManyDsRecordsException} + * @error {@link DomainFlowUtils.TooManyNameserversException} + * @error {@link DomainFlowUtils.TooManySignedMarksException} + * @error {@link DomainFlowUtils.TrailingDashException} + * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + */ +public class DomainApplicationCreateFlow extends BaseDomainCreateFlow { + + @Override + protected void initDomainCreateFlow() { + registerExtensions(FeeCreateExtension.class, LaunchCreateExtension.class); + } + + @Override + protected void validateDomainLaunchCreateExtension() throws EppException { + if (launchCreate.getSignedMarks().isEmpty()) { + // During sunrise, a signed mark is required since only trademark holders are allowed to + // create an application. However, we found no marks (ie, this was a landrush application). + if (tldState == TldState.SUNRISE) { + throw new LandrushApplicationDisallowedDuringSunriseException(); + } + } else { + if (launchCreate.getNotice() != null) { // Can't use a claims notice id with a signed mark. + throw new NoticeCannotBeUsedWithSignedMarkException(); + } + if (tldState == TldState.LANDRUSH) { + throw new SunriseApplicationDisallowedDuringLandrushException(); + } + } + } + + @Override + protected void verifyDomainCreateIsAllowed() throws EppException { + validateFeeChallenge(targetId, getTld(), feeCreate, createCost); + if (tldState == TldState.LANDRUSH && !superuser) { + // Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is + // exactly one sunrise application for the same name. + List applications = FluentIterable + .from(loadActiveApplicationsByDomainName(targetId, now)) + .limit(2) + .toList(); + if (applications.size() == 1 && applications.get(0).getPhase().equals(LaunchPhase.SUNRISE)) { + throw new UncontestedSunriseApplicationBlockedInLandrushException(); + } + } + // Fail if the domain is already registered (e.g. this is a landrush application but the domain + // was awarded at the end of sunrise). + if (loadAndGetReference(DomainResource.class, targetId, now) != null) { + throw new ResourceAlreadyExistsException(targetId); + } + } + + @Override + protected void setDomainCreateProperties(Builder builder) { + builder + .setCreationTrid(trid) + .setPhase(launchCreate.getPhase()) + .setApplicationStatus(ApplicationStatus.VALIDATED) + .addStatusValue(StatusValue.PENDING_CREATE); + if (!launchCreate.getSignedMarks().isEmpty()) { + builder.setEncodedSignedMarks(FluentIterable + .from(launchCreate.getSignedMarks()) + .transform(new Function() { + @Override + public EncodedSignedMark apply(AbstractSignedMark abstractSignedMark) { + // We verified that this is the case in verifyDomainCreateIsAllowed(). + return (EncodedSignedMark) abstractSignedMark; + }}) + .toList()); + } + } + + @Override + protected final ImmutableSet getDisallowedTldStates() { + return DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_APPLICATION_CREATE; + } + + @Override + protected final Period getCommandPeriod() { + return command.getPeriod(); + } + + @Override + protected boolean tryToLoadExisting() { + // Multiple domain applications can be created for the same targetId (which is the fully + // qualified domain name), so don't try to load an existing resource with the same target id. + return false; + } + + @Override + protected final EppOutput getOutput() { + ImmutableList.Builder responseExtensionsBuilder = + new ImmutableList.Builder<>(); + responseExtensionsBuilder.add(new LaunchCreateResponseExtension.Builder() + .setPhase(launchCreate.getPhase()) + .setApplicationId(newResource.getForeignKey()) + .build()); + if (feeCreate != null) { + responseExtensionsBuilder.add(new FeeCreateResponseExtension.Builder() + .setCurrency(createCost.getCurrencyUnit()) + .setFee(ImmutableList.of(Fee.create(createCost.getAmount(), "create"))) + .build()); + } + + return createOutput( + Success, + DomainCreateData.create(newResource.getFullyQualifiedDomainName(), now, null), + responseExtensionsBuilder.build()); + } + + /** Landrush applications are disallowed during sunrise. */ + static class LandrushApplicationDisallowedDuringSunriseException + extends RequiredParameterMissingException { + public LandrushApplicationDisallowedDuringSunriseException() { + super("Landrush applications are disallowed during sunrise"); + } + } + + /** A notice cannot be specified when using a signed mark. */ + static class NoticeCannotBeUsedWithSignedMarkException extends CommandUseErrorException { + public NoticeCannotBeUsedWithSignedMarkException() { + super("A notice cannot be specified when using a signed mark"); + } + } + + /** Sunrise applications are disallowed during landrush. */ + static class SunriseApplicationDisallowedDuringLandrushException + extends CommandUseErrorException { + public SunriseApplicationDisallowedDuringLandrushException() { + super("Sunrise applications are disallowed during landrush"); + } + } + + /** This name has already been claimed by a sunrise applicant. */ + static class UncontestedSunriseApplicationBlockedInLandrushException + extends ObjectAlreadyExistsException { + public UncontestedSunriseApplicationBlockedInLandrushException() { + super("This name has already been claimed by a sunrise applicant"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainApplicationDeleteFlow.java b/java/com/google/domain/registry/flows/domain/DomainApplicationDeleteFlow.java new file mode 100644 index 000000000..b5ff59279 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainApplicationDeleteFlow.java @@ -0,0 +1,96 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchApplicationIdMatchesDomain; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchPhase; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.flows.ResourceSyncDeleteFlow; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainApplication.Builder; +import com.google.domain.registry.model.domain.DomainCommand.Delete; +import com.google.domain.registry.model.domain.launch.LaunchDeleteExtension; +import com.google.domain.registry.model.domain.launch.LaunchPhase; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import java.util.Set; + +/** + * An EPP flow that deletes a domain application. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link DomainApplicationDeleteFlow.SunriseApplicationCannotBeDeletedInLandrushException} + * @error {@link DomainFlowUtils.ApplicationDomainNameMismatchException} + * @error {@link DomainFlowUtils.LaunchPhaseMismatchException} + */ +public class DomainApplicationDeleteFlow + extends ResourceSyncDeleteFlow { + + @Override + protected void initResourceCreateOrMutateFlow() throws EppException { + registerExtensions(LaunchDeleteExtension.class); + } + + @Override + protected void verifyMutationOnOwnedResourceAllowed() throws EppException { + String tld = existingResource.getTld(); + checkRegistryStateForTld(tld); + checkAllowedAccessToTld(getAllowedTlds(), tld); + verifyLaunchPhase(tld, eppInput.getSingleExtension(LaunchDeleteExtension.class), now); + verifyLaunchApplicationIdMatchesDomain(command, existingResource); + // Don't allow deleting a sunrise application during landrush. + if (existingResource.getPhase().equals(LaunchPhase.SUNRISE) + && Registry.get(existingResource.getTld()).getTldState(now).equals(TldState.LANDRUSH) + && !superuser) { + throw new SunriseApplicationCannotBeDeletedInLandrushException(); + } + } + + @Override + protected final ImmutableSet getDisallowedTldStates() { + return DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; + } + + /** Domain applications do not respect status values that prohibit various operations. */ + @Override + protected Set getDisallowedStatuses() { + return ImmutableSet.of(); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_APPLICATION_DELETE; + } + + /** A sunrise application cannot be deleted during landrush. */ + static class SunriseApplicationCannotBeDeletedInLandrushException + extends StatusProhibitsOperationException { + public SunriseApplicationCannotBeDeletedInLandrushException() { + super("A sunrise application cannot be deleted during landrush"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainApplicationInfoFlow.java b/java/com/google/domain/registry/flows/domain/DomainApplicationInfoFlow.java new file mode 100644 index 000000000..7c066aee0 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainApplicationInfoFlow.java @@ -0,0 +1,117 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.EppXmlTransformer.unmarshal; +import static com.google.domain.registry.flows.ResourceFlowUtils.verifyResourceOwnership; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchApplicationIdMatchesDomain; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainApplication.Builder; +import com.google.domain.registry.model.domain.launch.LaunchInfoExtension; +import com.google.domain.registry.model.domain.launch.LaunchInfoResponseExtension; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.mark.Mark; +import com.google.domain.registry.model.smd.EncodedSignedMark; +import com.google.domain.registry.model.smd.SignedMark; + +/** + * An EPP flow that reads a domain application. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + * @error {@link DomainFlowUtils.ApplicationDomainNameMismatchException} + * @error {@link DomainApplicationInfoFlow.ApplicationLaunchPhaseMismatchException} + * @error {@link DomainApplicationInfoFlow.MissingApplicationIdException} + */ +public class DomainApplicationInfoFlow extends BaseDomainInfoFlow { + + private boolean includeMarks; + + @Override + protected final void initSingleResourceFlow() throws EppException { + registerExtensions(LaunchInfoExtension.class); + // We need to do this in init rather than verify or we'll get the generic "object not found". + LaunchInfoExtension extension = eppInput.getSingleExtension(LaunchInfoExtension.class); + if (extension.getApplicationId() == null) { + throw new MissingApplicationIdException(); + } + includeMarks = Boolean.TRUE.equals(extension.getIncludeMark()); // Default to false. + } + + @Override + protected final void verifyQueryIsAllowed() throws EppException { + verifyLaunchApplicationIdMatchesDomain(command, existingResource); + if (!existingResource.getPhase().equals( + eppInput.getSingleExtension(LaunchInfoExtension.class).getPhase())) { + throw new ApplicationLaunchPhaseMismatchException(); + } + } + + @Override + protected final DomainApplication getResourceInfo() throws EppException { + // We don't support authInfo for applications, so if it's another registrar always fail. + verifyResourceOwnership(getClientId(), existingResource); + if (!command.getHostsRequest().requestDelegated()) { + // Delegated hosts are present by default, so clear them out if they aren't wanted. + // This requires overriding the implicit status values so that we don't get INACTIVE added due + // to the missing nameservers. + return existingResource.asBuilder() + .setNameservers(null) + .buildWithoutImplicitStatusValues(); + } + return existingResource; + } + + @Override + protected final ImmutableList getDomainResponseExtensions() + throws EppException { + ImmutableList.Builder marksBuilder = new ImmutableList.Builder<>(); + if (includeMarks) { + for (EncodedSignedMark encodedMark : existingResource.getEncodedSignedMarks()) { + try { + marksBuilder.add(((SignedMark) unmarshal(encodedMark.getBytes())).getMark()); + } catch (EppException e) { + // This is a serious error; don't let the benign EppException propagate. + throw new IllegalStateException("Could not decode a stored encoded signed mark"); + } + } + } + return ImmutableList.of(new LaunchInfoResponseExtension.Builder() + .setPhase(existingResource.getPhase()) + .setApplicationId(existingResource.getForeignKey()) + .setApplicationStatus(existingResource.getApplicationStatus()) + .setMarks(marksBuilder.build()) + .build()); + } + + /** Application id is required. */ + static class MissingApplicationIdException extends RequiredParameterMissingException { + public MissingApplicationIdException() { + super("Application id is required"); + } + } + + /** Declared launch extension phase does not match phase of the application. */ + static class ApplicationLaunchPhaseMismatchException extends ParameterValuePolicyErrorException { + public ApplicationLaunchPhaseMismatchException() { + super("Declared launch extension phase does not match the phase of the application"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainApplicationUpdateFlow.java b/java/com/google/domain/registry/flows/domain/DomainApplicationUpdateFlow.java new file mode 100644 index 000000000..d7b7b6fdb --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainApplicationUpdateFlow.java @@ -0,0 +1,95 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.CaseFormat.LOWER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainApplication.Builder; +import com.google.domain.registry.model.domain.launch.ApplicationStatus; +import com.google.domain.registry.model.domain.launch.LaunchUpdateExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that updates a domain resource. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.AddRemoveSameValueEppException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link BaseDomainUpdateFlow.EmptySecDnsUpdateException} + * @error {@link BaseDomainUpdateFlow.MaxSigLifeChangeNotSupportedException} + * @error {@link BaseDomainUpdateFlow.SecDnsAllUsageException} + * @error {@link BaseDomainUpdateFlow.UrgentAttributeNotSupportedException} + * @error {@link DomainFlowUtils.DuplicateContactForRoleException} + * @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException} + * @error {@link DomainFlowUtils.MissingAdminContactException} + * @error {@link DomainFlowUtils.MissingContactTypeException} + * @error {@link DomainFlowUtils.MissingTechnicalContactException} + * @error {@link DomainFlowUtils.TooManyDsRecordsException} + * @error {@link DomainFlowUtils.TooManyNameserversException} + * @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException} + */ +public class DomainApplicationUpdateFlow + extends BaseDomainUpdateFlow { + + @Override + protected void initDomainUpdateFlow() throws EppException { + registerExtensions(LaunchUpdateExtension.class, SecDnsUpdateExtension.class); + } + + @Override + protected final void verifyDomainUpdateIsAllowed() throws EppException { + switch (existingResource.getApplicationStatus()) { + case PENDING_ALLOCATION: + case PENDING_VALIDATION: + case VALIDATED: + return; + default: + throw new ApplicationStatusProhibitsUpdateException( + existingResource.getApplicationStatus()); + } + } + + @Override + protected final ImmutableSet getDisallowedTldStates() { + return DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS; + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_APPLICATION_UPDATE; + } + + /** Application status prohibits this domain update. */ + static class ApplicationStatusProhibitsUpdateException extends StatusProhibitsOperationException { + public ApplicationStatusProhibitsUpdateException(ApplicationStatus status) { + super(String.format( + "Applications in state %s can not be updated", + UPPER_UNDERSCORE.to(LOWER_CAMEL, status.name()))); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainCheckFlow.java b/java/com/google/domain/registry/flows/domain/DomainCheckFlow.java new file mode 100644 index 000000000..c6c0356bc --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainCheckFlow.java @@ -0,0 +1,128 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.getReservationType; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.handleFeeRequest; +import static com.google.domain.registry.model.EppResourceUtils.checkResourcesExist; +import static com.google.domain.registry.model.domain.DomainUtils.getTldFromDomainName; +import static com.google.domain.registry.model.registry.label.ReservationType.UNRESERVED; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.collect.ImmutableList; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.model.domain.fee.FeeCheckExtension; +import com.google.domain.registry.model.domain.fee.FeeCheckResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeCheckResponseExtension.FeeCheck; +import com.google.domain.registry.model.domain.launch.LaunchCheckExtension; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; +import com.google.domain.registry.model.eppoutput.CheckData; +import com.google.domain.registry.model.eppoutput.CheckData.DomainCheck; +import com.google.domain.registry.model.eppoutput.CheckData.DomainCheckData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.label.ReservationType; + +import java.util.Set; + +/** + * An EPP flow that checks whether a domain can be provisioned. + * + * @error {@link com.google.domain.registry.flows.ResourceCheckFlow.TooManyResourceChecksException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link DomainFlowUtils.BadDomainNameCharacterException} + * @error {@link DomainFlowUtils.BadDomainNamePartsCountException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.DashesInThirdAndFourthException} + * @error {@link DomainFlowUtils.DomainLabelTooLongException} + * @error {@link DomainFlowUtils.EmptyDomainNamePartException} + * @error {@link DomainFlowUtils.FeeChecksDontSupportPhasesException} + * @error {@link DomainFlowUtils.InvalidIdnDomainLabelException} + * @error {@link DomainFlowUtils.InvalidPunycodeException} + * @error {@link DomainFlowUtils.LeadingDashException} + * @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException} + * @error {@link DomainFlowUtils.TldDoesNotExistException} + * @error {@link DomainFlowUtils.TrailingDashException} + * @error {@link DomainFlowUtils.UnknownFeeCommandException} + * @error {@link DomainCheckFlow.OnlyCheckedNamesCanBeFeeCheckedException} + */ +public class DomainCheckFlow extends BaseDomainCheckFlow { + + @Override + protected void initDomainCheckFlow() throws EppException { + registerExtensions(LaunchCheckExtension.class, FeeCheckExtension.class); + } + + private String getMessageForCheck(String targetId, Set existingIds) { + if (existingIds.contains(targetId)) { + return "In use"; + } + InternetDomainName domainName = domainNames.get(targetId); + ReservationType reservationType = getReservationType(domainName); + Registry registry = Registry.get(domainName.parent().toString()); + if (reservationType == UNRESERVED + && registry.isPremiumName(domainName) + && registry.getPremiumPriceAckRequired() + && !nullToEmpty(sessionMetadata.getServiceExtensionUris()).contains( + ServiceExtension.FEE_0_6.getUri())) { + return "Premium names require EPP ext."; + } + return reservationType.getMessageForCheck(); + } + + @Override + protected CheckData getCheckData() { + Set existingIds = checkResourcesExist(resourceClass, targetIds, now); + ImmutableList.Builder checks = new ImmutableList.Builder<>(); + for (String id : targetIds) { + String message = getMessageForCheck(id, existingIds); + checks.add(DomainCheck.create(message == null, id, message)); + } + return DomainCheckData.create(checks.build()); + } + + /** Handle the fee check extension. */ + @Override + protected ImmutableList getResponseExtensions() throws EppException { + FeeCheckExtension feeCheck = eppInput.getSingleExtension(FeeCheckExtension.class); + if (feeCheck == null) { + return null; // No fee checks were requested. + } + ImmutableList.Builder feeChecksBuilder = new ImmutableList.Builder<>(); + for (FeeCheckExtension.DomainCheck domainCheck : feeCheck.getDomains()) { + String domainName = domainCheck.getName(); + if (!domainNames.containsKey(domainName)) { + // Although the fee extension explicitly says it's ok to fee check a domain name that you + // aren't also availability checking, we forbid it. This makes the experience simpler and + // also means we can assume any domain names in the fee checks have been validated. + throw new OnlyCheckedNamesCanBeFeeCheckedException(); + } + FeeCheck.Builder builder = new FeeCheck.Builder(); + handleFeeRequest(domainCheck, builder, domainName, getTldFromDomainName(domainName), now); + feeChecksBuilder.add(builder.setName(domainName).build()); + } + return ImmutableList.of(FeeCheckResponseExtension.create(feeChecksBuilder.build())); + } + + /** By server policy, fee check names must be listed in the availability check. */ + static class OnlyCheckedNamesCanBeFeeCheckedException extends ParameterValuePolicyErrorException { + OnlyCheckedNamesCanBeFeeCheckedException() { + super("By server policy, fee check names must be listed in the availability check"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainCreateFlow.java b/java/com/google/domain/registry/flows/domain/DomainCreateFlow.java new file mode 100644 index 000000000..d17ddba7a --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainCreateFlow.java @@ -0,0 +1,197 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static com.google.domain.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.fee.FeeCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.tmch.LordnTask; + +import java.util.Set; + +/** + * An EPP flow that creates a new domain resource. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.LoggedInFlow.UndeclaredServiceExtensionException} + * @error {@link com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException} + * @error {@link com.google.domain.registry.flows.ResourceCreateOrMutateFlow.OnlyToolCanPassMetadataException} + * @error {@link com.google.domain.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link BaseDomainCreateFlow.AcceptedTooLongAgoException} + * @error {@link BaseDomainCreateFlow.ClaimsPeriodEndedException} + * @error {@link BaseDomainCreateFlow.ExpiredClaimException} + * @error {@link BaseDomainCreateFlow.InvalidTcnIdChecksumException} + * @error {@link BaseDomainCreateFlow.InvalidTrademarkValidatorException} + * @error {@link BaseDomainCreateFlow.MalformedTcnIdException} + * @error {@link BaseDomainCreateFlow.MaxSigLifeNotSupportedException} + * @error {@link BaseDomainCreateFlow.MissingClaimsNoticeException} + * @error {@link BaseDomainCreateFlow.UnexpectedClaimsNoticeException} + * @error {@link BaseDomainCreateFlow.UnsupportedMarkTypeException} + * @error {@link DomainCreateFlow.SignedMarksNotAcceptedInCurrentPhaseException} + * @error {@link DomainFlowUtils.BadDomainNameCharacterException} + * @error {@link DomainFlowUtils.BadDomainNamePartsCountException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.CurrencyValueScaleException} + * @error {@link DomainFlowUtils.DashesInThirdAndFourthException} + * @error {@link DomainFlowUtils.DomainLabelTooLongException} + * @error {@link DomainFlowUtils.DomainReservedException} + * @error {@link DomainFlowUtils.DuplicateContactForRoleException} + * @error {@link DomainFlowUtils.EmptyDomainNamePartException} + * @error {@link DomainFlowUtils.FeesMismatchException} + * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} + * @error {@link DomainFlowUtils.InvalidIdnDomainLabelException} + * @error {@link DomainFlowUtils.InvalidPunycodeException} + * @error {@link DomainFlowUtils.LeadingDashException} + * @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException} + * @error {@link DomainFlowUtils.LinkedResourceInPendingDeleteProhibitsOperationException} + * @error {@link DomainFlowUtils.MissingAdminContactException} + * @error {@link DomainFlowUtils.MissingContactTypeException} + * @error {@link DomainFlowUtils.MissingRegistrantException} + * @error {@link DomainFlowUtils.MissingTechnicalContactException} + * @error {@link DomainFlowUtils.PremiumNameBlockedException} + * @error {@link DomainFlowUtils.TldDoesNotExistException} + * @error {@link DomainFlowUtils.TooManyDsRecordsException} + * @error {@link DomainFlowUtils.TooManyNameserversException} + * @error {@link DomainFlowUtils.TrailingDashException} + * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + * @error {@link DomainCreateFlow.DomainHasOpenApplicationsException} + * @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException} + */ + +public class DomainCreateFlow extends DomainCreateOrAllocateFlow { + + private static final Set QLP_SMD_ALLOWED_STATES = + Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH); + + private boolean isAnchorTenant() { + return isAnchorTenantViaReservation || isAnchorTenantViaExtension; + } + + @Override + protected final void verifyDomainCreateIsAllowed() throws EppException { + String tld = getTld(); + validateFeeChallenge(targetId, tld, feeCreate, createCost); + if (!superuser) { + // Prohibit creating a domain if there is an open application for the same name. + for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) { + if (!application.getApplicationStatus().isFinalStatus()) { + throw new DomainHasOpenApplicationsException(); + } + } + // Prohibit registrations for non-qlp and non-superuser outside of GA. + if (!isAnchorTenant() + && Registry.get(tld).getTldState(now) != TldState.GENERAL_AVAILABILITY) { + throw new NoGeneralRegistrationsInCurrentPhaseException(); + } + } + } + + @Override + protected final void initDomainCreateOrAllocateFlow() { + registerExtensions(FeeCreateExtension.class, LaunchCreateExtension.class); + } + + @Override + protected final void validateDomainLaunchCreateExtension() throws EppException { + // We can assume launchCreate is not null here. + // Only QLP domains can have a signed mark on a domain create, and only in sunrise or sunrush. + if (hasSignedMarks) { + if (isAnchorTenant() && QLP_SMD_ALLOWED_STATES.contains( + Registry.get(getTld()).getTldState(now))) { + return; + } + throw new SignedMarksNotAcceptedInCurrentPhaseException(); + } + } + + @Override + protected final void setDomainCreateOrAllocateProperties(Builder builder) throws EppException { + Registry registry = Registry.get(getTld()); + // Bill for the create. + BillingEvent.OneTime createEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.CREATE) + .setTargetId(targetId) + .setClientId(getClientId()) + .setPeriodYears(command.getPeriod().getValue()) + .setCost(checkNotNull(createCost)) + .setEventTime(now) + .setBillingTime(now.plus(isAnchorTenant() + ? registry.getAnchorTenantAddGracePeriodLength() + : registry.getAddGracePeriodLength())) + .setFlags(isAnchorTenant() ? ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT) : null) + .setParent(historyEntry) + .build(); + ofy().save().entity(createEvent); + builder.addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.ADD, createEvent)); + if (launchCreate != null && (launchCreate.getNotice() != null || hasSignedMarks)) { + builder + .setLaunchNotice(launchCreate.getNotice()) + .setSmdId(signedMark == null ? null : signedMark.getId()); + } + } + + @Override + protected void enqueueLordnTaskIfNeeded() { + if (launchCreate != null && (launchCreate.getNotice() != null || hasSignedMarks)) { + LordnTask.enqueueDomainResourceTask(newResource); + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_CREATE; + } + + /** There is an open application for this domain. */ + static class DomainHasOpenApplicationsException extends StatusProhibitsOperationException { + public DomainHasOpenApplicationsException() { + super("There is an open application for this domain"); + } + } + + /** Signed marks are not accepted in the current registry phase. */ + static class SignedMarksNotAcceptedInCurrentPhaseException extends CommandUseErrorException { + public SignedMarksNotAcceptedInCurrentPhaseException() { + super("Signed marks are not accepted in the current registry phase"); + } + } + + /** The current registry phase does not allow for general registrations. */ + static class NoGeneralRegistrationsInCurrentPhaseException extends CommandUseErrorException { + public NoGeneralRegistrationsInCurrentPhaseException() { + super("The current registry phase does not allow for general registrations"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainCreateOrAllocateFlow.java b/java/com/google/domain/registry/flows/domain/DomainCreateOrAllocateFlow.java new file mode 100644 index 000000000..7f797e33a --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainCreateOrAllocateFlow.java @@ -0,0 +1,118 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.leapSafeAddYears; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeCreateResponseExtension; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.eppoutput.CreateData.DomainCreateData; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Result; +import com.google.domain.registry.model.poll.PollMessage; + +import com.googlecode.objectify.Ref; + +import org.joda.time.DateTime; + +/** An EPP flow that creates or allocates a new domain resource. */ +public abstract class DomainCreateOrAllocateFlow + extends BaseDomainCreateFlow { + + protected boolean isAnchorTenantViaExtension; + + @Override + protected final void initDomainCreateFlow() { + registerExtensions(MetadataExtension.class); + isAnchorTenantViaExtension = + (metadataExtension != null && metadataExtension.getIsAnchorTenant()); + initDomainCreateOrAllocateFlow(); + } + + protected abstract void initDomainCreateOrAllocateFlow(); + + @Override + protected final void setDomainCreateProperties(Builder builder) throws EppException { + DateTime registrationExpirationTime = leapSafeAddYears(now, command.getPeriod().getValue()); + // Create a new autorenew billing event and poll message starting at the expiration time. + BillingEvent.Recurring autorenewEvent = new BillingEvent.Recurring.Builder() + .setReason(Reason.AUTO_RENEW) + .setTargetId(targetId) + .setClientId(getClientId()) + .setEventTime(registrationExpirationTime) + .setRecurrenceEndTime(END_OF_TIME) + .setParent(historyEntry) + .build(); + PollMessage.Autorenew autorenewPollMessage = new PollMessage.Autorenew.Builder() + .setTargetId(targetId) + .setClientId(getClientId()) + .setEventTime(registrationExpirationTime) + .setMsg("Domain was auto-renewed.") + .setParent(historyEntry) + .build(); + ofy().save().entities(autorenewEvent, autorenewPollMessage); + + builder + .setRegistrationExpirationTime(registrationExpirationTime) + .setAutorenewBillingEvent(Ref.create(autorenewEvent)) + .setAutorenewPollMessage(Ref.create(autorenewPollMessage)); + setDomainCreateOrAllocateProperties(builder); + } + + /** Subclasses must override this to set more fields, like any grace period. */ + protected abstract void setDomainCreateOrAllocateProperties(Builder builder) throws EppException; + + @Override + protected final void enqueueTasks() { + if (newResource.shouldPublishToDns()) { + DnsQueue.create().addDomainRefreshTask(newResource.getFullyQualifiedDomainName()); + } + enqueueLordnTaskIfNeeded(); + } + + /** Subclasses must override this to enqueue any additional tasks. */ + protected abstract void enqueueLordnTaskIfNeeded(); + + @Override + protected final Period getCommandPeriod() { + return command.getPeriod(); + } + + @Override + protected final EppOutput getOutput() { + return createOutput( + Result.Code.Success, + DomainCreateData.create( + newResource.getFullyQualifiedDomainName(), + now, + newResource.getRegistrationExpirationTime()), + (feeCreate == null) ? null : ImmutableList.of( + new FeeCreateResponseExtension.Builder() + .setCurrency(createCost.getCurrencyUnit()) + .setFee(ImmutableList.of(Fee.create(createCost.getAmount(), "create"))) + .build())); + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainDeleteFlow.java b/java/com/google/domain/registry/flows/domain/DomainDeleteFlow.java new file mode 100644 index 000000000..2723d579c --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainDeleteFlow.java @@ -0,0 +1,198 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithActionPending; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AssociationProhibitsOperationException; +import com.google.domain.registry.flows.ResourceSyncDeleteFlow; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.common.TimeOfYear; +import com.google.domain.registry.model.domain.DomainCommand.Delete; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.fee.Credit; +import com.google.domain.registry.model.domain.fee.FeeDeleteResponseExtension; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.eppoutput.Result.Code; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Key; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; + +/** + * An EPP flow that deletes a domain resource. + * + * @error {@link com.google.domain.registry.flows.ResourceCreateOrMutateFlow.OnlyToolCanPassMetadataException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link DomainDeleteFlow.DomainToDeleteHasHostsException} + */ +public class DomainDeleteFlow extends ResourceSyncDeleteFlow { + + PollMessage.OneTime deletePollMessage; + + CurrencyUnit creditsCurrencyUnit; + + ImmutableList credits; + + @Override + protected void initResourceCreateOrMutateFlow() throws EppException { + registerExtensions(SecDnsUpdateExtension.class, MetadataExtension.class); + } + + @Override + protected final void verifyMutationOnOwnedResourceAllowed() throws EppException { + checkRegistryStateForTld(existingResource.getTld()); + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + if (!existingResource.getSubordinateHosts().isEmpty()) { + throw new DomainToDeleteHasHostsException(); + } + } + + @Override + protected final void setDeleteProperties(Builder builder) { + // Only set to PENDING_DELETE if this domain is not in the Add Grace Period. If domain is in Add + // Grace Period, we delete it immediately. + // The base class code already handles the immediate delete case, so we only have to handle the + // pending delete case here. + if (!existingResource.getGracePeriodStatuses().contains(GracePeriodStatus.ADD)) { + Registry registry = Registry.get(existingResource.getTld()); + // By default, this should be 30 days of grace, and 5 days of pending delete. */ + DateTime deletionTime = now + .plus(registry.getRedemptionGracePeriodLength()) + .plus(registry.getPendingDeleteLength()); + deletePollMessage = new PollMessage.OneTime.Builder() + .setClientId(existingResource.getCurrentSponsorClientId()) + .setEventTime(deletionTime) + .setMsg("Domain deleted.") + .setResponseData(ImmutableList.of(DomainPendingActionNotificationResponse.create( + existingResource.getFullyQualifiedDomainName(), true, trid, deletionTime))) + .setParent(historyEntry) + .build(); + builder.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE)) + .setDeletionTime(deletionTime) + // Clear out all old grace periods and add REDEMPTION, which does not include a ref + // to a billing event because there isn't one for a domain delete. + .setGracePeriods(ImmutableSet.of(GracePeriod.create( + GracePeriodStatus.REDEMPTION, + now.plus(registry.getRedemptionGracePeriodLength()), + getClientId(), + null))) + .setDeletePollMessage(Key.create(deletePollMessage)); + } + } + + @Override + protected final void enqueueTasks() { + DnsQueue.create().addDomainRefreshTask(existingResource.getFullyQualifiedDomainName()); + } + + @Override + protected final void modifySyncDeleteRelatedResources() { + // Cancel any grace periods that were still active. + ImmutableList.Builder creditsBuilder = new ImmutableList.Builder<>(); + for (GracePeriod gracePeriod : existingResource.getGracePeriods()) { + // No cancellation is written if the grace period was not for a billable event. + if (gracePeriod.getBillingEvent() != null) { + ofy().save().entity( + BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId)); + + Money cost; + if (gracePeriod.getType() == GracePeriodStatus.AUTO_RENEW) { + TimeOfYear recurrenceTimeOfYear = + checkNotNull(gracePeriod.getRecurringBillingEvent()).get().getRecurrenceTimeOfYear(); + DateTime autoRenewTime = recurrenceTimeOfYear.beforeOrAt(now); + cost = Registry.get(existingResource.getTld()) + .getDomainRenewCost(targetId, 1, autoRenewTime); + } else { + cost = checkNotNull(gracePeriod.getOneTimeBillingEvent()).get().getCost(); + } + creditsBuilder.add(Credit.create( + cost.negated().getAmount(), + String.format("%s credit", gracePeriod.getType().getXmlName()))); + creditsCurrencyUnit = cost.getCurrencyUnit(); + } + } + credits = creditsBuilder.build(); + + // If the delete isn't immediate, save the poll message for when the delete will happen. + if (deletePollMessage != null) { + ofy().save().entity(deletePollMessage); + } + // Close the autorenew billing event and poll message. This may delete the poll message. + updateAutorenewRecurrenceEndTime(existingResource, now); + + // If there's a pending transfer, the gaining client's autorenew billing + // event and poll message will already have been deleted in + // ResourceDeleteFlow since it's listed in serverApproveEntities. + } + + @Override + protected final Code getDeleteResultCode() { + return newResource.getDeletionTime().isAfter(now) + ? SuccessWithActionPending : Success; + } + + @Override + protected final ImmutableList getDeleteResponseExtensions() { + if (!credits.isEmpty() + && nullToEmpty(sessionMetadata.getServiceExtensionUris()).contains( + ServiceExtension.FEE_0_6.getUri())) { + return ImmutableList.of(new FeeDeleteResponseExtension.Builder() + .setCurrency(checkNotNull(creditsCurrencyUnit)) + .setCredits(credits) + .build()); + } else { + return null; + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_DELETE; + } + + /** Domain to be deleted has subordinate hosts. */ + static class DomainToDeleteHasHostsException extends AssociationProhibitsOperationException { + public DomainToDeleteHasHostsException() { + super("Domain to be deleted has subordinate hosts"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainFlowUtils.java b/java/com/google/domain/registry/flows/domain/DomainFlowUtils.java new file mode 100644 index 000000000..58ce91ddb --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainFlowUtils.java @@ -0,0 +1,966 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.collect.Iterables.any; +import static com.google.common.collect.Iterables.concat; +import static com.google.domain.registry.flows.EppXmlTransformer.unmarshal; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.findTldForName; +import static com.google.domain.registry.model.registry.label.ReservedList.getReservation; +import static com.google.domain.registry.tldconfig.idn.IdnLabelValidator.findValidIdnTableForTld; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; +import static com.google.domain.registry.util.DomainNameUtils.ACE_PREFIX; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.flows.EppException.UnimplementedOptionException; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.domain.DesignatedContact.Type; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainCommand.CreateOrUpdate; +import com.google.domain.registry.model.domain.DomainCommand.InvalidReferenceException; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.domain.fee.BaseFeeCommand; +import com.google.domain.registry.model.domain.fee.BaseFeeRequest; +import com.google.domain.registry.model.domain.fee.BaseFeeResponse; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeCommandDescriptor; +import com.google.domain.registry.model.domain.launch.LaunchExtension; +import com.google.domain.registry.model.domain.launch.LaunchPhase; +import com.google.domain.registry.model.domain.secdns.DelegationSignerData; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.mark.Mark; +import com.google.domain.registry.model.mark.ProtectedMark; +import com.google.domain.registry.model.mark.Trademark; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.registry.label.ReservationType; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.smd.AbstractSignedMark; +import com.google.domain.registry.model.smd.EncodedSignedMark; +import com.google.domain.registry.model.smd.SignedMark; +import com.google.domain.registry.model.smd.SignedMarkRevocationList; +import com.google.domain.registry.tmch.TmchXmlSignature; +import com.google.domain.registry.tmch.TmchXmlSignature.CertificateSignatureException; +import com.google.domain.registry.util.Idn; + +import com.googlecode.objectify.Key; + +import org.joda.money.Money; +import org.joda.time.DateTime; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.math.BigDecimal; +import java.security.GeneralSecurityException; +import java.security.SignatureException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.CertificateRevokedException; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.parsers.ParserConfigurationException; + +/** Static utility functions for domain flows. */ +public class DomainFlowUtils { + + /** Map from launch phases to the equivalent tld states. */ + private static final ImmutableMap LAUNCH_PHASE_TO_TLD_STATE = + ImmutableMap.of( + LaunchPhase.SUNRISE, TldState.SUNRISE, + LaunchPhase.SUNRUSH, TldState.SUNRUSH, + LaunchPhase.LANDRUSH, TldState.LANDRUSH, + LaunchPhase.CLAIMS, TldState.GENERAL_AVAILABILITY, + LaunchPhase.OPEN, TldState.GENERAL_AVAILABILITY); + + /** Non-sunrise tld states. */ + public static final ImmutableSet DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS = + Sets.immutableEnumSet( + TldState.PREDELEGATION, + TldState.QUIET_PERIOD, + TldState.GENERAL_AVAILABILITY); + + /** Reservation types that are allowed in sunrise by policy. */ + public static final ImmutableSet TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE = + Sets.immutableEnumSet( + ReservationType.ALLOWED_IN_SUNRISE, + ReservationType.NAME_COLLISION, + ReservationType.MISTAKEN_PREMIUM); + + /** Strict validator for ascii lowercase letters, digits, and "-", allowing "." as a separator */ + private static final CharMatcher ALLOWED_CHARS = + CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('0', '9').or(CharMatcher.anyOf("-."))); + + /** The maximum number of DS records allowed on a domain. */ + private static final int MAX_DS_RECORDS_PER_DOMAIN = 8; + + /** Maximum number of nameservers allowed per domain. */ + private static final int MAX_NAMESERVERS_PER_DOMAIN = 13; + + /** Maximum number of characters in a domain label, from RFC 2181. */ + private static final int MAX_LABEL_SIZE = 63; + + /** + * Returns parsed version of {@code name} if domain name label follows our naming rules and is + * under one of the given allowed TLDs. + * + *

Note: This method does not perform language validation with IDN tables. + * + * @see #validateDomainNameWithIdnTables(InternetDomainName) + */ + static InternetDomainName validateDomainName(String name) + throws EppException { + if (!ALLOWED_CHARS.matchesAllOf(name)) { + throw new BadDomainNameCharacterException(); + } + List parts = Splitter.on('.').splitToList(name); + if (parts.size() <= 1) { + throw new BadDomainNamePartsCountException(); + } + if (any(parts, equalTo(""))) { + throw new EmptyDomainNamePartException(); + } + validateFirstLabel(parts.get(0)); + InternetDomainName domainName = InternetDomainName.from(name); + Optional tldParsed = findTldForName(domainName); + if (!tldParsed.isPresent()) { + throw new TldDoesNotExistException(domainName.parent().toString()); + } + if (domainName.parts().size() != tldParsed.get().parts().size() + 1) { + throw new BadDomainNamePartsCountException(); + } + return domainName; + } + + private static void validateFirstLabel(String firstLabel) throws EppException { + if (firstLabel.length() > MAX_LABEL_SIZE) { + throw new DomainLabelTooLongException(); + } + if (firstLabel.startsWith("-")) { + throw new LeadingDashException(); + } + if (firstLabel.endsWith("-")) { + throw new TrailingDashException(); + } + String unicode = Idn.toUnicode(firstLabel); + if (firstLabel.startsWith(ACE_PREFIX) && firstLabel.equals(unicode)) { + throw new InvalidPunycodeException(); + } + if (!firstLabel.startsWith(ACE_PREFIX) + && firstLabel.length() >= 4 + && firstLabel.substring(2).startsWith("--")) { + throw new DashesInThirdAndFourthException(); + } + } + + /** + * Returns name of first matching IDN table for domain label. + * + * @throws InvalidIdnDomainLabelException if IDN table or language validation failed + * @see #validateDomainName(String) + */ + static String validateDomainNameWithIdnTables(InternetDomainName domainName) + throws InvalidIdnDomainLabelException { + Optional idnTableName = + findValidIdnTableForTld(domainName.parts().get(0), domainName.parent().toString()); + if (!idnTableName.isPresent()) { + throw new InvalidIdnDomainLabelException(); + } + return idnTableName.get(); + } + + /** Check if the registrar running the flow has access to the TLD in question. */ + public static void checkAllowedAccessToTld(Set allowedTlds, String tld) + throws EppException { + if (!allowedTlds.contains(tld)) { + throw new DomainFlowUtils.NotAuthorizedForTldException(tld); + } + } + + /** Check that the DS data that will be set on a domain is valid. */ + static void validateDsData(Set dsData) throws EppException { + if (dsData != null && dsData.size() > MAX_DS_RECORDS_PER_DOMAIN) { + throw new TooManyDsRecordsException(String.format( + "A maximum of %s DS records are allowed per domain.", MAX_DS_RECORDS_PER_DOMAIN)); + } + } + + /** We only allow specifying years in a period. */ + static Period verifyUnitIsYears(Period period) throws EppException { + if (!checkNotNull(period).getUnit().equals(Period.Unit.YEARS)) { + throw new BadPeriodUnitException(); + } + return period; + } + + /** Verify that no linked resources have disallowed statuses. */ + static void verifyNotInPendingDelete( + Set contacts, + ReferenceUnion registrant, + Set> nameservers) throws EppException { + for (DesignatedContact contact : nullToEmpty(contacts)) { + verifyNotInPendingDelete(contact.getContactId()); + } + if (registrant != null) { + verifyNotInPendingDelete(registrant); + } + for (ReferenceUnion host : nullToEmpty(nameservers)) { + verifyNotInPendingDelete(host); + } + } + + private static void verifyNotInPendingDelete( + ReferenceUnion resourceRef) throws EppException { + EppResource resource = resourceRef.getLinked().get(); + if (resource.getStatusValues().contains(StatusValue.PENDING_DELETE)) { + throw new LinkedResourceInPendingDeleteProhibitsOperationException(resource.getForeignKey()); + } + } + + static void validateContactsHaveTypes(Set contacts) + throws ParameterValuePolicyErrorException { + for (DesignatedContact contact : nullToEmpty(contacts)) { + if (contact.getType() == null) { + throw new MissingContactTypeException(); + } + } + } + + static void validateNameservers(Set> nameservers) + throws EppException { + if (nameservers != null && nameservers.size() > MAX_NAMESERVERS_PER_DOMAIN) { + throw new TooManyNameserversException(String.format( + "Only %d nameservers are allowed per domain", MAX_NAMESERVERS_PER_DOMAIN)); + } + } + + static void validateNoDuplicateContacts(Set contacts) + throws ParameterValuePolicyErrorException { + Set roles = new HashSet<>(); + for (DesignatedContact contact : nullToEmpty(contacts)) { + if (!roles.add(contact.getType())) { + throw new DuplicateContactForRoleException(); + } + } + } + + static void validateRequiredContactsPresent( + ReferenceUnion registrant, Set contacts) + throws RequiredParameterMissingException { + if (registrant == null) { + throw new MissingRegistrantException(); + } + + Set roles = new HashSet<>(); + for (DesignatedContact contact : nullToEmpty(contacts)) { + roles.add(contact.getType()); + } + if (!roles.contains(Type.ADMIN)) { + throw new MissingAdminContactException(); + } + if (!roles.contains(Type.TECH)) { + throw new MissingTechnicalContactException(); + } + } + + static void verifyNotReserved( + InternetDomainName domainName, boolean isSunriseApplication) throws EppException { + if (isReserved(domainName, isSunriseApplication)) { + throw new DomainReservedException(domainName.toString()); + } + } + + private static boolean isReserved(InternetDomainName domainName, boolean inSunrise) { + ReservationType type = getReservationType(domainName); + return type == ReservationType.FULLY_BLOCKED + || type == ReservationType.RESERVED_FOR_ANCHOR_TENANT + || (TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE.contains(type) && !inSunrise); + } + + /** Returns an enum that encodes how and when this name is reserved in the current tld. */ + static ReservationType getReservationType(InternetDomainName domainName) { + // The TLD should always be the parent of the requested domain name. + return getReservation(domainName.parts().get(0), domainName.parent().toString()); + } + + /** Verifies that a launch extension's specified phase matches the specified registry's phase. */ + static void verifyLaunchPhase( + String tld, LaunchExtension launchExtension, DateTime now) throws EppException { + if (!Objects.equals( + Registry.get(tld).getTldState(now), + LAUNCH_PHASE_TO_TLD_STATE.get(launchExtension.getPhase()))) { + // No launch operations are allowed during the quiet period or predelegation. + throw new LaunchPhaseMismatchException(); + } + } + + /** + * Verifies that a launch extension's application id refers to an application with the same + * domain name as the one specified in the launch command. + */ + static void verifyLaunchApplicationIdMatchesDomain( + SingleResourceCommand command, DomainBase existingResource) throws EppException { + if (!Objects.equals(command.getTargetId(), existingResource.getFullyQualifiedDomainName())) { + throw new ApplicationDomainNameMismatchException(); + } + } + + /** + * Verifies that a domain name is allowed to be delegated to the given client id. The only case + * where it would not be allowed is if domain name is premium, and premium names are blocked by + * this registrar. + */ + static void verifyPremiumNameIsNotBlocked(String domainName, String tld, String clientId) + throws EppException { + if (Registry.get(tld).isPremiumName(domainName)) { + // NB: The load of the Registar object is transactionless, which means that it should hit + // memcache most of the time. + if (Registrar.loadByClientId(clientId).getBlockPremiumNames()) { + throw new PremiumNameBlockedException(); + } + } + } + + /** + * Helper to call {@link CreateOrUpdate#cloneAndLinkReferences} and convert exceptions to + * EppExceptions, since this is needed in several places. + */ + static > T cloneAndLinkReferences(T command, DateTime now) + throws EppException { + try { + return command.cloneAndLinkReferences(now); + } catch (InvalidReferenceException e) { + throw new LinkedResourceDoesNotExistException(e.getType(), e.getForeignKey()); + } + } + + /** + * Fills in a builder with the data needed for an autorenew billing event for this domain. This + * does not copy over the id of the current autorenew billing event. + */ + static BillingEvent.Recurring.Builder newAutorenewBillingEvent(DomainResource domain) { + return new BillingEvent.Recurring.Builder() + .setReason(Reason.AUTO_RENEW) + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setEventTime(domain.getRegistrationExpirationTime()); + } + + /** + * Fills in a builder with the data needed for an autorenew poll message for this domain. This + * does not copy over the id of the current autorenew poll message. + */ + static PollMessage.Autorenew.Builder newAutorenewPollMessage(DomainResource domain) { + return new PollMessage.Autorenew.Builder() + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setEventTime(domain.getRegistrationExpirationTime()) + .setMsg("Domain was auto-renewed."); + } + + /** + * Re-saves the current autorenew billing event and poll message with a new end time. This may end + * up deleting the poll message (if closing the message interval) or recreating it (if opening the + * message interval). + */ + @SuppressWarnings("unchecked") + static void updateAutorenewRecurrenceEndTime(DomainResource domain, DateTime newEndTime) { + Optional autorenewPollMessage = + Optional.fromNullable(domain.getAutorenewPollMessage().get()); + + // Construct an updated autorenew poll message. If the autorenew poll message no longer exists, + // create a new one at the same id. This can happen if a transfer was requested on a domain + // where all autorenew poll messages had already been delivered (this would cause the poll + // message to be deleted), and then subsequently the transfer was canceled, rejected, or deleted + // (which would cause the poll message to be recreated here). + Key existingAutorenewKey = domain.getAutorenewPollMessage().key(); + PollMessage.Autorenew updatedAutorenewPollMessage = autorenewPollMessage.isPresent() + ? autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build() + : newAutorenewPollMessage(domain) + .setId(existingAutorenewKey.getId()) + .setAutorenewEndTime(newEndTime) + .setParentKey(existingAutorenewKey.getParent()) + .build(); + + // If the resultant autorenew poll message would have no poll messages to deliver, then just + // delete it. Otherwise save it with the new end time. + if (isAtOrAfter(updatedAutorenewPollMessage.getEventTime(), newEndTime)) { + if (autorenewPollMessage.isPresent()) { + ofy().delete().entity(autorenewPollMessage.get()); + } + } else { + ofy().save().entity(updatedAutorenewPollMessage); + } + + ofy().save().entity(domain.getAutorenewBillingEvent().get().asBuilder() + .setRecurrenceEndTime(newEndTime) + .build()); + } + + public static SignedMark verifySignedMarks( + ImmutableList signedMarks, String domainLabel, DateTime now) + throws EppException { + if (signedMarks.size() > 1) { + throw new TooManySignedMarksException(); + } + if (!(signedMarks.get(0) instanceof EncodedSignedMark)) { + throw new SignedMarksMustBeEncodedException(); + } + return verifyEncodedSignedMark((EncodedSignedMark) signedMarks.get(0), domainLabel, now); + } + + public static SignedMark verifyEncodedSignedMark( + EncodedSignedMark encodedSignedMark, String domainLabel, DateTime now) throws EppException { + if (!encodedSignedMark.getEncoding().equals("base64")) { + throw new Base64RequiredForEncodedSignedMarksException(); + } + byte[] signedMarkData; + try { + signedMarkData = encodedSignedMark.getBytes(); + } catch (IllegalStateException e) { + throw new SignedMarkEncodingErrorException(); + } + + SignedMark signedMark; + try { + signedMark = unmarshal(signedMarkData); + } catch (EppException e) { + throw new SignedMarkParsingErrorException(); + } + + if (SignedMarkRevocationList.get().isSmdRevoked(signedMark.getId(), now)) { + throw new SignedMarkRevokedErrorException(); + } + + try { + TmchXmlSignature.verify(signedMarkData); + } catch (CertificateExpiredException e) { + throw new SignedMarkCertificateExpiredException(); + } catch (CertificateNotYetValidException e) { + throw new SignedMarkCertificateNotYetValidException(); + } catch (CertificateRevokedException e) { + throw new SignedMarkCertificateRevokedException(); + } catch (CertificateSignatureException e) { + throw new SignedMarkCertificateSignatureException(); + } catch (SignatureException | XMLSignatureException e) { + throw new SignedMarkSignatureException(); + } catch (GeneralSecurityException e) { + throw new SignedMarkCertificateInvalidException(); + } catch (IOException + | MarshalException + | SAXException + | ParserConfigurationException e) { + throw new SignedMarkParsingErrorException(); + } + + if (!(isAtOrAfter(now, signedMark.getCreationTime()) + && now.isBefore(signedMark.getExpirationTime()) + && containsMatchingLabel(signedMark.getMark(), domainLabel))) { + throw new NoMarksFoundMatchingDomainException(); + } + return signedMark; + } + + /** Returns true if the mark contains a valid claim that matches the label. */ + static boolean containsMatchingLabel(Mark mark, String label) { + for (Trademark trademark : mark.getTrademarks()) { + if (trademark.getLabels().contains(label)) { + return true; + } + } + for (ProtectedMark protectedMark + : concat(mark.getTreatyOrStatuteMarks(), mark.getCourtMarks())) { + if (protectedMark.getLabels().contains(label)) { + return true; + } + } + return false; + } + + /** + * Validates a {@link BaseFeeRequest} and sets the appropriate fields on a {@link BaseFeeResponse} + * builder. + */ + static void handleFeeRequest( + BaseFeeRequest feeRequest, + BaseFeeResponse.Builder builder, + String domainName, + String tld, + DateTime now) throws EppException { + InternetDomainName domain = InternetDomainName.from(domainName); + FeeCommandDescriptor feeCommand = feeRequest.getCommand(); + Registry registry = Registry.get(tld); + int years = verifyUnitIsYears(feeRequest.getPeriod()).getValue(); + boolean isSunrise = registry.getTldState(now).equals(TldState.SUNRISE); + boolean isNameCollisionInSunrise = + isSunrise && getReservationType(domain) == ReservationType.NAME_COLLISION; + + if (feeCommand.getPhase() != null || feeCommand.getSubphase() != null) { + throw new FeeChecksDontSupportPhasesException(); + } + if (feeRequest.getCurrency() != null + && !feeRequest.getCurrency().equals(registry.getCurrency())) { + throw new CurrencyUnitMismatchException(); + } + + builder + .setCommand(feeCommand) + .setCurrency(registry.getCurrency()) + .setPeriod(feeRequest.getPeriod()) + // Choose from four classes: premium, premium-collision, collision, or null (standard case). + .setClass(emptyToNull(Joiner.on('-').skipNulls().join( + registry.isPremiumName(domainName) ? "premium" : null, + isNameCollisionInSunrise ? "collision" : null))); + + switch (feeCommand.getCommand()) { + case UNKNOWN: + throw new UnknownFeeCommandException(feeCommand.getUnparsedCommandName()); + case CREATE: + if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names. + builder.setClass("reserved"); // Override whatever class we've set above. + } else { + builder.setFee( + Fee.create(registry.getDomainCreateCost(domainName, years).getAmount(), "create")); + } + break; + case RESTORE: + if (years != 1) { + throw new RestoresAreAlwaysForOneYearException(); + } + // Restores have a "renew" and a "restore" fee. + builder.setFee( + Fee.create(registry.getDomainRenewCost(domainName, years, now).getAmount(), "renew"), + Fee.create(registry.getStandardRestoreCost().getAmount(), "restore")); + break; + default: + // Anything else (transfer|renew) will have a "renew" fee. + builder.setFee( + Fee.create(registry.getDomainRenewCost(domainName, years, now).getAmount(), "renew")); + } + } + + static void validateFeeChallenge( + String domainName, String tld, + final BaseFeeCommand feeCommand, + Money cost, Money... otherCosts) throws EppException { + Registry registry = Registry.get(tld); + if (registry.getPremiumPriceAckRequired() + && registry.isPremiumName(domainName) + && feeCommand == null) { + throw new FeesRequiredForPremiumNameException(); + } + if (feeCommand == null) { + return; + } + List fees = feeCommand.getFees(); + // The schema guarantees that at least one fee will be present. + checkState(!fees.isEmpty()); + BigDecimal total = BigDecimal.ZERO; + for (Fee fee : fees) { + if (!fee.hasDefaultAttributes()) { + throw new UnsupportedFeeAttributeException(); + } + total = total.add(fee.getCost()); + } + + Money feeTotal = null; + try { + feeTotal = Money.of(feeCommand.getCurrency(), total); + } catch (ArithmeticException e) { + throw new CurrencyValueScaleException(); + } + + Money costTotal = cost; + for (Money otherCost : otherCosts) { + costTotal = costTotal.plus(otherCost); + } + + if (!feeTotal.getCurrencyUnit().equals(costTotal.getCurrencyUnit())) { + throw new CurrencyUnitMismatchException(); + } + if (!feeTotal.equals(costTotal)) { + throw new FeesMismatchException(); + } + } + + /** Encoded signed marks must use base64 encoding. */ + static class Base64RequiredForEncodedSignedMarksException + extends ParameterValuePolicyErrorException { + public Base64RequiredForEncodedSignedMarksException() { + super("Encoded signed marks must use base64 encoding"); + } + } + + /** Resource linked to this domain does not exist. */ + static class LinkedResourceDoesNotExistException extends ObjectDoesNotExistException { + public LinkedResourceDoesNotExistException(Class type, String resourceId) { + super(type, resourceId); + } + } + + /** Linked resource in pending delete prohibits operation. */ + static class LinkedResourceInPendingDeleteProhibitsOperationException + extends StatusProhibitsOperationException { + public LinkedResourceInPendingDeleteProhibitsOperationException(String resourceId) { + super(String.format( + "Linked resource in pending delete prohibits operation: %s", + resourceId)); + } + } + + /** Domain names can only contain a-z, 0-9, '.' and '-'. */ + static class BadDomainNameCharacterException extends ParameterValuePolicyErrorException { + public BadDomainNameCharacterException() { + super("Domain names can only contain a-z, 0-9, '.' and '-'"); + } + } + + /** Non-IDN domain names cannot contain hyphens in the third or fourth position. */ + static class DashesInThirdAndFourthException extends ParameterValuePolicyErrorException { + public DashesInThirdAndFourthException() { + super("Non-IDN domain names cannot contain dashes in the third or fourth position"); + } + } + + /** Domain labels cannot begin with a dash. */ + static class LeadingDashException extends ParameterValuePolicyErrorException { + public LeadingDashException() { + super("Domain labels cannot begin with a dash"); + } + } + + /** Domain labels cannot end with a dash. */ + static class TrailingDashException extends ParameterValuePolicyErrorException { + public TrailingDashException() { + super("Domain labels cannot end with a dash"); + } + } + + /** Domain labels cannot be longer than 63 characters. */ + static class DomainLabelTooLongException extends ParameterValuePolicyErrorException { + public DomainLabelTooLongException() { + super("Domain labels cannot be longer than 63 characters"); + } + } + + /** No part of a domain name can be empty. */ + static class EmptyDomainNamePartException extends ParameterValuePolicyErrorException { + public EmptyDomainNamePartException() { + super("No part of a domain name can be empty"); + } + } + + /** Domain name starts with xn-- but is not a valid IDN. */ + static class InvalidPunycodeException extends ParameterValuePolicyErrorException { + public InvalidPunycodeException() { + super("Domain name starts with xn-- but is not a valid IDN"); + } + } + + /** Periods for domain registrations must be specified in years. */ + static class BadPeriodUnitException extends ParameterValuePolicyErrorException { + public BadPeriodUnitException() { + super("Periods for domain registrations must be specified in years"); + } + } + + /** Missing type attribute for contact. */ + static class MissingContactTypeException extends ParameterValuePolicyErrorException { + public MissingContactTypeException() { + super("Missing type attribute for contact"); + } + } + + /** More than one contact for a given role is not allowed. */ + static class DuplicateContactForRoleException extends ParameterValuePolicyErrorException { + public DuplicateContactForRoleException() { + super("More than one contact for a given role is not allowed"); + } + } + + /** Declared launch extension phase does not match the current registry phase. */ + static class LaunchPhaseMismatchException extends ParameterValuePolicyErrorException { + public LaunchPhaseMismatchException() { + super("Declared launch extension phase does not match the current registry phase"); + } + } + + /** Application referenced does not match specified domain name. */ + static class ApplicationDomainNameMismatchException extends ParameterValuePolicyErrorException { + public ApplicationDomainNameMismatchException() { + super("Application referenced does not match specified domain name"); + } + } + + /** Too many DS records set on a domain. */ + static class TooManyDsRecordsException extends ParameterValuePolicyErrorException { + public TooManyDsRecordsException(String message) { + super(message); + } + } + + /** Domain name is under tld which doesn't exist. */ + static class TldDoesNotExistException extends ParameterValueRangeErrorException { + public TldDoesNotExistException(String tld) { + super(String.format("Domain name is under tld %s which doesn't exist", tld)); + } + } + + /** Domain label is not allowed by IDN table. */ + static class InvalidIdnDomainLabelException extends ParameterValueRangeErrorException { + public InvalidIdnDomainLabelException() { + super("Domain label is not allowed by IDN table"); + } + } + + /** Registrant is required. */ + static class MissingRegistrantException extends RequiredParameterMissingException { + public MissingRegistrantException() { + super("Registrant is required"); + } + } + + /** Admin contact is required. */ + static class MissingAdminContactException extends RequiredParameterMissingException { + public MissingAdminContactException() { + super("Admin contact is required"); + } + } + + /** Technical contact is required. */ + static class MissingTechnicalContactException extends RequiredParameterMissingException { + public MissingTechnicalContactException() { + super("Technical contact is required"); + } + } + + /** Too many nameservers set on this domain. */ + static class TooManyNameserversException extends ParameterValuePolicyErrorException { + public TooManyNameserversException(String message) { + super(message); + } + } + + /** Domain name must have exactly one part above the tld. */ + static class BadDomainNamePartsCountException extends ParameterValueSyntaxErrorException { + public BadDomainNamePartsCountException() { + super("Domain name must have exactly one part above the tld"); + } + } + + /** Signed mark data is improperly encoded. */ + static class SignedMarkEncodingErrorException extends ParameterValueSyntaxErrorException { + public SignedMarkEncodingErrorException() { + super("Signed mark data is improperly encoded"); + } + } + + /** Error while parsing encoded signed mark data. */ + static class SignedMarkParsingErrorException extends ParameterValueSyntaxErrorException { + public SignedMarkParsingErrorException() { + super("Error while parsing encoded signed mark data"); + } + } + + /** Invalid signature on a signed mark. */ + static class SignedMarkSignatureException extends ParameterValuePolicyErrorException { + public SignedMarkSignatureException() { + super("Signed mark signature is invalid"); + } + } + + /** Invalid signature on a signed mark. */ + static class SignedMarkCertificateSignatureException extends ParameterValuePolicyErrorException { + public SignedMarkCertificateSignatureException() { + super("Signed mark certificate not signed by ICANN"); + } + } + + /** Certificate used in signed mark signature was revoked by ICANN. */ + static class SignedMarkCertificateRevokedException extends ParameterValuePolicyErrorException { + public SignedMarkCertificateRevokedException() { + super("Signed mark certificate was revoked"); + } + } + + /** Certificate used in signed mark signature has expired. */ + static class SignedMarkCertificateExpiredException extends ParameterValuePolicyErrorException { + public SignedMarkCertificateExpiredException() { + super("Signed mark certificate has expired"); + } + } + + /** Certificate used in signed mark signature has expired. */ + static class SignedMarkCertificateNotYetValidException + extends ParameterValuePolicyErrorException { + public SignedMarkCertificateNotYetValidException() { + super("Signed mark certificate not yet valid"); + } + } + + /** Certificate parsing error, or possibly a bad provider or algorithm. */ + static class SignedMarkCertificateInvalidException extends ParameterValuePolicyErrorException { + public SignedMarkCertificateInvalidException() { + super("Signed mark certificate is invalid"); + } + } + + /** Signed mark data is revoked. */ + static class SignedMarkRevokedErrorException extends ParameterValuePolicyErrorException { + public SignedMarkRevokedErrorException() { + super("SMD has been revoked"); + } + } + + /** Only one signed mark is allowed per application. */ + static class TooManySignedMarksException extends ParameterValuePolicyErrorException { + public TooManySignedMarksException() { + super("Only one signed mark is allowed per application"); + } + } + + /** Signed marks must be encoded. */ + static class SignedMarksMustBeEncodedException extends ParameterValuePolicyErrorException { + public SignedMarksMustBeEncodedException() { + super("Signed marks must be encoded"); + } + } + + /** The provided mark does not match the desired domain label. */ + static class NoMarksFoundMatchingDomainException extends RequiredParameterMissingException { + public NoMarksFoundMatchingDomainException() { + super("The provided mark does not match the desired domain label"); + } + } + + /** Unknown fee command name. */ + static class UnknownFeeCommandException extends ParameterValuePolicyErrorException { + UnknownFeeCommandException(String commandName) { + super("Unknown fee command: " + commandName); + } + } + + /** Fee checks for command phases and subphases are not supported. */ + static class FeeChecksDontSupportPhasesException extends ParameterValuePolicyErrorException { + FeeChecksDontSupportPhasesException() { + super("Fee checks for command phases and subphases are not supported"); + } + } + + /** The requested fees cannot be provided in the requested currency. */ + static class CurrencyUnitMismatchException extends ParameterValuePolicyErrorException { + CurrencyUnitMismatchException() { + super("The requested fees cannot be provided in the requested currency"); + } + } + + /** The requested fee is expressed in a scale that is invalid for the given currency. */ + static class CurrencyValueScaleException extends ParameterValueSyntaxErrorException { + CurrencyValueScaleException() { + super("The requested fee is expressed in a scale that is invalid for the given currency"); + } + } + + /** Fees must be explicitly acknowledged when performing any operations on a premium name. */ + static class FeesRequiredForPremiumNameException extends RequiredParameterMissingException { + FeesRequiredForPremiumNameException() { + super("Fees must be explicitly acknowledged when performing any operations on a premium" + + " name"); + } + } + + /** The 'grace-period', 'applied' and 'refundable' fields are disallowed by server policy. */ + static class UnsupportedFeeAttributeException extends UnimplementedOptionException { + UnsupportedFeeAttributeException() { + super("The 'grace-period', 'refundable' and 'applied' attributes are disallowed by server " + + "policy"); + } + } + + /** Restores always renew a domain for one year. */ + static class RestoresAreAlwaysForOneYearException extends ParameterValuePolicyErrorException { + RestoresAreAlwaysForOneYearException() { + super("Restores always renew a domain for one year"); + } + } + + /** Requested domain is reserved. */ + static class DomainReservedException extends StatusProhibitsOperationException { + public DomainReservedException(String domainName) { + super(String.format("%s is a reserved domain", domainName)); + } + } + + /** + * The requested domain name is on the premium price list, and this registrar has blocked premium + * registrations. + */ + static class PremiumNameBlockedException extends StatusProhibitsOperationException { + public PremiumNameBlockedException() { + super("The requested domain name is on the premium price list, " + + "and this registrar has blocked premium registrations"); + } + } + + /** The fees passed in the transform command do not match the fees that will be charged. */ + static class FeesMismatchException extends ParameterValueRangeErrorException { + public FeesMismatchException() { + super("The fees passed in the transform command do not match the fees that will be charged"); + } + } + + /** Registrar is not authorized to access this TLD. */ + public static class NotAuthorizedForTldException extends AuthorizationErrorException { + public NotAuthorizedForTldException(String tld) { + super("Registrar is not authorized to access the TLD " + tld); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainInfoFlow.java b/java/com/google/domain/registry/flows/domain/DomainInfoFlow.java new file mode 100644 index 000000000..191eba5da --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainInfoFlow.java @@ -0,0 +1,94 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.handleFeeRequest; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.fee.FeeInfoExtension; +import com.google.domain.registry.model.domain.fee.FeeInfoResponseExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.rgp.RgpInfoExtension; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +/** + * An EPP flow that reads a domain. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.FeeChecksDontSupportPhasesException} + * @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException} + */ +public class DomainInfoFlow extends BaseDomainInfoFlow { + + @Override + protected void initSingleResourceFlow() throws EppException { + registerExtensions(FeeInfoExtension.class); + } + + @Override + protected final DomainResource getResourceInfo() { + // If authInfo is non-null, then the caller is authorized to see the full information since we + // will have already verified the authInfo is valid in ResourceQueryFlow.verifyIsAllowed(). + if (!getClientId().equals(existingResource.getCurrentSponsorClientId()) + && command.getAuthInfo() == null) { + // Registrars can only see a few fields on unauthorized domains. + // This is a policy decision that is left up to us by the rfcs. + return new DomainResource.Builder() + .setFullyQualifiedDomainName(existingResource.getFullyQualifiedDomainName()) + .setRepoId(existingResource.getRepoId()) + .setCurrentSponsorClientId(existingResource.getCurrentSponsorClientId()) + // If we didn't do this, we'd get implicit status values. + .buildWithoutImplicitStatusValues(); + } + Builder info = existingResource.asBuilder(); + if (!command.getHostsRequest().requestSubordinate()) { + info.setSubordinateHosts(null); + } + if (!command.getHostsRequest().requestDelegated()) { + // Delegated hosts are present by default, so clear them out if they aren't wanted. + // This requires overriding the implicit status values so that we don't get INACTIVE added due + // to the missing nameservers. + return info.setNameservers(null).buildWithoutImplicitStatusValues(); + } + return info.build(); + } + + @Override + protected final ImmutableList getDomainResponseExtensions() + throws EppException { + ImmutableList.Builder extensions = new ImmutableList.Builder<>(); + // According to RFC 5910 section 2, we should only return this if the client specified the + // "urn:ietf:params:xml:ns:rgp-1.0" when logging in. However, this is a "SHOULD" not a "MUST" + // and we are going to ignore it; clients who don't care about rgp can just ignore it. + ImmutableSet gracePeriodStatuses = existingResource.getGracePeriodStatuses(); + if (!gracePeriodStatuses.isEmpty()) { + extensions.add(RgpInfoExtension.create(gracePeriodStatuses)); + } + FeeInfoExtension feeInfo = eppInput.getSingleExtension(FeeInfoExtension.class); + if (feeInfo != null) { // Fee check was requested. + FeeInfoResponseExtension.Builder builder = new FeeInfoResponseExtension.Builder(); + handleFeeRequest(feeInfo, builder, getTargetId(), existingResource.getTld(), now); + extensions.add(builder.build()); + } + return extensions.build(); + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainRenewFlow.java b/java/com/google/domain/registry/flows/domain/DomainRenewFlow.java new file mode 100644 index 000000000..d242ba296 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainRenewFlow.java @@ -0,0 +1,206 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.newAutorenewBillingEvent; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessage; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; +import static com.google.domain.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.leapSafeAddYears; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ObjectPendingTransferException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.OwnedResourceMutateFlow; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainCommand.Renew; +import com.google.domain.registry.model.domain.DomainRenewData; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeRenewExtension; +import com.google.domain.registry.model.domain.fee.FeeRenewResponseExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferStatus; + +import com.googlecode.objectify.Ref; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.Set; + +/** + * An EPP flow that updates a domain resource. + * + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.CurrencyValueScaleException} + * @error {@link DomainFlowUtils.FeesMismatchException} + * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} + * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + * @error {@link DomainRenewFlow.DomainHasPendingTransferException} + * @error {@link DomainRenewFlow.ExceedsMaxRegistrationYearsException} + * @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException} + */ +public class DomainRenewFlow extends OwnedResourceMutateFlow { + + private static final Set RENEW_DISALLOWED_STATUSES = ImmutableSet.of( + StatusValue.CLIENT_RENEW_PROHIBITED, + StatusValue.PENDING_DELETE, + StatusValue.SERVER_RENEW_PROHIBITED); + + protected FeeRenewExtension feeRenew; + protected Money renewCost; + + @Override + protected Set getDisallowedStatuses() { + return RENEW_DISALLOWED_STATUSES; + } + + @Override + public final void initResourceCreateOrMutateFlow() throws EppException { + registerExtensions(FeeRenewExtension.class); + feeRenew = eppInput.getSingleExtension(FeeRenewExtension.class); + } + + @Override + protected void verifyMutationOnOwnedResourceAllowed() throws EppException { + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + // Verify that the resource does not have a pending transfer on it. + if (existingResource.getTransferData().getTransferStatus() == TransferStatus.PENDING) { + throw new DomainHasPendingTransferException(targetId); + } + verifyUnitIsYears(command.getPeriod()); + // If the date they specify doesn't match the expiration, fail. (This is an idempotence check). + if (!command.getCurrentExpirationDate().equals( + existingResource.getRegistrationExpirationTime().toLocalDate())) { + throw new IncorrectCurrentExpirationDateException(); + } + renewCost = Registry.get(existingResource.getTld()) + .getDomainRenewCost(targetId, command.getPeriod().getValue(), now); + validateFeeChallenge(targetId, existingResource.getTld(), feeRenew, renewCost); + } + + @Override + protected DomainResource createOrMutateResource() { + DateTime newExpirationTime = leapSafeAddYears( + existingResource.getRegistrationExpirationTime(), command.getPeriod().getValue()); + // Bill for this explicit renew itself. + BillingEvent.OneTime explicitRenewEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.RENEW) + .setTargetId(targetId) + .setClientId(getClientId()) + .setPeriodYears(command.getPeriod().getValue()) + .setCost(checkNotNull(renewCost)) + .setEventTime(now) + .setBillingTime( + now.plus(Registry.get(existingResource.getTld()).getRenewGracePeriodLength())) + .setParent(historyEntry) + .build(); + // End the old autorenew billing event and poll message now. This may delete the poll message. + updateAutorenewRecurrenceEndTime(existingResource, now); + // Create a new autorenew billing event and poll message starting at the new expiration time. + BillingEvent.Recurring newAutorenewEvent = newAutorenewBillingEvent(existingResource) + .setEventTime(newExpirationTime) + .setParent(historyEntry) + .build(); + PollMessage.Autorenew newAutorenewPollMessage = newAutorenewPollMessage(existingResource) + .setEventTime(newExpirationTime) + .setParent(historyEntry) + .build(); + ofy().save().entities(explicitRenewEvent, newAutorenewEvent, newAutorenewPollMessage); + return existingResource.asBuilder() + .setRegistrationExpirationTime(newExpirationTime) + .setAutorenewBillingEvent(Ref.create(newAutorenewEvent)) + .setAutorenewPollMessage(Ref.create(newAutorenewPollMessage)) + .addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.RENEW, explicitRenewEvent)) + .build(); + } + + @Override + protected void verifyNewStateIsAllowed() throws EppException { + if (leapSafeAddYears(now, MAX_REGISTRATION_YEARS) + .isBefore(newResource.getRegistrationExpirationTime())) { + throw new ExceedsMaxRegistrationYearsException(); + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_RENEW; + } + + @Override + protected final Period getCommandPeriod() { + return command.getPeriod(); + } + + @Override + protected final EppOutput getOutput() { + return createOutput( + Success, + DomainRenewData.create( + newResource.getFullyQualifiedDomainName(), + newResource.getRegistrationExpirationTime()), + (feeRenew == null) ? null : ImmutableList.of( + new FeeRenewResponseExtension.Builder() + .setCurrency(renewCost.getCurrencyUnit()) + .setFee(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew"))) + .build())); + } + + /** The domain has a pending transfer on it and so can't be explicitly renewed. */ + public static class DomainHasPendingTransferException extends ObjectPendingTransferException { + public DomainHasPendingTransferException(String targetId) { + super(targetId); + } + } + + /** The current expiration date is incorrect. */ + static class IncorrectCurrentExpirationDateException extends ParameterValueRangeErrorException { + public IncorrectCurrentExpirationDateException() { + super("The current expiration date is incorrect"); + } + } + + /** New registration period exceeds maximum number of years. */ + static class ExceedsMaxRegistrationYearsException extends ParameterValueRangeErrorException { + public ExceedsMaxRegistrationYearsException() { + super(String.format( + "Registrations cannot extend for more than %d years into the future", + MAX_REGISTRATION_YEARS)); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainRestoreRequestFlow.java b/java/com/google/domain/registry/flows/domain/DomainRestoreRequestFlow.java new file mode 100644 index 000000000..319d86684 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainRestoreRequestFlow.java @@ -0,0 +1,208 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.newAutorenewBillingEvent; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessage; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotReserved; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.collect.ImmutableList; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.flows.OwnedResourceMutateFlow; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainCommand.Update; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeUpdateExtension; +import com.google.domain.registry.model.domain.fee.FeeUpdateResponseExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.rgp.RgpUpdateExtension; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Ref; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +/** + * An EPP flow that requests that a deleted domain be restored. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.CurrencyValueScaleException} + * @error {@link DomainFlowUtils.DomainReservedException} + * @error {@link DomainFlowUtils.FeesMismatchException} + * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} + * @error {@link DomainFlowUtils.PremiumNameBlockedException} + * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + * @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException} + * @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException} + */ +public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow { + + protected FeeUpdateExtension feeUpdate; + protected Money restoreCost; + protected Money renewCost; + + @Override + protected final void initResourceCreateOrMutateFlow() throws EppException { + registerExtensions(FeeUpdateExtension.class, RgpUpdateExtension.class); + } + + @Override + protected final void verifyMutationOnOwnedResourceAllowed() throws EppException { + // No other changes can be specified on a restore request. + if (!command.noChangesPresent()) { + throw new RestoreCommandIncludesChangesException(); + } + + // Domain must be in pendingDelete and within the redemptionPeriod to be eligible for restore. + if (!existingResource.getStatusValues().contains(StatusValue.PENDING_DELETE) + || !existingResource.getGracePeriodStatuses().contains(GracePeriodStatus.REDEMPTION)) { + throw new DomainNotEligibleForRestoreException(); + } + + String tld = existingResource.getTld(); + checkAllowedAccessToTld(getAllowedTlds(), tld); + if (!superuser) { + verifyNotReserved(InternetDomainName.from(targetId), false); + verifyPremiumNameIsNotBlocked(targetId, tld, getClientId()); + } + feeUpdate = eppInput.getSingleExtension(FeeUpdateExtension.class); + restoreCost = Registry.get(tld).getStandardRestoreCost(); + renewCost = Registry.get(tld).getDomainRenewCost(targetId, 1, now); + validateFeeChallenge(targetId, tld, feeUpdate, restoreCost, renewCost); + } + + @Override + protected final DomainResource createOrMutateResource() throws EppException { + // We don't preserve the original expiration time of the domain when we restore, since doing so + // would require us to know if they received a grace period refund when they deleted the domain, + // and to charge them for that again. Instead, we just say that all restores get a fresh year of + // registration and bill them for that accordingly. + DateTime newExpirationTime = now.plusYears(1); + + // Bill for the restore. + BillingEvent.OneTime restoreEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.RESTORE) + .setTargetId(targetId) + .setClientId(getClientId()) + .setCost(restoreCost) + .setEventTime(now) + .setBillingTime(now) + .setParent(historyEntry) + .build(); + // Create a new autorenew billing event and poll message starting at the new expiration time. + BillingEvent.Recurring autorenewEvent = newAutorenewBillingEvent(existingResource) + .setEventTime(newExpirationTime) + .setRecurrenceEndTime(END_OF_TIME) + .setParent(historyEntry) + .build(); + PollMessage.Autorenew autorenewPollMessage = newAutorenewPollMessage(existingResource) + .setEventTime(newExpirationTime) + .setAutorenewEndTime(END_OF_TIME) + .setParent(historyEntry) + .build(); + + // Also bill for the 1 year cost of a domain renew. This is to avoid registrants being able to + // game the system for premium names by renewing, deleting, and then restoring to get a free + // year. Note that this billing event has no grace period; it is effective immediately. + BillingEvent.OneTime renewEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.RENEW) + .setTargetId(targetId) + .setClientId(getClientId()) + .setPeriodYears(1) + .setCost(renewCost) + .setEventTime(now) + .setBillingTime(now) + .setParent(historyEntry) + .build(); + + ofy().save().entities(restoreEvent, autorenewEvent, autorenewPollMessage, renewEvent); + return existingResource.asBuilder() + .setRegistrationExpirationTime(newExpirationTime) + .setDeletionTime(END_OF_TIME) + .setStatusValues(null) + .setGracePeriods(null) + .setDeletePollMessage(null) + .setAutorenewBillingEvent(Ref.create(autorenewEvent)) + .setAutorenewPollMessage(Ref.create(autorenewPollMessage)) + .build(); + } + + @Override + protected void modifyRelatedResources() { + // Update the relevant {@link ForeignKey} to cache the new deletion time. + ofy().save().entity(ForeignKeyIndex.create(newResource, newResource.getDeletionTime())); + ofy().delete().key(existingResource.getDeletePollMessage()); + } + + @Override + protected void enqueueTasks() { + DnsQueue.create().addDomainRefreshTask(existingResource.getFullyQualifiedDomainName()); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_RESTORE; + } + + @Override + protected final EppOutput getOutput() { + return createOutput( + Success, + null, + (feeUpdate == null) ? null : ImmutableList.of( + new FeeUpdateResponseExtension.Builder() + .setCurrency(restoreCost.getCurrencyUnit()) + .setFee(ImmutableList.of( + Fee.create(restoreCost.getAmount(), "restore"), + Fee.create(renewCost.getAmount(), "renew"))) + .build())); + } + + /** Restore command cannot have other changes specified. */ + static class RestoreCommandIncludesChangesException extends CommandUseErrorException { + public RestoreCommandIncludesChangesException() { + super("Restore command cannot have other changes specified"); + } + } + + /** Domain is not eligible for restore. */ + static class DomainNotEligibleForRestoreException extends StatusProhibitsOperationException { + public DomainNotEligibleForRestoreException() { + super("Domain is not eligible for restore"); + } + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainTransferApproveFlow.java b/java/com/google/domain/registry/flows/domain/DomainTransferApproveFlow.java new file mode 100644 index 000000000..4bf9d2997 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainTransferApproveFlow.java @@ -0,0 +1,138 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.model.domain.DomainResource.extendRegistrationWithCap; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceTransferApproveFlow; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainCommand.Transfer; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferData; + +import com.googlecode.objectify.Ref; + +import org.joda.time.DateTime; + +/** + * An EPP flow that approves a pending transfer on a {@link DomainResource}. + *

+ * The logic in this flow, which handles client approvals, very closely parallels the logic in + * {@link DomainResource#cloneProjectedAtTime} which handles implicit server approvals. + * + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + */ +public class DomainTransferApproveFlow extends + ResourceTransferApproveFlow { + + @Override + protected void verifyOwnedResourcePendingTransferMutationAllowed() throws EppException { + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + } + + @Override + protected final void setTransferApproveProperties(Builder builder) { + TransferData transferData = existingResource.getTransferData(); + String gainingClientId = transferData.getGainingClientId(); + String tld = existingResource.getTld(); + int extraYears = transferData.getExtendedRegistrationYears(); + // Bill for the transfer. + BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.TRANSFER) + .setTargetId(targetId) + .setClientId(gainingClientId) + .setPeriodYears(extraYears) + .setCost(Registry.get(tld).getDomainRenewCost( + targetId, + extraYears, + transferData.getTransferRequestTime())) + .setEventTime(now) + .setBillingTime(now.plus(Registry.get(tld).getTransferGracePeriodLength())) + .setParent(historyEntry) + .build(); + ofy().save().entity(billingEvent); + // If we are within an autorenew grace period, cancel the autorenew billing event and reduce + // the number of years to extend the registration by one. + GracePeriod autorenewGrace = Iterables.getOnlyElement(FluentIterable + .from(existingResource.getGracePeriods()) + .filter(new Predicate(){ + @Override + public boolean apply(GracePeriod gracePeriod) { + return GracePeriodStatus.AUTO_RENEW.equals(gracePeriod.getType()); + }}), null); + if (autorenewGrace != null) { + extraYears--; + ofy().save().entity( + BillingEvent.Cancellation.forGracePeriod(autorenewGrace, historyEntry, targetId)); + } + // Close the old autorenew event and poll message at the transfer time (aka now). This may end + // up deleting the poll message. + updateAutorenewRecurrenceEndTime(existingResource, now); + DateTime newExpirationTime = extendRegistrationWithCap( + now, existingResource.getRegistrationExpirationTime(), extraYears); + // Create a new autorenew event starting at the expiration time. + BillingEvent.Recurring autorenewEvent = new BillingEvent.Recurring.Builder() + .setReason(Reason.AUTO_RENEW) + .setTargetId(targetId) + .setClientId(gainingClientId) + .setEventTime(newExpirationTime) + .setRecurrenceEndTime(END_OF_TIME) + .setParent(historyEntry) + .build(); + ofy().save().entity(autorenewEvent); + // Create a new autorenew poll message. + PollMessage.Autorenew gainingClientAutorenewPollMessage = new PollMessage.Autorenew.Builder() + .setTargetId(targetId) + .setClientId(gainingClientId) + .setEventTime(newExpirationTime) + .setAutorenewEndTime(END_OF_TIME) + .setMsg("Domain was auto-renewed.") + .setParent(historyEntry) + .build(); + ofy().save().entity(gainingClientAutorenewPollMessage); + builder + .setRegistrationExpirationTime(newExpirationTime) + .setAutorenewBillingEvent(Ref.create(autorenewEvent)) + .setAutorenewPollMessage(Ref.create(gainingClientAutorenewPollMessage)) + // Remove all the old grace periods and add a new one for the transfer. + .setGracePeriods(ImmutableSet.of( + GracePeriod.forBillingEvent(GracePeriodStatus.TRANSFER, billingEvent))); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE; + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainTransferCancelFlow.java b/java/com/google/domain/registry/flows/domain/DomainTransferCancelFlow.java new file mode 100644 index 000000000..99f6249ff --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainTransferCancelFlow.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceTransferCancelFlow; +import com.google.domain.registry.model.domain.DomainCommand.Transfer; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that cancels a pending transfer on a {@link DomainResource}. + * + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + * @error {@link com.google.domain.registry.flows.ResourceTransferCancelFlow.NotTransferInitiatorException} + */ +public class DomainTransferCancelFlow + extends ResourceTransferCancelFlow { + + /** + * Reopen the autorenew event and poll message that we closed for the implicit transfer. + * This may end up recreating the autorenew poll message if it was deleted when the transfer + * request was made. + */ + @Override + protected final void modifyRelatedResourcesForTransferCancel() { + updateAutorenewRecurrenceEndTime(existingResource, END_OF_TIME); + } + + @Override + protected void verifyTransferCancelMutationAllowed() throws EppException { + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL; + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainTransferQueryFlow.java b/java/com/google/domain/registry/flows/domain/DomainTransferQueryFlow.java new file mode 100644 index 000000000..81a9e39d7 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainTransferQueryFlow.java @@ -0,0 +1,29 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import com.google.domain.registry.flows.ResourceTransferQueryFlow; +import com.google.domain.registry.model.domain.DomainCommand.Transfer; +import com.google.domain.registry.model.domain.DomainResource; + +/** + * An EPP flow that queries a pending transfer on a {@link DomainResource}. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceTransferQueryFlow.NoTransferHistoryToQueryException} + * @error {@link com.google.domain.registry.flows.ResourceTransferQueryFlow.NotAuthorizedToViewTransferException} + */ +public class DomainTransferQueryFlow extends ResourceTransferQueryFlow {} diff --git a/java/com/google/domain/registry/flows/domain/DomainTransferRejectFlow.java b/java/com/google/domain/registry/flows/domain/DomainTransferRejectFlow.java new file mode 100644 index 000000000..5b910f986 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainTransferRejectFlow.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceTransferRejectFlow; +import com.google.domain.registry.model.domain.DomainCommand.Transfer; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +/** + * An EPP flow that rejects a pending transfer on a {@link DomainResource}. + * + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException} + */ +public class DomainTransferRejectFlow + extends ResourceTransferRejectFlow { + + @Override + protected void verifyOwnedResourcePendingTransferMutationAllowed() throws EppException { + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + } + + /** + * Reopen the autorenew event and poll message that we closed for the implicit transfer. + * This may end up recreating the poll message if it was deleted upon the transfer request. + */ + @Override + protected final void modifyRelatedResourcesForTransferReject() { + updateAutorenewRecurrenceEndTime(existingResource, END_OF_TIME); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_TRANSFER_REJECT; + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainTransferRequestFlow.java b/java/com/google/domain/registry/flows/domain/DomainTransferRequestFlow.java new file mode 100644 index 000000000..81869e5c3 --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainTransferRequestFlow.java @@ -0,0 +1,238 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + + +import static com.google.domain.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; +import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; +import static com.google.domain.registry.model.domain.DomainResource.extendRegistrationWithCap; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceTransferRequestFlow; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainCommand.Transfer; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.fee.Fee; +import com.google.domain.registry.model.domain.fee.FeeTransferExtension; +import com.google.domain.registry.model.domain.fee.FeeTransferResponseExtension; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferData.TransferServerApproveEntity; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; + +import org.joda.money.Money; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.HashSet; +import java.util.Set; + +/** + * An EPP flow that requests a transfer on a {@link DomainResource}. + * + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.AlreadyPendingTransferException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.MissingTransferRequestAuthInfoException} + * @error {@link com.google.domain.registry.flows.ResourceTransferRequestFlow.ObjectAlreadySponsoredException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link DomainFlowUtils.BadPeriodUnitException} + * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} + * @error {@link DomainFlowUtils.CurrencyValueScaleException} + * @error {@link DomainFlowUtils.FeesMismatchException} + * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} + * @error {@link DomainFlowUtils.PremiumNameBlockedException} + * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + */ +public class DomainTransferRequestFlow + extends ResourceTransferRequestFlow { + + /** The time when the transfer will be server approved if no other action happens first. */ + private DateTime automaticTransferTime; + + /** A new one-time billing event for the renewal packaged as part of this transfer. */ + private BillingEvent.OneTime transferBillingEvent; + + /** A new autorenew billing event starting at the transfer time. */ + private BillingEvent.Recurring gainingClientAutorenewEvent; + + /** A new autorenew poll message starting at the transfer time. */ + private PollMessage.Autorenew gainingClientAutorenewPollMessage; + + /** The amount that this transfer will cost due to the implied renew. */ + private Money renewCost; + + /** + * An optional extension from the client specifying how much they think the transfer should cost. + */ + private FeeTransferExtension feeTransfer; + + @Override + protected Duration getAutomaticTransferLength() { + return Registry.get(existingResource.getTld()).getAutomaticTransferLength(); + } + + @Override + protected final void initResourceTransferRequestFlow() { + registerExtensions(FeeTransferExtension.class); + feeTransfer = eppInput.getSingleExtension(FeeTransferExtension.class); + // The "existingResource" field is loaded before this function is called, but it may be null if + // the domain name specified is invalid or doesn't exist. If that's the case, simply exit + // early, and ResourceMutateFlow will later throw ResourceToMutateDoesNotExistException. + if (existingResource == null) { + return; + } + Registry registry = Registry.get(existingResource.getTld()); + automaticTransferTime = now.plus(registry.getAutomaticTransferLength()); + renewCost = registry.getDomainRenewCost(targetId, command.getPeriod().getValue(), now); + transferBillingEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.TRANSFER) + .setTargetId(targetId) + .setClientId(getClientId()) + .setCost(renewCost) + .setPeriodYears(command.getPeriod().getValue()) + .setEventTime(automaticTransferTime) + .setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength())) + .setParent(historyEntry) + .build(); + DateTime newExpirationTime = extendRegistrationWithCap( + automaticTransferTime, + existingResource.getRegistrationExpirationTime(), + command.getPeriod().getValue()); + gainingClientAutorenewEvent = new BillingEvent.Recurring.Builder() + .setReason(Reason.AUTO_RENEW) + .setTargetId(targetId) + .setClientId(gainingClient.getId()) + .setEventTime(newExpirationTime) + .setRecurrenceEndTime(END_OF_TIME) + .setParent(historyEntry) + .build(); + gainingClientAutorenewPollMessage = new PollMessage.Autorenew.Builder() + .setTargetId(targetId) + .setClientId(gainingClient.getId()) + .setEventTime(newExpirationTime) + .setAutorenewEndTime(END_OF_TIME) + .setMsg("Domain was auto-renewed.") + .setParent(historyEntry) + .build(); + } + + @Override + protected final void verifyTransferRequestIsAllowed() throws EppException { + verifyUnitIsYears(command.getPeriod()); + if (!superuser) { + verifyPremiumNameIsNotBlocked(targetId, existingResource.getTld(), getClientId()); + } + validateFeeChallenge(targetId, existingResource.getTld(), feeTransfer, renewCost); + checkAllowedAccessToTld(getAllowedTlds(), existingResource.getTld()); + } + + @Override + protected ImmutableList getTransferResponseExtensions() { + if (feeTransfer != null) { + return ImmutableList.of(new FeeTransferResponseExtension.Builder() + .setCurrency(renewCost.getCurrencyUnit()) + .setFee(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew"))) + .build()); + } else { + return null; + } + } + + @Override + protected void setTransferDataProperties(TransferData.Builder builder) { + builder + .setServerApproveBillingEvent(Ref.create(transferBillingEvent)) + .setServerApproveAutorenewEvent(Ref.create(gainingClientAutorenewEvent)) + .setServerApproveAutorenewPollMessage(Ref.create(gainingClientAutorenewPollMessage)) + .setExtendedRegistrationYears(command.getPeriod().getValue()); + } + + /** + * When a transfer is requested, schedule a billing event and poll message for the automatic + * approval case. + *

+ * Note that the action time is AUTOMATIC_TRANSFER_DAYS in the future, matching the server policy + * on automated approval of transfers. There is no equivalent grace period added; if the transfer + * is implicitly approved, the resource will project a grace period on itself. + */ + @Override + protected Set> getTransferServerApproveEntities() { + ofy().save().entities( + transferBillingEvent, gainingClientAutorenewEvent, gainingClientAutorenewPollMessage); + // If there will be an autorenew between now and the automatic transfer time, and if the + // autorenew grace period length is long enough that the domain will still be within it at the + // automatic transfer time, then the transfer will subsume the autorenew so we need to write out + // a cancellation for it. + Set> serverApproveEntities = new HashSet<>(); + DateTime expirationTime = existingResource.getRegistrationExpirationTime(); + Registry registry = Registry.get(existingResource.getTld()); + if (automaticTransferTime.isAfter(expirationTime) && automaticTransferTime.isBefore( + expirationTime.plus(registry.getAutoRenewGracePeriodLength()))) { + BillingEvent.Cancellation autorenewCancellation = new BillingEvent.Cancellation.Builder() + .setReason(Reason.AUTO_RENEW) + .setTargetId(targetId) + .setClientId(existingResource.getCurrentSponsorClientId()) + .setEventTime(automaticTransferTime) + .setBillingTime(expirationTime.plus(registry.getAutoRenewGracePeriodLength())) + .setEventRef(existingResource.getAutorenewBillingEvent()) + .setParent(historyEntry) + .build(); + ofy().save().entity(autorenewCancellation); + serverApproveEntities.add(Key.create(autorenewCancellation)); + } + serverApproveEntities.add(Key.create(transferBillingEvent)); + serverApproveEntities.add(Key.create(gainingClientAutorenewEvent)); + serverApproveEntities.add(Key.create(gainingClientAutorenewPollMessage)); + return serverApproveEntities; + } + + /** Close the old autorenew billing event and save a new one. */ + @Override + protected final void modifyRelatedResources() throws EppException { + // End the old autorenew event and poll message at the implicit transfer time. This may delete + // the poll message if it has no events left. + // + // Note that this is still left on the domain as the autorenewBillingEvent because it is still + // the current autorenew event until the transfer happens. If you read the domain after the + // transfer occurs, then the logic in cloneProjectedAtTime() will move the + // serverApproveAutoRenewEvent into the autoRenewEvent field. + updateAutorenewRecurrenceEndTime(existingResource, automaticTransferTime); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST; + } + + @Override + protected final Period getCommandPeriod() { + return command.getPeriod(); + } +} diff --git a/java/com/google/domain/registry/flows/domain/DomainUpdateFlow.java b/java/com/google/domain/registry/flows/domain/DomainUpdateFlow.java new file mode 100644 index 000000000..187b35e0d --- /dev/null +++ b/java/com/google/domain/registry/flows/domain/DomainUpdateFlow.java @@ -0,0 +1,165 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.domain; + +import static com.google.common.collect.Sets.symmetricDifference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.earliestOf; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.BillingEvent.Reason; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.DomainResource.Builder; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import org.joda.time.DateTime; + +import java.util.Set; + +/** + * An EPP flow that updates a domain resource. + * + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.ResourceCreateOrMutateFlow.OnlyToolCanPassMetadataException} + * @error {@link com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.AddRemoveSameValueEppException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link BaseDomainUpdateFlow.EmptySecDnsUpdateException} + * @error {@link BaseDomainUpdateFlow.MaxSigLifeChangeNotSupportedException} + * @error {@link BaseDomainUpdateFlow.SecDnsAllUsageException} + * @error {@link BaseDomainUpdateFlow.UrgentAttributeNotSupportedException} + * @error {@link DomainFlowUtils.DuplicateContactForRoleException} + * @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException} + * @error {@link DomainFlowUtils.LinkedResourceInPendingDeleteProhibitsOperationException} + * @error {@link DomainFlowUtils.MissingAdminContactException} + * @error {@link DomainFlowUtils.MissingContactTypeException} + * @error {@link DomainFlowUtils.MissingTechnicalContactException} + * @error {@link DomainFlowUtils.TooManyDsRecordsException} + * @error {@link DomainFlowUtils.TooManyNameserversException} + */ +public class DomainUpdateFlow extends BaseDomainUpdateFlow { + + @Override + protected void initDomainUpdateFlow() { + registerExtensions(SecDnsUpdateExtension.class, MetadataExtension.class); + } + + @Override + protected Builder setDomainUpdateProperties(Builder builder) { + // Check if the domain is currently in the sunrush add grace period. + Optional sunrushAddGracePeriod = Iterables.tryFind( + existingResource.getGracePeriods(), + new Predicate() { + @Override + public boolean apply(GracePeriod gracePeriod) { + return gracePeriod.isSunrushAddGracePeriod(); + }}); + + // If this domain is currently in the sunrush add grace period, and we're updating it in a way + // that will cause it to now get delegated (either by setting nameservers, or by removing a + // clientHold or serverHold), then that will remove the sunrush add grace period and convert + // that to a standard add grace period. + DomainResource updatedDomain = builder.build(); + builder = updatedDomain.asBuilder(); + if (sunrushAddGracePeriod.isPresent() && updatedDomain.shouldPublishToDns()) { + // Remove the sunrush grace period and write a billing event cancellation for it. + builder.removeGracePeriod(sunrushAddGracePeriod.get()); + BillingEvent.Cancellation billingEventCancellation = BillingEvent.Cancellation + .forGracePeriod(sunrushAddGracePeriod.get(), historyEntry, targetId); + + // Compute the expiration time of the add grace period. We will not allow it to be after the + // sunrush add grace period expiration time (i.e. you can't get extra add grace period by + // setting a nameserver). + DateTime addGracePeriodExpirationTime = earliestOf( + now.plus(Registry.get(existingResource.getTld()).getAddGracePeriodLength()), + sunrushAddGracePeriod.get().getExpirationTime()); + + // Create a new billing event for the add grace period. Note that we do this even if it would + // occur at the same time as the sunrush add grace period, as the event time will differ + // between them. + BillingEvent.OneTime originalAddEvent = + ((BillingEvent.OneTime) sunrushAddGracePeriod.get().getBillingEvent().get()); + BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.CREATE) + .setTargetId(targetId) + .setFlags(originalAddEvent.getFlags()) + .setClientId(sunrushAddGracePeriod.get().getClientId()) + .setCost(originalAddEvent.getCost()) + .setPeriodYears(originalAddEvent.getPeriodYears()) + .setEventTime(now) + .setBillingTime(addGracePeriodExpirationTime) + .setParent(historyEntry) + .build(); + + // Set the add grace period on the domain. + builder.addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.ADD, billingEvent)); + + // Save the billing events. + ofy().save().entities(billingEvent, billingEventCancellation); + } + + return builder; + } + + @Override + protected final void modifyRelatedResources() { + // Determine the status changes, and filter to server statuses. + // If any of these statuses have been added or removed, bill once. + if (metadataExtension != null && metadataExtension.getRequestedByRegistrar()) { + Set statusDifferences = + symmetricDifference(existingResource.getStatusValues(), newResource.getStatusValues()); + if (Iterables.any(statusDifferences, new Predicate() { + @Override + public boolean apply(StatusValue statusValue) { + return statusValue.isChargedStatus(); + }})) { + BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder() + .setReason(Reason.SERVER_STATUS) + .setTargetId(targetId) + .setClientId(getClientId()) + .setCost(Registry.get(existingResource.getTld()).getServerStatusChangeCost()) + .setEventTime(now) + .setBillingTime(now) + .setParent(historyEntry) + .build(); + ofy().save().entity(billingEvent); + } + } + } + + @Override + protected void enqueueTasks() { + DnsQueue.create().addDomainRefreshTask(existingResource.getFullyQualifiedDomainName()); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.DOMAIN_UPDATE; + } +} diff --git a/java/com/google/domain/registry/flows/host/HostCheckFlow.java b/java/com/google/domain/registry/flows/host/HostCheckFlow.java new file mode 100644 index 000000000..19e6d312a --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostCheckFlow.java @@ -0,0 +1,45 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import static com.google.domain.registry.model.EppResourceUtils.checkResourcesExist; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.ResourceCheckFlow; +import com.google.domain.registry.model.eppoutput.CheckData; +import com.google.domain.registry.model.eppoutput.CheckData.HostCheck; +import com.google.domain.registry.model.eppoutput.CheckData.HostCheckData; +import com.google.domain.registry.model.host.HostCommand.Check; +import com.google.domain.registry.model.host.HostResource; + +import java.util.Set; + +/** + * An EPP flow that checks whether a host can be provisioned. + * + * @error {@link com.google.domain.registry.flows.ResourceCheckFlow.TooManyResourceChecksException} + */ +public class HostCheckFlow extends ResourceCheckFlow { + @Override + protected CheckData getCheckData() { + Set existingIds = checkResourcesExist(resourceClass, targetIds, now); + ImmutableList.Builder checks = new ImmutableList.Builder<>(); + for (String id : targetIds) { + boolean unused = !existingIds.contains(id); + checks.add(HostCheck.create(unused, id, unused ? null : "In use")); + } + return HostCheckData.create(checks.build()); + } +} diff --git a/java/com/google/domain/registry/flows/host/HostCreateFlow.java b/java/com/google/domain/registry/flows/host/HostCreateFlow.java new file mode 100644 index 000000000..53c588470 --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostCreateFlow.java @@ -0,0 +1,143 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import static com.google.domain.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain; +import static com.google.domain.registry.flows.host.HostFlowUtils.validateHostName; +import static com.google.domain.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar; +import static com.google.domain.registry.model.EppResourceUtils.createContactHostRoid; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.isNullOrEmpty; + +import com.google.common.base.Optional; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.ResourceCreateFlow; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.eppoutput.CreateData.HostCreateData; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.host.HostCommand.Create; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.host.HostResource.Builder; +import com.google.domain.registry.model.ofy.ObjectifyService; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Ref; + +/** + * An EPP flow that creates a new host resource. + * + * @error {@link com.google.domain.registry.flows.EppXmlTransformer.IpAddressVersionMismatchException} + * @error {@link com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException} + * @error {@link HostFlowUtils.HostNameTooLongException} + * @error {@link HostFlowUtils.HostNameTooShallowException} + * @error {@link HostFlowUtils.InvalidHostNameException} + * @error {@link HostFlowUtils.SuperordinateDomainDoesNotExistException} + * @error {@link SubordinateHostMustHaveIpException} + * @error {@link UnexpectedExternalHostIpException} + */ +public class HostCreateFlow extends ResourceCreateFlow { + + /** + * The superordinate domain of the host object if creating an in-bailiwick host, or null if + * creating an external host. This is looked up before we actually create the Host object so that + * we can detect error conditions earlier. By the time {@link #setCreateProperties} is called + * (where this reference is actually used), we no longer have the ability to return an + * {@link EppException}. + * + *

The general model of these classes is to do validation of parameters up front before we get + * to the actual object creation, which is why this class looks up and stores the superordinate + * domain ahead of time. + */ + private Optional> superordinateDomain; + + @Override + protected void initResourceCreateOrMutateFlow() throws EppException { + superordinateDomain = Optional.fromNullable(lookupSuperordinateDomain( + validateHostName(command.getFullyQualifiedHostName()), now)); + } + + @Override + protected String createFlowRepoId() { + return createContactHostRoid(ObjectifyService.allocateId()); + } + + @Override + protected void verifyCreateIsAllowed() throws EppException { + verifyDomainIsSameRegistrar(superordinateDomain.orNull(), getClientId()); + boolean willBeSubordinate = superordinateDomain.isPresent(); + boolean hasIpAddresses = !isNullOrEmpty(command.getInetAddresses()); + if (willBeSubordinate != hasIpAddresses) { + // Subordinate hosts must have ip addresses and external hosts must not have them. + throw willBeSubordinate + ? new SubordinateHostMustHaveIpException() + : new UnexpectedExternalHostIpException(); + } + } + + @Override + protected void setCreateProperties(Builder builder) { + if (superordinateDomain.isPresent()) { + builder.setSuperordinateDomain(superordinateDomain.get()); + } + } + + /** Modify any other resources that need to be informed of this create. */ + @Override + protected void modifyCreateRelatedResources() { + if (superordinateDomain.isPresent()) { + ofy().save().entity(superordinateDomain.get().get().asBuilder() + .addSubordinateHost(command.getFullyQualifiedHostName()) + .build()); + } + } + + @Override + protected void enqueueTasks() { + // Only update DNS if this is a subordinate host. External hosts have no glue to write, so they + // are only written as NS records from the referencing domain. + if (superordinateDomain.isPresent()) { + DnsQueue.create().addHostRefreshTask(newResource.getFullyQualifiedHostName()); + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.HOST_CREATE; + } + + @Override + protected EppOutput getOutput() { + return createOutput(Success, + HostCreateData.create(newResource.getFullyQualifiedHostName(), now)); + } + + /** Subordinate hosts must have an ip address. */ + static class SubordinateHostMustHaveIpException extends RequiredParameterMissingException { + public SubordinateHostMustHaveIpException() { + super("Subordinate hosts must have an ip address"); + } + } + + /** External hosts must not have ip addresses. */ + static class UnexpectedExternalHostIpException extends ParameterValueRangeErrorException { + public UnexpectedExternalHostIpException() { + super("External hosts must not have ip addresses"); + } + } +} diff --git a/java/com/google/domain/registry/flows/host/HostDeleteFlow.java b/java/com/google/domain/registry/flows/host/HostDeleteFlow.java new file mode 100644 index 000000000..c60ea2f8d --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostDeleteFlow.java @@ -0,0 +1,87 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import static com.google.domain.registry.model.EppResourceUtils.queryDomainsUsingResource; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.ResourceAsyncDeleteFlow; +import com.google.domain.registry.flows.async.AsyncFlowUtils; +import com.google.domain.registry.flows.async.DeleteEppResourceAction; +import com.google.domain.registry.flows.async.DeleteHostResourceAction; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.host.HostCommand.Delete; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.host.HostResource.Builder; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Key; + +/** + * An EPP flow that deletes a host resource. + * + * @error {@link com.google.domain.registry.flows.ResourceAsyncDeleteFlow.ResourceToDeleteIsReferencedException} + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + */ +public class HostDeleteFlow extends ResourceAsyncDeleteFlow { + + /** In {@link #isLinkedForFailfast}, check this (arbitrary) number of resources from the query. */ + private static final int FAILFAST_CHECK_COUNT = 5; + + @Override + protected boolean isLinkedForFailfast(final ReferenceUnion ref) { + // Query for the first few linked domains, and if found, actually load them. The query is + // eventually consistent and so might be very stale, but the direct load will not be stale, + // just non-transactional. If we find at least one actual reference then we can reliably + // fail. If we don't find any, we can't trust the query and need to do the full mapreduce. + return Iterables.any( + ofy().load().keys( + queryDomainsUsingResource( + HostResource.class, ref.getLinked(), now, FAILFAST_CHECK_COUNT)).values(), + new Predicate() { + @Override + public boolean apply(DomainBase domain) { + return domain.getNameservers().contains(ref); + }}); + } + + /** Enqueues a host resource deletion on the mapreduce queue. */ + @Override + protected final void enqueueTasks() throws EppException { + AsyncFlowUtils.enqueueMapreduceAction( + DeleteHostResourceAction.class, + ImmutableMap.of( + DeleteEppResourceAction.PARAM_RESOURCE_KEY, + Key.create(existingResource).getString(), + DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID, + getClientId(), + DeleteEppResourceAction.PARAM_IS_SUPERUSER, + Boolean.toString(superuser)), + RegistryEnvironment.get().config().getAsyncDeleteFlowMapreduceDelay()); + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.HOST_PENDING_DELETE; + } +} diff --git a/java/com/google/domain/registry/flows/host/HostFlowUtils.java b/java/com/google/domain/registry/flows/host/HostFlowUtils.java new file mode 100644 index 000000000..84c4d2d3d --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostFlowUtils.java @@ -0,0 +1,143 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import static com.google.domain.registry.model.EppResourceUtils.isActive; +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.model.registry.Registries.findTldForName; + +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.model.domain.DomainResource; + +import com.googlecode.objectify.Ref; + +import org.joda.time.DateTime; + +/** Static utility functions for host flows. */ +public class HostFlowUtils { + + /** Checks that a host name is valid. */ + static InternetDomainName validateHostName(String name) throws EppException { + if (name == null) { + return null; + } + if (name.length() > 253) { + throw new HostNameTooLongException(); + } + try { + InternetDomainName hostName = InternetDomainName.from(name); + // Checks whether a hostname is deep enough. Technically a host can be just one under a + // public suffix (e.g. example.com) but we require by policy that it has to be at least one + // part beyond that (e.g. ns1.example.com). The public suffix list includes all current + // ccTlds, so this check requires 4+ parts if it's a ccTld that doesn't delegate second + // level domains, such as .co.uk. But the list does not include new tlds, so in that case + // we just ensure 3+ parts. In the particular case where our own tld has a '.' in it, we know + // that there need to be 4 parts as well. + if (hostName.isUnderPublicSuffix()) { + if (hostName.parent().isUnderPublicSuffix()) { + return hostName; + } + } else { + // We need to know how many parts the hostname has beyond the public suffix, but we don't + // know what the public suffix is. If the host is in bailiwick and we are hosting a + // multipart "tld" like .co.uk the publix suffix might be 2 parts. Otherwise it's an + // unrecognized tld that's not on the public suffix list, so assume the tld alone is the + // public suffix. + Optional tldParsed = findTldForName(hostName); + int suffixSize = tldParsed.isPresent() ? tldParsed.get().parts().size() : 1; + if (hostName.parts().size() >= suffixSize + 2) { + return hostName; + } + } + throw new HostNameTooShallowException(); + } catch (IllegalArgumentException e) { + throw new InvalidHostNameException(); + } + } + + /** Return the {@link DomainResource} this host is subordinate to, or null for external hosts. */ + static Ref lookupSuperordinateDomain( + InternetDomainName hostName, DateTime now) throws EppException { + Optional tldParsed = findTldForName(hostName); + if (!tldParsed.isPresent()) { + // This is an host on a TLD we don't run, therefore obviously external, so we are done. + return null; + } + + // This is a subordinate host + @SuppressWarnings("deprecation") + String domainName = Joiner.on('.').join(Iterables.skip( + hostName.parts(), hostName.parts().size() - (tldParsed.get().parts().size() + 1))); + DomainResource superordinateDomain = loadByUniqueId(DomainResource.class, domainName, now); + if (superordinateDomain == null || !isActive(superordinateDomain, now)) { + throw new SuperordinateDomainDoesNotExistException(domainName); + } + return Ref.create(superordinateDomain); + } + + /** Superordinate domain for this hostname does not exist. */ + static class SuperordinateDomainDoesNotExistException extends ObjectDoesNotExistException { + public SuperordinateDomainDoesNotExistException(String domainName) { + super(DomainResource.class, domainName); + } + } + + /** Ensure that the superordinate domain is sponsored by the provided clientId. */ + static void verifyDomainIsSameRegistrar( + Ref superordinateDomain, + String clientId) throws EppException { + if (superordinateDomain != null + && !clientId.equals(superordinateDomain.get().getCurrentSponsorClientId())) { + throw new HostDomainNotOwnedException(); + } + } + + /** Domain for host is sponsored by another registrar. */ + static class HostDomainNotOwnedException extends AuthorizationErrorException { + public HostDomainNotOwnedException() { + super("Domain for host is sponsored by another registrar"); + } + } + + /** Host names are limited to 253 characters. */ + static class HostNameTooLongException extends ParameterValueRangeErrorException { + public HostNameTooLongException() { + super("Host names are limited to 253 characters"); + } + } + + /** Host names must be at least two levels below the public suffix. */ + static class HostNameTooShallowException extends ParameterValuePolicyErrorException { + public HostNameTooShallowException() { + super("Host names must be at least two levels below the public suffix"); + } + } + + /** Invalid host name. */ + static class InvalidHostNameException extends ParameterValueSyntaxErrorException { + public InvalidHostNameException() { + super("Invalid host name"); + } + } +} diff --git a/java/com/google/domain/registry/flows/host/HostInfoFlow.java b/java/com/google/domain/registry/flows/host/HostInfoFlow.java new file mode 100644 index 000000000..93e9ed703 --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostInfoFlow.java @@ -0,0 +1,26 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import com.google.domain.registry.flows.ResourceInfoFlow; +import com.google.domain.registry.model.host.HostCommand; +import com.google.domain.registry.model.host.HostResource; + +/** + * An EPP flow that reads a host. + * + * @error {@link com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException} + */ +public class HostInfoFlow extends ResourceInfoFlow {} diff --git a/java/com/google/domain/registry/flows/host/HostUpdateFlow.java b/java/com/google/domain/registry/flows/host/HostUpdateFlow.java new file mode 100644 index 000000000..cc3eb3031 --- /dev/null +++ b/java/com/google/domain/registry/flows/host/HostUpdateFlow.java @@ -0,0 +1,235 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.host; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.domain.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain; +import static com.google.domain.registry.flows.host.HostFlowUtils.validateHostName; +import static com.google.domain.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar; +import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.isNullOrEmpty; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.dns.DnsQueue; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ObjectAlreadyExistsException; +import com.google.domain.registry.flows.EppException.ParameterValueRangeErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.EppException.StatusProhibitsOperationException; +import com.google.domain.registry.flows.ResourceUpdateFlow; +import com.google.domain.registry.flows.async.AsyncFlowUtils; +import com.google.domain.registry.flows.async.DnsRefreshForHostRenameAction; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostCommand.Update; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.host.HostResource.Builder; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; + +import org.joda.time.Duration; + +import java.util.Objects; + +/** + * An EPP flow that updates a host resource. + * + * @error {@link com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException} + * @error {@link com.google.domain.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException} + * @error {@link com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException} + * @error {@link HostFlowUtils.HostNameTooShallowException} + * @error {@link HostFlowUtils.InvalidHostNameException} + * @error {@link HostFlowUtils.SuperordinateDomainDoesNotExistException} + * @error {@link CannotAddIpToExternalHostException} + * @error {@link CannotRemoveSubordinateHostLastIpException} + * @error {@link HostAlreadyExistsException} + * @error {@link RenameHostToExternalRemoveIpException} + * @error {@link RenameHostToSubordinateRequiresIpException} + */ +public class HostUpdateFlow extends ResourceUpdateFlow { + + private Ref superordinateDomain; + + private String oldHostName; + private String newHostName; + private boolean isHostRename; + + @Override + protected void initResourceCreateOrMutateFlow() throws EppException { + String suppliedNewHostName = command.getInnerChange().getFullyQualifiedHostName(); + isHostRename = suppliedNewHostName != null; + oldHostName = targetId; + newHostName = firstNonNull(suppliedNewHostName, oldHostName); + superordinateDomain = + lookupSuperordinateDomain(validateHostName(newHostName), now); + } + + @Override + protected void verifyUpdateIsAllowed() throws EppException { + verifyDomainIsSameRegistrar(superordinateDomain, getClientId()); + if (isHostRename + && loadAndGetReference(HostResource.class, newHostName, now) != null) { + throw new HostAlreadyExistsException(newHostName); + } + } + + @Override + protected void verifyNewUpdatedStateIsAllowed() throws EppException { + boolean wasExternal = existingResource.getSuperordinateDomain() == null; + boolean wasSubordinate = !wasExternal; + boolean willBeExternal = superordinateDomain == null; + boolean willBeSubordinate = !willBeExternal; + boolean newResourceHasIps = !isNullOrEmpty(newResource.getInetAddresses()); + boolean commandAddsIps = !isNullOrEmpty(command.getInnerAdd().getInetAddresses()); + // These checks are order-dependent. For example a subordinate-to-external rename that adds new + // ips should hit the first exception, whereas one that only fails to remove the existing ips + // should hit the second. + if (willBeExternal && commandAddsIps) { + throw new CannotAddIpToExternalHostException(); + } + if (wasSubordinate && willBeExternal && newResourceHasIps) { + throw new RenameHostToExternalRemoveIpException(); + } + if (wasExternal && willBeSubordinate && !commandAddsIps) { + throw new RenameHostToSubordinateRequiresIpException(); + } + if (willBeSubordinate && !newResourceHasIps) { + throw new CannotRemoveSubordinateHostLastIpException(); + } + } + + @Override + protected Builder setUpdateProperties(Builder builder) { + // The superordinateDomain can be null if the new name is external. + // Note that the value of superordinateDomain is projected to the current time inside of + // the lookupSuperordinateDomain(...) call above, so that it will never be stale. + builder.setSuperordinateDomain(superordinateDomain); + builder.setLastSuperordinateChange(superordinateDomain == null ? null : now); + // Rely on the host's cloneProjectedAtTime() method to handle setting of transfer data. + return builder.build().cloneProjectedAtTime(now).asBuilder(); + } + + /** Keep the {@link ForeignKeyIndex} for this host up to date. */ + @Override + protected void modifyRelatedResources() { + if (isHostRename) { + // Update the foreign key for the old host name. + ofy().save().entity(ForeignKeyIndex.create(existingResource, now)); + // Save the foreign key for the new host name. + ofy().save().entity(ForeignKeyIndex.create(newResource, newResource.getDeletionTime())); + updateSuperordinateDomains(); + } + } + + @Override + public void enqueueTasks() throws EppException { + DnsQueue dnsQueue = DnsQueue.create(); + // Only update DNS for subordinate hosts. External hosts have no glue to write, so they + // are only written as NS records from the referencing domain. + if (existingResource.getSuperordinateDomain() != null) { + dnsQueue.addHostRefreshTask(oldHostName); + } + // In case of a rename, there are many updates we need to queue up. + if (isHostRename) { + // If the renamed host is also subordinate, then we must enqueue an update to write the new + // glue. + if (newResource.getSuperordinateDomain() != null) { + dnsQueue.addHostRefreshTask(newHostName); + } + // We must also enqueue updates for all domains that use this host as their nameserver so + // that their NS records can be updated to point at the new name. + AsyncFlowUtils.enqueueMapreduceAction( + DnsRefreshForHostRenameAction.class, + ImmutableMap.of( + DnsRefreshForHostRenameAction.PARAM_HOST_KEY, + Key.create(existingResource).getString()), + Duration.ZERO); + } + } + + @Override + protected final HistoryEntry.Type getHistoryEntryType() { + return HistoryEntry.Type.HOST_UPDATE; + } + + private void updateSuperordinateDomains() { + Ref oldSuperordinateDomain = existingResource.getSuperordinateDomain(); + if (oldSuperordinateDomain != null || superordinateDomain != null) { + if (Objects.equals(oldSuperordinateDomain, superordinateDomain)) { + ofy().save().entity(oldSuperordinateDomain.get().asBuilder() + .removeSubordinateHost(oldHostName) + .addSubordinateHost(newHostName) + .build()); + } else { + if (oldSuperordinateDomain != null) { + ofy().save().entity( + oldSuperordinateDomain.get() + .asBuilder() + .removeSubordinateHost(oldHostName) + .build()); + } + if (superordinateDomain != null) { + ofy().save().entity( + superordinateDomain.get() + .asBuilder() + .addSubordinateHost(newHostName) + .build()); + } + } + } + } + + /** Host with specified name already exists. */ + static class HostAlreadyExistsException extends ObjectAlreadyExistsException { + public HostAlreadyExistsException(String hostName) { + super(String.format("Object with given ID (%s) already exists", hostName)); + } + } + + /** Cannot add ip addresses to an external host. */ + static class CannotAddIpToExternalHostException extends ParameterValueRangeErrorException { + public CannotAddIpToExternalHostException() { + super("Cannot add ip addresses to external hosts"); + } + } + + /** Cannot remove all ip addresses from a subordinate host. */ + static class CannotRemoveSubordinateHostLastIpException + extends StatusProhibitsOperationException { + public CannotRemoveSubordinateHostLastIpException() { + super("Cannot remove all ip addresses from a subordinate host"); + } + } + + /** Host rename from external to subordinate must also add an ip addresses. */ + static class RenameHostToSubordinateRequiresIpException + extends RequiredParameterMissingException { + public RenameHostToSubordinateRequiresIpException() { + super("Host rename from external to subordinate must also add an ip address"); + } + } + + /** Host rename from subordinate to external must also remove all ip addresses. */ + static class RenameHostToExternalRemoveIpException extends ParameterValueRangeErrorException { + public RenameHostToExternalRemoveIpException() { + super("Host rename from subordinate to external must also remove all ip addresses"); + } + } +} diff --git a/java/com/google/domain/registry/flows/poll/PollAckFlow.java b/java/com/google/domain/registry/flows/poll/PollAckFlow.java new file mode 100644 index 000000000..a0abcfad0 --- /dev/null +++ b/java/com/google/domain/registry/flows/poll/PollAckFlow.java @@ -0,0 +1,148 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.poll; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.eppoutput.Result.Code.Success; +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithNoMessages; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.ObjectDoesNotExistException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.flows.EppException.RequiredParameterMissingException; +import com.google.domain.registry.flows.TransactionalFlow; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.poll.MessageQueueInfo; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException; + +import com.googlecode.objectify.Key; + +import org.joda.time.DateTime; + +/** + * An EPP flow for acknowledging poll messages. + * + * @error {@link PollAckFlow.InvalidMessageIdException} + * @error {@link PollAckFlow.MessageDoesNotExistException} + * @error {@link PollAckFlow.MissingMessageIdException} + * @error {@link PollAckFlow.NotAuthorizedToAckMessageException} + */ +public class PollAckFlow extends PollFlow implements TransactionalFlow { + + @Override + public final EppOutput run() throws EppException { + if (command.getMessageId() == null) { + throw new MissingMessageIdException(); + } + + Key pollMessageKey; + // Try parsing the messageId, and throw an exception if it's invalid. + try { + pollMessageKey = PollMessage.EXTERNAL_KEY_CONVERTER.reverse().convert(command.getMessageId()); + } catch (PollMessageExternalKeyParseException e) { + throw new InvalidMessageIdException(command.getMessageId()); + } + + // Load the message to be acked. If a message is queued to be delivered in the future, we treat + // it as if it doesn't exist yet. + PollMessage pollMessage = ofy().load().key(pollMessageKey).now(); + if (pollMessage == null || !isBeforeOrAt(pollMessage.getEventTime(), now)) { + throw new MessageDoesNotExistException(command.getMessageId()); + } + + // Make sure this client is authorized to ack this message. It could be that the message is + // supposed to go to a different registrar. + if (!getClientId().equals(pollMessage.getClientId())) { + throw new NotAuthorizedToAckMessageException(); + } + + // This keeps track of whether we should include the current acked message in the updated + // message count that's returned to the user. The only case where we do so is if an autorenew + // poll message is acked, but its next event is already ready to be delivered. + boolean includeAckedMessageInCount = false; + if (pollMessage instanceof PollMessage.OneTime) { + // One-time poll messages are deleted once acked. + ofy().delete().entity(pollMessage); + } else { + checkState(pollMessage instanceof PollMessage.Autorenew, "Unknown poll message type"); + PollMessage.Autorenew autorenewPollMessage = (PollMessage.Autorenew) pollMessage; + + // Move the eventTime of this autorenew poll message forward by a year. + DateTime nextEventTime = autorenewPollMessage.getEventTime().plusYears(1); + + // If the next event falls within the bounds of the end time, then just update the eventTime + // and re-save it for future autorenew poll messages to be delivered. Otherwise, this + // autorenew poll message has no more events to deliver and should be deleted. + if (nextEventTime.isBefore(autorenewPollMessage.getAutorenewEndTime())) { + ofy().save().entity(autorenewPollMessage.asBuilder().setEventTime(nextEventTime).build()); + includeAckedMessageInCount = isBeforeOrAt(nextEventTime, now); + } else { + ofy().delete().entity(autorenewPollMessage); + } + } + // We need to return the new queue length. If this was the last message in the queue being + // acked, then we return a special status code indicating that. Note that the query will + // include the message being acked. + int messageCount = getMessageQueueLength(); + if (!includeAckedMessageInCount) { + messageCount--; + } + if (messageCount <= 0) { + return createOutput(SuccessWithNoMessages); + } + + return createOutput( + Success, + MessageQueueInfo.create( + null, // eventTime + null, // msg + messageCount, + command.getMessageId()), + null, // responseData + null); // extensions + } + + /** Registrar is not authorized to ack this message. */ + static class NotAuthorizedToAckMessageException extends AuthorizationErrorException { + public NotAuthorizedToAckMessageException() { + super("Registrar is not authorized to ack this message"); + } + } + + /** Message with this id does not exist. */ + public static class MessageDoesNotExistException extends ObjectDoesNotExistException { + public MessageDoesNotExistException(String messageIdString) { + super(PollMessage.class, messageIdString); + } + } + + /** Message id is invalid. */ + static class InvalidMessageIdException extends ParameterValueSyntaxErrorException { + public InvalidMessageIdException(String messageIdStr) { + super(String.format("Message id \"%s\" is invalid", messageIdStr)); + } + } + + /** Message id is required. */ + static class MissingMessageIdException extends RequiredParameterMissingException { + public MissingMessageIdException() { + super("Message id is required"); + } + } +} diff --git a/java/com/google/domain/registry/flows/poll/PollFlow.java b/java/com/google/domain/registry/flows/poll/PollFlow.java new file mode 100644 index 000000000..4934cbb37 --- /dev/null +++ b/java/com/google/domain/registry/flows/poll/PollFlow.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.poll; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.LoggedInFlow; +import com.google.domain.registry.model.eppinput.EppInput.Poll; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Response; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.eppoutput.Result; +import com.google.domain.registry.model.poll.MessageQueueInfo; +import com.google.domain.registry.model.poll.PollMessage; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.cmd.Query; + +import java.util.List; + +/** Base class of EPP Poll command flows. Mostly provides datastore helper methods. */ +public abstract class PollFlow extends LoggedInFlow { + + protected Poll command; + + @Override + @SuppressWarnings("unchecked") + protected final void initLoggedInFlow() throws EppException { + command = (Poll) eppInput.getCommandWrapper().getCommand(); + } + + /** + * Returns a query for all poll messages for the logged in registrar in the current TLD which are + * not in the future. + */ + private Query getQuery() { + return ofy().doTransactionless(new Work>() { + @Override + public Query run() { + return ofy().load() + .type(PollMessage.class) + .filter("clientId", getClientId()) + .filter("eventTime <=", now.toDate()); + }}); + } + + /** Return the length of the message queue for the logged in registrar. */ + protected int getMessageQueueLength() { + return getQuery().keys().list().size(); + } + + /** + * Retrieves the Keys of all active PollMessage entities for the current client ordered by + * eventTime. + */ + protected List> getMessageQueueKeysInOrder() { + return getQuery().order("eventTime").keys().list(); + } + + protected EppOutput createOutput( + Result.Code code, + MessageQueueInfo messageQueueInfo, + ImmutableList responseData, + ImmutableList responseExtensions) { + return EppOutput.create(new Response.Builder() + .setTrid(trid) + .setResult(Result.create(code)) + .setMessageQueueInfo(messageQueueInfo) + .setResData(responseData) + .setExtensions(responseExtensions) + .setExecutionTime(now) + .build()); + } +} diff --git a/java/com/google/domain/registry/flows/poll/PollRequestFlow.java b/java/com/google/domain/registry/flows/poll/PollRequestFlow.java new file mode 100644 index 000000000..7b309ac55 --- /dev/null +++ b/java/com/google/domain/registry/flows/poll/PollRequestFlow.java @@ -0,0 +1,71 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.poll; + +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithAckMessage; +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessWithNoMessages; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.ParameterValueSyntaxErrorException; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.poll.MessageQueueInfo; +import com.google.domain.registry.model.poll.PollMessage; + +import com.googlecode.objectify.Key; + +import java.util.List; + +/** + * An EPP flow for requesting poll messages. + * + * @error {@link PollRequestFlow.UnexpectedMessageIdException} + */ +public class PollRequestFlow extends PollFlow { + + @Override + public final EppOutput run() throws EppException { + if (command.getMessageId() != null) { + throw new UnexpectedMessageIdException(); + } + + List> pollMessageKeys = getMessageQueueKeysInOrder(); + // Retrieve the oldest message from the queue that still exists -- since the query is eventually + // consistent, it may return keys to some entities that no longer exist. + for (Key key : pollMessageKeys) { + PollMessage pollMessage = ofy().load().key(key).now(); + if (pollMessage != null) { + return createOutput( + SuccessWithAckMessage, + MessageQueueInfo.create( + pollMessage.getEventTime(), + pollMessage.getMsg(), + pollMessageKeys.size(), + PollMessage.EXTERNAL_KEY_CONVERTER.convert(key)), + forceEmptyToNull(pollMessage.getResponseData()), + forceEmptyToNull(pollMessage.getResponseExtensions())); + } + } + return createOutput(SuccessWithNoMessages); + } + + /** Unexpected message id. */ + static class UnexpectedMessageIdException extends ParameterValueSyntaxErrorException { + public UnexpectedMessageIdException() { + super("Unexpected message id"); + } + } +} diff --git a/java/com/google/domain/registry/flows/session/HelloFlow.java b/java/com/google/domain/registry/flows/session/HelloFlow.java new file mode 100644 index 000000000..c4714ed9c --- /dev/null +++ b/java/com/google/domain/registry/flows/session/HelloFlow.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.session; + +import com.google.domain.registry.flows.Flow; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Greeting; + +/** A flow for an Epp "hello". */ +public class HelloFlow extends Flow { + @Override + public EppOutput run() { + return EppOutput.create(new Greeting()); + } +} diff --git a/java/com/google/domain/registry/flows/session/LoginFlow.java b/java/com/google/domain/registry/flows/session/LoginFlow.java new file mode 100644 index 000000000..675932667 --- /dev/null +++ b/java/com/google/domain/registry/flows/session/LoginFlow.java @@ -0,0 +1,200 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.session; + +import static com.google.common.collect.Sets.difference; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppException.AuthenticationErrorClosingConnectionException; +import com.google.domain.registry.flows.EppException.AuthenticationErrorException; +import com.google.domain.registry.flows.EppException.AuthorizationErrorException; +import com.google.domain.registry.flows.EppException.CommandUseErrorException; +import com.google.domain.registry.flows.EppException.ParameterValuePolicyErrorException; +import com.google.domain.registry.flows.EppException.UnimplementedExtensionException; +import com.google.domain.registry.flows.EppException.UnimplementedObjectServiceException; +import com.google.domain.registry.flows.EppException.UnimplementedOptionException; +import com.google.domain.registry.flows.Flow; +import com.google.domain.registry.flows.TransportCredentials; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; +import com.google.domain.registry.model.eppinput.EppInput.Login; +import com.google.domain.registry.model.eppinput.EppInput.Options; +import com.google.domain.registry.model.eppinput.EppInput.Services; +import com.google.domain.registry.model.eppoutput.EppOutput; +import com.google.domain.registry.model.eppoutput.Result.Code; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.util.FormattingLogger; + +import java.util.Objects; +import java.util.Set; + +/** + * An EPP flow for login. + * + * @error {@link com.google.domain.registry.flows.EppConsoleServlet.GaeUserCredentials.BadGaeUserIdException} + * @error {@link com.google.domain.registry.flows.EppConsoleServlet.GaeUserCredentials.UserNotLoggedInException} + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedExtensionException} + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedObjectServiceException} + * @error {@link com.google.domain.registry.flows.EppException.UnimplementedProtocolVersionException} + * @error {@link com.google.domain.registry.flows.TlsCredentials.BadRegistrarCertificateException} + * @error {@link com.google.domain.registry.flows.TlsCredentials.BadRegistrarIpAddressException} + * @error {@link com.google.domain.registry.flows.TlsCredentials.MissingRegistrarCertificateException} + * @error {@link com.google.domain.registry.flows.TlsCredentials.NoSniException} + * @error {@link LoginFlow.AlreadyLoggedInException} + * @error {@link LoginFlow.BadRegistrarClientIdException} + * @error {@link LoginFlow.BadRegistrarPasswordException} + * @error {@link LoginFlow.TooManyFailedLoginsException} + * @error {@link LoginFlow.PasswordChangesNotSupportedException} + * @error {@link LoginFlow.RegistrarAccountNotActiveException} + * @error {@link LoginFlow.UnsupportedLanguageException} + */ +public class LoginFlow extends Flow { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** This is the IANA ID used for the internal account of the registry. */ + private static final long INTERNAL_IANA_REGISTRAR_ID = 9999L; + + /** Maximum number of failed login attempts allowed per connection. */ + private static final int MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION = 3; + + /** Run the flow and log errors. */ + @Override + public final EppOutput run() throws EppException { + try { + return runWithoutLogging(); + } catch (EppException e) { + logger.warning("Login failed: " + e.getMessage()); + throw e; + } + } + + /** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */ + public final EppOutput runWithoutLogging() throws EppException { + Login login = (Login) eppInput.getCommandWrapper().getCommand(); + if (getClientId() != null) { + throw new AlreadyLoggedInException(); + } + Options options = login.getOptions(); + if (!ProtocolDefinition.LANGUAGE.equals(options.getLanguage())) { + throw new UnsupportedLanguageException(); + } + Services services = login.getServices(); + Set unsupportedObjectServices = difference( + nullToEmpty(services.getObjectServices()), + ProtocolDefinition.SUPPORTED_OBJECT_SERVICES); + if (!unsupportedObjectServices.isEmpty()) { + throw new UnimplementedObjectServiceException(); + } + ImmutableSet.Builder serviceExtensionUrisBuilder = new ImmutableSet.Builder<>(); + for (String uri : nullToEmpty(services.getServiceExtensions())) { + ServiceExtension serviceExtension = ProtocolDefinition.getServiceExtensionFromUri(uri); + if (serviceExtension == null) { + throw new UnimplementedExtensionException(); + } + serviceExtensionUrisBuilder.add(uri); + } + Registrar registrar = Registrar.loadByClientId(login.getClientId()); + if (registrar == null) { + throw new BadRegistrarClientIdException(login.getClientId()); + } + + TransportCredentials credentials = sessionMetadata.getTransportCredentials(); + // AuthenticationErrorExceptions will propagate up through here. + if (credentials != null) { // Allow no-credential logins, for load-testing and RDE. + try { + credentials.validate(registrar); + } catch (AuthenticationErrorException e) { + sessionMetadata.incrementFailedLoginAttempts(); + throw e; + } + } + + final boolean requiresLoginCheck = credentials == null || !credentials.performsLoginCheck(); + if (requiresLoginCheck && !registrar.testPassword(login.getPassword())) { + sessionMetadata.incrementFailedLoginAttempts(); + if (sessionMetadata.getFailedLoginAttempts() > MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION) { + throw new TooManyFailedLoginsException(); + } else { + throw new BadRegistrarPasswordException(); + } + } + if (registrar.getState().equals(Registrar.State.PENDING)) { + throw new RegistrarAccountNotActiveException(); + } + if (login.getNewPassword() != null) { // We don't support in-band password changes. + throw new PasswordChangesNotSupportedException(); + } + + // We are in! + sessionMetadata.resetFailedLoginAttempts(); + sessionMetadata.setClientId(login.getClientId()); + sessionMetadata.setSuperuser( + Objects.equals(INTERNAL_IANA_REGISTRAR_ID, registrar.getIanaIdentifier())); + sessionMetadata.setServiceExtensionUris(serviceExtensionUrisBuilder.build()); + return createOutput(Code.Success); + } + + /** Registrar with this client ID could not be found. */ + static class BadRegistrarClientIdException extends AuthenticationErrorException { + public BadRegistrarClientIdException(String clientId) { + super("Registrar with this client ID could not be found: " + clientId); + } + } + + /** Registrar password is incorrect. */ + static class BadRegistrarPasswordException extends AuthenticationErrorException { + public BadRegistrarPasswordException() { + super("Registrar password is incorrect"); + } + } + + /** Registrar login failed too many times. */ + static class TooManyFailedLoginsException extends AuthenticationErrorClosingConnectionException { + public TooManyFailedLoginsException() { + super("Registrar login failed too many times"); + } + } + + /** Registrar account is not active. */ + static class RegistrarAccountNotActiveException extends AuthorizationErrorException { + public RegistrarAccountNotActiveException() { + super("Registrar account is not active"); + } + } + + /** Registrar is already logged in. */ + static class AlreadyLoggedInException extends CommandUseErrorException { + public AlreadyLoggedInException() { + super("Registrar is already logged in"); + } + } + + /** Specified language is not supported. */ + static class UnsupportedLanguageException extends ParameterValuePolicyErrorException { + public UnsupportedLanguageException() { + super("Specified language is not supported"); + } + } + + /** In-band password changes are not supported. */ + static class PasswordChangesNotSupportedException extends UnimplementedOptionException { + public PasswordChangesNotSupportedException() { + super("In-band password changes are not supported"); + } + } +} diff --git a/java/com/google/domain/registry/flows/session/LogoutFlow.java b/java/com/google/domain/registry/flows/session/LogoutFlow.java new file mode 100644 index 000000000..4d4a77ab2 --- /dev/null +++ b/java/com/google/domain/registry/flows/session/LogoutFlow.java @@ -0,0 +1,34 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.flows.session; + +import static com.google.domain.registry.model.eppoutput.Result.Code.SuccessAndClose; + +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.LoggedInFlow; +import com.google.domain.registry.model.eppoutput.EppOutput; + +/** + * An EPP flow for logout. + * + * @error {@link com.google.domain.registry.flows.LoggedInFlow.NotLoggedInException} + */ +public class LogoutFlow extends LoggedInFlow { + @Override + public final EppOutput run() throws EppException { + sessionMetadata.invalidate(); + return createOutput(SuccessAndClose); + } +} diff --git a/java/com/google/domain/registry/gcs/BUILD b/java/com/google/domain/registry/gcs/BUILD new file mode 100644 index 000000000..15c04ffb7 --- /dev/null +++ b/java/com/google/domain/registry/gcs/BUILD @@ -0,0 +1,18 @@ +package(default_visibility = ["//java/com/google/domain/registry:registry_project"]) + + +java_library( + name = "gcs", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine_gcs_client", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + ], +) diff --git a/java/com/google/domain/registry/gcs/GcsServiceModule.java b/java/com/google/domain/registry/gcs/GcsServiceModule.java new file mode 100644 index 000000000..58128d06c --- /dev/null +++ b/java/com/google/domain/registry/gcs/GcsServiceModule.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.gcs; + +import com.google.appengine.tools.cloudstorage.GcsService; +import com.google.appengine.tools.cloudstorage.GcsServiceFactory; +import com.google.appengine.tools.cloudstorage.RetryParams; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module for {@link GcsService}. */ +@Module +public final class GcsServiceModule { + + private static final GcsService gcsService = + GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance()); + + @Provides + static GcsService provideGcsService() { + return gcsService; + } +} diff --git a/java/com/google/domain/registry/gcs/GcsUtils.java b/java/com/google/domain/registry/gcs/GcsUtils.java new file mode 100644 index 000000000..a2c4d6d8b --- /dev/null +++ b/java/com/google/domain/registry/gcs/GcsUtils.java @@ -0,0 +1,101 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.gcs; + +import static com.google.common.collect.Iterables.getLast; + +import com.google.appengine.tools.cloudstorage.GcsFileMetadata; +import com.google.appengine.tools.cloudstorage.GcsFileOptions; +import com.google.appengine.tools.cloudstorage.GcsFileOptions.Builder; +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.appengine.tools.cloudstorage.GcsService; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import com.google.common.net.MediaType; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; + +import javax.annotation.CheckReturnValue; +import javax.inject.Inject; + +/** Utilities for working with Google Cloud Storage. */ +public final class GcsUtils { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final ImmutableMap EXTENSIONS = + new ImmutableMap.Builder() + .put("ghostryde", MediaType.APPLICATION_BINARY) + .put("length", MediaType.PLAIN_TEXT_UTF_8) + .put("json", MediaType.JSON_UTF_8) + .build(); + + private final GcsService gcsService; + private final int bufferSize; + + @Inject + public GcsUtils(GcsService gcsService, @Config("gcsBufferSize") int bufferSize) { + this.gcsService = gcsService; + this.bufferSize = bufferSize; + } + + /** Opens a GCS file for reading as an {@link InputStream} with prefetching. */ + @CheckReturnValue + public InputStream openInputStream(GcsFilename filename) { + return Channels.newInputStream(gcsService.openPrefetchingReadChannel(filename, 0, bufferSize)); + } + + /** Opens a GCS file for writing as an {@link OutputStream}, overwriting existing files. */ + @CheckReturnValue + public OutputStream openOutputStream(GcsFilename filename) throws IOException { + return Channels.newOutputStream(gcsService.createOrReplace(filename, getOptions(filename))); + } + + /** Creates a GCS file with the given byte contents, overwriting existing files. */ + public void createFromBytes(GcsFilename filename, byte[] bytes) throws IOException { + gcsService.createOrReplace(filename, getOptions(filename), ByteBuffer.wrap(bytes)); + } + + /** Returns {@code true} if a file exists and is non-empty on Google Cloud Storage. */ + public boolean existsAndNotEmpty(GcsFilename file) { + GcsFileMetadata metadata; + try { + metadata = gcsService.getMetadata(file); + } catch (IOException e) { + logger.warning(e, "Failed to check if GCS file exists"); + return false; + } + if (metadata == null) { + return false; + } + return metadata.getLength() > 0; + } + + /** Determines most appropriate {@link GcsFileOptions} based on filename extension. */ + private static GcsFileOptions getOptions(GcsFilename filename) { + Builder builder = new GcsFileOptions.Builder().cacheControl("no-cache"); + MediaType mediaType = EXTENSIONS.get(getLast(Splitter.on('.').split(filename.getObjectName()))); + if (mediaType != null) { + builder = builder.mimeType(mediaType.type()); + } + return builder.build(); + } +} diff --git a/java/com/google/domain/registry/groups/BUILD b/java/com/google/domain/registry/groups/BUILD new file mode 100644 index 000000000..bbcb0b5d3 --- /dev/null +++ b/java/com/google/domain/registry/groups/BUILD @@ -0,0 +1,25 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "groups", + srcs = glob(["*.java"]), + deps = [ + "//apiserving/discoverydata/admin:admin_directory_v1", + "//apiserving/discoverydata/groupssettings", + "//java/com/google/api/client/googleapis/auth/oauth2", + "//java/com/google/api/client/googleapis/json", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/groups/DirectoryGroupsConnection.java b/java/com/google/domain/registry/groups/DirectoryGroupsConnection.java new file mode 100644 index 000000000..a0efe12b4 --- /dev/null +++ b/java/com/google/domain/registry/groups/DirectoryGroupsConnection.java @@ -0,0 +1,171 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.groups; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static javax.servlet.http.HttpServletResponse.SC_CONFLICT; +import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; + +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.admin.directory.Directory; +import com.google.api.services.admin.directory.model.Group; +import com.google.api.services.admin.directory.model.Member; +import com.google.api.services.admin.directory.model.Members; +import com.google.api.services.groupssettings.Groupssettings; +import com.google.api.services.groupssettings.model.Groups; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; +import java.util.Set; + +import javax.inject.Inject; + +/** + * Class encapsulating methods to access Google Groups API. + */ +public class DirectoryGroupsConnection implements GroupsConnection { + + // NOTE: These error message strings were determined empirically. The API documentation contains + // no mention of what happens in error conditions. Here be dragons. + private static final String GROUP_NOT_FOUND_MSG = "Resource Not Found: groupKey"; + private static final String MEMBER_NOT_FOUND_MSG = "Resource Not Found: memberKey"; + private static final String MEMBER_ALREADY_EXISTS_MSG = "Member already exists."; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + private static final Groups defaultGroupPermissions = getDefaultGroupPermissions(); + + @VisibleForTesting + static Groups getDefaultGroupPermissions() { + Groups permissions = new Groups(); + permissions.setAllowExternalMembers(Boolean.TRUE.toString()); + permissions.setWhoCanPostMessage("ALL_MANAGERS_CAN_POST"); + permissions.setWhoCanViewGroup("ALL_MANAGERS_CAN_VIEW"); + permissions.setWhoCanViewMembership("ALL_MANAGERS_CAN_VIEW"); + permissions.setWhoCanJoin("INVITED_CAN_JOIN"); + permissions.setWhoCanInvite("ALL_MANAGERS_CAN_INVITE"); + return permissions; + } + + @Inject Directory directory; + @Inject Groupssettings groupsSettings; + @Inject @Config("googleAppsAdminEmailAddress") String googleAppsAdminEmailAddress; + @Inject DirectoryGroupsConnection() {} + + @Override + public void addMemberToGroup(String groupKey, String email, Role role) throws IOException { + // Documentation for this API call: + // https://developers.google.com/admin-sdk/directory/v1/reference/members/insert + Member member = new Member(); + member.setEmail(email); + member.setRole(role.toString()); + try { + directory.members().insert(groupKey, member).execute(); + } catch (GoogleJsonResponseException e) { + // If the member is already in the group, ignore the error, get the existing member, and + // return it. + GoogleJsonError err = e.getDetails(); + if (err.getCode() == SC_NOT_FOUND && err.getMessage().equals(GROUP_NOT_FOUND_MSG)) { + logger.infofmt( + e, + "Creating group %s during addition of member %s because the group doesn't exist.", + groupKey, + email); + createGroup(groupKey); + addMemberToGroup(groupKey, email, role); + } else if (err.getCode() == SC_NOT_FOUND && err.getMessage().equals(MEMBER_NOT_FOUND_MSG)) { + throw new RuntimeException(String.format( + "Adding member %s to group %s failed because the member wasn't found.", + email, + groupKey), e); + } else if (err.getCode() == SC_CONFLICT + && err.getMessage().equals(MEMBER_ALREADY_EXISTS_MSG)) { + // This error case usually happens when an email address is already a member of the gorup, + // but it is bouncing incoming emails. It won't show up in the members list API call, but + // will throw a "Member already exists" error message if you attempt to add it again. The + // correct thing to do is log an info message when this happens and then ignore it. + logger.infofmt( + e, + "Could not add email %s to group %s because it is already a member " + + "(likely because the email address is bouncing incoming messages).", + email, + groupKey); + } else { + throw e; + } + } + } + + @Override + public void removeMemberFromGroup(String groupKey, String email) throws IOException { + // Documentation for this API call: + // https://developers.google.com/admin-sdk/directory/v1/reference/members/delete + directory.members().delete(groupKey, email).execute(); + } + + @Override + public Set getMembersOfGroup(String groupKey) throws IOException { + // Documentation for this API call: + // https://developers.google.com/admin-sdk/directory/v1/reference/members/list + try { + ImmutableSet.Builder allMembers = new ImmutableSet.Builder<>(); + Directory.Members.List listRequest = + directory.members().list(groupKey).setRoles(Role.MEMBER.toString()); + do { + Members currentPage = listRequest.execute(); + for (Member member : nullToEmpty(currentPage.getMembers())) { + allMembers.add(member.getEmail()); + } + listRequest.setPageToken(currentPage.getNextPageToken()); + } while (!Strings.isNullOrEmpty(listRequest.getPageToken())); + return allMembers.build(); + } catch (GoogleJsonResponseException e) { + if (e.getDetails() != null + && e.getDetails().getCode() == SC_NOT_FOUND + && e.getDetails().getMessage().equals(GROUP_NOT_FOUND_MSG)) { + return ImmutableSet.of(); + } else { + throw e; + } + } + } + + @Override + public Group createGroup(String groupKey) throws IOException { + // Documentation for this API call: + // https://developers.google.com/admin-sdk/directory/v1/reference/groups/insert + Group group = new Group(); + group.setEmail(groupKey); + try { + Group createdGroup = directory.groups().insert(group).execute(); + addMemberToGroup(groupKey, googleAppsAdminEmailAddress, Role.OWNER); + groupsSettings.groups().patch(groupKey, defaultGroupPermissions).execute(); + return createdGroup; + } catch (GoogleJsonResponseException e) { + // Ignore the error thrown if the group already exists. + if (e.getDetails().getCode() == SC_CONFLICT + && e.getDetails().getMessage().equals("Entity already exists.")) { + logger.infofmt(e, "Could not create group %s because it already exists.", groupKey); + return directory.groups().get(groupKey).execute(); + } else { + throw e; + } + } + } +} diff --git a/java/com/google/domain/registry/groups/DirectoryModule.java b/java/com/google/domain/registry/groups/DirectoryModule.java new file mode 100644 index 000000000..9b46d111e --- /dev/null +++ b/java/com/google/domain/registry/groups/DirectoryModule.java @@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.groups; + +import static dagger.Provides.Type.SET_VALUES; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.services.admin.directory.Directory; +import com.google.api.services.admin.directory.DirectoryScopes; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.DelegatedOAuthScopes; + +import dagger.Module; +import dagger.Provides; + +import java.util.Set; + +import javax.inject.Named; + +/** + * Dagger module for the Google {@link Directory} service. + * + * @see com.google.domain.registry.config.ConfigModule + * @see com.google.domain.registry.request.Modules.UrlFetchTransportModule + * @see com.google.domain.registry.request.Modules.Jackson2Module + * @see com.google.domain.registry.request.Modules.AppIdentityCredentialModule + * @see com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule + */ +@Module +public final class DirectoryModule { + + /** Provides OAuth2 scopes for the Directory service needed by Domain Registry. */ + @Provides(type = SET_VALUES) + @DelegatedOAuthScopes + static Set provideDirectoryOAuthScopes() { + return ImmutableSet.of( + DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER, + DirectoryScopes.ADMIN_DIRECTORY_GROUP); + } + + @Provides + static Directory provideDirectory( + @Named("delegatedAdmin") GoogleCredential credential, + @Config("projectId") String projectId) { + return new Directory.Builder(credential.getTransport(), credential.getJsonFactory(), credential) + .setApplicationName(projectId) + .build(); + } +} diff --git a/java/com/google/domain/registry/groups/GroupsConnection.java b/java/com/google/domain/registry/groups/GroupsConnection.java new file mode 100644 index 000000000..f81037350 --- /dev/null +++ b/java/com/google/domain/registry/groups/GroupsConnection.java @@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.groups; + +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.admin.directory.model.Group; + +import java.io.IOException; +import java.util.Set; + +/** + * Interface for common operations on Groups. + */ +public interface GroupsConnection { + + /** The role of a member in a group. */ + public enum Role { + MEMBER, + MANAGER, + OWNER + } + + /** + * Adds a member to the specified group with the given role. This function is idempotent; if the + * member already exists in the group, then it returns normally. If the group doesn't exist, then + * it is created. + */ + public void addMemberToGroup(String groupKey, String email, Role role) throws IOException; + + /** + * Removes a member from the specified group, or throws {@link GoogleJsonResponseException} if the + * member doesn't exist. + */ + public void removeMemberFromGroup(String groupKey, String email) throws IOException; + + /** + * Returns all of the members of the specified group. Note that it gets members only; not owners + * or managers. Returns an empty set if the group in question does not exist. + */ + public Set getMembersOfGroup(String groupKey) throws IOException; + + /** + * Creates a group with the given email address (groupKey) that is open for external members to + * join, and returns it. This function is idempotent; if the given group already exists, then this + * function returns as normal without error (and without modifying the existing group in any way, + * including permissions on who is able to join). The configured admin owner for the Google App is + * automatically added as an owner. + */ + public Group createGroup(String groupKey) throws IOException; +} diff --git a/java/com/google/domain/registry/groups/GroupsModule.java b/java/com/google/domain/registry/groups/GroupsModule.java new file mode 100644 index 000000000..afee86031 --- /dev/null +++ b/java/com/google/domain/registry/groups/GroupsModule.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.groups; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module for groups package. */ +@Module +public final class GroupsModule { + + @Provides + static GroupsConnection provideGroupsConnection(DirectoryGroupsConnection connection) { + return connection; + } +} diff --git a/java/com/google/domain/registry/groups/GroupssettingsModule.java b/java/com/google/domain/registry/groups/GroupssettingsModule.java new file mode 100644 index 000000000..4ff5251ab --- /dev/null +++ b/java/com/google/domain/registry/groups/GroupssettingsModule.java @@ -0,0 +1,61 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.groups; + +import static dagger.Provides.Type.SET_VALUES; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.services.groupssettings.Groupssettings; +import com.google.api.services.groupssettings.GroupssettingsScopes; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.DelegatedOAuthScopes; + +import dagger.Module; +import dagger.Provides; + +import java.util.Set; + +import javax.inject.Named; + +/** + * Dagger module for the Google {@link Groupssettings} service. + * + * @see com.google.domain.registry.config.ConfigModule + * @see com.google.domain.registry.request.Modules.UrlFetchTransportModule + * @see com.google.domain.registry.request.Modules.Jackson2Module + * @see com.google.domain.registry.request.Modules.AppIdentityCredentialModule + * @see com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule + */ +@Module +public final class GroupssettingsModule { + + /** Provides OAuth2 scopes for the Groupssettings service needed by Domain Registry. */ + @Provides(type = SET_VALUES) + @DelegatedOAuthScopes + static Set provideGroupssettingsOAuthScopes() { + return ImmutableSet.of(GroupssettingsScopes.APPS_GROUPS_SETTINGS); + } + + @Provides + static Groupssettings provideGroupssettings( + @Named("delegatedAdmin") GoogleCredential credential, + @Config("projectId") String projectId) { + return new Groupssettings + .Builder(credential.getTransport(), credential.getJsonFactory(), credential) + .setApplicationName(projectId) + .build(); + } +} diff --git a/java/com/google/domain/registry/idn/Arabic-IDN.txt b/java/com/google/domain/registry/idn/Arabic-IDN.txt new file mode 100644 index 000000000..efc200502 --- /dev/null +++ b/java/com/google/domain/registry/idn/Arabic-IDN.txt @@ -0,0 +1,76 @@ +# Registry: Charleston Road Registry Inc. +# Script: Arabic +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Arabic script. +# Registrations using either Arabic-Indic or Arabic digits are allowed, +# but digit types are not allowed to be mixed. Homogeneity is enforced +# by the registry. + +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0660 # ARABIC-INDIC DIGIT ZERO +U+0661 # ARABIC-INDIC DIGIT ONE +U+0662 # ARABIC-INDIC DIGIT TWO +U+0663 # ARABIC-INDIC DIGIT THREE +U+0664 # ARABIC-INDIC DIGIT FOUR +U+0665 # ARABIC-INDIC DIGIT FIVE +U+0666 # ARABIC-INDIC DIGIT SIX +U+0667 # ARABIC-INDIC DIGIT SEVEN +U+0668 # ARABIC-INDIC DIGIT EIGHT +U+0669 # ARABIC-INDIC DIGIT NINE +U+0621 # ARABIC LETTER HAMZAH +U+0622 # ARABIC LETTER MADDAH ON ALEF +U+0623 # ARABIC LETTER HAMZAH ON ALEF +U+0624 # ARABIC LETTER HAMZAH ON WAW +U+0625 # ARABIC LETTER HAMZAH UNDER ALEF +U+0626 # ARABIC LETTER HAMZAH ON YA +U+0627 # ARABIC LETTER ALEF +U+0628 # ARABIC LETTER BAA +U+0629 # ARABIC LETTER TAA MARBUTAH +U+062A # ARABIC LETTER TAA +U+062B # ARABIC LETTER THAA +U+062C # ARABIC LETTER JEEM +U+062D # ARABIC LETTER HAA +U+062E # ARABIC LETTER KHAA +U+062F # ARABIC LETTER DAL +U+0630 # ARABIC LETTER THAL +U+0631 # ARABIC LETTER RA +U+0632 # ARABIC LETTER ZAIN +U+0633 # ARABIC LETTER SEEN +U+0634 # ARABIC LETTER SHEEN +U+0635 # ARABIC LETTER SAD +U+0636 # ARABIC LETTER DAD +U+0637 # ARABIC LETTER TAH +U+0638 # ARABIC LETTER DHAH +U+0639 # ARABIC LETTER AIN +U+063A # ARABIC LETTER GHAIN +U+063B # ARABIC LETTER KEHEH WITH TWO DOTS ABOVE +U+063C # ARABIC LETTER KEHEH WITH THREE DOTS BELOW +U+063D # ARABIC LETTER FARSI YEH WITH INVERTED V +U+063E # ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE +U+063F # ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE +U+0641 # ARABIC LETTER FA +U+0642 # ARABIC LETTER QAF +U+0643 # ARABIC LETTER CAF +U+0644 # ARABIC LETTER LAM +U+0645 # ARABIC LETTER MEEM +U+0646 # ARABIC LETTER NOON +U+0647 # ARABIC LETTER HA +U+0648 # ARABIC LETTER WAW +U+0649 # ARABIC LETTER ALEF MAQSURAH +U+064A # ARABIC LETTER YA diff --git a/java/com/google/domain/registry/idn/Armenian-IDN.txt b/java/com/google/domain/registry/idn/Armenian-IDN.txt new file mode 100644 index 000000000..cb7d58c88 --- /dev/null +++ b/java/com/google/domain/registry/idn/Armenian-IDN.txt @@ -0,0 +1,61 @@ +# Registry: Charleston Road Registry Inc. +# Script: Armenian +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# +# Notes: This table describes codepoints allowed for the Armenian script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0561 # ARMENIAN SMALL LETTER AYB +U+0562 # ARMENIAN SMALL LETTER BEN +U+0563 # ARMENIAN SMALL LETTER GIM +U+0564 # ARMENIAN SMALL LETTER DA +U+0565 # ARMENIAN SMALL LETTER ECH +U+0566 # ARMENIAN SMALL LETTER ZA +U+0567 # ARMENIAN SMALL LETTER EH +U+0568 # ARMENIAN SMALL LETTER ET +U+0569 # ARMENIAN SMALL LETTER TO +U+056A # ARMENIAN SMALL LETTER ZHE +U+056B # ARMENIAN SMALL LETTER INI +U+056C # ARMENIAN SMALL LETTER LIWN +U+056D # ARMENIAN SMALL LETTER XEH +U+056E # ARMENIAN SMALL LETTER CA +U+056F # ARMENIAN SMALL LETTER KEN +U+0570 # ARMENIAN SMALL LETTER HO +U+0571 # ARMENIAN SMALL LETTER JA +U+0572 # ARMENIAN SMALL LETTER LAD +U+0573 # ARMENIAN SMALL LETTER CHEH +U+0574 # ARMENIAN SMALL LETTER MEN +U+0575 # ARMENIAN SMALL LETTER YI +U+0576 # ARMENIAN SMALL LETTER NOW +U+0577 # ARMENIAN SMALL LETTER SHA +U+0578 # ARMENIAN SMALL LETTER VO +U+0579 # ARMENIAN SMALL LETTER CHA +U+057A # ARMENIAN SMALL LETTER PEH +U+057B # ARMENIAN SMALL LETTER JHEH +U+057C # ARMENIAN SMALL LETTER RA +U+057D # ARMENIAN SMALL LETTER SEH +U+057E # ARMENIAN SMALL LETTER VEW +U+057F # ARMENIAN SMALL LETTER TIWN +U+0580 # ARMENIAN SMALL LETTER REH +U+0581 # ARMENIAN SMALL LETTER CO +U+0582 # ARMENIAN SMALL LETTER YIWN +U+0583 # ARMENIAN SMALL LETTER PIWR +U+0584 # ARMENIAN SMALL LETTER KEH +U+0585 # ARMENIAN SMALL LETTER OH +U+0586 # ARMENIAN SMALL LETTER FEH diff --git a/java/com/google/domain/registry/idn/BUILD b/java/com/google/domain/registry/idn/BUILD new file mode 100644 index 000000000..17f9f5013 --- /dev/null +++ b/java/com/google/domain/registry/idn/BUILD @@ -0,0 +1,4 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + diff --git a/java/com/google/domain/registry/idn/Bengali-IDN.txt b/java/com/google/domain/registry/idn/Bengali-IDN.txt new file mode 100644 index 000000000..27d1ceea2 --- /dev/null +++ b/java/com/google/domain/registry/idn/Bengali-IDN.txt @@ -0,0 +1,102 @@ +# Registry: Charleston Road Registry Inc. +# Script: Bengali +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Bengali script. +# +# Common codepoints (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0981 # BENGALI SIGN CANDRABINDU +U+0982 # BENGALI SIGN ANUSVARA +U+0983 # BENGALI SIGN VISARGA +U+0985 # BENGALI LETTER A +U+0986 # BENGALI LETTER AA +U+0987 # BENGALI LETTER I +U+0988 # BENGALI LETTER II +U+0989 # BENGALI LETTER U +U+098A # BENGALI LETTER UU +U+098B # BENGALI LETTER VOCALIC R +U+098C # BENGALI LETTER VOCALIC L +U+098F # BENGALI LETTER E +U+0990 # BENGALI LETTER AI +U+0993 # BENGALI LETTER O +U+0994 # BENGALI LETTER AU +U+0995 # BENGALI LETTER KA +U+0996 # BENGALI LETTER KHA +U+0997 # BENGALI LETTER GA +U+0998 # BENGALI LETTER GHA +U+0999 # BENGALI LETTER NGA +U+099A # BENGALI LETTER CA +U+099B # BENGALI LETTER CHA +U+099C # BENGALI LETTER JA +U+099D # BENGALI LETTER JHA +U+099E # BENGALI LETTER NYA +U+099F # BENGALI LETTER TTA +U+09A0 # BENGALI LETTER TTHA +U+09A1 # BENGALI LETTER DDA +U+09A2 # BENGALI LETTER DDHA +U+09A3 # BENGALI LETTER NNA +U+09A4 # BENGALI LETTER TA +U+09A5 # BENGALI LETTER THA +U+09A6 # BENGALI LETTER DA +U+09A7 # BENGALI LETTER DHA +U+09A8 # BENGALI LETTER NA +U+09AA # BENGALI LETTER PA +U+09AB # BENGALI LETTER PHA +U+09AC # BENGALI LETTER BA +U+09AD # BENGALI LETTER BHA +U+09AE # BENGALI LETTER MA +U+09AF # BENGALI LETTER YA +U+09B0 # BENGALI LETTER RA +U+09B2 # BENGALI LETTER LA +U+09B6 # BENGALI LETTER SHA +U+09B7 # BENGALI LETTER SSA +U+09B8 # BENGALI LETTER SA +U+09B9 # BENGALI LETTER HA +U+09BC # BENGALI SIGN NUKTA +U+09BD # BENGALI SIGN AVAGRAHA +U+09BE # BENGALI VOWEL SIGN AA +U+09BF # BENGALI VOWEL SIGN I +U+09C0 # BENGALI VOWEL SIGN II +U+09C1 # BENGALI VOWEL SIGN U +U+09C2 # BENGALI VOWEL SIGN UU +U+09C3 # BENGALI VOWEL SIGN VOCALIC R +U+09C4 # BENGALI VOWEL SIGN VOCALIC RR +U+09C7 # BENGALI VOWEL SIGN E +U+09C8 # BENGALI VOWEL SIGN AI +U+09CB # BENGALI VOWEL SIGN O +U+09CC # BENGALI VOWEL SIGN AU +U+09CD # BENGALI SIGN VIRAMA +U+09CE # BENGALI LETTER KHANDA TA +U+09D7 # BENGALI AU LENGTH MARK +U+09E0 # BENGALI LETTER VOCALIC RR +U+09E1 # BENGALI LETTER VOCALIC LL +U+09E2 # BENGALI VOWEL SIGN VOCALIC L +U+09E3 # BENGALI VOWEL SIGN VOCALIC LL +U+09E6 # BENGALI DIGIT ZERO +U+09E7 # BENGALI DIGIT ONE +U+09E8 # BENGALI DIGIT TWO +U+09E9 # BENGALI DIGIT THREE +U+09EA # BENGALI DIGIT FOUR +U+09EB # BENGALI DIGIT FIVE +U+09EC # BENGALI DIGIT SIX +U+09ED # BENGALI DIGIT SEVEN +U+09EE # BENGALI DIGIT EIGHT +U+09EF # BENGALI DIGIT NINE +U+09F0 # BENGALI LETTER RA WITH MIDDLE DIAGONAL +U+09F1 # BENGALI LETTER VA WITH LOWER DIAGONAL diff --git a/java/com/google/domain/registry/idn/Chinese-IDN.txt b/java/com/google/domain/registry/idn/Chinese-IDN.txt new file mode 100644 index 000000000..2edc09086 --- /dev/null +++ b/java/com/google/domain/registry/idn/Chinese-IDN.txt @@ -0,0 +1,19928 @@ +# Registry: Charleston Road Registry Inc. +# Script: Chinese +# Version: 1.0 +# Effective Date: 04-12-2012 +# +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Chinese script. + +Reference 0 Unicode 3.2 +Reference 1 A Complete Set of Simplified Chinese Characters +Reference 2 Chinese Variants Collation Table +Reference 3 Chinese Big Dictionary +Reference 4 Chinese Relationship Table for Unihan Project +Reference 5 GB2312 +Reference 6 General Table for Modern Chinese +Reference 7 International Chinese Standard Big Dictionary +Reference 8 Unihan Database +Reference 9 BIG5 + +U+002D(0);U+002D(0); +U+0030(0);U+0030(0); +U+0031(0);U+0031(0); +U+0032(0);U+0032(0); +U+0033(0);U+0033(0); +U+0034(0);U+0034(0); +U+0035(0);U+0035(0); +U+0036(0);U+0036(0); +U+0037(0);U+0037(0); +U+0038(0);U+0038(0); +U+0039(0);U+0039(0); +U+0061(0);U+0061(0); +U+0062(0);U+0062(0); +U+0063(0);U+0063(0); +U+0064(0);U+0064(0); +U+0065(0);U+0065(0); +U+0066(0);U+0066(0); +U+0067(0);U+0067(0); +U+0068(0);U+0068(0); +U+0069(0);U+0069(0); +U+006A(0);U+006A(0); +U+006B(0);U+006B(0); +U+006C(0);U+006C(0); +U+006D(0);U+006D(0); +U+006E(0);U+006E(0); +U+006F(0);U+006F(0); +U+0070(0);U+0070(0); +U+0071(0);U+0071(0); +U+0072(0);U+0072(0); +U+0073(0);U+0073(0); +U+0074(0);U+0074(0); +U+0075(0);U+0075(0); +U+0076(0);U+0076(0); +U+0077(0);U+0077(0); +U+0078(0);U+0078(0); +U+0079(0);U+0079(0); +U+007A(0);U+007A(0); +U+3447(0);U+3447(1,3);U+3473(1,3) +U+3473(0);U+3447(1,3);U+3447(1,3) +U+359E(0);U+359E(1,3);U+558E(1,3) +U+360E(0);U+360E(1,3);U+361A(1,3) +U+361A(0);U+360E(1,3);U+360E(1,3) +U+3918(0);U+3918(1);U+396E(1) +U+396E(0);U+3918(1);U+3918(1) +U+39CF(0);U+39CF(1,3);U+6386(1,3) +U+39D0(0);U+39D0(1,3);U+3A73(1,3) +U+39DF(0);U+39DF(1,3);U+64D3(1,3) +U+3A73(0);U+39D0(1,3);U+39D0(1,3) +U+3B4E(0);U+3B4E(1,3);U+68E1(1,3) +U+3C6E(0);U+3C6E(1,3);U+6BA8(1,3) + +U+3CE0(0);U+3CE0(1,3);U+6FBE(1,3) +U+4056(0);U+4056(1,3);U+779C(1,3) +U+415F(0);U+415F(1,3);U+7A47(1,3) +U+4337(0);U+4337(1,3);U+7D2C(1,3),U+7EF8(1,3,4),U+7DA2(1,3,4) +U+43AC(0);U+43AC(1,3);U+43B1(1,3) +U+43B1(0);U+43AC(1,3);U+43AC(1,3) +U+43DD(0);U+43DD(1,3);U+819E(1,3) +U+44D6(0);U+44D6(1,3);U+85ED(1,3) +U+464C(0);U+464C(1,3);U+4661(1,3) +U+4661(0);U+464C(1,3);U+464C(1,3) +U+4723(0);U+4723(1,3);U+8A22(1,3) +U+4729(0);U+4729(1,3);U+8B8C(1,3) +U+477C(0);U+478D(1);U+478D(1) +U+478D(0);U+478D(1);U+477C(1,3) +U+4947(0);U+4982(1,3);U+4982(1,3) +U+497A(0);U+497A(1,3);U+91FE(1,3) +U+497D(0);U+497D(1,3);U+93FA(1,3) +U+4982(0);U+4982(1,3);U+4947(1,3) +U+4983(0);U+4983(1,3);U+942F(1,3) +U+4985(0);U+4985(1,3);U+9425(1,3) +U+4986(0);U+4986(1,3);U+9481(1,3) +U+499B(0);U+49B6(1,3);U+49B6(1,3) +U+499F(0);U+49B7(1,3);U+49B7(1,3) +U+49B6(0);U+49B6(1,3);U+499B(1,3) +U+49B7(0);U+49B7(1,3);U+499F(1,3) +U+4C77(0);U+4CA3(1,3);U+4CA3(1,3) +U+4C9F(0);U+4C9F(1,3);U+9BA3(1,3) +U+4CA0(0);U+4CA0(1,3);U+9C06(1,3) +U+4CA1(0);U+4CA1(1,3);U+9C0C(1,3),U+9C0D(1,3),U+9CC5(1,3) +U+4CA2(0);U+4CA2(1,3);U+9C27(1,3) +U+4CA3(0);U+4CA3(1,3);U+4C77(1,3) +U+4D13(0);U+4D13(1,3);U+9CFE(1,3) +U+4D14(0);U+4D14(1,3);U+9D41(1,3) +U+4D15(0);U+4D15(1,3);U+9D37(1,3) +U+4D16(0);U+4D16(1,3);U+9D84(1,3) +U+4D17(0);U+4D17(1,3);U+9DAA(1,3) +U+4D18(0);U+4D18(1,3);U+9DC8(3),U+9DC9(1,3) +U+4D19(0);U+4D19(1,3);U+9DFF(3),U+9E0A(1,3) +U+4DAE(0);U+4DAE(1,3);U+9F91(1,3) +U+4E00(0);U+4E00(5);U+58F9(3),U+5F0C(3),U+58F1(3,4) +U+4E01(0);U+4E01(5); +U+4E02(0);U+4E02(0); +U+4E03(0);U+4E03(5); +U+4E04(0);U+4E0A(3);U+4E0A(3),U+4EE9(3,4) +U+4E05(0);U+4E0B(3);U+4E0B(3) +U+4E06(0);U+4E06(0); +U+4E07(0);U+4E07(1,3);U+842C(1,3) +U+4E08(0);U+4E08(5); +U+4E09(0);U+4E09(5); +U+4E0A(0);U+4E0A(5);U+4E04(3),U+4EE9(4) +U+4E0B(0);U+4E0B(5);U+4E05(3) +U+4E0C(0);U+4E0C(5);U+4E93(4),U+5176(3) +U+4E0D(0);U+4E0D(5); +U+4E0E(0);U+4E0E(1,3);U+8207(1,3) +U+4E0F(0);U+4E10(4);U+4E10(4) +U+4E10(0);U+4E10(5);U+4E0F(4) +U+4E11(0);U+4E11(1,3);U+919C(1,3,4) +U+4E13(0);U+4E13(1,3);U+5C08(1,3) +U+4E14(0);U+4E14(5); +U+4E15(0);U+4E15(5); +U+4E16(0);U+4E16(5);U+4E17(3),U+534B(3) +U+4E17(0);U+4E16(3);U+4E16(3),U+534B(3) +U+4E18(0);U+4E18(5);U+4E20(3),U+5775(2,3) + +U+4E19(0);U+4E19(5); +U+4E1A(0);U+4E1A(1,3);U+696D(1,3) +U+4E1B(0);U+4E1B(1,3);U+53E2(1,3,4),U+6B09(3),U+85C2(3) +U+4E1C(0);U+4E1C(1,3);U+6771(1,3) +U+4E1D(0);U+4E1D(1,3);U+7D72(1,3),U+7CF8(1,3),U+7CF9(1,3,8,9),U+7E9F(1,3,8,9) +U+4E1E(0);U+4E1E(5); +U+4E1F(0);U+4E22(3,4);U+4E22(3,4) +U+4E20(0);U+4E18(3);U+4E18(3),U+5775(2,3) +U+4E21(0);U+4E24(3);U+4E24(3),U+5169(3) +U+4E22(0);U+4E22(5);U+4E1F(3,4) +U+4E23(0);U+9149(3);U+9149(3) +U+4E24(0);U+4E24(1,3);U+4E21(3),U+5169(1,3) +U+4E25(0);U+4E25(1,3);U+53B3(4),U+56B4(1,3) +U+4E26(0);U+5E76(2);U+4F75(3),U+5E76(2),U+7ADD(3),U+5002(3),U+5E77(2,3,4) +U+4E27(0);U+4E27(1,3);U+55AA(1,3) +U+4E28(0);U+4E28(5); +U+4E2A(0);U+4E2A(1,3);U+500B(1,3),U+7B87(4) +U+4E2B(0);U+4E2B(5); +U+4E2C(0);U+4E2C(5);U+723F(8,9) +U+4E2D(0);U+4E2D(5); +U+4E2E(0);U+4E2E(0); +U+4E2F(0);U+4E2F(0); +U+4E30(0);U+4E30(1,3);U+8C4A(3),U+8C50(1,3,4) +U+4E31(0);U+4E31(0); +U+4E32(0);U+4E32(5);U+8CD7(4) +U+4E33(0);U+4E33(0); +U+4E34(0);U+4E34(1,3);U+81E8(1,3) +U+4E35(0);U+4E35(0); +U+4E36(0);U+4E36(5); +U+4E37(0);U+4E37(0); +U+4E38(0);U+4E38(5); +U+4E39(0);U+4E39(5); +U+4E3A(0);U+4E3A(1,3);U+7232(1,3),U+70BA(3) +U+4E3B(0);U+4E3B(5); +U+4E3C(0);U+4E95(3);U+4E95(3) +U+4E3D(0);U+4E3D(1,3);U+9E97(1,3) +U+4E3E(0);U+4E3E(1,3);U+6319(4),U+64E7(4),U+8209(1,3) +U+4E3F(0);U+4E3F(5); +U+4E40(0);U+4E40(0); +U+4E41(0);U+4E41(0); +U+4E42(0);U+4E42(3); +U+4E43(0);U+4E43(5);U+5EFC(2,3),U+8FFA(2) +U+4E44(0);U+4E44(0); +U+4E45(0);U+4E45(5);U+4E46(3) +U+4E46(0);U+4E45(3);U+4E45(3) +U+4E47(0);U+4E47(5); +U+4E48(0);U+4E48(1,3,4);U+5E7A(3),U+5E85(4),U+9EBC(4),U+9EBD(1,3) +U+4E49(0);U+4E49(1,3);U+7F9B(3),U+7FA9(1,3) +U+4E4A(0);U+4E4A(0); +U+4E4B(0);U+4E4B(5); +U+4E4C(0);U+4E4C(1,3);U+70CF(1,3) +U+4E4D(0);U+4E4D(5); +U+4E4E(0);U+4E4E(5); +U+4E4F(0);U+4E4F(5); +U+4E50(0);U+4E50(1,3);U+697D(3),U+6A02(1,3) +U+4E51(0);U+4E51(3); +U+4E52(0);U+4E52(5); +U+4E53(0);U+4E53(5); +U+4E54(0);U+4E54(1,3);U+55AC(1,3) +U+4E56(0);U+4E56(5); +U+4E57(0);U+4E58(2,3);U+4E58(2,3) +U+4E58(0);U+4E58(5);U+4E57(2,3) +U+4E59(0);U+4E59(5); + +U+4E5A(0);U+4E5A(0); +U+4E5B(0);U+4E5B(0); +U+4E5C(0);U+4E5C(5); +U+4E5D(0);U+4E5D(5); +U+4E5E(0);U+4E5E(5); +U+4E5F(0);U+4E5F(5); +U+4E60(0);U+4E60(1,3);U+7FD2(1,3) +U+4E61(0);U+4E61(1,3);U+90F7(3),U+9109(1,3),U+9115(4) +U+4E62(0);U+4E62(0); +U+4E63(0);U+4E63(0); +U+4E64(0);U+4E64(0); +U+4E65(0);U+4E65(0); +U+4E66(0);U+4E66(1,3);U+66F8(1,3) +U+4E67(0);U+4E67(0); +U+4E69(0);U+4E69(5);U+7A3D(3) +U+4E6A(0);U+4E6A(0); +U+4E6B(0);U+4E6B(0); +U+4E6C(0);U+4E6C(0); +U+4E6D(0);U+4E6D(0); +U+4E6E(0);U+4E6E(0); +U+4E6F(0);U+4E6F(0); +U+4E70(0);U+4E70(1,3);U+8CB7(1,3) +U+4E71(0);U+4E71(1,3);U+4E7F(3),U+4E82(1,3) +U+4E72(0);U+4E72(0); +U+4E73(0);U+4E73(5); +U+4E74(0);U+4E74(0); +U+4E75(0);U+4E75(0); +U+4E76(0);U+4E76(0); +U+4E77(0);U+4E77(0); +U+4E78(0);U+4E78(4); +U+4E7A(0);U+4E7A(0); +U+4E7B(0);U+4E7B(0); +U+4E7C(0);U+4E7C(0); +U+4E7D(0);U+4E7D(0); +U+4E7E(0);U+4E7E(1,3),U+5E72(1,3);U+4E81(2),U+5E72(1,3),U+6F27(3),U+5E79(1,3,4),U+69A6(1,3,4) + +U+4E7F(0);U+4E71(3);U+4E71(3),U+4E82(1,3) +U+4E80(0);U+9F9F(4);U+9F9C(4),U+9F9F(4) +U+4E81(0);U+5E72(4);U+4E7E(2),U+5E72(4),U+6F27(2,3),U+5E79(1,2,3,4),U+69A6(1,2,3,4) +U+4E82(0);U+4E71(1,3);U+4E71(1,3),U+4E7F(1,3) +U+4E83(0);U+4E83(0); +U+4E84(0);U+4E84(0); +U+4E85(0);U+4E85(0); +U+4E86(0);U+4E86(1,3);U+66B8(7),U+77AD(1,3,4) +U+4E87(0);U+4E87(0); +U+4E88(0);U+4E88(5); +U+4E89(0);U+4E89(5);U+722D(3,4) +U+4E8B(0);U+4E8B(5); +U+4E8C(0);U+4E8C(5);U+5F0D(3),U+8CB3(3),U+8CAE(3,4),U+8D30(1,3) +U+4E8D(0);U+4E8D(5); +U+4E8E(0);U+4E8E(5);U+65BC(4),U+6275(3,4) +U+4E8F(0);U+4E8F(1,3);U+8667(1,3) +U+4E90(0);U+4E90(0); +U+4E91(0);U+4E91(1,3);U+96F2(1,3,4) +U+4E92(0);U+4E92(5); +U+4E93(0);U+4E93(5);U+4E0C(4),U+5176(3) +U+4E94(0);U+4E94(5);U+4F0D(3) +U+4E95(0);U+4E95(5);U+4E3C(3) +U+4E97(0);U+5C81(3);U+5C81(3),U+6B72(3),U+6B73(7) +U+4E98(0);U+4E98(5);U+4E99(2) +U+4E99(0);U+4E98(2);U+4E98(2) +U+4E9A(0);U+4E9A(1,3);U+4E9C(3),U+4E9E(1,3) +U+4E9B(0);U+4E9B(5); + +U+4E9C(0);U+4E9A(3);U+4E9A(3),U+4E9E(3) +U+4E9D(0);U+9F50(3,4);U+9F4A(3),U+9F50(3,4),U+6589(3) +U+4E9E(0);U+4E9A(1,3);U+4E9A(1,3),U+4E9C(3) +U+4E9F(0);U+4E9F(5); +U+4EA0(0);U+4EA0(5); +U+4EA1(0);U+4EA1(5);U+4EBE(2,3),U+5166(3) +U+4EA2(0);U+4EA2(5); +U+4EA4(0);U+4EA4(5); +U+4EA5(0);U+4EA5(5); +U+4EA6(0);U+4EA6(5); +U+4EA7(0);U+4EA7(1,3,4);U+7522(4),U+7523(1,3) +U+4EA8(0);U+4EA8(5); +U+4EA9(0);U+4EA9(1,3);U+7546(4),U+755D(1,3),U+756E(4) +U+4EAA(0);U+4EAA(0); +U+4EAB(0);U+4EAB(5);U+4EAF(2,3) +U+4EAC(0);U+4EAC(5);U+4EB0(4) +U+4EAD(0);U+4EAD(5); +U+4EAE(0);U+4EAE(5); +U+4EAF(0);U+4EAB(2,3);U+4EAB(2,3) +U+4EB0(0);U+4EAC(4);U+4EAC(4) +U+4EB1(0);U+591C(2,3);U+591C(2,3) +U+4EB2(0);U+4EB2(1,3);U+89AA(1,3) +U+4EB3(0);U+4EB3(5); +U+4EB4(0);U+4EB4(0); +U+4EB5(0);U+4EB5(1,3);U+893B(1,3) +U+4EB6(0);U+4EB6(4); +U+4EB7(0);U+5EC9(2);U+5EC9(2),U+899D(2,4) +U+4EB8(0);U+4EB8(4);U+56B2(4) +U+4EB9(0);U+4EB9(4);U+6596(4) +U+4EBA(0);U+4EBA(5); +U+4EBB(0);U+4EBB(5); +U+4EBD(0);U+4EBD(0); +U+4EBE(0);U+4EA1(2,3);U+4EA1(2,3),U+5166(4) +U+4EBF(0);U+4EBF(1,3);U+5104(1,3) +U+4EC0(0);U+4EC0(5); +U+4EC1(0);U+4EC1(5);U+5FC8(4) +U+4EC2(0);U+4EC2(5); +U+4EC3(0);U+4EC3(5); +U+4EC4(0);U+4EC4(5);U+5E82(3) +U+4EC5(0);U+4EC5(1,3);U+50C5(1,3) +U+4EC6(0);U+4EC6(1,3);U+50D5(1,3) +U+4EC7(0);U+4EC7(5);U+8B8E(3),U+8B90(2),U+96E0(1,3) +U+4EC8(0);U+4EC8(0); +U+4EC9(0);U+4EC9(5); +U+4ECA(0);U+4ECA(5); +U+4ECB(0);U+4ECB(5); +U+4ECD(0);U+4ECD(5); +U+4ECE(0);U+4ECE(1,3);U+5F93(3),U+5F9E(1,3) +U+4ECF(0);U+4F5B(3);U+4F5B(3),U+5F7F(2,3),U+9AF4(2,3) +U+4ED0(0);U+4ED0(0); +U+4ED1(0);U+4ED1(1,3);U+4F96(1,3),U+5D18(4),U+5D19(4) +U+4ED2(0);U+4ED2(0); +U+4ED3(0);U+4ED3(1,3);U+5009(1,3) +U+4ED4(0);U+4ED4(5); +U+4ED5(0);U+4ED5(5); +U+4ED6(0);U+4ED6(5);U+6039(3) +U+4ED7(0);U+4ED7(5); +U+4ED8(0);U+4ED8(5); +U+4ED9(0);U+4ED9(5);U+4EDA(3),U+50CA(2,3) +U+4EDA(0);U+4ED9(3);U+4ED9(3),U+50CA(2,3) +U+4EDB(0);U+4EDB(0); +U+4EDC(0);U+4EDC(0); +U+4EDD(0);U+4EDD(5);U+540C(2,3),U+8855(2,3) + +U+4EDE(0);U+4EDE(5); +U+4EDF(0);U+4EDF(5);U+5343(3),U+97C6(1,3,4) +U+4EE0(0);U+4EE0(0); +U+4EE1(0);U+4EE1(5); +U+4EE2(0);U+4EE2(0); +U+4EE3(0);U+4EE3(5); +U+4EE4(0);U+4EE4(5); +U+4EE5(0);U+4EE5(5); +U+4EE6(0);U+4EE6(0); +U+4EE8(0);U+4EE8(5); +U+4EE9(0);U+4E0A(4);U+4E0A(4),U+4E04(0,3,4) +U+4EEA(0);U+4EEA(1,3);U+5100(1,3) +U+4EEB(0);U+4EEB(5); +U+4EEC(0);U+4EEC(1,3);U+5011(1,3) +U+4EEF(0);U+4EEF(3); +U+4EF0(0);U+4EF0(5);U+4F52(3) +U+4EF1(0);U+4EF1(0); +U+4EF2(0);U+4EF2(5);U+72C6(3) +U+4EF3(0);U+4EF3(5); +U+4EF4(0);U+4EF4(0); +U+4EF5(0);U+4EF5(5); +U+4EF6(0);U+4EF6(5); +U+4EF7(0);U+4EF7(1,3);U+4FA1(4),U+50F9(1,3) +U+4EFB(0);U+4EFB(5); +U+4EFD(0);U+4EFD(5);U+5F6C(3) +U+4EFF(0);U+4EFF(5);U+5023(2,3),U+5F77(4),U+9AE3(2,3) +U+4F00(0);U+4F00(0); +U+4F01(0);U+4F01(5); +U+4F02(0);U+6C9B(3);U+6C9B(3) +U+4F03(0);U+4F03(0); +U+4F04(0);U+4F04(0); +U+4F05(0);U+4F05(0); +U+4F06(0);U+4F06(0); +U+4F08(0);U+4F08(0); +U+4F09(0);U+4F09(5); +U+4F0A(0);U+4F0A(5);U+6D22(3) +U+4F0B(0);U+4F0B(3);U+89D9(3) +U+4F0C(0);U+4F0C(0); +U+4F0D(0);U+4F0D(5);U+4E94(3) +U+4F0E(0);U+4F0E(5); +U+4F0F(0);U+4F0F(5); +U+4F10(0);U+4F10(5); +U+4F11(0);U+4F11(5); +U+4F12(0);U+4F12(0); +U+4F13(0);U+4F13(0); +U+4F14(0);U+628C(4);U+628C(4) +U+4F15(0);U+592B(3);U+592B(3) +U+4F17(0);U+4F17(1,3);U+773E(4),U+8846(1,3) +U+4F18(0);U+4F18(1,3);U+512A(1,3) +U+4F19(0);U+4F19(1,3);U+5925(1,3) +U+4F1A(0);U+4F1A(1,3);U+6703(1,3) +U+4F1B(0);U+4F1B(1,3);U+50B4(1,3) +U+4F1C(0);U+5005(3);U+5005(3) +U+4F1D(0);U+4F1D(0); +U+4F1E(0);U+4F1E(1,3);U+5098(1,3),U+7E56(4) +U+4F1F(0);U+4F1F(1,3);U+5049(1,3) +U+4F20(0);U+4F20(1,3);U+50B3(1,3) +U+4F21(0);U+4F21(4);U+4FE5(4) +U+4F22(0);U+4F22(5); +U+4F23(0);U+4F23(4);U+4FD4(4) +U+4F24(0);U+4F24(1,3);U+50B7(1,3) +U+4F25(0);U+4F25(1,3);U+5000(1,3) +U+4F26(0);U+4F26(1,3);U+502B(1,3) + +U+4F27(0);U+4F27(1,3);U+5096(1,3) +U+4F29(0);U+4FE1(7);U+4FE1(7) +U+4F2A(0);U+4F2A(1,3,4);U+507D(4),U+50DE(1,3) +U+4F2B(0);U+4F2B(5);U+4F47(2,3) +U+4F2C(0);U+4F2C(0); +U+4F2D(0);U+4F2D(0); +U+4F2E(0);U+4F2E(0); +U+4F2F(0);U+4F2F(5); +U+4F30(0);U+4F30(5); +U+4F32(0);U+4F32(5);U+4F60(3),U+511E(3),U+59B3(2,3),U+5976(2,3),U+5B2D(2,3) +U+4F33(0);U+4F33(0); +U+4F34(0);U+4F34(5); +U+4F36(0);U+4F36(5); +U+4F38(0);U+4F38(5);U+62BB(3) +U+4F39(0);U+4F39(0); +U+4F3A(0);U+4F3A(5); +U+4F3B(0);U+4F3B(0); +U+4F3C(0);U+4F3C(5); +U+4F3D(0);U+4F3D(5); +U+4F3E(0);U+4F3E(3); +U+4F3F(0);U+4F3F(0); +U+4F41(0);U+4F41(0); +U+4F42(0);U+4F42(0); +U+4F43(0);U+4F43(5); +U+4F45(0);U+4F45(0); +U+4F46(0);U+4F46(5); +U+4F47(0);U+4F2B(2,3);U+4F2B(2,3) +U+4F48(0);U+5E03(2,3);U+5E03(2,3) +U+4F49(0);U+4F49(0); +U+4F4A(0);U+4F4A(0); +U+4F4B(0);U+4F4B(0); +U+4F4C(0);U+4F4C(0); +U+4F4D(0);U+4F4D(5); +U+4F4E(0);U+4F4E(5); +U+4F4F(0);U+4F4F(5); +U+4F50(0);U+4F50(5); +U+4F51(0);U+4F51(5); +U+4F52(0);U+4EF0(3);U+4EF0(3) +U+4F53(0);U+4F53(1,3);U+8EB0(3),U+8EC6(3),U+9AB5(3),U+9AD4(1,3) +U+4F54(0);U+5360(2,3);U+5360(2,3) +U+4F55(0);U+4F55(5); +U+4F56(0);U+4F56(0); +U+4F57(0);U+4F57(5); +U+4F58(0);U+4F58(5); +U+4F59(0);U+4F59(1,3);U+9918(1,3),U+9980(1,3,4) +U+4F5A(0);U+4F5A(5); +U+4F5B(0);U+4F5B(5);U+4ECF(3),U+5F7F(2),U+9AF4(2) +U+4F5C(0);U+4F5C(5); +U+4F5D(0);U+4F5D(5);U+6010(3) +U+4F5E(0);U+4F5E(5);U+4FAB(4) +U+4F5F(0);U+4F5F(5); +U+4F60(0);U+4F60(5);U+4F32(3),U+511E(3),U+59B3(2,3),U+5976(2,3),U+5B2D(2,3) +U+4F61(0);U+4F61(0); +U+4F62(0);U+4F62(0); +U+4F63(0);U+4F63(1,3);U+50AD(1,3) +U+4F64(0);U+4F64(5); +U+4F65(0);U+4F65(1,3);U+50C9(1,3) +U+4F66(0);U+4F66(0); +U+4F67(0);U+4F67(5); +U+4F68(0);U+4F68(0); +U+4F69(0);U+4F69(5);U+73EE(4) +U+4F6A(0);U+5F8A(3);U+5F8A(3) +U+4F6B(0);U+4F6B(0); + +U+4F6C(0);U+4F6C(5);U+72EB(3) +U+4F6D(0);U+4F6D(0); +U+4F6E(0);U+4F6E(0); +U+4F6F(0);U+4F6F(5); +U+4F70(0);U+4F70(5); +U+4F72(0);U+4F72(0); +U+4F73(0);U+4F73(5); +U+4F74(0);U+4F74(5); +U+4F75(0);U+5E76(2);U+4E26(3),U+5002(3),U+5E76(2),U+7ADD(3),U+5E77(2,3,4) +U+4F76(0);U+4F76(5); +U+4F77(0);U+5F88(3);U+5F88(3) +U+4F78(0);U+4F78(3); +U+4F79(0);U+4F79(0); +U+4F7A(0);U+4F7A(0); +U+4F7B(0);U+4F7B(5); +U+4F7C(0);U+4F7C(5); +U+4F7D(0);U+4F7D(0); +U+4F7E(0);U+4F7E(5); +U+4F7F(0);U+4F7F(5); +U+4F80(0);U+4F80(0); +U+4F81(0);U+4F81(0); +U+4F82(0);U+4F82(3); +U+4F83(0);U+4F83(5); +U+4F84(0);U+4F84(5);U+59EA(2) +U+4F85(0);U+4F85(0); +U+4F86(0);U+6765(1,3);U+6765(1,3) +U+4F87(0);U+5937(3);U+5937(3) +U+4F88(0);U+4F88(5); +U+4F89(0);U+4F89(5); +U+4F8A(0);U+4F8A(0); +U+4F8B(0);U+4F8B(5); +U+4F8D(0);U+4F8D(5); +U+4F8F(0);U+4F8F(5); +U+4F90(0);U+4F90(3); +U+4F91(0);U+4F91(5); +U+4F92(0);U+5B89(3);U+5B89(3) +U+4F93(0);U+4F93(0); +U+4F94(0);U+4F94(5); +U+4F95(0);U+4F95(0); +U+4F96(0);U+4ED1(1,3);U+4ED1(1,3),U+5D18(2),U+5D19(2,3) +U+4F97(0);U+4F97(5); +U+4F98(0);U+8BE7(3);U+8BE7(3),U+8A6B(1,3) +U+4F99(0);U+4F99(3); +U+4F9A(0);U+4F9A(0); +U+4F9B(0);U+4F9B(5); +U+4F9C(0);U+4F9C(3); +U+4F9D(0);U+4F9D(5); +U+4F9E(0);U+4F9E(0); +U+4F9F(0);U+4F9F(0); +U+4FA0(0);U+4FA0(1,3);U+4FE0(1,3) +U+4FA1(0);U+4EF7(4);U+4EF7(4),U+50F9(8,9) +U+4FA3(0);U+4FA3(5);U+4FB6(4) +U+4FA4(0);U+4FA4(0); +U+4FA5(0);U+4FA5(1,3);U+50E5(1),U+510C(4),U+5FBA(3) +U+4FA6(0);U+4FA6(1,3);U+5075(1,3),U+9049(4) +U+4FA7(0);U+4FA7(1,3);U+5074(1,3) +U+4FA8(0);U+4FA8(1,3);U+50D1(1,3) +U+4FA9(0);U+4FA9(1,3);U+5108(1,3) +U+4FAA(0);U+4FAA(1,3);U+5115(1,3) +U+4FAB(0);U+4F5E(4);U+4F5E(4) +U+4FAC(0);U+4FAC(1,3);U+5102(1,3) +U+4FAE(0);U+4FAE(5); +U+4FAF(0);U+4FAF(5); + +U+4FB0(0);U+4FB0(0); +U+4FB1(0);U+4FB1(0); +U+4FB2(0);U+4FB2(0); +U+4FB3(0);U+4FB3(0); +U+4FB4(0);U+4FB4(0); +U+4FB5(0);U+4FB5(5); +U+4FB6(0);U+4FA3(4);U+4FA3(4) +U+4FB7(0);U+5C40(2);U+5C40(2),U+8DFC(2) +U+4FB8(0);U+4FB8(0); +U+4FB9(0);U+4FB9(0); +U+4FBA(0);U+4FBA(0); +U+4FBB(0);U+4FBB(0); +U+4FBC(0);U+4FBC(0); +U+4FBE(0);U+4FBE(0); +U+4FBF(0);U+4FBF(5); +U+4FC0(0);U+4FC0(0); +U+4FC1(0);U+4FE3(4);U+4FE3(4) +U+4FC2(0);U+7CFB(1,3);U+7CFB(1,3),U+7E6B(1,3,4) +U+4FC3(0);U+4FC3(5); +U+4FC4(0);U+4FC4(5); +U+4FC5(0);U+4FC5(5); +U+4FC7(0);U+4FC7(3); +U+4FC9(0);U+4FC9(0); +U+4FCA(0);U+4FCA(5);U+5101(2,3) +U+4FCB(0);U+4FCB(0); +U+4FCD(0);U+4FCD(0); +U+4FCE(0);U+4FCE(5);U+723C(3) +U+4FCF(0);U+4FCF(5); +U+4FD0(0);U+4FD0(5); +U+4FD1(0);U+4FD1(5); +U+4FD2(0);U+4FD2(0); +U+4FD3(0);U+4FD3(0); +U+4FD4(0);U+4F23(4);U+4F23(4) +U+4FD5(0);U+4FD5(0); +U+4FD6(0);U+4FD6(0); +U+4FD7(0);U+4FD7(5); +U+4FD8(0);U+4FD8(5); +U+4FD9(0);U+4FD9(0); +U+4FDA(0);U+4FDA(5); +U+4FDB(0);U+4FEF(2,3);U+4FEF(2,3),U+982B(2,3) +U+4FDC(0);U+4FDC(5); +U+4FDD(0);U+4FDD(5);U+5AAC(4) +U+4FDE(0);U+4FDE(5);U+516A(3),U+9103(4) +U+4FDF(0);U+4FDF(5);U+7AE2(2) +U+4FE0(0);U+4FA0(1,3);U+4FA0(1,3) +U+4FE1(0);U+4FE1(5);U+4F29(7) +U+4FE3(0);U+4FE3(5);U+4FC1(4) +U+4FE4(0);U+4FE4(0); +U+4FE5(0);U+4F21(4);U+4F21(4) +U+4FE6(0);U+4FE6(1,3);U+5114(1,3) +U+4FE7(0);U+4FE7(0); +U+4FE8(0);U+4FE8(1,3);U+513C(1,3) +U+4FE9(0);U+4FE9(1,3);U+5006(1,3) +U+4FEA(0);U+4FEA(1,3);U+5137(1,3) +U+4FEB(0);U+4FEB(4);U+5008(4) +U+4FEC(0);U+4FEC(0); +U+4FED(0);U+4FED(1,3);U+5039(4),U+5109(1,3) +U+4FEE(0);U+4FEE(5);U+8129(2,3) +U+4FEF(0);U+4FEF(5);U+4FDB(2,3),U+982B(2,3) +U+4FF0(0);U+4FF0(0); +U+4FF1(0);U+4FF1(5);U+5036(4) +U+4FF2(0);U+6548(2,3);U+509A(3),U+6548(2,3),U+52B9(2,3) +U+4FF3(0);U+4FF3(5); + +U+4FF4(0);U+4FF4(0); +U+4FF5(0);U+4FF5(3); +U+4FF6(0);U+4FF6(3); +U+4FF7(0);U+4FF7(0); +U+4FF8(0);U+4FF8(5); +U+4FF9(0);U+4FF9(0); +U+4FFA(0);U+4FFA(5); +U+4FFB(0);U+5907(4);U+5907(4),U+5099(2,3),U+5079(3,4) +U+4FFE(0);U+4FFE(5); +U+4FFF(0);U+4FFF(0); +U+5000(0);U+4F25(1,3);U+4F25(1,3) +U+5001(0);U+5001(0); +U+5002(0);U+5E76(4);U+4F75(3),U+5E76(4),U+4E26(0,3),U+7ADD(3),U+5E77(2,3,4) +U+5003(0);U+5003(0); +U+5004(0);U+5004(0); +U+5005(0);U+5005(3);U+4F1C(3) +U+5006(0);U+4FE9(1,3);U+4FE9(1,3) +U+5007(0);U+5A49(4);U+5A49(4) +U+5008(0);U+4FEB(4);U+4FEB(4) +U+5009(0);U+4ED3(1,3);U+4ED3(1,3) +U+500A(0);U+500A(0); +U+500B(0);U+4E2A(1,3);U+4E2A(1,3),U+7B87(2,3) +U+500C(0);U+500C(5); +U+500D(0);U+500D(5); +U+500E(0);U+8146(3);U+8146(3) +U+500F(0);U+500F(5);U+5135(2,3) +U+5011(0);U+4EEC(1,3);U+4EEC(1,3) +U+5012(0);U+5012(5); +U+5013(0);U+5013(0); +U+5014(0);U+5014(5); +U+5015(0);U+5015(0); +U+5016(0);U+5E78(2,3);U+5E78(2,3) +U+5017(0);U+5017(0); +U+5018(0);U+5018(5); +U+5019(0);U+5019(5); +U+501A(0);U+501A(5); +U+501B(0);U+501B(0); +U+501C(0);U+501C(5); +U+501D(0);U+501D(0); +U+501E(0);U+501E(3); +U+501F(0);U+501F(1,3);U+8024(3),U+85C9(1,3) +U+5020(0);U+5020(0); +U+5021(0);U+5021(5); +U+5022(0);U+5022(4); +U+5023(0);U+4EFF(2,3);U+4EFF(2,3),U+5F77(2,3,4),U+9AE3(2,3) +U+5024(0);U+503C(7);U+503C(7) +U+5025(0);U+5025(5); +U+5026(0);U+5026(5);U+52B5(3),U+5238(2,3) +U+5027(0);U+5027(0); +U+5028(0);U+5028(5); +U+5029(0);U+5029(5); +U+502A(0);U+502A(5);U+6DE3(3) +U+502B(0);U+4F26(1,3);U+4F26(1,3) +U+502C(0);U+502C(5); +U+502D(0);U+502D(5); +U+502E(0);U+502E(5); +U+502F(0);U+502F(0); +U+5030(0);U+5030(0); +U+5031(0);U+5031(0); +U+5032(0);U+5032(4); +U+5033(0);U+5033(4);U+525A(3,4) +U+5035(0);U+5035(0); +U+5036(0);U+4FF1(4);U+4FF1(4) + +U+5037(0);U+5037(0); +U+5039(0);U+4FED(4);U+4FED(4),U+5109(7) +U+503A(0);U+503A(1,3);U+50B5(1,3) +U+503B(0);U+503B(0); +U+503C(0);U+503C(5);U+5024(7) +U+503E(0);U+503E(1,3);U+50BE(1,3) +U+503F(0);U+503F(0); +U+5040(0);U+82F1(3);U+82F1(3) +U+5041(0);U+79F0(3);U+79F0(3),U+7A31(1,3) +U+5043(0);U+5043(5); +U+5044(0);U+5044(3); +U+5045(0);U+5045(0); +U+5046(0);U+5046(0); +U+5047(0);U+5047(5); +U+5048(0);U+5048(5); +U+5049(0);U+4F1F(1,3);U+4F1F(1,3) +U+504A(0);U+504A(0); +U+504B(0);U+504B(0); +U+504C(0);U+504C(5); +U+504D(0);U+504D(0); +U+504E(0);U+504E(5); +U+504F(0);U+504F(5); +U+5051(0);U+5051(0); +U+5053(0);U+5053(0); +U+5054(0);U+5054(0); +U+5055(0);U+5055(5); +U+5056(0);U+5056(0); +U+5057(0);U+5057(0); +U+5059(0);U+5059(3); +U+505A(0);U+505A(5); +U+505B(0);U+505B(0); +U+505C(0);U+505C(5); +U+505D(0);U+80CC(3);U+80CC(3),U+63F9(2,3) +U+505E(0);U+505E(4); +U+505F(0);U+505F(0); +U+5060(0);U+5060(3); +U+5061(0);U+5061(0); +U+5062(0);U+7785(7);U+7785(7) +U+5063(0);U+5063(0); +U+5064(0);U+5064(0); +U+5065(0);U+5065(5); +U+5066(0);U+5066(3); +U+5067(0);U+5067(0); +U+5068(0);U+5068(0); +U+5069(0);U+5069(0); +U+506A(0);U+506A(3); +U+506B(0);U+506B(0); +U+506C(0);U+506C(5);U+50AF(2,3) +U+506D(0);U+506D(0); +U+506E(0);U+506E(0); +U+506F(0);U+506F(0); +U+5070(0);U+5070(0); +U+5071(0);U+5071(0); +U+5072(0);U+5072(0); +U+5073(0);U+5073(0); +U+5074(0);U+4FA7(1,3);U+4FA7(1,3) +U+5075(0);U+4FA6(1,3);U+4FA6(1,3),U+9049(1,3,4) +U+5076(0);U+5076(5); +U+5077(0);U+5077(5);U+5078(4),U+5A7E(4),U+5AAE(2,3) +U+5078(0);U+5077(4);U+5077(4),U+5A7E(4),U+5AAE(2,3,4) +U+5079(0);U+5907(3);U+5907(3),U+5099(3),U+4FFB(0,3,4) +U+507A(0);U+54B1(2,3);U+54B1(2,3),U+5592(2,3) +U+507B(0);U+507B(1,3);U+50C2(1,3) + +U+507D(0);U+4F2A(4);U+4F2A(4),U+50DE(3,4) +U+507E(0);U+507E(1,3);U+50E8(1,3) +U+507F(0);U+507F(1,3);U+511F(1,3) +U+5080(0);U+5080(5); +U+5082(0);U+5082(0); +U+5083(0);U+5083(0); +U+5084(0);U+5084(0); +U+5085(0);U+5085(5); +U+5086(0);U+5086(0); +U+5087(0);U+5087(0); +U+5088(0);U+5088(5); +U+5089(0);U+5089(0); +U+508A(0);U+508A(0); +U+508B(0);U+508B(0); +U+508C(0);U+9A82(4);U+9A82(4),U+7F75(4),U+99E1(1,3,4) +U+508D(0);U+508D(5);U+5FAC(3) +U+508E(0);U+98A0(3);U+98A0(3),U+985B(1,3),U+985A(3) +U+508F(0);U+508F(0); +U+5090(0);U+5090(0); +U+5091(0);U+6770(2,3);U+6770(2,3) +U+5092(0);U+5092(0); +U+5094(0);U+5094(0); +U+5095(0);U+5095(0); +U+5096(0);U+4F27(1,3);U+4F27(1,3) +U+5098(0);U+4F1E(1,3);U+4F1E(1,3),U+7E56(1,3,4) +U+5099(0);U+5907(1,3);U+5907(1,3),U+4FFB(2,3),U+5079(3) +U+509A(0);U+6548(2,3);U+4FF2(3),U+6548(2,3),U+52B9(2,3) +U+509B(0);U+509B(0); +U+509C(0);U+5FAD(4);U+5FAD(4) +U+509D(0);U+509D(0); +U+509E(0);U+509E(0); +U+50A2(0);U+5BB6(1,3);U+5BB6(1,3) +U+50A3(0);U+50A3(5); +U+50A4(0);U+50A4(4);U+510E(4) +U+50A5(0);U+50A5(1,3);U+513B(1,3,4) +U+50A6(0);U+50A6(0); +U+50A7(0);U+50A7(1,3);U+5110(1,3) +U+50A8(0);U+50A8(1,3);U+5132(1,3) +U+50A9(0);U+50A9(1,3);U+513A(1,3) +U+50AA(0);U+50AA(0); +U+50AB(0);U+50AB(3); +U+50AC(0);U+50AC(5); +U+50AD(0);U+4F63(1,3);U+4F63(1,3) +U+50AE(0);U+5608(4);U+5608(4) +U+50AF(0);U+506C(2,3);U+506C(2,3) +U+50B0(0);U+50B0(0); +U+50B1(0);U+50B1(0); +U+50B2(0);U+50B2(5); +U+50B3(0);U+4F20(1,3);U+4F20(1,3) +U+50B4(0);U+4F1B(1,3);U+4F1B(1,3) +U+50B5(0);U+503A(1,3);U+503A(1,3) +U+50B6(0);U+8160(4);U+8160(4) +U+50B7(0);U+4F24(1,3);U+4F24(1,3) +U+50B8(0);U+50B8(0); +U+50BA(0);U+50BA(5); +U+50BB(0);U+50BB(5);U+510D(3) +U+50BC(0);U+50BC(0); +U+50BD(0);U+50BD(0); +U+50BE(0);U+503E(1,3);U+503E(1,3) +U+50BF(0);U+50BF(0); +U+50C0(0);U+50C0(0); +U+50C1(0);U+50C1(0); +U+50C2(0);U+507B(1,3);U+507B(1,3) + +U+50C4(0);U+50C4(0); +U+50C5(0);U+4EC5(1,3);U+4EC5(1,3) +U+50C6(0);U+50C6(0); +U+50C7(0);U+50C7(0); +U+50C8(0);U+50C8(0); +U+50C9(0);U+4F65(1,3);U+4F65(1,3) +U+50CA(0);U+4ED9(2,3);U+4ED9(2,3),U+4EDA(2,3) +U+50CB(0);U+50CB(0); +U+50CC(0);U+50CC(0); +U+50CD(0);U+52A8(4);U+52A8(4),U+52D5(2) +U+50CE(0);U+50CE(0); +U+50CF(0);U+50CF(5);U+8C61(3) +U+50D0(0);U+50D0(0); +U+50D1(0);U+4FA8(1,3);U+4FA8(1,3) +U+50D2(0);U+50D2(3); +U+50D3(0);U+50D3(0); +U+50D4(0);U+50D4(0); +U+50D5(0);U+4EC6(1,3);U+4EC6(1,3) +U+50D6(0);U+50D6(5); +U+50D7(0);U+50D7(0); +U+50D9(0);U+50D9(3); +U+50DA(0);U+50DA(5); +U+50DB(0);U+50DB(0); +U+50DC(0);U+50DC(0); +U+50DD(0);U+50DD(0); +U+50DE(0);U+4F2A(1,3);U+4F2A(1,3),U+507D(3,4) +U+50E0(0);U+50E0(0); +U+50E3(0);U+50ED(3);U+50ED(3) +U+50E4(0);U+50E4(0); +U+50E5(0);U+4FA5(1);U+4FA5(1),U+510C(2),U+5FBA(8,9) +U+50E6(0);U+50E6(5); +U+50E7(0);U+50E7(5); +U+50E8(0);U+507E(1,3);U+507E(1,3) +U+50E9(0);U+50E9(3); +U+50EA(0);U+50EA(0); +U+50EC(0);U+50EC(5); +U+50ED(0);U+50ED(5);U+50E3(3) +U+50EE(0);U+50EE(5);U+735E(3) +U+50EF(0);U+50EF(0); +U+50F0(0);U+50F0(0); +U+50F1(0);U+96C7(2,3);U+96C7(2,3) +U+50F2(0);U+50F2(0); +U+50F3(0);U+50F3(5); +U+50F5(0);U+50F5(5);U+6BAD(2,3) +U+50F6(0);U+50F6(0); +U+50F8(0);U+50F8(3); +U+50F9(0);U+4EF7(1,3);U+4EF7(1,3),U+4FA1(8,9) +U+50FA(0);U+50FA(0); +U+50FB(0);U+50FB(5); +U+50FC(0);U+50FC(0); +U+50FD(0);U+50FD(3); +U+50FE(0);U+50FE(3); +U+50FF(0);U+50FF(0); +U+5100(0);U+4EEA(1,3);U+4EEA(1,3) +U+5101(0);U+4FCA(2,3);U+4FCA(2,3) +U+5102(0);U+4FAC(1,3);U+4FAC(1,3) +U+5103(0);U+5103(3); +U+5104(0);U+4EBF(1,3);U+4EBF(1,3) +U+5105(0);U+5105(0); +U+5106(0);U+5106(5);U+61BC(3) +U+5107(0);U+5107(5); +U+5108(0);U+4FA9(1,3);U+4FA9(1,3) +U+5109(0);U+4FED(1,3);U+4FED(1,3),U+5039(7) + +U+510A(0);U+510A(0); +U+510B(0);U+510B(5); +U+510C(0);U+4FA5(3);U+4FA5(3),U+50E5(2),U+5FBA(3) +U+510D(0);U+50BB(3);U+50BB(3) +U+510E(0);U+50A4(4);U+50A4(4) +U+510F(0);U+510F(0); +U+5110(0);U+50A7(1,3);U+50A7(1,3) +U+5111(0);U+5111(0); +U+5112(0);U+5112(5); +U+5113(0);U+5113(0); +U+5114(0);U+4FE6(1,3);U+4FE6(1,3) +U+5115(0);U+4FAA(1,3);U+4FAA(1,3) +U+5116(0);U+5116(0); +U+5117(0);U+5117(0);U+62DF(4),U+64EC(2) +U+5118(0);U+5C3D(1,3);U+5C3D(1,3),U+76E1(4) +U+5119(0);U+5119(0); +U+511A(0);U+511A(0); +U+511C(0);U+511C(3); +U+511D(0);U+511D(0); +U+511E(0);U+4F60(3);U+4F60(3),U+4F32(3,5),U+59B3(2,3),U+5976(2,3),U+5B2D(2,3) +U+511F(0);U+507F(1,3);U+507F(1,3) +U+5120(0);U+5120(0); +U+5121(0);U+5121(5); +U+5122(0);U+5122(0); +U+5123(0);U+5123(0); +U+5124(0);U+5124(3); +U+5125(0);U+5125(0); +U+5126(0);U+5126(0); +U+5127(0);U+5127(0); +U+5129(0);U+5129(0); +U+512A(0);U+4F18(1,3);U+4F18(1,3) +U+512C(0);U+512C(0); +U+512D(0);U+512D(0); +U+512E(0);U+512E(0); +U+512F(0);U+512F(0); +U+5130(0);U+5130(0); +U+5131(0);U+5131(0); +U+5132(0);U+50A8(1,3);U+50A8(1,3) +U+5133(0);U+5133(0); +U+5134(0);U+5134(0); +U+5135(0);U+500F(2,3);U+500F(2,3) +U+5136(0);U+5136(0); +U+5137(0);U+4FEA(1,3);U+4FEA(1,3) +U+5138(0);U+5138(0); +U+5139(0);U+5139(3); +U+513A(0);U+50A9(1,3);U+50A9(1,3) +U+513B(0);U+50A5(1,3);U+50A5(1,3) +U+513C(0);U+4FE8(1,3);U+4FE8(1,3) +U+513D(0);U+513D(3); +U+513E(0);U+513E(0); +U+513F(0);U+513F(1,3);U+5150(3),U+5152(1,3) +U+5140(0);U+5140(5); +U+5141(0);U+5141(5); +U+5143(0);U+5143(5); +U+5144(0);U+5144(5); +U+5145(0);U+5145(5); +U+5146(0);U+5146(5); +U+5147(0);U+51F6(2,3);U+51F6(2,3) +U+5148(0);U+5148(5); +U+5149(0);U+5149(5);U+706E(3),U+709A(3),U+70E1(3) +U+514B(0);U+514B(1,3);U+524B(1,3,4),U+5C05(4) +U+514C(0);U+5151(4);U+5151(4) +U+514D(0);U+514D(5); + +U+514E(0);U+5154(2,3);U+5154(2,3) +U+5150(0);U+513F(3);U+513F(3),U+5152(3) +U+5151(0);U+5151(5);U+514C(4) +U+5152(0);U+513F(1,3);U+513F(1,3),U+5150(3) +U+5154(0);U+5154(5);U+514E(2,3) +U+5155(0);U+5155(5); +U+5156(0);U+5156(5);U+5157(3) +U+5157(0);U+5156(3);U+5156(3) +U+5159(0);U+5159(0); +U+515A(0);U+515A(1,3);U+9EE8(1,3,4) +U+515B(0);U+515B(0); +U+515C(0);U+515C(5); +U+515D(0);U+515D(0); +U+515E(0);U+515E(0); +U+515F(0);U+515F(0); +U+5161(0);U+5161(0); +U+5162(0);U+5162(5); +U+5163(0);U+5163(0); +U+5165(0);U+5165(5); +U+5166(0);U+4EA1(3);U+4EA1(3),U+4EBE(4) +U+5167(0);U+5185(4);U+5185(4) +U+5168(0);U+5168(5); +U+5169(0);U+4E24(1,3);U+4E21(3),U+4E24(1,3) +U+516A(0);U+4FDE(3);U+4FDE(3),U+9103(3,4) +U+516B(0);U+516B(5);U+634C(3) +U+516C(0);U+516C(5); +U+516D(0);U+516D(5); +U+516E(0);U+516E(5); +U+516F(0);U+516F(0); +U+5170(0);U+5170(1,3);U+862D(1,3) +U+5171(0);U+5171(5); +U+5173(0);U+5173(1,3);U+959E(3),U+95A2(3),U+95D7(3),U+95DC(1,3) +U+5174(0);U+5174(1,3);U+8208(1,3) +U+5175(0);U+5175(5); +U+5176(0);U+5176(5);U+4E0C(3),U+4E93(3) +U+5177(0);U+5177(5); +U+5178(0);U+5178(5); +U+5179(0);U+5179(5);U+7386(3),U+8332(3,4) +U+517A(0);U+517A(0); +U+517B(0);U+517B(1,3);U+990A(1,3) +U+517C(0);U+517C(5); +U+517D(0);U+517D(1,3);U+7378(1,3) +U+517F(0);U+827A(4);U+827A(4),U+85DD(4),U+84FA(3,4) +U+5180(0);U+5180(5); +U+5181(0);U+5181(1,3);U+56C5(1,3) +U+5182(0);U+5182(5); +U+5185(0);U+5185(5);U+5167(4) +U+5186(0);U+5706(4);U+5706(4),U+5713(4),U+570E(3,4) +U+5187(0);U+5187(0); +U+5188(0);U+5188(1,3);U+5CA1(1,3),U+5D17(1,3,4),U+5C97(1,3,4) +U+5189(0);U+5189(5); +U+518A(0);U+518C(2,3);U+518C(2,3) +U+518B(0);U+518B(3); +U+518C(0);U+518C(5);U+518A(2,3) +U+518D(0);U+518D(5); +U+518F(0);U+518F(3);U+56E7(3) +U+5190(0);U+5192(2,3);U+5192(2,3) +U+5191(0);U+80C4(4);U+80C4(4) +U+5192(0);U+5192(5);U+5190(2,3) +U+5193(0);U+6784(3);U+6784(3),U+6406(3,4),U+69CB(1,3) +U+5194(0);U+5194(0); +U+5195(0);U+5195(5); +U+5196(0);U+5196(5); + +U+5197(0);U+5197(5);U+5B82(2) +U+5198(0);U+5198(0); +U+5199(0);U+5199(1,3);U+5BEB(1,3) +U+519A(0);U+519A(0); +U+519B(0);U+519B(1,3);U+8ECD(1,3) +U+519C(0);U+519C(1,3);U+8FB2(1,3) +U+519D(0);U+5B9C(3);U+5B9C(3) +U+519E(0);U+5F25(7);U+5F25(7),U+5F4C(1,3,7),U+7030(1,3,7) +U+519F(0);U+519F(0); +U+51A0(0);U+51A0(5); +U+51A2(0);U+51A2(5);U+585A(2,3) +U+51A4(0);U+51A4(5);U+5BC3(2,3) +U+51A5(0);U+51A5(5); +U+51A6(0);U+5BC7(3);U+5BC7(3) +U+51A7(0);U+51A7(0); +U+51A8(0);U+5BCC(3);U+5BCC(3) +U+51AA(0);U+5E42(2,3);U+5E42(2,3),U+7F83(3) +U+51AB(0);U+51AB(5); +U+51AC(0);U+51AC(1,3);U+9F15(1,3,4) +U+51AE(0);U+51AE(0); +U+51AF(0);U+51AF(1,3);U+99AE(1,3) +U+51B0(0);U+51B0(5);U+6C37(2,3) +U+51B1(0);U+51B1(5);U+6C8D(3) +U+51B2(0);U+51B2(1,3,4);U+6C96(3,4),U+794C(3),U+885D(1,3,4),U+8876(4),U+76C5(3,4) +U+51B3(0);U+51B3(5);U+6C7A(2,3) +U+51B5(0);U+51B5(5);U+6CC1(2,4) +U+51B6(0);U+51B6(5); +U+51B7(0);U+51B7(5); +U+51B9(0);U+51B9(0); +U+51BB(0);U+51BB(1,3);U+51CD(1,3) +U+51BC(0);U+51BC(5); +U+51BD(0);U+51BD(5);U+6D0C(3) +U+51BE(0);U+6D3D(3);U+6D3D(3) +U+51BF(0);U+51BF(0); +U+51C0(0);U+51C0(4);U+51C8(4),U+6D44(2,4),U+6DE8(3,4) +U+51C1(0);U+51C1(0); +U+51C3(0);U+6D82(3);U+6D82(3),U+5857(1,3,4) +U+51C4(0);U+51C4(5);U+60BD(2),U+6DD2(2,3) +U+51C5(0);U+51C5(0); +U+51C6(0);U+51C6(1,3);U+51D6(3),U+6E96(1,3) +U+51C7(0);U+51C7(5); +U+51C8(0);U+51C0(4);U+51C0(4),U+6D44(2,4),U+6DE8(3,4) +U+51C9(0);U+51C9(5);U+6DBC(2,3) +U+51CA(0);U+6E05(4);U+6E05(4),U+6DF8(4) +U+51CB(0);U+51CB(5); +U+51CC(0);U+51CC(5);U+6DE9(3) +U+51CD(0);U+51BB(1,3);U+51BB(1,3) +U+51CE(0);U+51CE(0); +U+51CF(0);U+51CF(5);U+6E1B(2,3) +U+51D0(0);U+51D0(3); +U+51D1(0);U+51D1(5);U+6E4A(2,3) +U+51D4(0);U+51D4(3); +U+51D5(0);U+51D5(0); +U+51D6(0);U+51C6(3);U+51C6(3),U+6E96(3) +U+51D7(0);U+51D7(0); +U+51D8(0);U+51D8(3); +U+51D9(0);U+51D9(0); +U+51DA(0);U+51DA(0); +U+51DB(0);U+51DB(5);U+51DC(3,4) +U+51DC(0);U+51DB(3,4);U+51DB(3,4) +U+51DD(0);U+51DD(5); +U+51DE(0);U+51DE(0); +U+51E0(0);U+51E0(1,3);U+5E7E(1,3) + +U+51E1(0);U+51E1(5);U+51E2(2,3),U+51E3(4) +U+51E2(0);U+51E1(2,3);U+51E1(2,3),U+51E3(4) +U+51E3(0);U+51E1(4);U+51E1(4),U+51E2(4) +U+51E4(0);U+51E4(1,3);U+9CEF(3),U+9CF3(1,3) +U+51E5(0);U+51E5(0); +U+51E7(0);U+51E7(0); +U+51E8(0);U+98CE(3);U+98A8(3),U+98CE(3),U+98CC(3) +U+51E9(0);U+51E9(0); +U+51EA(0);U+51EA(0); +U+51EB(0);U+51EB(1,3,4);U+9CE7(4),U+9CEC(1,3) +U+51ED(0);U+51ED(1,3);U+51F4(3),U+6191(1,3,4) +U+51EF(0);U+51EF(1,3);U+51F1(1,3) +U+51F0(0);U+51F0(5); +U+51F1(0);U+51EF(1,3);U+51EF(1,3) +U+51F3(0);U+51F3(5); +U+51F4(0);U+51ED(3);U+51ED(3),U+6191(2) +U+51F5(0);U+51F5(5); +U+51F6(0);U+51F6(5);U+5147(2,3) +U+51F7(0);U+5757(3);U+5757(3),U+584A(3) +U+51F8(0);U+51F8(5); +U+51F9(0);U+51F9(5); +U+51FA(0);U+51FA(1);U+5C80(3),U+9F63(1,3) +U+51FB(0);U+51FB(1,3);U+6483(4),U+64CA(1,3) +U+51FC(0);U+51FC(5); +U+51FD(0);U+51FD(5);U+51FE(3),U+80A3(3) +U+51FE(0);U+51FD(3);U+51FD(3),U+80A3(3) +U+51FF(0);U+51FF(1,3);U+947F(1,3) +U+5200(0);U+5200(5);U+5202(3) +U+5201(0);U+5201(5); +U+5202(0);U+5200(3);U+5200(3) +U+5203(0);U+5203(5);U+5204(3) +U+5204(0);U+5203(3);U+5203(3) +U+5205(0);U+5205(0); +U+5206(0);U+5206(5); +U+5207(0);U+5207(5); +U+5208(0);U+5208(5);U+82C5(3) +U+5209(0);U+5209(0); +U+520A(0);U+520A(5);U+520B(4) +U+520B(0);U+520A(4);U+520A(4) +U+520C(0);U+5FD6(3);U+5FD6(3) +U+520D(0);U+520D(1,3);U+82BB(1,3) +U+520E(0);U+520E(5); +U+520F(0);U+520F(3); +U+5210(0);U+5210(0); +U+5211(0);U+5211(5); +U+5212(0);U+5212(1,3);U+5283(1,3) +U+5213(0);U+5213(3); +U+5214(0);U+6289(7);U+6289(7) +U+5215(0);U+5215(0); +U+5216(0);U+5216(5); +U+5217(0);U+5217(5); +U+5218(0);U+5218(1,3);U+5289(1,3) +U+5219(0);U+5219(1,3);U+5247(1,3) +U+521A(0);U+521A(1,3);U+525B(1,3) +U+521B(0);U+521B(1,3);U+5231(3),U+5259(4),U+5275(1,3) +U+521C(0);U+521C(0); +U+521D(0);U+521D(5); +U+521E(0);U+801D(3);U+801D(3) +U+521F(0);U+521F(0); +U+5220(0);U+5220(5);U+522A(2,3) +U+5221(0);U+5221(0); +U+5222(0);U+5222(0); +U+5223(0);U+5223(0); + +U+5224(0);U+5224(5); +U+5225(0);U+522B(4);U+522B(4),U+5F46(1,3,4),U+618B(3,4) +U+5226(0);U+52AB(2,3);U+52AB(2,3),U+523C(2,3) +U+5228(0);U+5228(4);U+9464(2,3) +U+5229(0);U+5229(5); +U+522A(0);U+5220(2,3);U+5220(2,3) +U+522B(0);U+522B(1,3);U+5225(4),U+5F46(1,3),U+618B(3) +U+522C(0);U+522C(1,3);U+5257(1,3),U+5277(8,9),U+93DF(1,3,4),U+94F2(1,3,4) +U+522D(0);U+522D(1,3);U+5244(1,3) +U+522E(0);U+522E(1,3);U+5280(3),U+98B3(1,3,4) +U+522F(0);U+522F(0); +U+5230(0);U+5230(5); +U+5231(0);U+521B(3);U+521B(3),U+5259(3,4),U+5275(1,3) +U+5232(0);U+5232(0); +U+5233(0);U+5233(5); +U+5234(0);U+5241(4);U+5241(4) +U+5235(0);U+5235(0); +U+5236(0);U+5236(1,3);U+88FD(1,3,4) +U+5237(0);U+5237(5); +U+5238(0);U+5238(5);U+52B5(2),U+5026(2,3) +U+5239(0);U+5239(5);U+524E(4) +U+523A(0);U+523A(5);U+523E(7),U+673F(3) +U+523B(0);U+523B(5); +U+523C(0);U+52AB(2,3);U+52AB(2,3),U+5226(0,2,3) +U+523D(0);U+523D(1,3);U+528A(1,3) +U+523E(0);U+523A(7);U+523A(7),U+673F(3,7) +U+523F(0);U+523F(1,3);U+528C(1,3) +U+5240(0);U+5240(1,3);U+5274(1,3) +U+5241(0);U+5241(5);U+5234(4) +U+5242(0);U+5242(1,3);U+5264(4),U+5291(1,3) +U+5243(0);U+5243(5);U+8599(2) +U+5244(0);U+522D(1,3);U+522D(1,3) +U+5245(0);U+5245(0); +U+5246(0);U+5246(0); +U+5247(0);U+5219(1,3);U+5219(1,3) +U+5248(0);U+5248(0); +U+5249(0);U+5249(0); +U+524A(0);U+524A(5); +U+524B(0);U+514B(1,3);U+514B(1,3),U+5C05(2,3) +U+524C(0);U+524C(5); +U+524D(0);U+524D(5); +U+524E(0);U+5239(4);U+5239(4) +U+5250(0);U+5250(1,3);U+526E(1,3) +U+5251(0);U+5251(1,3);U+5263(3),U+528D(1,3),U+5292(4),U+5294(3),U+9431(3) +U+5252(0);U+5252(0); +U+5254(0);U+5254(5); +U+5255(0);U+5255(0); +U+5256(0);U+5256(5); +U+5257(0);U+522C(1,3);U+522C(1,3),U+5277(8,9),U+93DF(4),U+94F2(4) +U+5258(0);U+5258(0); +U+5259(0);U+521B(4);U+521B(4),U+5275(2,3),U+5231(3,4) +U+525A(0);U+5033(3,4);U+5033(3,4) +U+525B(0);U+521A(1,3);U+521A(1,3) +U+525C(0);U+525C(5); +U+525D(0);U+5265(4);U+5265(4) +U+525E(0);U+525E(5); +U+525F(0);U+525F(0); +U+5260(0);U+5260(0); +U+5261(0);U+5261(5); +U+5262(0);U+5262(0); +U+5263(0);U+5251(3);U+5251(3),U+528D(3),U+5292(3,4),U+5294(3),U+9431(3) +U+5264(0);U+5242(4);U+5242(4),U+5291(4) +U+5265(0);U+5265(5);U+525D(4) + +U+5267(0);U+5267(1,3);U+5287(1,3) +U+5268(0);U+5268(0); +U+5269(0);U+5269(5);U+5270(4),U+8CF8(2,3) +U+526A(0);U+526A(5); +U+526B(0);U+526B(3); +U+526C(0);U+526C(0); +U+526D(0);U+526D(3); +U+526E(0);U+5250(1,3);U+5250(1,3) +U+526F(0);U+526F(5);U+8914(4) +U+5270(0);U+5269(4);U+5269(4),U+8CF8(2,3,4) +U+5272(0);U+5272(5); +U+5273(0);U+672D(2,3);U+624E(4),U+5284(4),U+672D(2,3),U+7B9A(4),U+7D25(2,4),U+7D2E(2,4) + +U+5274(0);U+5240(1,3);U+5240(1,3) +U+5275(0);U+521B(1,3);U+521B(1,3),U+5259(2,3),U+5231(1,3) +U+5276(0);U+5276(0); +U+5277(0);U+94F2(4);U+522C(8,9),U+5257(8,9),U+93DF(2,3),U+94F2(4) +U+5278(0);U+5278(3); +U+527A(0);U+527A(3); +U+527B(0);U+527B(0); +U+527C(0);U+527C(0); +U+527D(0);U+527D(5);U+6153(4) +U+527E(0);U+527E(3); +U+527F(0);U+527F(5);U+528B(3),U+52E6(2) +U+5280(0);U+522E(3);U+522E(3),U+98B3(1,3,4) +U+5281(0);U+5281(5); +U+5282(0);U+5282(5); +U+5283(0);U+5212(1,3);U+5212(1,3) +U+5284(0);U+672D(2,3);U+624E(4),U+5273(4),U+672D(2,3),U+7B9A(4),U+7D25(2,4),U+7D2E(2,4) + +U+5286(0);U+5286(0);U+942E(3),U+9570(3),U+938C(2,3) +U+5287(0);U+5267(1,3);U+5267(1,3) +U+5288(0);U+5288(5); +U+5289(0);U+5218(1,3);U+5218(1,3) +U+528A(0);U+523D(1,3);U+523D(1,3) +U+528B(0);U+527F(3);U+527F(3),U+52E6(2,3) +U+528C(0);U+523F(1,3);U+523F(1,3) +U+528D(0);U+5251(1,3);U+5251(1,3),U+5263(3),U+5292(2),U+5294(3),U+9431(1,3) +U+528F(0);U+528F(0); +U+5290(0);U+5290(5); +U+5291(0);U+5242(1,3);U+5242(1,3),U+5264(4) +U+5292(0);U+5251(4);U+5251(4),U+528D(2),U+5294(4),U+5263(3,4),U+9431(3,4) +U+5293(0);U+5293(5); +U+5294(0);U+5251(3);U+5251(3),U+528D(3),U+5292(4),U+5263(3),U+9431(3) +U+5295(0);U+5295(0); +U+5296(0);U+5296(0); +U+5297(0);U+5297(0); +U+5298(0);U+5298(0); +U+5299(0);U+5299(3);U+882B(3) +U+529A(0);U+529A(0); +U+529B(0);U+529B(5); +U+529C(0);U+529C(0); +U+529D(0);U+529D(1,3);U+52E7(3),U+52F8(1,3) +U+529E(0);U+529E(1,3);U+8FA6(1,3),U+8FA8(1,3),U+8FA7(1,3),U+91C6(1,3,4) +U+529F(0);U+529F(5); +U+52A0(0);U+52A0(5); +U+52A1(0);U+52A1(1,3);U+52D9(1,3) +U+52A2(0);U+52A2(4);U+52F1(4) +U+52A3(0);U+52A3(5); +U+52A5(0);U+52A5(0); +U+52A6(0);U+534F(3);U+534F(3),U+5354(1,3),U+604A(3) +U+52A7(0);U+52A7(0); +U+52A8(0);U+52A8(1,3,4);U+50CD(4),U+52D5(1,3) + +U+52A9(0);U+52A9(5); +U+52AA(0);U+52AA(5); +U+52AB(0);U+52AB(5);U+5226(2,3),U+523C(2,3) +U+52AC(0);U+52AC(5); +U+52AD(0);U+52AD(5); +U+52AE(0);U+9038(4);U+9038(4) +U+52AF(0);U+52AF(0); +U+52B0(0);U+52B0(0); +U+52B1(0);U+52B1(1,3);U+52F5(1,3) +U+52B2(0);U+52B2(1,3);U+52C1(1,3) +U+52B3(0);U+52B3(1,3);U+52B4(4),U+52DE(1,3) +U+52B4(0);U+52B3(4);U+52B3(4),U+52DE(4) +U+52B5(0);U+5026(3,5);U+5026(3,5),U+5238(2) +U+52B6(0);U+52B6(0); +U+52B7(0);U+52B7(0); +U+52B8(0);U+52B8(0); +U+52B9(0);U+6548(2,3);U+6548(2,3),U+4FF2(0,2,3),U+509A(2,3) +U+52BA(0);U+52BA(3); +U+52BB(0);U+52BB(0); +U+52BC(0);U+52BC(0); +U+52BD(0);U+52BD(0); +U+52BE(0);U+52BE(5);U+52D3(3) +U+52BF(0);U+52BF(1,3);U+52E2(1,3) +U+52C0(0);U+52C0(4); +U+52C1(0);U+52B2(1,3);U+52B2(1,3) +U+52C2(0);U+52C2(0); +U+52C3(0);U+52C3(5); +U+52C6(0);U+52C6(0); +U+52C7(0);U+52C7(5); +U+52C9(0);U+52C9(5); +U+52CA(0);U+52CA(0); +U+52CB(0);U+52CB(1,3);U+52DB(1,3),U+52F2(4),U+52F3(4) +U+52CD(0);U+52CD(0); +U+52CF(0);U+52CF(0); +U+52D0(0);U+52D0(5); +U+52D2(0);U+52D2(5); +U+52D3(0);U+52BE(3);U+52BE(3) +U+52D5(0);U+52A8(1,3);U+50CD(2),U+52A8(1,3) +U+52D6(0);U+52D6(5);U+52D7(2,3) +U+52D7(0);U+52D6(2,3);U+52D6(2,3) +U+52D8(0);U+52D8(5); +U+52D9(0);U+52A1(1,3);U+52A1(1,3) +U+52DA(0);U+52DA(1,3);U+52E9(1,3) +U+52DB(0);U+52CB(1,3);U+52CB(1,3),U+52F2(4),U+52F3(2,3) +U+52DC(0);U+52DC(0); +U+52DD(0);U+80DC(1,3);U+80DC(1,3) +U+52DE(0);U+52B3(1,3);U+52B3(1,3),U+52B4(4) +U+52DF(0);U+52DF(5); +U+52E0(0);U+52E0(3); +U+52E2(0);U+52BF(1,3);U+52BF(1,3) +U+52E3(0);U+7EE9(4);U+7EE9(4),U+7E3E(1,3,4) +U+52E4(0);U+52E4(5);U+61C3(2,3),U+763D(3) +U+52E6(0);U+527F(2);U+527F(2),U+528B(2,3) +U+52E7(0);U+529D(3);U+529D(3),U+52F8(3) +U+52E8(0);U+52E8(0); +U+52E9(0);U+52DA(1,3);U+52DA(1,3) +U+52EA(0);U+52EA(0); +U+52EB(0);U+52EB(0); +U+52EC(0);U+52EC(3); +U+52ED(0);U+52ED(0); +U+52EF(0);U+52EF(0); +U+52F0(0);U+52F0(5); +U+52F1(0);U+52A2(4);U+52A2(4) + +U+52F2(0);U+52CB(4);U+52CB(4),U+52DB(2,3),U+52F3(3) +U+52F3(0);U+52CB(4);U+52CB(4),U+52DB(2,3),U+52F2(3) +U+52F4(0);U+52F4(0); +U+52F5(0);U+52B1(1,3);U+52B1(1,3) +U+52F6(0);U+52F6(0); +U+52F7(0);U+52F7(0); +U+52F8(0);U+529D(1,3);U+529D(1,3),U+52E7(3) +U+52F9(0);U+52F9(5); +U+52FA(0);U+52FA(5); +U+52FB(0);U+5300(4);U+5300(4) +U+52FC(0);U+52FC(3); +U+52FD(0);U+52FD(0); +U+52FE(0);U+52FE(5);U+53E5(3) +U+52FF(0);U+52FF(5); +U+5300(0);U+5300(5);U+52FB(4) +U+5301(0);U+5301(0); +U+5302(0);U+5302(0); +U+5305(0);U+5305(5); +U+5306(0);U+5306(5);U+6031(2,3),U+60A4(2,3) +U+5307(0);U+5307(0); +U+5308(0);U+5308(5); +U+5309(0);U+5309(0); +U+530A(0);U+63AC(3);U+63AC(3) +U+530B(0);U+9676(4);U+9676(4) +U+530C(0);U+530C(0); +U+530D(0);U+530D(5); +U+530E(0);U+530E(0); +U+530F(0);U+530F(5); +U+5310(0);U+5310(5); +U+5311(0);U+5311(3); +U+5312(0);U+5312(0); +U+5313(0);U+5313(0); +U+5314(0);U+5314(4); +U+5315(0);U+5315(5); +U+5316(0);U+5316(5); +U+5317(0);U+5317(5); +U+5319(0);U+5319(5); +U+531A(0);U+531A(5); +U+531C(0);U+531C(3); +U+531D(0);U+531D(5); +U+531F(0);U+7095(2,3);U+7095(2,3) +U+5320(0);U+5320(5); +U+5321(0);U+5321(5); +U+5322(0);U+532B(3);U+532B(3) +U+5323(0);U+5323(5); +U+5324(0);U+5324(0); +U+5325(0);U+5325(0); +U+5326(0);U+5326(1,3);U+532D(1,3) +U+5328(0);U+5328(0); +U+532A(0);U+532A(5); +U+532B(0);U+532B(3);U+5322(3) +U+532C(0);U+532C(0); +U+532D(0);U+5326(1,3);U+5326(1,3) +U+532E(0);U+532E(1,3);U+5331(1,3),U+9400(1,3) +U+532F(0);U+6C47(1,3);U+5F59(1,3,4),U+5F5A(4),U+6C47(1,3),U+6ED9(4) +U+5330(0);U+5330(0); +U+5331(0);U+532E(1,3);U+532E(1,3),U+9400(1,3) +U+5333(0);U+5941(2,3);U+5941(2,3),U+5969(2) +U+5334(0);U+5334(3); +U+5337(0);U+5337(0); +U+5339(0);U+5339(5);U+758B(2,3) +U+533A(0);U+533A(1,3);U+5340(1,3) +U+533B(0);U+533B(1,3);U+6BC9(3),U+91AB(1,3) + +U+533C(0);U+533C(3); +U+533D(0);U+533D(3); +U+533E(0);U+533E(5); +U+533F(0);U+533F(5); +U+5340(0);U+533A(1,3);U+533A(1,3) +U+5341(0);U+5341(5); +U+5343(0);U+5343(1,3);U+4EDF(3),U+97C6(1,3,4) +U+5344(0);U+5EFF(3);U+5EFF(3) +U+5345(0);U+5345(5); +U+5346(0);U+5352(3);U+5352(3) +U+5347(0);U+5347(5);U+965E(2,3),U+6607(2,3) +U+5348(0);U+5348(5); +U+5349(0);U+5349(5); +U+534A(0);U+534A(5); +U+534B(0);U+4E16(3);U+4E16(3),U+4E17(3) +U+534C(0);U+534C(0); +U+534D(0);U+534D(4);U+5350(3,4) +U+534E(0);U+534E(1,3);U+5D0B(3),U+83EF(1,3) +U+534F(0);U+534F(1,3);U+52A6(3),U+5354(1,3),U+604A(3) +U+5350(0);U+534D(3,4);U+534D(3,4) +U+5351(0);U+5351(5); +U+5352(0);U+5352(5);U+5346(3) +U+5353(0);U+5353(5); +U+5354(0);U+534F(1,3);U+534F(1,3),U+604A(3),U+52A6(0,1,3) +U+5355(0);U+5355(1,3);U+5358(4),U+55AE(1,3) +U+5356(0);U+5356(1,3);U+58F2(4),U+8CE3(1,3) +U+5357(0);U+5357(5); +U+5358(0);U+5355(4);U+5355(4),U+55AE(8,9) +U+5359(0);U+5359(0); +U+535A(0);U+535A(5);U+613D(2,3) +U+535C(0);U+535C(1,3);U+8514(1,3,4),U+83D4(1,3,4) +U+535E(0);U+535E(5); +U+535F(0);U+535F(5); +U+5360(0);U+5360(5);U+4F54(2,3) +U+5361(0);U+5361(5); +U+5362(0);U+5362(1,3);U+76E7(1,3) +U+5363(0);U+5363(5); +U+5364(0);U+5364(1,3);U+6EF7(1,3),U+9E75(1,3) +U+5365(0);U+5365(0); +U+5366(0);U+5366(5); +U+5367(0);U+5367(5);U+81E5(3,4) +U+5369(0);U+5369(5); +U+536B(0);U+536B(1,3);U+885B(1,3),U+885E(3) +U+536C(0);U+536C(0); +U+536E(0);U+536E(5);U+5DF5(2,3) +U+536F(0);U+536F(5);U+5918(2,3),U+623C(2,3) +U+5370(0);U+5370(5); +U+5371(0);U+5371(5); +U+5372(0);U+5372(0); +U+5373(0);U+5373(5);U+537D(3,4) +U+5374(0);U+5374(5);U+537B(3) +U+5375(0);U+5375(5); +U+5376(0);U+5376(3); +U+5377(0);U+5377(1,3);U+5DFB(4),U+6372(1,3,4) +U+5378(0);U+5378(5);U+7F37(3) +U+5379(0);U+6064(2);U+6064(2),U+8CC9(2,3) +U+537A(0);U+537A(5); +U+537B(0);U+5374(3);U+5374(3) +U+537C(0);U+537C(0); +U+537D(0);U+5373(3,4);U+5373(3,4) +U+537E(0);U+537E(0); +U+537F(0);U+537F(5); +U+5381(0);U+5381(0); + +U+5382(0);U+5382(1,3,4);U+53B0(4),U+5EE0(1,3) +U+5383(0);U+5383(0); +U+5384(0);U+5384(5);U+9628(2) +U+5385(0);U+5385(1,3);U+539B(3),U+5EF0(4),U+5EF3(1,3),U+5E81(1,3) +U+5386(0);U+5386(1,3);U+53A4(4),U+66A6(4),U+66C6(1,3),U+6B74(2,3),U+6B77(1,3,4) +U+5387(0);U+5387(0); +U+5388(0);U+5388(0); +U+5389(0);U+5389(1,3);U+53B2(1,3) +U+538A(0);U+538A(0); +U+538B(0);U+538B(1,3);U+5727(4),U+58D3(1,3) +U+538C(0);U+538C(1,3);U+53AD(1,3),U+7312(3) +U+538D(0);U+538D(1,3);U+5399(1,3) +U+538E(0);U+5E95(4);U+5E95(4) +U+538F(0);U+538F(0); +U+5390(0);U+5E9E(4);U+5E9E(4),U+9F8E(4),U+9F90(8,9) +U+5391(0);U+5391(0); +U+5392(0);U+5392(0); +U+5393(0);U+5393(0); +U+5394(0);U+5394(0); +U+5395(0);U+5395(1,3);U+53A0(1,3),U+5EC1(4) +U+5396(0);U+5396(3); +U+5397(0);U+5397(0); +U+5398(0);U+5398(5);U+91D0(2,3) +U+5399(0);U+538D(1,3);U+538D(1,3) +U+539A(0);U+539A(5); +U+539B(0);U+5385(3);U+5385(3),U+5EF3(3),U+5EF0(3,4),U+5E81(1,3) +U+539C(0);U+539C(0); +U+539D(0);U+539D(5); +U+539E(0);U+539E(3); +U+539F(0);U+539F(5);U+908D(4) +U+53A0(0);U+5395(1,3);U+5395(1,3),U+5EC1(2,3) +U+53A2(0);U+53A2(5);U+5EC2(2,3) +U+53A3(0);U+53A3(1,3);U+53B4(1,3) +U+53A4(0);U+5386(4);U+5386(4),U+66A6(4),U+66C6(1,3,4),U+6B74(2,3,4),U+6B77(1,3,4) +U+53A5(0);U+53A5(5); +U+53A6(0);U+53A6(5);U+5EC8(2,3) +U+53A7(0);U+53A7(0); +U+53A8(0);U+53A8(5);U+5EDA(2,3) +U+53A9(0);U+53A9(5);U+5EC4(2),U+5ECF(3,4),U+5ED0(2) +U+53AC(0);U+53AC(0); +U+53AD(0);U+538C(1,3);U+538C(1,3),U+7312(1,3) +U+53AE(0);U+53AE(5);U+5EDD(2,3) +U+53B0(0);U+5382(4);U+5382(4),U+5EE0(3) +U+53B1(0);U+53B1(0); +U+53B2(0);U+5389(1,3);U+5389(1,3) +U+53B3(0);U+4E25(4);U+4E25(4),U+56B4(4) +U+53B4(0);U+53A3(1,3);U+53A3(1,3) +U+53B5(0);U+6E90(3);U+6E90(3) +U+53B6(0);U+53B6(5);U+79C1(3) +U+53B7(0);U+53B7(0); +U+53B8(0);U+53B8(4); +U+53B9(0);U+53B9(0); +U+53BB(0);U+53BB(5); +U+53BC(0);U+53BC(0); +U+53BD(0);U+53BD(0); +U+53BE(0);U+53BE(0); +U+53BF(0);U+53BF(1,3);U+7E23(1,3) +U+53C0(0);U+53C0(0); +U+53C1(0);U+53C1(5);U+53C2(4),U+53C3(8,9),U+84E1(4),U+53C4(3,4),U+8460(4) +U+53C2(0);U+53C2(1,3);U+84E1(4),U+53C1(4),U+53C3(1,3),U+53C4(3),U+8460(4) +U+53C3(0);U+53C2(1,3);U+84E1(2,3),U+53C1(8,9),U+53C2(1,3),U+53C4(3),U+8460(4,8,9) +U+53C4(0);U+53C2(3);U+53C2(3),U+53C3(3),U+53C1(3,4,5),U+84E1(3,4),U+8460(3,4) +U+53C6(0);U+53C6(1,3);U+9749(1,3) + +U+53C7(0);U+53C7(1,3);U+9746(1,3) +U+53C8(0);U+53C8(5); +U+53C9(0);U+53C9(5); +U+53CA(0);U+53CA(5); +U+53CB(0);U+53CB(5); +U+53CC(0);U+53CC(1,3);U+96D9(1,3) +U+53CD(0);U+53CD(5);U+6604(4) +U+53CE(0);U+6536(3);U+6536(3) +U+53D0(0);U+53D0(0); +U+53D1(0);U+53D1(1,3);U+5F42(4),U+767C(1,3),U+9AEA(4),U+9AEE(1,3) +U+53D2(0);U+53D2(0); +U+53D3(0);U+53D3(0); +U+53D4(0);U+53D4(5); +U+53D5(0);U+53D5(0); +U+53D6(0);U+53D6(5); +U+53D7(0);U+53D7(5); +U+53D8(0);U+53D8(1,3);U+5909(3),U+8B8A(1,3) +U+53D9(0);U+53D9(5);U+654D(2,3),U+6558(2) +U+53DB(0);U+53DB(5); +U+53DC(0);U+53DF(3);U+53DF(3) +U+53DF(0);U+53DF(5);U+53DC(3) +U+53E0(0);U+53E0(5);U+66E1(2),U+7589(2),U+758A(2,3),U+8FED(2,4) +U+53E1(0);U+777F(2,3);U+777F(2,3) +U+53E2(0);U+4E1B(1,3);U+4E1B(1,3),U+6B09(1,3,4),U+85C2(1,3,4) +U+53E3(0);U+53E3(5); +U+53E4(0);U+53E4(5); +U+53E5(0);U+53E5(5);U+52FE(3) +U+53E6(0);U+53E6(5); +U+53E8(0);U+53E8(5); +U+53E9(0);U+53E9(5); +U+53EA(0);U+53EA(1,3);U+8879(1),U+96BB(1,3,4) +U+53EB(0);U+53EB(5);U+5602(3) +U+53EC(0);U+53EC(5); +U+53ED(0);U+53ED(5); +U+53EE(0);U+53EE(5); +U+53EF(0);U+53EF(5); +U+53F0(0);U+53F0(1,3);U+6AAF(1,3,4),U+7C49(4),U+81FA(1,3,4),U+98B1(1,3,4) +U+53F1(0);U+53F1(5); +U+53F2(0);U+53F2(5); +U+53F3(0);U+53F3(5); +U+53F4(0);U+53F4(0); +U+53F5(0);U+53F5(5); +U+53F6(0);U+53F6(1,3);U+8449(1,3,4) +U+53F7(0);U+53F7(1,3);U+865F(1,3),U+8B79(3) +U+53F8(0);U+53F8(5); +U+53F9(0);U+53F9(1,3);U+5606(1,3),U+6B4E(4) +U+53FA(0);U+53FA(0); +U+53FB(0);U+53FB(5); +U+53FC(0);U+53FC(5); +U+53FD(0);U+53FD(1,3);U+5630(1,3) +U+53FE(0);U+53FE(0); +U+5401(0);U+5401(1,3);U+7C72(1,3,4) +U+5402(0);U+5402(0); +U+5403(0);U+5403(5);U+55AB(2) +U+5404(0);U+5404(5); +U+5405(0);U+5405(0);U+55A7(3),U+8AE0(2,3) +U+5406(0);U+5406(5); +U+5407(0);U+5407(0); +U+5408(0);U+5408(1,3);U+6546(3),U+95A4(1,3) +U+5409(0);U+5409(5); +U+540A(0);U+540A(5);U+5F14(2,3) +U+540B(0);U+540B(0); +U+540C(0);U+540C(5);U+4EDD(2,3),U+8855(2) + +U+540D(0);U+540D(5); +U+540E(0);U+540E(1,3);U+5F8C(1,3,4) +U+540F(0);U+540F(5); +U+5410(0);U+5410(5); +U+5411(0);U+5411(1,3);U+56AE(1,3,4),U+66CF(4) +U+5412(0);U+5412(5); +U+5413(0);U+5413(1,3);U+5687(1,3,4) +U+5414(0);U+5414(0); +U+5415(0);U+5415(5);U+5442(4),U+90D8(3) +U+5416(0);U+5416(5); +U+5417(0);U+5417(1,3);U+55CE(1,3) +U+5418(0);U+5418(0); +U+5419(0);U+5419(0); +U+541B(0);U+541B(5); +U+541C(0);U+541C(0); +U+541D(0);U+541D(5);U+608B(3) +U+541E(0);U+541E(5);U+5451(4) +U+541F(0);U+541F(5); +U+5420(0);U+5420(5); +U+5421(0);U+5421(5); +U+5423(0);U+5423(5);U+551A(3) +U+5424(0);U+5424(0); +U+5425(0);U+5425(0); +U+5426(0);U+5426(5); +U+5427(0);U+5427(5); +U+5428(0);U+5428(1,3);U+5678(1,3) +U+5429(0);U+5429(5); +U+542A(0);U+542A(3); +U+542B(0);U+542B(5); +U+542C(0);U+542C(1,3);U+8074(3),U+807C(3),U+807D(1,3) +U+542D(0);U+542D(5); +U+542E(0);U+542E(5); +U+542F(0);U+542F(1,3);U+5553(1,3),U+5554(3),U+555F(4) +U+5430(0);U+5B8F(3);U+5B8F(3) +U+5431(0);U+5431(5); +U+5432(0);U+5432(5); +U+5433(0);U+5434(3);U+5434(3),U+5449(4) +U+5434(0);U+5434(5);U+5433(3),U+5449(4) +U+5435(0);U+5435(5); +U+5436(0);U+5450(4);U+5450(4) +U+5437(0);U+5437(0); +U+5438(0);U+5438(5); +U+5439(0);U+5439(5); +U+543A(0);U+543A(0); +U+543B(0);U+543B(5);U+5445(3),U+5461(3) +U+543C(0);U+543C(5); +U+543D(0);U+543D(0); +U+543E(0);U+543E(5); +U+543F(0);U+544A(4);U+544A(4) +U+5440(0);U+5440(5); +U+5441(0);U+5441(0); +U+5442(0);U+5415(4);U+5415(4),U+90D8(3,4) +U+5443(0);U+5443(5); +U+5444(0);U+5444(0); +U+5445(0);U+543B(3);U+543B(3),U+5461(3) +U+5446(0);U+5446(3);U+7343(2,3),U+9A03(2) +U+5447(0);U+5447(0); +U+5448(0);U+5448(5); +U+5449(0);U+5434(4);U+5433(4),U+5434(4) +U+544A(0);U+544A(5);U+543F(4) +U+544B(0);U+544B(5); +U+544D(0);U+544D(0); +U+544E(0);U+544E(0); + +U+544F(0);U+544F(0); +U+5450(0);U+5450(5);U+5436(4) +U+5451(0);U+541E(4);U+541E(4) +U+5452(0);U+5452(1,3);U+5638(1,3) +U+5453(0);U+5453(1,3);U+56C8(1,3),U+5BF1(3) +U+5454(0);U+5454(5); +U+5455(0);U+5455(1,3);U+5614(1,3) +U+5456(0);U+5456(1,3);U+56A6(1,3) +U+5457(0);U+5457(1,3);U+5504(1,3) +U+5458(0);U+5458(1,3);U+54E1(1,3) +U+5459(0);U+5459(3);U+54BC(3) +U+545A(0);U+545A(0); +U+545B(0);U+545B(1,3);U+55C6(1,3) +U+545C(0);U+545C(1,3);U+55DA(1,3) +U+545E(0);U+545E(4); +U+545F(0);U+545F(0); +U+5460(0);U+5460(0); +U+5461(0);U+543B(3);U+543B(3),U+5445(3) +U+5462(0);U+5462(5); +U+5463(0);U+5463(0); +U+5464(0);U+5464(5); +U+5465(0);U+5465(0); +U+5466(0);U+5466(5); +U+5467(0);U+8BCB(3);U+8BCB(3),U+8A46(1,3) +U+5468(0);U+5468(5);U+9031(2,3) +U+546A(0);U+5492(2,3);U+5492(2,3) +U+546B(0);U+546B(3); +U+546C(0);U+546C(0); +U+546D(0);U+546D(0); +U+546E(0);U+546E(0); +U+546F(0);U+546F(0); +U+5470(0);U+5470(0); +U+5471(0);U+5471(5);U+54CC(3) +U+5472(0);U+5472(5); +U+5473(0);U+5473(5); +U+5474(0);U+5474(3); +U+5475(0);U+5475(5);U+55EC(4),U+8A36(3,4),U+8BC3(1,3,4) +U+5476(0);U+5476(5); +U+5477(0);U+5477(5); +U+5478(0);U+5478(5); +U+5479(0);U+5479(0); +U+547A(0);U+547A(3); +U+547B(0);U+547B(5); +U+547C(0);U+547C(5);U+5611(2,3),U+8656(2,3),U+8B3C(2,3) +U+547D(0);U+547D(5); +U+547E(0);U+547E(0); +U+547F(0);U+547F(0); +U+5480(0);U+5480(5);U+5634(3) +U+5481(0);U+5481(0); +U+5482(0);U+5482(5); +U+5483(0);U+5483(0); +U+5484(0);U+5484(5); +U+5485(0);U+5485(3); +U+5486(0);U+5486(5); +U+5487(0);U+5487(3); +U+5488(0);U+5488(0); +U+5489(0);U+5489(0); +U+548B(0);U+548B(5); +U+548C(0);U+548C(5);U+924C(3),U+9FA2(2,3) +U+548D(0);U+548D(0); +U+548E(0);U+548E(5); +U+548F(0);U+548F(5);U+8A60(2,3) +U+5490(0);U+5490(5); + +U+5491(0);U+5491(0); +U+5492(0);U+5492(5);U+546A(2,3) +U+5493(0);U+5493(0); +U+5494(0);U+5494(5); +U+5495(0);U+5495(5); +U+5496(0);U+5496(5); +U+5497(0);U+5497(0); +U+5498(0);U+5498(0); +U+5499(0);U+5499(1,3);U+56A8(1,3) +U+549A(0);U+549A(5); +U+549B(0);U+549B(1,3);U+5680(1,3) +U+549C(0);U+549C(0); +U+549D(0);U+549D(1,3);U+565D(1,3) +U+549E(0);U+549E(0); +U+549F(0);U+549F(0); +U+54A0(0);U+54A0(0); +U+54A1(0);U+54A1(0); +U+54A2(0);U+54A2(0); +U+54A3(0);U+54A3(5); +U+54A4(0);U+54A4(5); +U+54A5(0);U+54A5(3); +U+54A6(0);U+54A6(5); +U+54A7(0);U+54A7(5); +U+54A8(0);U+54A8(5);U+8AEE(3),U+8C18(1,3) +U+54A9(0);U+54A9(5); +U+54AA(0);U+54AA(5); +U+54AB(0);U+54AB(5); +U+54AC(0);U+54AC(5);U+9F69(2,3) +U+54AD(0);U+54AD(5); +U+54AE(0);U+54AE(3); +U+54AF(0);U+54AF(5);U+8A7B(3) +U+54B0(0);U+54B0(0); +U+54B1(0);U+54B1(5);U+507A(2,3),U+5592(2,3) +U+54B2(0);U+7B11(2);U+7B11(2) +U+54B3(0);U+54B3(5); +U+54B4(0);U+54B4(5); +U+54B6(0);U+54B6(0); +U+54B7(0);U+5555(4);U+5555(4) +U+54B8(0);U+54B8(1,3);U+9E79(1,3,4) +U+54B9(0);U+54B9(0); +U+54BA(0);U+54BA(3); +U+54BB(0);U+54BB(5); +U+54BC(0);U+5459(3);U+5459(3) +U+54BD(0);U+54BD(5);U+56A5(2,3) +U+54BE(0);U+54BE(0); +U+54BF(0);U+54BF(5); +U+54C0(0);U+54C0(5); +U+54C1(0);U+54C1(5); +U+54C2(0);U+54C2(5); +U+54C3(0);U+54C3(0); +U+54C4(0);U+54C4(5);U+95A7(2),U+9B28(2,3) +U+54C5(0);U+8BBB(3);U+8BBB(3),U+8A29(1,3) +U+54C6(0);U+54C6(5); +U+54C7(0);U+54C7(5); +U+54C8(0);U+54C8(5); +U+54C9(0);U+54C9(5); +U+54CA(0);U+54CA(0); +U+54CB(0);U+54CB(0); +U+54CC(0);U+54CC(5);U+5471(3) +U+54CD(0);U+54CD(1,3);U+97FF(1,3) +U+54CE(0);U+54CE(5); +U+54CF(0);U+54CF(5); +U+54D0(0);U+54D0(5); + +U+54D1(0);U+54D1(1,3);U+5516(3),U+555E(1,3),U+75D6(7),U+7602(7) +U+54D2(0);U+54D2(1,3);U+5660(1,3) +U+54D3(0);U+54D3(1,3);U+5635(1,3) +U+54D4(0);U+54D4(1,3);U+55F6(1,3) +U+54D5(0);U+54D5(1,3);U+5666(1,3) +U+54D6(0);U+54D6(0); +U+54D7(0);U+54D7(1,3);U+5629(1,3),U+8B41(4) +U+54D8(0);U+54D8(0); +U+54D9(0);U+54D9(1,3);U+5672(1,3) +U+54DA(0);U+54DA(5); +U+54DB(0);U+54DB(0); +U+54DC(0);U+54DC(4);U+568C(4) +U+54DD(0);U+54DD(1,3);U+5665(1,3) +U+54DE(0);U+54DE(5); +U+54DF(0);U+54DF(1,3);U+55B2(1,3) +U+54E0(0);U+54E0(0); +U+54E1(0);U+5458(1,3);U+5458(1,3) +U+54E2(0);U+54E2(3); +U+54E3(0);U+54E3(0); +U+54E4(0);U+54E4(0); +U+54E5(0);U+54E5(5); +U+54E6(0);U+54E6(5); +U+54E7(0);U+54E7(5); +U+54E8(0);U+54E8(5); +U+54E9(0);U+54E9(5); +U+54EA(0);U+54EA(5); +U+54EB(0);U+54EB(0); +U+54EC(0);U+54EC(0); +U+54ED(0);U+54ED(5); +U+54EE(0);U+54EE(5); +U+54EF(0);U+54EF(0); +U+54F0(0);U+54F0(0); +U+54F1(0);U+54F1(0); +U+54F2(0);U+54F2(5);U+5586(2,3) +U+54F3(0);U+54F3(5); +U+54F4(0);U+54F4(3); +U+54F5(0);U+54F5(0); +U+54F7(0);U+54F7(0); +U+54F8(0);U+54F8(0); +U+54F9(0);U+54F9(0); +U+54FA(0);U+54FA(5); +U+54FB(0);U+9F3E(3);U+9F3E(3) +U+54FC(0);U+54FC(5); +U+54FD(0);U+54FD(5); +U+54FE(0);U+54FE(0); +U+54FF(0);U+54FF(5); +U+5500(0);U+5500(0); +U+5501(0);U+5501(5); +U+5502(0);U+5502(3); +U+5503(0);U+5503(0); +U+5504(0);U+5457(1,3);U+5457(1,3) +U+5505(0);U+5505(0); +U+5506(0);U+5506(5); +U+5507(0);U+5507(5);U+8123(3) +U+5508(0);U+5508(0); +U+5509(0);U+5509(5); +U+550A(0);U+550A(0); +U+550B(0);U+550B(0); +U+550C(0);U+550C(0); +U+550D(0);U+550D(0); +U+550E(0);U+550E(0); +U+550F(0);U+550F(5); +U+5510(0);U+5510(5); + +U+5511(0);U+5511(5); +U+5512(0);U+5512(0); +U+5513(0);U+5513(0); +U+5514(0);U+5514(5); +U+5516(0);U+54D1(3);U+54D1(3),U+555E(3),U+75D6(7),U+7602(7) +U+5517(0);U+5517(0); +U+551A(0);U+5423(3);U+5423(3) +U+551B(0);U+551B(1,3);U+561C(1,3) +U+551C(0);U+551C(0); +U+551D(0);U+551D(1,3);U+55CA(1,3) +U+551E(0);U+551E(0); +U+551F(0);U+551F(0); +U+5520(0);U+5520(1,3);U+562E(1,3) +U+5521(0);U+5521(1,3);U+5562(1,3) +U+5522(0);U+5522(1,3);U+55E9(1,3) +U+5523(0);U+5523(5); +U+5524(0);U+5524(4);U+559A(4) +U+5525(0);U+5525(0); +U+5526(0);U+5526(0); +U+5527(0);U+5527(5);U+559E(4) +U+5528(0);U+5528(0); +U+5529(0);U+5529(0); +U+552A(0);U+552A(5); +U+552B(0);U+552B(0); +U+552C(0);U+552C(5); +U+552D(0);U+552D(0); +U+552E(0);U+552E(5); +U+552F(0);U+552F(5); +U+5530(0);U+5530(5); +U+5531(0);U+5531(5); +U+5532(0);U+5532(0); +U+5533(0);U+5533(5); +U+5534(0);U+5534(0); +U+5535(0);U+5535(0); +U+5536(0);U+5536(3); +U+5537(0);U+5537(5); +U+5538(0);U+5FF5(2,3);U+5FF5(2,3) +U+5539(0);U+5539(0); +U+553A(0);U+553A(0); +U+553B(0);U+553B(0); +U+553C(0);U+553C(5); +U+553D(0);U+553D(0); +U+553E(0);U+553E(5); +U+553F(0);U+553F(5); +U+5540(0);U+5540(3); +U+5541(0);U+5541(5); +U+5542(0);U+5542(0); +U+5543(0);U+5543(5); +U+5544(0);U+5544(5); +U+5545(0);U+5545(0); +U+5546(0);U+5546(5);U+8B2A(3) +U+5548(0);U+5548(0); +U+5549(0);U+5549(5); +U+554A(0);U+554A(5); +U+554B(0);U+554B(0); +U+554C(0);U+554C(0); +U+554D(0);U+554D(3); +U+554E(0);U+554E(3); +U+554F(0);U+95EE(1,3);U+95EE(1,3) +U+5550(0);U+5550(5); +U+5551(0);U+5551(0); +U+5552(0);U+5552(3); +U+5553(0);U+542F(1,3);U+542F(1,3),U+5554(3),U+555F(2,3) + +U+5554(0);U+542F(3);U+542F(3),U+5553(3),U+555F(8,9) +U+5555(0);U+5555(5);U+54B7(4) +U+5556(0);U+5556(5);U+5557(2,3),U+5649(2,3),U+56AA(3) +U+5557(0);U+5556(2,3);U+5556(2,3),U+5649(2,3),U+56AA(2,3) +U+5558(0);U+5558(0); +U+5559(0);U+5559(0); +U+555A(0);U+555A(0); +U+555B(0);U+555B(0); +U+555C(0);U+555C(5);U+56BD(3) +U+555D(0);U+555D(0); +U+555E(0);U+54D1(1,3);U+54D1(1,3),U+5516(3),U+75D6(4),U+7602(3) +U+555F(0);U+542F(4);U+542F(4),U+5553(2,3),U+5554(8,9) +U+5561(0);U+5561(5); +U+5562(0);U+5521(1,3);U+5521(1,3) +U+5563(0);U+8854(4);U+8854(4),U+929C(1,3,4) +U+5564(0);U+5564(5); +U+5565(0);U+5565(5); +U+5566(0);U+5566(5); +U+5567(0);U+5567(1,3);U+5616(1,3) +U+5568(0);U+5568(0); +U+5569(0);U+5569(0); +U+556A(0);U+556A(5); +U+556B(0);U+556B(0); +U+556C(0);U+556C(1,3);U+55C7(1,3) +U+556D(0);U+556D(1,3);U+56C0(1,3) +U+556E(0);U+556E(1,3);U+5699(1,3),U+56D3(4),U+9F67(4) +U+556F(0);U+556F(4);U+5613(4) +U+5570(0);U+5570(1,3);U+56C9(1,3) +U+5571(0);U+5571(0); +U+5572(0);U+5572(0); +U+5573(0);U+5573(0); +U+5574(0);U+5574(4);U+563D(4) +U+5575(0);U+5575(5); +U+5576(0);U+5576(5); +U+5577(0);U+5577(5); +U+5578(0);U+5578(1,3);U+5628(4),U+562F(1,3) +U+5579(0);U+5579(0); +U+557B(0);U+557B(5); +U+557C(0);U+557C(5);U+8B15(3) +U+557D(0);U+557D(0); +U+557E(0);U+557E(5); +U+557F(0);U+557F(0); +U+5580(0);U+5580(5); +U+5581(0);U+5581(5); +U+5582(0);U+5582(5);U+9935(2,3) +U+5583(0);U+5583(5);U+5A1A(3),U+8AF5(3) +U+5584(0);U+5584(5);U+8B71(3) +U+5585(0);U+5585(3); +U+5586(0);U+54F2(2,3);U+54F2(2,3) +U+5587(0);U+5587(5); +U+5588(0);U+5588(5); +U+5589(0);U+5589(5); +U+558A(0);U+558A(5); +U+558B(0);U+558B(5); +U+558C(0);U+558C(0); +U+558D(0);U+558D(0); +U+558E(0);U+359E(1,3);U+359E(1,3) +U+558F(0);U+558F(5); +U+5590(0);U+5590(0); +U+5591(0);U+5591(5);U+567E(3),U+7616(2) +U+5592(0);U+54B1(2,3);U+54B1(2,3),U+507A(0,2,3) +U+5593(0);U+5593(0); +U+5594(0);U+5594(5); + +U+5595(0);U+5595(0); +U+5596(0);U+5596(0); +U+5597(0);U+5597(0); +U+5598(0);U+5598(5); +U+5599(0);U+5599(5); +U+559A(0);U+5524(4);U+5524(4) +U+559B(0);U+559B(0); +U+559C(0);U+559C(5);U+6199(3) +U+559D(0);U+559D(5); +U+559E(0);U+5527(4);U+5527(4) +U+559F(0);U+559F(5);U+5633(3),U+6B33(3) +U+55A0(0);U+55A0(0); +U+55A1(0);U+55A1(0); +U+55A2(0);U+55A2(0); +U+55A3(0);U+55A3(0); +U+55A4(0);U+55A4(3); +U+55A5(0);U+55A5(0); +U+55A6(0);U+5CA9(4);U+5CA9(4),U+5D52(2,4),U+58E7(3,4),U+5DCC(4),U+5DD6(2,3,4),U+789E(3,4),U+7939(3,4) + +U+55A7(0);U+55A7(5);U+5405(3),U+8AE0(2,3) +U+55A8(0);U+55A8(0); +U+55A9(0);U+55BB(4);U+55BB(4) +U+55AA(0);U+4E27(1,3);U+4E27(1,3) +U+55AB(0);U+5403(2);U+5403(2) +U+55AC(0);U+4E54(1,3);U+4E54(1,3) +U+55AD(0);U+55AD(0); +U+55AE(0);U+5355(1,3);U+5355(1,3),U+5358(8,9) +U+55AF(0);U+55AF(0); +U+55B0(0);U+9910(3);U+9910(3) +U+55B1(0);U+55B1(5); +U+55B2(0);U+54DF(1,3);U+54DF(1,3) +U+55B3(0);U+55B3(5); +U+55B4(0);U+55B4(0); +U+55B5(0);U+55B5(5); +U+55B6(0);U+8425(4);U+71DF(4),U+8425(4) +U+55B7(0);U+55B7(1,3);U+5674(1,3),U+6B55(3) +U+55B8(0);U+55B8(0); +U+55B9(0);U+55B9(5); +U+55BA(0);U+55BA(0); +U+55BB(0);U+55BB(5);U+55A9(4) +U+55BC(0);U+55BC(0); +U+55BD(0);U+55BD(1,3);U+560D(1,3) +U+55BE(0);U+55BE(1,3);U+56B3(1,3) +U+55BF(0);U+55BF(0); +U+55C0(0);U+55C0(0); +U+55C1(0);U+55C1(4); +U+55C2(0);U+55C2(0); +U+55C3(0);U+55C3(0); +U+55C4(0);U+55C4(5); +U+55C5(0);U+55C5(5); +U+55C6(0);U+545B(1,3);U+545B(1,3) +U+55C7(0);U+556C(1,3);U+556C(1,3) +U+55C8(0);U+55C8(0); +U+55C9(0);U+55C9(5);U+8186(3) +U+55CA(0);U+551D(1,3);U+551D(1,3) +U+55CB(0);U+55CB(0); +U+55CC(0);U+55CC(5); +U+55CD(0);U+55CD(5); +U+55CE(0);U+5417(1,3);U+5417(1,3) +U+55CF(0);U+55CF(0); +U+55D0(0);U+55D0(0); +U+55D1(0);U+55D1(5); +U+55D2(0);U+55D2(5); + +U+55D3(0);U+55D3(5); +U+55D4(0);U+55D4(5); +U+55D5(0);U+55D5(0); +U+55D6(0);U+55D6(5); +U+55D7(0);U+55D7(0); +U+55D8(0);U+55D8(0); +U+55D9(0);U+55D9(0); +U+55DA(0);U+545C(1,3);U+545C(1,3) +U+55DB(0);U+55DB(4); +U+55DC(0);U+55DC(5); +U+55DD(0);U+55DD(5); +U+55DE(0);U+55DE(0); +U+55DF(0);U+55DF(5); +U+55E1(0);U+55E1(5); +U+55E2(0);U+55E2(0); +U+55E3(0);U+55E3(5); +U+55E4(0);U+55E4(5); +U+55E5(0);U+55E5(5); +U+55E6(0);U+55E6(5); +U+55E7(0);U+55E7(0); +U+55E8(0);U+55E8(5); +U+55E9(0);U+5522(1,3);U+5522(1,3) +U+55EA(0);U+55EA(5); +U+55EB(0);U+55EB(1,3);U+56C1(1,3) +U+55EC(0);U+55EC(5);U+5475(4),U+8A36(3,4),U+8BC3(1,3,4) +U+55ED(0);U+55ED(0); +U+55EE(0);U+55EE(0); +U+55EF(0);U+55EF(5); +U+55F0(0);U+55F0(0); +U+55F1(0);U+55F1(0); +U+55F2(0);U+55F2(5); +U+55F3(0);U+55F3(1,3);U+566F(1,3) +U+55F4(0);U+55F4(0); +U+55F5(0);U+55F5(5); +U+55F6(0);U+54D4(1,3);U+54D4(1,3) +U+55F7(0);U+55F7(5); +U+55F9(0);U+55F9(0); +U+55FA(0);U+55FA(3); +U+55FB(0);U+55FB(3); +U+55FC(0);U+5BDE(4);U+5BDE(4) +U+55FD(0);U+55FD(5);U+6B36(3) +U+55FE(0);U+55FE(5); +U+55FF(0);U+55FF(0); +U+5600(0);U+5600(5); +U+5601(0);U+5601(5); +U+5602(0);U+53EB(3);U+53EB(3) +U+5603(0);U+5603(0); +U+5604(0);U+5604(0); +U+5606(0);U+53F9(1,3);U+53F9(1,3),U+6B4E(1,3,4) +U+5607(0);U+5607(0); +U+5608(0);U+5608(5);U+50AE(4) +U+5609(0);U+5609(5); +U+560C(0);U+560C(5); +U+560D(0);U+55BD(1,3);U+55BD(1,3) +U+560E(0);U+560E(5); +U+560F(0);U+560F(5); +U+5610(0);U+5610(0); +U+5611(0);U+547C(2,3);U+547C(2,3),U+8656(2,3),U+8B3C(2,3) +U+5612(0);U+5612(3); +U+5613(0);U+556F(4);U+556F(4) +U+5614(0);U+5455(1,3);U+5455(1,3) +U+5615(0);U+5615(0); +U+5616(0);U+5567(1,3);U+5567(1,3) + +U+5617(0);U+5C1D(1,3);U+5C1D(1,3),U+751E(2,3),U+5690(1,3,4) +U+5618(0);U+5618(5);U+5653(4) +U+5619(0);U+5619(0); +U+561A(0);U+561A(0); +U+561B(0);U+561B(5); +U+561C(0);U+551B(1,3);U+551B(1,3) +U+561D(0);U+561D(0); +U+561E(0);U+561E(5); +U+561F(0);U+561F(5); +U+5621(0);U+5621(0); +U+5622(0);U+5622(0); +U+5623(0);U+5623(5); +U+5624(0);U+5624(1,3);U+56B6(1,3),U+8B7B(3) +U+5625(0);U+5625(0); +U+5626(0);U+5626(0); +U+5627(0);U+5627(5); +U+5628(0);U+5578(4);U+5578(4),U+562F(4) +U+5629(0);U+54D7(1,3);U+54D7(1,3),U+8B41(2,3) +U+562A(0);U+562A(0); +U+562C(0);U+562C(5); +U+562D(0);U+562D(5); +U+562E(0);U+5520(1,3);U+5520(1,3) +U+562F(0);U+5578(1,3);U+5578(1,3),U+5628(4) +U+5630(0);U+53FD(1,3);U+53FD(1,3) +U+5631(0);U+5631(1,3);U+56D1(1,3) +U+5632(0);U+5632(5); +U+5633(0);U+559F(3);U+559F(3),U+6B33(3) +U+5634(0);U+5634(5);U+5480(3) +U+5635(0);U+54D3(1,3);U+54D3(1,3) +U+5636(0);U+5636(5); +U+5638(0);U+5452(1,3);U+5452(1,3) +U+5639(0);U+5639(5); +U+563A(0);U+563A(0); +U+563B(0);U+563B(5);U+8B46(2) +U+563D(0);U+5574(4);U+5574(4) +U+563E(0);U+563E(0); +U+563F(0);U+563F(5); +U+5640(0);U+5640(4); +U+5641(0);U+6076(1,3);U+6076(1,3),U+60E1(4),U+60AA(1,3) +U+5642(0);U+5642(3);U+8B50(3) +U+5643(0);U+5643(0); +U+5645(0);U+5645(3);U+5655(3) +U+5646(0);U+5646(0); +U+5647(0);U+5647(3); +U+5648(0);U+5648(0); +U+5649(0);U+5556(2,3);U+5556(2,3),U+5557(2,3),U+56AA(2,3) +U+564A(0);U+8C32(3);U+8C32(3),U+8B4E(1,3) +U+564C(0);U+564C(5); +U+564D(0);U+564D(5); +U+564E(0);U+564E(5); +U+564F(0);U+564F(0); +U+5650(0);U+5668(3);U+5668(3) +U+5652(0);U+5652(0); +U+5653(0);U+5618(4);U+5618(4) +U+5654(0);U+5654(5); +U+5655(0);U+5645(3);U+5645(3) +U+5657(0);U+5657(5); +U+5658(0);U+5658(5); +U+5659(0);U+5659(5); +U+565A(0);U+565A(0); +U+565B(0);U+565B(0); +U+565C(0);U+565C(1,3);U+5695(1,3) +U+565D(0);U+549D(1,3);U+549D(1,3) + +U+565E(0);U+565E(0); +U+5660(0);U+54D2(1,3);U+54D2(1,3) +U+5662(0);U+5662(5); +U+5663(0);U+5663(0); +U+5664(0);U+5664(5); +U+5665(0);U+54DD(1,3);U+54DD(1,3) +U+5666(0);U+54D5(1,3);U+54D5(1,3) +U+5667(0);U+5667(0); +U+5668(0);U+5668(5);U+5650(3) +U+5669(0);U+5669(5); +U+566A(0);U+566A(5);U+8B5F(2,3) +U+566B(0);U+566B(5); +U+566C(0);U+566C(5); +U+566D(0);U+566D(0); +U+566E(0);U+566E(0); +U+566F(0);U+55F3(1,3);U+55F3(1,3) +U+5670(0);U+5670(3); +U+5671(0);U+5671(5); +U+5672(0);U+54D9(1,3);U+54D9(1,3) +U+5673(0);U+5673(0); +U+5674(0);U+55B7(1,3);U+55B7(1,3),U+6B55(1,3) +U+5676(0);U+5676(5); +U+5677(0);U+5677(0); +U+5678(0);U+5428(1,3);U+5428(1,3) +U+5679(0);U+5F53(1,3);U+5F53(1,3),U+7576(3,4) +U+567A(0);U+567A(0); +U+567B(0);U+567B(5); +U+567C(0);U+567C(5); +U+567E(0);U+5591(3);U+5591(3),U+7616(2,3) +U+567F(0);U+567F(0); +U+5680(0);U+549B(1,3);U+549B(1,3) +U+5681(0);U+5681(0); +U+5682(0);U+5682(0); +U+5683(0);U+5683(4); +U+5684(0);U+5684(0); +U+5685(0);U+5685(5); +U+5686(0);U+5686(5); +U+5687(0);U+5413(1,3);U+5413(1,3) +U+568A(0);U+568A(0); +U+568C(0);U+54DC(4);U+54DC(4) +U+568D(0);U+568D(0); +U+568E(0);U+568E(5); +U+568F(0);U+568F(5);U+5694(4) +U+5690(0);U+5C1D(4);U+5C1D(4),U+5617(0,1,3,4),U+751E(1,2,3,4) +U+5691(0);U+5691(0); +U+5692(0);U+5692(0); +U+5693(0);U+5693(5); +U+5694(0);U+568F(4);U+568F(4) +U+5695(0);U+565C(1,3);U+565C(1,3) +U+5697(0);U+5697(0); +U+5698(0);U+5698(0); +U+5699(0);U+556E(1,3);U+556E(1,3),U+56D3(2),U+9F67(2,3) +U+569A(0);U+569A(0); +U+569B(0);U+569B(0); +U+569C(0);U+569C(0); +U+569D(0);U+569D(0); +U+569F(0);U+569F(0); +U+56A0(0);U+6D4F(4);U+6D4F(4),U+700F(4) +U+56A1(0);U+56A1(0); +U+56A3(0);U+56A3(1,3);U+56BB(3),U+56C2(1,3) +U+56A4(0);U+56A4(0); +U+56A5(0);U+54BD(2,3);U+54BD(2,3) +U+56A6(0);U+5456(1,3);U+5456(1,3) + +U+56A7(0);U+56A7(0); +U+56A8(0);U+5499(1,3);U+5499(1,3) +U+56A9(0);U+56A9(0); +U+56AA(0);U+5556(2,3);U+5556(2,3),U+5557(2,3),U+5649(2,3) +U+56AB(0);U+56AB(0); +U+56AC(0);U+56AC(0); +U+56AD(0);U+56AD(3); +U+56AE(0);U+5411(1,3);U+5411(1,3),U+66CF(1,3,4) +U+56AF(0);U+56AF(5); +U+56B0(0);U+56B0(0); +U+56B1(0);U+56B1(0); +U+56B2(0);U+4EB8(4);U+4EB8(4) +U+56B3(0);U+55BE(1,3);U+55BE(1,3) +U+56B4(0);U+4E25(1,3);U+4E25(1,3),U+53B3(4) +U+56B5(0);U+56B5(0); +U+56B6(0);U+5624(1,3);U+5624(1,3),U+8B7B(1,3) +U+56B7(0);U+56B7(5); +U+56B8(0);U+56B8(0); +U+56B9(0);U+56B9(0); +U+56BB(0);U+56A3(3);U+56A3(3),U+56C2(3) +U+56BC(0);U+56BC(5); +U+56BD(0);U+555C(3);U+555C(3) +U+56BE(0);U+56BE(0); +U+56BF(0);U+56BF(0); +U+56C0(0);U+556D(1,3);U+556D(1,3) +U+56C1(0);U+55EB(1,3);U+55EB(1,3) +U+56C2(0);U+56A3(1,3);U+56A3(1,3),U+56BB(3) +U+56C3(0);U+56C3(0); +U+56C4(0);U+56C4(0); +U+56C5(0);U+5181(1,3);U+5181(1,3) +U+56C6(0);U+56C6(0); +U+56C7(0);U+56C7(0); +U+56C8(0);U+5453(1,3);U+5453(1,3),U+5BF1(1,3) +U+56C9(0);U+5570(1,3);U+5570(1,3) +U+56CA(0);U+56CA(5); +U+56CB(0);U+56CB(3); +U+56CC(0);U+82CF(1,3);U+82CF(1,3),U+8607(4),U+7526(1,3,4),U+8613(1,3,4) +U+56CD(0);U+56CD(0); +U+56CE(0);U+56CE(0); +U+56D0(0);U+56D0(0); +U+56D1(0);U+5631(1,3);U+5631(1,3) +U+56D2(0);U+56D2(0); +U+56D3(0);U+556E(4);U+556E(4),U+5699(2),U+9F67(3) +U+56D4(0);U+56D4(5); +U+56D5(0);U+56D5(0); +U+56D6(0);U+56D6(0); +U+56D7(0);U+56D7(5); +U+56D8(0);U+56DE(3);U+56DE(3),U+56EC(3),U+5EFB(3),U+5EFD(2,3),U+8FF4(1,3,4),U+9025(3,4) + +U+56DA(0);U+56DA(5); +U+56DB(0);U+56DB(5);U+8086(3) +U+56DC(0);U+56DC(0); +U+56DD(0);U+56DD(5); +U+56DE(0);U+56DE(1,3);U+56D8(3),U+56EC(3),U+5EFB(3),U+5EFD(2),U+8FF4(1,3,4),U+9025(4) + +U+56DF(0);U+56DF(5); +U+56E0(0);U+56E0(5); +U+56E1(0);U+56E1(5); +U+56E2(0);U+56E2(1,3);U+56E3(4),U+5718(1,3),U+7CF0(1,3) +U+56E3(0);U+56E2(4);U+56E2(4),U+5718(4),U+7CF0(1,3,4) +U+56E4(0);U+56E4(5); +U+56E5(0);U+56E5(0); +U+56E7(0);U+518F(3);U+518F(3) + +U+56E8(0);U+56E8(0); +U+56E9(0);U+56E9(0); +U+56EA(0);U+56F1(4);U+56F1(4) +U+56EB(0);U+56EB(5); +U+56EC(0);U+56DE(3);U+56DE(3),U+56D8(0,3),U+5EFB(3),U+5EFD(2,3),U+8FF4(1,3,4),U+9025(3,4) + +U+56ED(0);U+56ED(1,3);U+5712(1,3) +U+56EE(0);U+56EE(0); +U+56EF(0);U+56FD(4);U+56FD(4),U+570B(3),U+5700(3,4) +U+56F0(0);U+56F0(1);U+774F(1,4) +U+56F1(0);U+56F1(5);U+56EA(4) +U+56F2(0);U+56F4(4);U+56F4(4),U+570D(4) +U+56F3(0);U+56FE(4);U+56FE(4),U+5716(4) +U+56F4(0);U+56F4(1,3);U+56F2(4),U+570D(1,3) +U+56F5(0);U+56F5(1,3);U+5707(1,3) +U+56F7(0);U+56F7(0); +U+56F9(0);U+56F9(5); +U+56FA(0);U+56FA(5); +U+56FD(0);U+56FD(1,3);U+56EF(4),U+5700(3),U+570B(1,3) +U+56FE(0);U+56FE(1,3);U+56F3(4),U+5716(1,3) +U+56FF(0);U+56FF(5); +U+5700(0);U+56FD(3);U+56FD(3),U+570B(3),U+56EF(0,3,4) +U+5701(0);U+5701(0); +U+5702(0);U+5702(3); +U+5703(0);U+5703(5); +U+5704(0);U+5704(5); +U+5706(0);U+5706(1,3);U+5186(4),U+570E(3),U+5713(1,3) +U+5707(0);U+56F5(1,3);U+56F5(1,3) +U+5708(0);U+5708(5);U+570F(4) +U+5709(0);U+5709(5); +U+570A(0);U+570A(5); +U+570B(0);U+56FD(1,3);U+56EF(3),U+56FD(1,3),U+5700(3) +U+570C(0);U+570C(0); +U+570D(0);U+56F4(1,3);U+56F2(4),U+56F4(1,3) +U+570E(0);U+5706(3);U+5706(3),U+5713(3),U+5186(0,3,4) +U+570F(0);U+5708(4);U+5708(4) +U+5710(0);U+5710(0); +U+5712(0);U+56ED(1,3);U+56ED(1,3) +U+5713(0);U+5706(1,3);U+5186(4),U+5706(1,3),U+570E(3) +U+5714(0);U+5714(0); +U+5715(0);U+5715(0); +U+5716(0);U+56FE(1,3);U+56F3(4),U+56FE(1,3) +U+5718(0);U+56E2(1,3);U+56E2(1,3),U+56E3(4),U+7CF0(4) +U+5719(0);U+5719(0); +U+571A(0);U+571A(0); +U+571B(0);U+571B(0); +U+571C(0);U+571C(5); +U+571D(0);U+571D(3); +U+571E(0);U+571E(0); +U+571F(0);U+571F(5); +U+5720(0);U+5720(0); +U+5722(0);U+753A(4);U+753A(4) +U+5723(0);U+5723(1,3);U+8056(1,3),U+57A9(1,3),U+580A(1,3) +U+5725(0);U+5725(0); +U+5726(0);U+5726(0); +U+5727(0);U+538B(4);U+538B(4),U+58D3(4) +U+5728(0);U+5728(5); +U+5729(0);U+5729(5); +U+572A(0);U+572A(5); +U+572B(0);U+572B(0); +U+572C(0);U+572C(5);U+6747(3) +U+572D(0);U+572D(5);U+73EA(3) +U+572E(0);U+572E(5); + +U+572F(0);U+572F(5); +U+5730(0);U+5730(5);U+58AC(3) +U+5731(0);U+5731(3); +U+5732(0);U+5732(0); +U+5733(0);U+5733(5); +U+5734(0);U+5734(0); +U+5735(0);U+5735(0); +U+5736(0);U+5736(0); +U+5737(0);U+5737(0); +U+5738(0);U+5738(0); +U+5739(0);U+5739(1,3);U+58D9(1,3) +U+573A(0);U+573A(1,3);U+5834(1,3),U+5872(4) +U+573B(0);U+573B(5);U+57A0(3) +U+573C(0);U+573C(0); +U+573E(0);U+573E(5); +U+573F(0);U+573F(0); +U+5740(0);U+5740(5);U+962F(2,3) +U+5741(0);U+5741(3); +U+5742(0);U+5742(5);U+962A(3) +U+5744(0);U+5744(3); +U+5745(0);U+5745(0); +U+5746(0);U+5746(0); +U+5747(0);U+5747(5); +U+5749(0);U+5749(0); +U+574A(0);U+574A(5); +U+574B(0);U+574B(3); +U+574C(0);U+574C(5); +U+574D(0);U+574D(5); +U+574E(0);U+574E(5); +U+574F(0);U+574F(1,3);U+576F(4),U+58CA(4),U+58DE(1,3),U+7623(4) +U+5750(0);U+5750(5);U+5EA7(3) +U+5751(0);U+5751(5);U+962C(2,3) +U+5752(0);U+5752(0); +U+5753(0);U+5753(0); +U+5754(0);U+5754(0); +U+5757(0);U+5757(1,3);U+51F7(3),U+584A(1,3) +U+5759(0);U+5759(0); +U+575A(0);U+575A(1,3);U+5805(1,3) +U+575B(0);U+575B(1,3);U+58C7(1,3),U+7F48(4),U+7F4E(1,3) +U+575C(0);U+575C(1,3);U+58E2(1,3) +U+575D(0);U+575D(1,3);U+57BB(4),U+58E9(1,3) +U+575E(0);U+575E(1,3);U+5862(1,3) +U+575F(0);U+575F(1,3);U+58B3(1,3) +U+5760(0);U+5760(1,3);U+589C(1,3) +U+5761(0);U+5761(5);U+5CA5(3) +U+5762(0);U+5762(0); +U+5764(0);U+5764(5);U+5803(2,3) +U+5765(0);U+5765(0); +U+5766(0);U+5766(5); +U+5767(0);U+5767(0); +U+5768(0);U+5768(5); +U+5769(0);U+5769(5); +U+576A(0);U+576A(5); +U+576B(0);U+576B(5);U+5E97(3) +U+576C(0);U+576C(0); +U+576D(0);U+576D(5); +U+576F(0);U+576F(5);U+574F(4),U+58DE(3),U+58CA(4),U+7623(4) +U+5770(0);U+5770(3); +U+5771(0);U+5771(0); +U+5772(0);U+5772(0); +U+5773(0);U+5773(5); +U+5774(0);U+9646(3);U+9646(3),U+9678(1,3) +U+5775(0);U+4E18(2,3);U+4E18(2,3),U+4E20(2,3) + +U+5776(0);U+5776(5); +U+5777(0);U+5777(5); +U+5779(0);U+5779(0); +U+577A(0);U+577A(0); +U+577B(0);U+577B(5); +U+577C(0);U+577C(5); +U+577D(0);U+577D(0); +U+577E(0);U+577E(0); +U+577F(0);U+9644(2,3);U+9644(2,3) +U+5780(0);U+5780(0); +U+5782(0);U+5782(5);U+57C0(3) +U+5783(0);U+5783(5); +U+5784(0);U+5784(1,3);U+5785(7),U+58DF(1,3),U+58E0(7) +U+5785(0);U+5785(4);U+5784(7),U+58DF(4),U+58E0(4) +U+5786(0);U+5786(1,3);U+58DA(1,3),U+7F4F(3) +U+5788(0);U+5788(0); +U+5789(0);U+5789(0); +U+578A(0);U+578A(0); +U+578B(0);U+578B(5); +U+578C(0);U+578C(5); +U+578D(0);U+578D(0); +U+578E(0);U+578E(0); +U+578F(0);U+578F(0); +U+5790(0);U+5790(3); +U+5791(0);U+5791(0); +U+5792(0);U+5792(1,3);U+58D8(1,3),U+58E8(3) +U+5793(0);U+5793(5);U+9654(3) +U+5794(0);U+5794(0); +U+5795(0);U+5795(0); +U+5797(0);U+5797(3); +U+5798(0);U+5798(0); +U+5799(0);U+5799(0); +U+579A(0);U+5C27(3);U+5C27(3),U+582F(1,3),U+5C2D(3,4) +U+579B(0);U+579B(5);U+579C(2,3) +U+579C(0);U+579B(2,3);U+579B(2,3) +U+579D(0);U+579D(3); +U+579E(0);U+579E(0); +U+579F(0);U+579F(0); +U+57A0(0);U+57A0(5);U+573B(3) +U+57A1(0);U+57A1(5); +U+57A2(0);U+57A2(5); +U+57A3(0);U+57A3(5); +U+57A4(0);U+57A4(5); +U+57A5(0);U+57A5(0); +U+57A6(0);U+57A6(1,3);U+58BE(1,3) +U+57A7(0);U+57A7(5); +U+57A9(0);U+57A9(1,3);U+580A(1,3),U+8056(3),U+5723(1,3) +U+57AA(0);U+57AA(0); +U+57AB(0);U+57AB(1,3);U+588A(1,3) +U+57AC(0);U+57AC(0); +U+57AD(0);U+57AD(1,3);U+57E1(1,3) +U+57AE(0);U+57AE(5); +U+57AF(0);U+57AF(4); +U+57B0(0);U+57B0(0); +U+57B1(0);U+57B1(4);U+58CB(4) +U+57B2(0);U+57B2(1,3);U+584F(1,3) +U+57B3(0);U+57B3(0); +U+57B4(0);U+57B4(5);U+5816(7) +U+57B5(0);U+57B5(0); +U+57B6(0);U+57B6(0); +U+57B7(0);U+57B7(0); +U+57B8(0);U+57B8(5); +U+57B9(0);U+57B9(4); + +U+57BA(0);U+57BA(0); +U+57BB(0);U+575D(4);U+575D(4),U+58E9(3) +U+57BC(0);U+57BC(0); +U+57BD(0);U+57BD(0); +U+57BE(0);U+57BE(0); +U+57BF(0);U+57BF(0); +U+57C0(0);U+5782(3);U+5782(3) +U+57C1(0);U+57C1(0); +U+57C2(0);U+57C2(5); +U+57C3(0);U+57C3(5); +U+57C4(0);U+57C4(0); +U+57C5(0);U+57C5(0); +U+57C6(0);U+57C6(0); +U+57C7(0);U+57C7(3); +U+57C8(0);U+57C8(0); +U+57C9(0);U+57C9(0); +U+57CB(0);U+57CB(5); +U+57CC(0);U+57CC(4); +U+57CD(0);U+57CD(0); +U+57CE(0);U+57CE(5); +U+57CF(0);U+57CF(5); +U+57D0(0);U+57D0(0); +U+57D2(0);U+57D2(5);U+57D3(4) +U+57D3(0);U+57D2(4);U+57D2(4) +U+57D4(0);U+57D4(5); +U+57D5(0);U+57D5(5); +U+57D6(0);U+57D6(0); +U+57D8(0);U+57D8(1,3);U+5852(1,3) +U+57D9(0);U+57D9(1,3);U+5864(1,3),U+58CE(4) +U+57DA(0);U+57DA(1,3);U+581D(1,3) +U+57DC(0);U+91CE(2,3);U+91CE(2,3) +U+57DD(0);U+57DD(5); +U+57DF(0);U+57DF(5); +U+57E0(0);U+57E0(5); +U+57E1(0);U+57AD(1,3);U+57AD(1,3) +U+57E2(0);U+57E2(0); +U+57E3(0);U+57E3(0); +U+57E4(0);U+57E4(5); +U+57E5(0);U+57E5(0); +U+57E6(0);U+57E6(0); +U+57E7(0);U+57E7(3); +U+57E8(0);U+57E8(0); +U+57E9(0);U+57E9(3); +U+57EA(0);U+57EA(0); +U+57EB(0);U+57EB(0); +U+57EC(0);U+57EC(0); +U+57ED(0);U+57ED(5); +U+57EE(0);U+57EE(0); +U+57EF(0);U+57EF(5); +U+57F0(0);U+57F0(0); +U+57F1(0);U+57F1(0); +U+57F2(0);U+57F2(3); +U+57F3(0);U+57F3(4); +U+57F4(0);U+57F4(5); +U+57F5(0);U+57F5(0); +U+57F6(0);U+57F6(0); +U+57F7(0);U+6267(1,3);U+6267(1,3),U+74E1(1,3) +U+57F8(0);U+57F8(5); +U+57F9(0);U+57F9(5); +U+57FA(0);U+57FA(5); +U+57FB(0);U+57FB(0); +U+57FC(0);U+5D0E(7);U+5D0E(7),U+7895(3) +U+57FD(0);U+57FD(5); + +U+57FE(0);U+57FE(0); +U+57FF(0);U+57FF(0); +U+5800(0);U+5800(5); +U+5801(0);U+5801(0); +U+5802(0);U+5802(5); +U+5803(0);U+5764(2,3);U+5764(2,3) +U+5804(0);U+5804(0); +U+5805(0);U+575A(1,3);U+575A(1,3) +U+5806(0);U+5806(5); +U+5807(0);U+5807(5);U+84F3(3),U+83EB(4) +U+5808(0);U+7F38(3);U+7F38(3) +U+5809(0);U+5809(0); +U+580A(0);U+57A9(1,3);U+57A9(1,3),U+8056(1,3),U+5723(1,3) +U+580B(0);U+580B(5);U+5874(3) +U+580C(0);U+580C(0); +U+580D(0);U+580D(5); +U+580E(0);U+580E(0); +U+580F(0);U+580F(0); +U+5810(0);U+5810(0); +U+5811(0);U+5811(1,3);U+5879(1,3) +U+5812(0);U+5812(0); +U+5813(0);U+5813(0); +U+5814(0);U+5814(0); +U+5815(0);U+5815(1,3);U+58AE(1,3),U+58AF(3) +U+5816(0);U+57B4(7);U+57B4(7) +U+5819(0);U+5819(5); +U+581A(0);U+581A(0); +U+581B(0);U+581B(0); +U+581C(0);U+581C(0); +U+581D(0);U+57DA(1,3);U+57DA(1,3) +U+581E(0);U+581E(5); +U+581F(0);U+581F(0); +U+5820(0);U+5820(5); +U+5821(0);U+5821(5); +U+5822(0);U+5822(0); +U+5823(0);U+5823(0); +U+5824(0);U+5824(5);U+9684(2,3) +U+5825(0);U+5825(0); +U+5826(0);U+9636(4);U+968E(2,3),U+9636(4) +U+5827(0);U+58D6(4);U+58D6(4) +U+5828(0);U+5828(0); +U+5829(0);U+5829(0); +U+582A(0);U+582A(5); +U+582B(0);U+582B(0); +U+582C(0);U+582C(0); +U+582D(0);U+582D(3); +U+582E(0);U+582E(3); +U+582F(0);U+5C27(1,3);U+5C27(1,3),U+5C2D(4),U+579A(0,1,3) +U+5830(0);U+5830(5); +U+5831(0);U+62A5(1,3);U+62A5(1,3) +U+5832(0);U+5832(3); +U+5833(0);U+5833(0); +U+5834(0);U+573A(1,3);U+573A(1,3),U+5872(2,3) +U+5835(0);U+5835(5); +U+5836(0);U+5836(3); +U+5837(0);U+7AA8(3);U+7AA8(3) +U+5838(0);U+5838(0); +U+5839(0);U+5839(0); +U+583A(0);U+754C(3);U+754C(3),U+754D(3) +U+583B(0);U+583B(0); +U+583C(0);U+583C(0); +U+583D(0);U+583D(0); +U+583E(0);U+583E(0); + +U+583F(0);U+583F(0); +U+5840(0);U+5840(0); +U+5842(0);U+5842(0); +U+5843(0);U+5843(0); +U+5844(0);U+5844(5); +U+5845(0);U+5845(0); +U+5846(0);U+5846(4);U+58EA(4) +U+5847(0);U+5847(0); +U+5848(0);U+5848(0);U+588D(4) +U+5849(0);U+5849(0); +U+584A(0);U+5757(1,3);U+51F7(3),U+5757(1,3) +U+584B(0);U+8314(1,3);U+8314(1,3) +U+584C(0);U+584C(5); +U+584D(0);U+584D(5); +U+584E(0);U+584E(0); +U+584F(0);U+57B2(1,3);U+57B2(1,3) +U+5851(0);U+5851(5); +U+5852(0);U+57D8(1,3);U+57D8(1,3) +U+5853(0);U+5853(0); +U+5854(0);U+5854(5);U+5896(2,3) +U+5855(0);U+5855(0); +U+5857(0);U+6D82(1,3);U+6D82(1,3),U+51C3(0,1,3,4) +U+5858(0);U+5858(5); +U+5859(0);U+786E(4);U+786E(4),U+78BA(1,3,4),U+78BB(4),U+792D(3,4) +U+585A(0);U+51A2(2,3);U+51A2(2,3) +U+585B(0);U+585B(0); +U+585C(0);U+585C(0);U+5873(3) +U+585D(0);U+585D(0); +U+585E(0);U+585E(5); +U+585F(0);U+846C(2,3);U+846C(2,3) +U+5861(0);U+586B(4);U+586B(4) +U+5862(0);U+575E(1,3);U+575E(1,3) +U+5863(0);U+5863(3); +U+5864(0);U+57D9(1,3);U+57D9(1,3),U+58CE(1,3,4) +U+5865(0);U+5865(5); +U+5868(0);U+5868(0); +U+5869(0);U+76D0(3);U+76D0(3),U+9E7D(3) +U+586A(0);U+586A(0); +U+586B(0);U+586B(5);U+5861(4) +U+586C(0);U+586C(5); +U+586D(0);U+586D(0); +U+586E(0);U+586E(0); +U+586F(0);U+586F(0); +U+5870(0);U+5870(0); +U+5871(0);U+5871(0); +U+5872(0);U+573A(4);U+573A(4),U+5834(2,3) +U+5873(0);U+5873(3);U+585C(3) +U+5874(0);U+580B(3);U+580B(3) +U+5875(0);U+5C18(1,3);U+5C18(1,3) +U+5876(0);U+5876(0); +U+5878(0);U+5878(3); +U+5879(0);U+5811(1,3);U+5811(1,3) +U+587A(0);U+587A(3); +U+587B(0);U+587B(0); +U+587C(0);U+587C(0); +U+587D(0);U+587D(3); +U+587E(0);U+587E(5); +U+587F(0);U+587F(0); +U+5880(0);U+5880(5); +U+5881(0);U+5881(5); +U+5882(0);U+6807(3);U+6807(3),U+6A19(1,3) +U+5883(0);U+5883(5); +U+5884(0);U+5884(0); + +U+5885(0);U+5885(5); +U+5886(0);U+5886(0); +U+5887(0);U+969C(3);U+969C(3) +U+5888(0);U+5888(0); +U+5889(0);U+5889(5); +U+588A(0);U+57AB(1,3);U+57AB(1,3) +U+588B(0);U+588B(3); +U+588C(0);U+588C(3); +U+588D(0);U+5848(4);U+5848(4) +U+588E(0);U+90ED(3);U+90ED(3) +U+588F(0);U+588F(0); +U+5890(0);U+5890(3); +U+5891(0);U+5891(0); +U+5892(0);U+5892(5); +U+5893(0);U+5893(5); +U+5894(0);U+5894(0); +U+5896(0);U+5854(2,3);U+5854(2,3) +U+5897(0);U+589E(4);U+589E(4) +U+5898(0);U+5898(0); +U+5899(0);U+5899(1,3);U+58BB(1,3),U+7246(4) +U+589A(0);U+589A(5); +U+589B(0);U+589B(0); +U+589C(0);U+5760(1,3);U+5760(1,3) +U+589D(0);U+589D(3); +U+589E(0);U+589E(5);U+5897(4) +U+589F(0);U+589F(5); +U+58A0(0);U+58A0(0); +U+58A1(0);U+58A1(3); +U+58A2(0);U+58A2(3); +U+58A3(0);U+58A3(3); +U+58A4(0);U+58A4(0); +U+58A5(0);U+7583(3);U+7583(3),U+757D(3) +U+58A6(0);U+58A6(0); +U+58A7(0);U+58A7(0); +U+58A8(0);U+58A8(5); +U+58A9(0);U+58A9(5); +U+58AB(0);U+58AB(0);U+6A3D(3),U+7F47(2,3) +U+58AC(0);U+5730(3);U+5730(3) +U+58AD(0);U+58AD(0); +U+58AE(0);U+5815(1,3);U+5815(1,3),U+58AF(1,3) +U+58AF(0);U+5815(3);U+5815(3),U+58AE(1,3) +U+58B0(0);U+58B0(0); +U+58B1(0);U+58B1(0); +U+58B2(0);U+58B2(0); +U+58B3(0);U+575F(1,3);U+575F(1,3) +U+58B4(0);U+58B4(0); +U+58B7(0);U+58B7(0); +U+58B8(0);U+58B8(0); +U+58B9(0);U+58B9(0); +U+58BA(0);U+58BA(3); +U+58BB(0);U+5899(1,3);U+5899(1,3),U+7246(2,3) +U+58BC(0);U+58BC(5); +U+58BD(0);U+58BD(3); +U+58BE(0);U+57A6(1,3);U+57A6(1,3) +U+58BF(0);U+58BF(0); +U+58C1(0);U+58C1(5); +U+58C2(0);U+58C2(0); +U+58C5(0);U+58C5(5); +U+58C6(0);U+58C6(0); +U+58C7(0);U+575B(1,3);U+575B(1,3),U+7F4E(4),U+7F48(1,3,4) +U+58C8(0);U+58C8(0); +U+58C9(0);U+58C9(0); +U+58CA(0);U+574F(4);U+574F(4),U+58DE(4),U+576F(4),U+7623(4) + +U+58CB(0);U+57B1(4);U+57B1(4) +U+58CE(0);U+57D9(4);U+57D9(4),U+5864(1,3,4) +U+58CF(0);U+58CF(0); +U+58D1(0);U+58D1(5); +U+58D2(0);U+58D2(3); +U+58D3(0);U+538B(1,3);U+538B(1,3),U+5727(4) +U+58D4(0);U+58D4(0); +U+58D5(0);U+58D5(5); +U+58D6(0);U+58D6(4);U+5827(4) +U+58D7(0);U+58D7(0); +U+58D8(0);U+5792(1,3);U+5792(1,3),U+58E8(1,3) +U+58D9(0);U+5739(1,3);U+5739(1,3) +U+58DA(0);U+5786(1,3);U+5786(1,3),U+7F4F(1,3) +U+58DB(0);U+58DB(0); +U+58DD(0);U+58DD(0); +U+58DE(0);U+574F(1,3);U+574F(1,3),U+576F(3),U+58CA(4),U+7623(1,3,4) +U+58DF(0);U+5784(1,3,4);U+5784(1,3,4),U+5785(4),U+58E0(3) +U+58E0(0);U+5785(4);U+5784(7),U+5785(4),U+58DF(3) +U+58E2(0);U+575C(1,3);U+575C(1,3) +U+58E3(0);U+58E3(3); +U+58E4(0);U+58E4(5); +U+58E5(0);U+58E5(0); +U+58E7(0);U+5CA9(3);U+5CA9(3),U+55A6(0,3,4),U+5D52(2,3,4),U+5DCC(3,4),U+5DD6(2,3,4),U+789E(3,4),U+7939(3,4) +U+58E8(0);U+5792(3);U+5792(3),U+58D8(1,3) +U+58E9(0);U+575D(1,3);U+575D(1,3),U+57BB(3) +U+58EA(0);U+5846(4);U+5846(4) +U+58EB(0);U+58EB(5); +U+58EC(0);U+58EC(5); +U+58ED(0);U+58ED(0); +U+58EE(0);U+58EE(1,3);U+58EF(1,3,4) +U+58EF(0);U+58EE(1,3);U+58EE(1,3) +U+58F0(0);U+58F0(1,3);U+8072(1,3) +U+58F1(0);U+58F9(4);U+58F9(4),U+4E00(3,4,5),U+5F0C(3,4) +U+58F2(0);U+5356(4);U+5356(4),U+8CE3(4) +U+58F3(0);U+58F3(1,3);U+6BBB(1,3),U+6BBC(4) +U+58F4(0);U+58F4(3); +U+58F6(0);U+58F6(1,3);U+58FA(1,3),U+58F7(3) +U+58F7(0);U+58F6(3);U+58F6(3),U+58FA(3) +U+58F8(0);U+58F8(1,3);U+58FC(1,3) +U+58F9(0);U+58F9(5);U+4E00(3),U+58F1(4),U+5F0C(3) +U+58FA(0);U+58F6(1,3);U+58F6(1,3),U+58F7(3) +U+58FB(0);U+58FB(3); +U+58FC(0);U+58F8(1,3);U+58F8(1,3) +U+58FD(0);U+5BFF(1,3);U+5900(4),U+5BFF(1,3) +U+58FE(0);U+58FE(0); +U+58FF(0);U+8E72(4);U+8E72(4) +U+5900(0);U+5BFF(4);U+58FD(4),U+5BFF(4) +U+5902(0);U+5902(5); +U+5903(0);U+5903(0); +U+5904(0);U+5904(1,3);U+8655(1,3) +U+5906(0);U+5906(0); +U+5907(0);U+5907(1,3);U+4FFB(4),U+5079(3),U+5099(1,3) +U+5909(0);U+53D8(3);U+53D8(3),U+8B8A(3) +U+590A(0);U+590A(0); +U+590B(0);U+590B(0); +U+590C(0);U+590C(0); +U+590D(0);U+590D(1,3);U+5FA9(1,3),U+8907(1,3),U+8986(1,3) +U+590E(0);U+590E(0); +U+590F(0);U+590F(5); +U+5910(0);U+5910(4);U+657B(4) +U+5912(0);U+5912(3); +U+5914(0);U+5914(5); + +U+5915(0);U+5915(5); +U+5916(0);U+5916(5); +U+5917(0);U+5917(3); +U+5918(0);U+536F(2,3);U+536F(2,3),U+623C(2,3) +U+5919(0);U+5919(5); +U+591A(0);U+591A(5);U+591B(4) +U+591B(0);U+591A(4);U+591A(4) +U+591C(0);U+591C(5);U+4EB1(2,3) +U+591D(0);U+591D(4); +U+591E(0);U+591E(0); +U+591F(0);U+591F(5);U+5920(2,3) +U+5920(0);U+591F(2,3);U+591F(2,3) +U+5921(0);U+5921(0); +U+5922(0);U+68A6(1,3);U+68A6(1,3) +U+5924(0);U+5924(5); +U+5925(0);U+5925(0),U+4F19(1,3);U+4F19(1,3) +U+5926(0);U+5926(0); +U+5927(0);U+5927(5); +U+5928(0);U+5928(0); +U+5929(0);U+5929(5); +U+592A(0);U+592A(5); +U+592B(0);U+592B(5);U+4F15(3) +U+592C(0);U+592C(4); +U+592D(0);U+592D(5);U+6B80(2,3) +U+592E(0);U+592E(5); +U+592F(0);U+592F(5); +U+5930(0);U+5930(0); +U+5931(0);U+5931(5); +U+5932(0);U+5932(3);U+672C(3) +U+5934(0);U+5934(1,3);U+982D(1,3) +U+5935(0);U+5935(0); +U+5937(0);U+5937(5);U+4F87(3) +U+5938(0);U+5938(1,3);U+8A87(1,3) +U+5939(0);U+5939(1,3);U+593E(1,3),U+88CC(4) +U+593A(0);U+593A(1,3);U+596A(1,3),U+6553(3) +U+593B(0);U+593B(0); +U+593C(0);U+593C(5); +U+593D(0);U+593D(0); +U+593E(0);U+5939(1,3);U+5939(1,3),U+88CC(1,3,4) +U+593F(0);U+593F(0); +U+5940(0);U+5940(0); +U+5941(0);U+5941(1,3);U+5333(2,3),U+5969(1,3) +U+5942(0);U+5942(5);U+5950(4) +U+5943(0);U+5943(0); +U+5944(0);U+5944(5); +U+5945(0);U+5945(3); +U+5946(0);U+5946(0); +U+5947(0);U+5947(5);U+7AD2(3) +U+5948(0);U+5948(5);U+67F0(3) +U+5949(0);U+5949(5); +U+594A(0);U+594A(0); +U+594B(0);U+594B(1,3);U+596E(1,3) +U+594C(0);U+70B9(4);U+70B9(4),U+9EDE(4) +U+594D(0);U+594D(0); +U+594E(0);U+594E(5); +U+594F(0);U+594F(5); +U+5950(0);U+5942(4);U+5942(4) +U+5951(0);U+5951(5);U+6814(3) +U+5952(0);U+5952(0); +U+5953(0);U+5953(3); +U+5954(0);U+5954(5);U+7287(2,3),U+9029(2,3) +U+5955(0);U+5955(5); +U+5956(0);U+5956(1,3,4);U+734E(4),U+5968(4),U+596C(1,3) + +U+5957(0);U+5957(5); +U+5958(0);U+5958(5); +U+595A(0);U+595A(5); +U+595C(0);U+595C(0); +U+595D(0);U+595D(0); +U+595E(0);U+595E(0); +U+595F(0);U+595F(0); +U+5960(0);U+5960(5); +U+5961(0);U+5961(0); +U+5962(0);U+5962(5); +U+5963(0);U+5963(0); +U+5964(0);U+5964(0); +U+5965(0);U+5965(5);U+5967(7) +U+5966(0);U+5966(0); +U+5967(0);U+5965(7);U+5965(7) +U+5968(0);U+5956(4);U+734E(8,9),U+5956(4),U+596C(3) +U+5969(0);U+5941(1,3);U+5333(2),U+5941(1,3) +U+596A(0);U+593A(1,3);U+593A(1,3),U+6553(1,3) +U+596B(0);U+596B(0); +U+596C(0);U+5956(1,3);U+734E(2),U+5956(1,3),U+5968(3) +U+596D(0);U+596D(0); +U+596E(0);U+594B(1,3);U+594B(1,3) +U+596F(0);U+596F(0); +U+5970(0);U+5970(0); +U+5971(0);U+5971(3); +U+5972(0);U+5972(0); +U+5973(0);U+5973(5); +U+5974(0);U+5974(5); +U+5975(0);U+5975(0); +U+5976(0);U+5976(5);U+59B3(2),U+5B2D(2,3),U+4F32(2,3),U+4F60(2,3,5),U+511E(2,3) +U+5977(0);U+5977(0); +U+5978(0);U+5978(5);U+59E6(2) +U+5979(0);U+5979(5); +U+597A(0);U+597A(0); +U+597B(0);U+597B(0); +U+597C(0);U+59F9(3);U+59F9(3) +U+597D(0);U+597D(5); +U+597E(0);U+597E(0); +U+597F(0);U+597F(0); +U+5980(0);U+5980(0); +U+5981(0);U+5981(5); +U+5982(0);U+5982(5); +U+5983(0);U+5983(5); +U+5984(0);U+5984(5); +U+5985(0);U+5985(0); +U+5986(0);U+5986(1,3);U+599D(1,3,4) +U+5987(0);U+5987(1,3);U+5A66(1,3) +U+5988(0);U+5988(1,3);U+5ABD(1,3) +U+5989(0);U+5989(3); +U+598A(0);U+598A(5);U+59D9(2) +U+598B(0);U+598B(0); +U+598C(0);U+598C(0); +U+598D(0);U+598D(5);U+59F8(3) +U+598E(0);U+598E(0); +U+598F(0);U+598F(0); +U+5990(0);U+5990(0); +U+5991(0);U+5991(0); +U+5992(0);U+5992(5);U+59AC(2,3) +U+5993(0);U+5993(5); +U+5994(0);U+5994(0); +U+5995(0);U+5995(0); +U+5996(0);U+5996(5);U+7945(3),U+8A1E(3) +U+5997(0);U+5997(5); + +U+5998(0);U+5998(0); +U+5999(0);U+5999(5);U+7385(2,3) +U+599A(0);U+599A(0); +U+599C(0);U+599C(0); +U+599D(0);U+5986(1,3);U+5986(1,3) +U+599E(0);U+599E(5); +U+599F(0);U+599F(0); +U+59A0(0);U+59A0(0); +U+59A1(0);U+59A1(0); +U+59A2(0);U+59A2(0); +U+59A3(0);U+59A3(5); +U+59A4(0);U+59A4(5); +U+59A5(0);U+59A5(5); +U+59A6(0);U+59A6(0); +U+59A7(0);U+59A7(0); +U+59A8(0);U+59A8(5); +U+59A9(0);U+59A9(1,3);U+5AF5(1,3) +U+59AA(0);U+59AA(1,3);U+5AD7(1,3) +U+59AB(0);U+59AB(1,3);U+5AAF(3),U+5B00(1) +U+59AC(0);U+5992(2,3);U+5992(2,3) +U+59AD(0);U+59AD(0); +U+59AE(0);U+59AE(5); +U+59AF(0);U+59AF(5); +U+59B0(0);U+59B0(0); +U+59B1(0);U+59B1(0); +U+59B2(0);U+59B2(5); +U+59B3(0);U+59B3(0);U+4F60(2,3),U+5976(2),U+5B2D(3),U+4F32(2,3,5),U+511E(2,3) +U+59B4(0);U+59B4(0); +U+59B5(0);U+59B5(0); +U+59B6(0);U+59B6(0); +U+59B8(0);U+59B8(3); +U+59B9(0);U+59B9(5); +U+59BA(0);U+59BA(0); +U+59BB(0);U+59BB(5); +U+59BC(0);U+59BC(0); +U+59BD(0);U+59BD(0); +U+59BE(0);U+59BE(5); +U+59BF(0);U+59BF(3); +U+59C0(0);U+59C0(0); +U+59C1(0);U+59C1(0); +U+59C2(0);U+59C2(0); +U+59C3(0);U+59C3(0); +U+59C4(0);U+59C4(0); +U+59C5(0);U+59C5(0); +U+59C6(0);U+59C6(5); +U+59C7(0);U+59C7(0); +U+59C8(0);U+59C8(0); +U+59C9(0);U+59CA(2,3);U+59CA(2,3) +U+59CA(0);U+59CA(5);U+59C9(2,3) +U+59CB(0);U+59CB(5); +U+59CC(0);U+59CC(0); +U+59CD(0);U+59D7(2,3);U+59D7(2,3) +U+59CE(0);U+59CE(0); +U+59CF(0);U+59CF(0); +U+59D0(0);U+59D0(5);U+5A8E(3) +U+59D1(0);U+59D1(5); +U+59D2(0);U+59D2(5); +U+59D3(0);U+59D3(5); +U+59D4(0);U+59D4(5); +U+59D5(0);U+59D5(0); +U+59D6(0);U+59D6(0); +U+59D7(0);U+59D7(5);U+59CD(2,3) +U+59D8(0);U+59D8(5); + +U+59D9(0);U+598A(2);U+598A(2) +U+59DA(0);U+59DA(5); +U+59DB(0);U+59DB(0); +U+59DC(0);U+59DC(1,3);U+8591(1,3,4) +U+59DD(0);U+59DD(5); +U+59DE(0);U+59DE(3); +U+59DF(0);U+59DF(0); +U+59E0(0);U+59E0(0); +U+59E1(0);U+59E1(0); +U+59E2(0);U+5A1F(3);U+5A1F(3) +U+59E3(0);U+59E3(5); +U+59E4(0);U+59E4(3); +U+59E5(0);U+59E5(5); +U+59E6(0);U+5978(2);U+5978(2) +U+59E8(0);U+59E8(5); +U+59E9(0);U+59E9(0); +U+59EA(0);U+4F84(2);U+4F84(2) +U+59EB(0);U+59EC(4);U+59EC(4) +U+59EC(0);U+59EC(5);U+59EB(4) +U+59ED(0);U+59ED(0); +U+59EE(0);U+59EE(0); +U+59EF(0);U+59EF(0); +U+59F0(0);U+59F0(0); +U+59F1(0);U+59F1(3); +U+59F2(0);U+59F2(0); +U+59F3(0);U+59F3(0); +U+59F4(0);U+59F4(0); +U+59F5(0);U+59F5(0); +U+59F6(0);U+59F6(0); +U+59F7(0);U+59F7(3); +U+59F8(0);U+598D(3);U+598D(3) +U+59F9(0);U+59F9(5);U+597C(3) +U+59FA(0);U+59FA(0); +U+59FB(0);U+59FB(5);U+5A63(2) +U+59FC(0);U+59FC(0); +U+59FD(0);U+59FD(0); +U+59FE(0);U+59FE(0); +U+59FF(0);U+59FF(5); +U+5A00(0);U+5A00(0); +U+5A01(0);U+5A01(5); +U+5A02(0);U+5A02(3); +U+5A03(0);U+5A03(5); +U+5A04(0);U+5A04(1,3);U+5A41(1,3) +U+5A05(0);U+5A05(1,3);U+5A6D(1,3) +U+5A06(0);U+5A06(1,3);U+5B08(1,3) +U+5A07(0);U+5A07(1,3);U+5B0C(1,3) +U+5A08(0);U+5A08(1,3);U+5B4C(1,3) +U+5A09(0);U+5A09(5); +U+5A0A(0);U+5A0A(0); +U+5A0B(0);U+5A0B(0); +U+5A0C(0);U+5A0C(5); +U+5A0D(0);U+5A0D(0); +U+5A0E(0);U+5A0E(0); +U+5A0F(0);U+5A0F(0); +U+5A10(0);U+5A10(0); +U+5A11(0);U+5A11(5); +U+5A12(0);U+5A12(0); +U+5A13(0);U+5A13(5); +U+5A14(0);U+5A14(0); +U+5A15(0);U+5A15(3); +U+5A16(0);U+5A16(4); +U+5A17(0);U+5A17(3); +U+5A18(0);U+5A18(5);U+5B22(2,4),U+5B43(2) + +U+5A19(0);U+5A19(0); +U+5A1A(0);U+5583(3);U+5583(3),U+8AF5(3) +U+5A1B(0);U+5A31(4);U+5A2F(8,9),U+5A31(4) +U+5A1C(0);U+5A1C(5); +U+5A1D(0);U+5A1D(0); +U+5A1E(0);U+5A1E(3); +U+5A1F(0);U+5A1F(5);U+59E2(3) +U+5A20(0);U+5A20(5); +U+5A21(0);U+5A21(0); +U+5A22(0);U+5A22(0); +U+5A23(0);U+5A23(5); +U+5A25(0);U+5A25(5); +U+5A27(0);U+5A27(0); +U+5A28(0);U+5A28(0); +U+5A29(0);U+5A29(5); +U+5A2A(0);U+5A2A(0); +U+5A2B(0);U+5A2B(0); +U+5A2D(0);U+5A2D(0); +U+5A2E(0);U+5A2E(0); +U+5A2F(0);U+5A31(4);U+5A1B(8,9),U+5A31(4) +U+5A31(0);U+5A31(5);U+5A1B(4),U+5A2F(4) +U+5A32(0);U+5A32(1,3);U+5AA7(1,3) +U+5A33(0);U+5A33(0); +U+5A34(0);U+5A34(1,3,4);U+5AFA(4),U+5AFB(1,3) +U+5A35(0);U+5A35(0); +U+5A36(0);U+5A36(5); +U+5A37(0);U+5A37(0); +U+5A38(0);U+5A38(0); +U+5A39(0);U+5A39(3); +U+5A3A(0);U+5A3A(0); +U+5A3B(0);U+5A3B(0); +U+5A3C(0);U+5A3C(5); +U+5A3D(0);U+5A3D(0); +U+5A3E(0);U+5A3E(0); +U+5A3F(0);U+5A40(2,4);U+5A40(2,4) +U+5A40(0);U+5A40(5);U+5A3F(2,4) +U+5A41(0);U+5A04(1,3);U+5A04(1,3) +U+5A42(0);U+5A42(0); +U+5A43(0);U+5A43(0); +U+5A44(0);U+5A44(0); +U+5A45(0);U+5A45(0); +U+5A46(0);U+5A46(5); +U+5A47(0);U+5A47(0); +U+5A48(0);U+5A48(0); +U+5A49(0);U+5A49(5);U+5007(4) +U+5A4A(0);U+5A4A(5); +U+5A4B(0);U+5A4B(0); +U+5A4C(0);U+5A4C(0); +U+5A4D(0);U+5A4D(0); +U+5A4E(0);U+5A4E(0); +U+5A4F(0);U+5A4F(0); +U+5A50(0);U+5A50(3); +U+5A51(0);U+5A51(0); +U+5A52(0);U+5A52(0); +U+5A53(0);U+5A53(3); +U+5A55(0);U+5A55(5); +U+5A56(0);U+5A56(0); +U+5A57(0);U+5A57(3); +U+5A58(0);U+5A58(3); +U+5A5A(0);U+5A5A(5); +U+5A5B(0);U+5A5B(0); +U+5A5C(0);U+5A5C(0); +U+5A5D(0);U+5A5D(0); + +U+5A5E(0);U+5A5E(3); +U+5A5F(0);U+5A5F(0); +U+5A60(0);U+5A60(0); +U+5A61(0);U+5A61(0); +U+5A62(0);U+5A62(5); +U+5A63(0);U+59FB(2);U+59FB(2) +U+5A64(0);U+5A64(0); +U+5A65(0);U+5A65(0); +U+5A66(0);U+5987(1,3);U+5987(1,3) +U+5A67(0);U+5A67(5); +U+5A68(0);U+5A68(0); +U+5A69(0);U+5A69(0); +U+5A6A(0);U+5A6A(5); +U+5A6B(0);U+5A6B(0); +U+5A6C(0);U+6DEB(2,3);U+6DEB(2,3) +U+5A6D(0);U+5A05(1,3);U+5A05(1,3) +U+5A6E(0);U+5A6E(0); +U+5A70(0);U+5A70(0); +U+5A72(0);U+5A72(0); +U+5A73(0);U+5A73(1,3);U+5AFF(1,3) +U+5A74(0);U+5A74(1,3);U+5B30(1,3) +U+5A75(0);U+5A75(1,3);U+5B0B(1,3) +U+5A76(0);U+5A76(1,3);U+5B38(1,3) +U+5A77(0);U+5A77(5); +U+5A78(0);U+5A78(0); +U+5A79(0);U+5A79(0); +U+5A7A(0);U+5A7A(5); +U+5A7B(0);U+5A7B(0); +U+5A7C(0);U+5A7C(0); +U+5A7D(0);U+5A7D(0); +U+5A7E(0);U+5077(4);U+5077(4),U+5AAE(4),U+5078(4) +U+5A7F(0);U+5A7F(5);U+805F(2,3) +U+5A80(0);U+5A80(0); +U+5A81(0);U+5A81(0); +U+5A82(0);U+5A82(0); +U+5A83(0);U+5A83(0); +U+5A84(0);U+5A84(0); +U+5A85(0);U+5A85(4); +U+5A86(0);U+5A86(3); +U+5A88(0);U+5A88(0); +U+5A89(0);U+5A89(0); +U+5A8A(0);U+5A8A(0); +U+5A8B(0);U+5A8B(0); +U+5A8C(0);U+5A8C(3);U+5AF9(3) +U+5A8E(0);U+59D0(3);U+59D0(3) +U+5A8F(0);U+5A8F(0); +U+5A90(0);U+5A90(0); +U+5A91(0);U+5A91(0); +U+5A92(0);U+5A92(5); +U+5A93(0);U+5A93(0); +U+5A94(0);U+5A94(0); +U+5A95(0);U+5A95(4); +U+5A96(0);U+5A96(0); +U+5A97(0);U+5A97(0); +U+5A98(0);U+5A98(0); +U+5A99(0);U+5A99(0); +U+5A9A(0);U+5A9A(5); +U+5A9B(0);U+5A9B(5); +U+5A9C(0);U+5A9C(0); +U+5A9D(0);U+5A9D(0); +U+5A9E(0);U+5A9E(3); +U+5A9F(0);U+5A9F(0); +U+5AA0(0);U+5AA0(3);U+5AF7(3) + +U+5AA1(0);U+5AA1(0); +U+5AA2(0);U+5AA2(3); +U+5AA3(0);U+5AA3(0); +U+5AA4(0);U+5AA4(0); +U+5AA5(0);U+5AA5(0); +U+5AA6(0);U+5AA6(0); +U+5AA7(0);U+5A32(1,3);U+5A32(1,3) +U+5AA8(0);U+5AA8(0); +U+5AA9(0);U+5AA9(0); +U+5AAA(0);U+5AAA(5);U+5ABC(4) +U+5AAC(0);U+4FDD(4);U+4FDD(4) +U+5AAD(0);U+5AAD(4);U+5B03(4) +U+5AAE(0);U+5077(2,3);U+5077(2,3),U+5A7E(4),U+5078(2,3,4) +U+5AAF(0);U+59AB(3);U+59AB(3),U+5B00(4) +U+5AB0(0);U+5AB0(3); +U+5AB1(0);U+5AB1(0); +U+5AB2(0);U+5AB2(5); +U+5AB3(0);U+5AB3(5); +U+5AB4(0);U+5AB4(0); +U+5AB5(0);U+5AB5(5); +U+5AB6(0);U+5AB6(0); +U+5AB7(0);U+5AB7(0); +U+5AB8(0);U+5AB8(5); +U+5AB9(0);U+5AB9(0); +U+5ABA(0);U+7F8E(3);U+7F8E(3) +U+5ABB(0);U+5ABB(0); +U+5ABC(0);U+5AAA(4);U+5AAA(4) +U+5ABD(0);U+5988(1,3);U+5988(1,3) +U+5ABE(0);U+5ABE(5); +U+5ABF(0);U+6127(2,3);U+6127(2,3) +U+5AC0(0);U+5AC0(0); +U+5AC1(0);U+5AC1(5); +U+5AC2(0);U+5AC2(5); +U+5AC3(0);U+5AC3(0); +U+5AC4(0);U+5AC4(0); +U+5AC5(0);U+5AC5(0); +U+5AC6(0);U+5AC6(0); +U+5AC7(0);U+5AC7(0); +U+5AC8(0);U+5AC8(0); +U+5AC9(0);U+5AC9(5); +U+5ACA(0);U+5ACA(0); +U+5ACB(0);U+8885(2);U+5B1D(3),U+8885(2),U+88CA(2),U+892D(2,3) +U+5ACC(0);U+5ACC(5); +U+5ACD(0);U+5ACD(0); +U+5ACE(0);U+5ACE(0); +U+5ACF(0);U+5ACF(0); +U+5AD1(0);U+5AD1(0); +U+5AD2(0);U+5AD2(1,3);U+5B21(1,3) +U+5AD4(0);U+5AD4(1,3);U+5B2A(1,3) +U+5AD5(0);U+5AD5(0); +U+5AD6(0);U+5AD6(5); +U+5AD7(0);U+59AA(1,3);U+59AA(1,3) +U+5AD8(0);U+5AD8(5); +U+5AD9(0);U+5AD9(0); +U+5ADA(0);U+5ADA(0); +U+5ADB(0);U+5ADB(0); +U+5ADC(0);U+5ADC(5); +U+5ADD(0);U+5ADD(0); +U+5ADE(0);U+6175(4);U+6175(4) +U+5ADF(0);U+5ADF(3); +U+5AE0(0);U+5AE0(5); +U+5AE1(0);U+5AE1(5); +U+5AE2(0);U+5AE2(0); + +U+5AE3(0);U+5AE3(5); +U+5AE4(0);U+5AE4(0); +U+5AE5(0);U+5AE5(0); +U+5AE6(0);U+5AE6(5); +U+5AE7(0);U+5AE7(0); +U+5AE8(0);U+5AE8(0); +U+5AE9(0);U+5AE9(5); +U+5AEA(0);U+5AEA(0); +U+5AEB(0);U+5AEB(5); +U+5AEC(0);U+5AEC(0); +U+5AED(0);U+5AED(3); +U+5AEE(0);U+5AEE(4); +U+5AF1(0);U+5AF1(1,3);U+5B19(1,3,4) +U+5AF2(0);U+5AF2(0); +U+5AF3(0);U+5AF3(0); +U+5AF4(0);U+5AF4(0); +U+5AF5(0);U+59A9(1,3);U+59A9(1,3) +U+5AF6(0);U+5AF6(0); +U+5AF7(0);U+5AA0(3);U+5AA0(3) +U+5AF8(0);U+5AF8(0); +U+5AF9(0);U+5A8C(3);U+5A8C(3) +U+5AFA(0);U+5A34(4);U+5A34(4),U+5AFB(2,3) +U+5AFB(0);U+5A34(1,3);U+5A34(1,3),U+5AFA(2,3) +U+5AFC(0);U+5AFC(0); +U+5AFD(0);U+5AFD(0); +U+5AFE(0);U+5AFE(0); +U+5AFF(0);U+5A73(1,3);U+5A73(1,3) +U+5B00(0);U+59AB(1);U+59AB(1),U+5AAF(4) +U+5B01(0);U+5B01(0); +U+5B02(0);U+5B02(0); +U+5B03(0);U+5AAD(4);U+5AAD(4) +U+5B04(0);U+5B04(0); +U+5B05(0);U+5B05(0); +U+5B06(0);U+5B06(0); +U+5B07(0);U+5B07(0); +U+5B08(0);U+5A06(1,3);U+5A06(1,3) +U+5B09(0);U+5B09(5); +U+5B0B(0);U+5A75(1,3);U+5A75(1,3) +U+5B0C(0);U+5A07(1,3);U+5A07(1,3) +U+5B0E(0);U+5B0E(4); +U+5B0F(0);U+5B0F(0); +U+5B10(0);U+5B10(0); +U+5B11(0);U+5B11(0); +U+5B12(0);U+5B12(0); +U+5B13(0);U+5B13(0); +U+5B14(0);U+5B14(4); +U+5B15(0);U+5B15(0); +U+5B16(0);U+5B16(5); +U+5B17(0);U+5B17(5); +U+5B18(0);U+5B18(0); +U+5B19(0);U+5AF1(1,3);U+5AF1(1,3) +U+5B1A(0);U+5B1A(0); +U+5B1B(0);U+5B1B(0); +U+5B1C(0);U+5B1C(0); +U+5B1D(0);U+8885(4);U+5ACB(3),U+8885(4),U+88CA(2),U+892D(2,3) +U+5B1E(0);U+5B1E(0); +U+5B1F(0);U+5B1F(0); +U+5B20(0);U+5B20(0); +U+5B21(0);U+5AD2(1,3);U+5AD2(1,3) +U+5B22(0);U+5A18(2,4);U+5A18(2,4),U+5B43(4) +U+5B23(0);U+5B23(0); +U+5B24(0);U+5B37(4);U+5B37(4) +U+5B25(0);U+5B25(0); + +U+5B26(0);U+5B26(0); +U+5B27(0);U+5B27(0); +U+5B28(0);U+5B28(0); +U+5B29(0);U+5B29(0); +U+5B2A(0);U+5AD4(1,3);U+5AD4(1,3) +U+5B2B(0);U+5B2B(0); +U+5B2C(0);U+5B2C(0); +U+5B2D(0);U+5976(2,3);U+5976(2,3),U+59B3(3),U+4F32(2,3),U+4F60(2,3,5),U+511E(2,3) +U+5B2E(0);U+5B2E(0); +U+5B2F(0);U+5B2F(3); +U+5B30(0);U+5A74(1,3);U+5A74(1,3) +U+5B31(0);U+5B31(0); +U+5B32(0);U+5B32(5); +U+5B33(0);U+5B33(0); +U+5B34(0);U+5B34(5); +U+5B35(0);U+5B35(3); +U+5B36(0);U+5B36(0); +U+5B37(0);U+5B37(5);U+5B24(4) +U+5B38(0);U+5A76(1,3);U+5A76(1,3) +U+5B3A(0);U+5B3A(0); +U+5B3B(0);U+5B3B(0); +U+5B3C(0);U+5B3C(0); +U+5B3D(0);U+5B3D(0); +U+5B3E(0);U+61D2(2,3);U+61D2(2,3),U+61F6(2,3) +U+5B3F(0);U+5B3F(3); +U+5B40(0);U+5B40(5); +U+5B41(0);U+5B41(0); +U+5B42(0);U+5B42(0); +U+5B43(0);U+5A18(2);U+5A18(2),U+5B22(4) +U+5B44(0);U+5B44(0); +U+5B45(0);U+7EA4(3);U+7EA4(3),U+7E34(1,3),U+7E8E(3),U+7E96(1,3) +U+5B47(0);U+5B47(0); +U+5B48(0);U+5B48(0); +U+5B49(0);U+5B49(0); +U+5B4A(0);U+5B4A(0); +U+5B4B(0);U+5B4B(0); +U+5B4C(0);U+5A08(1,3);U+5A08(1,3) +U+5B4D(0);U+5B4D(0); +U+5B4E(0);U+5B4E(0); +U+5B50(0);U+5B50(5); +U+5B51(0);U+5B51(5); +U+5B53(0);U+5B53(5); +U+5B54(0);U+5B54(5); +U+5B55(0);U+5B55(5); +U+5B56(0);U+5B56(0); +U+5B57(0);U+5B57(5); +U+5B58(0);U+5B58(5); +U+5B59(0);U+5B59(1,3);U+5B6B(1,3) +U+5B5A(0);U+5B5A(5);U+5B75(3) +U+5B5B(0);U+5B5B(5); +U+5B5C(0);U+5B5C(5); +U+5B5D(0);U+5B5D(5); +U+5B5E(0);U+5B5E(0); +U+5B5F(0);U+5B5F(5); +U+5B62(0);U+5B62(5); +U+5B63(0);U+5B63(5); +U+5B64(0);U+5B64(5); +U+5B65(0);U+5B65(5); +U+5B66(0);U+5B66(1,3);U+5B78(1,3),U+6588(3) +U+5B67(0);U+5B67(0); +U+5B68(0);U+5B68(0); +U+5B69(0);U+5B69(5); +U+5B6A(0);U+5B6A(1,3);U+5B7F(1,3) + +U+5B6B(0);U+5B59(1,3);U+5B59(1,3) +U+5B6C(0);U+5B6C(5); +U+5B6D(0);U+5B6D(0); +U+5B6E(0);U+5B6E(0); +U+5B70(0);U+5B70(5); +U+5B71(0);U+5B71(5); +U+5B72(0);U+5B72(0); +U+5B73(0);U+5B73(5);U+5B76(4) +U+5B74(0);U+5B74(3); +U+5B75(0);U+5B75(5);U+5B5A(3) +U+5B76(0);U+5B73(4);U+5B73(4) +U+5B77(0);U+5B77(0); +U+5B78(0);U+5B66(1,3);U+5B66(1,3),U+6588(3) +U+5B7A(0);U+5B7A(5); +U+5B7B(0);U+5B7B(0); +U+5B7C(0);U+5B7D(2,3);U+5B7D(2,3) +U+5B7D(0);U+5B7D(5);U+5B7C(2,3) +U+5B7F(0);U+5B6A(1,3);U+5B6A(1,3) +U+5B80(0);U+5B80(5); +U+5B81(0);U+5B81(1,3);U+5BCD(3),U+5BD5(4),U+5BDC(4),U+5BE7(1,3) +U+5B82(0);U+5197(2);U+5197(2) +U+5B83(0);U+5B83(5);U+7260(2,3) +U+5B84(0);U+5B84(5); +U+5B85(0);U+5B85(5); +U+5B87(0);U+5B87(5);U+7A7B(3) +U+5B88(0);U+5B88(5); +U+5B89(0);U+5B89(5);U+4F92(3) +U+5B8A(0);U+5B8A(0); +U+5B8B(0);U+5B8B(5); +U+5B8C(0);U+5B8C(5); +U+5B8D(0);U+8089(4);U+8089(4) +U+5B8E(0);U+5B8E(0); +U+5B8F(0);U+5B8F(5);U+5430(3) +U+5B91(0);U+5B91(0); +U+5B92(0);U+5B92(0); +U+5B93(0);U+5B93(5); +U+5B94(0);U+5B94(3); +U+5B95(0);U+5B95(5); +U+5B96(0);U+5B96(0); +U+5B97(0);U+5B97(5); +U+5B98(0);U+5B98(5); +U+5B99(0);U+5B99(5); +U+5B9A(0);U+5B9A(5); +U+5B9B(0);U+5B9B(5); +U+5B9C(0);U+5B9C(5);U+519D(3) +U+5B9D(0);U+5B9D(1,3);U+5BF3(3),U+5BF6(1,3) +U+5B9E(0);U+5B9E(1,3);U+5B9F(4),U+5BE6(1,3) +U+5B9F(0);U+5B9E(4);U+5B9E(4),U+5BE6(4) +U+5BA0(0);U+5BA0(1,3);U+5BF5(1,3) +U+5BA1(0);U+5BA1(1,3);U+5BE9(1,3) +U+5BA2(0);U+5BA2(5); +U+5BA3(0);U+5BA3(5); +U+5BA4(0);U+5BA4(5); +U+5BA5(0);U+5BA5(5); +U+5BA6(0);U+5BA6(5); +U+5BA7(0);U+5BA7(0); +U+5BA8(0);U+5BA8(0); +U+5BAA(0);U+5BAA(1,3);U+61B2(1,3) +U+5BAB(0);U+5BAB(5);U+5BAE(4) +U+5BAC(0);U+5BAC(3); +U+5BAD(0);U+5BAD(0); +U+5BAE(0);U+5BAB(4);U+5BAB(4) +U+5BAF(0);U+5BAF(3); + +U+5BB0(0);U+5BB0(5); +U+5BB1(0);U+5BB1(0); +U+5BB3(0);U+5BB3(5); +U+5BB4(0);U+5BB4(5);U+91BC(2,3) +U+5BB5(0);U+5BB5(5); +U+5BB6(0);U+5BB6(1,3);U+50A2(1,3,4) +U+5BB8(0);U+5BB8(5); +U+5BB9(0);U+5BB9(5); +U+5BBA(0);U+5BBA(0); +U+5BBB(0);U+5BC6(3);U+5BC6(3) +U+5BBD(0);U+5BBD(1,3);U+5BDB(3),U+5BEC(1,3) +U+5BBE(0);U+5BBE(1,3);U+8CD3(1,3),U+8CD4(3) +U+5BBF(0);U+5BBF(5); +U+5BC0(0);U+5BC0(0); +U+5BC1(0);U+5BC1(0); +U+5BC2(0);U+5BC2(5); +U+5BC3(0);U+51A4(2,3);U+51A4(2,3) +U+5BC4(0);U+5BC4(5); +U+5BC5(0);U+5BC5(5); +U+5BC6(0);U+5BC6(5);U+5BBB(3) +U+5BC7(0);U+5BC7(5);U+51A6(3) +U+5BCA(0);U+5BCA(0); +U+5BCB(0);U+5BCB(0); +U+5BCC(0);U+5BCC(5);U+51A8(3) +U+5BCD(0);U+5B81(3);U+5B81(3),U+5BD5(3,4),U+5BDC(3,4),U+5BE7(1,3) +U+5BCE(0);U+5BCE(3); +U+5BCF(0);U+5BCF(0); +U+5BD0(0);U+5BD0(5); +U+5BD1(0);U+5BDD(4);U+5BDD(4),U+5BE2(1,3,4) +U+5BD2(0);U+5BD2(5); +U+5BD3(0);U+5BD3(5);U+5EBD(2,3) +U+5BD4(0);U+5BD4(0); +U+5BD5(0);U+5B81(4);U+5B81(4),U+5BE7(2,3),U+5BCD(3,4),U+5BDC(4) +U+5BD6(0);U+5BD6(0); +U+5BD8(0);U+7F6E(2);U+7F6E(2) +U+5BD9(0);U+5BD9(0); +U+5BDB(0);U+5BBD(3);U+5BBD(3),U+5BEC(3) +U+5BDC(0);U+5B81(4);U+5B81(4),U+5BE7(4),U+5BCD(3,4),U+5BD5(4) +U+5BDD(0);U+5BDD(1,3);U+5BD1(4),U+5BE2(1,3,4) +U+5BDE(0);U+5BDE(5);U+55FC(4) +U+5BDF(0);U+5BDF(5);U+8A67(2) +U+5BE0(0);U+7AAD(4);U+7AAD(4),U+7AB6(1,3,4) +U+5BE1(0);U+5BE1(5); +U+5BE2(0);U+5BDD(1,3);U+5BDD(1,3),U+5BD1(0,1,3,4) +U+5BE3(0);U+5BE3(0); +U+5BE4(0);U+5BE4(5); +U+5BE5(0);U+5BE5(5); +U+5BE6(0);U+5B9E(1,3);U+5B9E(1,3),U+5B9F(4) +U+5BE7(0);U+5B81(1,3);U+5B81(1,3),U+5BD5(2,3),U+5BDC(4),U+5BCD(1,3) +U+5BE8(0);U+5BE8(5); +U+5BE9(0);U+5BA1(1,3);U+5BA1(1,3) +U+5BEA(0);U+5BEA(0); +U+5BEB(0);U+5199(1,3);U+5199(1,3) +U+5BEC(0);U+5BBD(1,3);U+5BBD(1,3),U+5BDB(3) +U+5BED(0);U+5BED(0); +U+5BEE(0);U+5BEE(5); +U+5BEF(0);U+5BEF(0); +U+5BF0(0);U+5BF0(5); +U+5BF1(0);U+5453(3);U+5453(3),U+56C8(1,3) +U+5BF2(0);U+5BF2(0); +U+5BF3(0);U+5B9D(3);U+5B9D(3),U+5BF6(2,3) +U+5BF4(0);U+5BF4(0); +U+5BF5(0);U+5BA0(1,3);U+5BA0(1,3) + +U+5BF6(0);U+5B9D(1,3);U+5B9D(1,3),U+5BF3(2,3) +U+5BF7(0);U+5BF7(0); +U+5BF8(0);U+5BF8(5); +U+5BF9(0);U+5BF9(1,3);U+5C0D(1,3) +U+5BFA(0);U+5BFA(5); +U+5BFB(0);U+5BFB(1,3);U+5C0B(1,3) +U+5BFC(0);U+5BFC(1,3);U+5C0E(1,3) +U+5BFD(0);U+5BFD(0); +U+5BFF(0);U+5BFF(1,3);U+58FD(1,3),U+5900(4) +U+5C01(0);U+5C01(5); +U+5C03(0);U+6577(3);U+6577(3) +U+5C04(0);U+5C04(5); +U+5C05(0);U+514B(4);U+514B(4),U+524B(2,3) +U+5C06(0);U+5C06(1,3);U+5C07(1,3,4) +U+5C07(0);U+5C06(1,3);U+5C06(1,3) +U+5C08(0);U+4E13(1,3);U+4E13(1,3) +U+5C09(0);U+5C09(5); +U+5C0A(0);U+5C0A(5); +U+5C0B(0);U+5BFB(1,3);U+5BFB(1,3) +U+5C0C(0);U+6811(3);U+6811(3),U+6A39(1,3) +U+5C0D(0);U+5BF9(1,3);U+5BF9(1,3) +U+5C0E(0);U+5BFC(1,3);U+5BFC(1,3) +U+5C0F(0);U+5C0F(5); +U+5C10(0);U+5C10(0); +U+5C11(0);U+5C11(5); +U+5C12(0);U+5C14(4);U+5C13(8,9),U+5C14(4),U+723E(2,3) +U+5C13(0);U+5C14(4);U+5C12(8,9),U+5C14(4),U+723E(3) +U+5C14(0);U+5C14(1,3);U+5C12(4),U+5C13(4),U+723E(1,3) +U+5C15(0);U+5C15(5); +U+5C16(0);U+5C16(5);U+946F(4) +U+5C17(0);U+5C17(0); +U+5C18(0);U+5C18(1,3);U+5875(1,3) +U+5C19(0);U+5C1A(4);U+5C1A(4) +U+5C1A(0);U+5C1A(5);U+5C19(4) +U+5C1C(0);U+5C1C(5); +U+5C1D(0);U+5C1D(1,3);U+5617(1,3),U+5690(4),U+751E(4) +U+5C1E(0);U+5C1E(0); +U+5C1F(0);U+9C9C(3);U+9BAE(2,3),U+9C9C(3),U+5C20(2,3) +U+5C20(0);U+9C9C(2);U+9BAE(2),U+9C9C(2),U+5C1F(0,2,3) +U+5C21(0);U+5C21(0); +U+5C22(0);U+5C22(5); +U+5C24(0);U+5C24(5);U+8A27(3) +U+5C25(0);U+5C25(5); +U+5C27(0);U+5C27(1,3);U+579A(3),U+582F(1,3),U+5C2D(4) +U+5C28(0);U+5C28(3); +U+5C2A(0);U+5C2A(4);U+5C2B(4) +U+5C2B(0);U+5C2A(4);U+5C2A(4) +U+5C2C(0);U+5C2C(5); +U+5C2D(0);U+5C27(4);U+582F(4),U+5C27(4),U+579A(0,3,4) +U+5C2E(0);U+5C2E(0); +U+5C2F(0);U+5C2F(0); +U+5C30(0);U+5C30(0); +U+5C31(0);U+5C31(5); +U+5C32(0);U+5C32(4); +U+5C33(0);U+5C33(0); +U+5C34(0);U+5C34(1,3);U+5C37(1,3) +U+5C35(0);U+5C35(0); +U+5C37(0);U+5C34(1,3);U+5C34(1,3) +U+5C38(0);U+5C38(5);U+5C4D(2,3) +U+5C39(0);U+5C39(5); +U+5C3A(0);U+5C3A(5); +U+5C3B(0);U+5C3B(5); +U+5C3C(0);U+5C3C(5); + +U+5C3D(0);U+5C3D(1,3);U+5118(1,3),U+76E1(1,3) +U+5C3E(0);U+5C3E(5); +U+5C3F(0);U+5C3F(5);U+6EBA(3) +U+5C40(0);U+5C40(5);U+4FB7(2),U+8DFC(2) +U+5C41(0);U+5C41(5); +U+5C42(0);U+5C42(1,3);U+5C64(1,3) +U+5C43(0);U+5C43(4);U+5C53(4),U+5C6D(4) +U+5C44(0);U+5C44(3); +U+5C45(0);U+5C45(5); +U+5C46(0);U+5C4A(2,3);U+5C4A(2,3),U+8250(2,3) +U+5C47(0);U+5C47(0); +U+5C48(0);U+5C48(5); +U+5C49(0);U+5C49(5); +U+5C4A(0);U+5C4A(5);U+5C46(2,3),U+8250(3) +U+5C4B(0);U+5C4B(5); +U+5C4C(0);U+5C4C(0); +U+5C4D(0);U+5C38(2,3);U+5C38(2,3) +U+5C4E(0);U+5C4E(5); +U+5C4F(0);U+5C4F(5);U+5C5B(3),U+5EB0(4) +U+5C50(0);U+5C50(5); +U+5C51(0);U+5C51(5); +U+5C52(0);U+5C52(0); +U+5C53(0);U+5C43(4);U+5C43(4),U+5C6D(4) +U+5C54(0);U+5C54(0); +U+5C55(0);U+5C55(5); +U+5C56(0);U+5C56(3); +U+5C57(0);U+5C57(0); +U+5C58(0);U+5C58(0); +U+5C59(0);U+5C59(5); +U+5C5B(0);U+5C4F(3);U+5C4F(3),U+5EB0(3,4) +U+5C5C(0);U+5C5C(4); +U+5C5D(0);U+5C5D(3); +U+5C5E(0);U+5C5E(1,3);U+5C6C(1,3) +U+5C5F(0);U+5C5F(4); +U+5C60(0);U+5C60(5); +U+5C61(0);U+5C61(1,3);U+5C62(1,3) +U+5C62(0);U+5C61(1,3);U+5C61(1,3) +U+5C63(0);U+5C63(5); +U+5C64(0);U+5C42(1,3);U+5C42(1,3) +U+5C65(0);U+5C65(5); +U+5C66(0);U+5C66(1,3);U+5C68(1,3) +U+5C67(0);U+5C67(3); +U+5C68(0);U+5C66(1,3);U+5C66(1,3) +U+5C69(0);U+5C69(3); +U+5C6A(0);U+5C6A(3); +U+5C6B(0);U+5C6B(0); +U+5C6C(0);U+5C5E(1,3);U+5C5E(1,3) +U+5C6D(0);U+5C43(4);U+5C43(4),U+5C53(4) +U+5C6E(0);U+5C6E(5); +U+5C6F(0);U+5C6F(5); +U+5C70(0);U+5C70(0); +U+5C71(0);U+5C71(5); +U+5C72(0);U+5C72(0); +U+5C73(0);U+5C73(0); +U+5C74(0);U+5C74(0); +U+5C75(0);U+5C75(0); +U+5C76(0);U+5C76(0); +U+5C77(0);U+5C77(0); +U+5C78(0);U+5C78(0); +U+5C79(0);U+5C79(5);U+9623(3) +U+5C7A(0);U+5C7A(5); +U+5C7B(0);U+5C7B(0); +U+5C7C(0);U+5C7C(0); + +U+5C7D(0);U+5C7D(0); +U+5C7E(0);U+5C7E(0); +U+5C7F(0);U+5C7F(1,3);U+5DBC(1,3) +U+5C80(0);U+51FA(3);U+51FA(3),U+9F63(3) +U+5C81(0);U+5C81(1,3);U+4E97(3),U+6B72(1,3),U+6B73(4) +U+5C82(0);U+5C82(1,3);U+8C48(1,3) +U+5C83(0);U+5C83(0); +U+5C84(0);U+5C84(0); +U+5C86(0);U+5C86(0); +U+5C87(0);U+5C87(0); +U+5C88(0);U+5C88(5); +U+5C89(0);U+5C89(0); +U+5C8A(0);U+5C8A(3); +U+5C8B(0);U+5C8B(0); +U+5C8C(0);U+5C8C(5); +U+5C8D(0);U+5C8D(5); +U+5C8E(0);U+5C8E(0); +U+5C8F(0);U+5C8F(0); +U+5C90(0);U+5C90(5);U+6B67(3) +U+5C91(0);U+5C91(5); +U+5C92(0);U+5C92(0); +U+5C93(0);U+5C93(0); +U+5C94(0);U+5C94(5); +U+5C95(0);U+5C95(0); +U+5C96(0);U+5C96(1,3);U+5D87(1,3) +U+5C97(0);U+5C97(1,3);U+5D17(1,3),U+5CA1(1,3,4),U+5188(1,3,4) +U+5C98(0);U+5C98(1,3);U+5CF4(1,3) +U+5C99(0);U+5C99(5); +U+5C9A(0);U+5C9A(1,3);U+5D50(1,3) +U+5C9B(0);U+5C9B(1,3);U+5D8B(3),U+5D8C(7),U+5CF6(1,3) +U+5C9C(0);U+5C9C(5); +U+5C9D(0);U+5C9D(3); +U+5C9E(0);U+5C9E(0); +U+5C9F(0);U+5C9F(0); +U+5CA0(0);U+5CA0(0); +U+5CA1(0);U+5188(1,3);U+5188(1,3),U+5D17(4),U+5C97(1,3,4) +U+5CA2(0);U+5CA2(5); +U+5CA3(0);U+5CA3(5); +U+5CA4(0);U+7A74(4);U+7A74(4) +U+5CA5(0);U+5761(3);U+5761(3) +U+5CA6(0);U+5CA6(0); +U+5CA7(0);U+5CA7(3); +U+5CA8(0);U+5CA8(3); +U+5CA9(0);U+5CA9(4);U+5D52(2),U+55A6(4),U+58E7(3),U+5DCC(4),U+5DD6(2,3),U+789E(3),U+7939(3) + +U+5CAA(0);U+5CAA(0); +U+5CAB(0);U+5CAB(5); +U+5CAC(0);U+5CAC(5); +U+5CAD(0);U+5CAD(1,3);U+5CBA(3),U+5DBA(1,3) +U+5CAE(0);U+5CAE(0); +U+5CAF(0);U+5CAF(3); +U+5CB0(0);U+5CB0(0); +U+5CB1(0);U+5CB1(5); +U+5CB2(0);U+5CB2(0); +U+5CB3(0);U+5CB3(5);U+5DBD(2,3) +U+5CB5(0);U+5CB5(5); +U+5CB6(0);U+5CB6(0); +U+5CB7(0);U+5CB7(5);U+5D0F(3) +U+5CB8(0);U+5CB8(5); +U+5CBA(0);U+5CAD(3);U+5CAD(3),U+5DBA(7) +U+5CBB(0);U+5CBB(0); +U+5CBC(0);U+5CBC(0); +U+5CBD(0);U+5CBD(1,3);U+5D2C(1,3) + +U+5CBE(0);U+5CBE(0); +U+5CBF(0);U+5CBF(1,3);U+5DCB(1,3) +U+5CC1(0);U+5CC1(5); +U+5CC2(0);U+5CC2(0); +U+5CC3(0);U+5CC3(1,3);U+5DA8(1,3) +U+5CC4(0);U+5CC4(1,3);U+5DA7(1,3) +U+5CC5(0);U+5CC5(0); +U+5CC6(0);U+5CC6(0); +U+5CC7(0);U+5CC7(0); +U+5CC8(0);U+5CC8(0); +U+5CC9(0);U+5CC9(0); +U+5CCA(0);U+961C(3);U+961C(3),U+961D(3) +U+5CCB(0);U+5CCB(5); +U+5CCC(0);U+5CCC(0); +U+5CCD(0);U+5CCD(0); +U+5CCE(0);U+5CCE(0); +U+5CCF(0);U+5CCF(0); +U+5CD0(0);U+5CD0(0); +U+5CD1(0);U+5CD1(0); +U+5CD2(0);U+5CD2(5); +U+5CD3(0);U+5CD3(0); +U+5CD4(0);U+5CD4(0); +U+5CD6(0);U+5CD6(0); +U+5CD7(0);U+5CD7(3); +U+5CD8(0);U+5CD8(0); +U+5CD9(0);U+5CD9(5); +U+5CDA(0);U+5CDA(0); +U+5CDB(0);U+5CDB(0); +U+5CDC(0);U+5CDC(0); +U+5CDE(0);U+5CDE(0); +U+5CDF(0);U+5CDF(0); +U+5CE0(0);U+5CE0(0); +U+5CE1(0);U+5CE1(1,3);U+5CFD(1,3) +U+5CE2(0);U+5CE2(0); +U+5CE3(0);U+5CE3(1,3);U+5DA2(1,3) +U+5CE4(0);U+5CE4(1,3);U+5DA0(1,3) +U+5CE5(0);U+5CE5(4);U+5D22(4) +U+5CE6(0);U+5CE6(1,3);U+5DD2(1,3) +U+5CE7(0);U+5CE7(0); +U+5CE8(0);U+5CE8(5);U+5CE9(2,3) +U+5CE9(0);U+5CE8(2,3);U+5CE8(2,3) +U+5CEA(0);U+5CEA(5); +U+5CEB(0);U+5CEB(0); +U+5CEC(0);U+5CEC(0); +U+5CED(0);U+5CED(5); +U+5CEE(0);U+5CEE(0); +U+5CEF(0);U+5CF0(2,3);U+5CF0(2,3) +U+5CF0(0);U+5CF0(5);U+5CEF(2,3) +U+5CF1(0);U+5CF1(3);U+5DA9(3) +U+5CF2(0);U+5CF2(0); +U+5CF3(0);U+5CF3(0); +U+5CF4(0);U+5C98(1,3);U+5C98(1,3) +U+5CF6(0);U+5C9B(1,3);U+5D8B(3),U+5D8C(8,9),U+5C9B(1,3) +U+5CF7(0);U+5CF7(0); +U+5CF8(0);U+5CF8(0); +U+5CF9(0);U+5CF9(0); +U+5CFA(0);U+5CFA(3);U+786C(3) +U+5CFB(0);U+5CFB(5); +U+5CFC(0);U+5CFC(0); +U+5CFD(0);U+5CE1(1,3);U+5CE1(1,3) +U+5CFE(0);U+5CFE(0); +U+5CFF(0);U+5CFF(0); +U+5D00(0);U+5D00(0); + +U+5D01(0);U+5D01(0); +U+5D02(0);U+5D02(1,3);U+5D97(1,3) +U+5D03(0);U+5D03(1,3);U+5D0D(1,3) +U+5D04(0);U+5D04(4);U+5DAE(4) +U+5D05(0);U+5D05(0); +U+5D06(0);U+5D06(5); +U+5D07(0);U+5D07(5);U+5D08(3) +U+5D08(0);U+5D07(3);U+5D07(3) +U+5D09(0);U+5D09(0); +U+5D0A(0);U+5D0A(0); +U+5D0B(0);U+534E(3);U+534E(3),U+83EF(3) +U+5D0C(0);U+5D0C(0); +U+5D0D(0);U+5D03(1,3);U+5D03(1,3) +U+5D0E(0);U+5D0E(5);U+57FC(7),U+7895(7) +U+5D0F(0);U+5CB7(3);U+5CB7(3) +U+5D10(0);U+6606(2);U+5D11(3),U+6606(2),U+665C(2,3) +U+5D11(0);U+6606(2);U+5D10(3),U+6606(2),U+665C(2,3) +U+5D12(0);U+5D12(3); +U+5D13(0);U+5D13(0); +U+5D14(0);U+5D14(5); +U+5D15(0);U+5D16(3);U+5D16(3) +U+5D16(0);U+5D16(5);U+5D15(3) +U+5D17(0);U+5C97(1,3);U+5C97(1,3),U+5CA1(4),U+5188(1,3,4) +U+5D18(0);U+4ED1(4);U+4ED1(4),U+4F96(2),U+5D19(3) +U+5D19(0);U+4ED1(2,4);U+4ED1(2,4),U+4F96(2,3),U+5D18(3) +U+5D1A(0);U+5D1A(3); +U+5D1B(0);U+5D1B(5); +U+5D1C(0);U+5D1C(0); +U+5D1D(0);U+5D1D(3); +U+5D1E(0);U+5D1E(5); +U+5D1F(0);U+5D1F(3); +U+5D20(0);U+5D20(0); +U+5D21(0);U+5D21(0); +U+5D22(0);U+5CE5(4);U+5CE5(4) +U+5D23(0);U+5D23(0); +U+5D24(0);U+5D24(5); +U+5D25(0);U+5D25(0); +U+5D26(0);U+5D26(5); +U+5D27(0);U+5D27(5); +U+5D28(0);U+5D28(0); +U+5D29(0);U+5D29(5); +U+5D2A(0);U+5D2A(0); +U+5D2C(0);U+5CBD(1,3);U+5CBD(1,3) +U+5D2D(0);U+5D2D(1,3);U+5D84(1,3) +U+5D2E(0);U+5D2E(5); +U+5D30(0);U+5D30(0); +U+5D31(0);U+5D31(0); +U+5D32(0);U+5D32(0); +U+5D33(0);U+5D33(0); +U+5D34(0);U+5D34(5); +U+5D35(0);U+5D35(0); +U+5D36(0);U+5D36(0); +U+5D37(0);U+5D37(0); +U+5D38(0);U+5D38(0); +U+5D39(0);U+5D39(0); +U+5D3A(0);U+5D3A(0); +U+5D3C(0);U+5D3C(0); +U+5D3D(0);U+5D3D(5); +U+5D3E(0);U+5D3E(5); +U+5D3F(0);U+5D3F(0); +U+5D40(0);U+5D40(0); +U+5D41(0);U+5D41(3); +U+5D42(0);U+5D42(3); + +U+5D43(0);U+5D43(0); +U+5D44(0);U+5D44(0); +U+5D45(0);U+5D45(0); +U+5D46(0);U+5D47(3);U+5D47(3) +U+5D47(0);U+5D47(5);U+5D46(3) +U+5D48(0);U+5D48(0); +U+5D49(0);U+5D49(0); +U+5D4A(0);U+5D4A(5); +U+5D4B(0);U+5D4B(5); +U+5D4C(0);U+5D4C(5); +U+5D4D(0);U+5D4D(3); +U+5D4E(0);U+5D4E(0); +U+5D4F(0);U+5D4F(3);U+5D55(3) +U+5D50(0);U+5C9A(1,3);U+5C9A(1,3) +U+5D51(0);U+5D51(0); +U+5D52(0);U+5CA9(2);U+5CA9(2),U+55A6(0,2,4),U+58E7(2,3,4),U+5DCC(2,4),U+5DD6(2,3,4),U+789E(2,3,4),U+7939(2,3,4) +U+5D54(0);U+5D54(0); +U+5D55(0);U+5D4F(3);U+5D4F(3) +U+5D56(0);U+5D56(0); +U+5D58(0);U+5D58(1,3);U+5DB8(1,3) +U+5D59(0);U+5D59(0); +U+5D5A(0);U+5D5A(1,3);U+5D94(1,3) +U+5D5B(0);U+5D5B(5); +U+5D5D(0);U+5D5D(1,3);U+5D81(1,3) +U+5D5E(0);U+5D5E(3); +U+5D5F(0);U+5D5F(0); +U+5D61(0);U+5D61(0); +U+5D62(0);U+5D62(0); +U+5D63(0);U+5D63(0); +U+5D64(0);U+5D64(0); +U+5D65(0);U+5D65(0); +U+5D66(0);U+5D66(0); +U+5D67(0);U+5D67(0); +U+5D68(0);U+5D68(0); +U+5D69(0);U+5D69(5); +U+5D6A(0);U+5D6A(0); +U+5D6B(0);U+5D6B(5); +U+5D6C(0);U+5D6C(5); +U+5D6D(0);U+5D6D(0); +U+5D6E(0);U+5D6E(0); +U+5D6F(0);U+5D6F(5);U+5D73(3) +U+5D70(0);U+5D70(0); +U+5D71(0);U+5D71(0); +U+5D72(0);U+5D72(0); +U+5D73(0);U+5D6F(3);U+5D6F(3) +U+5D74(0);U+5D74(5); +U+5D75(0);U+5D75(0); +U+5D76(0);U+5D76(0); +U+5D77(0);U+5D77(0); +U+5D78(0);U+5D78(0); +U+5D79(0);U+5D79(0); +U+5D7A(0);U+5D7A(0); +U+5D7B(0);U+5D7B(0); +U+5D7C(0);U+5D7C(0); +U+5D7D(0);U+5D7D(3); +U+5D7E(0);U+5D7E(0); +U+5D7F(0);U+5D7F(0); +U+5D80(0);U+5D80(0); +U+5D81(0);U+5D5D(1,3);U+5D5D(1,3) +U+5D82(0);U+5D82(5); +U+5D84(0);U+5D2D(1,3);U+5D2D(1,3) +U+5D85(0);U+5D85(3); + +U+5D86(0);U+5D86(0); +U+5D87(0);U+5C96(1,3);U+5C96(1,3) +U+5D88(0);U+5D88(0); +U+5D89(0);U+5D89(0); +U+5D8A(0);U+5D8A(0); +U+5D8B(0);U+5C9B(3);U+5C9B(3),U+5CF6(3),U+5D8C(3,7) +U+5D8C(0);U+5C9B(7);U+5C9B(7),U+5CF6(8,9),U+5D8B(3,7) +U+5D8D(0);U+5D8D(0); +U+5D8E(0);U+5D8E(0); +U+5D8F(0);U+5D8F(0); +U+5D90(0);U+5D90(0); +U+5D91(0);U+5D91(0); +U+5D92(0);U+5D92(0); +U+5D93(0);U+5D93(0); +U+5D94(0);U+5D5A(1,3);U+5D5A(1,3) +U+5D95(0);U+5D95(4); +U+5D97(0);U+5D02(1,3);U+5D02(1,3) +U+5D98(0);U+5D98(0); +U+5D99(0);U+5D99(5); +U+5D9A(0);U+5D9A(3); +U+5D9B(0);U+5D9B(0); +U+5D9C(0);U+5D9C(0); +U+5D9D(0);U+5D9D(5); +U+5D9E(0);U+5D9E(0); +U+5D9F(0);U+5D9F(0); +U+5DA0(0);U+5CE4(1,3);U+5CE4(1,3) +U+5DA1(0);U+5DA1(3); +U+5DA2(0);U+5CE3(1,3);U+5CE3(1,3) +U+5DA5(0);U+5DA5(0); +U+5DA6(0);U+5DA6(0); +U+5DA7(0);U+5CC4(1,3);U+5CC4(1,3) +U+5DA8(0);U+5CC3(1,3);U+5CC3(1,3) +U+5DA9(0);U+5CF1(3);U+5CF1(3) +U+5DAA(0);U+5DAA(3); +U+5DAC(0);U+5DAC(0); +U+5DAD(0);U+5DAD(0); +U+5DAE(0);U+5D04(4);U+5D04(4) +U+5DAF(0);U+5DAF(0); +U+5DB0(0);U+5DB0(0); +U+5DB1(0);U+5DB1(0); +U+5DB2(0);U+5DB2(0); +U+5DB4(0);U+5DB4(3); +U+5DB5(0);U+5DB5(0); +U+5DB6(0);U+5DB6(0); +U+5DB7(0);U+5DB7(5); +U+5DB8(0);U+5D58(1,3);U+5D58(1,3) +U+5DBA(0);U+5CAD(1,3);U+5CAD(1,3),U+5CBA(7) +U+5DBB(0);U+5DBB(4); +U+5DBC(0);U+5C7F(1,3);U+5C7F(1,3) +U+5DBD(0);U+5CB3(2,3);U+5CB3(2,3) +U+5DBE(0);U+5DBE(0); +U+5DBF(0);U+5DBF(0); +U+5DC0(0);U+5DC0(3); +U+5DC1(0);U+5DC1(0); +U+5DC2(0);U+5DC2(3); +U+5DC3(0);U+5DC3(3); +U+5DC5(0);U+5DC5(1,3,4);U+5DD3(4),U+5DD4(1,3) +U+5DC6(0);U+5DC6(0); +U+5DC7(0);U+5DC7(3); +U+5DC8(0);U+5DC8(0); +U+5DC9(0);U+6E10(4);U+6E10(4),U+6F38(1,3,4) +U+5DCA(0);U+5DCA(0); +U+5DCB(0);U+5CBF(1,3);U+5CBF(1,3) + +U+5DCC(0);U+5CA9(4);U+5CA9(4),U+5DD6(7),U+55A6(0,4),U+5D52(2,4),U+58E7(3,4),U+789E(3,4),U+7939(3,4) + +U+5DCD(0);U+5DCD(5); +U+5DCE(0);U+5DCE(4); +U+5DCF(0);U+5DCF(0); +U+5DD0(0);U+5DD0(0); +U+5DD1(0);U+5DD1(0); +U+5DD2(0);U+5CE6(1,3);U+5CE6(1,3) +U+5DD3(0);U+5DC5(4);U+5DC5(4),U+5DD4(4) +U+5DD4(0);U+5DC5(1,3);U+5DC5(1,3),U+5DD3(4) +U+5DD5(0);U+5DD5(0); +U+5DD6(0);U+5CA9(2,3);U+5CA9(2,3),U+5DCC(7),U+55A6(0,2,3,4),U+5D52(2,3,4),U+58E7(2,3,4),U+789E(2,3,4),U+7939(2,3,4) + +U+5DD8(0);U+5DD8(3); +U+5DD9(0);U+5DD9(0); +U+5DDB(0);U+5DDB(5); +U+5DDD(0);U+5DDD(5); +U+5DDE(0);U+5DDE(5); +U+5DDF(0);U+5DDF(0); +U+5DE0(0);U+5DE0(3); +U+5DE1(0);U+5DE1(5);U+5EF5(2,3) +U+5DE2(0);U+5DE2(5);U+5DE3(3),U+6F05(3) +U+5DE3(0);U+5DE2(3);U+5DE2(3),U+6F05(3) +U+5DE4(0);U+5DE4(0); +U+5DE5(0);U+5DE5(5); +U+5DE6(0);U+5DE6(5); +U+5DE7(0);U+5DE7(5); +U+5DE8(0);U+5DE8(5);U+9245(2,3),U+949C(2,3,4) +U+5DE9(0);U+5DE9(1,3);U+978F(1,3) +U+5DEA(0);U+5DEA(0); +U+5DEB(0);U+5DEB(5); +U+5DEC(0);U+5DEC(0); +U+5DED(0);U+5DED(0); +U+5DEE(0);U+5DEE(5); +U+5DEF(0);U+5DEF(1,3);U+5DF0(1,3) +U+5DF0(0);U+5DEF(1,3);U+5DEF(1,3) +U+5DF1(0);U+5DF1(5); +U+5DF2(0);U+5DF2(5); +U+5DF3(0);U+5DF3(5); +U+5DF4(0);U+5DF4(5);U+7B06(3) +U+5DF5(0);U+536E(2,3);U+536E(2,3) +U+5DF7(0);U+5DF7(5); +U+5DF8(0);U+5DF8(3); +U+5DF9(0);U+5DF9(0); +U+5DFA(0);U+5DFD(3);U+5DFD(3) +U+5DFB(0);U+5377(4);U+5377(4),U+6372(1,3,4) +U+5DFC(0);U+5DFC(0); +U+5DFD(0);U+5DFD(5);U+5DFA(3) +U+5DFE(0);U+5DFE(5); +U+5DFF(0);U+5DFF(0); +U+5E00(0);U+5E00(3); +U+5E01(0);U+5E01(1,3);U+5E63(1,3),U+5E64(4) +U+5E02(0);U+5E02(5); +U+5E03(0);U+5E03(3);U+4F48(2,3) +U+5E04(0);U+5E04(0); +U+5E05(0);U+5E05(1,3);U+5E25(1,3) +U+5E06(0);U+5E06(5); +U+5E07(0);U+5E07(0); +U+5E08(0);U+5E08(1,3);U+5E2B(1,3) +U+5E09(0);U+5E09(0); +U+5E0A(0);U+5E0A(3); +U+5E0B(0);U+7EB8(4);U+7D19(2,3),U+7EB8(4) +U+5E0C(0);U+5E0C(5);U+7A00(3) + +U+5E0D(0);U+5E0D(0); +U+5E0E(0);U+5E0E(0); +U+5E0F(0);U+5E0F(1,3);U+5E43(1,3) +U+5E10(0);U+5E10(1,3);U+5E33(1,3),U+8CEC(1,3),U+8D26(1,3) +U+5E11(0);U+5E11(5); +U+5E13(0);U+5E13(0); +U+5E14(0);U+5E14(5); +U+5E15(0);U+5E15(5); +U+5E16(0);U+5E16(5); +U+5E17(0);U+5E17(0); +U+5E18(0);U+5E18(1,3);U+7C3E(1,3) +U+5E19(0);U+5E19(5);U+889F(2,3) +U+5E1A(0);U+5E1A(5);U+83F7(3) +U+5E1B(0);U+5E1B(5); +U+5E1C(0);U+5E1C(1,3);U+5E5F(1,3) +U+5E1D(0);U+5E1D(5); +U+5E1E(0);U+5E1E(3); +U+5E1F(0);U+5E1F(0); +U+5E20(0);U+5E20(0); +U+5E21(0);U+5E21(3);U+5E32(3) +U+5E22(0);U+5E22(0); +U+5E23(0);U+5E23(0); +U+5E24(0);U+5E24(0); +U+5E25(0);U+5E05(1,3);U+5E05(1,3) +U+5E26(0);U+5E26(1,3);U+5E2F(3),U+5E36(1,3) +U+5E27(0);U+5E27(1,3);U+5E40(1,3) +U+5E28(0);U+5E28(0); +U+5E29(0);U+5E29(0); +U+5E2A(0);U+5E2A(0); +U+5E2B(0);U+5E08(1,3);U+5E08(1,3) +U+5E2C(0);U+88D9(2,3);U+88D9(2,3),U+88E0(2,3) +U+5E2D(0);U+5E2D(5);U+5ED7(4),U+84C6(2,3) +U+5E2E(0);U+5E2E(1,3);U+5E47(4),U+5E5A(3),U+5E6B(1,3,4),U+7E0D(3),U+97A4(4) +U+5E2F(0);U+5E26(3);U+5E26(3),U+5E36(3) +U+5E30(0);U+5F52(3);U+5F52(3),U+6B78(3),U+7688(3) +U+5E31(0);U+5E31(4);U+5E6C(4) +U+5E32(0);U+5E21(3);U+5E21(3) +U+5E33(0);U+5E10(1,3);U+5E10(1,3),U+8CEC(3),U+8D26(1,3) +U+5E34(0);U+5E34(0); +U+5E35(0);U+5E35(0); +U+5E36(0);U+5E26(1,3);U+5E26(1,3),U+5E2F(3) +U+5E37(0);U+5E37(5); +U+5E38(0);U+5E38(5); +U+5E39(0);U+5E39(0); +U+5E3A(0);U+5E3A(4);U+8900(4) +U+5E3B(0);U+5E3B(1,3);U+5E58(1,3) +U+5E3C(0);U+5E3C(1,3);U+5E57(1,3),U+852E(4) +U+5E3D(0);U+5E3D(5); +U+5E3E(0);U+5E3E(0); +U+5E40(0);U+5E27(1,3);U+5E27(1,3) +U+5E41(0);U+5E41(0); +U+5E42(0);U+5E42(5);U+51AA(2,3),U+7F83(2,3) +U+5E43(0);U+5E0F(1,3);U+5E0F(1,3) +U+5E44(0);U+5E44(5); +U+5E45(0);U+5E45(5); +U+5E46(0);U+5E46(0); +U+5E47(0);U+5E2E(4);U+5E2E(4),U+5E6B(2,3),U+5E5A(3,4),U+7E0D(3,4),U+97A4(4) +U+5E49(0);U+5E49(0); +U+5E4A(0);U+5E4A(0); +U+5E4B(0);U+5E4B(3); +U+5E4C(0);U+5E4C(5); +U+5E4D(0);U+5E4D(0); +U+5E4E(0);U+5E4E(0); + +U+5E4F(0);U+5E4F(0); +U+5E50(0);U+5E50(0); +U+5E52(0);U+5E52(0); +U+5E53(0);U+5E53(0); +U+5E54(0);U+5E54(5); +U+5E55(0);U+5E55(5);U+5E59(2,3) +U+5E56(0);U+5E56(0); +U+5E57(0);U+5E3C(1,3);U+5E3C(1,3),U+852E(1,3,4) +U+5E58(0);U+5E3B(1,3);U+5E3B(1,3) +U+5E59(0);U+5E55(2,3);U+5E55(2,3) +U+5E5A(0);U+5E2E(3);U+5E2E(3),U+5E6B(2,3),U+5E47(3,4),U+7E0D(3),U+97A4(3,4) +U+5E5B(0);U+5E5B(5); +U+5E5C(0);U+5E5C(0); +U+5E5D(0);U+5E5D(0); +U+5E5E(0);U+5E5E(5); +U+5E5F(0);U+5E1C(1,3);U+5E1C(1,3) +U+5E60(0);U+5E60(0); +U+5E61(0);U+5E61(5); +U+5E62(0);U+5E62(5); +U+5E63(0);U+5E01(1,3);U+5E01(1,3),U+5E64(4) +U+5E64(0);U+5E01(4);U+5E01(4),U+5E63(4) +U+5E65(0);U+5E65(0); +U+5E66(0);U+5E66(0); +U+5E67(0);U+5E67(3); +U+5E68(0);U+5E68(0); +U+5E69(0);U+5E69(0); +U+5E6A(0);U+5E6A(0); +U+5E6B(0);U+5E2E(1,3);U+5E2E(1,3),U+5E47(2,3),U+5E5A(2,3),U+7E0D(1,3,4),U+97A4(1,3,4) + +U+5E6C(0);U+5E31(4);U+5E31(4) +U+5E6D(0);U+5E6D(0); +U+5E6E(0);U+5E6E(3); +U+5E6F(0);U+5E6F(3); +U+5E70(0);U+5E70(0); +U+5E71(0);U+8955(3);U+8955(3),U+8974(3) +U+5E72(0);U+5E72(1,3,4);U+4E7E(1,3,4),U+4E81(4),U+5E79(1,3,4),U+69A6(4),U+6F27(1,3) +U+5E73(0);U+5E73(5); +U+5E74(0);U+5E74(5);U+79CA(2,3) +U+5E75(0);U+5E75(0); +U+5E76(0);U+5E76(4);U+4E26(2),U+4F75(2),U+5002(4),U+5E77(3,4),U+7ADD(2) +U+5E77(0);U+5E76(4);U+5E76(4),U+4E26(0,2,3,4),U+4F75(2,3,4),U+7ADD(2,3,4),U+5002(2,3,4) + +U+5E78(0);U+5E78(5);U+5016(2,3) +U+5E79(0);U+5E72(1,3);U+5E72(1,3),U+69A6(2,3),U+4E7E(1,3,4),U+4E81(1,2,3,4),U+6F27(1,3,4) + +U+5E7A(0);U+5E7A(5);U+4E48(3),U+5E85(3,4),U+9EBC(3,4),U+9EBD(1,3) +U+5E7B(0);U+5E7B(5); +U+5E7C(0);U+5E7C(5); +U+5E7D(0);U+5E7D(5); +U+5E7E(0);U+51E0(1,3);U+51E0(1,3) +U+5E7F(0);U+5E7F(1,3);U+5E83(4),U+5EE3(1,3) +U+5E80(0);U+5E80(5); +U+5E81(0);U+5E81(0);U+5EF3(3),U+5385(1,3),U+539B(1,3),U+5EF0(1,3,4) +U+5E82(0);U+4EC4(3);U+4EC4(3) +U+5E83(0);U+5E7F(4);U+5E7F(4),U+5EE3(4) +U+5E84(0);U+5E84(1,3);U+8358(4),U+838A(1,3) +U+5E85(0);U+4E48(4);U+4E48(4),U+9EBC(8,9),U+9EBD(4),U+5E7A(3,4) +U+5E86(0);U+5E86(1,3);U+6176(1,3) +U+5E87(0);U+5E87(5); +U+5E88(0);U+5E88(0); +U+5E89(0);U+5E89(0); +U+5E8A(0);U+5E8A(5);U+7240(2,3) +U+5E8B(0);U+5E8B(5); + +U+5E8C(0);U+5E8C(0); +U+5E8D(0);U+5E8D(0); +U+5E8E(0);U+5E8E(3); +U+5E8F(0);U+5E8F(5); +U+5E90(0);U+5E90(1,3);U+5EEC(1,3) +U+5E91(0);U+5E91(1,3);U+5EE1(1,3) +U+5E93(0);U+5E93(1,3);U+5EAB(1,3) +U+5E94(0);U+5E94(1,3,4);U+5FDC(4),U+61C9(1,3,4),U+8B4D(3) +U+5E95(0);U+5E95(5);U+538E(4) +U+5E96(0);U+5E96(5); +U+5E97(0);U+5E97(5);U+576B(3) +U+5E98(0);U+5E98(0); +U+5E99(0);U+5E99(1,3);U+5EBF(3),U+5EDF(1,3) +U+5E9A(0);U+5E9A(5); +U+5E9B(0);U+5E9B(0); +U+5E9C(0);U+5E9C(5); +U+5E9D(0);U+5E9D(0); +U+5E9E(0);U+5E9E(1,3);U+5390(4),U+9F8E(1,3,4),U+9F90(1,3) +U+5E9F(0);U+5E9F(1,3);U+5EC3(4),U+5EE2(1,3),U+7648(2) +U+5EA0(0);U+5EA0(5); +U+5EA1(0);U+5EA1(0); +U+5EA2(0);U+5EA2(3); +U+5EA3(0);U+5EA3(0); +U+5EA4(0);U+5EA4(0); +U+5EA5(0);U+5EA5(5); +U+5EA6(0);U+5EA6(5); +U+5EA7(0);U+5EA7(5);U+5750(3) +U+5EA8(0);U+5EA8(0); +U+5EA9(0);U+5EA9(0); +U+5EAA(0);U+5EAA(0); +U+5EAB(0);U+5E93(1,3);U+5E93(1,3) +U+5EAC(0);U+5EAC(3); +U+5EAD(0);U+5EAD(5); +U+5EAE(0);U+5EAE(0); +U+5EAF(0);U+5EAF(3); +U+5EB0(0);U+5C4F(4);U+5C4F(4),U+5C5B(3,4) +U+5EB1(0);U+5EB1(0); +U+5EB2(0);U+5EB2(0); +U+5EB3(0);U+5EB3(5); +U+5EB4(0);U+5EB4(0); +U+5EB5(0);U+5EB5(5);U+83F4(2,3) +U+5EB6(0);U+5EB6(5);U+5EBB(2),U+8B36(3) +U+5EB7(0);U+5EB7(5); +U+5EB8(0);U+5EB8(5); +U+5EB9(0);U+5EB9(5); +U+5EBB(0);U+5EB6(2);U+5EB6(2),U+8B36(2,3) +U+5EBC(0);U+5EBC(1,3);U+5ECE(1,3) +U+5EBD(0);U+5BD3(2,3);U+5BD3(2,3) +U+5EBE(0);U+5EBE(5);U+6594(3),U+659E(3) +U+5EBF(0);U+5E99(3);U+5E99(3),U+5EDF(3) +U+5EC1(0);U+5395(4);U+5395(4),U+53A0(2,3) +U+5EC2(0);U+53A2(2,3);U+53A2(2,3) +U+5EC3(0);U+5E9F(4);U+5E9F(4),U+5EE2(4),U+7648(2,4) +U+5EC4(0);U+53A9(2);U+53A9(2),U+5ECF(4),U+5ED0(8,9) +U+5EC5(0);U+5EC5(0); +U+5EC6(0);U+5EC6(0); +U+5EC7(0);U+5EC7(0); +U+5EC8(0);U+53A6(2,3);U+53A6(2,3) +U+5EC9(0);U+5EC9(5);U+4EB7(2),U+899D(4) +U+5ECA(0);U+5ECA(5); +U+5ECB(0);U+5ECB(3); +U+5ECC(0);U+5ECC(0); +U+5ECD(0);U+5ECD(0); + +U+5ECE(0);U+5EBC(1,3);U+5EBC(1,3) +U+5ECF(0);U+53A9(3,4);U+53A9(3,4),U+5EC4(4),U+5ED0(3) +U+5ED0(0);U+53A9(2);U+53A9(2),U+5EC4(8,9),U+5ECF(3) +U+5ED1(0);U+5ED1(5); +U+5ED2(0);U+5ED2(5); +U+5ED3(0);U+5ED3(5);U+9729(3) +U+5ED4(0);U+5ED4(0); +U+5ED5(0);U+836B(4);U+836B(4),U+852D(1,3,4) +U+5ED6(0);U+5ED6(5); +U+5ED7(0);U+5E2D(4);U+5E2D(4),U+84C6(2,3,4) +U+5ED8(0);U+5ED8(3); +U+5ED9(0);U+5ED9(0); +U+5EDA(0);U+53A8(2,3);U+53A8(2,3) +U+5EDB(0);U+5EDB(5); +U+5EDC(0);U+5EDC(0); +U+5EDD(0);U+53AE(2,3);U+53AE(2,3) +U+5EDE(0);U+5EDE(0); +U+5EDF(0);U+5E99(1,3);U+5E99(1,3),U+5EBF(3) +U+5EE0(0);U+5382(1,3);U+5382(1,3),U+53B0(3) +U+5EE1(0);U+5E91(1,3);U+5E91(1,3) +U+5EE2(0);U+5E9F(1,3);U+5E9F(1,3),U+5EC3(4),U+7648(1,2,3) +U+5EE3(0);U+5E7F(1,3);U+5E7F(1,3),U+5E83(4) +U+5EE4(0);U+5EE4(0); +U+5EE5(0);U+5EE5(0); +U+5EE6(0);U+5EE6(0); +U+5EE7(0);U+5EE7(0); +U+5EE8(0);U+5EE8(5); +U+5EE9(0);U+5EEA(3);U+5EEA(3),U+7A1F(3),U+7980(2,3) +U+5EEA(0);U+5EEA(5);U+5EE9(3),U+7A1F(3),U+7980(2,3) +U+5EEC(0);U+5E90(1,3);U+5E90(1,3) +U+5EED(0);U+5EED(0); +U+5EEE(0);U+5EEE(0); +U+5EEF(0);U+5EEF(0); +U+5EF0(0);U+5385(4);U+5385(4),U+5EF3(4),U+539B(3,4),U+5E81(1,3,4) +U+5EF1(0);U+5EF1(0); +U+5EF2(0);U+5EF2(0); +U+5EF3(0);U+5385(1,3);U+5385(1,3),U+539B(3),U+5E81(3),U+5EF0(4) +U+5EF4(0);U+5EF4(5); +U+5EF5(0);U+5DE1(2,3);U+5DE1(2,3) +U+5EF6(0);U+5EF6(5); +U+5EF7(0);U+5EF7(5); +U+5EF8(0);U+8FEA(3);U+8FEA(3) +U+5EFA(0);U+5EFA(5); +U+5EFB(0);U+56DE(2);U+56DE(2),U+5EFD(4),U+8FF4(2),U+9025(3),U+56D8(0,3),U+56EC(3) +U+5EFC(0);U+4E43(2,3);U+4E43(2,3),U+8FFA(4) +U+5EFD(0);U+56DE(4);U+56DE(4),U+5EFB(4),U+8FF4(8,9),U+56D8(0,2,3),U+56EC(2,3),U+9025(2,3,4) + +U+5EFE(0);U+5EFE(5); +U+5EFF(0);U+5EFF(5);U+5344(3) +U+5F00(0);U+5F00(1,3);U+958B(1,3) +U+5F01(0);U+5F01(5); +U+5F02(0);U+5F02(5);U+7570(2,3) +U+5F03(0);U+5F03(5);U+68C4(2,3) +U+5F04(0);U+5F04(5);U+8856(2) +U+5F05(0);U+5F05(0); +U+5F06(0);U+5F06(3); +U+5F07(0);U+5F07(0); +U+5F08(0);U+5F08(5); +U+5F0A(0);U+5F0A(5); +U+5F0B(0);U+5F0B(5);U+96BF(3) +U+5F0C(0);U+4E00(3);U+4E00(3),U+58F9(3),U+58F1(3,4) +U+5F0D(0);U+4E8C(3);U+4E8C(3),U+8CB3(3),U+8CAE(3,4),U+8D30(1,3) +U+5F0F(0);U+5F0F(5); + +U+5F11(0);U+5F11(5);U+5F12(4) +U+5F12(0);U+5F11(4);U+5F11(4) +U+5F13(0);U+5F13(5); +U+5F14(0);U+540A(2,3);U+540A(2,3) +U+5F15(0);U+5F15(5); +U+5F16(0);U+5F16(0); +U+5F17(0);U+5F17(5); +U+5F18(0);U+5F18(5); +U+5F19(0);U+5F19(0); +U+5F1A(0);U+5F1A(0); +U+5F1B(0);U+5F1B(5); +U+5F1C(0);U+5F1C(0); +U+5F1D(0);U+5F1D(0); +U+5F1E(0);U+5F1E(3); +U+5F1F(0);U+5F1F(5); +U+5F20(0);U+5F20(1,3);U+5F35(1,3) +U+5F21(0);U+5F21(0); +U+5F22(0);U+5F22(3); +U+5F23(0);U+5F23(3); +U+5F24(0);U+5F24(0); +U+5F25(0);U+5F25(1,3);U+519E(7),U+5F4C(1,3),U+7030(1,3) +U+5F26(0);U+5F26(5);U+7D43(2) +U+5F27(0);U+5F27(5); +U+5F28(0);U+5F28(0); +U+5F29(0);U+5F29(5); +U+5F2A(0);U+5F2A(4);U+5F33(4) +U+5F2B(0);U+5F2B(0); +U+5F2C(0);U+5F2C(0); +U+5F2D(0);U+5F2D(5); +U+5F2E(0);U+5F2E(0); +U+5F2F(0);U+5F2F(1,3);U+5F4E(1,3) +U+5F30(0);U+5F30(0); +U+5F31(0);U+5F31(5); +U+5F32(0);U+5F32(0); +U+5F33(0);U+5F2A(4);U+5F2A(4) +U+5F34(0);U+5F34(0); +U+5F35(0);U+5F20(1,3);U+5F20(1,3) +U+5F36(0);U+5F36(4); +U+5F37(0);U+5F3A(2,3);U+5F3A(2,3),U+5F4A(7) +U+5F38(0);U+5F38(0); +U+5F39(0);U+5F39(1,3);U+5F3E(4),U+5F48(1,3) +U+5F3A(0);U+5F3A(5);U+5F37(2,3),U+5F4A(2,3) +U+5F3C(0);U+5F3C(5); +U+5F3E(0);U+5F39(4);U+5F39(4),U+5F48(8,9) +U+5F3F(0);U+5F3F(0); +U+5F40(0);U+5F40(5); +U+5F41(0);U+5F41(0); +U+5F42(0);U+53D1(4);U+53D1(4),U+767C(4),U+9AEA(4),U+9AEE(1,3,4) +U+5F43(0);U+5F43(3); +U+5F44(0);U+5F44(3); +U+5F45(0);U+5F45(0); +U+5F46(0);U+522B(1,3);U+522B(1,3),U+618B(3),U+5225(0,1,3,4) +U+5F47(0);U+5F47(0); +U+5F48(0);U+5F39(1,3);U+5F39(1,3),U+5F3E(8,9) +U+5F49(0);U+5F4D(3);U+5F4D(3) +U+5F4A(0);U+5F3A(2,3);U+5F37(7),U+5F3A(2,3) +U+5F4B(0);U+5F4B(0); +U+5F4C(0);U+5F25(1,3);U+5F25(1,3),U+7030(4),U+519E(1,3,7) +U+5F4D(0);U+5F4D(3);U+5F49(3) +U+5F4E(0);U+5F2F(1,3);U+5F2F(1,3) +U+5F4F(0);U+5F4F(0); +U+5F50(0);U+5F50(5);U+5F51(4) +U+5F51(0);U+5F50(4);U+5F50(4) + +U+5F52(0);U+5F52(1,3);U+5E30(3),U+6B78(1,3),U+7688(3) +U+5F53(0);U+5F53(1,3);U+5679(1,3),U+7576(1,3) +U+5F54(0);U+5F55(3);U+5F55(3),U+9304(3,4),U+9332(1,3) +U+5F55(0);U+5F55(1,3,4);U+5F54(3),U+9304(4),U+9332(1,3) +U+5F56(0);U+5F56(5); +U+5F57(0);U+5F57(5);U+7BF2(3) +U+5F58(0);U+5F58(5); +U+5F59(0);U+6C47(1,3);U+532F(1,3),U+5F5A(4),U+6C47(1,3),U+6ED9(4) +U+5F5A(0);U+6C47(4);U+5F59(4),U+6C47(4),U+532F(0,4),U+6ED9(4) +U+5F5B(0);U+5F5D(4);U+5F5C(4),U+5F5D(4),U+5F5E(4) +U+5F5C(0);U+5F5D(3);U+5F5B(4),U+5F5D(3),U+5F5E(4) +U+5F5D(0);U+5F5D(5);U+5F5B(4),U+5F5C(3),U+5F5E(4) +U+5F5E(0);U+5F5D(4);U+5F5D(4),U+5F5B(0,4),U+5F5C(4) +U+5F5F(0);U+5F5F(4);U+5F60(4) +U+5F60(0);U+5F5F(4);U+5F5F(4) +U+5F61(0);U+5F61(5); +U+5F62(0);U+5F62(5); +U+5F63(0);U+5F63(0); +U+5F64(0);U+5F64(5); +U+5F65(0);U+5F66(4);U+5F66(4) +U+5F66(0);U+5F66(5);U+5F65(4) +U+5F67(0);U+5F67(3); +U+5F68(0);U+5F68(4);U+5F72(4) +U+5F69(0);U+5F69(5);U+7DB5(2) +U+5F6A(0);U+5F6A(5); +U+5F6B(0);U+5F6B(3);U+96D5(2),U+7431(2,3),U+9D70(2,3) +U+5F6C(0);U+5F6C(5);U+4EFD(3) +U+5F6D(0);U+5F6D(5); +U+5F6E(0);U+5F6E(0); +U+5F6F(0);U+5F6F(0); +U+5F70(0);U+5F70(5); +U+5F71(0);U+5F71(5); +U+5F72(0);U+5F68(4);U+5F68(4) +U+5F73(0);U+5F73(5); +U+5F74(0);U+5F74(0); +U+5F75(0);U+5F75(0); +U+5F76(0);U+5F76(0); +U+5F77(0);U+5F77(5);U+4EFF(4),U+5023(2,3,4),U+9AE3(2,3,4) +U+5F78(0);U+5F78(0); +U+5F79(0);U+5F79(5); +U+5F7A(0);U+5F7A(0); +U+5F7B(0);U+5F7B(1,3);U+5FB9(1,3) +U+5F7C(0);U+5F7C(5); +U+5F7D(0);U+5F7D(0); +U+5F7E(0);U+5F7E(0); +U+5F7F(0);U+4F5B(2);U+4F5B(2),U+9AF4(8,9),U+4ECF(0,2,3) +U+5F80(0);U+5F80(5);U+5F83(2,3),U+8FEC(3) +U+5F81(0);U+5F81(1,3);U+5FB4(4),U+5FB5(1,3,4) +U+5F82(0);U+5F82(5); +U+5F83(0);U+5F80(2,3);U+5F80(2,3),U+8FEC(2,3) +U+5F84(0);U+5F84(1,3);U+5F91(1,3),U+9015(4),U+8FF3(4) +U+5F85(0);U+5F85(5); +U+5F86(0);U+5F86(0); +U+5F87(0);U+5F87(5); +U+5F88(0);U+5F88(5);U+4F77(3) +U+5F89(0);U+5F89(5); +U+5F8A(0);U+5F8A(5);U+4F6A(3) +U+5F8B(0);U+5F8B(5); +U+5F8C(0);U+540E(1,3);U+540E(1,3) +U+5F8D(0);U+5F8D(0); +U+5F8E(0);U+5F8E(0); +U+5F90(0);U+5F90(5); +U+5F91(0);U+5F84(1,3);U+5F84(1,3),U+9015(2,3),U+8FF3(1,3,4) + +U+5F92(0);U+5F92(5); +U+5F93(0);U+4ECE(3);U+4ECE(3),U+5F9E(3) +U+5F94(0);U+5F94(0); +U+5F95(0);U+5F95(1,3);U+5FA0(1,3) +U+5F96(0);U+5F96(0); +U+5F97(0);U+5F97(5); +U+5F98(0);U+5F98(5); +U+5F99(0);U+5F99(5); +U+5F9B(0);U+5F9B(3); +U+5F9C(0);U+5F9C(5); +U+5F9D(0);U+5F9D(0); +U+5F9E(0);U+4ECE(1,3);U+4ECE(1,3),U+5F93(3) +U+5F9F(0);U+5F9F(0); +U+5FA0(0);U+5F95(1,3);U+5F95(1,3) +U+5FA1(0);U+5FA1(1,3);U+79A6(1,3) +U+5FA2(0);U+5FA2(0); +U+5FA5(0);U+5FA5(0); +U+5FA6(0);U+5FA6(0); +U+5FA7(0);U+904D(2,3);U+904D(2,3) +U+5FA8(0);U+5FA8(5);U+9051(3) +U+5FA9(0);U+590D(1,3);U+590D(1,3),U+8986(3),U+8907(1,3) +U+5FAA(0);U+5FAA(5); +U+5FAB(0);U+5FAB(0); +U+5FAC(0);U+508D(3);U+508D(3) +U+5FAD(0);U+5FAD(5);U+509C(4) +U+5FAE(0);U+5FAE(5); +U+5FAF(0);U+5FAF(3); +U+5FB1(0);U+5FB1(0); +U+5FB2(0);U+5FB2(4); +U+5FB3(0);U+5FB7(3);U+5FB7(3),U+60B3(2,3),U+60EA(3,4) +U+5FB4(0);U+5F81(4);U+5F81(4),U+5FB5(4) +U+5FB5(0);U+5FB5(0),U+5F81(1,3);U+5F81(1,3),U+5FB4(4) +U+5FB6(0);U+5FB6(0); +U+5FB7(0);U+5FB7(5);U+5FB3(3),U+60B3(2,3),U+60EA(4) +U+5FB8(0);U+5FB8(0); +U+5FB9(0);U+5F7B(1,3);U+5F7B(1,3) +U+5FBA(0);U+4FA5(3);U+4FA5(3),U+50E5(8,9),U+510C(3) +U+5FBB(0);U+5FBB(0); +U+5FBC(0);U+5FBC(5); +U+5FBD(0);U+5FBD(5); +U+5FBE(0);U+5FBE(0); +U+5FBF(0);U+5FBF(0); +U+5FC0(0);U+5FC0(0); +U+5FC1(0);U+5FC1(0); +U+5FC3(0);U+5FC3(5); +U+5FC4(0);U+5FC4(5); +U+5FC5(0);U+5FC5(5); +U+5FC6(0);U+5FC6(1,3);U+61B6(1,3) +U+5FC7(0);U+5FC7(0); +U+5FC8(0);U+4EC1(4);U+4EC1(4) +U+5FC9(0);U+5FC9(5); +U+5FCA(0);U+5FCA(0); +U+5FCB(0);U+5FCB(0); +U+5FCC(0);U+5FCC(5);U+8A8B(3),U+8AC5(3) +U+5FCD(0);U+5FCD(5); +U+5FCF(0);U+5FCF(1,3);U+61FA(1,3) +U+5FD0(0);U+5FD0(5); +U+5FD1(0);U+5FD1(5); +U+5FD2(0);U+5FD2(5); +U+5FD3(0);U+5FD3(0); +U+5FD4(0);U+5FD4(3); +U+5FD5(0);U+5FD5(0); +U+5FD6(0);U+5FD6(5);U+520C(3) + +U+5FD7(0);U+5FD7(5);U+8A8C(2,3) +U+5FD8(0);U+5FD8(5); +U+5FD9(0);U+5FD9(5); +U+5FDA(0);U+5FDA(0); +U+5FDC(0);U+5E94(1,3,4);U+5E94(1,3,4),U+61C9(1,3,4),U+8B4D(3) +U+5FDD(0);U+5FDD(5); +U+5FDE(0);U+5FDE(3); +U+5FE0(0);U+5FE0(5); +U+5FE1(0);U+5FE1(5); +U+5FE3(0);U+6025(3);U+6025(3) +U+5FE4(0);U+5FE4(5); +U+5FE5(0);U+5FE5(0); +U+5FE6(0);U+5FE6(3); +U+5FE7(0);U+5FE7(1,3);U+6182(1,3) +U+5FE8(0);U+5FE8(0); +U+5FE9(0);U+5FE9(0); +U+5FEA(0);U+5FEA(5); +U+5FEB(0);U+5FEB(5); +U+5FED(0);U+5FED(5); +U+5FEE(0);U+5FEE(5); +U+5FEF(0);U+5FEF(0); +U+5FF0(0);U+60B4(3);U+60B4(3) +U+5FF1(0);U+5FF1(5); +U+5FF2(0);U+5FF2(3); +U+5FF3(0);U+5FF3(3); +U+5FF4(0);U+5FF4(0); +U+5FF5(0);U+5FF5(5);U+5538(2,3) +U+5FF6(0);U+5FF6(0); +U+5FF7(0);U+5FF7(0); +U+5FF8(0);U+5FF8(5); +U+5FF9(0);U+5FF9(0); +U+5FFA(0);U+5FFA(0); +U+5FFB(0);U+5FFB(5); +U+5FFD(0);U+5FFD(5); +U+5FFE(0);U+5FFE(1,3);U+613E(1,3) +U+5FFF(0);U+5FFF(5); +U+6000(0);U+6000(1,3);U+61F7(1,3),U+61D0(3),U+8922(3),U+8931(3) +U+6001(0);U+6001(1,3);U+614B(1,3) +U+6002(0);U+6002(1,3);U+616B(1,3) +U+6003(0);U+6003(1,3);U+61AE(1,3) +U+6004(0);U+6004(1,3);U+616A(1,3) +U+6005(0);U+6005(1,3);U+60B5(1,3) +U+6006(0);U+6006(1,3);U+6134(1,3) +U+6007(0);U+6007(0); +U+6008(0);U+6008(0); +U+6009(0);U+6009(0); +U+600A(0);U+600A(5); +U+600B(0);U+600B(3); +U+600C(0);U+600C(0); +U+600D(0);U+600D(5); +U+600E(0);U+600E(5); +U+600F(0);U+600F(5); +U+6010(0);U+4F5D(3);U+4F5D(3) +U+6011(0);U+6011(0); +U+6012(0);U+6012(5); +U+6013(0);U+6013(0); +U+6014(0);U+6014(5); +U+6015(0);U+6015(5); +U+6016(0);U+6016(5); +U+6017(0);U+6017(3); +U+6018(0);U+6018(0); +U+6019(0);U+6019(5); +U+601A(0);U+601A(0); + +U+601B(0);U+601B(5); +U+601C(0);U+601C(1,3);U+6190(1,3) +U+601D(0);U+601D(5); +U+601E(0);U+601E(0); +U+601F(0);U+601F(0); +U+6020(0);U+6020(5); +U+6021(0);U+6021(5); +U+6022(0);U+6022(0); +U+6024(0);U+6024(3); +U+6025(0);U+6025(5);U+5FE3(3) +U+6026(0);U+6026(5); +U+6027(0);U+6027(5); +U+6028(0);U+6028(5); +U+6029(0);U+6029(5); +U+602A(0);U+602A(5); +U+602B(0);U+602B(5); +U+602C(0);U+602C(0); +U+602D(0);U+602D(0); +U+602E(0);U+602E(0); +U+602F(0);U+602F(5); +U+6030(0);U+6030(0); +U+6031(0);U+5306(2,3);U+5306(2,3),U+60A4(4) +U+6032(0);U+6032(0); +U+6033(0);U+604D(2);U+604D(2) +U+6034(0);U+6034(0); +U+6035(0);U+6035(5); +U+6036(0);U+6036(0); +U+6037(0);U+6037(0); +U+6038(0);U+6038(0); +U+6039(0);U+4ED6(3);U+4ED6(3) +U+603A(0);U+603A(0); +U+603B(0);U+603B(1,3);U+6374(4),U+6403(3),U+6460(3),U+7DCF(3),U+7E02(4),U+7E3D(1,3) +U+603C(0);U+603C(1,3);U+61DF(1,3) +U+603D(0);U+603D(0); +U+603E(0);U+603E(0); +U+603F(0);U+603F(1,3);U+61CC(1,3) +U+6040(0);U+6040(3); +U+6041(0);U+6041(5); +U+6042(0);U+6042(5);U+609B(4) +U+6043(0);U+6043(5); +U+6044(0);U+6044(0); +U+6045(0);U+6045(0); +U+6046(0);U+6052(2,3);U+6052(2,3) +U+6047(0);U+6047(0); +U+6048(0);U+6048(0); +U+6049(0);U+65E8(4);U+65E8(4) +U+604A(0);U+534F(3);U+534F(3),U+5354(3),U+52A6(0,3) +U+604B(0);U+604B(1,3);U+6200(1,3) +U+604C(0);U+604C(0); +U+604D(0);U+604D(5);U+6033(2) +U+604E(0);U+604E(0); +U+604F(0);U+604F(0); +U+6050(0);U+6050(5); +U+6051(0);U+6051(0); +U+6052(0);U+6052(5);U+6046(2,3) +U+6053(0);U+6053(0); +U+6054(0);U+6054(0); +U+6055(0);U+6055(5); +U+6057(0);U+6057(0); +U+6058(0);U+6058(3); +U+6059(0);U+6059(5); +U+605A(0);U+605A(5); +U+605B(0);U+605B(0); + +U+605C(0);U+605C(0); +U+605D(0);U+605D(5); +U+605E(0);U+605E(3); +U+605F(0);U+605F(3); +U+6062(0);U+6062(5); +U+6063(0);U+6063(5); +U+6064(0);U+6064(5);U+5379(2),U+8CC9(2,3) +U+6065(0);U+803B(2,3);U+803B(2,3) +U+6066(0);U+6066(0); +U+6067(0);U+6067(5); +U+6068(0);U+6068(5); +U+6069(0);U+6069(5); +U+606A(0);U+606A(5);U+6118(3) +U+606B(0);U+606B(5);U+75CC(3) +U+606C(0);U+606C(5); +U+606D(0);U+606D(5); +U+606E(0);U+606E(0); +U+606F(0);U+606F(5); +U+6070(0);U+6070(5); +U+6072(0);U+6072(0); +U+6073(0);U+6073(1,3);U+61C7(1,3) +U+6075(0);U+60E0(4);U+60E0(4),U+6193(4) +U+6076(0);U+6076(1,3);U+5641(1,3),U+60AA(3),U+60E1(1,3) +U+6077(0);U+6077(0); +U+6078(0);U+6078(1,3);U+615F(1,3),U+6185(3) +U+6079(0);U+6079(1,3);U+61E8(1,3) +U+607A(0);U+607A(1,3);U+6137(1,3) +U+607B(0);U+607B(1,3);U+60FB(1,3) +U+607C(0);U+607C(1,3);U+60F1(1,3) +U+607D(0);U+607D(1,3);U+60F2(1,3) +U+607E(0);U+607E(3); +U+607F(0);U+607F(5);U+6142(2,3) +U+6080(0);U+6080(3); +U+6081(0);U+6081(0); +U+6082(0);U+6082(0); +U+6083(0);U+6083(5); +U+6084(0);U+6084(5); +U+6085(0);U+60A6(4);U+60A6(4) +U+6086(0);U+6086(0); +U+6087(0);U+6087(0); +U+6088(0);U+6088(0); +U+6089(0);U+6089(5); +U+608A(0);U+608A(0); +U+608B(0);U+541D(3);U+541D(3) +U+608C(0);U+608C(5); +U+608D(0);U+608D(5); +U+608E(0);U+608E(0); +U+608F(0);U+608F(0); +U+6090(0);U+60D5(3);U+60D5(3) +U+6092(0);U+6092(5); +U+6094(0);U+6094(5); +U+6095(0);U+6095(0); +U+6096(0);U+6096(5);U+8A96(2,3) +U+6097(0);U+6097(3); +U+6098(0);U+6098(0); +U+6099(0);U+6099(0); +U+609A(0);U+609A(5); +U+609B(0);U+609B(5);U+6042(4) +U+609C(0);U+609C(0); +U+609D(0);U+609D(5); +U+609E(0);U+8BEF(3);U+60AE(7),U+8AA4(3),U+8BEF(3) +U+609F(0);U+609F(5); +U+60A0(0);U+60A0(5); + +U+60A1(0);U+60A1(0); +U+60A2(0);U+60A2(3); +U+60A3(0);U+60A3(5); +U+60A4(0);U+5306(2,3,4);U+5306(2,3,4),U+6031(4) +U+60A6(0);U+60A6(5);U+6085(4) +U+60A7(0);U+60A7(0); +U+60A8(0);U+60A8(5); +U+60AA(0);U+6076(3);U+6076(3),U+60E1(3),U+5641(0,1,3) +U+60AB(0);U+60AB(1,3);U+6128(3),U+6164(1,3) +U+60AC(0);U+60AC(1,3);U+61F8(1,3) +U+60AD(0);U+60AD(1,3);U+6173(1,3) +U+60AE(0);U+8BEF(4);U+609E(7),U+8AA4(4),U+8BEF(4) +U+60AF(0);U+60AF(1,3);U+61AB(1,3) +U+60B0(0);U+60B0(0); +U+60B1(0);U+60B1(5); +U+60B2(0);U+60B2(5); +U+60B3(0);U+5FB7(2,3);U+5FB7(2,3),U+5FB3(0,2,3),U+60EA(2,3,4) +U+60B4(0);U+60B4(5);U+5FF0(3) +U+60B5(0);U+6005(1,3);U+6005(1,3) +U+60B6(0);U+95F7(1,3);U+95F7(1,3) +U+60B7(0);U+60B7(0); +U+60B8(0);U+60B8(5);U+75F5(3,4) +U+60B9(0);U+60B9(3);U+60BA(3) +U+60BA(0);U+60B9(3);U+60B9(3) +U+60BB(0);U+60BB(5); +U+60BC(0);U+60BC(5); +U+60BD(0);U+51C4(2);U+51C4(2),U+6DD2(2,3) +U+60BE(0);U+60BE(0); +U+60BF(0);U+60BF(0); +U+60C0(0);U+60C0(0); +U+60C1(0);U+60C1(0); +U+60C2(0);U+60C2(0); +U+60C3(0);U+60C3(0); +U+60C4(0);U+60C4(3); +U+60C5(0);U+60C5(5); +U+60C6(0);U+60C6(5); +U+60C7(0);U+60C7(0); +U+60C8(0);U+60C8(4); +U+60C9(0);U+60C9(3); +U+60CA(0);U+60CA(1,3);U+9A5A(1,3) +U+60CB(0);U+60CB(5); +U+60CC(0);U+60CC(0); +U+60CD(0);U+60CD(0); +U+60CE(0);U+60CE(0); +U+60CF(0);U+60CF(0); +U+60D0(0);U+60D0(3); +U+60D1(0);U+60D1(5); +U+60D3(0);U+60D3(0); +U+60D4(0);U+60D4(0); +U+60D5(0);U+60D5(5);U+6090(3) +U+60D7(0);U+60D7(0); +U+60D8(0);U+60D8(5); +U+60D9(0);U+60D9(0); +U+60DA(0);U+60DA(5); +U+60DB(0);U+60DB(3); +U+60DC(0);U+60DC(5); +U+60DD(0);U+60DD(5); +U+60DF(0);U+60DF(5); +U+60E0(0);U+60E0(5);U+6075(4),U+6193(4) +U+60E1(0);U+6076(1,3);U+5641(4),U+6076(1,3),U+60AA(3) +U+60E2(0);U+60E2(0); +U+60E4(0);U+60E4(0); +U+60E6(0);U+60E6(5); + +U+60E7(0);U+60E7(1,3);U+61FC(1,3) +U+60E8(0);U+60E8(1,3);U+6158(1,3) +U+60E9(0);U+60E9(1,3);U+61F2(1,3) +U+60EA(0);U+5FB7(4);U+5FB7(4),U+5FB3(0,3,4),U+60B3(2,3,4) +U+60EB(0);U+60EB(1,3);U+618A(1,3) +U+60EC(0);U+60EC(1,3);U+611C(1,3) +U+60ED(0);U+60ED(1,3);U+6159(4),U+615A(1,3) +U+60EE(0);U+60EE(1,3);U+619A(1,3) +U+60EF(0);U+60EF(1,3);U+6163(1,3) +U+60F0(0);U+60F0(5); +U+60F1(0);U+607C(1,3);U+607C(1,3) +U+60F2(0);U+607D(1,3);U+607D(1,3) +U+60F3(0);U+60F3(5); +U+60F4(0);U+60F4(5); +U+60F5(0);U+60F5(0); +U+60F6(0);U+60F6(5); +U+60F7(0);U+8822(2,3);U+8822(2,3) +U+60F8(0);U+8315(4);U+8315(4),U+7162(1,3,4),U+712D(0,1,3,4) +U+60F9(0);U+60F9(5); +U+60FA(0);U+60FA(5); +U+60FB(0);U+607B(1,3);U+607B(1,3) +U+60FC(0);U+890A(3);U+890A(3) +U+60FE(0);U+60FE(0); +U+60FF(0);U+60FF(3); +U+6100(0);U+6100(5); +U+6101(0);U+6101(5); +U+6103(0);U+6103(0); +U+6104(0);U+754F(4);U+754F(4) +U+6105(0);U+6105(0); +U+6106(0);U+6106(5); +U+6108(0);U+6108(5);U+7609(2,3),U+7652(2) +U+6109(0);U+6109(5); +U+610A(0);U+610A(0); +U+610B(0);U+63F4(3);U+63F4(3) +U+610C(0);U+610C(0); +U+610D(0);U+610D(5);U+656F(4) +U+610E(0);U+610E(5); +U+610F(0);U+610F(5); +U+6110(0);U+6110(0); +U+6112(0);U+6112(3); +U+6113(0);U+6113(0); +U+6114(0);U+6114(0); +U+6115(0);U+6115(5); +U+6116(0);U+6116(0); +U+6117(0);U+6117(0); +U+6118(0);U+606A(3);U+606A(3) +U+6119(0);U+6119(4); +U+611A(0);U+611A(5); +U+611B(0);U+7231(1,3);U+7231(1,3) +U+611C(0);U+60EC(1,3);U+60EC(1,3) +U+611D(0);U+611D(0); +U+611F(0);U+611F(5); +U+6120(0);U+6120(5);U+614D(3) +U+6122(0);U+6122(0); +U+6123(0);U+6123(5); +U+6124(0);U+6124(1,3);U+61A4(1,3) +U+6125(0);U+6125(0); +U+6126(0);U+6126(1,3);U+6192(1,3) +U+6127(0);U+6127(5);U+5ABF(2,3) +U+6128(0);U+60AB(3);U+60AB(3),U+6164(3) +U+6129(0);U+6129(0); +U+612A(0);U+612A(0); +U+612B(0);U+612B(5); + +U+612C(0);U+8BC9(3);U+8BC9(3),U+8A34(2,3) +U+612D(0);U+612D(0); +U+612E(0);U+612E(0); +U+612F(0);U+612F(0); +U+6130(0);U+6130(0); +U+6132(0);U+6132(0); +U+6134(0);U+6006(1,3);U+6006(1,3) +U+6136(0);U+6136(3); +U+6137(0);U+607A(1,3);U+607A(1,3) +U+613A(0);U+613A(0); +U+613B(0);U+900A(3);U+900A(3),U+905C(1,3) +U+613C(0);U+614E(4);U+614E(4),U+661A(2,3,4),U+7718(3,4) +U+613D(0);U+535A(2,3);U+535A(2,3) +U+613E(0);U+5FFE(1,3);U+5FFE(1,3) +U+613F(0);U+613F(1,3);U+9858(1,3) +U+6140(0);U+6140(0); +U+6141(0);U+6141(0); +U+6142(0);U+607F(2,3);U+607F(2,3) +U+6143(0);U+6143(3); +U+6144(0);U+6817(2);U+6817(2) +U+6145(0);U+6145(3); +U+6146(0);U+6146(0); +U+6147(0);U+6BB7(2,3);U+6BB7(2,3) +U+6148(0);U+6148(5); +U+6149(0);U+6149(3); +U+614A(0);U+614A(5); +U+614B(0);U+6001(1,3);U+6001(1,3) +U+614C(0);U+614C(5); +U+614D(0);U+6120(3);U+6120(3) +U+614E(0);U+614E(5);U+613C(4),U+661A(2,3),U+7718(3) +U+614F(0);U+614F(0); +U+6150(0);U+6150(0); +U+6151(0);U+6151(1,3);U+61FE(1,3),U+6174(4) +U+6152(0);U+6152(0); +U+6153(0);U+527D(4);U+527D(4) +U+6154(0);U+6154(0); +U+6155(0);U+6155(5); +U+6156(0);U+6156(0); +U+6157(0);U+6157(0); +U+6158(0);U+60E8(1,3);U+60E8(1,3) +U+6159(0);U+60ED(4);U+60ED(4),U+615A(2,3) +U+615A(0);U+60ED(1,3);U+60ED(1,3),U+6159(2,3) +U+615B(0);U+615B(0); +U+615C(0);U+615C(0); +U+615D(0);U+615D(5); +U+615E(0);U+615E(0); +U+615F(0);U+6078(1,3);U+6078(1,3),U+6185(3) +U+6161(0);U+723D(3);U+723D(3) +U+6162(0);U+6162(5); +U+6163(0);U+60EF(1,3);U+60EF(1,3) +U+6164(0);U+60AB(1,3);U+60AB(1,3),U+6128(3) +U+6165(0);U+6165(0); +U+6166(0);U+6166(0); +U+6167(0);U+6167(5);U+8B7F(3) +U+6168(0);U+6168(5); +U+6169(0);U+6169(0); +U+616A(0);U+6004(1,3);U+6004(1,3) +U+616B(0);U+6002(1,3);U+6002(1,3) +U+616C(0);U+616C(3); +U+616D(0);U+616D(6);U+6196(3) +U+616E(0);U+8651(1,3);U+8651(1,3) +U+6170(0);U+6170(5); +U+6171(0);U+6171(0); + +U+6172(0);U+6172(0); +U+6173(0);U+60AD(1,3);U+60AD(1,3) +U+6174(0);U+6151(4);U+6151(4),U+61FE(1,3,4) +U+6175(0);U+6175(5);U+5ADE(4) +U+6176(0);U+5E86(1,3);U+5E86(1,3) +U+6177(0);U+6177(5); +U+6178(0);U+6178(0); +U+6179(0);U+6179(0); +U+617A(0);U+617A(0); +U+617C(0);U+617C(3); +U+617E(0);U+6B32(2);U+6B32(2) +U+6180(0);U+6180(0); +U+6181(0);U+6181(3); +U+6182(0);U+5FE7(1,3);U+5FE7(1,3) +U+6183(0);U+6183(0); +U+6184(0);U+6184(0); +U+6185(0);U+6078(3);U+6078(3),U+615F(3) +U+6187(0);U+61A9(2,3);U+61A9(2,3) +U+6188(0);U+6188(0); +U+6189(0);U+6189(0); +U+618A(0);U+60EB(1,3);U+60EB(1,3) +U+618B(0);U+618B(5);U+522B(3),U+5F46(3),U+5225(0,3,4) +U+618C(0);U+618C(0); +U+618D(0);U+9A84(3);U+9A84(3),U+9A55(1,3) +U+618E(0);U+618E(5); +U+618F(0);U+618F(0); +U+6190(0);U+601C(1,3);U+601C(1,3) +U+6191(0);U+51ED(1,3);U+51ED(1,3),U+51F4(2) +U+6192(0);U+6126(1,3);U+6126(1,3) +U+6193(0);U+60E0(4);U+60E0(4),U+6075(0,4) +U+6194(0);U+6194(5); +U+6195(0);U+6195(0); +U+6196(0);U+616D(3);U+616D(3) +U+6198(0);U+6198(0); +U+6199(0);U+559C(3);U+559C(3) +U+619A(0);U+60EE(1,3);U+60EE(1,3) +U+619B(0);U+619B(0); +U+619D(0);U+619D(5);U+8B48(3) +U+619E(0);U+619E(3); +U+619F(0);U+619F(0); +U+61A0(0);U+61A0(0); +U+61A1(0);U+61A1(0); +U+61A2(0);U+61A2(0); +U+61A3(0);U+61A3(0); +U+61A4(0);U+6124(1,3);U+6124(1,3) +U+61A5(0);U+61A5(3); +U+61A6(0);U+61A6(0); +U+61A7(0);U+61A7(5); +U+61A8(0);U+61A8(5); +U+61A9(0);U+61A9(5);U+6187(2,3) +U+61AA(0);U+61AA(0); +U+61AB(0);U+60AF(1,3);U+60AF(1,3) +U+61AC(0);U+61AC(5); +U+61AD(0);U+61AD(0); +U+61AE(0);U+6003(1,3);U+6003(1,3) +U+61AF(0);U+61AF(0); +U+61B0(0);U+61B0(0); +U+61B1(0);U+61B1(0); +U+61B2(0);U+5BAA(1,3);U+5BAA(1,3) +U+61B3(0);U+61B3(0); +U+61B4(0);U+61B4(0); +U+61B5(0);U+61B5(0); + +U+61B6(0);U+5FC6(1,3);U+5FC6(1,3) +U+61B7(0);U+61B7(5); +U+61B8(0);U+61B8(0); +U+61BA(0);U+61BA(0); +U+61BC(0);U+5106(3);U+5106(3) +U+61BD(0);U+61BD(0); +U+61BE(0);U+61BE(5); +U+61BF(0);U+61BF(0); +U+61C0(0);U+61C0(0); +U+61C1(0);U+61C1(0); +U+61C2(0);U+61C2(5); +U+61C3(0);U+52E4(2,3);U+52E4(2,3),U+763D(2,3) +U+61C4(0);U+61C4(0); +U+61C5(0);U+61C5(0); +U+61C6(0);U+61C6(0); +U+61C7(0);U+6073(1,3);U+6073(1,3) +U+61C8(0);U+61C8(5); +U+61C9(0);U+5E94(1,3,4);U+5E94(1,3,4),U+5FDC(4),U+8B4D(3) +U+61CA(0);U+61CA(5); +U+61CB(0);U+61CB(5); +U+61CC(0);U+603F(1,3);U+603F(1,3) +U+61CD(0);U+61D4(4);U+61D4(4) +U+61CE(0);U+61CE(0); +U+61CF(0);U+61CF(0); +U+61D0(0);U+6000(3);U+61F7(3),U+6000(3),U+8922(3),U+8931(3) +U+61D1(0);U+61D1(1,3);U+61E3(1,3) +U+61D2(0);U+61D2(1,3);U+61F6(1,3),U+5B3E(4) +U+61D4(0);U+61D4(5);U+61CD(4) +U+61D6(0);U+61D6(0); +U+61D7(0);U+61D7(0); +U+61D8(0);U+61D8(3); +U+61D9(0);U+61D9(0); +U+61DA(0);U+61DA(0); +U+61DB(0);U+61DB(0); +U+61DC(0);U+61DC(3); +U+61DD(0);U+61DD(0); +U+61DE(0);U+8499(1);U+8499(1),U+6FDB(1,3,4),U+77C7(1,4) +U+61DF(0);U+603C(1,3);U+603C(1,3) +U+61E0(0);U+61E0(0); +U+61E1(0);U+61E1(0); +U+61E2(0);U+61E2(0); +U+61E3(0);U+61D1(1,3);U+61D1(1,3) +U+61E4(0);U+61E4(0); +U+61E5(0);U+61E5(0); +U+61E6(0);U+61E6(5);U+61E7(3) +U+61E7(0);U+61E6(3);U+61E6(3) +U+61E8(0);U+6079(1,3);U+6079(1,3) +U+61E9(0);U+61E9(0); +U+61EA(0);U+61EA(0); +U+61EB(0);U+61EB(0); +U+61ED(0);U+61ED(0); +U+61EE(0);U+61EE(0); +U+61F0(0);U+61F0(0); +U+61F1(0);U+61F1(0); +U+61F2(0);U+60E9(1,3);U+60E9(1,3) +U+61F3(0);U+61F3(0); +U+61F5(0);U+61F5(5); +U+61F6(0);U+61D2(1,3);U+61D2(1,3),U+5B3E(2,3) +U+61F7(0);U+6000(1,3);U+61D0(3),U+6000(1,3),U+8922(1,3),U+8931(1,3) +U+61F8(0);U+60AC(1,3);U+60AC(1,3) +U+61F9(0);U+61F9(0); +U+61FA(0);U+5FCF(1,3);U+5FCF(1,3) +U+61FB(0);U+61FB(0); + +U+61FC(0);U+60E7(1,3);U+60E7(1,3) +U+61FD(0);U+6B22(4);U+6B22(4),U+6B61(2,3),U+6B53(3,4),U+8B99(4),U+9A69(4) +U+61FE(0);U+6151(1,3);U+6151(1,3),U+6174(1,3,4) +U+61FF(0);U+61FF(5); +U+6200(0);U+604B(1,3);U+604B(1,3) +U+6201(0);U+6201(3); +U+6202(0);U+6202(0); +U+6203(0);U+6203(0); +U+6204(0);U+6204(0); +U+6206(0);U+6206(1,3);U+6207(1,3) +U+6207(0);U+6206(1,3);U+6206(1,3) +U+6208(0);U+6208(5); +U+6209(0);U+6209(0); +U+620A(0);U+620A(5); +U+620B(0);U+620B(1,3);U+6214(1,3) +U+620C(0);U+620C(5); +U+620D(0);U+620D(5); +U+620E(0);U+620E(5); +U+620F(0);U+620F(1,3,4);U+6231(4),U+6232(1,3),U+622F(4) +U+6210(0);U+6210(5); +U+6211(0);U+6211(5); +U+6212(0);U+6212(5); +U+6213(0);U+6213(0); +U+6214(0);U+620B(1,3);U+620B(1,3) +U+6215(0);U+6215(5); +U+6216(0);U+6216(5); +U+6217(0);U+6217(1,3);U+6227(1,3) +U+6218(0);U+6218(1,3);U+6230(1,3),U+6226(4) +U+6219(0);U+6219(0); +U+621A(0);U+621A(5); +U+621B(0);U+621B(5);U+621E(2,3) +U+621C(0);U+621C(0); +U+621D(0);U+8D3C(3);U+8CCA(3),U+8D3C(3) +U+621E(0);U+621B(2,3);U+621B(2,3) +U+621F(0);U+621F(5); +U+6220(0);U+6220(0); +U+6221(0);U+6221(5); +U+6222(0);U+6222(5); +U+6223(0);U+6223(3); +U+6224(0);U+6224(5); +U+6225(0);U+6225(5); +U+6226(0);U+6218(4);U+6218(4),U+6230(4) +U+6227(0);U+6217(1,3);U+6217(1,3) +U+6228(0);U+6228(0); +U+6229(0);U+622C(4);U+622C(4) +U+622A(0);U+622A(5); +U+622B(0);U+622B(0); +U+622C(0);U+622C(4);U+6229(4) +U+622D(0);U+622D(0); +U+622E(0);U+622E(5); +U+622F(0);U+620F(4);U+620F(4),U+6231(4),U+6232(2,3) +U+6230(0);U+6218(1,3);U+6218(1,3),U+6226(4) +U+6231(0);U+620F(4);U+620F(4),U+622F(4),U+6232(4) +U+6232(0);U+620F(1,3);U+620F(1,3),U+622F(2,3),U+6231(4) +U+6233(0);U+6233(5); +U+6234(0);U+6234(5); +U+6236(0);U+6237(4);U+6237(4),U+6238(8,9) +U+6237(0);U+6237(5);U+6236(4),U+6238(4) +U+6238(0);U+6237(4);U+6237(4),U+6236(8,9) +U+623A(0);U+623A(0); +U+623B(0);U+623E(4);U+623E(4),U+76ED(4) +U+623C(0);U+536F(2,3);U+536F(2,3),U+5918(2,3) +U+623D(0);U+623D(5); + +U+623E(0);U+623E(5);U+623B(4),U+76ED(4) +U+623F(0);U+623F(5); +U+6240(0);U+6240(5); +U+6241(0);U+6241(5); +U+6242(0);U+6242(0); +U+6243(0);U+6243(5); +U+6244(0);U+6244(0); +U+6245(0);U+6245(0); +U+6246(0);U+6246(0); +U+6247(0);U+6247(5);U+6427(4) +U+6248(0);U+6248(5); +U+6249(0);U+6249(5); +U+624A(0);U+624A(0); +U+624B(0);U+624B(5); +U+624C(0);U+624C(5); +U+624D(0);U+624D(1,3);U+7E94(1,3) +U+624E(0);U+624E(4);U+5273(4),U+5284(4),U+672D(3),U+7B9A(4),U+7D25(2),U+7D2E(2) +U+624F(0);U+624F(0); +U+6250(0);U+6250(3); +U+6251(0);U+6251(1,3);U+64B2(1,3),U+6534(3) +U+6252(0);U+6252(5); +U+6253(0);U+6253(5); +U+6254(0);U+6254(5); +U+6255(0);U+62C2(4);U+62C2(4) +U+6256(0);U+6256(0); +U+6258(0);U+6258(4);U+8A17(2,4),U+8BAC(4) +U+6259(0);U+6259(0); +U+625A(0);U+625A(0); +U+625B(0);U+625B(5);U+6443(2,3) +U+625C(0);U+625C(0); +U+625D(0);U+625D(0); +U+625E(0);U+625E(0);U+634D(2,3),U+64C0(3) +U+625F(0);U+625F(0); +U+6260(0);U+6260(3);U+640B(3) +U+6261(0);U+6261(0); +U+6262(0);U+6262(0); +U+6263(0);U+6263(5);U+91E6(2) +U+6264(0);U+6264(0); +U+6265(0);U+6265(0); +U+6266(0);U+6266(5); +U+6267(0);U+6267(1,3);U+57F7(1,3),U+74E1(3) +U+6268(0);U+6268(0); +U+6269(0);U+6269(1,3);U+62E1(4),U+64F4(1,3) +U+626A(0);U+626A(1,3);U+636B(1,3) +U+626B(0);U+626B(1,3);U+6383(1,3) +U+626C(0);U+626C(1,3,4);U+63DA(1,3),U+98BA(4),U+98CF(4) +U+626D(0);U+626D(5); +U+626E(0);U+626E(5); +U+626F(0);U+626F(5);U+64A6(2,3) +U+6270(0);U+6270(1,3);U+64FE(1,3) +U+6271(0);U+6271(3); +U+6272(0);U+6272(0); +U+6273(0);U+6273(5); +U+6274(0);U+6274(0); +U+6275(0);U+65BC(3);U+65BC(3),U+4E8E(3,4,5) +U+6276(0);U+6276(5); +U+6277(0);U+6277(0); +U+6278(0);U+6278(0); +U+6279(0);U+6279(5); +U+627A(0);U+627A(3);U+62B5(3),U+89DD(3),U+7274(2,3),U+7F9D(2,3) +U+627B(0);U+627B(0); +U+627C(0);U+627C(5);U+6424(2,3),U+6439(3) +U+627D(0);U+627D(3); + +U+627E(0);U+627E(5); +U+627F(0);U+627F(5); +U+6280(0);U+6280(5); +U+6281(0);U+6281(3); +U+6283(0);U+62DA(3);U+62DA(3) +U+6284(0);U+6284(5); +U+6285(0);U+6285(0); +U+6286(0);U+6286(3); +U+6287(0);U+6287(0); +U+6288(0);U+6288(0); +U+6289(0);U+6289(5);U+5214(7) +U+628A(0);U+628A(5); +U+628B(0);U+628B(0); +U+628C(0);U+628C(4);U+4F14(4) +U+628E(0);U+628E(0); +U+628F(0);U+628F(0); +U+6290(0);U+6290(0); +U+6291(0);U+6291(5); +U+6292(0);U+6292(5); +U+6293(0);U+6293(5); +U+6294(0);U+6294(3); +U+6295(0);U+6295(5); +U+6296(0);U+6296(5); +U+6297(0);U+6297(5); +U+6298(0);U+6298(1,3);U+647A(1,3,4) +U+6299(0);U+6299(0); +U+629A(0);U+629A(1,3);U+64AB(1,3),U+62CA(1,3) +U+629B(0);U+629B(5);U+62CB(4) +U+629C(0);U+62D4(4);U+62D4(4) +U+629E(0);U+62E9(4);U+62E9(4),U+64C7(8,9) +U+629F(0);U+629F(1,3);U+6476(1,3) +U+62A0(0);U+62A0(1,3);U+6473(1,3) +U+62A1(0);U+62A1(1,3);U+6384(1,3) +U+62A2(0);U+62A2(1,3);U+6436(1,3) +U+62A3(0);U+62A3(0); +U+62A4(0);U+62A4(1,3);U+8B77(1,3) +U+62A5(0);U+62A5(1,3);U+5831(1,3) +U+62A7(0);U+62A7(0); +U+62A8(0);U+62A8(5); +U+62A9(0);U+62A9(0); +U+62AA(0);U+62AA(0); +U+62AB(0);U+62AB(5); +U+62AC(0);U+62AC(5); +U+62AD(0);U+8200(4);U+8200(4) +U+62AE(0);U+62AE(0); +U+62AF(0);U+62AF(3); +U+62B0(0);U+62B0(0); +U+62B1(0);U+62B1(5); +U+62B2(0);U+62B2(3); +U+62B3(0);U+62B3(0); +U+62B4(0);U+62B4(0); +U+62B5(0);U+62B5(5);U+627A(3),U+7274(2,3),U+89DD(2),U+7F9D(2,3) +U+62B6(0);U+62B6(0); +U+62B7(0);U+62B7(0); +U+62B8(0);U+62B8(0); +U+62B9(0);U+62B9(5); +U+62BA(0);U+62BA(0); +U+62BB(0);U+62BB(5);U+4F38(3) +U+62BC(0);U+62BC(5); +U+62BD(0);U+62BD(5); +U+62BE(0);U+62BE(0); +U+62BF(0);U+62BF(5); +U+62C0(0);U+62C0(0); + +U+62C1(0);U+62C1(0); +U+62C2(0);U+62C2(5);U+6255(4) +U+62C3(0);U+62C3(3); +U+62C4(0);U+62C4(5); +U+62C5(0);U+62C5(1,3);U+64D4(1,3,4) +U+62C6(0);U+62C6(5); +U+62C7(0);U+62C7(5); +U+62C8(0);U+62C8(5); +U+62C9(0);U+62C9(5); +U+62CA(0);U+62CA(5);U+64AB(3),U+629A(1,3) +U+62CB(0);U+629B(4);U+629B(4) +U+62CC(0);U+62CC(5); +U+62CD(0);U+62CD(5); +U+62CE(0);U+62CE(5); +U+62CF(0);U+62CF(3);U+62FF(2,3) +U+62D0(0);U+62D0(4);U+67B4(4) +U+62D1(0);U+94B3(4);U+94B3(4),U+9257(1,3,4),U+7B9D(0,1,3,4,5) +U+62D2(0);U+62D2(5); +U+62D3(0);U+62D3(5);U+646D(3) +U+62D4(0);U+62D4(5);U+629C(4) +U+62D5(0);U+62D6(2,3);U+62D6(2,3) +U+62D6(0);U+62D6(5);U+62D5(2,3) +U+62D7(0);U+62D7(5); +U+62D8(0);U+62D8(5); +U+62D9(0);U+62D9(5); +U+62DA(0);U+62DA(5);U+6283(3) +U+62DB(0);U+62DB(5); +U+62DC(0);U+62DC(5);U+62DD(4) +U+62DD(0);U+62DC(4);U+62DC(4) +U+62DF(0);U+62DF(1,3);U+5117(4),U+64EC(1,3) +U+62E0(0);U+636E(3);U+636E(3),U+64DA(3) +U+62E1(0);U+6269(4);U+6269(4),U+64F4(4) +U+62E2(0);U+62E2(1,3);U+650F(1,3) +U+62E3(0);U+62E3(1,3);U+63C0(1,3) +U+62E4(0);U+62E4(0); +U+62E5(0);U+62E5(1,3);U+64C1(1,3) +U+62E6(0);U+62E6(1,3);U+6514(1,3) +U+62E7(0);U+62E7(1,3);U+64F0(1,3) +U+62E8(0);U+62E8(1,3);U+64A5(1,3) +U+62E9(0);U+62E9(1,3);U+629E(4),U+64C7(1,3) +U+62EB(0);U+62EB(3); +U+62EC(0);U+62EC(5); +U+62ED(0);U+62ED(5); +U+62EE(0);U+62EE(5); +U+62EF(0);U+62EF(5); +U+62F0(0);U+62F0(0); +U+62F1(0);U+62F1(5); +U+62F2(0);U+62F2(0); +U+62F3(0);U+62F3(5); +U+62F4(0);U+62F4(5); +U+62F5(0);U+62F5(0); +U+62F6(0);U+62F6(5); +U+62F7(0);U+62F7(5); +U+62F8(0);U+62F8(3); +U+62F9(0);U+62F9(3); +U+62FA(0);U+62FA(0); +U+62FB(0);U+8C57(3);U+8C57(3) +U+62FC(0);U+62FC(5); +U+62FD(0);U+62FD(5);U+6359(4) +U+62FE(0);U+62FE(5); +U+62FF(0);U+62FF(5);U+62CF(2,3) +U+6300(0);U+6300(0); +U+6301(0);U+6301(5); + +U+6302(0);U+6302(5);U+639B(2,3),U+7F63(4) +U+6303(0);U+6303(3); +U+6304(0);U+6304(0); +U+6305(0);U+6306(3,4);U+6306(3,4) +U+6306(0);U+6306(4);U+6305(3,4) +U+6307(0);U+6307(5); +U+6308(0);U+6308(5); +U+6309(0);U+6309(5); +U+630B(0);U+630B(0); +U+630C(0);U+630C(0); +U+630D(0);U+6821(3);U+6821(3) +U+630E(0);U+630E(5); +U+630F(0);U+630F(0); +U+6310(0);U+6310(0); +U+6311(0);U+6311(5); +U+6312(0);U+6312(0); +U+6313(0);U+6313(0); +U+6314(0);U+6314(0); +U+6315(0);U+6444(3);U+6444(3),U+651D(1,3) +U+6316(0);U+6316(5);U+7A75(3) +U+6318(0);U+6318(0); +U+6319(0);U+4E3E(4);U+4E3E(4),U+8209(4),U+64E7(4) +U+631A(0);U+631A(1,3);U+646F(1,3) +U+631B(0);U+631B(1,3);U+6523(1,3) +U+631C(0);U+631C(1,3);U+6397(1,3) +U+631D(0);U+631D(1,3);U+64BE(1,3) +U+631E(0);U+631E(1,3);U+64BB(1,3) +U+631F(0);U+631F(1,3);U+633E(1,3) +U+6320(0);U+6320(1,3);U+6493(1,3) +U+6321(0);U+6321(1,3);U+64CB(1,3) +U+6322(0);U+6322(1,3);U+649F(1,3),U+8B51(4) +U+6323(0);U+6323(4);U+6399(4) +U+6324(0);U+6324(1,3);U+64E0(1,3) +U+6325(0);U+6325(1,3);U+63EE(1,3) +U+6326(0);U+6326(1,3);U+648F(1,3) +U+6327(0);U+6327(0); +U+6328(0);U+6328(5); +U+6329(0);U+635D(7);U+635D(7) +U+632A(0);U+632A(5); +U+632B(0);U+632B(5); +U+632C(0);U+632C(0); +U+632D(0);U+632D(0); +U+632E(0);U+632E(0); +U+632F(0);U+632F(5); +U+6330(0);U+6330(0); +U+6332(0);U+6332(5); +U+6333(0);U+647C(3);U+647C(3) +U+6334(0);U+6334(0); +U+6336(0);U+6336(3); +U+6338(0);U+6338(0); +U+6339(0);U+6339(5); +U+633A(0);U+633A(5); +U+633B(0);U+633B(0); +U+633C(0);U+633C(0); +U+633D(0);U+633D(5);U+8F13(2,3) +U+633E(0);U+631F(1,3);U+631F(1,3) +U+6340(0);U+6340(0); +U+6341(0);U+6405(3);U+6405(3),U+64B9(3,4),U+652A(1,3) +U+6342(0);U+6342(5);U+6440(3) +U+6343(0);U+6343(5); +U+6344(0);U+6344(0); +U+6345(0);U+6345(5); +U+6346(0);U+6346(5);U+7D91(2,3) + +U+6347(0);U+6347(0); +U+6348(0);U+6445(3);U+6445(3),U+6504(1,3) +U+6349(0);U+6349(5); +U+634A(0);U+634A(3); +U+634B(0);U+634B(5); +U+634C(0);U+634C(5);U+516B(3) +U+634D(0);U+634D(5);U+625E(2,3),U+64C0(8,9) +U+634E(0);U+634E(5); +U+634F(0);U+634F(5); +U+6350(0);U+6350(5); +U+6351(0);U+6351(0); +U+6352(0);U+6352(0); +U+6353(0);U+6353(0); +U+6354(0);U+6354(3); +U+6355(0);U+6355(5); +U+6356(0);U+6356(0); +U+6357(0);U+6357(0); +U+6358(0);U+6358(0); +U+6359(0);U+62FD(4);U+62FD(4) +U+635A(0);U+635A(0); +U+635C(0);U+641C(4);U+641C(4),U+9A2A(3,4) +U+635D(0);U+635D(0);U+6329(7) +U+635E(0);U+635E(1,3);U+6488(1,3) +U+635F(0);U+635F(1,3);U+640D(1,3) +U+6360(0);U+6360(0); +U+6361(0);U+6361(1,3);U+64BF(1,3) +U+6362(0);U+6362(4);U+63DB(4) +U+6363(0);U+6363(1,3);U+6417(1,3),U+64E3(4) +U+6364(0);U+6364(0); +U+6365(0);U+6365(0); +U+6366(0);U+6366(4); +U+6367(0);U+6367(5); +U+6368(0);U+820D(1,3);U+820D(1,3),U+820E(1,3,4) +U+6369(0);U+6369(5); +U+636A(0);U+636A(0); +U+636B(0);U+626A(1,3);U+626A(1,3) +U+636C(0);U+636C(0); +U+636D(0);U+636D(5); +U+636E(0);U+636E(1,3);U+62E0(3),U+64DA(1,3) +U+636F(0);U+636F(0); +U+6370(0);U+6370(3); +U+6371(0);U+6371(5); +U+6372(0);U+5377(1,3);U+5377(1,3),U+5DFB(1,3,4) +U+6373(0);U+6373(0); +U+6374(0);U+603B(4);U+603B(4),U+7E3D(4),U+6403(3,4),U+6460(3,4),U+7DCF(3,4),U+7E02(4) + +U+6375(0);U+6375(0); +U+6376(0);U+6376(5);U+6425(2) +U+6377(0);U+6377(5); +U+6378(0);U+6378(0); +U+6379(0);U+6379(0); +U+637A(0);U+637A(5);U+933C(4) +U+637B(0);U+637B(5);U+649A(4) +U+637C(0);U+637C(3); +U+637D(0);U+637D(0); +U+637E(0);U+637E(0); +U+6380(0);U+6380(5); +U+6381(0);U+6381(4); +U+6382(0);U+6382(5); +U+6383(0);U+626B(1,3);U+626B(1,3) +U+6384(0);U+62A1(1,3);U+62A1(1,3) +U+6385(0);U+6385(0); +U+6386(0);U+39CF(1,3);U+39CF(1,3) + +U+6387(0);U+6387(5); +U+6388(0);U+6388(5); +U+6389(0);U+6389(5); +U+638A(0);U+638A(5); +U+638C(0);U+638C(5); +U+638D(0);U+638D(0); +U+638E(0);U+638E(5); +U+638F(0);U+638F(5);U+642F(2,3) +U+6390(0);U+6390(5); +U+6391(0);U+6391(0); +U+6392(0);U+6392(5); +U+6394(0);U+6394(0); +U+6395(0);U+6395(3); +U+6396(0);U+6396(5); +U+6397(0);U+631C(1,3);U+631C(1,3) +U+6398(0);U+6398(5);U+6485(3) +U+6399(0);U+6323(4);U+6323(4) +U+639A(0);U+639A(0); +U+639B(0);U+6302(2,3);U+6302(2,3),U+7F63(2,3,4) +U+639C(0);U+639C(0); +U+639D(0);U+639D(0); +U+639E(0);U+639E(0); +U+639F(0);U+639F(0); +U+63A0(0);U+63A0(5); +U+63A1(0);U+91C7(2,3);U+91C7(2,3) +U+63A2(0);U+63A2(5); +U+63A3(0);U+63A3(5); +U+63A4(0);U+63A4(0); +U+63A5(0);U+63A5(5); +U+63A6(0);U+63A6(0); +U+63A7(0);U+63A7(5); +U+63A8(0);U+63A8(5); +U+63A9(0);U+63A9(5); +U+63AA(0);U+63AA(5); +U+63AB(0);U+63AB(3); +U+63AC(0);U+63AC(5);U+530A(3) +U+63AD(0);U+63AD(5); +U+63AE(0);U+63AE(5); +U+63AF(0);U+63AF(0); +U+63B0(0);U+63B0(5); +U+63B1(0);U+63B1(0); +U+63B2(0);U+63ED(4);U+63ED(4) +U+63B3(0);U+63B3(1,3);U+64C4(1,3) +U+63B4(0);U+63B4(1,3);U+6451(1,3) +U+63B5(0);U+63B5(0); +U+63B6(0);U+63B6(0); +U+63B7(0);U+63B7(1,3);U+64F2(1,3) +U+63B8(0);U+63B8(1,3);U+64A3(1,3) +U+63B9(0);U+63B9(4); +U+63BA(0);U+63BA(1,3);U+647B(1,3) +U+63BC(0);U+63BC(1,3);U+645C(1,3) +U+63BD(0);U+78B0(2);U+78B0(2),U+8E2B(2,3) +U+63BE(0);U+63BE(5); +U+63BF(0);U+63BF(0); +U+63C0(0);U+62E3(1,3);U+62E3(1,3) +U+63C1(0);U+63C1(0); +U+63C2(0);U+63C2(0); +U+63C3(0);U+63C3(0); +U+63C4(0);U+63C4(5); +U+63C5(0);U+7814(3);U+7814(3) +U+63C6(0);U+63C6(5);U+6951(3) +U+63C7(0);U+63C7(0); +U+63C8(0);U+63C8(0); + +U+63C9(0);U+63C9(5); +U+63CA(0);U+63CA(3); +U+63CB(0);U+63CB(0); +U+63CC(0);U+63CC(0); +U+63CD(0);U+63CD(5); +U+63CE(0);U+63CE(5); +U+63CF(0);U+63CF(5); +U+63D0(0);U+63D0(5); +U+63D2(0);U+63D2(5);U+63F7(2) +U+63D3(0);U+63D3(0); +U+63D4(0);U+63D4(3); +U+63D5(0);U+63D5(0); +U+63D6(0);U+63D6(5); +U+63D7(0);U+63D7(0); +U+63D8(0);U+63D8(0); +U+63D9(0);U+63D9(0); +U+63DA(0);U+626C(1,3);U+626C(1,3),U+98BA(2),U+98CF(1,3,4) +U+63DB(0);U+6362(4);U+6362(4) +U+63DC(0);U+63DC(3); +U+63DD(0);U+63DD(0); +U+63DE(0);U+63DE(5); +U+63DF(0);U+63DF(0); +U+63E0(0);U+63E0(5); +U+63E1(0);U+63E1(5); +U+63E2(0);U+63E2(3); +U+63E3(0);U+63E3(5); +U+63E4(0);U+63E4(0); +U+63E5(0);U+63E5(0); +U+63E6(0);U+63E6(0); +U+63E7(0);U+63E7(0); +U+63E8(0);U+63E8(0); +U+63E9(0);U+63E9(5); +U+63EA(0);U+63EA(5);U+63EB(2,3) +U+63EB(0);U+63EA(2,3);U+63EA(2,3) +U+63EC(0);U+63EC(0); +U+63ED(0);U+63ED(5);U+63B2(4) +U+63EE(0);U+6325(1,3);U+6325(1,3) +U+63EF(0);U+6404(4);U+6404(4) +U+63F0(0);U+63F0(0); +U+63F1(0);U+63F1(3); +U+63F2(0);U+63F2(5); +U+63F3(0);U+63F3(0); +U+63F4(0);U+63F4(5);U+610B(3) +U+63F5(0);U+63F5(0); +U+63F6(0);U+63F6(5); +U+63F7(0);U+63D2(2);U+63D2(2) +U+63F8(0);U+63F8(5); +U+63F9(0);U+80CC(2,3);U+80CC(2,3),U+505D(0,2,3) +U+63FA(0);U+6447(4);U+6416(8,9),U+6447(4) +U+63FB(0);U+63FB(0); +U+63FC(0);U+63FC(0); +U+63FD(0);U+63FD(1,3);U+652C(1,3) +U+63FE(0);U+63FE(0);U+6435(4) +U+63FF(0);U+63FF(1,3);U+64B3(1,3) +U+6400(0);U+6400(1,3);U+6519(1,3) +U+6401(0);U+6401(1,3);U+64F1(1,3) +U+6402(0);U+6402(1,3);U+645F(1,3) +U+6403(0);U+603B(3);U+603B(3),U+7E3D(3),U+6374(3,4),U+6460(3),U+7DCF(3),U+7E02(3,4) +U+6404(0);U+6404(4);U+63EF(4) +U+6405(0);U+6405(1,3);U+6341(3),U+64B9(4),U+652A(1,3) +U+6406(0);U+6784(4);U+6784(4),U+69CB(2,3),U+5193(0,3,4) +U+6408(0);U+6408(0); +U+6409(0);U+69B7(2,3);U+69B7(2,3) + +U+640A(0);U+640A(0); +U+640B(0);U+640B(5);U+6260(3) +U+640C(0);U+640C(5); +U+640D(0);U+635F(1,3);U+635F(1,3) +U+640E(0);U+640E(0); +U+640F(0);U+640F(5); +U+6410(0);U+6410(5); +U+6411(0);U+6411(0); +U+6412(0);U+6412(4); +U+6413(0);U+6413(5); +U+6414(0);U+6414(5); +U+6415(0);U+6415(0); +U+6416(0);U+6447(4);U+63FA(8,9),U+6447(4) +U+6417(0);U+6363(1,3);U+6363(1,3),U+64E3(2,3) +U+6418(0);U+652F(3);U+652F(3) +U+6419(0);U+6419(0); +U+641A(0);U+641A(4); +U+641B(0);U+641B(5); +U+641C(0);U+641C(5);U+635C(4),U+9A2A(3) +U+641D(0);U+641D(0); +U+641E(0);U+641E(5); +U+641F(0);U+641F(0); +U+6420(0);U+6420(5); +U+6421(0);U+6421(5); +U+6422(0);U+6422(0); +U+6423(0);U+6423(0); +U+6424(0);U+627C(2,3);U+627C(2,3),U+6439(2,3) +U+6425(0);U+6425(3);U+6376(2) +U+6426(0);U+6426(5); +U+6427(0);U+6247(4);U+6247(4) +U+6428(0);U+6428(3);U+642D(3),U+6498(3) +U+6429(0);U+6429(0); +U+642A(0);U+642A(5); +U+642B(0);U+642B(0); +U+642C(0);U+642C(5); +U+642D(0);U+642D(5);U+6428(3),U+6498(3) +U+642E(0);U+642E(0); +U+642F(0);U+642F(0);U+638F(2,3) +U+6430(0);U+6430(3); +U+6431(0);U+6431(0); +U+6432(0);U+6432(3); +U+6433(0);U+6433(3); +U+6434(0);U+6434(5); +U+6435(0);U+63FE(4);U+63FE(4) +U+6436(0);U+62A2(1,3);U+62A2(1,3) +U+6437(0);U+6437(0); +U+6438(0);U+6438(0); +U+6439(0);U+627C(3);U+627C(3),U+6424(2,3) +U+643A(0);U+643A(5);U+651C(2,3) +U+643D(0);U+643D(5); +U+643E(0);U+69A8(2,3);U+69A8(2,3),U+91A1(2,3) +U+643F(0);U+643F(5); +U+6440(0);U+6342(3);U+6342(3) +U+6441(0);U+6441(5); +U+6443(0);U+625B(2,3);U+625B(2,3) +U+6444(0);U+6444(1,3);U+6315(3),U+651D(1,3) +U+6445(0);U+6445(1,3);U+6348(3),U+6504(1,3) +U+6446(0);U+6446(1,3);U+64FA(1,3),U+896C(1,3) +U+6447(0);U+6447(5);U+63FA(4),U+6416(4) +U+6448(0);U+6448(1,3);U+64EF(1,3) +U+644A(0);U+644A(1,3);U+6524(1,3) +U+644B(0);U+644B(0); +U+644C(0);U+644C(0); + +U+644D(0);U+7F29(4);U+7F29(4),U+7E2E(1,3,4) +U+644E(0);U+644E(0); +U+644F(0);U+644F(0); +U+6450(0);U+6450(0); +U+6451(0);U+63B4(1,3);U+63B4(1,3) +U+6452(0);U+6452(5); +U+6453(0);U+6453(3); +U+6454(0);U+6454(5); +U+6455(0);U+6455(3); +U+6456(0);U+6456(0); +U+6457(0);U+6457(0); +U+6458(0);U+6458(5); +U+6459(0);U+6459(0); +U+645B(0);U+645B(3); +U+645C(0);U+63BC(1,3);U+63BC(1,3) +U+645D(0);U+645D(0); +U+645E(0);U+645E(5); +U+645F(0);U+6402(1,3);U+6402(1,3) +U+6460(0);U+603B(3);U+603B(3),U+6374(3,4),U+6403(3),U+7DCF(3),U+7E02(3,4),U+7E3D(1,3) + +U+6461(0);U+6461(0); +U+6462(0);U+6462(0); +U+6463(0);U+6463(3); +U+6464(0);U+6464(0); +U+6465(0);U+6465(0); +U+6466(0);U+6466(0); +U+6467(0);U+6467(5); +U+6468(0);U+6468(0); +U+6469(0);U+6469(5); +U+646A(0);U+646A(0); +U+646B(0);U+646B(0); +U+646C(0);U+646C(0); +U+646D(0);U+646D(5);U+62D3(3) +U+646E(0);U+646E(0); +U+646F(0);U+631A(1,3);U+631A(1,3) +U+6470(0);U+6470(0); +U+6471(0);U+6471(0); +U+6472(0);U+6472(0); +U+6473(0);U+62A0(1,3);U+62A0(1,3) +U+6474(0);U+6474(3); +U+6475(0);U+6475(0); +U+6476(0);U+629F(1,3);U+629F(1,3) +U+6477(0);U+6477(0); +U+6478(0);U+6478(5); +U+6479(0);U+6479(5); +U+647A(0);U+647A(0),U+6298(1,3);U+6298(1,3) +U+647B(0);U+63BA(1,3);U+63BA(1,3) +U+647C(0);U+647C(3);U+6333(3) +U+647D(0);U+647D(0); +U+647F(0);U+647F(0); +U+6480(0);U+6480(0); +U+6481(0);U+6481(0); +U+6482(0);U+6482(5); +U+6483(0);U+51FB(4);U+51FB(4),U+64CA(4) +U+6484(0);U+6484(1,3);U+6516(1,3) +U+6485(0);U+6485(5);U+6398(3) +U+6487(0);U+6487(5); +U+6488(0);U+635E(1,3);U+635E(1,3) +U+6489(0);U+6489(0); +U+648A(0);U+648A(3); +U+648B(0);U+648B(0); +U+648C(0);U+648C(0); +U+648D(0);U+648D(3); + +U+648E(0);U+648E(3); +U+648F(0);U+6326(1,3);U+6326(1,3) +U+6490(0);U+6491(2,3);U+6491(2,3),U+725A(2,3,4) +U+6491(0);U+6491(5);U+6490(2,3),U+725A(4) +U+6492(0);U+6492(5); +U+6493(0);U+6320(1,3);U+6320(1,3) +U+6494(0);U+6494(0); +U+6495(0);U+6495(5); +U+6496(0);U+6496(5); +U+6497(0);U+6497(3); +U+6498(0);U+642D(3);U+642D(3),U+6428(3) +U+6499(0);U+6499(5); +U+649A(0);U+649A(3);U+637B(4) +U+649B(0);U+649B(0); +U+649C(0);U+649C(0); +U+649D(0);U+649D(0); +U+649E(0);U+649E(5); +U+649F(0);U+6322(1,3);U+6322(1,3),U+8B51(1,3,4) +U+64A0(0);U+64A0(0); +U+64A2(0);U+64A2(0); +U+64A3(0);U+63B8(1,3);U+63B8(1,3) +U+64A4(0);U+64A4(5); +U+64A5(0);U+62E8(1,3);U+62E8(1,3) +U+64A6(0);U+626F(2,3);U+626F(2,3) +U+64A7(0);U+64A7(0); +U+64A8(0);U+64A8(0); +U+64A9(0);U+64A9(5); +U+64AA(0);U+64AA(0); +U+64AB(0);U+629A(1,3);U+629A(1,3),U+62CA(3) +U+64AC(0);U+64AC(5); +U+64AD(0);U+64AD(5); +U+64AE(0);U+64AE(5); +U+64B0(0);U+64B0(5);U+8B54(2,3) +U+64B1(0);U+692D(4);U+692D(4),U+6955(3,4),U+6A62(1,3,4) +U+64B2(0);U+6251(1,3);U+6251(1,3),U+6534(1,3) +U+64B3(0);U+63FF(1,3);U+63FF(1,3) +U+64B4(0);U+64B4(0); +U+64B5(0);U+64B5(1,3);U+6506(1,3) +U+64B7(0);U+64B7(1,3);U+64F7(1,3) +U+64B8(0);U+64B8(4);U+64FC(4) +U+64B9(0);U+6405(4);U+6405(4),U+652A(4),U+6341(0,3,4) +U+64BA(0);U+64BA(1,3);U+651B(1,3) +U+64BB(0);U+631E(1,3);U+631E(1,3) +U+64BC(0);U+64BC(5); +U+64BD(0);U+64BD(0); +U+64BE(0);U+631D(1,3);U+631D(1,3) +U+64BF(0);U+6361(1,3);U+6361(1,3) +U+64C0(0);U+64C0(5);U+625E(3),U+634D(8,9) +U+64C1(0);U+62E5(1,3);U+62E5(1,3) +U+64C2(0);U+64C2(5); +U+64C3(0);U+64C3(3); +U+64C4(0);U+63B3(1,3);U+63B3(1,3) +U+64C5(0);U+64C5(5); +U+64C6(0);U+64C6(3); +U+64C7(0);U+62E9(1,3);U+629E(8,9),U+62E9(1,3) +U+64C9(0);U+64C9(3); +U+64CA(0);U+51FB(1,3);U+51FB(1,3),U+6483(4) +U+64CB(0);U+6321(1,3);U+6321(1,3) +U+64CC(0);U+64CC(0); +U+64CD(0);U+64CD(5); +U+64CE(0);U+64CE(5); +U+64CF(0);U+64CF(0); +U+64D0(0);U+64D0(5); + +U+64D1(0);U+64D1(0); +U+64D2(0);U+64D2(5); +U+64D3(0);U+39DF(1,3);U+39DF(1,3) +U+64D4(0);U+62C5(1,3);U+62C5(1,3) +U+64D6(0);U+64D6(0); +U+64D7(0);U+64D7(5); +U+64D8(0);U+64D8(5); +U+64D9(0);U+64D9(0); +U+64DA(0);U+636E(1,3);U+62E0(3),U+636E(1,3) +U+64DB(0);U+64DB(3); +U+64DC(0);U+64DC(0); +U+64DD(0);U+64DD(0); +U+64DE(0);U+64DE(1,3);U+64FB(1,3) +U+64DF(0);U+64DF(0); +U+64E0(0);U+6324(1,3);U+6324(1,3) +U+64E2(0);U+64E2(5); +U+64E3(0);U+64E3(3);U+6363(4),U+6417(2,3) +U+64E4(0);U+64E4(5); +U+64E6(0);U+64E6(5); +U+64E7(0);U+4E3E(4);U+4E3E(4),U+8209(2,3),U+6319(4) +U+64E8(0);U+64E8(0); +U+64E9(0);U+64E9(0); +U+64EA(0);U+64EA(3);U+64EB(3) +U+64EB(0);U+64EA(3);U+64EA(3) +U+64EC(0);U+62DF(1,3);U+5117(2),U+62DF(1,3) +U+64ED(0);U+64ED(0); +U+64EF(0);U+6448(1,3);U+6448(1,3) +U+64F0(0);U+62E7(1,3);U+62E7(1,3) +U+64F1(0);U+6401(1,3);U+6401(1,3) +U+64F2(0);U+63B7(1,3);U+63B7(1,3) +U+64F3(0);U+64F3(0); +U+64F4(0);U+6269(1,3);U+6269(1,3),U+62E1(4) +U+64F6(0);U+64F6(0); +U+64F7(0);U+64B7(1,3);U+64B7(1,3) +U+64F8(0);U+64F8(0); +U+64FA(0);U+6446(1,3);U+6446(1,3),U+896C(4) +U+64FB(0);U+64DE(1,3);U+64DE(1,3) +U+64FC(0);U+64B8(4);U+64B8(4) +U+64FD(0);U+64FD(3); +U+64FE(0);U+6270(1,3);U+6270(1,3) +U+64FF(0);U+64FF(3); +U+6500(0);U+6500(5); +U+6501(0);U+6501(0); +U+6503(0);U+6503(3); +U+6504(0);U+6445(1,3);U+6445(1,3),U+6348(0,1,3) +U+6505(0);U+6512(3);U+6512(3),U+6522(3) +U+6506(0);U+64B5(1,3);U+64B5(1,3) +U+6507(0);U+6507(3); +U+6508(0);U+6508(4); +U+6509(0);U+6509(5); +U+650B(0);U+650B(3); +U+650C(0);U+650C(0); +U+650D(0);U+650D(0); +U+650E(0);U+650E(0); +U+650F(0);U+62E2(1,3);U+62E2(1,3) +U+6510(0);U+6510(3); +U+6511(0);U+6511(0); +U+6512(0);U+6512(1,3);U+6505(3),U+6522(1,3) +U+6513(0);U+6513(0); +U+6514(0);U+62E6(1,3);U+62E6(1,3) +U+6515(0);U+6515(3); +U+6516(0);U+6484(1,3);U+6484(1,3) +U+6517(0);U+6517(0); + +U+6518(0);U+6518(5); +U+6519(0);U+6400(1,3);U+6400(1,3) +U+651A(0);U+651A(0); +U+651B(0);U+64BA(1,3);U+64BA(1,3) +U+651C(0);U+643A(2,3);U+643A(2,3) +U+651D(0);U+6444(1,3);U+6444(1,3),U+6315(0,1,3) +U+651E(0);U+651E(3); +U+6520(0);U+6520(0); +U+6521(0);U+6521(0); +U+6522(0);U+6512(1,3);U+6505(3),U+6512(1,3) +U+6523(0);U+631B(1,3);U+631B(1,3) +U+6524(0);U+644A(1,3);U+644A(1,3) +U+6525(0);U+6525(5); +U+6526(0);U+6526(0); +U+6527(0);U+6527(0); +U+6529(0);U+6529(0); +U+652A(0);U+6405(1,3);U+6405(1,3),U+64B9(4),U+6341(0,1,3) +U+652B(0);U+652B(5); +U+652C(0);U+63FD(1,3);U+63FD(1,3) +U+652D(0);U+652D(0); +U+652E(0);U+652E(5); +U+652F(0);U+652F(5);U+6418(3) +U+6530(0);U+6530(0); +U+6531(0);U+6531(3); +U+6532(0);U+6532(3); +U+6533(0);U+6533(0); +U+6534(0);U+6534(5);U+6251(3),U+64B2(1,3) +U+6535(0);U+6535(5); +U+6536(0);U+6536(5);U+53CE(3) +U+6537(0);U+8003(2,3);U+8003(2,3) +U+6538(0);U+6538(5);U+900C(3) +U+6539(0);U+6539(5); +U+653A(0);U+653A(0); +U+653B(0);U+653B(5); +U+653C(0);U+653C(0); +U+653D(0);U+653D(3); +U+653E(0);U+653E(5); +U+653F(0);U+653F(5); +U+6541(0);U+6541(0); +U+6543(0);U+6543(0); +U+6544(0);U+6544(0); +U+6545(0);U+6545(5); +U+6546(0);U+5408(3);U+5408(3),U+95A4(1,3) +U+6547(0);U+6547(0); +U+6548(0);U+6548(5);U+4FF2(2,3),U+509A(2,3),U+52B9(2,3) +U+6549(0);U+6549(5); +U+654A(0);U+654A(0); +U+654B(0);U+654B(0); +U+654C(0);U+654C(1,3);U+6575(1,3) +U+654D(0);U+53D9(2,3);U+53D9(2,3),U+6558(3) +U+654E(0);U+6559(3);U+6559(3) +U+654F(0);U+654F(5); +U+6550(0);U+6550(0); +U+6551(0);U+6551(5); +U+6552(0);U+6552(0); +U+6553(0);U+593A(3);U+593A(3),U+596A(1,3) +U+6554(0);U+6554(3); +U+6555(0);U+6555(5); +U+6556(0);U+6556(5);U+969E(3) +U+6557(0);U+8D25(1,3);U+8D25(1,3) +U+6558(0);U+53D9(2);U+53D9(2),U+654D(3) +U+6559(0);U+6559(5);U+654E(3) +U+655B(0);U+655B(1,3);U+6582(1,3),U+6B5B(3) + +U+655C(0);U+655C(3); +U+655D(0);U+655D(5); +U+655E(0);U+655E(5); +U+6560(0);U+6560(4);U+656A(4) +U+6561(0);U+6561(0); +U+6562(0);U+6562(5); +U+6563(0);U+6563(5); +U+6564(0);U+6564(0); +U+6565(0);U+6565(0); +U+6566(0);U+6566(5); +U+6567(0);U+6567(3); +U+6568(0);U+6568(0); +U+6569(0);U+6569(4);U+6585(4),U+6586(4) +U+656A(0);U+6560(4);U+6560(4) +U+656B(0);U+656B(5); +U+656C(0);U+656C(5); +U+656E(0);U+656E(0); +U+656F(0);U+610D(4);U+610D(4) +U+6570(0);U+6570(1,3);U+6578(1,3) +U+6571(0);U+6571(0); +U+6572(0);U+6572(5);U+6BC3(3) +U+6573(0);U+6573(0); +U+6574(0);U+6574(5); +U+6575(0);U+654C(1,3);U+654C(1,3) +U+6576(0);U+9648(3);U+9648(3),U+9673(1,3) +U+6577(0);U+6577(5);U+5C03(3) +U+6578(0);U+6570(1,3);U+6570(1,3) +U+6579(0);U+6579(0); +U+657A(0);U+9A71(4);U+9A71(4),U+99C6(1,4),U+99C8(4),U+9A45(1,3,4) +U+657B(0);U+5910(4);U+5910(4) +U+657C(0);U+657C(0); +U+657E(0);U+657E(0); +U+657F(0);U+657F(0); +U+6580(0);U+6580(3); +U+6581(0);U+6581(3); +U+6582(0);U+655B(1,3);U+655B(1,3),U+6B5B(2,3) +U+6583(0);U+6BD9(1,3);U+6BD9(1,3) +U+6584(0);U+6584(3); +U+6585(0);U+6569(4);U+6569(4),U+6586(3,4) +U+6586(0);U+6569(4);U+6569(4),U+6585(3,4) +U+6587(0);U+6587(5); +U+6588(0);U+5B66(3);U+5B66(3),U+5B78(3) +U+6589(0);U+9F50(3);U+9F4A(3),U+9F50(3),U+4E9D(0,3) +U+658B(0);U+658B(1,3);U+658E(4),U+9F4B(1,3) +U+658C(0);U+658C(5); +U+658D(0);U+89C9(3);U+89BA(3),U+89C9(3),U+899A(3,4) +U+658E(0);U+658B(4);U+658B(4),U+9F4B(4) +U+658F(0);U+658F(0); +U+6590(0);U+6590(5); +U+6591(0);U+6591(5); +U+6592(0);U+6592(3); +U+6593(0);U+6593(1,3);U+6595(1,3) +U+6594(0);U+5EBE(3);U+5EBE(3),U+659E(3) +U+6595(0);U+6593(1,3);U+6593(1,3) +U+6596(0);U+4EB9(4);U+4EB9(4) +U+6597(0);U+6597(1,3);U+95D8(4),U+9B25(1,3),U+9B26(4),U+9B2A(4),U+9B2C(3),U+9B2D(4) +U+6598(0);U+6598(0); +U+6599(0);U+6599(5); +U+659B(0);U+659B(5); +U+659C(0);U+659C(5); +U+659D(0);U+659D(3); +U+659E(0);U+5EBE(3);U+5EBE(3),U+6594(3) +U+659F(0);U+659F(5); + +U+65A0(0);U+65A0(0); +U+65A1(0);U+65A1(5); +U+65A2(0);U+65A2(0); +U+65A3(0);U+65A3(0); +U+65A4(0);U+65A4(5);U+89D4(2),U+7B4B(2,3) +U+65A5(0);U+65A5(5); +U+65A6(0);U+65A6(0); +U+65A7(0);U+65A7(5); +U+65A8(0);U+65A8(0); +U+65A9(0);U+65A9(1,3);U+65AC(1,3) +U+65AA(0);U+65AA(0); +U+65AB(0);U+65AB(5); +U+65AC(0);U+65A9(1,3);U+65A9(1,3) +U+65AD(0);U+65AD(1,3);U+65B7(1,3) +U+65AE(0);U+65AE(3); +U+65AF(0);U+65AF(5); +U+65B0(0);U+65B0(5); +U+65B1(0);U+65B1(0); +U+65B2(0);U+65B2(4); +U+65B3(0);U+65B3(0); +U+65B4(0);U+65B4(0); +U+65B6(0);U+65B6(0); +U+65B7(0);U+65AD(1,3);U+65AD(1,3) +U+65B8(0);U+65B8(3); +U+65B9(0);U+65B9(5); +U+65BA(0);U+65BA(0); +U+65BB(0);U+65BB(3); +U+65BC(0);U+65BC(5);U+4E8E(4),U+6275(3) +U+65BD(0);U+65BD(5); +U+65BF(0);U+65BF(0); +U+65C0(0);U+65C0(0); +U+65C1(0);U+65C1(5); +U+65C2(0);U+65D7(2);U+65D7(2) +U+65C3(0);U+65C3(5); +U+65C4(0);U+65C4(5); +U+65C5(0);U+65C5(5);U+7963(3) +U+65C6(0);U+65C6(5); +U+65C7(0);U+65C7(0); +U+65CA(0);U+65CA(0); +U+65CB(0);U+65CB(1,3);U+93C7(1,3,4),U+955F(1,3,4) +U+65CC(0);U+65CC(5);U+65CD(3) +U+65CD(0);U+65CC(3);U+65CC(3) +U+65CE(0);U+65CE(5); +U+65CF(0);U+65CF(5); +U+65D0(0);U+65D0(0); +U+65D2(0);U+65D2(5); +U+65D3(0);U+65D3(0); +U+65D4(0);U+65D4(0); +U+65D5(0);U+65D5(0); +U+65D6(0);U+65D6(5); +U+65D7(0);U+65D7(5);U+65C2(2) +U+65DA(0);U+98D8(3);U+98D8(3),U+98C3(3,4),U+98C4(1,3) +U+65DB(0);U+65DB(4); +U+65DD(0);U+65DD(0); +U+65DE(0);U+65DE(0); +U+65DF(0);U+65DF(0); +U+65E0(0);U+65E0(1,3);U+7121(1,3) +U+65E1(0);U+65E1(0); +U+65E2(0);U+65E2(5);U+65E3(3) +U+65E3(0);U+65E2(3);U+65E2(3) +U+65E5(0);U+65E5(5); +U+65E6(0);U+65E6(5); +U+65E7(0);U+65E7(1,3);U+820A(1,3) + +U+65E8(0);U+65E8(5);U+6049(4) +U+65E9(0);U+65E9(5); +U+65EB(0);U+65EB(0); +U+65EC(0);U+65EC(5); +U+65ED(0);U+65ED(5);U+65EE(3) +U+65EE(0);U+65EE(5);U+65ED(3) +U+65EF(0);U+65EF(5); +U+65F0(0);U+65F0(5); +U+65F1(0);U+65F1(5); +U+65F2(0);U+65F2(0); +U+65F3(0);U+65F3(0); +U+65F4(0);U+65F4(3); +U+65F5(0);U+65F5(0); +U+65F6(0);U+65F6(1,3);U+6642(1,3) +U+65F7(0);U+65F7(1,3);U+66E0(1,3) +U+65F8(0);U+65F8(1,3);U+6698(1,3) +U+65FA(0);U+65FA(5); +U+65FB(0);U+65FB(3); +U+65FC(0);U+65FC(0); +U+65FD(0);U+65FD(0); +U+6600(0);U+6600(5); +U+6601(0);U+6601(0); +U+6602(0);U+6602(5); +U+6603(0);U+6603(5); +U+6604(0);U+53CD(4);U+53CD(4) +U+6605(0);U+6605(0); +U+6606(0);U+6606(5);U+5D10(2),U+5D11(2),U+665C(3) +U+6607(0);U+5347(2,3);U+5347(2,3),U+965E(2,3) +U+6608(0);U+6608(0); +U+6609(0);U+6609(3); +U+660A(0);U+660A(5);U+6626(3) +U+660B(0);U+660B(0); +U+660C(0);U+660C(5); +U+660D(0);U+660D(0); +U+660E(0);U+660E(5); +U+660F(0);U+660F(5); +U+6610(0);U+6610(0); +U+6611(0);U+6611(0); +U+6612(0);U+6612(3); +U+6613(0);U+6613(5); +U+6614(0);U+6614(5); +U+6615(0);U+6615(5); +U+6616(0);U+6616(0); +U+6618(0);U+6618(0); +U+6619(0);U+6619(1,3);U+66C7(1,3) +U+661A(0);U+614E(2,3);U+614E(2,3),U+613C(0,2,3,4),U+7718(2,3,4) +U+661B(0);U+661B(0); +U+661C(0);U+9633(3);U+967D(3),U+9633(3) +U+661D(0);U+661D(5); +U+661F(0);U+661F(5); +U+6620(0);U+6620(5);U+668E(2,3) +U+6621(0);U+6621(0); +U+6622(0);U+6622(3); +U+6623(0);U+6623(0); +U+6624(0);U+6624(0); +U+6625(0);U+6625(5);U+8405(3) +U+6626(0);U+660A(3);U+660A(3) +U+6627(0);U+6627(5); +U+6628(0);U+6628(5); +U+6629(0);U+6629(0); +U+662A(0);U+662A(0); +U+662B(0);U+662B(3); +U+662D(0);U+662D(5); + +U+662E(0);U+662E(0); +U+662F(0);U+662F(5);U+6630(2,3) +U+6630(0);U+662F(2,3);U+662F(2,3) +U+6631(0);U+6631(5); +U+6632(0);U+6632(4);U+66CA(4) +U+6633(0);U+6633(0); +U+6634(0);U+6634(5); +U+6635(0);U+6635(5);U+66B1(2,3) +U+6636(0);U+6636(5); +U+6639(0);U+6639(0); +U+663A(0);U+70B3(3);U+70B3(3) +U+663C(0);U+663C(1,3);U+665D(1,3) +U+663D(0);U+663D(1,3);U+66E8(1,3) +U+663E(0);U+663E(1,3);U+9855(4),U+986F(1,3) +U+6640(0);U+6640(0); +U+6641(0);U+6641(5); +U+6642(0);U+65F6(1,3);U+65F6(1,3) +U+6643(0);U+6643(5);U+6644(3) +U+6644(0);U+6643(3);U+6643(3) +U+6645(0);U+6645(0); +U+6646(0);U+6646(0); +U+6647(0);U+6647(0); +U+6649(0);U+664B(2,3);U+664B(2,3) +U+664A(0);U+664A(0); +U+664B(0);U+664B(5);U+6649(2,3) +U+664C(0);U+664C(5); +U+664E(0);U+664E(0); +U+664F(0);U+664F(5); +U+6650(0);U+6650(0); +U+6651(0);U+6651(0); +U+6652(0);U+6652(1,3);U+66EC(1,3) +U+6653(0);U+6653(1,3);U+6681(4),U+66C9(1,3) +U+6654(0);U+6654(1,3);U+66C4(1,3),U+66C5(3) +U+6655(0);U+6655(1,3);U+6688(1,3) +U+6656(0);U+6656(4);U+6689(4) +U+6657(0);U+6657(5); +U+6658(0);U+6658(0); +U+6659(0);U+6659(0); +U+665A(0);U+665A(5);U+6669(4) +U+665B(0);U+665B(0); +U+665C(0);U+6606(3);U+6606(3),U+5D10(0,2,3),U+5D11(2,3) +U+665D(0);U+663C(1,3);U+663C(1,3) +U+665E(0);U+665E(3); +U+665F(0);U+665F(5); +U+6661(0);U+6661(5); +U+6662(0);U+6662(3); +U+6664(0);U+6664(5); +U+6665(0);U+7696(3);U+7696(3) +U+6666(0);U+6666(5); +U+6668(0);U+6668(5); +U+6669(0);U+665A(4);U+665A(4) +U+666A(0);U+666A(0); +U+666B(0);U+666B(0); +U+666C(0);U+666C(0); +U+666D(0);U+666D(0); +U+666E(0);U+666E(5); +U+666F(0);U+666F(5); +U+6670(0);U+6670(5); +U+6671(0);U+6671(0); +U+6672(0);U+6672(0); +U+6673(0);U+6673(0); +U+6674(0);U+6674(5); +U+6675(0);U+6675(0); + +U+6676(0);U+6676(5); +U+6677(0);U+6677(5); +U+6678(0);U+6678(0); +U+6679(0);U+6679(0); +U+667A(0);U+667A(5); +U+667B(0);U+6697(2,3);U+6697(2,3),U+95C7(2,3) +U+667C(0);U+667C(0); +U+667D(0);U+667D(0); +U+667E(0);U+667E(5); +U+667F(0);U+667F(0); +U+6680(0);U+6680(0); +U+6681(0);U+6653(4);U+6653(4),U+66C9(4) +U+6682(0);U+6682(1,3);U+66AB(1,3),U+8E54(4) +U+6683(0);U+6683(0); +U+6684(0);U+6684(5); +U+6685(0);U+6685(0); +U+6686(0);U+6686(0); +U+6687(0);U+6687(5); +U+6688(0);U+6655(1,3);U+6655(1,3) +U+6689(0);U+6656(4);U+6656(4) +U+668A(0);U+668A(0); +U+668B(0);U+668B(3); +U+668C(0);U+668C(5); +U+668D(0);U+668D(0); +U+668E(0);U+6620(2,3);U+6620(2,3) +U+668F(0);U+668F(0); +U+6690(0);U+6690(0); +U+6691(0);U+6691(5); +U+6693(0);U+6693(0); +U+6694(0);U+6694(0); +U+6695(0);U+6695(0); +U+6696(0);U+6696(5);U+7156(2,3) +U+6697(0);U+6697(5);U+667B(2,3),U+95C7(2) +U+6698(0);U+65F8(1,3);U+65F8(1,3) +U+6699(0);U+6699(0); +U+669A(0);U+669A(0); +U+669B(0);U+669B(0); +U+669D(0);U+669D(5); +U+669F(0);U+669F(0); +U+66A0(0);U+7693(2,3);U+7693(2,3),U+769C(2,3) +U+66A1(0);U+66A1(0); +U+66A2(0);U+7545(1,3);U+7545(1,3) +U+66A3(0);U+66A3(0); +U+66A4(0);U+66A4(3); +U+66A5(0);U+66A5(0); +U+66A6(0);U+5386(4);U+5386(4),U+66C6(4),U+53A4(4),U+6B74(2,3,4),U+6B77(1,3,4) +U+66A7(0);U+66A7(1,3);U+66D6(1,3) +U+66A8(0);U+66A8(5);U+66C1(4),U+81EE(4),U+8507(4) +U+66A9(0);U+66A9(0); +U+66AA(0);U+66AA(0); +U+66AB(0);U+6682(1,3);U+6682(1,3),U+8E54(1,3,4) +U+66AE(0);U+66AE(5); +U+66AF(0);U+66AF(0); +U+66B0(0);U+66B0(0); +U+66B1(0);U+6635(2,3);U+6635(2,3) +U+66B2(0);U+66B2(0); +U+66B3(0);U+66B3(0); +U+66B4(0);U+66B4(5);U+8663(3) +U+66B5(0);U+66B5(3); +U+66B6(0);U+66B6(0); +U+66B7(0);U+66B7(0); +U+66B8(0);U+4E86(7);U+4E86(7),U+77AD(1,3,4,7) +U+66B9(0);U+66B9(5); + +U+66BA(0);U+66BA(0); +U+66BB(0);U+66BB(0); +U+66BC(0);U+66BC(0); +U+66BD(0);U+66BD(0); +U+66BE(0);U+66BE(5); +U+66BF(0);U+66BF(0); +U+66C0(0);U+66C0(0); +U+66C1(0);U+66A8(4);U+66A8(4),U+81EE(4),U+8507(4) +U+66C2(0);U+66C2(0); +U+66C3(0);U+66C3(0); +U+66C4(0);U+6654(1,3);U+6654(1,3),U+66C5(3) +U+66C5(0);U+6654(3);U+6654(3),U+66C4(3) +U+66C6(0);U+5386(1,3);U+5386(1,3),U+66A6(4),U+6B77(3,4),U+53A4(1,3,4),U+6B74(1,2,3) +U+66C7(0);U+6619(1,3);U+6619(1,3) +U+66C8(0);U+66C8(3); +U+66C9(0);U+6653(1,3);U+6653(1,3),U+6681(4) +U+66CA(0);U+6632(4);U+6632(4) +U+66CB(0);U+66CB(0); +U+66CC(0);U+7167(3);U+7167(3),U+70A4(2,3) +U+66CD(0);U+66CD(0); +U+66CE(0);U+66CE(0); +U+66CF(0);U+5411(4);U+5411(4),U+56AE(1,3,4) +U+66D1(0);U+66D1(0); +U+66D2(0);U+66D2(4); +U+66D4(0);U+66D4(0); +U+66D5(0);U+66D5(0); +U+66D6(0);U+66A7(1,3);U+66A7(1,3) +U+66D8(0);U+66D8(0); +U+66D9(0);U+66D9(5); +U+66DA(0);U+66DA(0); +U+66DB(0);U+66DB(5); +U+66DC(0);U+66DC(5);U+71FF(3),U+8000(2,3) +U+66DD(0);U+66DD(5); +U+66DE(0);U+66DE(0); +U+66E0(0);U+65F7(1,3);U+65F7(1,3) +U+66E1(0);U+53E0(2);U+53E0(2),U+758A(3),U+8FED(4),U+7589(2) +U+66E2(0);U+66E2(0); +U+66E3(0);U+66E3(0); +U+66E4(0);U+66E4(0); +U+66E5(0);U+66E5(0); +U+66E6(0);U+66E6(5); +U+66E7(0);U+66E7(0); +U+66E8(0);U+663D(1,3);U+663D(1,3) +U+66E9(0);U+66E9(5); +U+66EA(0);U+66EA(0); +U+66EB(0);U+66EB(0); +U+66EC(0);U+6652(1,3);U+6652(1,3) +U+66ED(0);U+66ED(0); +U+66EE(0);U+66EE(0); +U+66F0(0);U+66F0(5); +U+66F1(0);U+66F1(0); +U+66F2(0);U+66F2(1,3,4);U+9EAF(1,3),U+9EB4(4) +U+66F3(0);U+66F3(5);U+66F5(3) +U+66F4(0);U+66F4(5); +U+66F5(0);U+66F3(3);U+66F3(3) +U+66F6(0);U+66F6(0); +U+66F7(0);U+66F7(5); +U+66F8(0);U+4E66(1,3);U+4E66(1,3) +U+66F9(0);U+66F9(5);U+66FA(3) +U+66FA(0);U+66F9(3);U+66F9(3) +U+66FB(0);U+66FB(0); +U+66FC(0);U+66FC(5); +U+66FE(0);U+66FE(5); + +U+66FF(0);U+66FF(5); +U+6700(0);U+6700(5); +U+6701(0);U+6701(0); +U+6703(0);U+4F1A(1,3);U+4F1A(1,3) +U+6704(0);U+6704(0); +U+6705(0);U+6705(0); +U+6706(0);U+6706(0); +U+6708(0);U+6708(5); +U+6709(0);U+6709(5); +U+670A(0);U+670A(5); +U+670B(0);U+670B(5); +U+670C(0);U+9881(3);U+9812(3),U+9881(3) +U+670D(0);U+670D(5); +U+670E(0);U+670E(0); +U+670F(0);U+670F(4);U+80D0(4) +U+6710(0);U+6710(5);U+80CA(4) +U+6711(0);U+6711(0); +U+6712(0);U+6712(3); +U+6713(0);U+6713(4);U+8101(4) +U+6714(0);U+6714(5); +U+6715(0);U+6715(5); +U+6716(0);U+6717(3);U+6717(3),U+70FA(3) +U+6717(0);U+6717(5);U+6716(3),U+70FA(3) +U+6718(0);U+6718(4);U+8127(4) +U+671A(0);U+671A(0); +U+671B(0);U+671B(5);U+6722(2,3) +U+671C(0);U+671C(0); +U+671D(0);U+671D(5); +U+671E(0);U+671F(2,3);U+671F(2,3) +U+671F(0);U+671F(5);U+671E(2,3) +U+6720(0);U+6720(0); +U+6721(0);U+6721(0); +U+6722(0);U+671B(2,3);U+671B(2,3) +U+6723(0);U+6723(4);U+81A7(4) +U+6725(0);U+6725(0); +U+6726(0);U+6726(5); +U+6727(0);U+80E7(1,3);U+80E7(1,3) +U+6728(0);U+6728(5); +U+672A(0);U+672A(5); +U+672B(0);U+672B(5); +U+672C(0);U+672C(5);U+5932(3) +U+672D(0);U+672D(5);U+624E(3),U+5273(2,3),U+5284(2,3),U+7B9A(2,3,4),U+7D25(2,3,4),U+7D2E(2,3,4) + +U+672E(0);U+672F(4);U+672F(4),U+8853(1,3,4) +U+672F(0);U+672F(1,3);U+672E(4),U+8853(1,3) +U+6730(0);U+6730(0); +U+6731(0);U+6731(1);U+7843(1,4) +U+6732(0);U+6732(0); +U+6733(0);U+6733(3); +U+6734(0);U+6734(1,3);U+6A38(1,3) +U+6735(0);U+6735(5);U+6736(2,3) +U+6736(0);U+6735(2,3);U+6735(2,3) +U+6737(0);U+6737(0); +U+6738(0);U+6738(0); +U+6739(0);U+6739(0); +U+673A(0);U+673A(1,3);U+6A5F(1,3) +U+673B(0);U+6A1B(3);U+6A1B(3) +U+673C(0);U+6787(3);U+6787(3) +U+673D(0);U+673D(5); +U+673E(0);U+673E(3); +U+673F(0);U+523A(3);U+523A(3),U+523E(3,7) +U+6740(0);U+6740(1,3);U+6BBA(1,3),U+95B7(3) +U+6741(0);U+6741(0); + +U+6742(0);U+6742(1,3);U+96D1(3),U+96DC(1,3),U+96E5(3) +U+6743(0);U+6743(1,3);U+6A29(3),U+6B0A(1,3) +U+6744(0);U+6744(3); +U+6745(0);U+6745(3); +U+6746(0);U+6746(5);U+687F(2,3) +U+6747(0);U+572C(3);U+572C(3) +U+6748(0);U+6748(5); +U+6749(0);U+6749(5); +U+674A(0);U+674A(0); +U+674B(0);U+674B(3); +U+674C(0);U+674C(5); +U+674D(0);U+6893(3);U+6893(3) +U+674E(0);U+674E(5); +U+674F(0);U+674F(5); +U+6750(0);U+6750(5); +U+6751(0);U+6751(5);U+90A8(2,3) +U+6752(0);U+6752(3); +U+6753(0);U+6753(5); +U+6754(0);U+6754(0); +U+6755(0);U+6755(0); +U+6756(0);U+6756(5); +U+6757(0);U+6757(0); +U+6758(0);U+6758(3); +U+6759(0);U+6759(3); +U+675A(0);U+675A(0); +U+675B(0);U+675B(0); +U+675C(0);U+675C(5); +U+675D(0);U+675D(4); +U+675E(0);U+675E(5); +U+675F(0);U+675F(5); +U+6760(0);U+6760(5);U+69D3(2,3) +U+6761(0);U+6761(1,3);U+689D(1,3) +U+6762(0);U+6762(0); +U+6763(0);U+6763(0); +U+6764(0);U+6764(0); +U+6765(0);U+6765(1,3);U+4F86(1,3) +U+6766(0);U+6766(0); +U+6768(0);U+6768(1,3);U+694A(1,3) +U+6769(0);U+6769(4);U+69AA(4) +U+676A(0);U+676A(5); +U+676B(0);U+676B(0); +U+676C(0);U+676C(0); +U+676D(0);U+676D(5); +U+676E(0);U+676E(4); +U+676F(0);U+676F(5);U+686E(2,3),U+76C3(2,3) +U+6770(0);U+6770(3);U+5091(2,3) +U+6771(0);U+4E1C(1,3);U+4E1C(1,3) +U+6772(0);U+6772(5); +U+6773(0);U+6773(5); +U+6774(0);U+6774(3); +U+6775(0);U+6775(5); +U+6776(0);U+6776(3); +U+6777(0);U+6777(5); +U+6778(0);U+6BB3(3);U+6BB3(3) +U+6779(0);U+6779(0); +U+677A(0);U+677A(0); +U+677B(0);U+677B(0); +U+677C(0);U+677C(5); +U+677D(0);U+677D(3); +U+677E(0);U+677E(1,3);U+6780(3),U+9B06(1,3,4) +U+677F(0);U+677F(1,3);U+95C6(1,3) +U+6780(0);U+677E(3);U+677E(3),U+9B06(1,3,4) +U+6781(0);U+6781(1,3);U+6975(1,3) + +U+6782(0);U+6782(0); +U+6783(0);U+6783(0); +U+6784(0);U+6784(1,3);U+5193(3),U+6406(4),U+69CB(1,3) +U+6785(0);U+6785(0); +U+6786(0);U+6786(0); +U+6787(0);U+6787(5);U+673C(3) +U+6789(0);U+6789(5); +U+678A(0);U+678A(0); +U+678B(0);U+678B(5); +U+678C(0);U+678C(0); +U+678D(0);U+678D(0); +U+678E(0);U+678E(0); +U+678F(0);U+6960(2,3);U+6960(2,3) +U+6790(0);U+6790(5); +U+6791(0);U+6791(3); +U+6792(0);U+6792(0); +U+6793(0);U+6793(3); +U+6794(0);U+6794(0); +U+6795(0);U+6795(5); +U+6797(0);U+6797(5); +U+6798(0);U+6798(5); +U+6799(0);U+8F6D(3);U+8F6D(3),U+8EDB(1,3),U+8EF6(3) +U+679A(0);U+679A(5); +U+679B(0);U+679B(0); +U+679C(0);U+679C(5);U+83D3(2,3) +U+679D(0);U+679D(5); +U+679E(0);U+679E(1,3);U+6A05(1,3) +U+679F(0);U+679F(0); +U+67A0(0);U+67A0(0); +U+67A1(0);U+67A1(0); +U+67A2(0);U+67A2(1,3);U+6A1E(1,3) +U+67A3(0);U+67A3(1,3,4);U+6806(4),U+68D7(1,3) +U+67A4(0);U+67A4(0); +U+67A5(0);U+67A5(1,3);U+6AEA(1,3) +U+67A6(0);U+67A6(0); +U+67A7(0);U+67A7(1,3);U+6898(1,3) +U+67A8(0);U+67A8(1,3);U+68D6(1,3) +U+67AA(0);U+67AA(1,3);U+69CD(1,3) +U+67AB(0);U+67AB(1,3);U+6953(1,3) +U+67AC(0);U+67AC(0); +U+67AD(0);U+67AD(1,3);U+689F(1,3),U+9DCD(3) +U+67AE(0);U+6939(3);U+6939(3) +U+67AF(0);U+67AF(5); +U+67B0(0);U+67B0(5);U+6A98(3) +U+67B1(0);U+67B1(3); +U+67B2(0);U+67B2(3); +U+67B3(0);U+67B3(5); +U+67B4(0);U+62D0(4);U+62D0(4) +U+67B5(0);U+67B5(5); +U+67B6(0);U+67B6(5); +U+67B7(0);U+67B7(5);U+801E(3) +U+67B8(0);U+67B8(5); +U+67B9(0);U+67B9(0); +U+67BA(0);U+67BA(0); +U+67BB(0);U+67BB(3); +U+67BC(0);U+67BC(3); +U+67BE(0);U+67FF(7);U+67FF(7) +U+67C0(0);U+67C0(0); +U+67C1(0);U+67C1(5);U+8235(3) +U+67C2(0);U+67C2(3); +U+67C3(0);U+67C3(5); +U+67C4(0);U+67C4(5); +U+67C5(0);U+67C5(3); + +U+67C6(0);U+67C6(0); +U+67C7(0);U+67C7(0); +U+67C8(0);U+67C8(0); +U+67C9(0);U+67C9(0); +U+67CA(0);U+67CA(0); +U+67CB(0);U+67CB(0); +U+67CC(0);U+67CC(3); +U+67CD(0);U+67CD(3); +U+67CE(0);U+67CE(3); +U+67CF(0);U+67CF(5);U+6822(2,3) +U+67D0(0);U+67D0(5); +U+67D1(0);U+67D1(5); +U+67D2(0);U+67D2(5);U+6F06(3),U+687C(3) +U+67D3(0);U+67D3(5); +U+67D4(0);U+67D4(5); +U+67D6(0);U+67D6(0); +U+67D8(0);U+67D8(5); +U+67D9(0);U+67D9(5); +U+67DA(0);U+67DA(5); +U+67DB(0);U+67DB(0); +U+67DC(0);U+67DC(1,3);U+6AC3(1,3) +U+67DD(0);U+67DD(5); +U+67DE(0);U+67DE(5); +U+67DF(0);U+67DF(0); +U+67E0(0);U+67E0(1,3);U+6AB8(1,3) +U+67E1(0);U+67E1(0); +U+67E2(0);U+67E2(5); +U+67E3(0);U+67E3(0); +U+67E4(0);U+67E4(0); +U+67E5(0);U+67E5(5);U+67FB(2),U+6942(3) +U+67E6(0);U+67E6(0); +U+67E7(0);U+67E7(0); +U+67E8(0);U+67E8(0); +U+67E9(0);U+67E9(5);U+67FE(3) +U+67EA(0);U+67EA(0); +U+67EB(0);U+67EB(3); +U+67EC(0);U+67EC(5); +U+67ED(0);U+67ED(0); +U+67EE(0);U+67EE(0); +U+67EF(0);U+67EF(5); +U+67F0(0);U+67F0(5);U+5948(3) +U+67F1(0);U+67F1(5);U+782B(3) +U+67F2(0);U+67F2(3); +U+67F3(0);U+67F3(5); +U+67F4(0);U+67F4(5);U+7961(3) +U+67F5(0);U+6805(2,3);U+6805(2,3) +U+67F6(0);U+67F6(0); +U+67F7(0);U+67F7(3); +U+67F8(0);U+67F8(0); +U+67FA(0);U+67FA(3); +U+67FB(0);U+67E5(2);U+67E5(2),U+6942(2,3) +U+67FC(0);U+67FC(0); +U+67FD(0);U+67FD(1,3);U+6A89(1,3) +U+67FE(0);U+67E9(3);U+67E9(3) +U+67FF(0);U+67FF(5);U+67BE(7) +U+6800(0);U+6800(5);U+6894(2,3) +U+6802(0);U+6802(0); +U+6803(0);U+6803(0); +U+6804(0);U+8363(7);U+69AE(8,9),U+8363(7) +U+6805(0);U+6805(5);U+67F5(2,3) +U+6806(0);U+67A3(1,3,4);U+67A3(1,3,4),U+68D7(1,3) +U+6807(0);U+6807(1,3);U+5882(3),U+6A19(1,3) +U+6808(0);U+6808(1,3);U+68E7(1,3),U+8F4F(3) + +U+6809(0);U+6809(1,3);U+6ADB(1,3) +U+680A(0);U+680A(1,3);U+6AF3(1,3) +U+680B(0);U+680B(1,3);U+68DF(1,3) +U+680C(0);U+680C(1,3);U+6AE8(1,3) +U+680D(0);U+680D(0); +U+680E(0);U+680E(1,3);U+6ADF(1,3) +U+680F(0);U+680F(1,3);U+6B04(1,3),U+6B17(3) +U+6810(0);U+6810(0); +U+6811(0);U+6811(1,3);U+5C0C(3),U+6A39(1,3) +U+6812(0);U+6812(0); +U+6813(0);U+6813(5); +U+6814(0);U+5951(3);U+5951(3) +U+6816(0);U+6816(3);U+68F2(2,3) +U+6817(0);U+6817(5);U+6144(2) +U+6818(0);U+6818(0); +U+6819(0);U+6819(0); +U+681A(0);U+681A(0); +U+681B(0);U+681B(0); +U+681C(0);U+681C(0); +U+681D(0);U+681D(5); +U+681F(0);U+681F(0); +U+6820(0);U+6820(3); +U+6821(0);U+6821(5);U+630D(3) +U+6822(0);U+67CF(2,3);U+67CF(2,3) +U+6823(0);U+6823(0); +U+6824(0);U+6824(0); +U+6825(0);U+6825(0); +U+6826(0);U+6826(0); +U+6828(0);U+6828(0); +U+6829(0);U+6829(5); +U+682A(0);U+682A(5); +U+682B(0);U+682B(0); +U+682C(0);U+682C(0); +U+682D(0);U+682D(3); +U+682E(0);U+682E(0); +U+682F(0);U+682F(0); +U+6831(0);U+6831(0); +U+6832(0);U+6832(5); +U+6833(0);U+6833(5); +U+6834(0);U+6834(0); +U+6835(0);U+6835(0); +U+6836(0);U+6836(0); +U+6837(0);U+6837(1,3);U+69D8(4),U+6A23(1,3) +U+6838(0);U+6838(5);U+69C5(4),U+8988(2,3) +U+6839(0);U+6839(5); +U+683A(0);U+683A(0); +U+683B(0);U+683B(3); +U+683C(0);U+683C(5); +U+683D(0);U+683D(5); +U+683E(0);U+683E(1,3);U+6B12(1,3) +U+683F(0);U+683F(0); +U+6840(0);U+6840(5);U+69A4(3) +U+6841(0);U+6841(5);U+822A(3) +U+6842(0);U+6842(5); +U+6843(0);U+6843(5); +U+6844(0);U+6844(5); +U+6845(0);U+6845(5); +U+6846(0);U+6846(5); +U+6847(0);U+6847(0); +U+6848(0);U+6848(5); +U+6849(0);U+6849(5); +U+684A(0);U+684A(5); +U+684B(0);U+684B(0); + +U+684C(0);U+684C(5);U+68F9(3),U+6AC2(2,3) +U+684D(0);U+684D(0); +U+684E(0);U+684E(5); +U+684F(0);U+684F(0); +U+6850(0);U+6850(5); +U+6851(0);U+6851(5);U+6852(3) +U+6852(0);U+6851(3);U+6851(3) +U+6853(0);U+6853(5); +U+6854(0);U+6854(5); +U+6855(0);U+6855(5); +U+6856(0);U+6856(0); +U+6857(0);U+6857(0); +U+685B(0);U+685B(0); +U+685D(0);U+685D(0); +U+6860(0);U+6860(4);U+690F(4) +U+6861(0);U+6861(1,3);U+6A48(1,3) +U+6862(0);U+6862(1,3);U+6968(1,3) +U+6863(0);U+6863(1,3);U+6A94(1,3) +U+6864(0);U+6864(1,3);U+69BF(1,3) +U+6865(0);U+6865(1,3);U+6A4B(1,3),U+6A47(1,3),U+97BD(1,3),U+9792(1,3) +U+6866(0);U+6866(1,3);U+6A3A(1,3) +U+6867(0);U+6867(1,3);U+6A9C(1,3) +U+6868(0);U+6868(1,3);U+69F3(1,3) +U+6869(0);U+6869(1,3);U+6A01(1,3),U+8E56(4) +U+686A(0);U+686A(4);U+6A33(4) +U+686B(0);U+686B(5); +U+686C(0);U+686C(0); +U+686D(0);U+686D(3); +U+686E(0);U+676F(2,3);U+676F(2,3),U+76C3(2,3) +U+686F(0);U+686F(0); +U+6870(0);U+6870(0); +U+6871(0);U+6871(0); +U+6872(0);U+6872(0); +U+6873(0);U+6873(0); +U+6874(0);U+6874(5);U+6CED(3) +U+6875(0);U+6875(0); +U+6876(0);U+6876(5); +U+6877(0);U+6877(5); +U+6878(0);U+6878(3); +U+6879(0);U+6994(3,4);U+6994(3,4) +U+687B(0);U+687B(0); +U+687C(0);U+6F06(3);U+6F06(3),U+67D2(3,5) +U+687D(0);U+687D(0); +U+687E(0);U+687E(0); +U+687F(0);U+6746(2,3);U+6746(2,3) +U+6880(0);U+6880(0); +U+6881(0);U+6881(5);U+6A11(2,3) +U+6882(0);U+6882(0); +U+6883(0);U+6883(5); +U+6884(0);U+6884(0); +U+6885(0);U+6885(5);U+6973(2,3) +U+6886(0);U+6886(5); +U+6887(0);U+6887(0); +U+6888(0);U+6888(0); +U+6889(0);U+6889(0); +U+688A(0);U+688A(0); +U+688B(0);U+688B(3); +U+688C(0);U+688C(0); +U+688D(0);U+688D(0); +U+688E(0);U+688E(0); +U+688F(0);U+688F(5); +U+6890(0);U+6890(0); +U+6891(0);U+6891(0); + +U+6892(0);U+6892(0); +U+6893(0);U+6893(5);U+674D(3) +U+6894(0);U+6800(2,3);U+6800(2,3) +U+6896(0);U+6896(0); +U+6897(0);U+6897(5); +U+6898(0);U+67A7(1,3);U+67A7(1,3) +U+689A(0);U+689A(0); +U+689B(0);U+689B(0); +U+689C(0);U+689C(0); +U+689D(0);U+6761(1,3);U+6761(1,3) +U+689E(0);U+689E(0); +U+689F(0);U+67AD(1,3);U+67AD(1,3),U+9DCD(1,3) +U+68A0(0);U+68A0(3); +U+68A1(0);U+68A1(3); +U+68A2(0);U+68A2(5); +U+68A3(0);U+68A3(3); +U+68A4(0);U+68A4(3); +U+68A6(0);U+68A6(1,3);U+5922(1,3) +U+68A7(0);U+68A7(5); +U+68A8(0);U+68A8(5); +U+68A9(0);U+68A9(0); +U+68AA(0);U+8C46(3);U+8C46(3),U+8373(2,3) +U+68AB(0);U+68AB(0); +U+68AC(0);U+68AC(0); +U+68AD(0);U+68AD(5); +U+68AE(0);U+68AE(3); +U+68AF(0);U+68AF(5); +U+68B0(0);U+68B0(5); +U+68B1(0);U+68B1(3); +U+68B2(0);U+68C1(4);U+68C1(4) +U+68B3(0);U+68B3(5); +U+68B4(0);U+68B4(0); +U+68B5(0);U+68B5(5); +U+68B6(0);U+68B6(0); +U+68B7(0);U+68B7(0); +U+68B9(0);U+69DF(3);U+69DF(3),U+6AB3(3) +U+68BB(0);U+68BB(0); +U+68BC(0);U+68BC(4);U+6AAE(4) +U+68BD(0);U+68BD(0); +U+68BE(0);U+68BE(4);U+68F6(4) +U+68BF(0);U+68BF(4);U+69E4(4) +U+68C0(0);U+68C0(1,3);U+691C(4),U+6AA2(1,3,4) +U+68C1(0);U+68C1(0);U+68B2(4) +U+68C2(0);U+68C2(1,3);U+6B1E(1,3) +U+68C4(0);U+5F03(2,3);U+5F03(2,3) +U+68C6(0);U+68C6(0); +U+68C7(0);U+68C7(0); +U+68C8(0);U+68C8(0); +U+68C9(0);U+68C9(5); +U+68CA(0);U+68CB(2,3);U+68CB(2,3),U+7881(2,3) +U+68CB(0);U+68CB(5);U+68CA(2,3),U+7881(2,3) +U+68CC(0);U+68CC(0); +U+68CD(0);U+68CD(5); +U+68CE(0);U+68CE(0); +U+68CF(0);U+68CF(0); +U+68D0(0);U+68D0(0); +U+68D1(0);U+68D1(0); +U+68D2(0);U+68D2(5); +U+68D3(0);U+68D3(0); +U+68D4(0);U+68D4(0); +U+68D5(0);U+68D5(5);U+6936(2,3) +U+68D6(0);U+67A8(1,3);U+67A8(1,3) +U+68D7(0);U+67A3(1,3,4);U+67A3(1,3,4),U+6806(4) + +U+68D8(0);U+68D8(5); +U+68DA(0);U+68DA(5); +U+68DB(0);U+68DB(0); +U+68DC(0);U+68DC(0); +U+68DD(0);U+68DD(0); +U+68DE(0);U+68DE(0); +U+68DF(0);U+680B(1,3);U+680B(1,3) +U+68E0(0);U+68E0(5); +U+68E1(0);U+3B4E(1,3);U+3B4E(1,3) +U+68E3(0);U+68E3(5); +U+68E4(0);U+68E4(0); +U+68E6(0);U+68E6(0); +U+68E7(0);U+6808(1,3);U+6808(1,3),U+8F4F(1,3) +U+68E8(0);U+7DAE(4);U+7DAE(4) +U+68E9(0);U+68E9(0); +U+68EA(0);U+68EA(0); +U+68EB(0);U+68EB(0); +U+68EC(0);U+68EC(3); +U+68ED(0);U+68ED(0); +U+68EE(0);U+68EE(5); +U+68EF(0);U+68EF(3); +U+68F0(0);U+68F0(5);U+7BA0(2,3) +U+68F1(0);U+68F1(5);U+7A1C(2,3) +U+68F2(0);U+6816(2,3);U+6816(2,3) +U+68F3(0);U+68F3(0); +U+68F4(0);U+68F4(0); +U+68F5(0);U+68F5(5); +U+68F6(0);U+68BE(4);U+68BE(4) +U+68F7(0);U+68F7(0); +U+68F8(0);U+68F8(0); +U+68F9(0);U+68F9(5);U+684C(3),U+6AC2(2,3) +U+68FA(0);U+68FA(5); +U+68FB(0);U+68FB(0); +U+68FC(0);U+68FC(5); +U+68FD(0);U+68FD(0); +U+68FE(0);U+68FE(0); +U+68FF(0);U+68FF(0); +U+6901(0);U+6901(5);U+69E8(2,3) +U+6902(0);U+6902(0); +U+6903(0);U+6903(0); +U+6904(0);U+6904(0); +U+6905(0);U+6905(5); +U+6906(0);U+6906(0); +U+6907(0);U+6907(0); +U+6908(0);U+6908(0); +U+690A(0);U+690A(0); +U+690B(0);U+690B(5); +U+690C(0);U+690C(0); +U+690D(0);U+690D(5); +U+690E(0);U+690E(5); +U+690F(0);U+6860(4);U+6860(4) +U+6910(0);U+6910(5); +U+6911(0);U+6911(0); +U+6912(0);U+6912(5); +U+6913(0);U+6913(0); +U+6914(0);U+6914(0); +U+6915(0);U+6915(0); +U+6916(0);U+6916(0); +U+6917(0);U+7887(2,3);U+7887(2,3) +U+6918(0);U+695A(3);U+695A(3),U+6A9A(3) +U+6919(0);U+6919(0); +U+691A(0);U+691A(0); +U+691B(0);U+691B(0); + +U+691C(0);U+68C0(4);U+68C0(4),U+6AA2(4) +U+691D(0);U+89C4(4);U+69FC(4),U+89C4(4),U+898F(2,4) +U+691E(0);U+691E(0); +U+691F(0);U+691F(1,3);U+6ADD(1,3) +U+6920(0);U+6920(1,3);U+69E7(1,3) +U+6921(0);U+6921(0); +U+6922(0);U+6922(0); +U+6923(0);U+6923(0); +U+6924(0);U+6924(1,3);U+6B0F(1,3) +U+6925(0);U+6925(0); +U+6926(0);U+6926(0); +U+6927(0);U+6927(0); +U+6928(0);U+6928(0); +U+6929(0);U+6929(0); +U+692A(0);U+692A(0); +U+692B(0);U+692B(4);U+6A3F(4) +U+692C(0);U+692C(0); +U+692D(0);U+692D(1,3);U+64B1(4),U+6955(3),U+6A62(1,3) +U+692E(0);U+692E(4); +U+692F(0);U+692F(0); +U+6930(0);U+6930(5); +U+6931(0);U+6931(0); +U+6932(0);U+6932(0); +U+6933(0);U+6933(0); +U+6934(0);U+6934(5);U+846E(3) +U+6935(0);U+6935(0); +U+6936(0);U+68D5(2,3);U+68D5(2,3) +U+6937(0);U+6937(0); +U+6938(0);U+6938(3); +U+6939(0);U+6939(5);U+67AE(3) +U+693A(0);U+693A(0); +U+693B(0);U+693B(0); +U+693C(0);U+693C(0); +U+693D(0);U+693D(5); +U+693F(0);U+693F(5); +U+6940(0);U+6940(0); +U+6941(0);U+6941(0); +U+6942(0);U+6942(5);U+67E5(3),U+67FB(2,3) +U+6943(0);U+6943(0); +U+6944(0);U+6944(0); +U+6945(0);U+6945(0); +U+6946(0);U+6946(0); +U+6947(0);U+6947(0); +U+6948(0);U+6948(3); +U+6949(0);U+6949(0); +U+694A(0);U+6768(1,3);U+6768(1,3) +U+694B(0);U+694B(0); +U+694C(0);U+694C(0); +U+694E(0);U+694E(3); +U+694F(0);U+694F(0); +U+6950(0);U+6950(0); +U+6951(0);U+63C6(3);U+63C6(3) +U+6952(0);U+6952(0); +U+6953(0);U+67AB(1,3);U+67AB(1,3) +U+6954(0);U+6954(5); +U+6955(0);U+692D(3);U+692D(3),U+6A62(3),U+64B1(0,3,4) +U+6956(0);U+6956(0); +U+6957(0);U+6957(5); +U+6958(0);U+6958(3); +U+6959(0);U+6959(3); +U+695A(0);U+695A(5);U+6918(3),U+6A9A(3) +U+695B(0);U+695B(0); +U+695C(0);U+695C(0); + +U+695D(0);U+695D(5); +U+695E(0);U+695E(5); +U+695F(0);U+695F(0); +U+6960(0);U+6960(5);U+678F(2,3) +U+6961(0);U+6986(4);U+6986(4) +U+6962(0);U+6962(0); +U+6963(0);U+6963(5); +U+6964(0);U+6964(3); +U+6965(0);U+6965(0); +U+6966(0);U+6966(5); +U+6967(0);U+6967(0); +U+6968(0);U+6862(1,3);U+6862(1,3) +U+6969(0);U+6969(0); +U+696A(0);U+696A(3); +U+696B(0);U+696B(5); +U+696C(0);U+696C(3); +U+696D(0);U+4E1A(1,3);U+4E1A(1,3) +U+696E(0);U+696E(5); +U+696F(0);U+696F(0); +U+6970(0);U+6970(0); +U+6971(0);U+6971(5); +U+6972(0);U+6972(0); +U+6973(0);U+6885(2,3);U+6885(2,3) +U+6974(0);U+6974(0); +U+6975(0);U+6781(1,3);U+6781(1,3) +U+6976(0);U+6976(0); +U+6977(0);U+6977(5); +U+6978(0);U+6978(5); +U+6979(0);U+6979(5); +U+697A(0);U+697A(0); +U+697B(0);U+697B(0); +U+697C(0);U+697C(1,3);U+6A13(1,3) +U+697D(0);U+4E50(3);U+4E50(3),U+6A02(3) +U+697E(0);U+697E(0); +U+697F(0);U+697F(0); +U+6980(0);U+6980(5); +U+6981(0);U+6981(0); +U+6982(0);U+6982(5);U+69EA(4) +U+6983(0);U+6983(0); +U+6984(0);U+6984(1,3);U+6B16(1,3) +U+6985(0);U+6985(0);U+69B2(4) +U+6986(0);U+6986(5);U+6961(4) +U+6987(0);U+6987(1,3);U+6AEC(1,3),U+85FD(3) +U+6988(0);U+6988(1,3);U+6ADA(1,3) +U+6989(0);U+6989(1,3);U+6AF8(1,3) +U+698A(0);U+698A(0); +U+698B(0);U+698B(0); +U+698C(0);U+698C(0); +U+698D(0);U+698D(5); +U+698E(0);U+69DA(3);U+69DA(3),U+6A9F(1,3) +U+698F(0);U+698F(0); +U+6990(0);U+6990(0); +U+6991(0);U+6991(0); +U+6992(0);U+6992(0); +U+6993(0);U+6993(3); +U+6994(0);U+6994(5);U+6879(3,4) +U+6995(0);U+6995(5); +U+6996(0);U+6996(0); +U+6997(0);U+6997(0); +U+6998(0);U+6998(5);U+77E9(2,3) +U+6999(0);U+6999(0); +U+699A(0);U+699A(0); +U+699B(0);U+699B(5);U+6A3C(3),U+7349(4) + +U+699C(0);U+699C(5);U+7253(3) +U+699D(0);U+699D(3);U+6A27(4),U+8531(3) +U+699E(0);U+699E(0); +U+69A0(0);U+69A0(0); +U+69A1(0);U+7D20(3);U+7D20(3) +U+69A3(0);U+69A3(0); +U+69A4(0);U+6840(3);U+6840(3) +U+69A5(0);U+69A5(0); +U+69A6(0);U+5E72(4);U+5E72(4),U+5E79(2,3),U+4E7E(1,3,4),U+4E81(1,2,3,4),U+6F27(1,3,4) + +U+69A7(0);U+69A7(5); +U+69A8(0);U+69A8(5);U+643E(2,3),U+91A1(3) +U+69A9(0);U+69A9(0); +U+69AA(0);U+6769(4);U+6769(4) +U+69AB(0);U+69AB(5); +U+69AC(0);U+69AC(3); +U+69AD(0);U+69AD(5); +U+69AE(0);U+8363(1,3);U+6804(8,9),U+8363(1,3) +U+69AF(0);U+69AF(0); +U+69B0(0);U+69B0(0); +U+69B1(0);U+69B1(5); +U+69B2(0);U+6985(4);U+6985(4) +U+69B3(0);U+69B3(0); +U+69B4(0);U+69B4(5); +U+69B5(0);U+69B5(0); +U+69B6(0);U+69B6(0); +U+69B7(0);U+69B7(5);U+6409(2,3) +U+69B8(0);U+69B8(0); +U+69B9(0);U+69B9(0); +U+69BA(0);U+69BA(0); +U+69BB(0);U+69BB(5); +U+69BC(0);U+69BC(3); +U+69BD(0);U+69BD(0); +U+69BE(0);U+69BE(0); +U+69BF(0);U+6864(1,3);U+6864(1,3) +U+69C1(0);U+69C1(5); +U+69C2(0);U+69C2(0); +U+69C3(0);U+69C3(3); +U+69C4(0);U+69C4(0); +U+69C5(0);U+69C5(0);U+6838(4),U+8988(2,3,4) +U+69C6(0);U+69C6(0); +U+69C7(0);U+69D9(4);U+69D9(4) +U+69C8(0);U+69C8(4); +U+69C9(0);U+69C9(0); +U+69CA(0);U+69CA(5); +U+69CB(0);U+6784(1,3);U+6406(2,3),U+6784(1,3),U+5193(0,1,3) +U+69CC(0);U+69CC(5); +U+69CD(0);U+67AA(1,3);U+67AA(1,3) +U+69CE(0);U+69CE(5); +U+69CF(0);U+69CF(0); +U+69D0(0);U+69D0(5); +U+69D3(0);U+6760(2,3);U+6760(2,3) +U+69D4(0);U+69D4(5); +U+69D8(0);U+6837(4);U+6837(4),U+6A23(4) +U+69D9(0);U+69D9(4);U+69C7(4) +U+69DA(0);U+69DA(1,3);U+698E(3),U+6A9F(1,3) +U+69DB(0);U+69DB(1,3);U+6ABB(1,3),U+8F5E(3) +U+69DC(0);U+69DC(3);U+6A87(3) +U+69DD(0);U+69DD(0); +U+69DE(0);U+69DE(0); +U+69DF(0);U+69DF(1,3);U+68B9(3),U+6AB3(1,3) +U+69E0(0);U+69E0(1,3);U+6AE7(1,3) +U+69E1(0);U+69E1(0); + +U+69E2(0);U+69E2(0); +U+69E3(0);U+69E3(0); +U+69E4(0);U+68BF(4);U+68BF(4) +U+69E5(0);U+69E5(3);U+6A85(3) +U+69E6(0);U+69E6(0); +U+69E7(0);U+6920(1,3);U+6920(1,3) +U+69E8(0);U+6901(2,3);U+6901(2,3) +U+69E9(0);U+69E9(0); +U+69EA(0);U+6982(4);U+6982(4) +U+69EB(0);U+69EB(0); +U+69EC(0);U+69EC(0); +U+69ED(0);U+69ED(5); +U+69EE(0);U+69EE(0); +U+69EF(0);U+69EF(0); +U+69F0(0);U+69F0(0); +U+69F1(0);U+69F1(3); +U+69F2(0);U+69F2(5); +U+69F3(0);U+6868(1,3);U+6868(1,3) +U+69F4(0);U+69F4(0); +U+69F5(0);U+69F5(3); +U+69F6(0);U+69F6(0); +U+69F7(0);U+69F7(4); +U+69F8(0);U+69F8(3); +U+69FA(0);U+69FA(0); +U+69FB(0);U+69FB(0); +U+69FC(0);U+89C4(4);U+691D(4),U+898F(2),U+89C4(4) +U+69FD(0);U+69FD(5); +U+69FE(0);U+69FE(0); +U+69FF(0);U+69FF(5); +U+6A00(0);U+6A00(0); +U+6A01(0);U+6869(1,3);U+6869(1,3),U+8E56(1,3,4) +U+6A02(0);U+4E50(1,3);U+4E50(1,3),U+697D(3) +U+6A04(0);U+6A04(0); +U+6A05(0);U+679E(1,3);U+679E(1,3) +U+6A06(0);U+6A06(0); +U+6A07(0);U+6A07(0); +U+6A08(0);U+6A08(0); +U+6A09(0);U+6A09(0); +U+6A0A(0);U+6A0A(5); +U+6A0B(0);U+6A0B(0); +U+6A0D(0);U+6A0D(0); +U+6A0E(0);U+6A0E(0); +U+6A0F(0);U+6A0F(4); +U+6A10(0);U+6A79(3);U+6A79(3),U+6AD3(2,3),U+8263(2,3),U+826A(2,3) +U+6A11(0);U+6881(2,3);U+6881(2,3) +U+6A12(0);U+6A12(0); +U+6A13(0);U+697C(1,3);U+697C(1,3) +U+6A14(0);U+6A14(0); +U+6A15(0);U+6A15(0); +U+6A16(0);U+6A16(0); +U+6A17(0);U+6A17(5); +U+6A18(0);U+6A18(5);U+6A55(3) +U+6A19(0);U+6807(1,3);U+6807(1,3),U+5882(0,1,3) +U+6A1A(0);U+6A1A(0); +U+6A1B(0);U+6A1B(3);U+673B(3) +U+6A1D(0);U+6A1D(3); +U+6A1E(0);U+67A2(1,3);U+67A2(1,3) +U+6A1F(0);U+6A1F(5); +U+6A20(0);U+6A20(3); +U+6A21(0);U+6A21(5); +U+6A22(0);U+6A22(0); +U+6A23(0);U+6837(1,3);U+6837(1,3),U+69D8(4) +U+6A25(0);U+6A25(0); + +U+6A26(0);U+6A26(0); +U+6A27(0);U+699D(4);U+699D(4),U+8531(3,4) +U+6A28(0);U+6A28(5); +U+6A29(0);U+6743(3);U+6743(3),U+6B0A(3) +U+6A2A(0);U+6A2A(5);U+6A6B(4) +U+6A2B(0);U+6A2B(0); +U+6A2C(0);U+6A2C(0); +U+6A2D(0);U+6A2D(0); +U+6A2E(0);U+6A2E(0); +U+6A2F(0);U+6A2F(1,3);U+6AA3(1,3) +U+6A30(0);U+6A30(0); +U+6A31(0);U+6A31(1,3);U+6AFB(1,3) +U+6A32(0);U+6A32(0); +U+6A33(0);U+686A(4);U+686A(4) +U+6A34(0);U+6A34(0); +U+6A35(0);U+6A35(5); +U+6A36(0);U+6A36(0); +U+6A38(0);U+6734(1,3);U+6734(1,3) +U+6A39(0);U+6811(1,3);U+6811(1,3),U+5C0C(0,1,3) +U+6A3A(0);U+6866(1,3);U+6866(1,3) +U+6A3B(0);U+6A3B(0); +U+6A3C(0);U+699B(3);U+699B(3),U+7349(3,4) +U+6A3D(0);U+6A3D(5);U+58AB(3),U+7F47(2,3) +U+6A3E(0);U+6A3E(5); +U+6A3F(0);U+692B(4);U+692B(4) +U+6A40(0);U+6A40(0); +U+6A41(0);U+6A41(3); +U+6A42(0);U+6A42(0); +U+6A43(0);U+6A43(3); +U+6A44(0);U+6A44(5); +U+6A45(0);U+6A45(0); +U+6A46(0);U+6A46(0); +U+6A47(0);U+6A47(5);U+6A4B(3),U+6865(1,3),U+97BD(1,3),U+9792(1,3) +U+6A48(0);U+6861(1,3);U+6861(1,3) +U+6A49(0);U+6A49(0); +U+6A4B(0);U+6865(1,3);U+6865(1,3),U+6A47(3),U+97BD(3),U+9792(1,3) +U+6A4C(0);U+6A4C(0); +U+6A4D(0);U+6A4D(0); +U+6A4E(0);U+6A4E(0); +U+6A4F(0);U+6A4F(0); +U+6A50(0);U+6A50(5); +U+6A51(0);U+6A51(0); +U+6A52(0);U+6A52(0); +U+6A54(0);U+6A54(0); +U+6A55(0);U+6A18(3);U+6A18(3) +U+6A56(0);U+6A56(0); +U+6A57(0);U+6A57(0); +U+6A58(0);U+6A58(5); +U+6A59(0);U+6A59(5); +U+6A5A(0);U+6A5A(3); +U+6A5B(0);U+6A5B(5); +U+6A5D(0);U+6A5D(0); +U+6A5E(0);U+6A5E(3); +U+6A5F(0);U+673A(1,3);U+673A(1,3) +U+6A60(0);U+6A60(0); +U+6A61(0);U+6A61(5); +U+6A62(0);U+692D(1,3);U+692D(1,3),U+6955(3),U+64B1(0,1,3,4) +U+6A63(0);U+6A63(0); +U+6A64(0);U+854A(2,3);U+854A(2,3),U+854B(2,3),U+8602(2,3) +U+6A65(0);U+6A65(5);U+6AEB(3) +U+6A66(0);U+6A66(0); +U+6A67(0);U+6A67(3); +U+6A68(0);U+6A68(0); + +U+6A69(0);U+6A69(0); +U+6A6A(0);U+6A6A(4); +U+6A6B(0);U+6A2A(4);U+6A2A(4) +U+6A6C(0);U+6A6C(0); +U+6A6D(0);U+6A6D(0); +U+6A6F(0);U+6A6F(0); +U+6A71(0);U+6A71(5);U+6AE5(2,3) +U+6A72(0);U+6A72(0); +U+6A73(0);U+6A73(0); +U+6A74(0);U+6A74(0); +U+6A75(0);U+6A75(0); +U+6A76(0);U+6A76(0); +U+6A77(0);U+6A77(0); +U+6A78(0);U+6A78(0); +U+6A79(0);U+6A79(1,3);U+6A10(3),U+6AD3(1,3),U+8263(2,3),U+826A(2,3) +U+6A7A(0);U+6A7A(0); +U+6A7B(0);U+6A7B(0); +U+6A7C(0);U+6A7C(1,3);U+6ADE(1,3) +U+6A7D(0);U+6A7D(0); +U+6A7E(0);U+6A7E(0); +U+6A7F(0);U+6A7F(0); +U+6A80(0);U+6A80(5); +U+6A81(0);U+6AA9(4);U+6AA9(4) +U+6A82(0);U+6A82(0); +U+6A83(0);U+6AFD(3);U+6AFD(3),U+6ABC(3) +U+6A84(0);U+6A84(5); +U+6A85(0);U+69E5(3);U+69E5(3) +U+6A87(0);U+69DC(3);U+69DC(3) +U+6A88(0);U+6A88(0); +U+6A89(0);U+67FD(1,3);U+67FD(1,3) +U+6A8B(0);U+6A8B(3); +U+6A8C(0);U+6A8C(0); +U+6A8D(0);U+6A8D(0); +U+6A8E(0);U+6A8E(5); +U+6A90(0);U+6A90(5);U+7C37(2,3) +U+6A91(0);U+6A91(5); +U+6A92(0);U+6A92(3); +U+6A93(0);U+6A93(0); +U+6A94(0);U+6863(1,3);U+6863(1,3) +U+6A95(0);U+6A95(0); +U+6A96(0);U+6A96(0); +U+6A97(0);U+6A97(5);U+8617(4) +U+6A98(0);U+6A98(0);U+67B0(3) +U+6A9A(0);U+695A(3);U+695A(3),U+6918(0,3) +U+6A9B(0);U+6A9B(0); +U+6A9C(0);U+6867(1,3);U+6867(1,3) +U+6A9E(0);U+6A9E(0); +U+6A9F(0);U+69DA(1,3);U+69DA(1,3),U+698E(0,1,3) +U+6AA0(0);U+6AA0(5); +U+6AA1(0);U+6AA1(0); +U+6AA2(0);U+68C0(1,3);U+68C0(1,3),U+691C(4) +U+6AA3(0);U+6A2F(1,3);U+6A2F(1,3) +U+6AA4(0);U+6AA4(0); +U+6AA5(0);U+8223(3);U+8223(3),U+8264(3,4) +U+6AA6(0);U+6AA6(0); +U+6AA7(0);U+6AA7(0); +U+6AA8(0);U+6AA8(0); +U+6AA9(0);U+6AA9(5);U+6A81(4) +U+6AAB(0);U+6AAB(5); +U+6AAC(0);U+6AAC(5); +U+6AAD(0);U+6AAD(0); +U+6AAE(0);U+68BC(4);U+68BC(4) +U+6AAF(0);U+53F0(1,3);U+53F0(1,3),U+7C49(1,3,4),U+81FA(1,3,4),U+98B1(1,3,4) + +U+6AB0(0);U+6AB0(0); +U+6AB2(0);U+6AB2(0); +U+6AB3(0);U+69DF(1,3);U+68B9(3),U+69DF(1,3) +U+6AB4(0);U+6AB4(0); +U+6AB5(0);U+6AB5(0); +U+6AB6(0);U+6AB6(0); +U+6AB7(0);U+6AB7(3); +U+6AB8(0);U+67E0(1,3);U+67E0(1,3) +U+6AB9(0);U+6AB9(0); +U+6ABA(0);U+6ABA(0); +U+6ABB(0);U+69DB(1,3);U+69DB(1,3),U+8F5E(1,3) +U+6ABC(0);U+6ABC(3);U+6AFD(3),U+6A83(0,3) +U+6ABD(0);U+6ABD(0); +U+6ABF(0);U+6ABF(0); +U+6AC1(0);U+6AC1(0); +U+6AC2(0);U+68F9(2,3);U+68F9(2,3),U+684C(2,3,5) +U+6AC3(0);U+67DC(1,3);U+67DC(1,3) +U+6AC5(0);U+6AC5(0); +U+6AC6(0);U+9B41(3);U+9B41(3) +U+6AC7(0);U+6AC7(0); +U+6ACA(0);U+6ACA(0); +U+6ACB(0);U+6ACB(0); +U+6ACC(0);U+8030(3);U+8030(3) +U+6ACD(0);U+6ACD(3); +U+6ACE(0);U+6ACE(3); +U+6ACF(0);U+6ACF(3); +U+6AD0(0);U+863D(3);U+863D(3) +U+6AD1(0);U+6AD1(0); +U+6AD2(0);U+6AD2(0); +U+6AD3(0);U+6A79(1,3);U+6A10(2,3),U+6A79(1,3),U+8263(2,3),U+826A(2,3) +U+6AD4(0);U+6AD4(0); +U+6AD5(0);U+6AD5(0); +U+6AD6(0);U+6AD6(0); +U+6AD7(0);U+6AD7(0); +U+6AD9(0);U+6AD9(3); +U+6ADA(0);U+6988(1,3);U+6988(1,3) +U+6ADB(0);U+6809(1,3);U+6809(1,3) +U+6ADC(0);U+6ADC(0); +U+6ADD(0);U+691F(1,3);U+691F(1,3) +U+6ADE(0);U+6A7C(1,3);U+6A7C(1,3) +U+6ADF(0);U+680E(1,3);U+680E(1,3) +U+6AE0(0);U+6AE0(0); +U+6AE1(0);U+6AE1(3); +U+6AE2(0);U+6AE2(0); +U+6AE3(0);U+6AE3(0); +U+6AE4(0);U+6AE4(0); +U+6AE5(0);U+6A71(2,3);U+6A71(2,3) +U+6AE6(0);U+6AE6(0); +U+6AE7(0);U+69E0(1,3);U+69E0(1,3) +U+6AE8(0);U+680C(1,3);U+680C(1,3) +U+6AEA(0);U+67A5(1,3);U+67A5(1,3) +U+6AEB(0);U+6A65(3);U+6A65(3) +U+6AEC(0);U+6987(1,3);U+6987(1,3),U+85FD(1,3) +U+6AED(0);U+6AED(0); +U+6AEE(0);U+6AEE(0); +U+6AEF(0);U+6AEF(0); +U+6AF0(0);U+6AF0(0); +U+6AF1(0);U+8616(4);U+8616(4) +U+6AF2(0);U+6AF2(0); +U+6AF3(0);U+680A(1,3);U+680A(1,3) +U+6AF4(0);U+6AF4(0); +U+6AF5(0);U+6AF5(0); +U+6AF6(0);U+6AF6(0); + +U+6AF7(0);U+6AF7(0); +U+6AF8(0);U+6989(1,3);U+6989(1,3) +U+6AF9(0);U+6AF9(0); +U+6AFA(0);U+6AFA(3); +U+6AFB(0);U+6A31(1,3);U+6A31(1,3) +U+6AFC(0);U+6AFC(0); +U+6AFD(0);U+6AFD(0);U+6A83(3),U+6ABC(3) +U+6AFE(0);U+6AFE(0); +U+6AFF(0);U+6AFF(0); +U+6B00(0);U+6B00(0); +U+6B01(0);U+6B01(0); +U+6B02(0);U+6B02(3); +U+6B03(0);U+6B03(0); +U+6B04(0);U+680F(1,3);U+680F(1,3),U+6B17(1,3) +U+6B05(0);U+6B05(0); +U+6B06(0);U+6B06(0); +U+6B07(0);U+6B07(3); +U+6B08(0);U+6B08(0); +U+6B09(0);U+4E1B(3);U+4E1B(3),U+53E2(1,3,4),U+85C2(3) +U+6B0A(0);U+6743(1,3);U+6743(1,3),U+6A29(3) +U+6B0B(0);U+6B0B(0); +U+6B0C(0);U+6B0C(0); +U+6B0D(0);U+6B0D(0); +U+6B0F(0);U+6924(1,3);U+6924(1,3) +U+6B10(0);U+6B10(3); +U+6B11(0);U+6B11(3); +U+6B12(0);U+683E(1,3);U+683E(1,3) +U+6B13(0);U+6B13(0); +U+6B14(0);U+6B14(0); +U+6B15(0);U+6B15(0); +U+6B16(0);U+6984(1,3);U+6984(1,3) +U+6B17(0);U+680F(3);U+680F(3),U+6B04(1,3) +U+6B18(0);U+6B18(0); +U+6B19(0);U+6B19(0); +U+6B1A(0);U+6B1A(3); +U+6B1C(0);U+6B1C(0); +U+6B1D(0);U+90C1(2,3);U+90C1(2,3),U+9B31(2,3),U+9B30(2,3,4) +U+6B1E(0);U+68C2(1,3);U+68C2(1,3) +U+6B1F(0);U+6B1F(0); +U+6B20(0);U+6B20(5); +U+6B21(0);U+6B21(5); +U+6B22(0);U+6B22(1,3);U+61FD(4),U+6B53(3),U+6B61(1,3),U+8B99(4),U+9A69(4) +U+6B23(0);U+6B23(5); +U+6B24(0);U+6B24(1,3);U+6B5F(1,3) +U+6B25(0);U+6B25(0); +U+6B26(0);U+6B26(0); +U+6B27(0);U+6B27(1,3);U+6B50(1,3) +U+6B28(0);U+6B28(0); +U+6B29(0);U+6B29(0); +U+6B2A(0);U+6B2A(0); +U+6B2B(0);U+6B2B(0); +U+6B2C(0);U+6B2C(0); +U+6B2D(0);U+6B2D(0); +U+6B2F(0);U+6B2F(3); +U+6B30(0);U+6B30(0); +U+6B31(0);U+6B31(0); +U+6B32(0);U+6B32(5);U+617E(2) +U+6B33(0);U+559F(3);U+559F(3),U+5633(3) +U+6B34(0);U+6B34(0); +U+6B36(0);U+55FD(3);U+55FD(3) +U+6B37(0);U+6B37(5); +U+6B38(0);U+6B38(4);U+8A92(4),U+8BF6(1,3,4) +U+6B39(0);U+6B39(5); + +U+6B3A(0);U+6B3A(5); +U+6B3B(0);U+6B3B(4); +U+6B3C(0);U+6B3C(0); +U+6B3D(0);U+94A6(1,3);U+94A6(1,3) +U+6B3E(0);U+6B3E(5); +U+6B3F(0);U+6B3F(3); +U+6B41(0);U+6B41(0); +U+6B42(0);U+6B42(0); +U+6B43(0);U+6B43(5); +U+6B44(0);U+6B44(0); +U+6B45(0);U+6B45(0); +U+6B46(0);U+6B46(5); +U+6B47(0);U+6B47(5); +U+6B48(0);U+6B48(0); +U+6B49(0);U+6B49(5); +U+6B4A(0);U+6B4A(3); +U+6B4B(0);U+6B4B(0); +U+6B4C(0);U+6B4C(5); +U+6B4D(0);U+6B4D(3); +U+6B4E(0);U+53F9(4);U+53F9(4),U+5606(1,3,4) +U+6B4F(0);U+6B4F(0); +U+6B50(0);U+6B27(1,3);U+6B27(1,3) +U+6B51(0);U+6B51(0); +U+6B52(0);U+6B52(0); +U+6B53(0);U+6B22(3);U+6B22(3),U+6B61(3),U+61FD(0,3,4),U+8B99(3,4),U+9A69(3,4) +U+6B54(0);U+6B54(4); +U+6B55(0);U+55B7(3);U+55B7(3),U+5674(1,3) +U+6B56(0);U+6B56(0); +U+6B59(0);U+6B59(5); +U+6B5A(0);U+6B5A(0); +U+6B5B(0);U+655B(3);U+655B(3),U+6582(2,3) +U+6B5C(0);U+6B5C(0); +U+6B5E(0);U+6B5E(0); +U+6B5F(0);U+6B24(1,3);U+6B24(1,3) +U+6B60(0);U+6B60(4); +U+6B61(0);U+6B22(1,3);U+61FD(2,3),U+6B22(1,3),U+6B53(3),U+8B99(2),U+9A69(2) +U+6B62(0);U+6B62(5); +U+6B63(0);U+6B63(5); +U+6B64(0);U+6B64(5); +U+6B65(0);U+6B65(5);U+6B69(4) +U+6B66(0);U+6B66(5); +U+6B67(0);U+6B67(5);U+5C90(3) +U+6B69(0);U+6B65(4);U+6B65(4) +U+6B6A(0);U+6B6A(5); +U+6B6B(0);U+6B6B(0); +U+6B6D(0);U+6B6D(0); +U+6B6F(0);U+9F7F(3);U+9F52(3),U+9F7F(3) +U+6B70(0);U+6B70(0); +U+6B72(0);U+5C81(1,3);U+4E97(3),U+5C81(1,3),U+6B73(4) +U+6B73(0);U+5C81(4);U+4E97(7),U+5C81(4),U+6B72(4) +U+6B74(0);U+5386(2,3);U+5386(2,3),U+6B77(2,3),U+53A4(2,3,4),U+66A6(2,3,4),U+66C6(1,2,3) + +U+6B76(0);U+6B76(0); +U+6B77(0);U+5386(1,3);U+5386(1,3),U+66C6(3,4),U+6B74(2,3),U+53A4(1,3,4),U+66A6(1,3,4) + +U+6B78(0);U+5F52(1,3);U+5E30(3),U+5F52(1,3),U+7688(3) +U+6B79(0);U+6B79(5);U+6B7A(3) +U+6B7A(0);U+6B79(3);U+6B79(3) +U+6B7B(0);U+6B7B(5); +U+6B7C(0);U+6B7C(1,3);U+6BB2(1,3) +U+6B7E(0);U+6B7E(4); +U+6B7F(0);U+6B81(4);U+6B81(4) +U+6B80(0);U+592D(2,3);U+592D(2,3) + +U+6B81(0);U+6B81(5);U+6B7F(4) +U+6B82(0);U+6B82(5); +U+6B83(0);U+6B83(5); +U+6B84(0);U+6B84(5); +U+6B85(0);U+6B85(0); +U+6B86(0);U+6B86(5); +U+6B87(0);U+6B87(1,3);U+6BA4(1,3) +U+6B88(0);U+6B88(0); +U+6B89(0);U+6B89(5); +U+6B8A(0);U+6B8A(5); +U+6B8B(0);U+6B8B(1,3);U+6B98(1,3) +U+6B8C(0);U+6B8C(0); +U+6B8D(0);U+6B8D(5); +U+6B8E(0);U+6B8E(0); +U+6B8F(0);U+6B8F(0); +U+6B90(0);U+6B90(0); +U+6B91(0);U+6B91(0); +U+6B92(0);U+6B92(1,3);U+6B9E(1,3) +U+6B93(0);U+6B93(1,3);U+6BAE(1,3) +U+6B94(0);U+6B94(0); +U+6B95(0);U+8E23(3);U+8E23(3) +U+6B96(0);U+6B96(5); +U+6B97(0);U+6B97(3); +U+6B98(0);U+6B8B(1,3);U+6B8B(1,3) +U+6B99(0);U+6B99(0); +U+6B9A(0);U+6B9A(1,3);U+6BAB(1,3) +U+6B9B(0);U+6B9B(5); +U+6B9C(0);U+6B9C(0); +U+6B9D(0);U+6B9D(0); +U+6B9E(0);U+6B92(1,3);U+6B92(1,3) +U+6B9F(0);U+6B9F(0); +U+6BA0(0);U+81ED(3);U+81ED(3) +U+6BA1(0);U+6BA1(1,3);U+6BAF(1,3) +U+6BA2(0);U+6BA2(0); +U+6BA3(0);U+6BA3(0); +U+6BA4(0);U+6B87(1,3);U+6B87(1,3) +U+6BA5(0);U+6BA5(0); +U+6BA6(0);U+6BA6(0); +U+6BA7(0);U+6BA7(0); +U+6BA8(0);U+3C6E(1,3);U+3C6E(1,3) +U+6BA9(0);U+6BA9(0); +U+6BAA(0);U+6BAA(5); +U+6BAB(0);U+6B9A(1,3);U+6B9A(1,3) +U+6BAC(0);U+6BAC(3); +U+6BAD(0);U+50F5(2,3);U+50F5(2,3) +U+6BAE(0);U+6B93(1,3);U+6B93(1,3) +U+6BAF(0);U+6BA1(1,3);U+6BA1(1,3) +U+6BB0(0);U+6BB0(0); +U+6BB2(0);U+6B7C(1,3);U+6B7C(1,3) +U+6BB3(0);U+6BB3(5);U+6778(3) +U+6BB4(0);U+6BB4(1,3);U+6BC6(1,3) +U+6BB5(0);U+6BB5(5); +U+6BB6(0);U+6BB6(0); +U+6BB7(0);U+6BB7(5);U+6147(2,3) +U+6BB9(0);U+6BB9(0); +U+6BBA(0);U+6740(1,3);U+6740(1,3),U+95B7(1,3) +U+6BBB(0);U+58F3(1,3);U+58F3(1,3),U+6BBC(3) +U+6BBC(0);U+58F3(4);U+58F3(4),U+6BBB(3) +U+6BBD(0);U+6BBD(0); +U+6BBE(0);U+6BBE(0); +U+6BBF(0);U+6BBF(5); +U+6BC0(0);U+6BC1(4);U+6BC1(4),U+8B6D(2,3,4) +U+6BC1(0);U+6BC1(5);U+6BC0(4),U+8B6D(2,3) + +U+6BC2(0);U+6BC2(1,3);U+8F42(1,3),U+8EF2(1,3,9),U+8F71(1,3,4) +U+6BC3(0);U+6572(3);U+6572(3) +U+6BC4(0);U+6BC4(0); +U+6BC5(0);U+6BC5(5); +U+6BC6(0);U+6BB4(1,3);U+6BB4(1,3) +U+6BC7(0);U+6BC7(0); +U+6BC8(0);U+6BC8(3); +U+6BC9(0);U+533B(3);U+533B(3),U+91AB(1,3) +U+6BCA(0);U+6BCA(0); +U+6BCB(0);U+6BCB(5); +U+6BCC(0);U+6BCC(0); +U+6BCD(0);U+6BCD(5); +U+6BCE(0);U+6BCF(4);U+6BCF(4) +U+6BCF(0);U+6BCF(5);U+6BCE(4) +U+6BD0(0);U+6BD0(0); +U+6BD1(0);U+6BD1(0); +U+6BD2(0);U+6BD2(5); +U+6BD3(0);U+6BD3(5); +U+6BD4(0);U+6BD4(5); +U+6BD5(0);U+6BD5(1,3);U+7562(1,3),U+7F7C(3),U+93CE(3) +U+6BD6(0);U+6BD6(5); +U+6BD7(0);U+6BD7(5);U+6BD8(2,3) +U+6BD8(0);U+6BD7(2,3);U+6BD7(2,3) +U+6BD9(0);U+6BD9(1,3);U+6583(1,3) +U+6BDA(0);U+6BDA(0); +U+6BDB(0);U+6BDB(5); +U+6BDC(0);U+6BDC(0); +U+6BDD(0);U+6BDD(0); +U+6BDE(0);U+6BDE(3); +U+6BDF(0);U+6BDF(0); +U+6BE0(0);U+8888(3);U+8888(3) +U+6BE1(0);U+6BE1(1,3);U+6C08(1,3) +U+6BE2(0);U+6BE2(0); +U+6BE3(0);U+6BE3(0); +U+6BE4(0);U+6BFB(3);U+6BFB(3) +U+6BE5(0);U+6BE5(0); +U+6BE6(0);U+6BE6(0); +U+6BE7(0);U+7ED2(2);U+7ED2(2),U+7D68(1,2,3),U+7FA2(2) +U+6BE8(0);U+6BE8(0); +U+6BEA(0);U+6BEA(5); +U+6BEB(0);U+6BEB(5); +U+6BEC(0);U+7403(2,3);U+7403(2,3) +U+6BED(0);U+6BED(0); +U+6BEE(0);U+6BEE(0); +U+6BEF(0);U+6BEF(5); +U+6BF0(0);U+6BF0(0); +U+6BF2(0);U+6BF2(0); +U+6BF3(0);U+6BF3(5); +U+6BF5(0);U+6BF5(1,3);U+6BFF(1,3) +U+6BF6(0);U+6BF6(0); +U+6BF7(0);U+6BF7(0); +U+6BF8(0);U+6BF8(0); +U+6BF9(0);U+6BF9(5); +U+6BFB(0);U+6BFB(3);U+6BE4(3) +U+6BFC(0);U+6BFC(0); +U+6BFD(0);U+6BFD(5); +U+6BFE(0);U+6BFE(0); +U+6BFF(0);U+6BF5(1,3);U+6BF5(1,3) +U+6C00(0);U+6C00(0); +U+6C01(0);U+6C01(0); +U+6C02(0);U+7266(2,3);U+7266(2,3),U+729B(2,3),U+9AE6(2,3) +U+6C03(0);U+6C03(0); +U+6C04(0);U+6C04(0); + +U+6C05(0);U+6C05(5); +U+6C06(0);U+6C06(5); +U+6C07(0);U+6C07(1,3);U+6C0C(1,3) +U+6C08(0);U+6BE1(1,3);U+6BE1(1,3) +U+6C09(0);U+6C09(0); +U+6C0B(0);U+6C0B(0); +U+6C0C(0);U+6C07(1,3);U+6C07(1,3) +U+6C0D(0);U+6C0D(5); +U+6C0E(0);U+6C0E(0); +U+6C0F(0);U+6C0F(5); +U+6C10(0);U+6C10(5); +U+6C11(0);U+6C11(5); +U+6C12(0);U+6C12(0); +U+6C13(0);U+6C13(5);U+753F(4) +U+6C14(0);U+6C14(1,3);U+6C23(1,3) +U+6C15(0);U+6C15(5); +U+6C16(0);U+6C16(5); +U+6C18(0);U+6C18(5); +U+6C19(0);U+6C19(5); +U+6C1A(0);U+6C1A(5); +U+6C1B(0);U+6C1B(5);U+96F0(2,3) +U+6C1D(0);U+6C1D(0); +U+6C1E(0);U+6C1E(0); +U+6C1F(0);U+6C1F(5); +U+6C20(0);U+6C20(0); +U+6C21(0);U+6C21(5); +U+6C22(0);U+6C22(1,3);U+6C2B(1,3) +U+6C23(0);U+6C14(1,3);U+6C14(1,3) +U+6C24(0);U+6C24(5); +U+6C25(0);U+6C25(0); +U+6C26(0);U+6C26(5); +U+6C27(0);U+6C27(5); +U+6C28(0);U+6C28(5); +U+6C29(0);U+6C29(1,3);U+6C2C(1,3) +U+6C2A(0);U+6C2A(5); +U+6C2B(0);U+6C22(1,3);U+6C22(1,3) +U+6C2C(0);U+6C29(1,3);U+6C29(1,3) +U+6C2E(0);U+6C2E(5); +U+6C2F(0);U+6C2F(5); +U+6C30(0);U+6C30(5); +U+6C31(0);U+6C31(0); +U+6C32(0);U+6C32(5);U+6C33(4) +U+6C33(0);U+6C32(4);U+6C32(4) +U+6C34(0);U+6C34(5); +U+6C35(0);U+6C35(5); +U+6C36(0);U+6C36(0); +U+6C37(0);U+51B0(2,3);U+51B0(2,3) +U+6C38(0);U+6C38(5); +U+6C3A(0);U+6C3A(0); +U+6C3B(0);U+6C3B(0); +U+6C3D(0);U+6C3D(5); +U+6C3E(0);U+6CDB(2,3);U+6C4E(3),U+6CDB(2,3) +U+6C3F(0);U+6C3F(3); +U+6C40(0);U+6C40(5); +U+6C41(0);U+6C41(5); +U+6C42(0);U+6C42(5); +U+6C43(0);U+6C43(0); +U+6C44(0);U+6C44(0); +U+6C46(0);U+6C46(5); +U+6C47(0);U+6C47(1,3);U+532F(1,3),U+5F59(1,3),U+5F5A(4),U+6ED9(4) +U+6C48(0);U+6C48(0); +U+6C49(0);U+6C49(1,3);U+6F22(1,3) +U+6C4A(0);U+6C4A(5); + +U+6C4B(0);U+6C4B(0); +U+6C4C(0);U+6C4C(0); +U+6C4D(0);U+6C4D(0); +U+6C4E(0);U+6CDB(2,3);U+6C3E(3),U+6CDB(2,3) +U+6C4F(0);U+6C70(3);U+6C70(3),U+6E99(3) +U+6C50(0);U+6C50(5); +U+6C51(0);U+6C51(0); +U+6C52(0);U+832B(3);U+832B(3) +U+6C53(0);U+6C53(0); +U+6C54(0);U+6C54(5); +U+6C55(0);U+6C55(5); +U+6C56(0);U+6C56(0); +U+6C57(0);U+6C57(5); +U+6C58(0);U+6C58(0); +U+6C59(0);U+6C61(2,3);U+6C5A(3),U+6C61(2,3) +U+6C5A(0);U+6C61(2);U+6C59(3),U+6C61(2) +U+6C5B(0);U+6C5B(5); +U+6C5C(0);U+6C5C(5);U+6D0D(4) +U+6C5D(0);U+6C5D(5); +U+6C5E(0);U+6C5E(5); +U+6C5F(0);U+6C5F(5); +U+6C60(0);U+6C60(5); +U+6C61(0);U+6C61(5);U+6C59(2,3),U+6C5A(2) +U+6C62(0);U+6C62(0); +U+6C63(0);U+6C63(0); +U+6C64(0);U+6C64(1,3);U+6E6F(1,3) +U+6C65(0);U+6C65(0); +U+6C66(0);U+6C66(0); +U+6C67(0);U+6C67(0); +U+6C68(0);U+6C68(5); +U+6C69(0);U+6C69(5); +U+6C6A(0);U+6C6A(5);U+7007(3) +U+6C6B(0);U+6C6B(0); +U+6C6D(0);U+6C6D(0); +U+6C6F(0);U+6C6F(0); +U+6C70(0);U+6C70(5);U+6C4F(3),U+6E99(3) +U+6C71(0);U+6C71(0); +U+6C72(0);U+6C72(5); +U+6C73(0);U+6C73(0); +U+6C74(0);U+6C74(5); +U+6C75(0);U+6C75(0); +U+6C76(0);U+6C76(5); +U+6C77(0);U+6C77(0); +U+6C78(0);U+6C78(3);U+6DD3(3) +U+6C79(0);U+6C79(5);U+6D36(2,3) +U+6C7A(0);U+51B3(2,3);U+51B3(2,3) +U+6C7B(0);U+6D52(3);U+6D52(3),U+6EF8(1,3) +U+6C7C(0);U+6C7C(0); +U+6C7D(0);U+6C7D(5);U+6ECA(3) +U+6C7E(0);U+6C7E(5); +U+6C7F(0);U+6C7F(3); +U+6C80(0);U+6C80(0); +U+6C81(0);U+6C81(5); +U+6C82(0);U+6C82(5); +U+6C83(0);U+6C83(5); +U+6C84(0);U+6C84(0); +U+6C85(0);U+6C85(5); +U+6C86(0);U+6C86(5); +U+6C87(0);U+6C87(3); +U+6C88(0);U+6C88(1);U+6C89(3),U+6E16(4),U+700B(1,3) +U+6C89(0);U+6C89(5);U+6C88(3),U+6E16(3,4),U+700B(1,3) +U+6C8A(0);U+6C8A(0); +U+6C8B(0);U+6C8B(0); + +U+6C8C(0);U+6C8C(5); +U+6C8D(0);U+51B1(3);U+51B1(3) +U+6C8E(0);U+6C8E(0); +U+6C8F(0);U+6C8F(5); +U+6C90(0);U+6C90(5); +U+6C91(0);U+6C91(0); +U+6C92(0);U+6CA1(3);U+6CA1(3) +U+6C93(0);U+6C93(5); +U+6C94(0);U+6C94(5); +U+6C95(0);U+6C95(0); +U+6C96(0);U+51B2(3,4);U+51B2(3,4),U+76C5(3),U+885D(3,4),U+794C(3,4),U+8876(3,4) +U+6C97(0);U+6C97(0); +U+6C98(0);U+6C98(0); +U+6C99(0);U+6C99(5); +U+6C9A(0);U+6C9A(3); +U+6C9B(0);U+6C9B(5);U+4F02(3) +U+6C9C(0);U+6C9C(3); +U+6C9D(0);U+6C9D(0); +U+6C9E(0);U+6C9E(0); +U+6C9F(0);U+6C9F(1,3);U+6E9D(1,3) +U+6CA1(0);U+6CA1(5);U+6C92(3) +U+6CA2(0);U+6CFD(4);U+6CFD(4),U+6FA4(4) +U+6CA3(0);U+6CA3(1,3);U+7043(1,3) +U+6CA4(0);U+6CA4(1,3);U+6F1A(1,3) +U+6CA5(0);U+6CA5(1,3);U+701D(1,3) +U+6CA6(0);U+6CA6(1,3);U+6DEA(1,3) +U+6CA7(0);U+6CA7(1,3);U+6EC4(1,3) +U+6CA8(0);U+6CA8(1,3);U+6E22(1,3) +U+6CA9(0);U+6CA9(1,3,4);U+6E88(4),U+6F59(1,3) +U+6CAA(0);U+6CAA(1,3);U+6EEC(1,3) +U+6CAB(0);U+6CAB(5); +U+6CAC(0);U+6CAC(3); +U+6CAD(0);U+6CAD(5); +U+6CAE(0);U+6CAE(5); +U+6CAF(0);U+6CAF(0); +U+6CB0(0);U+6CB0(0); +U+6CB1(0);U+6CB1(5);U+6CB2(3) +U+6CB2(0);U+6CB2(5);U+6CB1(3) +U+6CB3(0);U+6CB3(5); +U+6CB4(0);U+6CB4(3); +U+6CB5(0);U+6CB5(4);U+6FD4(4) +U+6CB6(0);U+6CB6(0); +U+6CB7(0);U+6CB7(0); +U+6CB8(0);U+6CB8(5); +U+6CB9(0);U+6CB9(5); +U+6CBA(0);U+6CBA(0); +U+6CBB(0);U+6CBB(5); +U+6CBC(0);U+6CBC(5); +U+6CBD(0);U+6CBD(5); +U+6CBE(0);U+6CBE(5);U+9711(2,3) +U+6CBF(0);U+6CBF(5); +U+6CC0(0);U+6CC0(0); +U+6CC1(0);U+51B5(2,4);U+51B5(2,4) +U+6CC2(0);U+6CC2(0); +U+6CC3(0);U+6CC3(0); +U+6CC4(0);U+6CC4(5);U+6D29(2,3),U+6E2B(3) +U+6CC5(0);U+6CC5(5); +U+6CC6(0);U+6CC6(3); +U+6CC7(0);U+6CC7(0); +U+6CC8(0);U+6CC8(0); +U+6CC9(0);U+6CC9(5); +U+6CCA(0);U+6CCA(5);U+6FFC(3),U+6CFA(1,3) +U+6CCB(0);U+6CCB(0); + +U+6CCC(0);U+6CCC(5); +U+6CCD(0);U+6CCD(0); +U+6CCE(0);U+6CCE(0); +U+6CCF(0);U+6CCF(0); +U+6CD0(0);U+6CD0(5); +U+6CD1(0);U+6CD1(0); +U+6CD2(0);U+6D3E(4);U+6D3E(4) +U+6CD3(0);U+6CD3(5); +U+6CD4(0);U+6CD4(5); +U+6CD5(0);U+6CD5(5); +U+6CD6(0);U+6CD6(5); +U+6CD7(0);U+6CD7(5); +U+6CD9(0);U+6CD9(0); +U+6CDA(0);U+6CDA(0); +U+6CDB(0);U+6CDB(5);U+6C3E(2,3),U+6C4E(2,3) +U+6CDC(0);U+6CDC(0); +U+6CDD(0);U+6EAF(3,4);U+6EAF(3,4),U+9061(3) +U+6CDE(0);U+6CDE(1,3);U+6FD8(1,3) +U+6CDF(0);U+6CDF(0); +U+6CE0(0);U+6CE0(5);U+6FAA(3) +U+6CE1(0);U+6CE1(5); +U+6CE2(0);U+6CE2(5); +U+6CE3(0);U+6CE3(5); +U+6CE4(0);U+6CE4(0); +U+6CE5(0);U+6CE5(5); +U+6CE6(0);U+6CE6(3);U+6DD7(3) +U+6CE7(0);U+6CE7(0); +U+6CE8(0);U+6CE8(5);U+8A3B(2,3) +U+6CE9(0);U+6CE9(0); +U+6CEA(0);U+6CEA(5);U+6D99(4),U+6DDA(2,3) +U+6CEB(0);U+6CEB(5); +U+6CEC(0);U+6CEC(0); +U+6CED(0);U+6874(3);U+6874(3) +U+6CEE(0);U+6CEE(5); +U+6CEF(0);U+6CEF(5); +U+6CF0(0);U+6CF0(5); +U+6CF1(0);U+6CF1(5); +U+6CF2(0);U+6CF2(0); +U+6CF3(0);U+6CF3(5); +U+6CF5(0);U+6CF5(5); +U+6CF6(0);U+6CF6(5);U+6FA9(4) +U+6CF7(0);U+6CF7(1,3);U+7027(1,3) +U+6CF8(0);U+6CF8(1,3);U+7018(1,3) +U+6CF9(0);U+6CF9(0); +U+6CFA(0);U+6CFA(1,3);U+6FFC(1,3),U+6CCA(1,3,5) +U+6CFB(0);U+6CFB(1,3);U+7009(1,3) +U+6CFC(0);U+6CFC(1,3);U+6F51(1,3) +U+6CFD(0);U+6CFD(1,3);U+6CA2(4),U+6FA4(1,3) +U+6CFE(0);U+6CFE(1,3);U+6D87(1,3) +U+6CFF(0);U+6CFF(0); +U+6D00(0);U+76D8(3);U+76D8(3),U+76E4(1,3) +U+6D01(0);U+6D01(1,3);U+6D2F(2,3),U+6F54(1,3) +U+6D03(0);U+6D03(0); +U+6D04(0);U+6D04(5); +U+6D05(0);U+6D05(0); +U+6D06(0);U+6D06(0); +U+6D07(0);U+6D07(5); +U+6D08(0);U+6D08(0); +U+6D09(0);U+6D09(0); +U+6D0A(0);U+6D0A(0); +U+6D0B(0);U+6D0B(5); +U+6D0C(0);U+6D0C(5);U+51BD(3) +U+6D0D(0);U+6C5C(4);U+6C5C(4) + +U+6D0E(0);U+6D0E(5); +U+6D0F(0);U+6D0F(3); +U+6D10(0);U+6D10(0); +U+6D11(0);U+6D11(3); +U+6D12(0);U+6D12(1,3);U+7051(1,3) +U+6D13(0);U+6D13(0); +U+6D14(0);U+6D14(0); +U+6D15(0);U+6D15(0); +U+6D16(0);U+6D16(0); +U+6D17(0);U+6D17(5); +U+6D18(0);U+6D18(0); +U+6D19(0);U+6D19(5); +U+6D1A(0);U+6D1A(5); +U+6D1B(0);U+6D1B(5); +U+6D1D(0);U+6D1D(0); +U+6D1E(0);U+6D1E(5); +U+6D1F(0);U+6D1F(0); +U+6D20(0);U+6D20(0); +U+6D21(0);U+6D21(0); +U+6D22(0);U+4F0A(3);U+4F0A(3) +U+6D23(0);U+6D23(0); +U+6D25(0);U+6D25(5); +U+6D26(0);U+6D26(4); +U+6D27(0);U+6D27(5); +U+6D28(0);U+6D28(0); +U+6D29(0);U+6CC4(2,3);U+6CC4(2,3),U+6E2B(2,3) +U+6D2A(0);U+6D2A(5); +U+6D2B(0);U+6D2B(5); +U+6D2C(0);U+6D2C(0); +U+6D2D(0);U+6D2D(0); +U+6D2E(0);U+6D2E(5); +U+6D2F(0);U+6D01(2,3);U+6D01(2,3),U+6F54(1,2,3) +U+6D30(0);U+6D30(0); +U+6D31(0);U+6D31(5); +U+6D32(0);U+6D32(5); +U+6D33(0);U+6D33(5); +U+6D34(0);U+6D34(0); +U+6D35(0);U+6D35(5); +U+6D36(0);U+6C79(2,3);U+6C79(2,3) +U+6D37(0);U+6D37(0); +U+6D38(0);U+6D38(3); +U+6D39(0);U+6D39(5); +U+6D3A(0);U+6D3A(0); +U+6D3B(0);U+6D3B(5); +U+6D3C(0);U+6D3C(1,3);U+6F25(3),U+7AAA(1,3) +U+6D3D(0);U+6D3D(5);U+51BE(3) +U+6D3E(0);U+6D3E(5);U+6CD2(4) +U+6D3F(0);U+6D3F(3); +U+6D40(0);U+6D40(0); +U+6D41(0);U+6D41(5); +U+6D42(0);U+6D42(0); +U+6D43(0);U+6D43(1,3);U+6D79(1,3) +U+6D44(0);U+51C0(2,4);U+51C0(2,4),U+6DE8(8,9),U+51C8(2,4) +U+6D45(0);U+6D45(1,3);U+6DFA(1,3) +U+6D46(0);U+6D46(1,3);U+6F3F(1,3) +U+6D47(0);U+6D47(1,3);U+6F86(1,3) +U+6D48(0);U+6D48(1,3);U+6E5E(1,3) +U+6D49(0);U+6D49(1,3);U+6EAE(1,3) +U+6D4A(0);U+6D4A(1,3);U+6FC1(1,3) +U+6D4B(0);U+6D4B(1,3);U+6E2C(1,3) +U+6D4C(0);U+6D4C(0); +U+6D4D(0);U+6D4D(1,3);U+6FAE(1,3) +U+6D4E(0);U+6D4E(1,3);U+6E08(3),U+6FDF(1,3) + +U+6D4F(0);U+6D4F(1,3);U+56A0(4),U+700F(1,3) +U+6D50(0);U+6D50(1,3);U+6EFB(1,3) +U+6D51(0);U+6D51(1,3);U+6E3E(1,3) +U+6D52(0);U+6D52(1,3);U+6C7B(3),U+6EF8(1,3) +U+6D53(0);U+6D53(1,3);U+6FC3(1,3) +U+6D54(0);U+6D54(1,3);U+6F6F(1,3) +U+6D55(0);U+6D55(1,3);U+6FDC(1,3) +U+6D56(0);U+6D56(0); +U+6D57(0);U+6D57(0); +U+6D58(0);U+6D58(0); +U+6D59(0);U+6D59(5);U+6DDB(2,3) +U+6D5A(0);U+6D5A(5);U+6FEC(2) +U+6D5B(0);U+6D5B(3); +U+6D5C(0);U+6D5C(5);U+6FF1(3),U+6EE8(1,3) +U+6D5D(0);U+6D5D(0); +U+6D5E(0);U+6D5E(5); +U+6D5F(0);U+6D5F(0); +U+6D60(0);U+6D60(5); +U+6D61(0);U+6D61(0); +U+6D62(0);U+6D62(0); +U+6D63(0);U+6D63(5);U+6FA3(2,3) +U+6D64(0);U+6D64(3); +U+6D65(0);U+6D65(3); +U+6D66(0);U+6D66(5); +U+6D67(0);U+6D67(0); +U+6D68(0);U+6D68(0); +U+6D69(0);U+6D69(5);U+6F94(3) +U+6D6A(0);U+6D6A(5); +U+6D6B(0);U+6D6B(0); +U+6D6C(0);U+6D6C(0); +U+6D6D(0);U+6D6D(0); +U+6D6E(0);U+6D6E(5); +U+6D6F(0);U+6D6F(5); +U+6D70(0);U+6D70(0); +U+6D72(0);U+6D72(0); +U+6D73(0);U+6D73(0); +U+6D74(0);U+6D74(5); +U+6D75(0);U+6D75(0); +U+6D76(0);U+6D76(0); +U+6D77(0);U+6D77(5); +U+6D78(0);U+6D78(5); +U+6D79(0);U+6D43(1,3);U+6D43(1,3) +U+6D7A(0);U+6D7A(0); +U+6D7B(0);U+6D7B(0); +U+6D7C(0);U+6D7C(5); +U+6D7D(0);U+6D7D(3); +U+6D7E(0);U+6D7E(3); +U+6D7F(0);U+6D7F(0); +U+6D80(0);U+6D80(0); +U+6D82(0);U+6D82(1,3);U+51C3(3),U+5857(1,3,4) +U+6D83(0);U+6D83(0); +U+6D84(0);U+6D84(0); +U+6D85(0);U+6D85(5); +U+6D86(0);U+6D86(0); +U+6D87(0);U+6CFE(1,3);U+6CFE(1,3) +U+6D88(0);U+6D88(5); +U+6D89(0);U+6D89(5);U+6E09(4) +U+6D8A(0);U+6D8A(0); +U+6D8B(0);U+6D8B(0); +U+6D8C(0);U+6D8C(5);U+6E67(2,3) +U+6D8D(0);U+6D8D(0); +U+6D8E(0);U+6D8E(5); +U+6D8F(0);U+6D8F(0); + +U+6D90(0);U+6D90(0); +U+6D91(0);U+6D91(5); +U+6D92(0);U+6D92(3); +U+6D93(0);U+6D93(5); +U+6D94(0);U+6D94(5); +U+6D95(0);U+6D95(5); +U+6D97(0);U+6D9A(4);U+6D9A(4) +U+6D98(0);U+6D98(0); +U+6D99(0);U+6CEA(4);U+6CEA(4),U+6DDA(4) +U+6D9A(0);U+6D9A(4);U+6D97(4) +U+6D9B(0);U+6D9B(1,3);U+6FE4(1,3) +U+6D9D(0);U+6D9D(1,3);U+6F87(1,3) +U+6D9E(0);U+6D9E(1,3);U+6DF6(1,3) +U+6D9F(0);U+6D9F(1,3);U+6F23(1,3) +U+6DA0(0);U+6DA0(1,3);U+6F7F(1,3) +U+6DA1(0);U+6DA1(1,3);U+6E26(1,3),U+6FC4(3) +U+6DA2(0);U+6DA2(1,3);U+6EB3(1,3) +U+6DA3(0);U+6DA3(4);U+6E19(4) +U+6DA4(0);U+6DA4(1,3);U+6ECC(1,3) +U+6DA5(0);U+6DA5(0); +U+6DA6(0);U+6DA6(1,3);U+6F64(1,3) +U+6DA7(0);U+6DA7(1,3);U+6F97(1,3) +U+6DA8(0);U+6DA8(1,3);U+6F32(1,3) +U+6DA9(0);U+6DA9(1,3);U+6E0B(4),U+6F80(1,3),U+6F81(3),U+6FC7(2),U+7012(3) +U+6DAA(0);U+6DAA(5); +U+6DAB(0);U+6DAB(5); +U+6DAC(0);U+6DAC(0); +U+6DAD(0);U+6DAD(0); +U+6DAE(0);U+6DAE(5); +U+6DAF(0);U+6DAF(5); +U+6DB2(0);U+6DB2(5); +U+6DB3(0);U+6DB3(0); +U+6DB4(0);U+6DB4(0); +U+6DB5(0);U+6DB5(5); +U+6DB7(0);U+6DB7(0); +U+6DB8(0);U+6DB8(5); +U+6DB9(0);U+6DB9(0); +U+6DBA(0);U+6DBA(0); +U+6DBB(0);U+6DBB(0); +U+6DBC(0);U+51C9(2,3);U+51C9(2,3) +U+6DBD(0);U+6DBD(4); +U+6DBE(0);U+6DBE(0); +U+6DBF(0);U+6DBF(5); +U+6DC0(0);U+6DC0(1,3);U+6FB1(1,3) +U+6DC1(0);U+6DC1(0); +U+6DC2(0);U+6DC2(0); +U+6DC3(0);U+6DC3(0); +U+6DC4(0);U+6DC4(5); +U+6DC5(0);U+6DC5(5); +U+6DC6(0);U+6DC6(5); +U+6DC7(0);U+6DC7(5); +U+6DC8(0);U+6DC8(0); +U+6DC9(0);U+6DC9(0); +U+6DCA(0);U+6DCA(0); +U+6DCB(0);U+6DCB(5);U+75F3(2,3),U+9EBB(2,3,4),U+75F2(0,2,3,4,5),U+8534(2,3,4,5) +U+6DCC(0);U+6DCC(5); +U+6DCD(0);U+6DCD(0); +U+6DCE(0);U+6DCE(0); +U+6DCF(0);U+6DCF(0); +U+6DD0(0);U+6DD0(0); +U+6DD1(0);U+6DD1(5); +U+6DD2(0);U+51C4(2,3);U+51C4(2,3),U+60BD(2,3) +U+6DD3(0);U+6C78(3);U+6C78(3) + +U+6DD4(0);U+6DD4(0); +U+6DD5(0);U+6DD5(0); +U+6DD6(0);U+6DD6(5); +U+6DD7(0);U+6CE6(3);U+6CE6(3) +U+6DD8(0);U+6DD8(5); +U+6DD9(0);U+6DD9(5); +U+6DDA(0);U+6CEA(2,3);U+6CEA(2,3),U+6D99(4) +U+6DDB(0);U+6D59(2,3);U+6D59(2,3) +U+6DDC(0);U+6DDC(0); +U+6DDD(0);U+6DDD(5); +U+6DDE(0);U+6DDE(5); +U+6DDF(0);U+6DDF(0); +U+6DE0(0);U+6DE0(5); +U+6DE1(0);U+6DE1(5);U+6FB9(4) +U+6DE2(0);U+6DE2(0); +U+6DE3(0);U+502A(3);U+502A(3) +U+6DE4(0);U+6DE4(5); +U+6DE5(0);U+6E0C(4);U+6E0C(4) +U+6DE6(0);U+6DE6(5); +U+6DE7(0);U+6DE7(0); +U+6DE8(0);U+51C0(4);U+51C0(4),U+6D44(8,9),U+51C8(3,4) +U+6DE9(0);U+51CC(3);U+51CC(3) +U+6DEA(0);U+6CA6(1,3);U+6CA6(1,3) +U+6DEB(0);U+6DEB(5);U+5A6C(2,3) +U+6DEC(0);U+6DEC(5); +U+6DED(0);U+6DED(0); +U+6DEE(0);U+6DEE(5); +U+6DEF(0);U+6DEF(0); +U+6DF0(0);U+6DF0(0); +U+6DF1(0);U+6DF1(5); +U+6DF2(0);U+6DF2(0); +U+6DF3(0);U+6DF3(5); +U+6DF4(0);U+6DF4(0); +U+6DF5(0);U+6E0A(1,3);U+6E0A(1,3),U+6E15(4),U+7041(1,3,4) +U+6DF6(0);U+6D9E(1,3);U+6D9E(1,3) +U+6DF7(0);U+6DF7(5); +U+6DF8(0);U+6E05(4);U+6E05(4),U+51CA(0,4) +U+6DF9(0);U+6DF9(5); +U+6DFA(0);U+6D45(1,3);U+6D45(1,3) +U+6DFB(0);U+6DFB(5); +U+6DFC(0);U+6DFC(5); +U+6DFD(0);U+6DFD(0); +U+6E00(0);U+6E00(0); +U+6E03(0);U+6E03(0); +U+6E04(0);U+6E04(0); +U+6E05(0);U+6E05(5);U+51CA(4),U+6DF8(4) +U+6E07(0);U+6E34(3);U+6E34(3) +U+6E08(0);U+6D4E(3);U+6D4E(3),U+6FDF(3) +U+6E09(0);U+6D89(4);U+6D89(4) +U+6E0A(0);U+6E0A(1,3);U+6DF5(1,3),U+6E15(4),U+7041(3,4) +U+6E0B(0);U+6DA9(4);U+6DA9(4),U+6F80(4),U+6F81(3,4),U+6FC7(2,4),U+7012(3,4) +U+6E0C(0);U+6E0C(5);U+6DE5(4) +U+6E0D(0);U+6E0D(1,3);U+6F2C(1,3) +U+6E0E(0);U+6E0E(1,3);U+7006(1,3) +U+6E0F(0);U+6E0F(0); +U+6E10(0);U+6E10(1,3);U+5DC9(4),U+6F38(1,3) +U+6E11(0);U+6E11(1,3);U+6FA0(1,3) +U+6E14(0);U+6E14(1,3);U+6F01(1,3) +U+6E15(0);U+6E0A(4);U+6DF5(4),U+6E0A(4),U+7041(1,3,4) +U+6E16(0);U+6C88(4);U+6C88(4),U+700B(4),U+6C89(3,4) +U+6E17(0);U+6E17(1,3);U+6EF2(1,3) +U+6E19(0);U+6DA3(4);U+6DA3(4) +U+6E1A(0);U+6E1A(5); + +U+6E1B(0);U+51CF(2,3);U+51CF(2,3) +U+6E1C(0);U+6E1C(3); +U+6E1D(0);U+6E1D(5); +U+6E1E(0);U+6E1E(0); +U+6E1F(0);U+6E1F(0); +U+6E20(0);U+6E20(5); +U+6E21(0);U+6E21(5); +U+6E22(0);U+6CA8(1,3);U+6CA8(1,3) +U+6E23(0);U+6E23(5); +U+6E24(0);U+6E24(5);U+90E3(3) +U+6E25(0);U+6E25(5); +U+6E26(0);U+6DA1(1,3);U+6DA1(1,3),U+6FC4(1,3) +U+6E27(0);U+6E27(0); +U+6E28(0);U+6E28(0); +U+6E29(0);U+6E29(5);U+6EAB(3) +U+6E2B(0);U+6E2B(5);U+6CC4(3),U+6D29(2,3) +U+6E2C(0);U+6D4B(1,3);U+6D4B(1,3) +U+6E2D(0);U+6E2D(5); +U+6E2E(0);U+83CF(3);U+83CF(3) +U+6E2F(0);U+6E2F(5); +U+6E30(0);U+6E30(3); +U+6E31(0);U+6E31(0); +U+6E32(0);U+6E32(5); +U+6E33(0);U+6E33(0); +U+6E34(0);U+6E34(5);U+6E07(3) +U+6E35(0);U+6E35(0); +U+6E36(0);U+6E36(0); +U+6E37(0);U+6E37(0); +U+6E38(0);U+6E38(5);U+9030(3),U+904A(2,3) +U+6E39(0);U+6E39(0); +U+6E3A(0);U+6E3A(5); +U+6E3B(0);U+6E3B(0); +U+6E3C(0);U+6E3C(0); +U+6E3D(0);U+6E3D(0); +U+6E3E(0);U+6D51(1,3);U+6D51(1,3) +U+6E3F(0);U+6E3F(0); +U+6E40(0);U+6E40(0); +U+6E41(0);U+6E41(0); +U+6E42(0);U+6E42(0); +U+6E43(0);U+6E43(5); +U+6E44(0);U+6E44(5); +U+6E45(0);U+6E45(0); +U+6E46(0);U+6E46(3);U+6E47(3) +U+6E47(0);U+6E46(3);U+6E46(3) +U+6E48(0);U+6E48(0); +U+6E49(0);U+6E49(0); +U+6E4A(0);U+51D1(2,3);U+51D1(2,3) +U+6E4B(0);U+6E4B(0); +U+6E4D(0);U+6E4D(5); +U+6E4E(0);U+6E4E(5); +U+6E4F(0);U+6E4F(0); +U+6E50(0);U+6E50(0); +U+6E51(0);U+6E51(0); +U+6E52(0);U+6E52(0); +U+6E53(0);U+6E53(5); +U+6E54(0);U+6E54(5); +U+6E55(0);U+6E55(0); +U+6E56(0);U+6E56(5); +U+6E57(0);U+6E57(0); +U+6E58(0);U+6E58(5); +U+6E59(0);U+6E59(0); +U+6E5A(0);U+6E5A(0); +U+6E5B(0);U+6E5B(5); + +U+6E5C(0);U+6E5C(0); +U+6E5D(0);U+6E5D(0); +U+6E5E(0);U+6D48(1,3);U+6D48(1,3) +U+6E5F(0);U+6E5F(5); +U+6E60(0);U+6E60(0); +U+6E61(0);U+6E61(0); +U+6E62(0);U+6E62(0); +U+6E63(0);U+6E63(0); +U+6E64(0);U+6E64(0); +U+6E65(0);U+6E65(0); +U+6E66(0);U+6E66(0); +U+6E67(0);U+6D8C(2,3);U+6D8C(2,3) +U+6E68(0);U+6E68(0); +U+6E69(0);U+6E69(0); +U+6E6A(0);U+6E6A(0); +U+6E6B(0);U+6E6B(5); +U+6E6D(0);U+6E6D(0); +U+6E6E(0);U+6E6E(5); +U+6E6F(0);U+6C64(1,3);U+6C64(1,3) +U+6E70(0);U+6E70(3); +U+6E71(0);U+6E71(0); +U+6E72(0);U+6E72(0); +U+6E73(0);U+6E73(0); +U+6E74(0);U+6E74(4); +U+6E75(0);U+6E75(0); +U+6E77(0);U+6E77(0); +U+6E78(0);U+6E78(0); +U+6E79(0);U+6E79(0); +U+6E7E(0);U+6E7E(1,3);U+7063(1,3) +U+6E7F(0);U+6E7F(1,3);U+6EBC(4),U+6FD5(1,3) +U+6E80(0);U+6EE1(4);U+6EE1(4),U+6EFF(4) +U+6E81(0);U+6E81(4);U+6FDA(4) +U+6E82(0);U+6E82(0); +U+6E83(0);U+6E83(1,3);U+6F70(1,3) +U+6E84(0);U+6E84(0); +U+6E85(0);U+6E85(1,3);U+6FFA(1,3) +U+6E86(0);U+6E86(5);U+6F35(4) +U+6E87(0);U+6E87(1,3);U+6F0A(1,3) +U+6E88(0);U+6CA9(4);U+6CA9(4),U+6F59(4) +U+6E89(0);U+6E89(5);U+6F11(4) +U+6E8A(0);U+6E8A(0); +U+6E8D(0);U+6E8D(0); +U+6E8E(0);U+6E8E(0); +U+6E8F(0);U+6E8F(5); +U+6E90(0);U+6E90(5);U+53B5(3) +U+6E91(0);U+6E91(0); +U+6E92(0);U+6E92(0); +U+6E93(0);U+6E93(3); +U+6E94(0);U+6E94(0); +U+6E96(0);U+51C6(1,3);U+51C6(1,3),U+51D6(3) +U+6E97(0);U+6E97(0); +U+6E98(0);U+6E98(5); +U+6E99(0);U+6C70(3);U+6C70(3),U+6C4F(0,3) +U+6E9A(0);U+6E9A(0); +U+6E9B(0);U+6E9B(0); +U+6E9C(0);U+6E9C(5);U+6F91(3) +U+6E9D(0);U+6C9F(1,3);U+6C9F(1,3) +U+6E9E(0);U+6E9E(0); +U+6E9F(0);U+6E9F(5); +U+6EA0(0);U+6EA0(3); +U+6EA1(0);U+6EA1(0); +U+6EA2(0);U+6EA2(5); +U+6EA3(0);U+6EA3(0); + +U+6EA4(0);U+6EA4(0); +U+6EA5(0);U+6EA5(5); +U+6EA6(0);U+6EA6(3);U+973A(3) +U+6EA7(0);U+6EA7(5); +U+6EA8(0);U+6EA8(0); +U+6EA9(0);U+6EA9(0); +U+6EAA(0);U+6EAA(5);U+8C3F(2,3) +U+6EAB(0);U+6E29(3);U+6E29(3) +U+6EAC(0);U+6EAC(0); +U+6EAD(0);U+6EAD(0); +U+6EAE(0);U+6D49(1,3);U+6D49(1,3) +U+6EAF(0);U+6EAF(5);U+6CDD(3,4),U+9061(2,3) +U+6EB0(0);U+6EB0(0); +U+6EB1(0);U+6EB1(5);U+6F67(3) +U+6EB2(0);U+6EB2(5); +U+6EB3(0);U+6DA2(1,3);U+6DA2(1,3) +U+6EB4(0);U+6EB4(5); +U+6EB5(0);U+6EB5(0); +U+6EB6(0);U+6EB6(5); +U+6EB7(0);U+6EB7(5); +U+6EB8(0);U+6EB8(0); +U+6EB9(0);U+6EB9(0); +U+6EBA(0);U+6EBA(5);U+5C3F(3) +U+6EBB(0);U+6EBB(5); +U+6EBC(0);U+6E7F(4);U+6E7F(4),U+6FD5(2,3) +U+6EBD(0);U+6EBD(5); +U+6EBE(0);U+6EBE(0); +U+6EBF(0);U+6EBF(0); +U+6EC0(0);U+6EC0(3); +U+6EC1(0);U+6EC1(5); +U+6EC2(0);U+6EC2(5); +U+6EC3(0);U+6EC3(0); +U+6EC4(0);U+6CA7(1,3);U+6CA7(1,3) +U+6EC5(0);U+706D(1,3);U+706D(1,3) +U+6EC6(0);U+6EC6(0); +U+6EC7(0);U+6EC7(5); +U+6EC8(0);U+6EC8(3); +U+6EC9(0);U+6EC9(3); +U+6ECA(0);U+6C7D(3);U+6C7D(3) +U+6ECB(0);U+6ECB(5); +U+6ECC(0);U+6DA4(1,3);U+6DA4(1,3) +U+6ECD(0);U+6ECD(0); +U+6ECE(0);U+8365(1,3);U+8365(1,3) +U+6ECF(0);U+6ECF(5); +U+6ED0(0);U+6ED0(0); +U+6ED1(0);U+6ED1(5);U+78C6(3) +U+6ED2(0);U+6ED2(0); +U+6ED3(0);U+6ED3(5); +U+6ED4(0);U+6ED4(5); +U+6ED5(0);U+6ED5(5); +U+6ED6(0);U+6ED6(0); +U+6ED7(0);U+6ED7(1,3);U+6F77(1,3) +U+6ED8(0);U+6ED8(0); +U+6ED9(0);U+6C47(1,3);U+532F(1,3),U+5F59(1,3),U+5F5A(4),U+6C47(1,3) +U+6EDA(0);U+6EDA(5);U+6EFE(4) +U+6EDC(0);U+6EDC(0); +U+6EDE(0);U+6EDE(1,3);U+6EEF(1,3) +U+6EDF(0);U+6EDF(1,3,4);U+7054(4),U+7067(1,3),U+7069(4) +U+6EE0(0);U+6EE0(1,3);U+7044(1,3) +U+6EE1(0);U+6EE1(1,3);U+6E80(4),U+6EFF(1,3) +U+6EE2(0);U+6EE2(4);U+7005(4) +U+6EE4(0);U+6EE4(1,3);U+6FFE(1,3) +U+6EE5(0);U+6EE5(1,3);U+6FEB(1,3) + +U+6EE6(0);U+6EE6(1,3);U+7064(1,3) +U+6EE7(0);U+6EE7(0); +U+6EE8(0);U+6EE8(1,3);U+6FF1(1,3),U+6D5C(1,3,5) +U+6EE9(0);U+6EE9(1,3);U+7058(1,3) +U+6EEA(0);U+6EEA(1,3);U+6FA6(1,3) +U+6EEB(0);U+6EEB(4);U+6F43(4) +U+6EEC(0);U+6CAA(1,3);U+6CAA(1,3) +U+6EED(0);U+6EED(0); +U+6EEE(0);U+6EEE(3); +U+6EEF(0);U+6EDE(1,3);U+6EDE(1,3) +U+6EF0(0);U+6EF0(0); +U+6EF1(0);U+6EF1(0); +U+6EF2(0);U+6E17(1,3);U+6E17(1,3) +U+6EF3(0);U+6EF3(0); +U+6EF4(0);U+6EF4(5); +U+6EF5(0);U+6EF5(0); +U+6EF6(0);U+6EF6(0); +U+6EF7(0);U+5364(1,3);U+5364(1,3),U+9E75(4) +U+6EF8(0);U+6D52(1,3);U+6D52(1,3),U+6C7B(0,1,3) +U+6EF9(0);U+6EF9(5); +U+6EFA(0);U+6EFA(0); +U+6EFB(0);U+6D50(1,3);U+6D50(1,3) +U+6EFC(0);U+6EFC(0); +U+6EFD(0);U+6EFD(0); +U+6EFE(0);U+6EDA(4);U+6EDA(4) +U+6EFF(0);U+6EE1(1,3);U+6E80(4),U+6EE1(1,3) +U+6F00(0);U+6F00(0); +U+6F01(0);U+6E14(1,3);U+6E14(1,3) +U+6F02(0);U+6F02(5); +U+6F03(0);U+6F03(0); +U+6F05(0);U+5DE2(3);U+5DE2(3),U+5DE3(3) +U+6F06(0);U+6F06(5);U+67D2(3),U+687C(3) +U+6F07(0);U+6F07(0); +U+6F08(0);U+6F08(0); +U+6F09(0);U+6F09(5); +U+6F0A(0);U+6E87(1,3);U+6E87(1,3) +U+6F0C(0);U+6F0C(0); +U+6F0D(0);U+6F0D(0); +U+6F0E(0);U+6F68(3);U+6F68(3),U+6F40(3,8,9) +U+6F0F(0);U+6F0F(5); +U+6F10(0);U+6F10(0); +U+6F11(0);U+6E89(4);U+6E89(4) +U+6F12(0);U+6F12(0); +U+6F13(0);U+6F13(1,3);U+7055(1,3,4) +U+6F14(0);U+6F14(5); +U+6F15(0);U+6F15(5); +U+6F16(0);U+6F16(0); +U+6F17(0);U+6F17(0); +U+6F18(0);U+6F18(3); +U+6F19(0);U+6F19(0); +U+6F1A(0);U+6CA4(1,3);U+6CA4(1,3) +U+6F1B(0);U+6F1B(0); +U+6F1C(0);U+6F1C(0); +U+6F1D(0);U+6F1D(0); +U+6F1E(0);U+6F1E(0); +U+6F1F(0);U+6F1F(0); +U+6F20(0);U+6F20(5); +U+6F21(0);U+6F21(0); +U+6F22(0);U+6C49(1,3);U+6C49(1,3) +U+6F23(0);U+6D9F(1,3);U+6D9F(1,3) +U+6F24(0);U+6F24(5); +U+6F25(0);U+6D3C(3);U+6D3C(3),U+7AAA(1,3) +U+6F26(0);U+6F26(0); + +U+6F27(0);U+4E7E(3);U+4E7E(3),U+4E81(2,3),U+5E72(1,3),U+5E79(1,3,4),U+69A6(1,3,4) +U+6F28(0);U+6F28(3); +U+6F29(0);U+6F29(5); +U+6F2A(0);U+6F2A(5); +U+6F2B(0);U+6F2B(5);U+6FAB(3) +U+6F2C(0);U+6E0D(1,3);U+6E0D(1,3) +U+6F2D(0);U+6F2D(5); +U+6F2E(0);U+6F2E(0); +U+6F2F(0);U+6F2F(5); +U+6F30(0);U+6F30(0); +U+6F31(0);U+6F31(5);U+6F44(2,3) +U+6F32(0);U+6DA8(1,3);U+6DA8(1,3) +U+6F33(0);U+6F33(5); +U+6F34(0);U+6F34(3); +U+6F35(0);U+6E86(4);U+6E86(4) +U+6F36(0);U+6F36(5); +U+6F37(0);U+6F37(0); +U+6F38(0);U+6E10(1,3);U+6E10(1,3),U+5DC9(0,1,3,4) +U+6F39(0);U+6F39(0); +U+6F3A(0);U+6F3A(0); +U+6F3B(0);U+6F3B(0); +U+6F3C(0);U+6F3C(0); +U+6F3D(0);U+6F3D(0); +U+6F3E(0);U+6F3E(5);U+7001(3) +U+6F3F(0);U+6D46(1,3);U+6D46(1,3) +U+6F40(0);U+6F40(0);U+6F68(8,9),U+6F0E(0,3,8,9) +U+6F41(0);U+988D(1,3);U+988D(1,3) +U+6F43(0);U+6EEB(4);U+6EEB(4) +U+6F44(0);U+6F31(2,3);U+6F31(2,3) +U+6F45(0);U+704C(3);U+704C(3) +U+6F46(0);U+6F46(4);U+7020(4) +U+6F47(0);U+6F47(1,3);U+701F(1,3) +U+6F49(0);U+6F49(0); +U+6F4B(0);U+6F4B(1,3);U+7032(1,3) +U+6F4C(0);U+6F4C(0); +U+6F4D(0);U+6F4D(1,3);U+6FF0(1,3) +U+6F4E(0);U+6F4E(0); +U+6F4F(0);U+6F4F(0); +U+6F50(0);U+6F50(0); +U+6F51(0);U+6CFC(1,3);U+6CFC(1,3) +U+6F52(0);U+8361(3);U+8361(3),U+76EA(3,4),U+8569(1,3),U+862F(3) +U+6F53(0);U+6F53(0); +U+6F54(0);U+6D01(1,3);U+6D01(1,3),U+6D2F(1,2,3) +U+6F55(0);U+6F55(0); +U+6F56(0);U+6F56(0); +U+6F57(0);U+6F57(0); +U+6F58(0);U+6F58(5); +U+6F59(0);U+6CA9(1,3);U+6CA9(1,3),U+6E88(4) +U+6F5A(0);U+6F5A(0); +U+6F5B(0);U+6F5C(2,3);U+6F5C(2,3),U+6FF3(3) +U+6F5C(0);U+6F5C(5);U+6F5B(2,3),U+6FF3(3) +U+6F5D(0);U+6F5D(0); +U+6F5E(0);U+6F5E(5); +U+6F5F(0);U+6F5F(0);U+6F99(7) +U+6F60(0);U+6F60(3); +U+6F61(0);U+6F61(0); +U+6F62(0);U+6F62(5); +U+6F63(0);U+6F63(3); +U+6F64(0);U+6DA6(1,3);U+6DA6(1,3) +U+6F65(0);U+6F65(0); +U+6F66(0);U+6F66(5); +U+6F67(0);U+6EB1(3);U+6EB1(3) +U+6F68(0);U+6F68(3);U+6F0E(3),U+6F40(8,9) + +U+6F69(0);U+6F69(0); +U+6F6A(0);U+6F6A(0); +U+6F6B(0);U+6F6B(0); +U+6F6C(0);U+6F6C(0); +U+6F6D(0);U+6F6D(5); +U+6F6E(0);U+6F6E(5); +U+6F6F(0);U+6D54(1,3);U+6D54(1,3) +U+6F70(0);U+6E83(1,3);U+6E83(1,3) +U+6F71(0);U+6F71(0); +U+6F72(0);U+6F72(5); +U+6F73(0);U+6F73(0); +U+6F74(0);U+6F74(5);U+7026(3) +U+6F75(0);U+6F75(0); +U+6F76(0);U+6F76(0); +U+6F77(0);U+6ED7(1,3);U+6ED7(1,3) +U+6F78(0);U+6F78(5); +U+6F7A(0);U+6F7A(5); +U+6F7B(0);U+6F7B(0); +U+6F7C(0);U+6F7C(5); +U+6F7D(0);U+6F7D(0); +U+6F7E(0);U+6F7E(0); +U+6F7F(0);U+6DA0(1,3);U+6DA0(1,3) +U+6F80(0);U+6DA9(1,3);U+6DA9(1,3),U+6E0B(4),U+6F81(2,3),U+6FC7(2),U+7012(3) +U+6F81(0);U+6DA9(3);U+6DA9(3),U+6F80(2,3),U+6E0B(3,4),U+6FC7(2,3),U+7012(3) +U+6F82(0);U+6F84(2,3);U+6F84(2,3) +U+6F83(0);U+6F83(0); +U+6F84(0);U+6F84(5);U+6F82(2,3) +U+6F85(0);U+6F85(0); +U+6F86(0);U+6D47(1,3);U+6D47(1,3) +U+6F87(0);U+6D9D(1,3);U+6D9D(1,3) +U+6F88(0);U+6F88(5); +U+6F89(0);U+6F89(5); +U+6F8A(0);U+6F8A(0); +U+6F8B(0);U+6F8B(0); +U+6F8C(0);U+6F8C(5); +U+6F8D(0);U+6F8D(5); +U+6F8E(0);U+6F8E(5); +U+6F8F(0);U+6F8F(0); +U+6F90(0);U+6F90(0); +U+6F91(0);U+6E9C(3);U+6E9C(3) +U+6F92(0);U+6F92(0); +U+6F93(0);U+6F93(0); +U+6F94(0);U+6D69(3);U+6D69(3) +U+6F95(0);U+6F95(0); +U+6F96(0);U+6F96(0); +U+6F97(0);U+6DA7(1,3);U+6DA7(1,3) +U+6F99(0);U+6F5F(7);U+6F5F(7) +U+6F9B(0);U+6F9B(4);U+7002(4) +U+6F9C(0);U+6F9C(1,3);U+703E(1,3) +U+6F9D(0);U+6F9D(0); +U+6F9E(0);U+6F9E(0); +U+6FA0(0);U+6E11(1,3);U+6E11(1,3) +U+6FA1(0);U+6FA1(5); +U+6FA2(0);U+6FA2(0); +U+6FA3(0);U+6D63(2,3);U+6D63(2,3) +U+6FA4(0);U+6CFD(1,3);U+6CA2(4),U+6CFD(1,3) +U+6FA5(0);U+6FA5(0); +U+6FA6(0);U+6EEA(1,3);U+6EEA(1,3) +U+6FA7(0);U+6FA7(5); +U+6FA8(0);U+6FA8(0); +U+6FA9(0);U+6CF6(4);U+6CF6(4) +U+6FAA(0);U+6CE0(3);U+6CE0(3) +U+6FAB(0);U+6F2B(3);U+6F2B(3) + +U+6FAC(0);U+6FAC(0); +U+6FAD(0);U+6FAD(0); +U+6FAE(0);U+6D4D(1,3);U+6D4D(1,3) +U+6FAF(0);U+6FAF(0); +U+6FB0(0);U+6FB0(0); +U+6FB1(0);U+6DC0(1,3);U+6DC0(1,3) +U+6FB2(0);U+6FB2(0); +U+6FB3(0);U+6FB3(5); +U+6FB4(0);U+6FB4(0); +U+6FB5(0);U+6FB5(0); +U+6FB6(0);U+6FB6(5); +U+6FB8(0);U+6FB8(0); +U+6FB9(0);U+6FB9(5);U+6DE1(4) +U+6FBA(0);U+6FBA(0); +U+6FBB(0);U+6FBB(0); +U+6FBC(0);U+6FBC(0); +U+6FBD(0);U+6FBD(0); +U+6FBE(0);U+3CE0(1,3);U+3CE0(1,3) +U+6FBF(0);U+6FBF(0); +U+6FC0(0);U+6FC0(5); +U+6FC1(0);U+6D4A(1,3);U+6D4A(1,3) +U+6FC2(0);U+6FC2(5); +U+6FC3(0);U+6D53(1,3);U+6D53(1,3) +U+6FC4(0);U+6DA1(3);U+6DA1(3),U+6E26(1,3) +U+6FC6(0);U+6FC6(3); +U+6FC7(0);U+6DA9(2);U+6DA9(2),U+6F80(2),U+7012(8,9),U+6E0B(2,4),U+6F81(2,3) +U+6FC8(0);U+6FC8(3); +U+6FC9(0);U+6FC9(5); +U+6FCA(0);U+6FCA(3); +U+6FCB(0);U+6FCB(0); +U+6FCC(0);U+6FCC(0); +U+6FCD(0);U+6FCD(0); +U+6FCE(0);U+6FCE(0); +U+6FCF(0);U+6FCF(0); +U+6FD1(0);U+6FD1(1,3);U+7028(1,3),U+702C(3) +U+6FD2(0);U+6FD2(1,3);U+7015(1,3) +U+6FD4(0);U+6CB5(4);U+6CB5(4) +U+6FD5(0);U+6E7F(1,3);U+6E7F(1,3),U+6EBC(2,3) +U+6FD6(0);U+6FD6(0); +U+6FD7(0);U+6FD7(0); +U+6FD8(0);U+6CDE(1,3);U+6CDE(1,3) +U+6FD9(0);U+6FD9(0); +U+6FDA(0);U+6E81(4);U+6E81(4) +U+6FDB(0);U+8499(1,3);U+8499(1,3),U+61DE(0,1,3,4),U+77C7(1,3,4) +U+6FDC(0);U+6D55(1,3);U+6D55(1,3) +U+6FDD(0);U+6FDD(0); +U+6FDE(0);U+6FDE(5); +U+6FDF(0);U+6D4E(1,3);U+6D4E(1,3),U+6E08(3) +U+6FE0(0);U+6FE0(5); +U+6FE1(0);U+6FE1(5); +U+6FE2(0);U+6FE2(0); +U+6FE3(0);U+6FE3(0); +U+6FE4(0);U+6D9B(1,3);U+6D9B(1,3) +U+6FE5(0);U+6FE5(3); +U+6FE6(0);U+6FE6(3); +U+6FE7(0);U+6FE7(0); +U+6FE8(0);U+6FE8(0); +U+6FE9(0);U+6FE9(4); +U+6FEA(0);U+6FEA(0); +U+6FEB(0);U+6EE5(1,3);U+6EE5(1,3) +U+6FEC(0);U+6D5A(2);U+6D5A(2) +U+6FED(0);U+6FED(0); +U+6FEE(0);U+6FEE(5); + +U+6FEF(0);U+6FEF(5); +U+6FF0(0);U+6F4D(1,3);U+6F4D(1,3) +U+6FF1(0);U+6EE8(1,3);U+6D5C(3),U+6EE8(1,3) +U+6FF2(0);U+6FF2(0); +U+6FF3(0);U+6F5C(3);U+6F5B(3),U+6F5C(3) +U+6FF4(0);U+6FF4(3); +U+6FF6(0);U+9614(4);U+95CA(2,3),U+9614(4) +U+6FF7(0);U+6FF7(0); +U+6FF8(0);U+6FF8(0); +U+6FF9(0);U+6FF9(0); +U+6FFA(0);U+6E85(1,3);U+6E85(1,3) +U+6FFB(0);U+7022(3);U+7022(3) +U+6FFC(0);U+6CFA(1,3);U+6CCA(3),U+6CFA(1,3) +U+6FFE(0);U+6EE4(1,3);U+6EE4(1,3) +U+6FFF(0);U+6FFF(3); +U+7000(0);U+7000(0); +U+7001(0);U+6F3E(3);U+6F3E(3) +U+7002(0);U+6F9B(4);U+6F9B(4) +U+7003(0);U+7003(0); +U+7004(0);U+7004(0); +U+7005(0);U+6EE2(4);U+6EE2(4) +U+7006(0);U+6E0E(1,3);U+6E0E(1,3) +U+7007(0);U+6C6A(3);U+6C6A(3) +U+7008(0);U+7008(0); +U+7009(0);U+6CFB(1,3);U+6CFB(1,3) +U+700A(0);U+700A(0); +U+700B(0);U+6C88(1);U+6C88(1),U+6E16(4),U+6C89(1,3) +U+700C(0);U+700C(0); +U+700D(0);U+700D(0); +U+700E(0);U+700E(0); +U+700F(0);U+6D4F(1,3);U+56A0(4),U+6D4F(1,3) +U+7011(0);U+7011(5); +U+7012(0);U+6DA9(3);U+6DA9(3),U+6F80(3),U+6FC7(8,9),U+6E0B(3,4),U+6F81(3) +U+7014(0);U+7014(0); +U+7015(0);U+6FD2(1,3);U+6FD2(1,3) +U+7016(0);U+7016(0); +U+7017(0);U+7017(0); +U+7018(0);U+6CF8(1,3);U+6CF8(1,3) +U+7019(0);U+7019(0); +U+701A(0);U+701A(5); +U+701B(0);U+701B(5); +U+701C(0);U+701C(0); +U+701D(0);U+6CA5(1,3);U+6CA5(1,3) +U+701F(0);U+6F47(1,3);U+6F47(1,3) +U+7020(0);U+6F46(4);U+6F46(4) +U+7021(0);U+7021(0); +U+7022(0);U+7022(3);U+6FFB(3) +U+7023(0);U+7023(5); +U+7024(0);U+7024(0); +U+7025(0);U+7025(0); +U+7026(0);U+6F74(3);U+6F74(3) +U+7027(0);U+6CF7(1,3);U+6CF7(1,3) +U+7028(0);U+6FD1(1,3);U+6FD1(1,3),U+702C(3) +U+7029(0);U+7029(0); +U+702A(0);U+702A(0); +U+702B(0);U+702B(0); +U+702C(0);U+6FD1(3);U+6FD1(3),U+7028(3) +U+702D(0);U+702D(0); +U+702E(0);U+702E(0); +U+702F(0);U+702F(3); +U+7030(0);U+5F25(1,3);U+5F25(1,3),U+5F4C(4),U+519E(1,3,7) +U+7031(0);U+7031(0); +U+7032(0);U+6F4B(1,3);U+6F4B(1,3) + +U+7033(0);U+7033(3); +U+7034(0);U+7034(0); +U+7035(0);U+7035(5); +U+7036(0);U+7036(3); +U+7037(0);U+7037(0); +U+7038(0);U+7038(3); +U+7039(0);U+7039(5); +U+703A(0);U+703A(0); +U+703B(0);U+703B(0); +U+703C(0);U+703C(0); +U+703D(0);U+703D(0); +U+703E(0);U+6F9C(1,3);U+6F9C(1,3) +U+703F(0);U+703F(0); +U+7040(0);U+7040(0); +U+7041(0);U+6E0A(3,4);U+6E0A(3,4),U+6DF5(0,1,3,4),U+6E15(1,3,4) +U+7042(0);U+7042(0); +U+7043(0);U+6CA3(1,3);U+6CA3(1,3) +U+7044(0);U+6EE0(1,3);U+6EE0(1,3) +U+7045(0);U+7045(3); +U+7046(0);U+7046(0); +U+7048(0);U+7048(0); +U+7049(0);U+7049(3); +U+704A(0);U+704A(0); +U+704C(0);U+704C(5);U+6F45(3) +U+704D(0);U+704D(0); +U+704F(0);U+704F(1,3);U+705D(1,3) +U+7050(0);U+7050(0); +U+7051(0);U+6D12(1,3);U+6D12(1,3) +U+7052(0);U+7052(3); +U+7053(0);U+7053(3); +U+7054(0);U+6EDF(4);U+6EDF(4),U+7067(4),U+7069(3) +U+7055(0);U+6F13(1,3);U+6F13(1,3) +U+7056(0);U+7056(0); +U+7057(0);U+7057(0); +U+7058(0);U+6EE9(1,3);U+6EE9(1,3) +U+7059(0);U+7059(0); +U+705A(0);U+705A(0); +U+705B(0);U+9610(3);U+9610(3),U+95E1(1,3) +U+705C(0);U+705C(0); +U+705D(0);U+704F(1,3);U+704F(1,3) +U+705E(0);U+705E(5); +U+705F(0);U+705F(0); +U+7060(0);U+7060(0); +U+7061(0);U+7061(3); +U+7062(0);U+7062(0); +U+7063(0);U+6E7E(1,3);U+6E7E(1,3) +U+7064(0);U+6EE6(1,3);U+6EE6(1,3) +U+7065(0);U+7065(0); +U+7066(0);U+7066(0); +U+7067(0);U+6EDF(1,3);U+6EDF(1,3),U+7054(4),U+7069(3,4) +U+7068(0);U+8D63(2);U+8D63(2),U+8D1B(1,2,3) +U+7069(0);U+6EDF(4);U+6EDF(4),U+7054(3),U+7067(3,4) +U+706A(0);U+706A(0); +U+706B(0);U+706B(5); +U+706C(0);U+706C(5); +U+706D(0);U+706D(1,3);U+6EC5(1,3) +U+706E(0);U+5149(3);U+5149(3),U+709A(3),U+70E1(3) +U+706F(0);U+706F(1,3);U+71C8(1,3) +U+7070(0);U+7070(5); +U+7071(0);U+7071(3); +U+7074(0);U+70D8(3);U+70D8(3) +U+7075(0);U+7075(1,3);U+970A(3),U+9748(1,3) +U+7076(0);U+7076(1,3);U+7AC8(1,3) + +U+7077(0);U+7077(0); +U+7078(0);U+7078(5); +U+7079(0);U+7079(0); +U+707A(0);U+707A(3); +U+707C(0);U+707C(5); +U+707D(0);U+707E(2,3);U+707E(2,3),U+70D6(4) +U+707E(0);U+707E(3);U+707D(2,3),U+70D6(2) +U+707F(0);U+707F(1,3);U+71E6(1,3) +U+7080(0);U+7080(1,3);U+716C(1,3) +U+7082(0);U+7082(0); +U+7083(0);U+711A(3);U+711A(3) +U+7084(0);U+7084(0); +U+7085(0);U+7085(5);U+7094(3) +U+7086(0);U+7086(0); +U+7087(0);U+7087(0); +U+7088(0);U+7088(0); +U+7089(0);U+7089(1,3,4);U+7210(1,3),U+946A(4) +U+708A(0);U+708A(5); +U+708B(0);U+708B(0); +U+708C(0);U+708C(0); +U+708E(0);U+708E(5); +U+708F(0);U+708F(0); +U+7090(0);U+7090(0); +U+7091(0);U+7091(0); +U+7092(0);U+7092(5); +U+7093(0);U+7093(0); +U+7094(0);U+7094(5);U+7085(3) +U+7095(0);U+7095(5);U+531F(2,3) +U+7096(0);U+7096(5);U+71C9(3) +U+7098(0);U+7098(0); +U+7099(0);U+7099(5); +U+709A(0);U+5149(3);U+5149(3),U+706E(3),U+70E1(3) +U+709C(0);U+709C(1,3);U+7152(1,3) +U+709D(0);U+709D(1,3);U+7197(1,3) +U+709E(0);U+709E(0); +U+709F(0);U+709F(0); +U+70A0(0);U+70A0(0); +U+70A1(0);U+70A1(0); +U+70A2(0);U+70A2(0); +U+70A3(0);U+70A3(0); +U+70A4(0);U+7167(2,3);U+7167(2,3),U+66CC(0,2,3) +U+70A5(0);U+70A5(0); +U+70A6(0);U+70A6(0); +U+70A7(0);U+70A7(0); +U+70A8(0);U+70A8(0); +U+70A9(0);U+70A9(0); +U+70AB(0);U+70AB(5); +U+70AC(0);U+70AC(5); +U+70AD(0);U+70AD(5); +U+70AE(0);U+70AE(5);U+70B0(3),U+7832(2,3),U+792E(2,3) +U+70AF(0);U+70AF(5);U+70F1(2,3) +U+70B0(0);U+70B0(0);U+70AE(3),U+7832(2,3),U+792E(2,3) +U+70B1(0);U+70B1(5); +U+70B3(0);U+70B3(5);U+663A(3) +U+70B4(0);U+70B4(0); +U+70B5(0);U+70B5(0); +U+70B7(0);U+70B7(5); +U+70B8(0);U+70B8(5); +U+70B9(0);U+70B9(1,3);U+594C(4),U+9EDE(1,3) +U+70BA(0);U+4E3A(3);U+4E3A(3),U+7232(3) +U+70BB(0);U+70BB(5); +U+70BC(0);U+70BC(1,3);U+7149(1,3),U+934A(4) +U+70BD(0);U+70BD(1,3);U+71BE(1,3) + +U+70BE(0);U+70BE(0); +U+70BF(0);U+70BF(0); +U+70C0(0);U+70C0(5); +U+70C1(0);U+70C1(1,3);U+720D(1,3) +U+70C2(0);U+70C2(1,3);U+71D7(3),U+721B(1,3) +U+70C3(0);U+70C3(1,3);U+70F4(1,3) +U+70C4(0);U+70C4(3); +U+70C5(0);U+70C5(0); +U+70C6(0);U+70C6(0); +U+70C7(0);U+70C7(0); +U+70C8(0);U+70C8(5); +U+70C9(0);U+7115(3);U+7115(3),U+7165(4) +U+70CA(0);U+70CA(5); +U+70CB(0);U+70CB(0); +U+70CC(0);U+70CC(0); +U+70CD(0);U+70CD(0); +U+70CE(0);U+70CE(0); +U+70CF(0);U+4E4C(1,3);U+4E4C(1,3) +U+70D0(0);U+70D0(0); +U+70D1(0);U+70D1(0); +U+70D2(0);U+70D2(0); +U+70D3(0);U+70D3(0); +U+70D4(0);U+70D4(3); +U+70D6(0);U+707E(2);U+707D(4),U+707E(2) +U+70D7(0);U+70D7(3); +U+70D8(0);U+70D8(5);U+7074(3) +U+70D9(0);U+70D9(5); +U+70DA(0);U+70DA(0); +U+70DB(0);U+70DB(1,3);U+71ED(1,3) +U+70DC(0);U+70DC(0); +U+70DD(0);U+70DD(0); +U+70DE(0);U+70DE(0); +U+70DF(0);U+70DF(5);U+7159(2,3),U+83F8(2) +U+70E0(0);U+70E0(0); +U+70E1(0);U+5149(3);U+5149(3),U+706E(3),U+709A(3) +U+70E2(0);U+70E2(0); +U+70E3(0);U+70E3(0); +U+70E4(0);U+70E4(5); +U+70E5(0);U+70E5(0); +U+70E6(0);U+70E6(1,3);U+7169(1,3) +U+70E7(0);U+70E7(1,3);U+71D2(1,3) +U+70E8(0);U+70E8(1,3);U+71C1(1,3) +U+70E9(0);U+70E9(1,3);U+71F4(1,3) +U+70EA(0);U+70EA(0); +U+70EB(0);U+70EB(1,3);U+71D9(1,3) +U+70EC(0);U+70EC(1,3);U+7161(3),U+71FC(1,3) +U+70ED(0);U+70ED(1,3);U+71B1(1,3) +U+70EE(0);U+70EE(0); +U+70EF(0);U+70EF(5); +U+70F0(0);U+70F0(0); +U+70F1(0);U+70AF(2,3);U+70AF(2,3) +U+70F2(0);U+70F2(3); +U+70F3(0);U+70F3(0); +U+70F4(0);U+70C3(1,3);U+70C3(1,3) +U+70F5(0);U+70F5(0); +U+70F6(0);U+70F6(0); +U+70F7(0);U+70F7(5); +U+70F8(0);U+70F8(0); +U+70F9(0);U+70F9(5); +U+70FA(0);U+6717(3);U+6717(3),U+6716(0,3) +U+70FB(0);U+70FB(0); +U+70FC(0);U+70FC(0); +U+70FD(0);U+70FD(5); + +U+70FF(0);U+70FF(0); +U+7100(0);U+7100(0); +U+7101(0);U+7101(0); +U+7102(0);U+7102(0); +U+7103(0);U+7103(0); +U+7104(0);U+7104(0); +U+7105(0);U+7105(0); +U+7106(0);U+7106(0); +U+7107(0);U+7107(0); +U+7109(0);U+7109(5); +U+710A(0);U+710A(5);U+91EC(2,3),U+92B2(2) +U+710B(0);U+710B(0); +U+710C(0);U+710C(3);U+71C7(3) +U+710D(0);U+710D(0); +U+710E(0);U+710E(0); +U+710F(0);U+710F(0); +U+7110(0);U+7110(5); +U+7111(0);U+7111(0); +U+7112(0);U+7112(0); +U+7113(0);U+7113(5); +U+7115(0);U+7115(4);U+70C9(3),U+7165(4) +U+7116(0);U+7116(1,3);U+71DC(1,3) +U+7117(0);U+7117(0); +U+7118(0);U+7118(1,3);U+71FE(1,3) +U+7119(0);U+7119(5); +U+711A(0);U+711A(5);U+7083(3) +U+711B(0);U+711B(0); +U+711C(0);U+711C(0); +U+711D(0);U+711D(0); +U+711E(0);U+711E(0); +U+711F(0);U+711F(0); +U+7120(0);U+7120(3); +U+7121(0);U+65E0(1,3);U+65E0(1,3) +U+7122(0);U+7122(0); +U+7123(0);U+7123(0); +U+7125(0);U+7125(0); +U+7126(0);U+7126(5); +U+7127(0);U+7127(0); +U+7128(0);U+7128(0); +U+7129(0);U+7129(0); +U+712A(0);U+712A(3); +U+712B(0);U+712B(0); +U+712C(0);U+712C(0); +U+712D(0);U+712D(4);U+7162(3,4),U+8315(1,3,4),U+60F8(0,1,3,4) +U+712E(0);U+712E(3); +U+712F(0);U+712F(5); +U+7130(0);U+7130(5);U+71C4(2,3) +U+7131(0);U+7131(5); +U+7132(0);U+7132(3); +U+7135(0);U+7135(0); +U+7136(0);U+7136(5); +U+7137(0);U+7137(0); +U+7138(0);U+7138(4); +U+7139(0);U+7139(0); +U+713A(0);U+713A(0); +U+713B(0);U+713B(0); +U+713D(0);U+713D(0); +U+713E(0);U+713E(0); +U+713F(0);U+713F(0); +U+7140(0);U+7140(0); +U+7141(0);U+7141(0); +U+7142(0);U+7142(0); +U+7143(0);U+7143(0); + +U+7144(0);U+7144(0); +U+7145(0);U+7145(5);U+935B(3),U+953B(1,3) +U+7146(0);U+7146(0); +U+7147(0);U+7147(4); +U+7148(0);U+7148(0); +U+7149(0);U+70BC(1,3);U+70BC(1,3),U+934A(1,3,4) +U+714A(0);U+714A(5); +U+714B(0);U+714B(0); +U+714C(0);U+714C(5); +U+714D(0);U+714D(0); +U+714E(0);U+714E(5); +U+714F(0);U+714F(0); +U+7150(0);U+7150(0); +U+7151(0);U+716E(2,3);U+716E(2,3) +U+7152(0);U+709C(1,3);U+709C(1,3) +U+7153(0);U+7153(0); +U+7154(0);U+7154(3); +U+7156(0);U+6696(2,3);U+6696(2,3) +U+7158(0);U+7158(0); +U+7159(0);U+70DF(2,3);U+70DF(2,3),U+83F8(4) +U+715A(0);U+715A(3);U+71DB(3) +U+715B(0);U+715B(0); +U+715C(0);U+715C(5); +U+715D(0);U+715D(0); +U+715E(0);U+715E(5); +U+715F(0);U+715F(0); +U+7160(0);U+7160(3); +U+7161(0);U+70EC(3);U+70EC(3),U+71FC(1,3) +U+7162(0);U+8315(1,3);U+712D(3,4),U+8315(1,3),U+60F8(0,1,3,4) +U+7163(0);U+7163(3); +U+7164(0);U+7164(5); +U+7165(0);U+7115(4);U+70C9(4),U+7115(4) +U+7166(0);U+7166(5); +U+7167(0);U+7167(5);U+66CC(3),U+70A4(2,3) +U+7168(0);U+7168(5);U+71F0(3) +U+7169(0);U+70E6(1,3);U+70E6(1,3) +U+716A(0);U+716A(0); +U+716C(0);U+7080(1,3);U+7080(1,3) +U+716E(0);U+716E(5);U+7151(2,3) +U+716F(0);U+716F(0); +U+7170(0);U+71E5(3);U+71E5(3) +U+7171(0);U+7171(3); +U+7172(0);U+7172(5); +U+7173(0);U+7173(5); +U+7174(0);U+7174(3);U+7185(4) +U+7175(0);U+7175(0); +U+7176(0);U+7176(0); +U+7177(0);U+7177(0); +U+7178(0);U+7178(5); +U+7179(0);U+7179(0); +U+717A(0);U+717A(5); +U+717B(0);U+717B(0); +U+717C(0);U+717C(0); +U+717D(0);U+717D(5); +U+717E(0);U+717E(0); +U+717F(0);U+717F(0); +U+7180(0);U+7180(0); +U+7181(0);U+7181(0); +U+7182(0);U+7182(0); +U+7183(0);U+7183(0); +U+7184(0);U+7184(5); +U+7185(0);U+7174(4);U+7174(4) +U+7186(0);U+7186(0); + +U+7187(0);U+7187(3); +U+7188(0);U+7199(2);U+7199(2) +U+7189(0);U+7189(0); +U+718A(0);U+718A(5); +U+718B(0);U+718B(0); +U+718C(0);U+718C(0); +U+718E(0);U+718E(0); +U+718F(0);U+718F(5);U+71FB(2,3) +U+7190(0);U+7190(0); +U+7191(0);U+7191(3); +U+7192(0);U+8367(1,3);U+8367(1,3) +U+7193(0);U+7193(0); +U+7194(0);U+7194(5);U+9394(2),U+9555(2,4) +U+7195(0);U+7195(0); +U+7197(0);U+709D(1,3);U+709D(1,3) +U+7198(0);U+7198(5); +U+7199(0);U+7199(5);U+7188(2) +U+719A(0);U+719A(0); +U+719B(0);U+719B(0); +U+719C(0);U+719C(3); +U+719D(0);U+719D(0); +U+719E(0);U+719E(0); +U+719F(0);U+719F(5); +U+71A0(0);U+71A0(5); +U+71A1(0);U+71A1(0); +U+71A2(0);U+71A2(0); +U+71A3(0);U+71A3(0); +U+71A4(0);U+71A4(0); +U+71A5(0);U+71A5(0); +U+71A7(0);U+71A7(0); +U+71A8(0);U+71A8(5); +U+71A9(0);U+71A9(0); +U+71AA(0);U+71AA(0); +U+71AC(0);U+71AC(5); +U+71AD(0);U+71AD(0); +U+71AE(0);U+71AE(0); +U+71AF(0);U+71AF(0); +U+71B0(0);U+71B0(0); +U+71B1(0);U+70ED(1,3);U+70ED(1,3) +U+71B2(0);U+988E(4);U+988E(4) +U+71B3(0);U+71B3(5); +U+71B4(0);U+71B4(0); +U+71B5(0);U+71B5(5); +U+71B7(0);U+71B7(0); +U+71B8(0);U+71B8(0); +U+71B9(0);U+71B9(5);U+71BA(3) +U+71BA(0);U+71B9(3);U+71B9(3) +U+71BB(0);U+71BB(0); +U+71BC(0);U+71BC(0); +U+71BD(0);U+71BD(0); +U+71BE(0);U+70BD(1,3);U+70BD(1,3) +U+71BF(0);U+71BF(0); +U+71C0(0);U+71C0(0); +U+71C1(0);U+70E8(1,3);U+70E8(1,3) +U+71C2(0);U+71C2(3); +U+71C3(0);U+71C3(5); +U+71C4(0);U+7130(2,3);U+7130(2,3) +U+71C5(0);U+71C5(0); +U+71C6(0);U+71C6(0); +U+71C7(0);U+710C(3);U+710C(3) +U+71C8(0);U+706F(1,3);U+706F(1,3) +U+71C9(0);U+7096(3);U+7096(3) +U+71CA(0);U+71CA(0); + +U+71CB(0);U+71CB(0); +U+71CD(0);U+71CD(0); +U+71CE(0);U+71CE(5); +U+71CF(0);U+71CF(0); +U+71D0(0);U+71D0(4);U+78F7(2) +U+71D1(0);U+71D1(0); +U+71D2(0);U+70E7(1,3);U+70E7(1,3) +U+71D4(0);U+71D4(5); +U+71D5(0);U+71D5(5);U+89FE(3),U+9DF0(2,3) +U+71D6(0);U+71D6(3); +U+71D7(0);U+70C2(3);U+70C2(3),U+721B(3) +U+71D8(0);U+71D8(0); +U+71D9(0);U+70EB(1,3);U+70EB(1,3) +U+71DA(0);U+71DA(0); +U+71DB(0);U+715A(3);U+715A(3) +U+71DC(0);U+7116(1,3);U+7116(1,3) +U+71DD(0);U+71DD(0); +U+71DE(0);U+71DE(0); +U+71DF(0);U+8425(1,3);U+55B6(4),U+8425(1,3) +U+71E0(0);U+71E0(5); +U+71E1(0);U+71E1(3); +U+71E2(0);U+71E2(0); +U+71E3(0);U+71F7(4);U+71F7(4) +U+71E4(0);U+71E4(0); +U+71E5(0);U+71E5(5);U+7170(3) +U+71E6(0);U+707F(1,3);U+707F(1,3) +U+71E7(0);U+71E7(5); +U+71E8(0);U+7214(3);U+7214(3) +U+71E9(0);U+71E9(0); +U+71EA(0);U+71EA(0); +U+71EB(0);U+71EB(0); +U+71EC(0);U+71EC(0); +U+71ED(0);U+70DB(1,3);U+70DB(1,3) +U+71EE(0);U+71EE(5); +U+71EF(0);U+71EF(0);U+7227(3) +U+71F0(0);U+7168(3);U+7168(3) +U+71F1(0);U+71F1(0); +U+71F2(0);U+71F2(0); +U+71F4(0);U+70E9(1,3);U+70E9(1,3) +U+71F5(0);U+71F5(0); +U+71F6(0);U+71F6(0); +U+71F7(0);U+71F7(0);U+71E3(4) +U+71F8(0);U+71F8(0); +U+71F9(0);U+71F9(5); +U+71FB(0);U+718F(2,3);U+718F(2,3) +U+71FC(0);U+70EC(1,3);U+70EC(1,3),U+7161(1,3) +U+71FD(0);U+71FD(0); +U+71FE(0);U+7118(1,3);U+7118(1,3) +U+71FF(0);U+8000(2,3);U+66DC(3),U+8000(2,3) +U+7201(0);U+7201(4);U+7226(4) +U+7202(0);U+7202(0); +U+7203(0);U+7203(0); +U+7204(0);U+7204(0); +U+7205(0);U+7205(0); +U+7206(0);U+7206(5); +U+7207(0);U+7207(3); +U+7208(0);U+7208(0); +U+7209(0);U+7209(0); +U+720A(0);U+720A(0); +U+720C(0);U+720C(3); +U+720D(0);U+70C1(1,3);U+70C1(1,3) +U+720E(0);U+720E(0); +U+720F(0);U+720F(0); + +U+7210(0);U+7089(1,3);U+7089(1,3),U+946A(1,3,4) +U+7212(0);U+7212(3); +U+7213(0);U+7213(0); +U+7214(0);U+7214(3);U+71E8(3) +U+7216(0);U+7216(0); +U+7218(0);U+7218(0); +U+7219(0);U+7219(0); +U+721A(0);U+721A(3); +U+721B(0);U+70C2(1,3);U+70C2(1,3),U+71D7(3) +U+721C(0);U+721C(0); +U+721D(0);U+721D(5); +U+721E(0);U+721E(3); +U+721F(0);U+721F(0); +U+7221(0);U+7221(0); +U+7222(0);U+7CDC(3);U+7CDC(3) +U+7223(0);U+7223(0); +U+7226(0);U+7201(4);U+7201(4) +U+7227(0);U+71EF(3);U+71EF(3) +U+7228(0);U+7228(5); +U+7229(0);U+7229(0); +U+722A(0);U+722A(5); +U+722B(0);U+722B(0); +U+722C(0);U+722C(5); +U+722D(0);U+4E89(3,4);U+4E89(3,4) +U+722E(0);U+722E(0); +U+7230(0);U+7230(5); +U+7231(0);U+7231(1,3);U+611B(1,3) +U+7232(0);U+4E3A(1,3);U+4E3A(1,3),U+70BA(3) +U+7233(0);U+7233(0); +U+7235(0);U+7235(5); +U+7236(0);U+7236(5); +U+7237(0);U+7237(1,3);U+723A(1,3) +U+7238(0);U+7238(5); +U+7239(0);U+7239(5); +U+723A(0);U+7237(1,3);U+7237(1,3) +U+723B(0);U+723B(5); +U+723C(0);U+4FCE(3);U+4FCE(3) +U+723D(0);U+723D(5);U+6161(3) +U+723E(0);U+5C14(1,3);U+5C12(2,3),U+5C13(3),U+5C14(1,3) +U+723F(0);U+723F(5);U+4E2C(8,9) +U+7240(0);U+5E8A(2,3);U+5E8A(2,3) +U+7241(0);U+7241(3); +U+7242(0);U+7242(3); +U+7243(0);U+7243(0); +U+7244(0);U+7244(0); +U+7246(0);U+5899(4);U+5899(4),U+58BB(2,3) +U+7247(0);U+7247(5); +U+7248(0);U+7248(5); +U+7249(0);U+7249(3); +U+724A(0);U+724A(0); +U+724B(0);U+7B3A(2,3);U+7B3A(2,3),U+7B8B(2,3) +U+724C(0);U+724C(5); +U+724D(0);U+724D(1,3);U+7258(1,3) +U+724F(0);U+724F(0); +U+7251(0);U+7251(0); +U+7252(0);U+7252(5); +U+7253(0);U+699C(3);U+699C(3) +U+7254(0);U+7254(0); +U+7256(0);U+7256(5); +U+7257(0);U+7257(0); +U+7258(0);U+724D(1,3);U+724D(1,3) +U+7259(0);U+7259(5); +U+725A(0);U+6491(4);U+6491(4),U+6490(0,2,3,4) + +U+725B(0);U+725B(5); +U+725C(0);U+725C(0); +U+725D(0);U+725D(5); +U+725E(0);U+725E(0); +U+725F(0);U+725F(5); +U+7260(0);U+5B83(2,3);U+5B83(2,3) +U+7261(0);U+7261(5); +U+7262(0);U+7262(5); +U+7263(0);U+7263(0); +U+7264(0);U+7264(0); +U+7265(0);U+7265(0); +U+7266(0);U+7266(5);U+6C02(2,3),U+729B(2,3),U+9AE6(3) +U+7267(0);U+7267(5); +U+7268(0);U+7268(0); +U+7269(0);U+7269(5); +U+726A(0);U+726A(0); +U+726B(0);U+726B(0); +U+726C(0);U+726C(0); +U+726D(0);U+726D(0); +U+726E(0);U+726E(5); +U+726F(0);U+726F(5); +U+7270(0);U+7270(0); +U+7271(0);U+7271(0); +U+7272(0);U+7272(5); +U+7273(0);U+7273(0); +U+7274(0);U+7274(0);U+62B5(2,3),U+7F9D(3),U+89DD(4),U+627A(2,3) +U+7275(0);U+7275(1,3);U+727D(1,3) +U+7276(0);U+7276(0); +U+7277(0);U+7277(0); +U+7278(0);U+7278(0); +U+7279(0);U+7279(5); +U+727A(0);U+727A(1,3);U+72A7(1,3) +U+727B(0);U+727B(0); +U+727C(0);U+727C(0); +U+727D(0);U+7275(1,3);U+7275(1,3) +U+727E(0);U+727E(5); +U+727F(0);U+727F(5); +U+7280(0);U+7280(5); +U+7281(0);U+7281(5);U+7282(2,3) +U+7282(0);U+7281(2,3);U+7281(2,3) +U+7283(0);U+7283(0); +U+7284(0);U+7284(5); +U+7285(0);U+7285(3); +U+7286(0);U+7286(0); +U+7287(0);U+5954(2,3);U+5954(2,3),U+9029(2,3) +U+7288(0);U+7288(0); +U+7289(0);U+7289(0); +U+728A(0);U+728A(1,3);U+72A2(1,3) +U+728B(0);U+728B(5); +U+728C(0);U+728C(0); +U+728D(0);U+728D(5); +U+728E(0);U+728E(0); +U+728F(0);U+728F(5); +U+7290(0);U+7290(0); +U+7291(0);U+7291(0); +U+7292(0);U+7292(5); +U+7293(0);U+7293(0); +U+7294(0);U+7294(0); +U+7295(0);U+7295(0); +U+7296(0);U+8366(1,3);U+8366(1,3) +U+7297(0);U+7297(0); +U+7298(0);U+7298(0); +U+7299(0);U+7299(0); + +U+729A(0);U+729A(0); +U+729B(0);U+7266(2,3);U+7266(2,3),U+6C02(0,2,3),U+9AE6(2,3) +U+729C(0);U+729C(0); +U+729D(0);U+729D(0); +U+729E(0);U+729E(0); +U+729F(0);U+729F(5); +U+72A1(0);U+72A1(0); +U+72A2(0);U+728A(1,3);U+728A(1,3) +U+72A3(0);U+72A3(0); +U+72A4(0);U+72A4(0); +U+72A5(0);U+72A5(0); +U+72A6(0);U+72A6(0); +U+72A7(0);U+727A(1,3);U+727A(1,3) +U+72A8(0);U+72A8(3); +U+72A9(0);U+72A9(0); +U+72AA(0);U+72AA(3); +U+72AC(0);U+72AC(5); +U+72AD(0);U+72AD(5); +U+72AE(0);U+72AE(0); +U+72AF(0);U+72AF(5); +U+72B0(0);U+72B0(5); +U+72B1(0);U+72B1(0); +U+72B2(0);U+8C7A(3);U+8C7A(3) +U+72B3(0);U+72B3(0); +U+72B4(0);U+72B4(5); +U+72B5(0);U+72B5(0); +U+72B6(0);U+72B6(1,3);U+72C0(1,3,4) +U+72B7(0);U+72B7(1,3);U+7377(1,3) +U+72B8(0);U+72B8(1,3);U+7341(1,3) +U+72B9(0);U+72B9(1,3);U+7336(1,3) +U+72BA(0);U+72BA(0); +U+72BB(0);U+72BB(0); +U+72BC(0);U+72BC(0); +U+72BD(0);U+72BD(0); +U+72BF(0);U+72BF(0); +U+72C0(0);U+72B6(1,3);U+72B6(1,3) +U+72C1(0);U+72C1(5); +U+72C2(0);U+72C2(5);U+72C5(3) +U+72C3(0);U+72C3(5); +U+72C4(0);U+72C4(5); +U+72C5(0);U+72C2(3);U+72C2(3) +U+72C6(0);U+4EF2(3);U+4EF2(3) +U+72C7(0);U+72C7(0); +U+72C8(0);U+72C8(1,3);U+72FD(1,3) +U+72C9(0);U+72C9(0); +U+72CA(0);U+72CA(0); +U+72CB(0);U+72CB(3); +U+72CC(0);U+72CC(0); +U+72CD(0);U+72CD(5); +U+72CE(0);U+72CE(5); +U+72CF(0);U+72CF(0); +U+72D0(0);U+72D0(5); +U+72D1(0);U+72D1(0); +U+72D2(0);U+72D2(5); +U+72D3(0);U+72D3(0); +U+72D4(0);U+72D4(0); +U+72D5(0);U+72D5(0); +U+72D6(0);U+72D6(3); +U+72D7(0);U+72D7(5); +U+72D8(0);U+72D8(0); +U+72D9(0);U+72D9(5); +U+72DA(0);U+72DA(0); +U+72DB(0);U+72DB(0); + +U+72DC(0);U+72DC(0); +U+72DD(0);U+72DD(4);U+736E(4) +U+72DE(0);U+72DE(1,3);U+7370(1,3) +U+72DF(0);U+72DF(0); +U+72E0(0);U+72E0(5); +U+72E1(0);U+72E1(5); +U+72E2(0);U+8C89(3);U+8C89(3) +U+72E3(0);U+72E3(0); +U+72E4(0);U+72E4(0); +U+72E5(0);U+72E5(4); +U+72E6(0);U+72E6(0); +U+72E7(0);U+72E7(0); +U+72E8(0);U+72E8(5); +U+72E9(0);U+72E9(5); +U+72EA(0);U+72EA(0); +U+72EB(0);U+4F6C(3);U+4F6C(3) +U+72EC(0);U+72EC(1,3);U+7368(1,3) +U+72ED(0);U+72ED(1,3);U+72F9(1,3) +U+72EE(0);U+72EE(1,3);U+7345(1,3) +U+72EF(0);U+72EF(1,3);U+736A(1,3),U+733E(1,3) +U+72F0(0);U+72F0(4);U+7319(4) +U+72F1(0);U+72F1(1,3);U+7344(1,3) +U+72F2(0);U+72F2(1,3);U+733B(1,3) +U+72F3(0);U+72F3(5); +U+72F4(0);U+72F4(5); +U+72F5(0);U+72F5(0); +U+72F6(0);U+72F6(0); +U+72F7(0);U+72F7(5);U+7367(2) +U+72F8(0);U+72F8(5);U+8C8D(2,3) +U+72F9(0);U+72ED(1,3);U+72ED(1,3) +U+72FA(0);U+72FA(5); +U+72FB(0);U+72FB(5); +U+72FC(0);U+72FC(5); +U+72FD(0);U+72C8(1,3);U+72C8(1,3) +U+72FE(0);U+72FE(3); +U+72FF(0);U+72FF(0); +U+7300(0);U+7300(0); +U+7301(0);U+7301(5); +U+7303(0);U+7303(1,3);U+736B(1,3),U+7381(3) +U+7304(0);U+7304(0); +U+7305(0);U+7305(0); +U+7306(0);U+7306(0); +U+7307(0);U+7307(0); +U+7308(0);U+7308(3); +U+7309(0);U+7309(0); +U+730A(0);U+730A(5); +U+730B(0);U+730B(4); +U+730C(0);U+730C(0); +U+730D(0);U+730D(0); +U+730E(0);U+730E(1,3);U+7375(1,3) +U+730F(0);U+730F(0); +U+7311(0);U+7311(0); +U+7312(0);U+538C(3);U+538C(3),U+53AD(1,3) +U+7313(0);U+7313(5); +U+7314(0);U+7314(0); +U+7315(0);U+7315(1,3);U+737C(1,3) +U+7316(0);U+7316(5); +U+7317(0);U+7317(5); +U+7318(0);U+7318(0); +U+7319(0);U+72F0(4);U+72F0(4) +U+731A(0);U+731A(0); +U+731B(0);U+731B(5); +U+731C(0);U+731C(5); + +U+731D(0);U+731D(5); +U+731E(0);U+731E(5); +U+7320(0);U+7320(0); +U+7321(0);U+7321(1,3);U+7380(1,3) +U+7322(0);U+7322(5); +U+7323(0);U+7323(0); +U+7324(0);U+7324(0); +U+7325(0);U+7325(5); +U+7326(0);U+7326(0); +U+7327(0);U+7327(0); +U+7329(0);U+7329(5); +U+732A(0);U+732A(5);U+8C6C(2,3) +U+732B(0);U+732B(5);U+8C93(2,3) +U+732C(0);U+732C(5);U+875F(2,3) +U+732D(0);U+732D(0); +U+732E(0);U+732E(1,3);U+737B(1,3) +U+7330(0);U+7330(3); +U+7331(0);U+7331(5); +U+7332(0);U+7332(3); +U+7333(0);U+7333(0); +U+7334(0);U+7334(5); +U+7335(0);U+7335(3); +U+7336(0);U+72B9(1,3);U+72B9(1,3) +U+7337(0);U+7337(5); +U+7338(0);U+7338(5); +U+7339(0);U+7339(5); +U+733A(0);U+733A(0); +U+733B(0);U+72F2(1,3);U+72F2(1,3) +U+733C(0);U+733C(0); +U+733D(0);U+733D(0); +U+733E(0);U+733E(5);U+736A(3),U+72EF(1,3) +U+733F(0);U+733F(5);U+876F(2,3) +U+7340(0);U+7340(0); +U+7341(0);U+72B8(1,3);U+72B8(1,3) +U+7342(0);U+7342(0); +U+7343(0);U+5446(2,3);U+5446(2,3),U+9A03(4) +U+7344(0);U+72F1(1,3);U+72F1(1,3) +U+7345(0);U+72EE(1,3);U+72EE(1,3) +U+7346(0);U+7346(4); +U+7347(0);U+7347(0); +U+7348(0);U+7348(0); +U+7349(0);U+699B(4);U+699B(4),U+6A3C(3,4) +U+734A(0);U+734A(0); +U+734B(0);U+734B(0); +U+734C(0);U+734C(0); +U+734D(0);U+734D(5); +U+734E(0);U+5956(4);U+5956(4),U+5968(8,9),U+596C(2) +U+7350(0);U+7350(5); +U+7351(0);U+7351(3); +U+7352(0);U+7352(5); +U+7354(0);U+7354(0); +U+7355(0);U+7355(0); +U+7356(0);U+7356(0); +U+7357(0);U+7357(5); +U+7358(0);U+7358(0); +U+7359(0);U+7359(3); +U+735A(0);U+735A(0); +U+735B(0);U+735B(0); +U+735C(0);U+735C(3); +U+735D(0);U+735D(3); +U+735E(0);U+50EE(3);U+50EE(3) +U+735F(0);U+735F(0); +U+7360(0);U+7360(5); + +U+7361(0);U+7361(0); +U+7362(0);U+7362(0); +U+7364(0);U+7364(0); +U+7365(0);U+7365(0); +U+7366(0);U+7366(0); +U+7367(0);U+72F7(2);U+72F7(2) +U+7368(0);U+72EC(1,3);U+72EC(1,3) +U+7369(0);U+7369(0); +U+736A(0);U+72EF(1,3);U+72EF(1,3),U+733E(3) +U+736B(0);U+7303(1,3);U+7303(1,3),U+7381(1,3) +U+736C(0);U+736C(5); +U+736D(0);U+736D(1,3);U+737A(1,3) +U+736E(0);U+72DD(4);U+72DD(4) +U+736F(0);U+736F(5); +U+7370(0);U+72DE(1,3);U+72DE(1,3) +U+7371(0);U+7371(0); +U+7372(0);U+83B7(1,3);U+83B7(1,3),U+7A6B(1,3) +U+7373(0);U+7373(0); +U+7374(0);U+7374(0); +U+7375(0);U+730E(1,3);U+730E(1,3) +U+7376(0);U+7376(4); +U+7377(0);U+72B7(1,3);U+72B7(1,3) +U+7378(0);U+517D(1,3);U+517D(1,3) +U+7379(0);U+7379(3); +U+737A(0);U+736D(1,3);U+736D(1,3) +U+737B(0);U+732E(1,3);U+732E(1,3) +U+737C(0);U+7315(1,3);U+7315(1,3) +U+737D(0);U+737D(0); +U+737E(0);U+737E(5); +U+737F(0);U+737F(0); +U+7380(0);U+7321(1,3);U+7321(1,3) +U+7381(0);U+7303(3);U+7303(3),U+736B(1,3) +U+7382(0);U+7382(0); +U+7383(0);U+7383(3);U+8C9C(3) +U+7384(0);U+7384(5); +U+7385(0);U+5999(2,3);U+5999(2,3) +U+7386(0);U+5179(3);U+5179(3),U+8332(3) +U+7387(0);U+7387(5); +U+7388(0);U+7388(0); +U+7389(0);U+7389(5); +U+738A(0);U+738A(3); +U+738B(0);U+738B(5); +U+738C(0);U+738C(0); +U+738D(0);U+738D(0); +U+738E(0);U+738E(5); +U+738F(0);U+738F(0); +U+7390(0);U+7390(0); +U+7391(0);U+7391(1,3);U+74A3(1,3) +U+7392(0);U+7392(3); +U+7393(0);U+7393(0); +U+7394(0);U+7394(0); +U+7395(0);U+7395(3); +U+7396(0);U+7396(5); +U+7397(0);U+7397(0); +U+7398(0);U+7398(0); +U+7399(0);U+7399(4);U+74B5(4) +U+739A(0);U+739A(4);U+7452(4),U+7497(4) +U+739B(0);U+739B(1,3);U+746A(1,3) +U+739D(0);U+739D(0); +U+739E(0);U+739E(3); +U+739F(0);U+739F(5);U+73C9(3),U+741D(3) +U+73A0(0);U+73A0(3); +U+73A1(0);U+73A1(4); + +U+73A2(0);U+73A2(5); +U+73A3(0);U+73A3(0); +U+73A4(0);U+73A4(0); +U+73A5(0);U+73A5(0); +U+73A6(0);U+73A6(3); +U+73A7(0);U+73A7(0); +U+73A8(0);U+73A8(3); +U+73A9(0);U+73A9(5); +U+73AA(0);U+73AA(0); +U+73AB(0);U+73AB(5); +U+73AC(0);U+73AC(0); +U+73AD(0);U+73AD(3); +U+73AE(0);U+73AE(1,3);U+744B(1,3) +U+73AF(0);U+73AF(1,3);U+74B0(1,3) +U+73B0(0);U+73B0(1,3);U+73FE(1,3) +U+73B1(0);U+73B1(1,3);U+7472(1,3) +U+73B2(0);U+73B2(5); +U+73B3(0);U+73B3(5);U+8773(3) +U+73B4(0);U+73B4(0); +U+73B5(0);U+73B5(0); +U+73B6(0);U+73B6(0); +U+73B7(0);U+73B7(5); +U+73B8(0);U+73B8(0); +U+73B9(0);U+73B9(0); +U+73BA(0);U+73BA(1,3);U+74BD(1,3) +U+73BB(0);U+73BB(5); +U+73BC(0);U+73BC(3); +U+73BD(0);U+73BD(0); +U+73BE(0);U+73BE(0); +U+73BF(0);U+73BF(0); +U+73C0(0);U+73C0(5); +U+73C2(0);U+73C2(5); +U+73C3(0);U+73C3(0); +U+73C4(0);U+73C4(0); +U+73C5(0);U+73C5(0); +U+73C6(0);U+73C6(0); +U+73C7(0);U+73C7(0); +U+73C8(0);U+73C8(5); +U+73C9(0);U+73C9(5);U+739F(3),U+741D(3) +U+73CA(0);U+73CA(5); +U+73CB(0);U+73CB(0); +U+73CC(0);U+73CC(0); +U+73CD(0);U+73CD(5);U+73CE(2,3) +U+73CE(0);U+73CD(2,3);U+73CD(2,3) +U+73CF(0);U+73CF(5); +U+73D0(0);U+73D0(5); +U+73D1(0);U+73D1(1,3);U+74CF(1,3) +U+73D2(0);U+73D2(0); +U+73D3(0);U+73D3(3); +U+73D4(0);U+73D4(0); +U+73D5(0);U+73D5(3); +U+73D6(0);U+73D6(0); +U+73D7(0);U+73D7(0); +U+73D8(0);U+73D8(0); +U+73D9(0);U+73D9(5); +U+73DA(0);U+73DA(0); +U+73DB(0);U+73DB(0); +U+73DC(0);U+73DC(0); +U+73DD(0);U+73DD(0); +U+73DE(0);U+73DE(5); +U+73DF(0);U+73DF(0); +U+73E0(0);U+73E0(5); +U+73E2(0);U+73E2(0); + +U+73E3(0);U+73E3(0); +U+73E5(0);U+73E5(5); +U+73E6(0);U+73E6(0); +U+73E7(0);U+73E7(5); +U+73E8(0);U+73E8(0); +U+73E9(0);U+73E9(5); +U+73EA(0);U+572D(3);U+572D(3) +U+73EB(0);U+73EB(0); +U+73EC(0);U+73EC(0); +U+73ED(0);U+73ED(5); +U+73EE(0);U+4F69(4);U+4F69(4) +U+73EF(0);U+73EF(0); +U+73F0(0);U+73F0(4);U+74AB(4) +U+73F1(0);U+73F1(0); +U+73F2(0);U+73F2(1,3);U+743F(1,3) +U+73F4(0);U+73F4(0); +U+73F5(0);U+73F5(0); +U+73F6(0);U+73F6(0);U+7445(3) +U+73F7(0);U+73F7(3); +U+73F8(0);U+73F8(0); +U+73F9(0);U+73F9(0); +U+73FA(0);U+73FA(0); +U+73FC(0);U+73FC(0); +U+73FD(0);U+73FD(3); +U+73FE(0);U+73B0(1,3);U+73B0(1,3) +U+73FF(0);U+73FF(0); +U+7400(0);U+7400(4); +U+7401(0);U+7487(3);U+7487(3),U+74BF(2,3) +U+7402(0);U+7402(0); +U+7403(0);U+7403(5);U+6BEC(2,3) +U+7404(0);U+7404(3); +U+7405(0);U+7405(5);U+746F(2) +U+7406(0);U+7406(5); +U+7407(0);U+7407(0); +U+7408(0);U+7408(3); +U+7409(0);U+7409(5); +U+740A(0);U+740A(5); +U+740B(0);U+740B(0); +U+740C(0);U+9675(4);U+9675(4) +U+740D(0);U+7483(2,3);U+7483(2,3) +U+740E(0);U+740E(1,3);U+74A1(1,3) +U+740F(0);U+740F(1,3);U+7489(1,3) +U+7410(0);U+7410(1,3);U+7463(1,3) +U+7411(0);U+7411(0); +U+7412(0);U+7412(0); +U+7413(0);U+7413(0); +U+7414(0);U+7414(0); +U+7415(0);U+7415(0); +U+7416(0);U+76CF(4);U+76CF(4),U+76DE(1,3,4),U+9186(4) +U+7417(0);U+7417(0); +U+7419(0);U+7419(0); +U+741A(0);U+741A(5); +U+741B(0);U+741B(5);U+8CDD(3) +U+741C(0);U+741C(0); +U+741D(0);U+73C9(3);U+73C9(3),U+739F(3,5) +U+741E(0);U+741E(0); +U+741F(0);U+741F(0); +U+7420(0);U+7420(0); +U+7421(0);U+7421(0); +U+7422(0);U+7422(5); +U+7423(0);U+7423(0); +U+7424(0);U+7424(3); +U+7425(0);U+7425(5); + +U+7426(0);U+7426(5); +U+7427(0);U+7427(0); +U+7428(0);U+7428(5); +U+7429(0);U+7429(0); +U+742A(0);U+742A(5); +U+742B(0);U+742B(3); +U+742C(0);U+742C(5); +U+742D(0);U+742D(0); +U+742E(0);U+742E(5); +U+742F(0);U+742F(3); +U+7430(0);U+7430(5); +U+7431(0);U+96D5(2,3);U+96D5(2,3),U+5F6B(2,3),U+9D70(2,3) +U+7432(0);U+7432(3); +U+7433(0);U+7433(5); +U+7434(0);U+7434(5); +U+7435(0);U+7435(5); +U+7436(0);U+7436(5); +U+7437(0);U+7437(0); +U+7438(0);U+7438(0); +U+743A(0);U+743A(4); +U+743B(0);U+743B(0); +U+743C(0);U+743C(1,3);U+749A(3),U+74CA(1,3) +U+743D(0);U+743D(0); +U+743F(0);U+73F2(1,3);U+73F2(1,3) +U+7440(0);U+7440(0); +U+7441(0);U+7441(5); +U+7442(0);U+7442(0); +U+7443(0);U+7443(0); +U+7444(0);U+7444(3); +U+7445(0);U+7445(3);U+73F6(3) +U+7446(0);U+7446(0); +U+7448(0);U+7448(3); +U+744A(0);U+744A(0); +U+744B(0);U+73AE(1,3);U+73AE(1,3) +U+744C(0);U+744C(0); +U+744D(0);U+744D(0); +U+744E(0);U+744E(0); +U+744F(0);U+744F(0); +U+7450(0);U+7450(0); +U+7451(0);U+7451(0); +U+7452(0);U+739A(4);U+739A(4),U+7497(4) +U+7453(0);U+7453(0); +U+7454(0);U+7454(0); +U+7455(0);U+7455(5); +U+7456(0);U+7456(0); +U+7457(0);U+7457(5); +U+7459(0);U+7459(5);U+78AF(3) +U+745A(0);U+745A(5); +U+745B(0);U+745B(5); +U+745C(0);U+745C(5); +U+745D(0);U+745D(0); +U+745E(0);U+745E(5); +U+745F(0);U+745F(5); +U+7461(0);U+7461(0); +U+7462(0);U+7462(0); +U+7463(0);U+7410(1,3);U+7410(1,3) +U+7464(0);U+7476(4);U+7476(4) +U+7465(0);U+7465(0); +U+7466(0);U+7466(0); +U+7467(0);U+7467(0); +U+7468(0);U+7468(0); +U+7469(0);U+83B9(1,3);U+83B9(1,3) +U+746A(0);U+739B(1,3);U+739B(1,3) + +U+746B(0);U+746B(0); +U+746C(0);U+746C(3); +U+746D(0);U+746D(5); +U+746E(0);U+746E(0); +U+746F(0);U+7405(2);U+7405(2) +U+7470(0);U+7470(5); +U+7471(0);U+7471(4); +U+7472(0);U+73B1(1,3);U+73B1(1,3) +U+7473(0);U+7473(3); +U+7474(0);U+7474(0); +U+7475(0);U+7475(0); +U+7476(0);U+7476(5);U+7464(4) +U+7477(0);U+7477(1,3);U+74A6(1,3) +U+7478(0);U+7478(4);U+74B8(4) +U+7479(0);U+7479(0); +U+747A(0);U+747A(0); +U+747C(0);U+747C(0); +U+747D(0);U+747D(0); +U+747E(0);U+747E(5); +U+747F(0);U+747F(3); +U+7480(0);U+7480(5); +U+7481(0);U+7481(5); +U+7482(0);U+7482(0); +U+7483(0);U+7483(5);U+740D(2,3) +U+7485(0);U+7485(0); +U+7486(0);U+7486(0); +U+7487(0);U+7487(5);U+7401(3),U+74BF(2,3) +U+7488(0);U+7488(0); +U+7489(0);U+740F(1,3);U+740F(1,3) +U+748A(0);U+748A(3); +U+748B(0);U+748B(5); +U+748C(0);U+748C(0); +U+748D(0);U+748D(0); +U+748E(0);U+748E(1,3);U+74D4(1,3) +U+748F(0);U+748F(0); +U+7490(0);U+7490(5); +U+7491(0);U+7491(0); +U+7492(0);U+7492(0); +U+7493(0);U+7493(3); +U+7494(0);U+7494(0); +U+7495(0);U+7495(0); +U+7497(0);U+739A(4);U+739A(4),U+7452(4) +U+7498(0);U+7498(0); +U+7499(0);U+7499(0); +U+749A(0);U+743C(3);U+743C(3),U+74CA(1,3) +U+749B(0);U+749B(0); +U+749C(0);U+749C(5); +U+749E(0);U+749E(5); +U+749F(0);U+749F(3); +U+74A0(0);U+74A0(0); +U+74A1(0);U+740E(1,3);U+740E(1,3) +U+74A3(0);U+7391(1,3);U+7391(1,3) +U+74A4(0);U+74A4(0); +U+74A5(0);U+74A5(0); +U+74A6(0);U+7477(1,3);U+7477(1,3) +U+74A7(0);U+74A7(5); +U+74A8(0);U+74A8(5); +U+74A9(0);U+74A9(5); +U+74AA(0);U+74AA(3); +U+74AB(0);U+73F0(4);U+73F0(4) +U+74AC(0);U+74AC(0); +U+74AD(0);U+74AD(0); +U+74AE(0);U+74AE(0); + +U+74AF(0);U+74AF(0); +U+74B0(0);U+73AF(1,3);U+73AF(1,3) +U+74B1(0);U+74B1(3); +U+74B2(0);U+74B2(0); +U+74B3(0);U+74B3(0); +U+74B4(0);U+74B4(0); +U+74B5(0);U+7399(4);U+7399(4) +U+74B6(0);U+74B6(0); +U+74B7(0);U+74B7(3); +U+74B8(0);U+7478(4);U+7478(4) +U+74B9(0);U+74B9(0); +U+74BA(0);U+74BA(5); +U+74BB(0);U+74BB(0); +U+74BC(0);U+74BC(0); +U+74BD(0);U+73BA(1,3);U+73BA(1,3) +U+74BE(0);U+74BE(0); +U+74BF(0);U+7487(2,3);U+7487(2,3),U+7401(0,2,3) +U+74C0(0);U+74C0(0); +U+74C1(0);U+74C1(0); +U+74C2(0);U+74C2(0); +U+74C3(0);U+74C3(0); +U+74C4(0);U+74C4(0); +U+74C5(0);U+74C5(3); +U+74C6(0);U+74C6(0); +U+74CA(0);U+743C(1,3);U+743C(1,3),U+749A(1,3) +U+74CB(0);U+74CB(0); +U+74CD(0);U+74CD(0); +U+74CE(0);U+74CE(0); +U+74CF(0);U+73D1(1,3);U+73D1(1,3) +U+74D0(0);U+74D0(0); +U+74D1(0);U+74D1(0); +U+74D2(0);U+74D2(1,3);U+74DA(1,3) +U+74D3(0);U+74D3(0); +U+74D4(0);U+748E(1,3);U+748E(1,3) +U+74D5(0);U+74D5(0); +U+74D6(0);U+74D6(0); +U+74D7(0);U+74D7(0); +U+74D8(0);U+74D8(0); +U+74D9(0);U+74D9(0); +U+74DA(0);U+74D2(1,3);U+74D2(1,3) +U+74DB(0);U+74DB(0); +U+74DC(0);U+74DC(5); +U+74DD(0);U+74DD(3); +U+74DE(0);U+74DE(5); +U+74DF(0);U+74DF(0); +U+74E0(0);U+74E0(5); +U+74E1(0);U+6267(3);U+6267(3),U+57F7(0,1,3) +U+74E2(0);U+74E2(5); +U+74E3(0);U+74E3(5); +U+74E4(0);U+74E4(5); +U+74E5(0);U+74E5(0); +U+74E6(0);U+74E6(5); +U+74E7(0);U+74E7(0); +U+74E8(0);U+74E8(0); +U+74E9(0);U+74E9(0); +U+74EA(0);U+74EA(0); +U+74EC(0);U+74EC(0); +U+74ED(0);U+74ED(0); +U+74EE(0);U+74EE(5);U+7515(2,4),U+7F4B(2,3) +U+74EF(0);U+74EF(1,3);U+750C(1,3) +U+74F0(0);U+74F0(0); +U+74F1(0);U+74F1(0); +U+74F2(0);U+74F2(0); + +U+74F3(0);U+74F3(0); +U+74F4(0);U+74F4(5); +U+74F5(0);U+74F5(3); +U+74F6(0);U+74F6(5);U+7501(3),U+7F3E(2) +U+74F7(0);U+74F7(5);U+7506(3) +U+74F8(0);U+74F8(0); +U+74F9(0);U+74F9(0); +U+74FA(0);U+74FA(0); +U+74FB(0);U+74FB(0); +U+74FC(0);U+74FC(0); +U+74FD(0);U+74FD(0); +U+74FE(0);U+74FE(0); +U+74FF(0);U+74FF(5); +U+7500(0);U+7500(0); +U+7501(0);U+74F6(3);U+74F6(3),U+7F3E(2,3) +U+7502(0);U+7502(0); +U+7503(0);U+7503(0); +U+7504(0);U+7504(5); +U+7505(0);U+7505(0); +U+7506(0);U+74F7(3);U+74F7(3) +U+7507(0);U+7F42(3);U+7F42(3),U+7516(2,3),U+7F43(3),U+7F4C(1,3) +U+7508(0);U+7508(0); +U+7509(0);U+7509(0); +U+750A(0);U+750A(0); +U+750B(0);U+750B(0); +U+750C(0);U+74EF(1,3);U+74EF(1,3) +U+750D(0);U+750D(5); +U+750F(0);U+750F(5); +U+7510(0);U+7510(0); +U+7511(0);U+7511(5); +U+7512(0);U+7512(3); +U+7513(0);U+7513(5); +U+7514(0);U+7514(3); +U+7515(0);U+74EE(2,4);U+74EE(2,4),U+7F4B(2,3,4) +U+7516(0);U+7F42(2,3);U+7F42(2,3),U+7507(0,2,3),U+7F43(2,3),U+7F4C(1,2,3) +U+7517(0);U+7517(0); +U+7518(0);U+7518(5); +U+7519(0);U+7519(5); +U+751A(0);U+751A(5); +U+751B(0);U+751C(3);U+751C(3) +U+751C(0);U+751C(5);U+751B(3) +U+751D(0);U+751D(0); +U+751E(0);U+5C1D(4);U+5617(2,3),U+5C1D(4),U+5690(1,2,3,4) +U+751F(0);U+751F(5); +U+7521(0);U+7521(0); +U+7522(0);U+4EA7(4);U+4EA7(4),U+7523(8,9) +U+7523(0);U+4EA7(1,3);U+4EA7(1,3),U+7522(8,9) +U+7524(0);U+7524(0); +U+7525(0);U+7525(5); +U+7526(0);U+82CF(4);U+82CF(4),U+56CC(0,1,3,4),U+8607(1,3,4),U+8613(1,3,4) +U+7527(0);U+7527(0); +U+7528(0);U+7528(5); +U+7529(0);U+7529(5); +U+752A(0);U+752A(0); +U+752B(0);U+752B(5); +U+752C(0);U+752C(5); +U+752D(0);U+752D(5); +U+752E(0);U+752E(0); +U+752F(0);U+752F(5); +U+7530(0);U+7530(5); +U+7531(0);U+7531(5); +U+7532(0);U+7532(5); +U+7533(0);U+7533(5); + +U+7535(0);U+7535(1,3);U+96FB(1,3) +U+7536(0);U+7536(0); +U+7537(0);U+7537(5); +U+7538(0);U+7538(5); +U+7539(0);U+7539(3); +U+753A(0);U+753A(5);U+5722(4) +U+753B(0);U+753B(1,3);U+756B(1,3),U+7575(3) +U+753C(0);U+753C(0); +U+753D(0);U+754E(3);U+754E(3) +U+753E(0);U+753E(5); +U+753F(0);U+6C13(4);U+6C13(4) +U+7540(0);U+7540(5); +U+7542(0);U+7542(0); +U+7543(0);U+7543(0); +U+7544(0);U+7559(4);U+7559(4) +U+7545(0);U+7545(1,3);U+66A2(1,3) +U+7546(0);U+4EA9(4);U+4EA9(4),U+755D(2,3),U+756E(4) +U+7547(0);U+7547(0); +U+7548(0);U+7548(5); +U+7549(0);U+7549(0); +U+754B(0);U+754B(5); +U+754C(0);U+754C(5);U+583A(3),U+754D(3) +U+754D(0);U+754C(3);U+754C(3),U+583A(0,3) +U+754E(0);U+754E(5);U+753D(3) +U+754F(0);U+754F(5);U+6104(4) +U+7550(0);U+7550(0); +U+7551(0);U+7551(0); +U+7553(0);U+7553(0); +U+7554(0);U+7554(5); +U+7556(0);U+7556(0); +U+7557(0);U+7557(0); +U+7558(0);U+7558(0); +U+7559(0);U+7559(5);U+7544(4) +U+755A(0);U+755A(5); +U+755B(0);U+755B(5); +U+755C(0);U+755C(5); +U+755D(0);U+4EA9(1,3);U+4EA9(1,3),U+7546(2,3),U+756E(2,3) +U+755F(0);U+755F(0); +U+7560(0);U+7560(0); +U+7562(0);U+6BD5(1,3);U+6BD5(1,3),U+7F7C(1,3),U+93CE(1,3) +U+7563(0);U+7B54(3);U+7B54(3),U+8345(3,4) +U+7564(0);U+7564(0); +U+7565(0);U+7565(5);U+7567(2) +U+7566(0);U+7566(5); +U+7567(0);U+7565(2);U+7565(2) +U+7568(0);U+7568(0); +U+7569(0);U+7569(0); +U+756A(0);U+756A(5);U+8E6F(3),U+7C75(3) +U+756B(0);U+753B(1,3);U+753B(1,3),U+7575(3) +U+756C(0);U+7572(4);U+756D(3),U+7572(4) +U+756D(0);U+7572(3,4);U+756C(3),U+7572(3,4) +U+756E(0);U+4EA9(4);U+4EA9(4),U+755D(2,3),U+7546(4) +U+756F(0);U+756F(0); +U+7570(0);U+5F02(2,3);U+5F02(2,3) +U+7572(0);U+7572(5);U+756C(4),U+756D(3,4) +U+7574(0);U+7574(1,3);U+7587(1,3) +U+7575(0);U+753B(3);U+753B(3),U+756B(3) +U+7576(0);U+5F53(1,3);U+5679(3,4),U+5F53(1,3) +U+7577(0);U+7577(0); +U+7578(0);U+7578(5); +U+7579(0);U+7579(5); +U+757C(0);U+757C(0); +U+757D(0);U+7583(3);U+7583(3),U+58A5(0,3) + +U+757E(0);U+757E(0); +U+757F(0);U+757F(5); +U+7580(0);U+7580(0); +U+7581(0);U+7581(0); +U+7582(0);U+7582(0); +U+7583(0);U+7583(5);U+58A5(3),U+757D(3) +U+7584(0);U+7584(0); +U+7586(0);U+7586(5); +U+7587(0);U+7574(1,3);U+7574(1,3) +U+7588(0);U+7588(0); +U+7589(0);U+53E0(2,3);U+53E0(2,3),U+758A(3),U+66E1(2),U+8FED(2,4) +U+758A(0);U+53E0(2,3);U+53E0(2,3),U+66E1(3),U+7589(3),U+8FED(3,4) +U+758B(0);U+758B(5);U+5339(2,3) +U+758C(0);U+758C(0); +U+758D(0);U+758D(0); +U+758F(0);U+758F(5);U+8E08(4) +U+7590(0);U+7590(0); +U+7591(0);U+7591(5); +U+7592(0);U+7592(5); +U+7593(0);U+7593(0); +U+7594(0);U+7594(5); +U+7595(0);U+7595(0); +U+7596(0);U+7596(1,3);U+7664(1,3) +U+7597(0);U+7597(1,3);U+7642(1,3) +U+7598(0);U+809B(2,3);U+809B(2,3) +U+7599(0);U+7599(5); +U+759A(0);U+759A(5); +U+759B(0);U+759B(0); +U+759C(0);U+759C(0); +U+759D(0);U+759D(5); +U+759E(0);U+759E(0); +U+759F(0);U+759F(1,3);U+7627(1,3) +U+75A0(0);U+75A0(1,3);U+7658(1,3) +U+75A1(0);U+75A1(1,3);U+760D(1,3) +U+75A2(0);U+75A2(3); +U+75A3(0);U+75A3(5); +U+75A4(0);U+75A4(5); +U+75A5(0);U+75A5(5); +U+75A6(0);U+75A6(0); +U+75A7(0);U+75A7(0); +U+75A8(0);U+75A8(0); +U+75AA(0);U+75F9(3);U+75F9(3),U+75FA(2,3) +U+75AB(0);U+75AB(5); +U+75AC(0);U+75AC(1,3);U+7667(1,3) +U+75AD(0);U+75AD(4);U+7632(4) +U+75AE(0);U+75AE(1,3);U+7621(1,3) +U+75AF(0);U+75AF(1,3);U+760B(1,3) +U+75B0(0);U+75B0(5); +U+75B1(0);U+75B1(5);U+76B0(2) +U+75B2(0);U+75B2(5); +U+75B3(0);U+75B3(5); +U+75B4(0);U+75B4(5); +U+75B5(0);U+75B5(5); +U+75B6(0);U+75B6(0); +U+75B8(0);U+75B8(5); +U+75B9(0);U+75B9(5); +U+75BA(0);U+75BA(0); +U+75BB(0);U+75BB(0); +U+75BC(0);U+75BC(5); +U+75BD(0);U+75BD(5); +U+75BE(0);U+75BE(5); +U+75BF(0);U+75F1(2);U+75F1(2) +U+75C0(0);U+75C0(0); + +U+75C1(0);U+75C1(0); +U+75C2(0);U+75C2(5); +U+75C3(0);U+75C3(5); +U+75C4(0);U+75C4(5); +U+75C5(0);U+75C5(5); +U+75C6(0);U+75C6(0); +U+75C7(0);U+75C7(1,3);U+7665(1,3,4) +U+75C8(0);U+75C8(1,3);U+7670(1,3) +U+75C9(0);U+75C9(1,3);U+75D9(1,3) +U+75CA(0);U+75CA(5); +U+75CB(0);U+75CB(0); +U+75CC(0);U+606B(3);U+606B(3) +U+75CD(0);U+75CD(5); +U+75CE(0);U+75CE(0); +U+75CF(0);U+75CF(0); +U+75D0(0);U+86D4(2,3);U+86D4(2,3),U+8698(2,3),U+8716(2,3) +U+75D1(0);U+75D1(0); +U+75D2(0);U+75D2(1,3);U+7662(1,3) +U+75D3(0);U+75D3(0); +U+75D4(0);U+75D4(5); +U+75D5(0);U+75D5(5); +U+75D6(0);U+75D6(4);U+54D1(7),U+5516(7),U+555E(4),U+7602(4) +U+75D7(0);U+75D7(0); +U+75D8(0);U+75D8(5); +U+75D9(0);U+75C9(1,3);U+75C9(1,3) +U+75DA(0);U+75DA(0); +U+75DB(0);U+75DB(5); +U+75DD(0);U+75DD(0); +U+75DE(0);U+75DE(5); +U+75DF(0);U+75DF(0); +U+75E0(0);U+75E0(0); +U+75E1(0);U+75E1(0); +U+75E2(0);U+75E2(5);U+9B01(4) +U+75E3(0);U+75E3(5); +U+75E4(0);U+75E4(5); +U+75E5(0);U+75E5(0); +U+75E6(0);U+75E6(5); +U+75E7(0);U+75E7(5); +U+75E8(0);U+75E8(1,3);U+7646(1,3) +U+75EA(0);U+75EA(4);U+7613(4) +U+75EB(0);U+75EB(1,3);U+7647(1,3) +U+75EC(0);U+75EC(0); +U+75ED(0);U+75ED(0); +U+75EF(0);U+75EF(0); +U+75F0(0);U+75F0(5); +U+75F1(0);U+75F1(5);U+75BF(2) +U+75F2(0);U+9EBB(3);U+9EBB(3),U+75F3(3,4),U+8534(2,3),U+6DCB(2,3,4,5) +U+75F3(0);U+6DCB(2,3);U+6DCB(2,3),U+9EBB(4),U+75F2(0,3,4),U+8534(2,3,4) +U+75F4(0);U+75F4(5);U+7661(2,3) +U+75F5(0);U+60B8(3,4);U+60B8(3,4) +U+75F6(0);U+75F6(0); +U+75F7(0);U+75F7(0); +U+75F8(0);U+75F8(0); +U+75F9(0);U+75F9(5);U+75AA(3),U+75FA(2) +U+75FA(0);U+75F9(2);U+75F9(2),U+75AA(0,2,3) +U+75FB(0);U+75FB(0); +U+75FC(0);U+75FC(5); +U+75FD(0);U+75FD(0); +U+75FE(0);U+75FE(0); +U+75FF(0);U+75FF(5); +U+7600(0);U+7600(5); +U+7601(0);U+7601(5); +U+7602(0);U+75D6(4);U+54D1(7),U+5516(7),U+555E(3),U+75D6(4) + +U+7603(0);U+7603(5); +U+7604(0);U+7604(0); +U+7605(0);U+7605(1,3);U+7649(1,3) +U+7606(0);U+7606(1,3);U+762E(1,3) +U+7607(0);U+7607(0); +U+7608(0);U+7608(0); +U+7609(0);U+6108(2,3);U+6108(2,3),U+7652(2,3) +U+760A(0);U+760A(5); +U+760B(0);U+75AF(1,3);U+75AF(1,3) +U+760C(0);U+760C(5);U+9B0E(4) +U+760D(0);U+75A1(1,3);U+75A1(1,3) +U+760E(0);U+760E(0); +U+760F(0);U+760F(0); +U+7610(0);U+7610(5); +U+7611(0);U+8717(4);U+8717(4),U+8778(1,3,4) +U+7612(0);U+7612(0); +U+7613(0);U+75EA(4);U+75EA(4) +U+7614(0);U+82E6(3);U+82E6(3) +U+7615(0);U+7615(5); +U+7616(0);U+5591(2);U+5591(2),U+567E(2,3) +U+7617(0);U+7617(1,3);U+761E(1,3) +U+7618(0);U+7618(1,3);U+763A(3),U+763B(1,3) +U+7619(0);U+7619(5); +U+761A(0);U+761A(3); +U+761B(0);U+761B(5); +U+761C(0);U+761C(0); +U+761D(0);U+761D(3); +U+761E(0);U+7617(1,3);U+7617(1,3) +U+761F(0);U+761F(5); +U+7620(0);U+7620(5);U+818C(3) +U+7621(0);U+75AE(1,3);U+75AE(1,3) +U+7622(0);U+7622(5); +U+7623(0);U+574F(4);U+574F(4),U+576F(4),U+58CA(4),U+58DE(1,3,4) +U+7624(0);U+7624(5); +U+7625(0);U+7625(5); +U+7626(0);U+7626(5); +U+7627(0);U+759F(1,3);U+759F(1,3) +U+7628(0);U+766B(3);U+766B(3),U+7672(1,3) +U+7629(0);U+7629(5); +U+762A(0);U+762A(1,3);U+765F(1,3) +U+762B(0);U+762B(1,3);U+7671(1,3) +U+762D(0);U+762D(5); +U+762E(0);U+7606(1,3);U+7606(1,3) +U+762F(0);U+762F(0); +U+7630(0);U+7630(5); +U+7631(0);U+7631(0); +U+7632(0);U+75AD(4);U+75AD(4) +U+7633(0);U+7633(5); +U+7634(0);U+7634(5); +U+7635(0);U+7635(5); +U+7636(0);U+7636(0); +U+7637(0);U+7637(0); +U+7638(0);U+7638(5); +U+7639(0);U+7639(0); +U+763A(0);U+7618(3);U+7618(3),U+763B(3) +U+763B(0);U+7618(1,3);U+7618(1,3),U+763A(3) +U+763C(0);U+763C(5); +U+763D(0);U+52E4(3);U+52E4(3),U+61C3(2,3) +U+763E(0);U+763E(1,3);U+766E(1,3) +U+763F(0);U+763F(1,3);U+766D(1,3) +U+7640(0);U+7640(5); +U+7641(0);U+7641(0); +U+7642(0);U+7597(1,3);U+7597(1,3) + +U+7643(0);U+7643(5); +U+7646(0);U+75E8(1,3);U+75E8(1,3) +U+7647(0);U+75EB(1,3);U+75EB(1,3) +U+7648(0);U+5E9F(2);U+5E9F(2),U+5EC3(2,4),U+5EE2(1,2,3) +U+7649(0);U+7605(1,3);U+7605(1,3) +U+764A(0);U+764A(0); +U+764B(0);U+764B(0); +U+764C(0);U+764C(5); +U+764D(0);U+764D(5); +U+764F(0);U+764F(0); +U+7650(0);U+7650(0); +U+7652(0);U+6108(2);U+6108(2),U+7609(2,3) +U+7653(0);U+7653(0); +U+7654(0);U+7654(5); +U+7656(0);U+7656(5); +U+7657(0);U+7657(0); +U+7658(0);U+75A0(1,3);U+75A0(1,3) +U+7659(0);U+7659(0); +U+765A(0);U+765A(0); +U+765B(0);U+765D(4);U+765D(4) +U+765C(0);U+765C(5); +U+765D(0);U+765D(4);U+765B(4) +U+765E(0);U+765E(1,3);U+7669(1,3) +U+765F(0);U+762A(1,3);U+762A(1,3) +U+7660(0);U+7660(0); +U+7661(0);U+75F4(2,3);U+75F4(2,3) +U+7662(0);U+75D2(1,3);U+75D2(1,3) +U+7663(0);U+7663(1,3);U+766C(1,3) +U+7664(0);U+7596(1,3);U+7596(1,3) +U+7665(0);U+75C7(1,3);U+75C7(1,3) +U+7666(0);U+7666(0); +U+7667(0);U+75AC(1,3);U+75AC(1,3) +U+7668(0);U+970D(7);U+970D(7) +U+7669(0);U+765E(1,3);U+765E(1,3) +U+766A(0);U+766A(0); +U+766B(0);U+766B(1,3);U+7628(3),U+7672(1,3) +U+766C(0);U+7663(1,3);U+7663(1,3) +U+766D(0);U+763F(1,3);U+763F(1,3) +U+766E(0);U+763E(1,3);U+763E(1,3) +U+766F(0);U+766F(5); +U+7670(0);U+75C8(1,3);U+75C8(1,3) +U+7671(0);U+762B(1,3);U+762B(1,3) +U+7672(0);U+766B(1,3);U+766B(1,3),U+7628(0,1,3) +U+7674(0);U+7674(0); +U+7675(0);U+7675(0); +U+7676(0);U+7676(0); +U+7677(0);U+7677(0); +U+7678(0);U+7678(5); +U+7679(0);U+7679(3); +U+767B(0);U+767B(5);U+8C4B(4) +U+767C(0);U+53D1(1,3);U+53D1(1,3),U+5F42(4),U+9AEA(1,3,4),U+9AEE(1,3) +U+767D(0);U+767D(5); +U+767E(0);U+767E(5); +U+767F(0);U+767F(0); +U+7680(0);U+7680(0); +U+7681(0);U+7682(2);U+7682(2) +U+7682(0);U+7682(5);U+7681(2) +U+7683(0);U+8C8C(3);U+8C8C(3) +U+7684(0);U+7684(5); +U+7685(0);U+7685(0); +U+7686(0);U+7686(5); +U+7687(0);U+7687(5); +U+7688(0);U+7688(5);U+6B78(3),U+5E30(0,3),U+5F52(3) + +U+7689(0);U+7689(0); +U+768A(0);U+768A(0); +U+768B(0);U+768B(5);U+7690(2,3) +U+768C(0);U+768C(0); +U+768E(0);U+768E(5);U+76A6(3) +U+768F(0);U+768F(0); +U+7690(0);U+768B(2,3);U+768B(2,3) +U+7691(0);U+7691(1,3);U+769A(1,3) +U+7692(0);U+7692(0); +U+7693(0);U+7693(5);U+66A0(2,3),U+769C(2,3) +U+7694(0);U+7694(0); +U+7695(0);U+7695(0); +U+7696(0);U+7696(5);U+6665(3) +U+7697(0);U+7697(0); +U+7698(0);U+7698(0); +U+7699(0);U+7699(5); +U+769A(0);U+7691(1,3);U+7691(1,3) +U+769B(0);U+769B(0); +U+769C(0);U+7693(2,3);U+7693(2,3),U+66A0(0,2,3) +U+769D(0);U+769D(0); +U+769E(0);U+769E(3); +U+769F(0);U+769F(0); +U+76A0(0);U+76A0(0); +U+76A3(0);U+76A3(0); +U+76A4(0);U+76A4(5); +U+76A6(0);U+768E(3);U+768E(3) +U+76A7(0);U+76A7(0); +U+76A9(0);U+76A9(0); +U+76AA(0);U+76AA(0); +U+76AB(0);U+76AB(0); +U+76AC(0);U+76AC(0); +U+76AD(0);U+76AD(0); +U+76AE(0);U+76AE(5); +U+76AF(0);U+76AF(0); +U+76B0(0);U+75B1(2);U+75B1(2) +U+76B1(0);U+76B1(1,3);U+76BA(1,3) +U+76B2(0);U+76B2(1,3);U+76B8(1,3) +U+76B4(0);U+76B4(5); +U+76B5(0);U+76B5(0); +U+76B7(0);U+9F13(2,3);U+9F13(2,3),U+76BC(2,3,7) +U+76B8(0);U+76B2(1,3);U+76B2(1,3) +U+76BA(0);U+76B1(1,3);U+76B1(1,3) +U+76BB(0);U+76BB(4); +U+76BC(0);U+9F13(7);U+9F13(7),U+76B7(0,2,3,7) +U+76BD(0);U+76BD(0); +U+76BE(0);U+76BE(0); +U+76BF(0);U+76BF(5); +U+76C0(0);U+76C0(0); +U+76C2(0);U+76C2(5); +U+76C3(0);U+676F(2,3);U+676F(2,3),U+686E(2,3) +U+76C4(0);U+76C4(0); +U+76C5(0);U+76C5(5);U+6C96(3),U+51B2(1,3,4),U+794C(3,4),U+885D(1,3,4),U+8876(3,4) +U+76C6(0);U+76C6(5); +U+76C7(0);U+76CD(2);U+76CD(2) +U+76C8(0);U+76C8(5); +U+76C9(0);U+76C9(0); +U+76CA(0);U+76CA(5); +U+76CD(0);U+76CD(5);U+76C7(2) +U+76CE(0);U+76CE(5); +U+76CF(0);U+76CF(1,3);U+7416(4),U+76DE(1,3),U+9186(4) +U+76D0(0);U+76D0(1,3);U+5869(3),U+9E7D(1,3) +U+76D1(0);U+76D1(1,3);U+76E3(1,3) +U+76D2(0);U+76D2(5); + +U+76D3(0);U+76D3(0); +U+76D4(0);U+76D4(5); +U+76D5(0);U+76D5(0); +U+76D6(0);U+76D6(1,3);U+8462(3),U+84CB(1,3) +U+76D7(0);U+76D7(5);U+76DC(3) +U+76D8(0);U+76D8(1,3);U+6D00(3),U+76E4(1,3) +U+76DA(0);U+76DA(0); +U+76DB(0);U+76DB(5); +U+76DC(0);U+76D7(3);U+76D7(3) +U+76DD(0);U+76DD(0); +U+76DE(0);U+76CF(1,3);U+76CF(1,3),U+7416(0,1,3,4),U+9186(1,3,4) +U+76DF(0);U+76DF(5); +U+76E0(0);U+76E0(0); +U+76E1(0);U+5C3D(1,3);U+5118(4),U+5C3D(1,3) +U+76E2(0);U+76E2(0); +U+76E3(0);U+76D1(1,3);U+76D1(1,3) +U+76E4(0);U+76D8(1,3);U+76D8(1,3),U+6D00(0,1,3) +U+76E5(0);U+76E5(5); +U+76E6(0);U+76E6(3); +U+76E7(0);U+5362(1,3);U+5362(1,3) +U+76E8(0);U+76E8(0); +U+76E9(0);U+76E9(0); +U+76EA(0);U+76EA(3);U+8361(4),U+8569(2,3),U+6F52(0,3,4),U+862F(3,4) +U+76EC(0);U+76EC(0); +U+76ED(0);U+623E(4);U+623E(4),U+623B(0,4) +U+76EE(0);U+76EE(5); +U+76EF(0);U+76EF(5); +U+76F0(0);U+76F0(0); +U+76F1(0);U+76F1(5); +U+76F2(0);U+76F2(5);U+76F3(3) +U+76F3(0);U+76F2(3);U+76F2(3) +U+76F4(0);U+76F4(5); +U+76F5(0);U+76F5(0); +U+76F6(0);U+76F6(0); +U+76F7(0);U+76F7(0); +U+76F8(0);U+76F8(5); +U+76F9(0);U+76F9(5); +U+76FA(0);U+76FA(0); +U+76FB(0);U+76FB(0); +U+76FC(0);U+76FC(5); +U+76FD(0);U+76FD(0); +U+76FE(0);U+76FE(5); +U+76FF(0);U+76FF(3); +U+7701(0);U+7701(5); +U+7703(0);U+7703(0); +U+7704(0);U+7704(5); +U+7705(0);U+7705(0); +U+7706(0);U+7706(3); +U+7707(0);U+7707(5); +U+7708(0);U+7708(5); +U+7709(0);U+7709(5); +U+770A(0);U+770A(3); +U+770B(0);U+770B(5); +U+770C(0);U+770C(0); +U+770D(0);U+770D(1,3);U+7798(1,3) +U+770F(0);U+770F(0); +U+7710(0);U+7710(0); +U+7711(0);U+7711(0); +U+7712(0);U+7712(3); +U+7713(0);U+7713(0); +U+7714(0);U+7714(0); +U+7715(0);U+7715(0); +U+7716(0);U+7716(0); + +U+7717(0);U+7717(0); +U+7718(0);U+614E(3);U+614E(3),U+613C(0,3,4),U+661A(2,3,4) +U+7719(0);U+7719(5); +U+771A(0);U+771A(5); +U+771B(0);U+771B(0); +U+771C(0);U+771C(0); +U+771D(0);U+771D(0); +U+771E(0);U+771F(3);U+771F(3) +U+771F(0);U+771F(5);U+771E(3) +U+7720(0);U+7720(5); +U+7722(0);U+7722(5); +U+7723(0);U+7723(3); +U+7725(0);U+7725(3); +U+7726(0);U+7726(5); +U+7727(0);U+7727(0); +U+7728(0);U+7728(5); +U+7729(0);U+7729(5); +U+772A(0);U+772A(0); +U+772C(0);U+772C(4);U+77D3(4) +U+772D(0);U+772D(5); +U+772E(0);U+772E(0); +U+772F(0);U+772F(5);U+7787(2,3) +U+7730(0);U+7730(0); +U+7731(0);U+7731(0); +U+7732(0);U+7732(0); +U+7733(0);U+7733(0); +U+7734(0);U+7734(3); +U+7735(0);U+7735(5); +U+7736(0);U+7736(5); +U+7737(0);U+7737(5);U+7760(2,3) +U+7738(0);U+7738(5); +U+7739(0);U+7739(0); +U+773A(0);U+773A(5);U+899C(2,3) +U+773B(0);U+773B(0); +U+773C(0);U+773C(5); +U+773D(0);U+773D(3); +U+773E(0);U+4F17(4);U+4F17(4),U+8846(2) +U+7740(0);U+7740(5);U+8457(4) +U+7741(0);U+7741(4);U+775C(4) +U+7743(0);U+7743(5); +U+7744(0);U+7744(0); +U+7745(0);U+7745(0); +U+7746(0);U+7746(0); +U+7747(0);U+7747(5); +U+7748(0);U+7748(0); +U+7749(0);U+7749(0); +U+774A(0);U+774A(0); +U+774B(0);U+774B(0); +U+774C(0);U+774C(0); +U+774D(0);U+774D(0); +U+774E(0);U+774E(3); +U+774F(0);U+56F0(1);U+56F0(1) +U+7750(0);U+7750(1,3);U+775E(1,3) +U+7751(0);U+7751(1,3);U+77BC(1,3) +U+7752(0);U+7752(0); +U+7753(0);U+7753(0); +U+7754(0);U+7754(0); +U+7755(0);U+7755(0); +U+7756(0);U+7756(0); +U+7757(0);U+7757(0); +U+7758(0);U+7758(0); +U+7759(0);U+7759(0); +U+775A(0);U+775A(5); + +U+775B(0);U+775B(5); +U+775C(0);U+7741(4);U+7741(4) +U+775D(0);U+775D(0); +U+775E(0);U+7750(1,3);U+7750(1,3) +U+775F(0);U+775F(3); +U+7760(0);U+7737(2,3);U+7737(2,3) +U+7761(0);U+7761(5); +U+7762(0);U+7762(5); +U+7763(0);U+7763(5); +U+7765(0);U+7765(5); +U+7766(0);U+7766(5); +U+7767(0);U+7767(0); +U+7768(0);U+7768(5); +U+7769(0);U+7769(0); +U+776A(0);U+776A(4);U+777E(3,4) +U+776B(0);U+776B(5); +U+776C(0);U+776C(5); +U+776D(0);U+776D(0); +U+776E(0);U+776E(0); +U+776F(0);U+776F(0); +U+7770(0);U+7770(0); +U+7771(0);U+7771(0); +U+7772(0);U+7772(0); +U+7773(0);U+7773(0); +U+7774(0);U+7774(0); +U+7775(0);U+7775(0); +U+7776(0);U+7776(0); +U+7777(0);U+7777(0); +U+7778(0);U+7778(0); +U+7779(0);U+7779(5); +U+777A(0);U+777A(0); +U+777B(0);U+777B(0); +U+777C(0);U+777C(3); +U+777D(0);U+777D(5); +U+777E(0);U+777E(5);U+776A(3,4) +U+777F(0);U+777F(5);U+53E1(2,3) +U+7780(0);U+7780(5); +U+7781(0);U+7781(3); +U+7782(0);U+7782(3); +U+7783(0);U+7783(0); +U+7784(0);U+7784(5); +U+7785(0);U+7785(5);U+5062(7) +U+7786(0);U+7786(4);U+77B6(4) +U+7787(0);U+772F(2,3);U+772F(2,3) +U+7788(0);U+7788(0); +U+7789(0);U+7789(0); +U+778A(0);U+778A(0); +U+778B(0);U+778B(0); +U+778C(0);U+778C(5); +U+778D(0);U+778D(5); +U+778E(0);U+778E(5); +U+778F(0);U+778F(3); +U+7790(0);U+7790(0); +U+7791(0);U+7791(5); +U+7792(0);U+7792(1,3);U+779E(1,3) +U+7793(0);U+7793(0); +U+7794(0);U+7794(0); +U+7795(0);U+7795(0); +U+7797(0);U+7797(0); +U+7798(0);U+770D(1,3);U+770D(1,3) +U+7799(0);U+7799(0); +U+779A(0);U+77AC(3);U+77AC(3) +U+779B(0);U+779B(0); + +U+779C(0);U+4056(1,3);U+4056(1,3) +U+779D(0);U+779D(0); +U+779E(0);U+7792(1,3);U+7792(1,3) +U+779F(0);U+779F(5); +U+77A0(0);U+77A0(5); +U+77A1(0);U+77A1(0); +U+77A2(0);U+77A2(5); +U+77A3(0);U+77A3(0); +U+77A5(0);U+77A5(5);U+8995(3) +U+77A6(0);U+77A6(0); +U+77A7(0);U+77A7(5); +U+77A8(0);U+77A8(0); +U+77A9(0);U+77A9(1,3);U+77DA(1,3) +U+77AA(0);U+77AA(5); +U+77AB(0);U+77AB(0); +U+77AC(0);U+77AC(5);U+779A(3) +U+77AD(0);U+77AD(0),U+4E86(1,3);U+4E86(1,3),U+66B8(1,3,4,7) +U+77AE(0);U+77AE(0); +U+77AF(0);U+77AF(3); +U+77B0(0);U+77B0(5);U+77D9(2,3) +U+77B1(0);U+77B1(0); +U+77B2(0);U+77B2(0); +U+77B3(0);U+77B3(5); +U+77B4(0);U+77B4(0); +U+77B5(0);U+77B5(5); +U+77B6(0);U+7786(4);U+7786(4) +U+77B7(0);U+77B7(0); +U+77B8(0);U+77B8(0); +U+77B9(0);U+77B9(0); +U+77BA(0);U+77BA(0); +U+77BB(0);U+77BB(5); +U+77BC(0);U+7751(1,3);U+7751(1,3) +U+77BD(0);U+77BD(5); +U+77BF(0);U+77BF(5); +U+77C0(0);U+77C0(0); +U+77C2(0);U+77C2(0); +U+77C3(0);U+77C3(0); +U+77C4(0);U+77C4(0); +U+77C5(0);U+77C5(0); +U+77C6(0);U+77C6(0); +U+77C7(0);U+8499(1);U+8499(1),U+61DE(0,1,4),U+6FDB(1,3,4) +U+77C8(0);U+77C8(3);U+77CF(8,9) +U+77C9(0);U+77C9(0); +U+77CA(0);U+77CA(0); +U+77CB(0);U+77CB(0); +U+77CC(0);U+77CC(0); +U+77CD(0);U+77CD(5); +U+77CE(0);U+77CE(0); +U+77CF(0);U+77CF(0);U+77C8(8,9) +U+77D0(0);U+77D0(0); +U+77D1(0);U+77D1(3); +U+77D3(0);U+772C(4);U+772C(4) +U+77D4(0);U+77D4(0); +U+77D5(0);U+77D5(0); +U+77D6(0);U+77D6(0); +U+77D7(0);U+77D7(5); +U+77D8(0);U+77D8(0); +U+77D9(0);U+77B0(2,3);U+77B0(2,3) +U+77DA(0);U+77A9(1,3);U+77A9(1,3) +U+77DB(0);U+77DB(5); +U+77DC(0);U+77DC(5); +U+77DE(0);U+77DE(3); +U+77DF(0);U+77DF(4);U+9399(4) + +U+77E0(0);U+77E0(0); +U+77E1(0);U+77E1(0); +U+77E2(0);U+77E2(5);U+7B36(3) +U+77E3(0);U+77E3(5); +U+77E5(0);U+77E5(5); +U+77E7(0);U+77E7(5); +U+77E8(0);U+77E8(0); +U+77E9(0);U+77E9(5);U+6998(2,3) +U+77EA(0);U+77EA(0); +U+77EB(0);U+77EB(1,3);U+77EF(1,3) +U+77EC(0);U+77EC(5);U+9073(3) +U+77ED(0);U+77ED(5); +U+77EE(0);U+77EE(5); +U+77EF(0);U+77EB(1,3);U+77EB(1,3) +U+77F0(0);U+77F0(0); +U+77F1(0);U+77F1(0); +U+77F2(0);U+77F2(3); +U+77F3(0);U+77F3(5); +U+77F6(0);U+77F6(1,3);U+78EF(1,3) +U+77F7(0);U+77F7(0); +U+77F8(0);U+77F8(5); +U+77F9(0);U+77F9(0); +U+77FA(0);U+77FA(0); +U+77FB(0);U+77FB(0); +U+77FC(0);U+77FC(0); +U+77FD(0);U+77FD(5); +U+77FE(0);U+77FE(1,3);U+792C(1,3) +U+77FF(0);U+77FF(1,3);U+7926(1,3),U+945B(4) +U+7800(0);U+7800(1,3);U+78AD(1,3) +U+7801(0);U+7801(1,3);U+78BC(1,3) +U+7802(0);U+7802(5); +U+7803(0);U+7803(0); +U+7804(0);U+7804(0); +U+7805(0);U+7805(3); +U+7806(0);U+7806(0); +U+7808(0);U+7808(0); +U+7809(0);U+7809(5); +U+780A(0);U+780A(0); +U+780B(0);U+780B(0); +U+780C(0);U+780C(5); +U+780D(0);U+780D(5); +U+780E(0);U+780E(0); +U+780F(0);U+780F(0); +U+7810(0);U+7810(0); +U+7811(0);U+7811(5); +U+7812(0);U+7812(5); +U+7813(0);U+7813(0); +U+7814(0);U+7814(5);U+63C5(3) +U+7815(0);U+788E(3);U+788E(3) +U+7816(0);U+7816(1,3);U+78DA(1,3) +U+7817(0);U+7817(1,3);U+7868(1,3) +U+7818(0);U+7818(5); +U+7819(0);U+7819(0); +U+781A(0);U+781A(1,3);U+786F(1,3) +U+781B(0);U+781B(0); +U+781C(0);U+781C(1,3);U+78B8(1,3) +U+781D(0);U+781D(5); +U+781E(0);U+781E(0); +U+781F(0);U+781F(5); +U+7820(0);U+7820(4); +U+7821(0);U+7821(0); +U+7822(0);U+7822(0); +U+7823(0);U+7823(5);U+78A2(3) + +U+7825(0);U+7825(5); +U+7826(0);U+7826(5); +U+7827(0);U+7827(5);U+78AA(2,3) +U+7828(0);U+7828(3); +U+7829(0);U+7829(5); +U+782A(0);U+782A(0); +U+782B(0);U+67F1(3);U+67F1(3) +U+782C(0);U+782C(5); +U+782D(0);U+782D(5); +U+782E(0);U+782E(0); +U+782F(0);U+782F(3); +U+7830(0);U+7830(5); +U+7831(0);U+7831(0); +U+7832(0);U+70AE(2,3);U+70AE(2,3),U+792E(3,4),U+70B0(2,3) +U+7833(0);U+7833(0); +U+7834(0);U+7834(5); +U+7835(0);U+7835(0); +U+7837(0);U+7837(5); +U+7838(0);U+7838(5); +U+7839(0);U+7839(5); +U+783A(0);U+783A(1,3);U+792A(1,3) +U+783B(0);U+783B(1,3);U+7931(1,3),U+9468(3) +U+783C(0);U+783C(5); +U+783D(0);U+783D(0); +U+783E(0);U+783E(1,3);U+792B(1,3) +U+7840(0);U+7840(1,3);U+790E(1,3) +U+7841(0);U+7841(4);U+785C(4) +U+7843(0);U+6731(1);U+6731(1) +U+7844(0);U+7844(0); +U+7845(0);U+7845(5); +U+7847(0);U+7847(5); +U+7848(0);U+7848(3); +U+7849(0);U+7849(0); +U+784A(0);U+784A(3); +U+784C(0);U+784C(5); +U+784D(0);U+784D(0); +U+784E(0);U+784E(5); +U+7850(0);U+7850(5); +U+7851(0);U+7851(0); +U+7852(0);U+7852(5); +U+7853(0);U+7853(0); +U+7854(0);U+7854(0); +U+7855(0);U+7855(1,3);U+78A9(1,3) +U+7856(0);U+7856(1,3);U+7864(1,3) +U+7857(0);U+7857(1,3);U+78FD(1,3) +U+7858(0);U+7858(0); +U+7859(0);U+7859(1,3);U+78A8(4),U+78D1(1,3) +U+785A(0);U+785A(1,3);U+7904(1,3) +U+785B(0);U+785B(0); +U+785C(0);U+7841(4);U+7841(4) +U+785D(0);U+785D(5); +U+785E(0);U+785E(0); +U+785F(0);U+785F(0); +U+7860(0);U+7860(0); +U+7861(0);U+7861(0); +U+7862(0);U+7862(0); +U+7863(0);U+7863(0); +U+7864(0);U+7856(1,3);U+7856(1,3) +U+7865(0);U+868C(4);U+868C(4) +U+7866(0);U+7866(0); +U+7867(0);U+7867(0); +U+7868(0);U+7817(1,3);U+7817(1,3) +U+7869(0);U+7869(0); + +U+786A(0);U+786A(5); +U+786B(0);U+786B(5); +U+786C(0);U+786C(5);U+5CFA(3) +U+786D(0);U+786D(5); +U+786E(0);U+786E(1,3,4);U+5859(4),U+78BA(1,3),U+78BB(4),U+792D(3) +U+786F(0);U+781A(1,3);U+781A(1,3) +U+7870(0);U+7870(0); +U+7871(0);U+7871(0); +U+7872(0);U+7872(0); +U+7873(0);U+7873(0); +U+7874(0);U+7874(0); +U+7875(0);U+7875(4);U+78E0(4) +U+7877(0);U+7877(1,3);U+7906(4),U+96AA(3,4),U+9E7C(1,3,4),U+9669(3,4),U+78B1(1,3,4) +U+7878(0);U+7878(0); +U+7879(0);U+7879(0); +U+787A(0);U+787A(0); +U+787B(0);U+787B(0); +U+787C(0);U+787C(5); +U+787D(0);U+787D(0); +U+787E(0);U+787E(3); +U+787F(0);U+787F(0); +U+7880(0);U+7880(0); +U+7881(0);U+68CB(2,3);U+68CB(2,3),U+68CA(0,2,3) +U+7882(0);U+7882(0); +U+7883(0);U+7883(0); +U+7884(0);U+7884(0); +U+7885(0);U+7885(0); +U+7886(0);U+7886(0); +U+7887(0);U+7887(5);U+6917(2,3) +U+7889(0);U+7889(5); +U+788A(0);U+788A(0); +U+788B(0);U+788B(0); +U+788C(0);U+788C(5);U+78DF(2,3) +U+788D(0);U+788D(1,3);U+7919(1,3) +U+788E(0);U+788E(5);U+7815(3) +U+788F(0);U+788F(0); +U+7890(0);U+7890(0); +U+7891(0);U+7891(5); +U+7892(0);U+7892(0); +U+7893(0);U+7893(5); +U+7894(0);U+7894(0); +U+7895(0);U+5D0E(7);U+57FC(3),U+5D0E(7) +U+7896(0);U+7896(0); +U+7897(0);U+7897(5);U+92FA(3) +U+7898(0);U+7898(5); +U+7899(0);U+7899(0); +U+789A(0);U+789A(5); +U+789B(0);U+789B(1,3);U+78E7(1,3) +U+789C(0);U+789C(1,3);U+78E3(1,3) +U+789D(0);U+789D(3);U+791D(3) +U+789E(0);U+5CA9(3);U+5CA9(3),U+55A6(0,3,4),U+5D52(2,3,4),U+58E7(3,4),U+5DCC(3,4),U+5DD6(2,3,4),U+7939(3,4) + +U+789F(0);U+789F(5); +U+78A0(0);U+78A0(0); +U+78A1(0);U+78A1(5); +U+78A2(0);U+7823(3);U+7823(3) +U+78A3(0);U+78A3(5); +U+78A4(0);U+78A4(0); +U+78A5(0);U+78A5(5); +U+78A6(0);U+78A6(0); +U+78A7(0);U+78A7(5); +U+78A8(0);U+7859(4);U+7859(4),U+78D1(1,3,4) +U+78A9(0);U+7855(1,3);U+7855(1,3) + +U+78AA(0);U+7827(2,3);U+7827(2,3) +U+78AB(0);U+78AB(0); +U+78AC(0);U+78AC(0); +U+78AD(0);U+7800(1,3);U+7800(1,3) +U+78AE(0);U+78AE(0); +U+78AF(0);U+7459(3);U+7459(3) +U+78B0(0);U+78B0(5);U+63BD(2),U+8E2B(2,3) +U+78B1(0);U+78B1(5);U+9E7C(3,4),U+7877(1,3,4),U+7906(1,3,4),U+96AA(1,3,4),U+9669(1,3,4) + +U+78B2(0);U+78B2(5); +U+78B3(0);U+78B3(5); +U+78B4(0);U+78B4(5); +U+78B5(0);U+78B5(0); +U+78B6(0);U+78B6(0); +U+78B7(0);U+78B7(0); +U+78B8(0);U+781C(1,3);U+781C(1,3) +U+78B9(0);U+78B9(5); +U+78BA(0);U+786E(1,3);U+786E(1,3),U+5859(0,1,3,4),U+78BB(1,3,4),U+792D(1,3,4) +U+78BB(0);U+786E(4);U+786E(4),U+5859(0,4),U+78BA(1,3,4),U+792D(3,4) +U+78BC(0);U+7801(1,3);U+7801(1,3) +U+78BD(0);U+78BD(0); +U+78BE(0);U+78BE(5); +U+78BF(0);U+78BF(0); +U+78C0(0);U+78C0(0); +U+78C1(0);U+78C1(5); +U+78C3(0);U+78C3(0); +U+78C4(0);U+78C4(0); +U+78C5(0);U+78C5(5); +U+78C6(0);U+78C6(0);U+6ED1(3) +U+78C8(0);U+78C8(0); +U+78C9(0);U+78C9(5); +U+78CA(0);U+78CA(5);U+78E5(3) +U+78CB(0);U+78CB(5); +U+78CC(0);U+78CC(0); +U+78CD(0);U+78CD(0); +U+78CE(0);U+78CE(0); +U+78CF(0);U+78CF(0); +U+78D0(0);U+78D0(5); +U+78D1(0);U+7859(1,3);U+7859(1,3),U+78A8(1,3,4) +U+78D3(0);U+78D3(0); +U+78D4(0);U+78D4(5); +U+78D5(0);U+78D5(5); +U+78D6(0);U+78D6(0); +U+78D7(0);U+78D7(0); +U+78D8(0);U+78D8(0); +U+78D9(0);U+78D9(5); +U+78DA(0);U+7816(1,3);U+7816(1,3) +U+78DB(0);U+78DB(0); +U+78DC(0);U+78DC(0); +U+78DD(0);U+78DD(3); +U+78DE(0);U+78DE(0); +U+78DF(0);U+788C(2,3);U+788C(2,3) +U+78E0(0);U+7875(4);U+7875(4) +U+78E1(0);U+78E1(3); +U+78E2(0);U+78E2(3); +U+78E3(0);U+789C(1,3);U+789C(1,3) +U+78E4(0);U+78E4(0); +U+78E5(0);U+78CA(3);U+78CA(3) +U+78E6(0);U+78E6(0); +U+78E7(0);U+789B(1,3);U+789B(1,3) +U+78E8(0);U+78E8(5); +U+78E9(0);U+78E9(0); +U+78EA(0);U+78EA(0); + +U+78EB(0);U+78EB(0); +U+78EC(0);U+78EC(5); +U+78ED(0);U+78ED(0); +U+78EE(0);U+78EE(0); +U+78EF(0);U+77F6(1,3);U+77F6(1,3) +U+78F1(0);U+78F1(0); +U+78F2(0);U+78F2(5); +U+78F3(0);U+78F3(0); +U+78F4(0);U+78F4(5); +U+78F5(0);U+78F5(4); +U+78F6(0);U+78F6(0); +U+78F7(0);U+78F7(5);U+71D0(2) +U+78F9(0);U+78F9(0); +U+78FA(0);U+78FA(5); +U+78FB(0);U+78FB(3); +U+78FC(0);U+78FC(0); +U+78FD(0);U+7857(1,3);U+7857(1,3) +U+78FE(0);U+78FE(0); +U+78FF(0);U+78FF(0); +U+7901(0);U+7901(5); +U+7902(0);U+7902(0); +U+7903(0);U+7903(0); +U+7904(0);U+785A(1,3);U+785A(1,3) +U+7905(0);U+7905(5); +U+7906(0);U+7877(7);U+9669(3),U+7877(7),U+96AA(3),U+9E7C(1,3,4),U+78B1(1,3,4) +U+7907(0);U+7907(0); +U+7909(0);U+7909(3); +U+790A(0);U+790A(0); +U+790B(0);U+790B(0); +U+790C(0);U+790C(0); +U+790E(0);U+7840(1,3);U+7840(1,3) +U+790F(0);U+790F(0); +U+7910(0);U+7910(3); +U+7911(0);U+7911(0); +U+7912(0);U+7912(3); +U+7913(0);U+7913(5); +U+7914(0);U+7914(4); +U+7916(0);U+7916(0); +U+7917(0);U+7917(0); +U+7918(0);U+7918(3); +U+7919(0);U+788D(1,3);U+788D(1,3) +U+791A(0);U+791A(0); +U+791B(0);U+791B(0); +U+791C(0);U+791C(0); +U+791D(0);U+789D(3);U+789D(3) +U+791E(0);U+791E(5); +U+7921(0);U+7921(0); +U+7922(0);U+7922(0); +U+7923(0);U+7923(0); +U+7924(0);U+7924(5);U+7938(3) +U+7925(0);U+7925(0); +U+7926(0);U+77FF(1,3);U+77FF(1,3),U+945B(3) +U+7927(0);U+7927(3); +U+7928(0);U+7928(0); +U+7929(0);U+7929(3); +U+792A(0);U+783A(1,3);U+783A(1,3) +U+792B(0);U+783E(1,3);U+783E(1,3) +U+792C(0);U+77FE(1,3);U+77FE(1,3) +U+792D(0);U+786E(3);U+786E(3),U+5859(0,3,4),U+78BA(1,3,4),U+78BB(3,4) +U+792E(0);U+70AE(2,3);U+70AE(2,3),U+7832(3,4),U+70B0(2,3) +U+792F(0);U+792F(0); +U+7930(0);U+7930(0); +U+7931(0);U+783B(1,3);U+783B(1,3),U+9468(1,3) + +U+7933(0);U+7933(0); +U+7934(0);U+7934(5); +U+7935(0);U+7935(0); +U+7937(0);U+7937(0); +U+7938(0);U+7924(3);U+7924(3) +U+7939(0);U+5CA9(3);U+5CA9(3),U+55A6(0,3,4),U+5D52(2,3,4),U+58E7(3,4),U+5DCC(3,4),U+5DD6(2,3,4),U+789E(3,4) + +U+793A(0);U+793A(5); +U+793B(0);U+793B(5); +U+793C(0);U+793C(1,3);U+79AE(1,3) +U+793D(0);U+793D(0); +U+793E(0);U+793E(5); +U+793F(0);U+793F(3);U+79B4(3) +U+7940(0);U+7940(5); +U+7941(0);U+7941(5); +U+7942(0);U+7942(0); +U+7943(0);U+7943(4);U+79A1(4) +U+7944(0);U+7944(0); +U+7945(0);U+5996(3);U+5996(3),U+8A1E(3) +U+7946(0);U+7946(5); +U+7947(0);U+7947(3);U+79D6(2,3) +U+7948(0);U+7948(5); +U+7949(0);U+7949(5); +U+794A(0);U+794A(0); +U+794B(0);U+794B(0); +U+794C(0);U+51B2(3);U+51B2(3),U+6C96(3,4),U+885D(1,3,4),U+8876(3,4),U+76C5(3,4) +U+794D(0);U+794D(0); +U+794E(0);U+794E(1,3);U+7995(1,3) +U+794F(0);U+794F(0); +U+7950(0);U+7950(3); +U+7951(0);U+7951(0); +U+7952(0);U+7952(0); +U+7953(0);U+7953(5); +U+7954(0);U+7954(0); +U+7955(0);U+79D8(2,3);U+79D8(2,3) +U+7956(0);U+7956(5); +U+7957(0);U+7957(5); +U+7958(0);U+7B97(3);U+7B97(3),U+7B6D(3) +U+795A(0);U+795A(5); +U+795B(0);U+795B(5); +U+795C(0);U+795C(5); +U+795D(0);U+795D(5);U+7969(3) +U+795E(0);U+795E(5); +U+795F(0);U+795F(5); +U+7960(0);U+7960(5); +U+7961(0);U+67F4(3);U+67F4(3) +U+7962(0);U+7962(1,3);U+79B0(1,3) +U+7963(0);U+65C5(3);U+65C5(3) +U+7964(0);U+7964(0); +U+7965(0);U+7965(5); +U+7966(0);U+7966(4); +U+7967(0);U+7967(5); +U+7968(0);U+7968(5); +U+7969(0);U+795D(3);U+795D(3) +U+796A(0);U+796A(0); +U+796B(0);U+796B(0); +U+796D(0);U+796D(5); +U+796F(0);U+796F(1,3);U+798E(1,3) +U+7970(0);U+7970(3); +U+7971(0);U+7971(0); +U+7972(0);U+7972(0); +U+7973(0);U+7973(0); +U+7974(0);U+7974(0); + +U+7977(0);U+7977(1,3);U+79B1(1,3) +U+7978(0);U+7978(1,3);U+798D(1,3) +U+7979(0);U+7979(0); +U+797A(0);U+797A(5);U+79A5(3) +U+797B(0);U+797B(0); +U+797C(0);U+797C(3); +U+797D(0);U+797D(0); +U+797E(0);U+797E(0); +U+797F(0);U+7984(4);U+7984(4) +U+7980(0);U+7980(5);U+7A1F(2,3),U+5EE9(0,2,3),U+5EEA(2,3) +U+7981(0);U+7981(5); +U+7982(0);U+7982(0); +U+7983(0);U+7983(0); +U+7984(0);U+7984(5);U+797F(4) +U+7985(0);U+7985(1,3);U+79AA(1,3) +U+7988(0);U+7988(0); +U+7989(0);U+7989(0); +U+798A(0);U+798A(5); +U+798B(0);U+798B(0); +U+798C(0);U+798C(0); +U+798D(0);U+7978(1,3);U+7978(1,3) +U+798E(0);U+796F(1,3);U+796F(1,3) +U+798F(0);U+798F(5); +U+7990(0);U+7990(0); +U+7991(0);U+7991(0); +U+7992(0);U+7992(0); +U+7993(0);U+7993(0); +U+7994(0);U+7994(3); +U+7995(0);U+794E(1,3);U+794E(1,3) +U+7996(0);U+7996(0); +U+7997(0);U+7997(0); +U+7998(0);U+7998(3); +U+7999(0);U+7999(0); +U+799A(0);U+799A(5); +U+799B(0);U+799B(0); +U+799C(0);U+799C(0); +U+799F(0);U+799F(0); +U+79A0(0);U+79A0(0); +U+79A1(0);U+7943(4);U+7943(4) +U+79A2(0);U+79A2(0); +U+79A3(0);U+79A3(0); +U+79A4(0);U+79A4(0); +U+79A5(0);U+797A(3);U+797A(3) +U+79A6(0);U+5FA1(1,3);U+5FA1(1,3) +U+79A7(0);U+79A7(5); +U+79A8(0);U+79A8(0); +U+79AA(0);U+7985(1,3);U+7985(1,3) +U+79AB(0);U+79AB(0); +U+79AC(0);U+79AC(0); +U+79AD(0);U+79AD(0); +U+79AE(0);U+793C(1,3);U+793C(1,3) +U+79AF(0);U+79AF(0); +U+79B0(0);U+7962(1,3);U+7962(1,3) +U+79B1(0);U+7977(1,3);U+7977(1,3) +U+79B2(0);U+79B2(0); +U+79B3(0);U+79B3(5); +U+79B4(0);U+793F(3);U+793F(3) +U+79B5(0);U+79B5(0); +U+79B6(0);U+79B6(0); +U+79B7(0);U+79B7(3); +U+79B8(0);U+8E42(3);U+8E42(3) +U+79B9(0);U+79B9(5); +U+79BA(0);U+79BA(5); + +U+79BB(0);U+79BB(1,3);U+96E2(1,3) +U+79BD(0);U+79BD(5); +U+79BE(0);U+79BE(5); +U+79BF(0);U+79C3(4);U+79C3(4) +U+79C0(0);U+79C0(5); +U+79C1(0);U+79C1(5);U+53B6(3) +U+79C2(0);U+79C2(0); +U+79C3(0);U+79C3(5);U+79BF(4) +U+79C5(0);U+79C5(3); +U+79C6(0);U+79C6(5);U+7A08(2,3) +U+79C8(0);U+7C7C(2,3);U+7C7C(2,3) +U+79C9(0);U+79C9(5); +U+79CA(0);U+5E74(2,3);U+5E74(2,3) +U+79CB(0);U+79CB(1,3);U+7A50(7),U+97A6(1,3,4),U+9F9D(7) +U+79CD(0);U+79CD(1,3);U+7A2E(1,3) +U+79CE(0);U+79CE(0); +U+79CF(0);U+79CF(3);U+8017(3) +U+79D0(0);U+8018(3);U+8018(3) +U+79D1(0);U+79D1(5); +U+79D2(0);U+79D2(5); +U+79D3(0);U+79D3(0); +U+79D5(0);U+79D5(5); +U+79D6(0);U+7947(2,3);U+7947(2,3) +U+79D8(0);U+79D8(5);U+7955(2,3) +U+79D9(0);U+79D9(0); +U+79DA(0);U+79DA(0); +U+79DB(0);U+79DB(0); +U+79DC(0);U+79DC(0); +U+79DD(0);U+79DD(0); +U+79DE(0);U+79DE(0); +U+79DF(0);U+79DF(5); +U+79E0(0);U+79E0(0); +U+79E1(0);U+79E1(0); +U+79E2(0);U+79E2(0); +U+79E3(0);U+79E3(5); +U+79E4(0);U+79E4(5); +U+79E5(0);U+79E5(0); +U+79E6(0);U+79E6(5); +U+79E7(0);U+79E7(5); +U+79E8(0);U+79E8(0); +U+79E9(0);U+79E9(5); +U+79EA(0);U+79EA(0); +U+79EB(0);U+79EB(5); +U+79EC(0);U+79EC(0); +U+79ED(0);U+79ED(5); +U+79EE(0);U+79EE(0); +U+79EF(0);U+79EF(1,3);U+7A4D(1,3) +U+79F0(0);U+79F0(1,3);U+5041(3),U+7A31(1,3) +U+79F1(0);U+79F1(0); +U+79F2(0);U+79F2(0); +U+79F3(0);U+79F3(0); +U+79F4(0);U+79F4(0); +U+79F5(0);U+79F5(0); +U+79F6(0);U+7CA2(3);U+7CA2(3) +U+79F7(0);U+79F7(0); +U+79F8(0);U+79F8(5);U+7A2D(2),U+9782(4) +U+79F9(0);U+79F9(0); +U+79FA(0);U+79FA(0); +U+79FB(0);U+79FB(5);U+8FFB(2,3) +U+79FC(0);U+79FC(0); +U+79FD(0);U+79FD(1,3);U+7A62(1,3),U+8589(3) +U+79FE(0);U+79FE(4);U+7A60(4) +U+79FF(0);U+79FF(0); + +U+7A00(0);U+7A00(5);U+5E0C(3) +U+7A02(0);U+7A02(5); +U+7A03(0);U+7A03(5); +U+7A04(0);U+7A04(0); +U+7A05(0);U+7A0E(4);U+7A0E(4) +U+7A06(0);U+7A06(5); +U+7A08(0);U+79C6(2,3);U+79C6(2,3) +U+7A0A(0);U+7A0A(4); +U+7A0B(0);U+7A0B(5); +U+7A0C(0);U+7A0C(3); +U+7A0D(0);U+7A0D(5);U+8571(4) +U+7A0E(0);U+7A0E(5);U+7A05(4) +U+7A0F(0);U+7A0F(0); +U+7A10(0);U+7A10(3); +U+7A11(0);U+7A11(3);U+7A4B(3) +U+7A12(0);U+7A12(0); +U+7A13(0);U+7A13(0); +U+7A14(0);U+7A14(5); +U+7A15(0);U+7A15(0); +U+7A16(0);U+7A16(0); +U+7A17(0);U+7A17(5);U+7CBA(2) +U+7A18(0);U+7A18(0); +U+7A19(0);U+7A19(0); +U+7A1A(0);U+7A1A(5);U+7A49(2,3) +U+7A1B(0);U+7A1B(3); +U+7A1C(0);U+68F1(2,3);U+68F1(2,3) +U+7A1D(0);U+7A1D(0); +U+7A1E(0);U+7A1E(5); +U+7A1F(0);U+7980(2,3);U+5EE9(3),U+7980(2,3),U+5EEA(3) +U+7A20(0);U+7A20(5); +U+7A21(0);U+7A21(0); +U+7A22(0);U+7A22(3); +U+7A23(0);U+7A23(1,3);U+7A4C(1,3) +U+7A24(0);U+7A24(0); +U+7A25(0);U+7A25(0); +U+7A26(0);U+7A26(0); +U+7A27(0);U+7A27(0); +U+7A28(0);U+7A28(0); +U+7A29(0);U+7A29(0); +U+7A2A(0);U+7A2A(0); +U+7A2B(0);U+7A2B(0); +U+7A2D(0);U+79F8(2);U+79F8(2),U+9782(2,4) +U+7A2E(0);U+79CD(1,3);U+79CD(1,3) +U+7A2F(0);U+7A2F(3); +U+7A30(0);U+7CC8(3);U+7CC8(3) +U+7A31(0);U+79F0(1,3);U+79F0(1,3),U+5041(0,1,3) +U+7A32(0);U+7A3B(3);U+7A3B(3) +U+7A33(0);U+7A33(1,3);U+7A69(1,3) +U+7A34(0);U+7A34(0); +U+7A35(0);U+7A35(0); +U+7A37(0);U+7A37(5); +U+7A39(0);U+7A39(5); +U+7A3B(0);U+7A3B(5);U+7A32(3) +U+7A3C(0);U+7A3C(5); +U+7A3D(0);U+7A3D(5);U+4E69(3) +U+7A3E(0);U+7A3F(3);U+7A3F(3) +U+7A3F(0);U+7A3F(5);U+7A3E(2,3) +U+7A40(0);U+8C37(1,3);U+8C37(1,3) +U+7A41(0);U+7A41(0); +U+7A42(0);U+7A57(3);U+7A57(3),U+7A5F(3) +U+7A43(0);U+7A43(0); +U+7A44(0);U+7A44(0); +U+7A45(0);U+7CE0(2,3);U+7CE0(2,3) + +U+7A46(0);U+7A46(5); +U+7A47(0);U+415F(1,3);U+415F(1,3) +U+7A48(0);U+7A48(0); +U+7A49(0);U+7A1A(2,3);U+7A1A(2,3) +U+7A4A(0);U+7A4A(3); +U+7A4B(0);U+7A11(3);U+7A11(3) +U+7A4C(0);U+7A23(1,3);U+7A23(1,3) +U+7A4D(0);U+79EF(1,3);U+79EF(1,3) +U+7A4E(0);U+9896(1,3);U+9834(2),U+9895(8,9),U+9896(1,3) +U+7A50(0);U+79CB(7);U+79CB(7),U+9F9D(4),U+97A6(1,3,4,7) +U+7A51(0);U+7A51(1,3);U+7A61(1,3) +U+7A52(0);U+7A52(0); +U+7A53(0);U+7A53(0); +U+7A54(0);U+7A54(0); +U+7A55(0);U+7A55(0); +U+7A56(0);U+7A56(0); +U+7A57(0);U+7A57(5);U+7A42(3),U+7A5F(3) +U+7A58(0);U+7A58(0); +U+7A59(0);U+7A59(0); +U+7A5A(0);U+7A5A(0); +U+7A5B(0);U+7A5B(3); +U+7A5C(0);U+7A5C(0); +U+7A5D(0);U+7A5D(0); +U+7A5E(0);U+7A5E(4);U+7A6D(4) +U+7A5F(0);U+7A57(3);U+7A57(3),U+7A42(0,3) +U+7A60(0);U+79FE(4);U+79FE(4) +U+7A61(0);U+7A51(1,3);U+7A51(1,3) +U+7A62(0);U+79FD(1,3);U+79FD(1,3),U+8589(1,3) +U+7A65(0);U+7A65(3); +U+7A66(0);U+7A66(0); +U+7A67(0);U+7A67(0); +U+7A68(0);U+9893(4);U+9893(4),U+9839(4),U+983D(1,3,4) +U+7A69(0);U+7A33(1,3);U+7A33(1,3) +U+7A6B(0);U+83B7(1,3);U+83B7(1,3),U+7372(0,1,3) +U+7A6C(0);U+7A6C(0); +U+7A6D(0);U+7A5E(4);U+7A5E(4) +U+7A6E(0);U+7A6E(0); +U+7A70(0);U+7A70(5); +U+7A71(0);U+7A71(0); +U+7A72(0);U+7A72(0); +U+7A73(0);U+7A73(0); +U+7A74(0);U+7A74(5);U+5CA4(4) +U+7A75(0);U+6316(3);U+6316(3) +U+7A76(0);U+7A76(5); +U+7A77(0);U+7A77(1,3);U+7AAE(1,3) +U+7A78(0);U+7A78(5); +U+7A79(0);U+7A79(5); +U+7A7A(0);U+7A7A(5); +U+7A7B(0);U+5B87(3);U+5B87(3) +U+7A7C(0);U+7A7C(0); +U+7A7D(0);U+9631(2,3);U+9631(2,3) +U+7A7E(0);U+7A7E(4); +U+7A7F(0);U+7A7F(5); +U+7A80(0);U+7A80(5); +U+7A81(0);U+7A81(5); +U+7A83(0);U+7A83(1,3);U+7ACA(1,3) +U+7A84(0);U+7A84(5); +U+7A85(0);U+7A85(3); +U+7A86(0);U+7A86(5); +U+7A87(0);U+7A87(0); +U+7A88(0);U+7A88(5); +U+7A89(0);U+7A89(3); +U+7A8A(0);U+7A8A(3); + +U+7A8B(0);U+7A8B(0); +U+7A8C(0);U+7A8C(0); +U+7A8D(0);U+7A8D(1,3);U+7AC5(1,3) +U+7A8E(0);U+7A8E(1,3);U+7AB5(1,3) +U+7A8F(0);U+7A8F(0); +U+7A90(0);U+7A90(0); +U+7A91(0);U+7A91(5);U+7AAF(2,3),U+7AB0(2,4) +U+7A92(0);U+7A92(5); +U+7A93(0);U+7A97(2,3);U+7A97(2,3) +U+7A94(0);U+7A94(3); +U+7A95(0);U+7A95(5); +U+7A96(0);U+7A96(5); +U+7A97(0);U+7A97(5);U+7A93(2,3) +U+7A98(0);U+7A98(5); +U+7A99(0);U+7A99(0); +U+7A9C(0);U+7A9C(1,3);U+7AC4(1,3) +U+7A9D(0);U+7A9D(1,3);U+7AA9(1,3) +U+7A9E(0);U+7A9E(0); +U+7A9F(0);U+7A9F(5); +U+7AA0(0);U+7AA0(5); +U+7AA1(0);U+7AA1(0); +U+7AA2(0);U+7AA2(0); +U+7AA3(0);U+7AA3(0); +U+7AA4(0);U+7AA4(0); +U+7AA5(0);U+7AA5(1,3);U+7ABA(1,3),U+95DA(2,3) +U+7AA6(0);U+7AA6(1,3);U+7AC7(1,3) +U+7AA7(0);U+7AA7(0); +U+7AA8(0);U+7AA8(5);U+5837(3) +U+7AA9(0);U+7A9D(1,3);U+7A9D(1,3) +U+7AAA(0);U+6D3C(1,3);U+6D3C(1,3),U+6F25(1,3) +U+7AAB(0);U+7AAB(0); +U+7AAC(0);U+7AAC(5); +U+7AAD(0);U+7AAD(1,3);U+5BE0(4),U+7AB6(1,3) +U+7AAE(0);U+7A77(1,3);U+7A77(1,3) +U+7AAF(0);U+7A91(2,3);U+7A91(2,3),U+7AB0(4) +U+7AB0(0);U+7A91(2,4);U+7A91(2,4),U+7AAF(4) +U+7AB1(0);U+7AB1(0); +U+7AB2(0);U+7AB2(0); +U+7AB3(0);U+7AB3(5); +U+7AB4(0);U+7AB4(0); +U+7AB5(0);U+7A8E(1,3);U+7A8E(1,3) +U+7AB6(0);U+7AAD(1,3);U+7AAD(1,3),U+5BE0(0,1,3,4) +U+7AB7(0);U+7AB7(0); +U+7AB8(0);U+7AB8(0); +U+7ABA(0);U+7AA5(1,3);U+7AA5(1,3),U+95DA(1,2,3) +U+7ABE(0);U+7ABE(4); +U+7ABF(0);U+7ABF(5); +U+7AC0(0);U+8D6A(7);U+8D6A(7),U+8D6C(1,3,7) +U+7AC1(0);U+7AC1(0); +U+7AC4(0);U+7A9C(1,3);U+7A9C(1,3) +U+7AC5(0);U+7A8D(1,3);U+7A8D(1,3) +U+7AC7(0);U+7AA6(1,3);U+7AA6(1,3) +U+7AC8(0);U+7076(1,3);U+7076(1,3) +U+7AC9(0);U+7AC9(0); +U+7ACA(0);U+7A83(1,3);U+7A83(1,3) +U+7ACB(0);U+7ACB(5); +U+7ACC(0);U+7ACC(0); +U+7ACD(0);U+7ACD(0); +U+7ACE(0);U+7ACE(0); +U+7ACF(0);U+7ACF(0); +U+7AD0(0);U+7AD0(0); +U+7AD1(0);U+7AD1(3);U+7AE4(3) +U+7AD2(0);U+5947(3);U+5947(3) + +U+7AD3(0);U+7AD3(0); +U+7AD4(0);U+7AD4(0); +U+7AD5(0);U+7AD5(0); +U+7AD6(0);U+7AD6(1,3);U+7AEA(1,3),U+8C4E(4) +U+7AD8(0);U+7AD8(0); +U+7AD9(0);U+7AD9(5); +U+7ADB(0);U+7ADB(0); +U+7ADC(0);U+9F99(3);U+9F8D(3),U+9F99(3),U+9F92(3) +U+7ADD(0);U+5E76(2);U+4E26(3),U+5E76(2),U+4F75(3),U+5002(3),U+5E77(2,3,4) +U+7ADE(0);U+7ADE(1,3);U+7AF6(1,3),U+7AF8(3) +U+7ADF(0);U+7ADF(5); +U+7AE0(0);U+7AE0(5);U+9067(3) +U+7AE1(0);U+7AE1(0); +U+7AE2(0);U+4FDF(2);U+4FDF(2) +U+7AE3(0);U+7AE3(5); +U+7AE4(0);U+7AD1(3);U+7AD1(3) +U+7AE5(0);U+7AE5(5); +U+7AE6(0);U+7AE6(5); +U+7AE7(0);U+7AE7(0); +U+7AE8(0);U+7AE8(0); +U+7AEA(0);U+7AD6(1,3);U+7AD6(1,3),U+8C4E(2,3) +U+7AEB(0);U+7AEB(0); +U+7AEC(0);U+7AEC(0); +U+7AED(0);U+7AED(5); +U+7AEE(0);U+7AEE(0); +U+7AEF(0);U+7AEF(5);U+8011(3) +U+7AF0(0);U+7AF0(0); +U+7AF1(0);U+7AF1(0); +U+7AF2(0);U+7AF2(0); +U+7AF3(0);U+7AF3(0); +U+7AF4(0);U+7AF4(0); +U+7AF6(0);U+7ADE(1,3);U+7ADE(1,3),U+7AF8(3) +U+7AF7(0);U+7AF7(3); +U+7AF8(0);U+7ADE(3);U+7ADE(3),U+7AF6(3) +U+7AF9(0);U+7AF9(5); +U+7AFA(0);U+7AFA(5);U+7B01(3) +U+7AFB(0);U+7AFB(0); +U+7AFD(0);U+7AFD(5); +U+7AFE(0);U+7BEA(3);U+7BEA(3),U+7B8E(3) +U+7AFF(0);U+7AFF(5); +U+7B00(0);U+8292(3);U+8292(3) +U+7B01(0);U+7AFA(3);U+7AFA(3) +U+7B02(0);U+7B02(0); +U+7B03(0);U+7B03(1,3);U+7BE4(1,3) +U+7B04(0);U+7B04(5); +U+7B05(0);U+7B4A(3);U+7B4A(3) +U+7B06(0);U+7B06(5);U+5DF4(3) +U+7B08(0);U+7B08(5); +U+7B09(0);U+7B09(0); +U+7B0A(0);U+7B0A(5); +U+7B0B(0);U+7B0B(5);U+7B4D(2,3) +U+7B0C(0);U+7B0C(0); +U+7B0D(0);U+7B0D(0); +U+7B0E(0);U+7B0E(0); +U+7B0F(0);U+7B0F(5); +U+7B10(0);U+7B10(0); +U+7B11(0);U+7B11(5);U+54B2(2) +U+7B12(0);U+7B12(0); +U+7B13(0);U+7B13(0); +U+7B14(0);U+7B14(1,3);U+7B46(1,3) +U+7B15(0);U+7B15(1,3);U+7B67(1,3) +U+7B16(0);U+7B16(0); +U+7B17(0);U+7B17(0); + +U+7B18(0);U+7B18(0); +U+7B19(0);U+7B19(5); +U+7B1A(0);U+7B1A(0); +U+7B1B(0);U+7B1B(5);U+7BF4(3) +U+7B1C(0);U+7B1C(0); +U+7B1D(0);U+7B1D(3); +U+7B1E(0);U+7B1E(5); +U+7B20(0);U+7B20(5); +U+7B21(0);U+7B21(0); +U+7B22(0);U+7B22(0); +U+7B23(0);U+7B23(0); +U+7B24(0);U+7B24(5); +U+7B25(0);U+7B25(5); +U+7B26(0);U+7B26(5); +U+7B28(0);U+7B28(5); +U+7B2A(0);U+7B2A(5); +U+7B2B(0);U+7B2B(5); +U+7B2C(0);U+7B2C(5); +U+7B2D(0);U+7B2D(0); +U+7B2E(0);U+7B2E(5);U+7B70(3,4) +U+7B2F(0);U+7B2F(0); +U+7B30(0);U+7B30(0); +U+7B31(0);U+7B31(5); +U+7B32(0);U+7B32(3); +U+7B33(0);U+7B33(5); +U+7B34(0);U+7B34(0); +U+7B35(0);U+7B35(0); +U+7B36(0);U+77E2(3);U+77E2(3) +U+7B37(0);U+7B37(0); +U+7B38(0);U+7B38(5); +U+7B39(0);U+7B39(0); +U+7B3A(0);U+7B3A(1,3);U+724B(2,3),U+7B8B(1,3) +U+7B3B(0);U+7B47(3);U+7B47(3) +U+7B3C(0);U+7B3C(1,3);U+7BED(4),U+7C60(1,3) +U+7B3D(0);U+7B3D(0); +U+7B3E(0);U+7B3E(1,3);U+7C69(1,3) +U+7B3F(0);U+7B3F(0); +U+7B40(0);U+7B40(3); +U+7B41(0);U+7B41(0); +U+7B43(0);U+7B43(0); +U+7B44(0);U+7B44(0); +U+7B45(0);U+7B45(5); +U+7B46(0);U+7B14(1,3);U+7B14(1,3) +U+7B47(0);U+7B47(5);U+7B3B(3) +U+7B48(0);U+7B48(0); +U+7B49(0);U+7B49(5); +U+7B4A(0);U+7B4A(3);U+7B05(3) +U+7B4B(0);U+7B4B(5);U+89D4(3),U+65A4(2,3,5) +U+7B4C(0);U+7B4C(5); +U+7B4D(0);U+7B0B(2,3);U+7B0B(2,3) +U+7B4E(0);U+7B4E(0); +U+7B4F(0);U+7B4F(5); +U+7B50(0);U+7B50(5); +U+7B51(0);U+7B51(1,3);U+7BC9(1,3) +U+7B52(0);U+7B52(5);U+7B69(2,3) +U+7B54(0);U+7B54(5);U+7563(3),U+8345(4) +U+7B55(0);U+7B55(0); +U+7B56(0);U+7B56(5);U+7B5E(2),U+7B74(2,3) +U+7B57(0);U+7B57(0); +U+7B58(0);U+7B58(5);U+7C06(4) +U+7B59(0);U+7B59(0); +U+7B5A(0);U+7B5A(1,3);U+7BF3(1,3) +U+7B5B(0);U+7B5B(1,3);U+7BE9(1,3) + +U+7B5C(0);U+7B5C(4);U+7C39(4) +U+7B5D(0);U+7B5D(4);U+7B8F(4) +U+7B5E(0);U+7B56(2);U+7B56(2),U+7B74(2,3) +U+7B5F(0);U+7B5F(0); +U+7B60(0);U+7B60(5); +U+7B61(0);U+7B61(0); +U+7B62(0);U+7B62(5); +U+7B63(0);U+7BF1(3);U+7BF1(3),U+7C6C(1,3) +U+7B64(0);U+7B64(0); +U+7B65(0);U+7B65(3); +U+7B66(0);U+7BA1(2,3);U+7BA1(2,3) +U+7B67(0);U+7B15(1,3);U+7B15(1,3) +U+7B68(0);U+7B68(0); +U+7B69(0);U+7B52(2,3);U+7B52(2,3) +U+7B6A(0);U+7B6A(0); +U+7B6B(0);U+7B6B(0); +U+7B6C(0);U+7B6C(0); +U+7B6D(0);U+7B97(3);U+7B97(3),U+7958(0,3) +U+7B6E(0);U+7B6E(5); +U+7B70(0);U+7B2E(3,4);U+7B2E(3,4) +U+7B71(0);U+7B71(5);U+7BE0(4),U+7B7F(4) +U+7B72(0);U+7B72(5); +U+7B73(0);U+7B73(0); +U+7B74(0);U+7B56(2,3);U+7B56(2,3),U+7B5E(2,3) +U+7B75(0);U+7B75(5); +U+7B76(0);U+7B76(0); +U+7B77(0);U+7B77(5); +U+7B78(0);U+7B78(0); +U+7B79(0);U+7B79(1,3);U+7C4C(1,3) +U+7B7B(0);U+7B7B(5); +U+7B7C(0);U+7B7C(4);U+7BD4(4) +U+7B7D(0);U+7B7D(0); +U+7B7E(0);U+7B7E(1,3);U+7C3D(1,3),U+7C56(4),U+7C64(1,3) +U+7B7F(0);U+7B7F(4);U+7BE0(4),U+7B71(4,5) +U+7B80(0);U+7B80(1,3);U+7C21(1,3) +U+7B81(0);U+7B81(0); +U+7B82(0);U+7B82(0); +U+7B83(0);U+7B83(0); +U+7B84(0);U+7B84(0); +U+7B85(0);U+7B85(5); +U+7B87(0);U+4E2A(4);U+4E2A(4),U+500B(2,3) +U+7B88(0);U+7B88(0); +U+7B89(0);U+7B89(0); +U+7B8A(0);U+7B8A(0); +U+7B8B(0);U+7B3A(1,3);U+724B(2,3),U+7B3A(1,3) +U+7B8C(0);U+7B8C(0); +U+7B8D(0);U+7B8D(5); +U+7B8E(0);U+7BEA(3);U+7BEA(3),U+7AFE(0,3) +U+7B8F(0);U+7B5D(4);U+7B5D(4) +U+7B90(0);U+7B90(5); +U+7B91(0);U+7B91(0); +U+7B93(0);U+7B93(1,3);U+7C59(1,3) +U+7B94(0);U+7B94(5); +U+7B95(0);U+7B95(5); +U+7B96(0);U+7B96(0); +U+7B97(0);U+7B97(5);U+7958(3),U+7B6D(3) +U+7B98(0);U+7B98(0); +U+7B99(0);U+7B99(3); +U+7B9A(0);U+624E(4);U+624E(4),U+5284(4),U+5273(0,4),U+672D(2,3,4),U+7D25(2,4),U+7D2E(2,4) + +U+7B9B(0);U+7B9B(3); +U+7B9C(0);U+7B9C(5); +U+7B9D(0);U+7B9D(5);U+9257(3),U+94B3(1,3),U+62D1(0,1,3,4) + +U+7B9E(0);U+7B9E(0); +U+7B9F(0);U+7B9F(0); +U+7BA0(0);U+68F0(2,3);U+68F0(2,3) +U+7BA1(0);U+7BA1(5);U+7B66(2,3) +U+7BA2(0);U+7BA2(5); +U+7BA4(0);U+7BA4(0); +U+7BA6(0);U+7BA6(1,3);U+7C00(1,3) +U+7BA7(0);U+7BA7(1,3);U+7BCB(1,3) +U+7BA8(0);U+7BA8(1,3);U+7C5C(1,3) +U+7BA9(0);U+7BA9(1,3);U+7C6E(1,3) +U+7BAA(0);U+7BAA(1,3);U+7C1E(1,3) +U+7BAB(0);U+7BAB(1,3);U+7C2B(1,3),U+7C18(4) +U+7BAC(0);U+7BAC(5);U+7BDB(2,3) +U+7BAD(0);U+7BAD(5); +U+7BAE(0);U+7BAE(0); +U+7BAF(0);U+7BAF(0); +U+7BB1(0);U+7BB1(5); +U+7BB3(0);U+7BB3(3);U+7C08(3) +U+7BB4(0);U+7BB4(5); +U+7BB5(0);U+7BB5(0); +U+7BB6(0);U+7BB6(0); +U+7BB7(0);U+7BB7(0); +U+7BB8(0);U+7BB8(5); +U+7BB9(0);U+7BB9(0); +U+7BBA(0);U+7BBA(0); +U+7BBB(0);U+7BBB(0); +U+7BBC(0);U+7BBC(0); +U+7BBD(0);U+7BBD(0); +U+7BBE(0);U+7BBE(0); +U+7BBF(0);U+7BBF(0); +U+7BC0(0);U+8282(1,3);U+8282(1,3) +U+7BC1(0);U+7BC1(5); +U+7BC2(0);U+7BC2(0); +U+7BC3(0);U+7BC3(0); +U+7BC4(0);U+8303(1,3);U+8303(1,3) +U+7BC5(0);U+7BC5(3); +U+7BC6(0);U+7BC6(5); +U+7BC7(0);U+7BC7(5); +U+7BC8(0);U+7BC8(0); +U+7BC9(0);U+7B51(1,3);U+7B51(1,3) +U+7BCA(0);U+7BCA(3); +U+7BCB(0);U+7BA7(1,3);U+7BA7(1,3) +U+7BCC(0);U+7BCC(5); +U+7BCD(0);U+7BCD(0); +U+7BCE(0);U+7BCE(0); +U+7BD0(0);U+7BD0(0); +U+7BD1(0);U+7BD1(1,3);U+7C23(1,3) +U+7BD2(0);U+7BD2(0); +U+7BD3(0);U+7BD3(1,3);U+7C0D(1,3) +U+7BD4(0);U+7B7C(4);U+7B7C(4) +U+7BD5(0);U+7BD5(0); +U+7BD6(0);U+7BD6(0); +U+7BD7(0);U+7BD7(0); +U+7BD8(0);U+7BD8(3); +U+7BD9(0);U+7BD9(5); +U+7BDA(0);U+7BDA(5); +U+7BDB(0);U+7BAC(2,3);U+7BAC(2,3) +U+7BDC(0);U+7BDC(0); +U+7BDD(0);U+7BDD(5);U+7C3C(3) +U+7BDE(0);U+7BDE(0); +U+7BDF(0);U+7BDF(0); +U+7BE0(0);U+7B7F(4);U+7B71(4),U+7B7F(4) +U+7BE1(0);U+7BE1(5);U+7C12(2) + +U+7BE2(0);U+7BE2(0); +U+7BE3(0);U+7BE3(0); +U+7BE4(0);U+7B03(1,3);U+7B03(1,3) +U+7BE5(0);U+7BE5(5); +U+7BE6(0);U+7BE6(5); +U+7BE7(0);U+7BE7(0); +U+7BE8(0);U+7BE8(0); +U+7BE9(0);U+7B5B(1,3);U+7B5B(1,3) +U+7BEA(0);U+7BEA(5);U+7AFE(3),U+7B8E(3) +U+7BEB(0);U+7BEB(0); +U+7BEC(0);U+7BEC(0); +U+7BED(0);U+7B3C(4);U+7B3C(4),U+7C60(4) +U+7BEE(0);U+7BEE(1,3);U+7C43(1,3) +U+7BEF(0);U+7BEF(4);U+7C5B(4) +U+7BF0(0);U+7BF0(0); +U+7BF1(0);U+7BF1(1,3);U+7B63(3),U+7C6C(1,3) +U+7BF2(0);U+7BF2(0);U+5F57(3) +U+7BF3(0);U+7B5A(1,3);U+7B5A(1,3) +U+7BF4(0);U+7B1B(3);U+7B1B(3) +U+7BF5(0);U+7BF5(0); +U+7BF6(0);U+7BF6(0); +U+7BF7(0);U+7BF7(5); +U+7BF8(0);U+7BF8(3); +U+7BF9(0);U+7BF9(0); +U+7BFB(0);U+7BFB(0); +U+7BFC(0);U+7BFC(5); +U+7BFD(0);U+7C5E(4);U+7C5E(4) +U+7BFE(0);U+7BFE(5); +U+7BFF(0);U+7BFF(0); +U+7C00(0);U+7BA6(1,3);U+7BA6(1,3) +U+7C01(0);U+7C01(0); +U+7C02(0);U+7C02(0); +U+7C03(0);U+7C03(0); +U+7C04(0);U+7C04(3); +U+7C05(0);U+7C05(0); +U+7C06(0);U+7B58(4);U+7B58(4) +U+7C07(0);U+7C07(5); +U+7C08(0);U+7BB3(3);U+7BB3(3) +U+7C09(0);U+7C09(0); +U+7C0A(0);U+7C0A(0); +U+7C0B(0);U+7C0B(5); +U+7C0C(0);U+7C0C(5); +U+7C0D(0);U+7BD3(1,3);U+7BD3(1,3) +U+7C0E(0);U+7C0E(4); +U+7C0F(0);U+7C0F(5); +U+7C10(0);U+7C10(0); +U+7C11(0);U+84D1(2);U+84D1(2) +U+7C12(0);U+7BE1(2);U+7BE1(2) +U+7C13(0);U+7C13(0); +U+7C15(0);U+7C15(0); +U+7C16(0);U+7C16(1,3);U+7C6A(1,3) +U+7C17(0);U+7C17(0); +U+7C18(0);U+7BAB(4);U+7C2B(4),U+7BAB(4) +U+7C19(0);U+7C19(0); +U+7C1A(0);U+7C1A(0); +U+7C1C(0);U+7C1C(3); +U+7C1D(0);U+7C1D(0); +U+7C1E(0);U+7BAA(1,3);U+7BAA(1,3) +U+7C1F(0);U+7C1F(5); +U+7C20(0);U+7C20(3); +U+7C21(0);U+7B80(1,3);U+7B80(1,3) +U+7C22(0);U+7C22(0); +U+7C23(0);U+7BD1(1,3);U+7BD1(1,3) + +U+7C24(0);U+7C24(0); +U+7C25(0);U+7C25(0); +U+7C26(0);U+7C26(5); +U+7C27(0);U+7C27(5); +U+7C28(0);U+7C28(3); +U+7C29(0);U+7C29(0); +U+7C2A(0);U+7C2A(5); +U+7C2B(0);U+7BAB(1,3);U+7BAB(1,3),U+7C18(4) +U+7C2C(0);U+7C2C(3); +U+7C2D(0);U+7C2D(0); +U+7C30(0);U+7C30(0); +U+7C31(0);U+7C31(0); +U+7C32(0);U+7C32(0); +U+7C33(0);U+7C33(0); +U+7C34(0);U+7C34(0); +U+7C35(0);U+7C35(4); +U+7C36(0);U+7C36(0); +U+7C37(0);U+6A90(2,3);U+6A90(2,3) +U+7C38(0);U+7C38(5); +U+7C39(0);U+7B5C(4);U+7B5C(4) +U+7C3A(0);U+7C3A(3); +U+7C3B(0);U+7C3B(0); +U+7C3C(0);U+7BDD(3);U+7BDD(3) +U+7C3D(0);U+7B7E(1,3);U+7B7E(1,3),U+7C64(3,4),U+7C56(1,3,4) +U+7C3E(0);U+5E18(1,3);U+5E18(1,3) +U+7C3F(0);U+7C3F(5); +U+7C40(0);U+7C40(5); +U+7C41(0);U+7C41(1,3);U+7C5F(1,3) +U+7C42(0);U+7C42(0); +U+7C43(0);U+7BEE(1,3);U+7BEE(1,3) +U+7C44(0);U+7C44(0); +U+7C45(0);U+7C45(0); +U+7C46(0);U+7C46(3); +U+7C47(0);U+7C47(0); +U+7C48(0);U+7C48(0); +U+7C49(0);U+53F0(4);U+53F0(4),U+6AAF(1,3,4),U+81FA(1,3,4),U+98B1(1,3,4) +U+7C4A(0);U+7C4A(0); +U+7C4B(0);U+7C4B(0); +U+7C4C(0);U+7B79(1,3);U+7B79(1,3) +U+7C4D(0);U+7C4D(5); +U+7C4E(0);U+7C4E(0); +U+7C50(0);U+85E4(2,3);U+7C58(3),U+85E4(2,3) +U+7C51(0);U+7C51(0); +U+7C53(0);U+85E9(3);U+85E9(3) +U+7C54(0);U+7C54(3);U+85EA(3),U+85AE(1,3) +U+7C56(0);U+7B7E(4);U+7B7E(4),U+7C64(8,9),U+7C3D(1,3,4) +U+7C57(0);U+7C57(0); +U+7C58(0);U+85E4(2,3);U+7C50(3),U+85E4(2,3) +U+7C59(0);U+7B93(1,3);U+7B93(1,3) +U+7C5A(0);U+7C5A(3); +U+7C5B(0);U+7BEF(4);U+7BEF(4) +U+7C5C(0);U+7BA8(1,3);U+7BA8(1,3) +U+7C5E(0);U+7C5E(4);U+7BFD(4) +U+7C5F(0);U+7C41(1,3);U+7C41(1,3) +U+7C60(0);U+7B3C(1,3);U+7B3C(1,3),U+7BED(4) +U+7C61(0);U+7C61(0); +U+7C62(0);U+7C62(4); +U+7C63(0);U+7C63(0); +U+7C64(0);U+7B7E(1,3);U+7C3D(3,4),U+7B7E(1,3),U+7C56(8,9) +U+7C65(0);U+7C65(0); +U+7C66(0);U+7C66(0); +U+7C67(0);U+7C67(0); +U+7C68(0);U+7C68(0); + +U+7C69(0);U+7B3E(1,3);U+7B3E(1,3) +U+7C6A(0);U+7C16(1,3);U+7C16(1,3) +U+7C6B(0);U+7C6B(0); +U+7C6C(0);U+7BF1(1,3);U+7BF1(1,3),U+7B63(0,1,3) +U+7C6D(0);U+7C6D(0); +U+7C6E(0);U+7BA9(1,3);U+7BA9(1,3) +U+7C6F(0);U+7C6F(3); +U+7C70(0);U+7C70(4); +U+7C71(0);U+7C71(3); +U+7C72(0);U+5401(1,3);U+5401(1,3) +U+7C73(0);U+7C73(5); +U+7C74(0);U+7C74(1,3);U+7CF4(1,3) +U+7C75(0);U+8E6F(3);U+8E6F(3),U+756A(3,5) +U+7C77(0);U+7C77(0); +U+7C78(0);U+7C78(3); +U+7C79(0);U+7C79(0); +U+7C7A(0);U+7C7A(3); +U+7C7B(0);U+7C7B(1,3);U+985E(1,3) +U+7C7C(0);U+7C7C(5);U+79C8(2,3) +U+7C7D(0);U+7C7D(5); +U+7C7E(0);U+7C7E(0); +U+7C7F(0);U+7C7F(0); +U+7C80(0);U+7C80(0); +U+7C81(0);U+7C81(0); +U+7C82(0);U+7C82(0); +U+7C84(0);U+7C84(0); +U+7C85(0);U+7C85(0); +U+7C86(0);U+7C86(0); +U+7C88(0);U+7CC5(3);U+7CC5(3) +U+7C89(0);U+7C89(5); +U+7C8A(0);U+7C8A(0); +U+7C8B(0);U+7CB9(3);U+7CB9(3) +U+7C8C(0);U+7C8C(0); +U+7C8D(0);U+7C8D(0); +U+7C8E(0);U+7C8E(0); +U+7C8F(0);U+7C8F(0); +U+7C90(0);U+7C90(0); +U+7C91(0);U+7C91(5); +U+7C92(0);U+7C92(5); +U+7C94(0);U+7C94(0); +U+7C95(0);U+7C95(5); +U+7C96(0);U+7C96(0); +U+7C97(0);U+7C97(5);U+850D(3),U+89D5(2,3),U+9E81(4),U+9E84(3),U+9E86(3),U+9EA4(2,3) +U+7C98(0);U+7C98(5); +U+7C99(0);U+7C99(0); +U+7C9B(0);U+8083(3);U+8083(3),U+8085(3) +U+7C9C(0);U+7C9C(1,3);U+7CF6(1,3) +U+7C9D(0);U+7C9D(1,3);U+7CF2(1,3) +U+7C9E(0);U+7C9E(5); +U+7C9F(0);U+7C9F(5); +U+7CA0(0);U+7CA0(0); +U+7CA1(0);U+7CA1(0); +U+7CA2(0);U+7CA2(5);U+79F6(3) +U+7CA3(0);U+7CA3(0); +U+7CA4(0);U+7CA4(5);U+7CB5(4) +U+7CA5(0);U+7CA5(5);U+9B3B(3) +U+7CA6(0);U+7CA6(0); +U+7CA7(0);U+7CA7(4); +U+7CA8(0);U+7CA8(0); +U+7CA9(0);U+7CA9(0); +U+7CAA(0);U+7CAA(1,3);U+7CDE(1,3) +U+7CAD(0);U+7CAD(0); +U+7CAE(0);U+7CAE(1,3);U+7CE7(1,3,4) + +U+7CAF(0);U+7CAF(0); +U+7CB0(0);U+7CB0(0); +U+7CB1(0);U+7CB1(5); +U+7CB2(0);U+7CB2(5); +U+7CB3(0);U+7CB3(5); +U+7CB4(0);U+7CB4(0); +U+7CB5(0);U+7CA4(4);U+7CA4(4) +U+7CB6(0);U+7CB6(0); +U+7CB7(0);U+7CB7(0); +U+7CB8(0);U+7CB8(0); +U+7CB9(0);U+7CB9(5);U+7C8B(3) +U+7CBA(0);U+7A17(2);U+7A17(2) +U+7CBB(0);U+7CBB(0); +U+7CBC(0);U+7CBC(5); +U+7CBD(0);U+7CBD(5);U+7CC9(2,3),U+7CED(7) +U+7CBE(0);U+7CBE(5); +U+7CBF(0);U+7CBF(0); +U+7CC0(0);U+7CC0(0); +U+7CC1(0);U+7CC1(1,3);U+7CDD(1,3) +U+7CC2(0);U+7CC2(4); +U+7CC3(0);U+7CC3(0); +U+7CC4(0);U+7CC4(0); +U+7CC5(0);U+7CC5(5);U+7C88(3) +U+7CC6(0);U+7CC6(0); +U+7CC7(0);U+7CC7(5);U+9931(2,3) +U+7CC8(0);U+7CC8(5);U+7A30(3) +U+7CC9(0);U+7CBD(2,3);U+7CBD(2,3),U+7CED(2,3,7) +U+7CCA(0);U+7CCA(5);U+992C(2,3) +U+7CCB(0);U+7CCB(0); +U+7CCC(0);U+7CCC(5); +U+7CCD(0);U+7CCD(5);U+9908(2) +U+7CCE(0);U+7CCE(0); +U+7CCF(0);U+7CCF(0); +U+7CD0(0);U+7CD0(0); +U+7CD1(0);U+7CD1(0); +U+7CD2(0);U+7CD2(0); +U+7CD4(0);U+7CD4(0); +U+7CD5(0);U+7CD5(5); +U+7CD6(0);U+7CD6(5);U+9939(2,3) +U+7CD7(0);U+7CD7(5); +U+7CD8(0);U+7CD8(0); +U+7CD9(0);U+7CD9(5); +U+7CDC(0);U+7CDC(5);U+7222(3) +U+7CDD(0);U+7CC1(1,3);U+7CC1(1,3) +U+7CDE(0);U+7CAA(1,3);U+7CAA(1,3) +U+7CDF(0);U+7CDF(5);U+8E67(2) +U+7CE0(0);U+7CE0(5);U+7A45(2,3) +U+7CE2(0);U+7CE2(0); +U+7CE4(0);U+9993(3);U+994A(3),U+9993(3) +U+7CE7(0);U+7CAE(1,3);U+7CAE(1,3) +U+7CE8(0);U+7CE8(5); +U+7CE9(0);U+7CE9(0); +U+7CEA(0);U+7CEA(0); +U+7CEB(0);U+7CEB(0); +U+7CEC(0);U+7CEC(0); +U+7CED(0);U+7CBD(7);U+7CBD(7),U+7CC9(2,3,7) +U+7CEE(0);U+7CEE(0); +U+7CEF(0);U+7CEF(5); +U+7CF0(0);U+56E2(1,3);U+56E2(1,3),U+5718(4),U+56E3(1,3,4) +U+7CF1(0);U+7CF5(4);U+7CF5(4) +U+7CF2(0);U+7C9D(1,3);U+7C9D(1,3) +U+7CF3(0);U+7CF3(0); +U+7CF4(0);U+7C74(1,3);U+7C74(1,3) + +U+7CF5(0);U+7CF5(4);U+7CF1(4) +U+7CF6(0);U+7C9C(1,3);U+7C9C(1,3) +U+7CF7(0);U+7CF7(0); +U+7CF8(0);U+7CF8(5);U+7CF9(8,9),U+7D72(3),U+7E9F(8,9),U+4E1D(1,3) +U+7CF9(0);U+7E9F(4);U+7CF8(8,9),U+7E9F(4),U+7D72(3,8,9),U+4E1D(1,3,8,9) +U+7CFA(0);U+7EA0(4);U+7CFE(2,3),U+7EA0(4) +U+7CFB(0);U+7CFB(1,3);U+4FC2(1,3,4),U+7E6B(1,3,4) +U+7CFD(0);U+7CFD(0); +U+7CFE(0);U+7EA0(1,3);U+7CFA(2,3),U+7EA0(1,3) +U+7D00(0);U+7EAA(1,3);U+7EAA(1,3) +U+7D01(0);U+8869(4);U+8869(4) +U+7D02(0);U+7EA3(1,3);U+7EA3(1,3) +U+7D03(0);U+7D03(0); +U+7D04(0);U+7EA6(1,3);U+7EA6(1,3) +U+7D05(0);U+7EA2(1,3);U+7EA2(1,3) +U+7D06(0);U+7EA1(1,3);U+7EA1(1,3) +U+7D07(0);U+7EA5(1,3);U+7EA5(1,3) +U+7D08(0);U+7EA8(1,3);U+7EA8(1,3) +U+7D09(0);U+7EAB(1,3);U+7EAB(1,3) +U+7D0A(0);U+7D0A(5); +U+7D0B(0);U+7EB9(1,3);U+7EB9(1,3) +U+7D0C(0);U+7D0C(0); +U+7D0D(0);U+7EB3(1,3);U+7EB3(1,3) +U+7D0E(0);U+7D0E(0); +U+7D0F(0);U+7D0F(0); +U+7D10(0);U+7EBD(1,3);U+7EBD(1,3) +U+7D11(0);U+7D11(0); +U+7D12(0);U+7D12(0); +U+7D13(0);U+7EBE(1,3);U+7EBE(1,3) +U+7D14(0);U+7EAF(1,3);U+7EAF(1,3) +U+7D15(0);U+7EB0(1,3);U+7EB0(1,3) +U+7D16(0);U+7EBC(1,3);U+7EBC(1,3),U+7D7C(1,3) +U+7D17(0);U+7EB1(1,3);U+7EB1(1,3) +U+7D18(0);U+7EAE(4);U+7EAE(4) +U+7D19(0);U+7EB8(1,3);U+5E0B(2,3),U+7EB8(1,3) +U+7D1A(0);U+7EA7(1,3);U+7EA7(1,3) +U+7D1B(0);U+7EB7(1,3);U+7EB7(1,3) +U+7D1C(0);U+7EAD(1,3);U+7EAD(1,3) +U+7D1D(0);U+7EB4(1,3);U+7EB4(1,3) +U+7D1E(0);U+7D1E(0); +U+7D1F(0);U+7D1F(0); +U+7D20(0);U+7D20(5);U+69A1(3) +U+7D21(0);U+7EBA(1,3);U+7EBA(1,3) +U+7D22(0);U+7D22(5); +U+7D24(0);U+7D24(0); +U+7D25(0);U+624E(2);U+624E(2),U+7D2E(3),U+5273(0,2,4),U+5284(2,4),U+672D(2,3,4),U+7B9A(2,4) + +U+7D26(0);U+7D26(0); +U+7D27(0);U+7D27(1,3);U+7DCA(1,3) +U+7D28(0);U+7D28(0); +U+7D29(0);U+7D29(0); +U+7D2B(0);U+7D2B(5); +U+7D2C(0);U+4337(1,3);U+4337(1,3),U+7EF8(4),U+7DA2(1,3,4) +U+7D2E(0);U+624E(2);U+624E(2),U+7D25(3),U+5273(0,2,4),U+5284(2,4),U+672D(2,3,4),U+7B9A(2,4) + +U+7D2F(0);U+7D2F(1,3);U+7D6B(3),U+7E8D(1,3) +U+7D30(0);U+7EC6(1,3);U+7EC6(1,3) +U+7D31(0);U+7EC2(1,3);U+7EC2(1,3) +U+7D32(0);U+7EC1(1,3);U+7D4F(2),U+7EC1(1,3) +U+7D33(0);U+7EC5(1,3);U+7EC5(1,3) +U+7D34(0);U+7D34(0); +U+7D35(0);U+7EBB(4);U+7EBB(4) +U+7D36(0);U+7D36(0); + +U+7D37(0);U+7D37(0); +U+7D38(0);U+7D38(0); +U+7D39(0);U+7ECD(1,3);U+7ECD(1,3) +U+7D3A(0);U+7EC0(1,3);U+7EC0(1,3) +U+7D3B(0);U+7D3B(0); +U+7D3C(0);U+7ECB(1,3);U+7ECB(1,3),U+7D8D(1,3) +U+7D3D(0);U+7D3D(0); +U+7D3E(0);U+7D3E(0); +U+7D3F(0);U+7ED0(1,3);U+7ED0(1,3) +U+7D40(0);U+7ECC(1,3);U+7ECC(1,3) +U+7D41(0);U+7D41(0); +U+7D42(0);U+7EC8(1,3);U+7EC8(1,3) +U+7D43(0);U+5F26(2);U+5F26(2) +U+7D44(0);U+7EC4(1,3);U+7EC4(1,3) +U+7D45(0);U+7D45(3); +U+7D46(0);U+7ECA(1,3);U+7ECA(1,3) +U+7D47(0);U+7D47(3); +U+7D49(0);U+7D49(0); +U+7D4A(0);U+7D4A(0); +U+7D4B(0);U+7EA9(4);U+7E8A(4),U+7EA9(4),U+7D56(3,4) +U+7D4C(0);U+7ECF(4);U+7D93(4),U+7ECF(4) +U+7D4E(0);U+7ED7(1,3);U+7ED7(1,3) +U+7D4F(0);U+7EC1(2,3);U+7D32(2),U+7EC1(2,3) +U+7D50(0);U+7ED3(1,3);U+7ED3(1,3) +U+7D51(0);U+7D51(0); +U+7D52(0);U+7D52(0); +U+7D53(0);U+7D53(0); +U+7D54(0);U+7D54(0); +U+7D55(0);U+7EDD(4);U+7D76(8,9),U+7EDD(4) +U+7D56(0);U+7EA9(3);U+7E8A(3),U+7EA9(3),U+7D4B(0,3,4) +U+7D57(0);U+7D57(0); +U+7D58(0);U+7D58(0); +U+7D59(0);U+7D59(4); +U+7D5B(0);U+7EE6(4);U+7EE6(4),U+7E1A(4),U+7E27(1,3,4) +U+7D5C(0);U+7D5C(3); +U+7D5D(0);U+7ED4(1,3);U+7ED4(1,3) +U+7D5E(0);U+7EDE(1,3);U+7EDE(1,3) +U+7D5F(0);U+7D5F(0); +U+7D60(0);U+7D60(0); +U+7D61(0);U+7EDC(1,3);U+7EDC(1,3) +U+7D62(0);U+7EDA(1,3);U+7EDA(1,3) +U+7D63(0);U+7D63(0); +U+7D65(0);U+7D65(0); +U+7D66(0);U+7ED9(1,3);U+7ED9(1,3) +U+7D67(0);U+7D67(0); +U+7D68(0);U+7ED2(1,3);U+7ED2(1,3),U+6BE7(0,1,2,3),U+7FA2(1,2,3) +U+7D69(0);U+7D69(0); +U+7D6A(0);U+7D6A(0); +U+7D6B(0);U+7D2F(3);U+7D2F(3),U+7E8D(1,3) +U+7D6C(0);U+7D6C(0); +U+7D6D(0);U+7D6D(3); +U+7D6E(0);U+7D6E(5); +U+7D6F(0);U+7D6F(0); +U+7D70(0);U+7ED6(1,3);U+7ED6(1,3) +U+7D71(0);U+7EDF(1,3);U+7EDF(1,3) +U+7D72(0);U+4E1D(1,3);U+4E1D(1,3),U+7CF8(3),U+7CF9(3,8,9),U+7E9F(3,8,9) +U+7D73(0);U+7EDB(1,3);U+7EDB(1,3) +U+7D74(0);U+7D74(0); +U+7D75(0);U+7ED8(4);U+7E6A(4),U+7ED8(4),U+7E62(3,4),U+7F0B(0,3,4) +U+7D76(0);U+7EDD(1,3);U+7D55(8,9),U+7EDD(1,3) +U+7D77(0);U+7D77(1,3);U+7E36(1,3),U+99BD(3) +U+7D79(0);U+7EE2(1,3);U+7EE2(1,3) +U+7D7A(0);U+7D7A(0); + +U+7D7B(0);U+7D7B(0); +U+7D7C(0);U+7EBC(3);U+7EBC(3),U+7D16(0,1,3) +U+7D7D(0);U+7D7D(0); +U+7D7E(0);U+7D7E(0); +U+7D7F(0);U+7D7F(0); +U+7D80(0);U+7D80(0); +U+7D81(0);U+7ED1(1,3);U+7ED1(1,3) +U+7D83(0);U+7EE1(1,3);U+7EE1(1,3) +U+7D84(0);U+7D84(0); +U+7D85(0);U+7D85(0); +U+7D86(0);U+7EE0(1,3);U+7EE0(1,3) +U+7D87(0);U+7D87(0); +U+7D88(0);U+7EE8(1,3);U+7EE8(1,3) +U+7D89(0);U+7EE3(1,3);U+7E61(2,3),U+7EE3(1,3),U+7E4D(2,3,8,9) +U+7D8A(0);U+7D8A(0); +U+7D8B(0);U+7D8B(0); +U+7D8C(0);U+7EE4(4);U+7EE4(4) +U+7D8D(0);U+7ECB(3);U+7ECB(3),U+7D3C(0,1,3) +U+7D8E(0);U+7D8E(0); +U+7D8F(0);U+7EE5(1,3);U+7EE5(1,3),U+7DCC(1,3,4) +U+7D90(0);U+7D90(0); +U+7D91(0);U+6346(2,3);U+6346(2,3) +U+7D92(0);U+7D92(0); +U+7D93(0);U+7ECF(1,3);U+7D4C(4),U+7ECF(1,3) +U+7D94(0);U+7D94(0); +U+7D96(0);U+7D96(0); +U+7D97(0);U+7D97(0); +U+7D99(0);U+7EE7(3);U+7E7C(3),U+7EE7(3) +U+7D9B(0);U+7D9B(0); +U+7D9C(0);U+7EFC(1,3);U+7EFC(1,3) +U+7D9D(0);U+7D9D(0); +U+7D9E(0);U+7F0D(4);U+7F0D(4) +U+7D9F(0);U+7D9F(0); +U+7DA0(0);U+7EFF(4);U+7DD1(8,9),U+7EFF(4) +U+7DA1(0);U+7DA1(0); +U+7DA2(0);U+7EF8(1,3);U+7EF8(1,3),U+4337(1,3,4),U+7D2C(0,1,3,4) +U+7DA3(0);U+7EFB(1,3);U+7EFB(1,3) +U+7DA5(0);U+7DA5(3); +U+7DA6(0);U+7DA6(5); +U+7DA7(0);U+7DA7(0); +U+7DA9(0);U+7DA9(0); +U+7DAA(0);U+7DAA(0); +U+7DAB(0);U+7EBF(1,3);U+7DDA(2,3),U+7EBF(1,3),U+7F10(2,3,4) +U+7DAC(0);U+7EF6(1,3);U+7EF6(1,3) +U+7DAD(0);U+7EF4(1,3);U+7EF4(1,3) +U+7DAE(0);U+7DAE(5);U+68E8(4) +U+7DAF(0);U+7EF9(4);U+7EF9(4) +U+7DB0(0);U+7EFE(1,3);U+7EFE(1,3) +U+7DB1(0);U+7EB2(1,3);U+7EB2(1,3) +U+7DB2(0);U+7F51(1,3);U+7F51(1,3) +U+7DB3(0);U+7EF7(1,3);U+7E43(2,3),U+7EF7(1,3) +U+7DB4(0);U+7F00(1,3);U+7F00(1,3) +U+7DB5(0);U+5F69(2);U+5F69(2) +U+7DB6(0);U+7DB6(0); +U+7DB7(0);U+7DB7(3); +U+7DB8(0);U+7EB6(1,3);U+7EB6(1,3) +U+7DB9(0);U+7EFA(1,3);U+7EFA(1,3) +U+7DBA(0);U+7EEE(1,3);U+7EEE(1,3) +U+7DBB(0);U+7EFD(1,3);U+7EFD(1,3) +U+7DBC(0);U+7DBC(0); +U+7DBD(0);U+7EF0(1,3);U+7EF0(1,3) +U+7DBE(0);U+7EEB(1,3);U+7EEB(1,3) +U+7DBF(0);U+7EF5(1,3);U+7EF5(1,3) + +U+7DC0(0);U+7DC0(3); +U+7DC1(0);U+7DC1(0); +U+7DC2(0);U+7DC2(0); +U+7DC3(0);U+7DC3(0); +U+7DC4(0);U+7EF2(1,3);U+7EF2(1,3) +U+7DC5(0);U+7DC5(0); +U+7DC6(0);U+7DC6(0); +U+7DC7(0);U+7F01(1,3);U+7F01(1,3) +U+7DC8(0);U+7DC8(0); +U+7DC9(0);U+7DC9(0); +U+7DCA(0);U+7D27(1,3);U+7D27(1,3) +U+7DCB(0);U+7EEF(1,3);U+7EEF(1,3) +U+7DCC(0);U+7EE5(4);U+7EE5(4),U+7D8F(0,1,3,4) +U+7DCE(0);U+7DCE(0); +U+7DCF(0);U+603B(3);U+603B(3),U+7E3D(3),U+6374(3,4),U+6403(3),U+6460(3),U+7E02(3,4) +U+7DD0(0);U+7E41(2);U+7E41(2) +U+7DD1(0);U+7EFF(1,3);U+7DA0(8,9),U+7EFF(1,3) +U+7DD2(0);U+7EEA(1,3);U+7DD6(4),U+7EEA(1,3) +U+7DD4(0);U+7EF1(4);U+7EF1(4) +U+7DD5(0);U+7DD5(0); +U+7DD6(0);U+7EEA(4);U+7DD2(4),U+7EEA(4) +U+7DD7(0);U+7F03(1,3);U+7F03(1,3) +U+7DD8(0);U+7F04(1,3);U+7F04(1,3) +U+7DD9(0);U+7F02(1,3);U+7F02(1,3) +U+7DDA(0);U+7EBF(4);U+7DAB(2,3),U+7EBF(4),U+7F10(4) +U+7DDB(0);U+7DDB(0); +U+7DDD(0);U+7F09(1,3);U+7F09(1,3) +U+7DDE(0);U+7F0E(1,3);U+7F0E(1,3) +U+7DDF(0);U+91CD(3);U+91CD(3) +U+7DE0(0);U+7F14(1,3);U+7F14(1,3) +U+7DE1(0);U+7F17(1,3);U+7F17(1,3) +U+7DE2(0);U+7DE2(0); +U+7DE3(0);U+7F18(1,3);U+7E01(4),U+7F18(1,3) +U+7DE6(0);U+7F0C(1,3);U+7F0C(1,3) +U+7DE7(0);U+7DE7(0); +U+7DE8(0);U+7F16(1,3);U+7F16(1,3) +U+7DE9(0);U+7F13(1,3);U+7F13(1,3) +U+7DEA(0);U+7E06(3);U+7E06(3) +U+7DEC(0);U+7F05(1,3);U+7F05(1,3) +U+7DED(0);U+7DED(0); +U+7DEE(0);U+7DEE(0); +U+7DEF(0);U+7EAC(1,3);U+7EAC(1,3) +U+7DF0(0);U+7DF0(0); +U+7DF1(0);U+7F11(1,3);U+7F11(1,3) +U+7DF2(0);U+7F08(1,3);U+7F08(1,3) +U+7DF3(0);U+7DF3(0); +U+7DF4(0);U+7EC3(1,3);U+7EC3(1,3) +U+7DF5(0);U+7DF5(0); +U+7DF6(0);U+7F0F(4);U+7F0F(4) +U+7DF7(0);U+886E(3);U+886E(3),U+889E(3) +U+7DF8(0);U+7DF8(0); +U+7DF9(0);U+7F07(1,3);U+7F07(1,3) +U+7DFA(0);U+7DFA(0); +U+7DFB(0);U+81F4(1,3);U+81F4(1,3) +U+7DFC(0);U+7F0A(1,3);U+7E15(3),U+7F0A(1,3),U+891E(1,3,4) +U+7E00(0);U+7E00(0); +U+7E01(0);U+7F18(4);U+7DE3(4),U+7F18(4) +U+7E02(0);U+603B(4);U+603B(4),U+7E3D(4),U+6374(4),U+6403(3,4),U+6460(3,4),U+7DCF(3,4) + +U+7E03(0);U+80E5(3);U+80E5(3) +U+7E04(0);U+7EF3(3);U+7E69(3),U+7EF3(3) +U+7E05(0);U+7E05(0); +U+7E06(0);U+7E06(4);U+7DEA(3) + +U+7E07(0);U+7E07(0); +U+7E08(0);U+8426(1,3);U+8426(1,3) +U+7E09(0);U+7F19(1,3);U+7F19(1,3) +U+7E0A(0);U+7F22(1,3);U+7F22(1,3) +U+7E0B(0);U+7F12(1,3);U+7F12(1,3) +U+7E0C(0);U+7E0C(0); +U+7E0D(0);U+5E2E(3);U+5E2E(3),U+5E47(3,4),U+5E5A(3),U+5E6B(1,3,4),U+97A4(3,4) +U+7E0E(0);U+7E0E(0); +U+7E0F(0);U+7E0F(0); +U+7E10(0);U+7EC9(1,3);U+7EC9(1,3) +U+7E11(0);U+7F23(1,3);U+7F23(1,3) +U+7E12(0);U+7E12(0); +U+7E13(0);U+7E13(0); +U+7E14(0);U+7E14(0); +U+7E15(0);U+7F0A(4);U+7DFC(3),U+7F0A(4),U+891E(1,3,4) +U+7E16(0);U+7E16(0); +U+7E17(0);U+7F1E(1,3);U+7F1E(1,3) +U+7E19(0);U+7E19(0); +U+7E1A(0);U+7EE6(2,4);U+7EE6(2,4),U+7D5B(0,4),U+7E27(1,3,4) +U+7E1B(0);U+7F1A(1,3);U+7F1A(1,3) +U+7E1C(0);U+7E1C(0); +U+7E1D(0);U+7F1C(1,3);U+7F1C(1,3) +U+7E1E(0);U+7F1F(1,3);U+7F1F(1,3) +U+7E1F(0);U+7F1B(1,3);U+7F1B(1,3) +U+7E20(0);U+7E20(0); +U+7E21(0);U+7E21(0); +U+7E22(0);U+7E22(0); +U+7E23(0);U+53BF(1,3);U+53BF(1,3) +U+7E24(0);U+7E24(0); +U+7E25(0);U+7E25(0); +U+7E26(0);U+7EB5(3);U+7E31(3),U+7EB5(3) +U+7E27(0);U+7EE6(1,3);U+7EE6(1,3),U+7D5B(0,1,3,4),U+7E1A(1,3,4) +U+7E28(0);U+7E28(0); +U+7E29(0);U+7E29(0); +U+7E2A(0);U+7E2A(3); +U+7E2B(0);U+7F1D(1,3);U+7F1D(1,3) +U+7E2C(0);U+7E2C(3); +U+7E2D(0);U+7F21(1,3);U+7F21(1,3),U+8935(1,3) +U+7E2E(0);U+7F29(1,3);U+7F29(1,3),U+644D(0,1,3,4) +U+7E2F(0);U+7E2F(0); +U+7E30(0);U+7E30(0); +U+7E31(0);U+7EB5(1,3);U+7E26(3),U+7EB5(1,3) +U+7E32(0);U+7F27(1,3);U+7F27(1,3) +U+7E33(0);U+7E33(0); +U+7E34(0);U+7EA4(1,3);U+7EA4(1,3),U+5B45(0,1,3),U+7E8E(1,3),U+7E96(1,3) +U+7E35(0);U+7F26(1,3);U+7F26(1,3) +U+7E36(0);U+7D77(1,3);U+7D77(1,3),U+99BD(1,3) +U+7E37(0);U+7F15(1,3);U+7F15(1,3) +U+7E38(0);U+7E38(0); +U+7E39(0);U+7F25(1,3);U+7F25(1,3) +U+7E3A(0);U+7E3A(0); +U+7E3B(0);U+7E3B(5); +U+7E3C(0);U+7E3C(0); +U+7E3D(0);U+603B(1,3);U+603B(1,3),U+6374(4),U+6403(3),U+7DCF(3),U+7E02(4),U+6460(1,3) + +U+7E3E(0);U+7EE9(1,3);U+7EE9(1,3),U+52E3(0,1,3,4) +U+7E3F(0);U+7E3F(3); +U+7E40(0);U+7E40(0); +U+7E41(0);U+7E41(5);U+7DD0(2) +U+7E42(0);U+7E42(0); +U+7E43(0);U+7EF7(4);U+7DB3(2,3),U+7EF7(4) +U+7E44(0);U+7E44(0); +U+7E45(0);U+7F2B(1,3);U+7F2B(1,3) + +U+7E46(0);U+7F2A(1,3);U+7F2A(1,3) +U+7E47(0);U+7E47(5); +U+7E48(0);U+7E66(4);U+7E66(4) +U+7E49(0);U+7E49(0); +U+7E4C(0);U+7E4C(0); +U+7E4D(0);U+7EE3(4);U+7E61(8,9),U+7EE3(4),U+7D89(0,2,3,8,9) +U+7E4E(0);U+7E4E(0); +U+7E4F(0);U+7E4F(0); +U+7E50(0);U+7E50(0); +U+7E51(0);U+7E51(4); +U+7E52(0);U+7F2F(1,3);U+7F2F(1,3) +U+7E53(0);U+7E53(0); +U+7E54(0);U+7EC7(1,3);U+7EC7(1,3) +U+7E55(0);U+7F2E(1,3);U+7F2E(1,3) +U+7E56(0);U+4F1E(4);U+4F1E(4),U+5098(1,3,4) +U+7E57(0);U+7E57(0); +U+7E58(0);U+7E58(0); +U+7E59(0);U+7FFB(2,3);U+7FFB(2,3),U+98DC(2,3) +U+7E5A(0);U+7F2D(1,3);U+7F2D(1,3) +U+7E5C(0);U+7E5C(0); +U+7E5D(0);U+7E5D(0); +U+7E5E(0);U+7ED5(1,3);U+7ED5(1,3),U+9076(1,3,4) +U+7E5F(0);U+7E5F(0); +U+7E60(0);U+7E60(3); +U+7E61(0);U+7EE3(4);U+7D89(2,3),U+7E4D(8,9),U+7EE3(4) +U+7E62(0);U+7F0B(4);U+7E6A(3),U+7F0B(4),U+7D75(0,3,4),U+7ED8(3,4) +U+7E63(0);U+7E63(0); +U+7E65(0);U+7E65(0); +U+7E66(0);U+7E66(3);U+7E48(4) +U+7E67(0);U+7E67(0); +U+7E68(0);U+7E68(0); +U+7E69(0);U+7EF3(1,3);U+7E04(3),U+7EF3(1,3) +U+7E6A(0);U+7ED8(1,3);U+7D75(4),U+7E62(3),U+7ED8(1,3),U+7F0B(3,4) +U+7E6B(0);U+7CFB(1,3);U+7CFB(1,3),U+4FC2(0,1,3,4) +U+7E6C(0);U+7E6C(0); +U+7E6D(0);U+8327(1,3);U+8327(1,3) +U+7E6E(0);U+7F30(1,3);U+7F30(1,3),U+97C1(1,3,4) +U+7E6F(0);U+7F33(1,3);U+7F33(1,3) +U+7E70(0);U+7F32(1,3);U+7F32(1,3) +U+7E71(0);U+7E71(0); +U+7E72(0);U+7E72(0); +U+7E73(0);U+7F34(1,3);U+7F34(1,3) +U+7E74(0);U+7E74(0); +U+7E75(0);U+7E75(0); +U+7E76(0);U+7E76(0); +U+7E77(0);U+7E77(0); +U+7E78(0);U+7E78(0); +U+7E79(0);U+7ECE(1,3);U+7ECE(1,3) +U+7E7A(0);U+7E7A(0); +U+7E7B(0);U+7E7B(0); +U+7E7C(0);U+7EE7(1,3);U+7D99(3),U+7EE7(1,3) +U+7E7D(0);U+7F24(1,3);U+7F24(1,3) +U+7E7E(0);U+7F31(1,3);U+7F31(1,3) +U+7E7F(0);U+8934(3);U+8934(3),U+8964(3) +U+7E80(0);U+7E80(3); +U+7E81(0);U+7E81(0); +U+7E82(0);U+7E82(5); +U+7E83(0);U+7E83(0); +U+7E84(0);U+7E84(0); +U+7E85(0);U+7E85(0); +U+7E86(0);U+7E86(0); +U+7E87(0);U+98A3(4);U+98A3(4) +U+7E88(0);U+7F2C(1,3);U+7F2C(1,3) + +U+7E89(0);U+7F35(3);U+7E98(3),U+7F35(3) +U+7E8A(0);U+7EA9(1,3);U+7D4B(4),U+7D56(3),U+7EA9(1,3) +U+7E8B(0);U+7E8B(0); +U+7E8C(0);U+7EED(1,3);U+7EED(1,3) +U+7E8D(0);U+7D2F(1,3);U+7D2F(1,3),U+7D6B(1,3) +U+7E8E(0);U+7EA4(3);U+7E96(3),U+7EA4(3),U+5B45(0,3),U+7E34(1,3) +U+7E8F(0);U+7F20(1,3);U+7E92(3),U+7F20(1,3) +U+7E90(0);U+7E90(0); +U+7E91(0);U+7E91(0); +U+7E92(0);U+7F20(3);U+7E8F(3),U+7F20(3) +U+7E93(0);U+7F28(1,3);U+7F28(1,3) +U+7E94(0);U+624D(1,3);U+624D(1,3) +U+7E95(0);U+7E95(0); +U+7E96(0);U+7EA4(1,3);U+7E8E(3),U+7EA4(1,3),U+5B45(0,1,3),U+7E34(1,3) +U+7E97(0);U+7E97(0); +U+7E98(0);U+7F35(1,3);U+7E89(3),U+7F35(1,3) +U+7E99(0);U+7E99(0); +U+7E9A(0);U+7E9A(0); +U+7E9B(0);U+7E9B(5);U+7FE2(3) +U+7E9C(0);U+7F06(1,3);U+7F06(1,3) +U+7E9E(0);U+7E9E(0); +U+7E9F(0);U+7E9F(4);U+7CF8(8,9),U+7CF9(4),U+7D72(3,8,9),U+4E1D(1,3,8,9) +U+7EA0(0);U+7EA0(1,3);U+7CFA(4),U+7CFE(1,3) +U+7EA1(0);U+7EA1(1,3);U+7D06(1,3) +U+7EA2(0);U+7EA2(1,3);U+7D05(1,3) +U+7EA3(0);U+7EA3(1,3);U+7D02(1,3) +U+7EA4(0);U+7EA4(1,3);U+5B45(3),U+7E34(1,3),U+7E8E(3),U+7E96(1,3) +U+7EA5(0);U+7EA5(1,3);U+7D07(1,3) +U+7EA6(0);U+7EA6(1,3);U+7D04(1,3) +U+7EA7(0);U+7EA7(1,3);U+7D1A(1,3) +U+7EA8(0);U+7EA8(1,3);U+7D08(1,3) +U+7EA9(0);U+7EA9(1,3);U+7D4B(4),U+7D56(3),U+7E8A(1,3) +U+7EAA(0);U+7EAA(1,3);U+7D00(1,3) +U+7EAB(0);U+7EAB(1,3);U+7D09(1,3) +U+7EAC(0);U+7EAC(1,3);U+7DEF(1,3) +U+7EAD(0);U+7EAD(1,3);U+7D1C(1,3) +U+7EAE(0);U+7EAE(4);U+7D18(4) +U+7EAF(0);U+7EAF(1,3);U+7D14(1,3) +U+7EB0(0);U+7EB0(1,3);U+7D15(1,3) +U+7EB1(0);U+7EB1(1,3);U+7D17(1,3) +U+7EB2(0);U+7EB2(1,3);U+7DB1(1,3) +U+7EB3(0);U+7EB3(1,3);U+7D0D(1,3) +U+7EB4(0);U+7EB4(1,3);U+7D1D(1,3) +U+7EB5(0);U+7EB5(1,3);U+7E26(3),U+7E31(1,3) +U+7EB6(0);U+7EB6(1,3);U+7DB8(1,3) +U+7EB7(0);U+7EB7(1,3);U+7D1B(1,3) +U+7EB8(0);U+7EB8(1,3);U+5E0B(4),U+7D19(1,3) +U+7EB9(0);U+7EB9(1,3);U+7D0B(1,3) +U+7EBA(0);U+7EBA(1,3);U+7D21(1,3) +U+7EBB(0);U+7EBB(4);U+7D35(4) +U+7EBC(0);U+7EBC(1,3);U+7D16(1,3),U+7D7C(3) +U+7EBD(0);U+7EBD(1,3);U+7D10(1,3) +U+7EBE(0);U+7EBE(1,3);U+7D13(1,3) +U+7EBF(0);U+7EBF(1,3,4);U+7DAB(1,3),U+7DDA(4),U+7F10(4) +U+7EC0(0);U+7EC0(1,3);U+7D3A(1,3) +U+7EC1(0);U+7EC1(1,3);U+7D32(1,3),U+7D4F(2,3) +U+7EC2(0);U+7EC2(1,3);U+7D31(1,3) +U+7EC3(0);U+7EC3(1,3);U+7DF4(1,3) +U+7EC4(0);U+7EC4(1,3);U+7D44(1,3) +U+7EC5(0);U+7EC5(1,3);U+7D33(1,3) +U+7EC6(0);U+7EC6(1,3);U+7D30(1,3) +U+7EC7(0);U+7EC7(1,3);U+7E54(1,3) +U+7EC8(0);U+7EC8(1,3);U+7D42(1,3) + +U+7EC9(0);U+7EC9(1,3);U+7E10(1,3) +U+7ECA(0);U+7ECA(1,3);U+7D46(1,3) +U+7ECB(0);U+7ECB(1,3);U+7D3C(1,3),U+7D8D(3) +U+7ECC(0);U+7ECC(1,3);U+7D40(1,3) +U+7ECD(0);U+7ECD(1,3);U+7D39(1,3) +U+7ECE(0);U+7ECE(1,3);U+7E79(1,3) +U+7ECF(0);U+7ECF(1,3);U+7D4C(4),U+7D93(1,3) +U+7ED0(0);U+7ED0(1,3);U+7D3F(1,3) +U+7ED1(0);U+7ED1(1,3);U+7D81(1,3) +U+7ED2(0);U+7ED2(1,3);U+6BE7(2),U+7D68(1,3),U+7FA2(2) +U+7ED3(0);U+7ED3(1,3);U+7D50(1,3) +U+7ED4(0);U+7ED4(1,3);U+7D5D(1,3) +U+7ED5(0);U+7ED5(1,3);U+7E5E(1,3),U+9076(4) +U+7ED6(0);U+7ED6(1,3);U+7D70(1,3) +U+7ED7(0);U+7ED7(1,3);U+7D4E(1,3) +U+7ED8(0);U+7ED8(1,3);U+7D75(4),U+7E6A(1,3),U+7E62(3,4),U+7F0B(3,4) +U+7ED9(0);U+7ED9(1,3);U+7D66(1,3) +U+7EDA(0);U+7EDA(1,3);U+7D62(1,3) +U+7EDB(0);U+7EDB(1,3);U+7D73(1,3) +U+7EDC(0);U+7EDC(1,3);U+7D61(1,3) +U+7EDD(0);U+7EDD(1,3,4);U+7D55(4),U+7D76(1,3) +U+7EDE(0);U+7EDE(1,3);U+7D5E(1,3) +U+7EDF(0);U+7EDF(1,3);U+7D71(1,3) +U+7EE0(0);U+7EE0(1,3);U+7D86(1,3) +U+7EE1(0);U+7EE1(1,3);U+7D83(1,3) +U+7EE2(0);U+7EE2(1,3);U+7D79(1,3) +U+7EE3(0);U+7EE3(1,3,4);U+7D89(1,3),U+7E4D(4),U+7E61(4) +U+7EE4(0);U+7EE4(4);U+7D8C(4) +U+7EE5(0);U+7EE5(1,3);U+7D8F(1,3),U+7DCC(4) +U+7EE6(0);U+7EE6(1,3);U+7D5B(4),U+7E1A(4),U+7E27(1,3) +U+7EE7(0);U+7EE7(1,3);U+7D99(3),U+7E7C(1,3) +U+7EE8(0);U+7EE8(1,3);U+7D88(1,3) +U+7EE9(0);U+7EE9(1,3);U+52E3(4),U+7E3E(1,3) +U+7EEA(0);U+7EEA(1,3);U+7DD2(1,3),U+7DD6(4) +U+7EEB(0);U+7EEB(1,3);U+7DBE(1,3) +U+7EEC(0);U+7EEC(4); +U+7EED(0);U+7EED(1,3);U+7E8C(1,3) +U+7EEE(0);U+7EEE(1,3);U+7DBA(1,3) +U+7EEF(0);U+7EEF(1,3);U+7DCB(1,3) +U+7EF0(0);U+7EF0(1,3);U+7DBD(1,3) +U+7EF1(0);U+7EF1(4);U+7DD4(4) +U+7EF2(0);U+7EF2(1,3);U+7DC4(1,3) +U+7EF3(0);U+7EF3(1,3);U+7E04(3),U+7E69(1,3) +U+7EF4(0);U+7EF4(1,3);U+7DAD(1,3) +U+7EF5(0);U+7EF5(1,3);U+7DBF(1,3) +U+7EF6(0);U+7EF6(1,3);U+7DAC(1,3) +U+7EF7(0);U+7EF7(1,3,4);U+7DB3(1,3),U+7E43(4) +U+7EF8(0);U+7EF8(1,3);U+7D2C(4),U+7DA2(1,3),U+4337(1,3,4) +U+7EF9(0);U+7EF9(4);U+7DAF(4) +U+7EFA(0);U+7EFA(1,3);U+7DB9(1,3) +U+7EFB(0);U+7EFB(1,3);U+7DA3(1,3) +U+7EFC(0);U+7EFC(1,3);U+7D9C(1,3) +U+7EFD(0);U+7EFD(1,3);U+7DBB(1,3) +U+7EFE(0);U+7EFE(1,3);U+7DB0(1,3) +U+7EFF(0);U+7EFF(1,3,4);U+7DA0(4),U+7DD1(1,3) +U+7F00(0);U+7F00(1,3);U+7DB4(1,3) +U+7F01(0);U+7F01(1,3);U+7DC7(1,3) +U+7F02(0);U+7F02(1,3);U+7DD9(1,3) +U+7F03(0);U+7F03(1,3);U+7DD7(1,3) +U+7F04(0);U+7F04(1,3);U+7DD8(1,3) +U+7F05(0);U+7F05(1,3);U+7DEC(1,3) +U+7F06(0);U+7F06(1,3);U+7E9C(1,3) +U+7F07(0);U+7F07(1,3);U+7DF9(1,3) + +U+7F08(0);U+7F08(1,3);U+7DF2(1,3) +U+7F09(0);U+7F09(1,3);U+7DDD(1,3) +U+7F0A(0);U+7F0A(1,3,4);U+7DFC(1,3),U+7E15(4),U+891E(4) +U+7F0B(0);U+7F0B(4);U+7E62(4),U+7E6A(3,4),U+7D75(0,3,4),U+7ED8(3,4) +U+7F0C(0);U+7F0C(1,3);U+7DE6(1,3) +U+7F0D(0);U+7F0D(4);U+7D9E(4) +U+7F0E(0);U+7F0E(1,3);U+7DDE(1,3) +U+7F0F(0);U+7F0F(4);U+7DF6(4) +U+7F10(0);U+7EBF(4);U+7DDA(4),U+7EBF(4),U+7DAB(0,2,3,4) +U+7F11(0);U+7F11(1,3);U+7DF1(1,3) +U+7F12(0);U+7F12(1,3);U+7E0B(1,3) +U+7F13(0);U+7F13(1,3);U+7DE9(1,3) +U+7F14(0);U+7F14(1,3);U+7DE0(1,3) +U+7F15(0);U+7F15(1,3);U+7E37(1,3) +U+7F16(0);U+7F16(1,3);U+7DE8(1,3) +U+7F17(0);U+7F17(1,3);U+7DE1(1,3) +U+7F18(0);U+7F18(1,3);U+7DE3(1,3),U+7E01(4) +U+7F19(0);U+7F19(1,3);U+7E09(1,3) +U+7F1A(0);U+7F1A(1,3);U+7E1B(1,3) +U+7F1B(0);U+7F1B(1,3);U+7E1F(1,3) +U+7F1C(0);U+7F1C(1,3);U+7E1D(1,3) +U+7F1D(0);U+7F1D(1,3);U+7E2B(1,3) +U+7F1E(0);U+7F1E(1,3);U+7E17(1,3) +U+7F1F(0);U+7F1F(1,3);U+7E1E(1,3) +U+7F20(0);U+7F20(1,3);U+7E8F(1,3),U+7E92(3) +U+7F21(0);U+7F21(1,3);U+8935(3),U+7E2D(1,3) +U+7F22(0);U+7F22(1,3);U+7E0A(1,3) +U+7F23(0);U+7F23(1,3);U+7E11(1,3) +U+7F24(0);U+7F24(1,3);U+7E7D(1,3) +U+7F25(0);U+7F25(1,3);U+7E39(1,3) +U+7F26(0);U+7F26(1,3);U+7E35(1,3) +U+7F27(0);U+7F27(1,3);U+7E32(1,3) +U+7F28(0);U+7F28(1,3);U+7E93(1,3) +U+7F29(0);U+7F29(1,3);U+644D(4),U+7E2E(1,3) +U+7F2A(0);U+7F2A(1,3);U+7E46(1,3) +U+7F2B(0);U+7F2B(1,3);U+7E45(1,3) +U+7F2C(0);U+7F2C(1,3);U+7E88(1,3) +U+7F2D(0);U+7F2D(1,3);U+7E5A(1,3) +U+7F2E(0);U+7F2E(1,3);U+7E55(1,3) +U+7F2F(0);U+7F2F(1,3);U+7E52(1,3) +U+7F30(0);U+7F30(1,3,4);U+7E6E(1,3),U+97C1(4) +U+7F31(0);U+7F31(1,3);U+7E7E(1,3) +U+7F32(0);U+7F32(1,3);U+7E70(1,3) +U+7F33(0);U+7F33(1,3);U+7E6F(1,3) +U+7F34(0);U+7F34(1,3);U+7E73(1,3) +U+7F35(0);U+7F35(1,3);U+7E89(3),U+7E98(1,3) +U+7F36(0);U+7F36(5); +U+7F37(0);U+5378(3);U+5378(3) +U+7F38(0);U+7F38(5);U+5808(3) +U+7F39(0);U+7F39(4); +U+7F3A(0);U+7F3A(5); +U+7F3D(0);U+94B5(4);U+9262(2,3),U+94B5(4) +U+7F3E(0);U+74F6(2);U+74F6(2),U+7501(2,3) +U+7F3F(0);U+7F3F(3); +U+7F40(0);U+7F40(0); +U+7F42(0);U+7F42(1,3);U+7507(3),U+7516(2,3),U+7F43(3),U+7F4C(1,3) +U+7F43(0);U+7F42(3);U+7F42(3),U+7507(0,3),U+7516(2,3),U+7F4C(1,3) +U+7F44(0);U+7F44(5); +U+7F45(0);U+7F45(5);U+93EC(4) +U+7F47(0);U+6A3D(2,3);U+6A3D(2,3),U+58AB(0,2,3) +U+7F48(0);U+575B(4);U+575B(4),U+58C7(1,3,4),U+7F4E(1,3,4) +U+7F49(0);U+7F49(0); +U+7F4A(0);U+7F4A(0); + +U+7F4B(0);U+74EE(2,3);U+74EE(2,3),U+7515(2,3,4) +U+7F4C(0);U+7F42(1,3);U+7F42(1,3),U+7507(0,1,3),U+7516(1,2,3),U+7F43(1,3) +U+7F4D(0);U+7F4D(3); +U+7F4E(0);U+575B(1,3);U+575B(1,3),U+58C7(4),U+7F48(1,3,4) +U+7F4F(0);U+5786(3);U+5786(3),U+58DA(1,3) +U+7F50(0);U+7F50(5);U+9475(2,3) +U+7F51(0);U+7F51(1,3);U+7DB2(1,3) +U+7F52(0);U+7F52(0); +U+7F53(0);U+7F53(0); +U+7F54(0);U+7F54(5); +U+7F55(0);U+7F55(5); +U+7F56(0);U+7F56(0); +U+7F57(0);U+7F57(1,3);U+7F85(1,3) +U+7F58(0);U+7F58(5);U+7F66(3) +U+7F5A(0);U+7F5A(1,3);U+7F70(1,3),U+7F78(4) +U+7F5B(0);U+7F5B(0); +U+7F5C(0);U+7F5C(0); +U+7F5D(0);U+7F5D(0); +U+7F5E(0);U+7F5E(0); +U+7F5F(0);U+7F5F(5); +U+7F60(0);U+7F60(0); +U+7F61(0);U+7F61(5); +U+7F62(0);U+7F62(1,3);U+7F77(1,3) +U+7F63(0);U+6302(4);U+6302(4),U+639B(2,3,4) +U+7F64(0);U+7F64(0); +U+7F65(0);U+7F65(3);U+7F82(3) +U+7F66(0);U+7F66(3);U+7F58(3) +U+7F67(0);U+7F67(3); +U+7F68(0);U+7F68(5); +U+7F69(0);U+7F69(5); +U+7F6A(0);U+7F6A(5);U+8FA0(2) +U+7F6B(0);U+7F6B(0); +U+7F6C(0);U+7F6C(3); +U+7F6D(0);U+7F6D(0); +U+7F6E(0);U+7F6E(5);U+5BD8(2) +U+7F6F(0);U+7F6F(0); +U+7F70(0);U+7F5A(1,3);U+7F5A(1,3),U+7F78(2,3) +U+7F71(0);U+7F71(5); +U+7F72(0);U+7F72(5); +U+7F73(0);U+7F73(0); +U+7F74(0);U+7F74(1,3);U+7F86(1,3) +U+7F75(0);U+9A82(4);U+99E1(2,3),U+9A82(4),U+508C(0,4) +U+7F76(0);U+7F76(4);U+7F80(4) +U+7F77(0);U+7F62(1,3);U+7F62(1,3) +U+7F78(0);U+7F5A(4);U+7F5A(4),U+7F70(2,3) +U+7F79(0);U+7F79(5); +U+7F7A(0);U+7F7A(3); +U+7F7B(0);U+7F7B(0); +U+7F7C(0);U+6BD5(3);U+6BD5(3),U+7562(1,3),U+93CE(3) +U+7F7D(0);U+7F7D(0); +U+7F7E(0);U+7F7E(5); +U+7F7F(0);U+7F7F(0); +U+7F80(0);U+7F76(4);U+7F76(4) +U+7F81(0);U+7F81(1,3);U+7F87(4),U+7F88(1,3),U+8989(3),U+898A(2,3) +U+7F82(0);U+7F65(3);U+7F65(3) +U+7F83(0);U+5E42(2,3);U+51AA(3),U+5E42(2,3) +U+7F85(0);U+7F57(1,3);U+7F57(1,3) +U+7F86(0);U+7F74(1,3);U+7F74(1,3) +U+7F87(0);U+7F81(4);U+7F81(4),U+7F88(4),U+8989(8,9),U+898A(2,3,4) +U+7F88(0);U+7F81(1,3);U+7F81(1,3),U+7F87(4),U+8989(3),U+898A(2,3) +U+7F89(0);U+7F89(0); +U+7F8A(0);U+7F8A(5); +U+7F8B(0);U+8288(4);U+8288(4) + +U+7F8C(0);U+7F8C(5); +U+7F8D(0);U+7F8D(3); +U+7F8E(0);U+7F8E(5);U+5ABA(3) +U+7F8F(0);U+7F8F(0); +U+7F91(0);U+7F91(3); +U+7F92(0);U+7F92(0); +U+7F93(0);U+7F93(3); +U+7F94(0);U+7F94(5); +U+7F95(0);U+7F95(0); +U+7F96(0);U+7F96(0); +U+7F98(0);U+7F98(0); +U+7F9A(0);U+7F9A(5); +U+7F9B(0);U+4E49(3);U+4E49(3),U+7FA9(1,3) +U+7F9C(0);U+7F9C(0); +U+7F9D(0);U+7F9D(5);U+7274(3),U+627A(2,3),U+62B5(2,3,5),U+89DD(2,3) +U+7F9E(0);U+7F9E(5); +U+7F9F(0);U+7F9F(1,3);U+7FA5(1,3) +U+7FA0(0);U+7FA0(0); +U+7FA1(0);U+7FA1(5);U+7FA8(3,4) +U+7FA2(0);U+7ED2(2);U+7ED2(2),U+6BE7(0,2),U+7D68(1,2,3) +U+7FA3(0);U+7FA4(2,3);U+7FA4(2,3) +U+7FA4(0);U+7FA4(5);U+7FA3(2,3) +U+7FA5(0);U+7F9F(1,3);U+7F9F(1,3) +U+7FA6(0);U+7FA6(0); +U+7FA7(0);U+7FA7(5); +U+7FA8(0);U+7FA1(3,4);U+7FA1(3,4) +U+7FA9(0);U+4E49(1,3);U+4E49(1,3),U+7F9B(1,3) +U+7FAA(0);U+7FAA(0); +U+7FAB(0);U+7FAB(3); +U+7FAC(0);U+7FAC(3); +U+7FAD(0);U+7FAD(0); +U+7FAE(0);U+7FB9(4);U+7FB9(4) +U+7FAF(0);U+7FAF(5); +U+7FB0(0);U+7FB0(5); +U+7FB1(0);U+7FB1(3); +U+7FB2(0);U+7FB2(5); +U+7FB3(0);U+7FB3(0); +U+7FB5(0);U+7FB5(0); +U+7FB6(0);U+81BB(2,3);U+81BB(2,3) +U+7FB7(0);U+7FB7(0); +U+7FB8(0);U+7FB8(5); +U+7FB9(0);U+7FB9(5);U+7FAE(4) +U+7FBA(0);U+7FBA(0); +U+7FBB(0);U+7FBB(0); +U+7FBC(0);U+7FBC(5); +U+7FBD(0);U+7FBD(5); +U+7FBE(0);U+7FBE(0); +U+7FBF(0);U+7FBF(5); +U+7FC0(0);U+7FC0(0); +U+7FC1(0);U+7FC1(5); +U+7FC2(0);U+7FC2(0); +U+7FC3(0);U+7FC3(3); +U+7FC4(0);U+7FC5(2,3);U+7FC5(2,3),U+7FE8(2,3) +U+7FC5(0);U+7FC5(5);U+7FC4(2,3),U+7FE8(3) +U+7FC6(0);U+7FE0(3);U+7FE0(3) +U+7FC7(0);U+7FC7(0); +U+7FC8(0);U+7FC8(0); +U+7FC9(0);U+7FC9(0); +U+7FCA(0);U+7FCA(5); +U+7FCB(0);U+7FCB(0); +U+7FCC(0);U+7FCC(5); +U+7FCD(0);U+7FCD(0); +U+7FCE(0);U+7FCE(5); + +U+7FCF(0);U+7FCF(0); +U+7FD0(0);U+7FD0(0); +U+7FD1(0);U+7FD1(0); +U+7FD2(0);U+4E60(1,3);U+4E60(1,3) +U+7FD3(0);U+7FD3(0); +U+7FD4(0);U+7FD4(5); +U+7FD5(0);U+7FD5(5); +U+7FD7(0);U+7FD7(0); +U+7FD8(0);U+7FD8(1,3);U+7FF9(1,3) +U+7FD9(0);U+7FD9(4);U+7FFD(4) +U+7FDA(0);U+7FDA(1,3);U+7FEC(1,3) +U+7FDB(0);U+7FDB(0); +U+7FDC(0);U+7FDC(0); +U+7FDE(0);U+7FDE(0); +U+7FDF(0);U+7FDF(5); +U+7FE0(0);U+7FE0(5);U+7FC6(3) +U+7FE1(0);U+7FE1(5); +U+7FE2(0);U+7E9B(3);U+7E9B(3) +U+7FE3(0);U+7FE3(3); +U+7FE5(0);U+7FE5(5); +U+7FE6(0);U+7FE6(5); +U+7FE7(0);U+7FE7(0); +U+7FE8(0);U+7FC5(3);U+7FC5(3),U+7FC4(0,2,3) +U+7FE9(0);U+7FE9(5); +U+7FEA(0);U+7FEA(0); +U+7FEB(0);U+7FEB(3); +U+7FEC(0);U+7FDA(1,3);U+7FDA(1,3) +U+7FED(0);U+7FED(4);U+7FF5(4) +U+7FEE(0);U+7FEE(5); +U+7FEF(0);U+7FEF(0); +U+7FF0(0);U+7FF0(5);U+9DBE(3) +U+7FF1(0);U+7FF1(5);U+7FF6(4),U+7FFA(2,3) +U+7FF2(0);U+7FF2(0); +U+7FF3(0);U+7FF3(5); +U+7FF4(0);U+7FF4(0); +U+7FF5(0);U+7FED(4);U+7FED(4) +U+7FF6(0);U+7FF1(4);U+7FF1(4),U+7FFA(4) +U+7FF7(0);U+7FF7(0); +U+7FF8(0);U+7FF8(0); +U+7FF9(0);U+7FD8(1,3);U+7FD8(1,3) +U+7FFA(0);U+7FF1(2,3);U+7FF1(2,3),U+7FF6(4) +U+7FFB(0);U+7FFB(5);U+7E59(2,3),U+98DC(2,3) +U+7FFC(0);U+7FFC(5); +U+7FFD(0);U+7FD9(4);U+7FD9(4) +U+7FFE(0);U+7FFE(0); +U+7FFF(0);U+7FFF(0); +U+8000(0);U+8000(5);U+71FF(2,3),U+66DC(2,3,5) +U+8001(0);U+8001(5);U+8002(8,9) +U+8002(0);U+8002(0);U+8001(8,9) +U+8003(0);U+8003(5);U+6537(2,3) +U+8004(0);U+8004(5); +U+8005(0);U+8005(5); +U+8006(0);U+8006(5); +U+8007(0);U+8007(3);U+8008(3),U+8009(3) +U+8008(0);U+8007(3);U+8007(3),U+8009(3) +U+8009(0);U+8007(3);U+8007(3),U+8008(3) +U+800B(0);U+800B(5); +U+800C(0);U+800C(5); +U+800D(0);U+800D(5); +U+800E(0);U+800E(0); +U+800F(0);U+800F(3); +U+8010(0);U+8010(5); +U+8011(0);U+8011(0);U+7AEF(3) + +U+8012(0);U+8012(5); +U+8013(0);U+8013(0); +U+8014(0);U+8014(5); +U+8015(0);U+8015(5); +U+8016(0);U+8016(5); +U+8017(0);U+8017(5);U+79CF(3) +U+8018(0);U+8018(5);U+79D0(3) +U+8019(0);U+8019(5); +U+801A(0);U+801A(0); +U+801B(0);U+801B(0); +U+801C(0);U+801C(5); +U+801D(0);U+801D(0);U+521E(3) +U+801E(0);U+67B7(3);U+67B7(3) +U+801F(0);U+801F(0); +U+8020(0);U+8020(5); +U+8021(0);U+9504(4);U+92E4(2,3),U+9504(4) +U+8022(0);U+8022(1,3);U+802E(1,3) +U+8023(0);U+8023(0); +U+8024(0);U+501F(3);U+501F(3),U+85C9(3) +U+8025(0);U+8025(5); +U+8026(0);U+8026(5); +U+8027(0);U+8027(1,3);U+802C(1,3) +U+8028(0);U+8028(5); +U+8029(0);U+8029(5); +U+802A(0);U+802A(5); +U+802B(0);U+802B(0); +U+802C(0);U+8027(1,3);U+8027(1,3) +U+802D(0);U+802D(0); +U+802E(0);U+8022(1,3);U+8022(1,3) +U+8030(0);U+8030(3);U+6ACC(3) +U+8031(0);U+8031(5); +U+8032(0);U+8032(0); +U+8033(0);U+8033(5); +U+8034(0);U+8034(0); +U+8035(0);U+8035(5); +U+8036(0);U+8036(5); +U+8037(0);U+8037(5); +U+8038(0);U+8038(1,3);U+8073(1,3) +U+8039(0);U+8039(0); +U+803A(0);U+803A(0); +U+803B(0);U+803B(5);U+6065(2,3) +U+803D(0);U+803D(5);U+8EAD(2,3) +U+803E(0);U+803E(0); +U+803F(0);U+803F(5); +U+8041(0);U+8041(0); +U+8042(0);U+8042(1,3);U+8076(1,3) +U+8043(0);U+8043(5); +U+8044(0);U+8044(0); +U+8045(0);U+8045(0); +U+8046(0);U+8046(5); +U+8047(0);U+8047(0); +U+8048(0);U+8048(0); +U+8049(0);U+8049(0); +U+804A(0);U+804A(5); +U+804B(0);U+804B(1,3);U+807E(1,3) +U+804C(0);U+804C(1,3);U+8077(1,3) +U+804D(0);U+804D(1,3);U+8079(1,3) +U+804E(0);U+804E(0); +U+804F(0);U+804F(0); +U+8050(0);U+8050(0); +U+8051(0);U+8051(0); +U+8052(0);U+8052(5); +U+8053(0);U+8053(0); + +U+8054(0);U+8054(1,3);U+8068(4),U+806B(3),U+806E(3),U+806F(1,3) +U+8055(0);U+8055(0); +U+8056(0);U+5723(1,3);U+5723(1,3),U+57A9(3),U+580A(1,3) +U+8057(0);U+8057(0); +U+8058(0);U+8058(5); +U+8059(0);U+8059(0); +U+805A(0);U+805A(5); +U+805B(0);U+805B(0); +U+805C(0);U+805C(0); +U+805D(0);U+9998(4);U+9998(4) +U+805E(0);U+95FB(1,3);U+95FB(1,3) +U+805F(0);U+5A7F(2,3);U+5A7F(2,3) +U+8060(0);U+8060(0); +U+8061(0);U+806A(3);U+806A(3),U+8070(3) +U+8062(0);U+8062(0); +U+8063(0);U+8063(0); +U+8064(0);U+8064(0); +U+8065(0);U+8065(0); +U+8067(0);U+8067(0); +U+8068(0);U+8054(4);U+8054(4),U+806F(4),U+806B(3,4),U+806E(3,4) +U+8069(0);U+8069(1,3);U+8075(1,3) +U+806A(0);U+806A(1,3);U+8061(3),U+8070(1,3,4) +U+806B(0);U+8054(3);U+8054(3),U+806F(3),U+8068(3,4),U+806E(3) +U+806C(0);U+806C(0); +U+806D(0);U+806D(0); +U+806E(0);U+8054(3);U+8054(3),U+806F(3),U+8068(3,4),U+806B(3) +U+806F(0);U+8054(1,3);U+8054(1,3),U+8068(4),U+806B(3),U+806E(3) +U+8070(0);U+806A(1,3);U+8061(3),U+806A(1,3) +U+8071(0);U+8071(5); +U+8072(0);U+58F0(1,3);U+58F0(1,3) +U+8073(0);U+8038(1,3);U+8038(1,3) +U+8074(0);U+542C(3);U+542C(3),U+807D(3),U+807C(3) +U+8075(0);U+8069(1,3);U+8069(1,3) +U+8076(0);U+8042(1,3);U+8042(1,3) +U+8077(0);U+804C(1,3);U+804C(1,3) +U+8078(0);U+8078(0); +U+8079(0);U+804D(1,3);U+804D(1,3) +U+807A(0);U+807A(0); +U+807B(0);U+807B(0); +U+807C(0);U+542C(3);U+542C(3),U+807D(3),U+8074(3) +U+807D(0);U+542C(1,3);U+542C(1,3),U+8074(3),U+807C(3) +U+807E(0);U+804B(1,3);U+804B(1,3) +U+807F(0);U+807F(5);U+8080(8,9) +U+8080(0);U+8080(5);U+807F(8,9) +U+8081(0);U+8081(0); +U+8082(0);U+8082(0); +U+8083(0);U+8083(1,3);U+7C9B(3),U+8085(1,3) +U+8084(0);U+8084(5); +U+8085(0);U+8083(1,3);U+7C9B(3),U+8083(1,3) +U+8086(0);U+8086(5);U+56DB(3) +U+8087(0);U+8087(5); +U+8089(0);U+8089(5);U+5B8D(4) +U+808A(0);U+81C6(3);U+81C6(3) +U+808B(0);U+808B(5); +U+808C(0);U+808C(5); +U+808D(0);U+808D(0); +U+808F(0);U+808F(0); +U+8090(0);U+80F3(2);U+80F3(2) +U+8091(0);U+8091(0); +U+8092(0);U+8092(0); +U+8093(0);U+8093(5); +U+8095(0);U+97E7(3);U+97E7(3),U+976D(3,4),U+97CC(1,3,4) +U+8096(0);U+8096(5); + +U+8097(0);U+8097(0); +U+8098(0);U+8098(5); +U+8099(0);U+8099(0); +U+809A(0);U+809A(5); +U+809B(0);U+809B(5);U+7598(2,3) +U+809C(0);U+809C(5); +U+809D(0);U+809D(5); +U+809E(0);U+809E(0); +U+809F(0);U+809F(5); +U+80A0(0);U+80A0(1,3);U+8178(1,3),U+8193(4) +U+80A1(0);U+80A1(5); +U+80A2(0);U+80A2(5);U+80D1(3) +U+80A3(0);U+51FD(3);U+51FD(3),U+51FE(3) +U+80A4(0);U+80A4(1,3);U+819A(1,3) +U+80A5(0);U+80A5(5); +U+80A9(0);U+80A9(5); +U+80AA(0);U+80AA(5); +U+80AB(0);U+80AB(5); +U+80AD(0);U+80AD(5); +U+80AE(0);U+80AE(1,3);U+9AAF(1,3,4) +U+80AF(0);U+80AF(5);U+80BB(3) +U+80B0(0);U+80B0(0); +U+80B1(0);U+80B1(5); +U+80B2(0);U+80B2(5); +U+80B4(0);U+80B4(5);U+991A(2,3) +U+80B5(0);U+80B5(0); +U+80B6(0);U+80B6(0); +U+80B7(0);U+80B7(5); +U+80B8(0);U+80B8(3); +U+80BA(0);U+80BA(5);U+80C7(3) +U+80BB(0);U+80AF(3);U+80AF(3) +U+80BC(0);U+80BC(5); +U+80BD(0);U+80BD(5); +U+80BE(0);U+80BE(1,3);U+814E(1,3) +U+80BF(0);U+80BF(1,3);U+816B(1,3) +U+80C0(0);U+80C0(1,3);U+8139(1,3) +U+80C1(0);U+80C1(1,3);U+8105(1,3),U+8107(4) +U+80C2(0);U+80C2(5); +U+80C3(0);U+80C3(5); +U+80C4(0);U+80C4(5);U+5191(4) +U+80C5(0);U+80C5(0); +U+80C6(0);U+80C6(1,3);U+81BD(1,3) +U+80C7(0);U+80BA(3);U+80BA(3) +U+80C8(0);U+80C8(0); +U+80C9(0);U+80C9(0); +U+80CA(0);U+6710(4);U+6710(4) +U+80CB(0);U+80CB(0); +U+80CC(0);U+80CC(5);U+505D(3),U+63F9(2,3) +U+80CD(0);U+80CD(5); +U+80CE(0);U+80CE(5); +U+80CF(0);U+80CF(0); +U+80D0(0);U+670F(4);U+670F(4) +U+80D1(0);U+80A2(3);U+80A2(3) +U+80D2(0);U+80D2(0); +U+80D3(0);U+80D3(0); +U+80D4(0);U+80D4(0); +U+80D5(0);U+80D5(0); +U+80D6(0);U+80D6(5); +U+80D7(0);U+80D7(5); +U+80D8(0);U+80D8(0); +U+80D9(0);U+80D9(5); +U+80DA(0);U+80DA(5); +U+80DB(0);U+80DB(5); + +U+80DC(0);U+80DC(1,3);U+52DD(1,3,4) +U+80DD(0);U+80DD(5); +U+80DE(0);U+80DE(5); +U+80E0(0);U+80E0(3); +U+80E1(0);U+80E1(1,3);U+885A(2),U+9B0D(1,3,4) +U+80E2(0);U+80E2(0); +U+80E3(0);U+80E3(3); +U+80E4(0);U+80E4(5); +U+80E5(0);U+80E5(5);U+7E03(3) +U+80E6(0);U+80E6(0); +U+80E7(0);U+80E7(1,3);U+6727(1,3) +U+80E8(0);U+80E8(1,3);U+8156(1,3) +U+80E9(0);U+80E9(5); +U+80EA(0);U+80EA(1,3);U+81DA(1,3) +U+80EB(0);U+80EB(1,3);U+811B(1,3) +U+80EC(0);U+80EC(5); +U+80ED(0);U+80ED(5);U+81D9(2,3) +U+80EE(0);U+80EE(3); +U+80EF(0);U+80EF(5);U+9ABB(3) +U+80F0(0);U+80F0(5); +U+80F1(0);U+80F1(5); +U+80F2(0);U+80F2(5); +U+80F3(0);U+80F3(5);U+8090(2) +U+80F4(0);U+80F4(5); +U+80F5(0);U+80F5(3); +U+80F6(0);U+80F6(1,3);U+81A0(1,3) +U+80F7(0);U+80F8(2,3);U+80F8(2,3) +U+80F8(0);U+80F8(5);U+80F7(2,3) +U+80F9(0);U+80F9(3); +U+80FA(0);U+80FA(5); +U+80FB(0);U+80FB(0); +U+80FC(0);U+80FC(5);U+8141(3) +U+80FD(0);U+80FD(5); +U+80FE(0);U+80FE(0); +U+80FF(0);U+80FF(0); +U+8100(0);U+8100(0); +U+8101(0);U+6713(4);U+6713(4) +U+8102(0);U+8102(5); +U+8105(0);U+80C1(1,3);U+80C1(1,3),U+8107(2,3) +U+8106(0);U+8106(5);U+81AC(3) +U+8107(0);U+80C1(4);U+80C1(4),U+8105(2,3) +U+8108(0);U+8109(2,3,4);U+8109(2,3,4) +U+8109(0);U+8109(5);U+8108(2,3,4) +U+810A(0);U+810A(5); +U+810B(0);U+810B(0); +U+810C(0);U+810C(0); +U+810D(0);U+810D(1,3);U+81BE(1,3) +U+810E(0);U+810E(5); +U+810F(0);U+810F(1,3);U+81DF(1,3),U+9AD2(1,3) +U+8110(0);U+8110(1,3);U+81CD(1,3) +U+8111(0);U+8111(1,3);U+8166(1,3) +U+8112(0);U+8112(5); +U+8113(0);U+8113(1,3);U+81BF(1,3) +U+8114(0);U+8114(1,3);U+81E0(1,3) +U+8115(0);U+8115(0); +U+8116(0);U+8116(5); +U+8118(0);U+8118(5); +U+8119(0);U+8119(0); +U+811A(0);U+811A(5);U+8173(2,3) +U+811B(0);U+80EB(1,3);U+80EB(1,3) +U+811C(0);U+811C(0); +U+811D(0);U+811D(0); +U+811E(0);U+811E(5); + +U+811F(0);U+811F(0); +U+8120(0);U+8120(0); +U+8121(0);U+8121(3); +U+8122(0);U+8122(3); +U+8123(0);U+5507(3);U+5507(3) +U+8124(0);U+8124(0); +U+8125(0);U+8125(0); +U+8126(0);U+8126(0); +U+8127(0);U+6718(4);U+6718(4) +U+8128(0);U+8128(0); +U+8129(0);U+8129(3);U+4FEE(2,3) +U+812A(0);U+812A(0); +U+812B(0);U+8131(4);U+8131(4) +U+812C(0);U+812C(5); +U+812D(0);U+812D(0); +U+812E(0);U+812E(0); +U+812F(0);U+812F(5); +U+8130(0);U+8130(0); +U+8131(0);U+8131(5);U+812B(4) +U+8132(0);U+8132(5); +U+8136(0);U+8136(1,3);U+8161(1,3) +U+8137(0);U+8137(0); +U+8138(0);U+8138(1,3);U+81C9(1,3) +U+8139(0);U+80C0(1,3);U+80C0(1,3) +U+813A(0);U+813A(0); +U+813B(0);U+813B(0); +U+813C(0);U+813C(0); +U+813D(0);U+813D(0); +U+813E(0);U+813E(5); +U+813F(0);U+813F(0); +U+8140(0);U+8140(0); +U+8141(0);U+80FC(3);U+80FC(3) +U+8142(0);U+8142(0); +U+8143(0);U+8143(0); +U+8144(0);U+8144(0); +U+8145(0);U+8145(0); +U+8146(0);U+8146(5);U+500E(3) +U+8147(0);U+8147(0); +U+8148(0);U+8148(5); +U+8149(0);U+8149(0); +U+814A(0);U+814A(1,3);U+81C8(4),U+81D8(1,3) +U+814B(0);U+814B(5); +U+814C(0);U+814C(5);U+9183(2) +U+814D(0);U+814D(0); +U+814E(0);U+80BE(1,3);U+80BE(1,3) +U+814F(0);U+814F(0); +U+8150(0);U+8150(5); +U+8151(0);U+8151(5); +U+8152(0);U+8152(3); +U+8153(0);U+8153(5); +U+8154(0);U+8154(5); +U+8155(0);U+8155(5); +U+8156(0);U+80E8(1,3);U+80E8(1,3) +U+8157(0);U+8157(0); +U+8158(0);U+8158(1,3);U+8195(1,3) +U+8159(0);U+8159(5); +U+815A(0);U+815A(5); +U+815B(0);U+815B(0); +U+815C(0);U+815C(0); +U+815D(0);U+815D(3); +U+815E(0);U+815E(3); +U+8160(0);U+8160(5);U+50B6(4) +U+8161(0);U+8136(1,3);U+8136(1,3) + +U+8162(0);U+8162(0); +U+8163(0);U+8163(0); +U+8164(0);U+8164(0); +U+8165(0);U+8165(5); +U+8166(0);U+8111(1,3);U+8111(1,3) +U+8167(0);U+8167(5); +U+8168(0);U+8168(0); +U+8169(0);U+8169(5); +U+816A(0);U+816A(0); +U+816B(0);U+80BF(1,3);U+80BF(1,3) +U+816C(0);U+816C(0); +U+816D(0);U+816D(5);U+9F76(2,3) +U+816E(0);U+816E(5); +U+816F(0);U+816F(3); +U+8170(0);U+8170(5); +U+8171(0);U+8171(5); +U+8172(0);U+8172(0); +U+8173(0);U+811A(2,3);U+811A(2,3) +U+8174(0);U+8174(5); +U+8175(0);U+8175(0); +U+8176(0);U+8176(3); +U+8177(0);U+8177(0); +U+8178(0);U+80A0(1,3);U+80A0(1,3),U+8193(2,3) +U+8179(0);U+8179(5); +U+817A(0);U+817A(5); +U+817B(0);U+817B(1,3);U+81A9(1,3) +U+817C(0);U+817C(5); +U+817D(0);U+817D(5);U+8183(4) +U+817E(0);U+817E(1,3);U+9A30(1,3) +U+817F(0);U+817F(5); +U+8180(0);U+8180(5); +U+8181(0);U+8181(0); +U+8182(0);U+8182(5); +U+8183(0);U+817D(4);U+817D(4) +U+8185(0);U+8185(0); +U+8186(0);U+55C9(3);U+55C9(3) +U+8187(0);U+8187(0); +U+8188(0);U+8188(5); +U+8189(0);U+8189(0); +U+818A(0);U+818A(5); +U+818B(0);U+818B(0); +U+818C(0);U+7620(3);U+7620(3) +U+818D(0);U+818D(3); +U+818E(0);U+818E(0); +U+818F(0);U+818F(5); +U+8191(0);U+8191(1,3);U+81CF(1,3),U+9AD5(1,3),U+9ACC(1,3) +U+8192(0);U+8192(0); +U+8193(0);U+80A0(4);U+80A0(4),U+8178(2,3) +U+8194(0);U+8194(0); +U+8195(0);U+8158(1,3);U+8158(1,3) +U+8197(0);U+8197(0); +U+8198(0);U+8198(5);U+81D5(2,3) +U+8199(0);U+8199(0); +U+819A(0);U+80A4(1,3);U+80A4(1,3) +U+819B(0);U+819B(5); +U+819C(0);U+819C(5); +U+819D(0);U+819D(5); +U+819E(0);U+43DD(1,3);U+43DD(1,3) +U+819F(0);U+819F(0); +U+81A0(0);U+80F6(1,3);U+80F6(1,3) +U+81A1(0);U+81A1(0); +U+81A2(0);U+81A2(0); +U+81A3(0);U+81A3(5); + +U+81A4(0);U+81A4(0); +U+81A5(0);U+81A5(0); +U+81A6(0);U+81A6(5); +U+81A7(0);U+6723(4);U+6723(4) +U+81A8(0);U+81A8(5); +U+81A9(0);U+817B(1,3);U+817B(1,3) +U+81AA(0);U+81AA(5); +U+81AB(0);U+81AB(0); +U+81AC(0);U+8106(3);U+8106(3) +U+81AD(0);U+81AD(0); +U+81AE(0);U+81AE(0); +U+81AF(0);U+81AF(0); +U+81B0(0);U+81B0(0); +U+81B1(0);U+81B1(0); +U+81B2(0);U+81B2(0); +U+81B3(0);U+81B3(5); +U+81B4(0);U+81B4(0); +U+81B5(0);U+81B5(4); +U+81B6(0);U+81B6(0); +U+81B7(0);U+81B7(0); +U+81B8(0);U+9AD3(3);U+9AD3(3),U+9AC4(3) +U+81B9(0);U+81B9(0); +U+81BA(0);U+81BA(5); +U+81BB(0);U+81BB(5);U+7FB6(2,3) +U+81BC(0);U+81BC(0); +U+81BD(0);U+80C6(1,3);U+80C6(1,3) +U+81BE(0);U+810D(1,3);U+810D(1,3) +U+81BF(0);U+8113(1,3);U+8113(1,3) +U+81C0(0);U+81C0(5); +U+81C1(0);U+81C1(5); +U+81C2(0);U+81C2(5); +U+81C3(0);U+81C3(5); +U+81C4(0);U+81C4(0); +U+81C5(0);U+81C5(0); +U+81C6(0);U+81C6(5);U+808A(3) +U+81C7(0);U+81C7(0); +U+81C8(0);U+814A(4);U+814A(4),U+81D8(2,3) +U+81C9(0);U+8138(1,3);U+8138(1,3) +U+81CA(0);U+81CA(5); +U+81CC(0);U+81CC(5); +U+81CD(0);U+8110(1,3);U+8110(1,3) +U+81CE(0);U+81CE(3); +U+81CF(0);U+8191(1,3);U+8191(1,3),U+9AD5(3),U+9ACC(1,3) +U+81D0(0);U+81D0(0); +U+81D1(0);U+81D1(0); +U+81D2(0);U+81D2(0); +U+81D4(0);U+81D4(0); +U+81D5(0);U+8198(2,3);U+8198(2,3) +U+81D6(0);U+81D6(0); +U+81D7(0);U+81D7(3); +U+81D8(0);U+814A(1,3);U+814A(1,3),U+81C8(2,3) +U+81D9(0);U+80ED(2,3);U+80ED(2,3) +U+81DA(0);U+80EA(1,3);U+80EA(1,3) +U+81DB(0);U+81DB(0); +U+81DC(0);U+81DC(1,3);U+81E2(1,3) +U+81DD(0);U+88F8(2,3);U+88F8(2,3) +U+81DE(0);U+81DE(3); +U+81DF(0);U+810F(1,3);U+810F(1,3),U+9AD2(1,3) +U+81E0(0);U+8114(1,3);U+8114(1,3) +U+81E1(0);U+81E1(0); +U+81E2(0);U+81DC(1,3);U+81DC(1,3) +U+81E3(0);U+81E3(5); +U+81E5(0);U+5367(3,4);U+5367(3,4) + +U+81E6(0);U+81E6(0); +U+81E7(0);U+81E7(5); +U+81E8(0);U+4E34(1,3);U+4E34(1,3) +U+81E9(0);U+81E9(0); +U+81EA(0);U+81EA(5); +U+81EB(0);U+81EB(0); +U+81EC(0);U+81EC(5); +U+81ED(0);U+81ED(5);U+6BA0(3) +U+81EE(0);U+66A8(4);U+66A8(4),U+66C1(4),U+8507(4) +U+81F1(0);U+81F1(0); +U+81F2(0);U+81F2(0); +U+81F3(0);U+81F3(5); +U+81F4(0);U+81F4(1,3);U+7DFB(1,3,4) +U+81F5(0);U+81F5(0); +U+81F6(0);U+81F6(0); +U+81F7(0);U+81F7(0); +U+81F8(0);U+81F8(0); +U+81F9(0);U+81F9(0); +U+81FA(0);U+53F0(1,3);U+53F0(1,3),U+6AAF(1,3,4),U+7C49(1,3,4),U+98B1(1,3,4) +U+81FB(0);U+81FB(5); +U+81FC(0);U+81FC(5); +U+81FD(0);U+81FD(0); +U+81FE(0);U+81FE(5); +U+81FF(0);U+9538(4);U+9538(4),U+9364(1,3,4) +U+8200(0);U+8200(5);U+62AD(4) +U+8201(0);U+8201(5); +U+8202(0);U+8202(5); +U+8203(0);U+8204(3,4);U+8204(3,4) +U+8204(0);U+8204(5);U+8203(3,4) +U+8205(0);U+8205(5); +U+8206(0);U+8206(1,3);U+8F3F(1,3),U+8F5D(3) +U+8207(0);U+4E0E(1,3);U+4E0E(1,3) +U+8208(0);U+5174(1,3);U+5174(1,3) +U+8209(0);U+4E3E(1,3);U+4E3E(1,3),U+6319(4),U+64E7(2,3) +U+820A(0);U+65E7(1,3);U+65E7(1,3) +U+820B(0);U+820B(4); +U+820C(0);U+820C(5); +U+820D(0);U+820D(1,3);U+6368(1,3,4),U+820E(4) +U+820E(0);U+820D(4);U+820D(4),U+6368(0,1,3,4) +U+820F(0);U+820F(0); +U+8210(0);U+8210(5); +U+8211(0);U+8211(4); +U+8212(0);U+8212(5); +U+8214(0);U+8214(5); +U+8215(0);U+8215(0); +U+8216(0);U+94FA(4);U+92EA(2,3),U+94FA(4) +U+8218(0);U+9986(4);U+9928(2,3),U+9986(4) +U+8219(0);U+8219(0); +U+821A(0);U+821A(0); +U+821B(0);U+821B(5); +U+821C(0);U+821C(5); +U+821D(0);U+821D(4); +U+821E(0);U+821E(5); +U+821F(0);U+821F(5); +U+8220(0);U+8220(0); +U+8221(0);U+8221(5);U+8239(3),U+8229(2,3) +U+8222(0);U+8222(5); +U+8223(0);U+8223(4);U+6AA5(3),U+8264(4) +U+8225(0);U+8225(0); +U+8226(0);U+8226(0); +U+8227(0);U+8227(4); +U+8228(0);U+8228(5); +U+8229(0);U+8239(2,3);U+8239(2,3),U+8221(2,3,5) + +U+822A(0);U+822A(5);U+6841(3) +U+822B(0);U+822B(5); +U+822C(0);U+822C(5); +U+822D(0);U+822D(5); +U+822F(0);U+822F(5); +U+8230(0);U+8230(1,3);U+8266(1,3) +U+8231(0);U+8231(1,3);U+8259(1,3) +U+8232(0);U+8232(0); +U+8233(0);U+8233(5); +U+8234(0);U+8234(5); +U+8235(0);U+8235(5);U+67C1(3) +U+8236(0);U+8236(5);U+824A(3) +U+8237(0);U+8237(5); +U+8238(0);U+8238(5); +U+8239(0);U+8239(5);U+8221(3),U+8229(2,3) +U+823A(0);U+823A(0); +U+823B(0);U+823B(1,3);U+826B(1,3) +U+823C(0);U+823C(0); +U+823D(0);U+823D(0); +U+823E(0);U+823E(5); +U+823F(0);U+823F(0); +U+8240(0);U+8240(0); +U+8242(0);U+8242(0); +U+8243(0);U+8243(0); +U+8244(0);U+8244(5); +U+8245(0);U+8245(0); +U+8246(0);U+8246(0); +U+8247(0);U+8247(5); +U+8248(0);U+8248(0); +U+8249(0);U+8249(5); +U+824A(0);U+8236(3);U+8236(3) +U+824B(0);U+824B(5); +U+824C(0);U+824C(0); +U+824D(0);U+824D(0); +U+824E(0);U+824E(3); +U+824F(0);U+824F(5); +U+8250(0);U+5C4A(3);U+5C4A(3),U+5C46(0,2,3) +U+8251(0);U+8251(0); +U+8252(0);U+8252(0); +U+8253(0);U+8253(0); +U+8254(0);U+8254(0); +U+8255(0);U+8255(0); +U+8256(0);U+8256(0); +U+8257(0);U+8257(3); +U+8258(0);U+8258(5); +U+8259(0);U+8231(1,3);U+8231(1,3) +U+825A(0);U+825A(5); +U+825B(0);U+825B(0); +U+825C(0);U+825C(0); +U+825D(0);U+825D(0); +U+825E(0);U+825E(0); +U+825F(0);U+825F(5); +U+8260(0);U+8260(0); +U+8261(0);U+8261(0); +U+8263(0);U+6A79(2,3);U+6A79(2,3),U+6AD3(2,3),U+826A(4),U+6A10(0,2,3) +U+8264(0);U+8223(4);U+8223(4),U+6AA5(0,3,4) +U+8266(0);U+8230(1,3);U+8230(1,3) +U+8267(0);U+8267(0); +U+8268(0);U+8268(5); +U+8269(0);U+8269(0); +U+826A(0);U+6A79(2,3);U+6A79(2,3),U+6AD3(2,3),U+8263(4),U+6A10(0,2,3) +U+826B(0);U+823B(1,3);U+823B(1,3) +U+826C(0);U+826C(0); + +U+826D(0);U+826D(0); +U+826E(0);U+826E(5); +U+826F(0);U+826F(5); +U+8270(0);U+8270(1,3);U+8271(1,3) +U+8271(0);U+8270(1,3);U+8270(1,3) +U+8272(0);U+8272(5); +U+8273(0);U+8273(1,3,4);U+8276(4),U+8277(1,3),U+8C54(4) +U+8274(0);U+8274(5); +U+8275(0);U+8275(0); +U+8276(0);U+8273(4);U+8273(4),U+8277(8,9),U+8C54(4) +U+8277(0);U+8273(1,3);U+8273(1,3),U+8276(8,9),U+8C54(2,3) +U+8278(0);U+8349(2,3);U+8349(2,3),U+9A32(2,3,4) +U+8279(0);U+8279(5); +U+827A(0);U+827A(1,3);U+84FA(3),U+517F(4),U+85DD(1,3) +U+827B(0);U+827B(0); +U+827C(0);U+827C(0); +U+827D(0);U+827D(5); +U+827E(0);U+827E(5); +U+827F(0);U+827F(5); +U+8280(0);U+82D5(3);U+82D5(3) +U+8281(0);U+8281(0); +U+8282(0);U+8282(1,3);U+7BC0(1,3) +U+8283(0);U+8283(3); +U+8284(0);U+8284(5); +U+8285(0);U+8285(0); +U+8286(0);U+8286(0); +U+8287(0);U+8287(0); +U+8288(0);U+8288(5);U+7F8B(4) +U+8289(0);U+8289(0); +U+828A(0);U+828A(5); +U+828B(0);U+828B(5); +U+828D(0);U+828D(5); +U+828E(0);U+828E(5); +U+828F(0);U+828F(5); +U+8290(0);U+8290(3); +U+8291(0);U+8291(5); +U+8292(0);U+8292(5);U+7B00(3) +U+8293(0);U+8293(0); +U+8294(0);U+8294(0); +U+8295(0);U+8295(0); +U+8296(0);U+8296(0); +U+8297(0);U+8297(1,3);U+858C(1,3) +U+8298(0);U+8298(5); +U+8299(0);U+8299(5); +U+829A(0);U+829A(0); +U+829B(0);U+829B(3); +U+829C(0);U+829C(1,3);U+856A(1,3) +U+829D(0);U+829D(5); +U+829E(0);U+829E(0); +U+829F(0);U+829F(5); +U+82A0(0);U+82A0(0); +U+82A1(0);U+82A1(5); +U+82A2(0);U+82A2(0); +U+82A3(0);U+82A3(0); +U+82A4(0);U+82A4(5); +U+82A5(0);U+82A5(5); +U+82A6(0);U+82A6(1,3);U+8606(1,3) +U+82A7(0);U+82A7(3); +U+82A8(0);U+82A8(5); +U+82A9(0);U+82A9(5); +U+82AA(0);U+82AA(5); +U+82AB(0);U+82AB(5); +U+82AC(0);U+82AC(5); + +U+82AD(0);U+82AD(5); +U+82AE(0);U+82AE(5); +U+82AF(0);U+82AF(5); +U+82B0(0);U+82B0(5); +U+82B1(0);U+82B1(5);U+8624(2,3) +U+82B3(0);U+82B3(5); +U+82B4(0);U+82B4(5); +U+82B5(0);U+82B5(0); +U+82B6(0);U+82DF(3);U+82DF(3) +U+82B7(0);U+82B7(5); +U+82B8(0);U+82B8(1,3);U+8553(1,3) +U+82B9(0);U+82B9(5); +U+82BA(0);U+82BA(0); +U+82BB(0);U+520D(1,3);U+520D(1,3) +U+82BC(0);U+82BC(0); +U+82BD(0);U+82BD(5); +U+82BE(0);U+82BE(5); +U+82BF(0);U+82BF(4); +U+82C0(0);U+82C0(0); +U+82C1(0);U+82C1(1,3);U+84EF(1,3) +U+82C2(0);U+82C2(0); +U+82C3(0);U+82C3(0); +U+82C4(0);U+82C4(5); +U+82C5(0);U+5208(3);U+5208(3) +U+82C6(0);U+82C6(0); +U+82C7(0);U+82C7(1,3);U+8466(1,3) +U+82C8(0);U+82C8(1,3);U+85F6(1,3) +U+82C9(0);U+82C9(0); +U+82CA(0);U+82CA(5); +U+82CB(0);U+82CB(1,3);U+83A7(1,3) +U+82CC(0);U+82CC(4);U+8407(4) +U+82CD(0);U+82CD(1,3);U+84BC(1,3) +U+82CE(0);U+82CE(5);U+82E7(4) +U+82CF(0);U+82CF(1,3);U+56CC(1,3),U+7526(4),U+8607(1,3),U+8613(4) +U+82D0(0);U+82D0(0); +U+82D1(0);U+82D1(5); +U+82D2(0);U+82D2(5); +U+82D3(0);U+82D3(5); +U+82D4(0);U+82D4(5); +U+82D5(0);U+82D5(5);U+8280(3) +U+82D6(0);U+82D6(0); +U+82D7(0);U+82D7(5); +U+82D8(0);U+82D8(5); +U+82D9(0);U+82D9(0); +U+82DA(0);U+82DA(0); +U+82DB(0);U+82DB(5); +U+82DC(0);U+82DC(5); +U+82DD(0);U+82DD(0); +U+82DE(0);U+82DE(5); +U+82DF(0);U+82DF(5);U+82B6(3) +U+82E0(0);U+82E0(5); +U+82E1(0);U+82E1(5); +U+82E3(0);U+82E3(5); +U+82E4(0);U+82E4(5); +U+82E5(0);U+82E5(5); +U+82E6(0);U+82E6(5);U+7614(3) +U+82E7(0);U+82CE(4);U+82CE(4) +U+82E8(0);U+82E8(0); +U+82E9(0);U+82E9(0); +U+82EA(0);U+82EA(0); +U+82EB(0);U+82EB(5); +U+82EC(0);U+82EC(0); +U+82ED(0);U+82ED(0); + +U+82EE(0);U+82EE(0); +U+82EF(0);U+82EF(5); +U+82F0(0);U+82F0(0); +U+82F1(0);U+82F1(5);U+5040(3) +U+82F2(0);U+82F2(0); +U+82F3(0);U+82F3(0); +U+82F4(0);U+82F4(5); +U+82F5(0);U+82F5(0); +U+82F6(0);U+82F6(4); +U+82F7(0);U+82F7(5); +U+82F8(0);U+82F8(0); +U+82F9(0);U+82F9(1,3);U+860B(1,3) +U+82FA(0);U+82FA(0); +U+82FB(0);U+82FB(5); +U+82FD(0);U+82FD(0);U+83F0(3),U+83C7(3,4) +U+82FE(0);U+82FE(3); +U+82FF(0);U+83CB(3);U+83CB(3) +U+8300(0);U+8300(0); +U+8301(0);U+8301(5); +U+8302(0);U+8302(5); +U+8303(0);U+8303(1,3);U+7BC4(1,3,4) +U+8304(0);U+8304(5); +U+8305(0);U+8305(5);U+8306(4) +U+8306(0);U+8306(5);U+8305(4) +U+8307(0);U+8307(5); +U+8308(0);U+8308(5); +U+8309(0);U+8309(5); +U+830B(0);U+830B(0); +U+830C(0);U+830C(5); +U+830D(0);U+830D(0); +U+830E(0);U+830E(1,3);U+8396(1,3) +U+830F(0);U+830F(1,3);U+8622(1,3) +U+8311(0);U+8311(1,3);U+8526(1,3) +U+8312(0);U+8312(0); +U+8313(0);U+8313(0); +U+8314(0);U+8314(1,3);U+584B(1,3) +U+8315(0);U+8315(1,3);U+60F8(4),U+7162(1,3),U+712D(1,3,4) +U+8316(0);U+8316(0); +U+8317(0);U+8317(5); +U+8318(0);U+8354(2,3);U+8354(2,3) +U+8319(0);U+8319(0); +U+831A(0);U+831A(5); +U+831B(0);U+831B(5); +U+831C(0);U+831C(5); +U+831D(0);U+831D(0); +U+831E(0);U+831E(0); +U+831F(0);U+831F(0); +U+8320(0);U+8320(0); +U+8321(0);U+8321(0); +U+8322(0);U+8322(0); +U+8323(0);U+8323(0); +U+8324(0);U+8324(0); +U+8325(0);U+8325(0); +U+8326(0);U+8326(0); +U+8327(0);U+8327(1,3);U+7E6D(1,3) +U+8328(0);U+8328(5); +U+8329(0);U+8329(0); +U+832A(0);U+832A(0); +U+832B(0);U+832B(5);U+6C52(3) +U+832C(0);U+832C(5); +U+832D(0);U+832D(5); +U+832E(0);U+832E(0); +U+832F(0);U+832F(5); + +U+8331(0);U+8331(5); +U+8332(0);U+5179(3,4);U+5179(3,4),U+7386(3) +U+8333(0);U+8333(5); +U+8334(0);U+8334(5); +U+8335(0);U+8335(5); +U+8336(0);U+8336(5); +U+8337(0);U+8337(4); +U+8338(0);U+8338(5); +U+8339(0);U+8339(5); +U+833A(0);U+833A(5); +U+833B(0);U+83BD(4);U+83BD(4) +U+833C(0);U+833C(5); +U+833D(0);U+833D(0); +U+833E(0);U+833E(0); +U+833F(0);U+833F(0); +U+8340(0);U+8340(5); +U+8341(0);U+8341(0); +U+8342(0);U+8342(3); +U+8343(0);U+8343(5); +U+8344(0);U+8344(0); +U+8345(0);U+7B54(4);U+7B54(4),U+7563(0,3,4) +U+8346(0);U+8346(5);U+834A(4) +U+8347(0);U+8347(5);U+8395(3) +U+8348(0);U+8348(0); +U+8349(0);U+8349(5);U+8278(2,3),U+9A32(4) +U+834A(0);U+8346(4);U+8346(4) +U+834B(0);U+834B(0); +U+834C(0);U+834C(0); +U+834D(0);U+834D(0); +U+834E(0);U+834E(3); +U+834F(0);U+834F(5); +U+8350(0);U+8350(1,3);U+85A6(1,3) +U+8351(0);U+8351(5); +U+8352(0);U+8352(5); +U+8353(0);U+8353(0); +U+8354(0);U+8354(5);U+8318(2,3) +U+8356(0);U+8356(0); +U+8357(0);U+8357(0); +U+8358(0);U+5E84(4);U+5E84(4),U+838A(4) +U+8359(0);U+8359(4);U+8598(4) +U+835A(0);U+835A(1,3);U+83A2(1,3) +U+835B(0);U+835B(1,3);U+8558(1,3) +U+835C(0);U+835C(1,3);U+84FD(1,3) +U+835D(0);U+835D(4);U+8434(4) +U+835E(0);U+835E(1,3);U+854E(1,3) +U+835F(0);U+835F(1,3);U+8588(1,3) +U+8360(0);U+8360(1,3);U+8415(3),U+85BA(1,3) +U+8361(0);U+8361(1,3);U+6F52(3),U+76EA(4),U+8569(1,3),U+862F(3) +U+8362(0);U+8362(0); +U+8363(0);U+8363(1,3);U+6804(7),U+69AE(1,3) +U+8364(0);U+8364(1,3);U+8477(1,3),U+8512(3) +U+8365(0);U+8365(1,3);U+6ECE(1,3) +U+8366(0);U+8366(1,3);U+7296(1,3) +U+8367(0);U+8367(1,3);U+7192(1,3) +U+8368(0);U+8368(1,3);U+8541(1,3) +U+8369(0);U+8369(1,3);U+85CE(1,3) +U+836A(0);U+836A(1,3);U+84C0(1,3) +U+836B(0);U+836B(1,3);U+5ED5(4),U+852D(1,3) +U+836C(0);U+836C(1,3);U+8552(1,3) +U+836D(0);U+836D(1,3);U+8452(1,3) +U+836E(0);U+836E(1,3);U+8464(1,3) +U+836F(0);U+836F(1,3,4);U+846F(4),U+85AC(4),U+85E5(1,3) +U+8370(0);U+8370(0); + +U+8371(0);U+8371(0); +U+8372(0);U+8372(0); +U+8373(0);U+8C46(2);U+8C46(2),U+68AA(0,2,3) +U+8374(0);U+8374(0); +U+8375(0);U+8375(0); +U+8376(0);U+8376(3); +U+8377(0);U+8377(5); +U+8378(0);U+8378(5);U+8467(4) +U+8379(0);U+8379(0); +U+837A(0);U+837A(0); +U+837B(0);U+837B(5);U+85E1(3) +U+837C(0);U+837C(5); +U+837D(0);U+837D(5);U+840E(3) +U+837E(0);U+837E(0); +U+837F(0);U+837F(0); +U+8380(0);U+8380(0); +U+8381(0);U+8381(0); +U+8382(0);U+8382(0); +U+8383(0);U+8383(0); +U+8384(0);U+8384(0); +U+8385(0);U+8385(5);U+849E(2,3) +U+8386(0);U+8386(5); +U+8387(0);U+8387(0); +U+8388(0);U+8388(0); +U+8389(0);U+8389(5); +U+838A(0);U+5E84(1,3);U+5E84(1,3),U+8358(4) +U+838B(0);U+838B(3); +U+838C(0);U+838C(0); +U+838D(0);U+838D(3); +U+838E(0);U+838E(5); +U+838F(0);U+838F(0); +U+8390(0);U+8390(0); +U+8391(0);U+8391(0); +U+8392(0);U+8392(5); +U+8393(0);U+8393(5); +U+8394(0);U+8394(0); +U+8395(0);U+8347(3);U+8347(3) +U+8396(0);U+830E(1,3);U+830E(1,3) +U+8397(0);U+8397(0); +U+8398(0);U+8398(5); +U+8399(0);U+8399(0); +U+839A(0);U+839A(3); +U+839B(0);U+839B(5); +U+839C(0);U+839C(5); +U+839D(0);U+839D(0); +U+839E(0);U+839E(5); +U+83A0(0);U+83A0(5); +U+83A1(0);U+83A1(0); +U+83A2(0);U+835A(1,3);U+835A(1,3) +U+83A3(0);U+83A3(0); +U+83A4(0);U+83A4(0); +U+83A5(0);U+83A5(0); +U+83A6(0);U+83A6(0); +U+83A7(0);U+82CB(1,3);U+82CB(1,3) +U+83A8(0);U+83A8(5); +U+83A9(0);U+83A9(5); +U+83AA(0);U+83AA(5); +U+83AB(0);U+83AB(5); +U+83AC(0);U+83AC(3); +U+83AD(0);U+83AD(0); +U+83AE(0);U+83AE(0); +U+83AF(0);U+83AF(0); +U+83B0(0);U+83B0(5); + +U+83B1(0);U+83B1(1,3);U+840A(1,3),U+90F2(3) +U+83B2(0);U+83B2(1,3);U+84EE(1,3) +U+83B3(0);U+83B3(1,3);U+8494(1,3) +U+83B4(0);U+83B4(1,3);U+8435(1,3) +U+83B6(0);U+83B6(4);U+859F(4) +U+83B7(0);U+83B7(1,3);U+7372(1,3),U+7A6B(1,3) +U+83B8(0);U+83B8(1,3);U+8555(1,3) +U+83B9(0);U+83B9(1,3);U+7469(1,3) +U+83BA(0);U+83BA(1,3);U+9DAF(1,3) +U+83BB(0);U+83BB(0); +U+83BC(0);U+83BC(1,3);U+84F4(2),U+8493(1,3) +U+83BD(0);U+83BD(5);U+833B(4) +U+83BF(0);U+83BF(0); +U+83C0(0);U+83C0(5); +U+83C1(0);U+83C1(5); +U+83C2(0);U+83C2(3); +U+83C3(0);U+83C3(0); +U+83C4(0);U+83C4(0); +U+83C5(0);U+83C5(5);U+844C(3) +U+83C6(0);U+83C6(0); +U+83C7(0);U+83C7(5);U+83F0(3,4),U+82FD(0,3,4) +U+83C8(0);U+83C8(0); +U+83C9(0);U+83C9(0); +U+83CA(0);U+83CA(5);U+861C(4) +U+83CB(0);U+83CB(3);U+82FF(3) +U+83CC(0);U+83CC(5); +U+83CD(0);U+83CD(0); +U+83CE(0);U+83CE(0); +U+83CF(0);U+83CF(5);U+6E2E(3) +U+83D0(0);U+83D0(0); +U+83D1(0);U+83D1(3); +U+83D2(0);U+83D2(0); +U+83D3(0);U+679C(2,3);U+679C(2,3) +U+83D4(0);U+83D4(5);U+8514(4),U+535C(1,3,4) +U+83D5(0);U+83D5(0); +U+83D6(0);U+83D6(5); +U+83D7(0);U+83D7(0); +U+83D8(0);U+83D8(5); +U+83D9(0);U+83D9(0); +U+83DA(0);U+83DA(0); +U+83DB(0);U+83DB(0); +U+83DC(0);U+83DC(5); +U+83DD(0);U+83DD(5); +U+83DE(0);U+9ECE(3);U+9ECE(3) +U+83DF(0);U+83DF(5); +U+83E0(0);U+83E0(5); +U+83E1(0);U+83E1(5); +U+83E2(0);U+83E2(3); +U+83E3(0);U+83E3(0); +U+83E4(0);U+83E4(0); +U+83E5(0);U+83E5(5); +U+83E7(0);U+83E7(0); +U+83E8(0);U+83E8(0); +U+83E9(0);U+83E9(5); +U+83EA(0);U+83EA(5); +U+83EB(0);U+5807(4);U+5807(4),U+84F3(3,4) +U+83EC(0);U+83EC(0); +U+83EE(0);U+83EE(0); +U+83EF(0);U+534E(1,3);U+534E(1,3),U+5D0B(3) +U+83F0(0);U+83F0(5);U+82FD(3),U+83C7(3,4) +U+83F1(0);U+83F1(5);U+8506(2,3) +U+83F2(0);U+83F2(5); +U+83F3(0);U+83F3(0); + +U+83F4(0);U+83F4(3);U+5EB5(2,3) +U+83F5(0);U+83F5(0); +U+83F6(0);U+83F6(0); +U+83F7(0);U+5E1A(3);U+5E1A(3) +U+83F8(0);U+83F8(5);U+70DF(2),U+7159(4) +U+83F9(0);U+83F9(5);U+8445(3) +U+83FA(0);U+83FA(0); +U+83FB(0);U+83FB(0); +U+83FC(0);U+83FC(0); +U+83FD(0);U+83FD(5); +U+83FE(0);U+83FE(0); +U+83FF(0);U+83FF(3); +U+8400(0);U+8400(0); +U+8401(0);U+8401(5); +U+8402(0);U+8402(0); +U+8403(0);U+8403(5); +U+8404(0);U+8404(5); +U+8405(0);U+6625(3);U+6625(3) +U+8406(0);U+8406(5); +U+8407(0);U+82CC(4);U+82CC(4) +U+8408(0);U+8408(3); +U+8409(0);U+8409(0); +U+840A(0);U+83B1(1,3);U+83B1(1,3),U+90F2(1,3) +U+840B(0);U+840B(5); +U+840C(0);U+840C(5);U+8544(4) +U+840D(0);U+840D(5); +U+840E(0);U+840E(5);U+837D(3) +U+840F(0);U+840F(5); +U+8410(0);U+8410(0); +U+8411(0);U+8411(5); +U+8412(0);U+8412(0); +U+8413(0);U+8413(3); +U+8415(0);U+8360(3);U+8360(3),U+85BA(3) +U+8418(0);U+8418(5); +U+8419(0);U+8419(0); +U+841A(0);U+841A(1,3);U+8600(1,3) +U+841B(0);U+841B(0); +U+841C(0);U+841C(5); +U+841D(0);U+841D(1,3);U+863F(1,3) +U+841E(0);U+841E(0); +U+8421(0);U+8421(0); +U+8422(0);U+8422(0); +U+8423(0);U+8423(0); +U+8424(0);U+8424(1,3);U+87A2(1,3) +U+8425(0);U+8425(1,3);U+55B6(4),U+71DF(1,3) +U+8426(0);U+8426(1,3);U+7E08(1,3) +U+8427(0);U+8427(1,3);U+856D(1,3) +U+8428(0);U+8428(1,3);U+85A9(1,3) +U+8429(0);U+8429(0); +U+842A(0);U+842A(0); +U+842B(0);U+842B(0); +U+842C(0);U+4E07(1,3);U+4E07(1,3) +U+842D(0);U+842D(0); +U+842E(0);U+842E(0); +U+842F(0);U+842F(0); +U+8430(0);U+8430(0); +U+8431(0);U+8431(5);U+8432(2) +U+8432(0);U+8431(2);U+8431(2) +U+8433(0);U+8433(0); +U+8434(0);U+835D(4);U+835D(4) +U+8435(0);U+83B4(1,3);U+83B4(1,3) +U+8436(0);U+8436(0); +U+8437(0);U+8437(0); + +U+8438(0);U+8438(5); +U+8439(0);U+8439(0); +U+843A(0);U+843A(0); +U+843B(0);U+843B(0); +U+843C(0);U+843C(5);U+855A(2,3) +U+843D(0);U+843D(5); +U+843E(0);U+843E(0); +U+843F(0);U+843F(0); +U+8440(0);U+8440(0); +U+8441(0);U+8441(0); +U+8442(0);U+8442(0); +U+8443(0);U+8443(0); +U+8444(0);U+8444(0); +U+8445(0);U+83F9(3);U+83F9(3) +U+8446(0);U+8446(5); +U+8447(0);U+8447(0); +U+8448(0);U+8448(0); +U+8449(0);U+53F6(1,3);U+53F6(1,3) +U+844A(0);U+844A(0); +U+844B(0);U+844B(3); +U+844C(0);U+83C5(3);U+83C5(3) +U+844D(0);U+844D(0); +U+844E(0);U+844E(0); +U+844F(0);U+844F(0); +U+8450(0);U+8450(0); +U+8451(0);U+8451(5); +U+8452(0);U+836D(1,3);U+836D(1,3) +U+8453(0);U+8453(0); +U+8454(0);U+8454(0); +U+8455(0);U+8455(0); +U+8456(0);U+8456(0); +U+8457(0);U+8457(5),U+7740(4);U+7740(4) +U+8459(0);U+8459(5); +U+845A(0);U+845A(5); +U+845B(0);U+845B(5); +U+845C(0);U+845C(5); +U+845D(0);U+845D(0); +U+845E(0);U+845E(0); +U+845F(0);U+845F(0); +U+8460(0);U+53C2(4);U+53C2(4),U+53C1(4,5),U+53C3(4,8,9),U+84E1(4),U+53C4(3,4) +U+8461(0);U+8461(5); +U+8462(0);U+76D6(3);U+76D6(3),U+84CB(3) +U+8463(0);U+8463(5);U+856B(3) +U+8464(0);U+836E(1,3);U+836E(1,3) +U+8465(0);U+8465(0); +U+8466(0);U+82C7(1,3);U+82C7(1,3) +U+8467(0);U+8378(4);U+8378(4) +U+8468(0);U+8468(0); +U+8469(0);U+8469(5); +U+846A(0);U+846A(0); +U+846B(0);U+846B(5); +U+846C(0);U+846C(5);U+585F(2,3) +U+846D(0);U+846D(5); +U+846E(0);U+6934(3);U+6934(3) +U+846F(0);U+836F(4);U+836F(4),U+85AC(4),U+85E5(1,3,4) +U+8470(0);U+8470(3); +U+8471(0);U+8471(5);U+8525(2,3) +U+8472(0);U+8472(0); +U+8473(0);U+8473(5); +U+8474(0);U+8474(0); +U+8475(0);U+8475(5); +U+8476(0);U+8476(5); +U+8477(0);U+8364(1,3);U+8364(1,3),U+8512(1,3) + +U+8478(0);U+8478(5); +U+8479(0);U+8479(0); +U+847A(0);U+847A(5); +U+847B(0);U+847B(0); +U+847C(0);U+847C(0); +U+847D(0);U+847D(0); +U+847E(0);U+847E(0); +U+847F(0);U+847F(0); +U+8480(0);U+8480(0); +U+8481(0);U+8481(0); +U+8482(0);U+8482(5); +U+8484(0);U+8484(0); +U+8485(0);U+8485(0); +U+8486(0);U+8486(0); +U+8487(0);U+8487(1,3);U+8546(1,3) +U+8488(0);U+8488(5); +U+8489(0);U+8489(1,3);U+8562(1,3) +U+848A(0);U+848A(0); +U+848B(0);U+848B(1,3);U+8523(1,3,4) +U+848C(0);U+848C(1,3);U+851E(1,3) +U+848D(0);U+853F(4);U+853F(4) +U+848E(0);U+848E(5); +U+848F(0);U+848F(0); +U+8490(0);U+8490(3); +U+8491(0);U+8491(0); +U+8492(0);U+8492(0); +U+8493(0);U+83BC(1,3);U+84F4(2),U+83BC(1,3) +U+8494(0);U+83B3(1,3);U+83B3(1,3) +U+8496(0);U+8496(0); +U+8497(0);U+8497(5); +U+8498(0);U+8498(0); +U+8499(0);U+8499(1,3);U+61DE(1,4),U+6FDB(1,3,4),U+77C7(1,4) +U+849A(0);U+849A(0); +U+849B(0);U+849B(0); +U+849C(0);U+849C(5); +U+849D(0);U+849D(0); +U+849E(0);U+8385(2,3);U+8385(2,3) +U+849F(0);U+849F(0); +U+84A0(0);U+84A0(0); +U+84A1(0);U+84A1(5); +U+84A2(0);U+84A2(0); +U+84A3(0);U+84A3(0); +U+84A4(0);U+84A4(0); +U+84A5(0);U+84A5(0); +U+84A6(0);U+84A6(3); +U+84A7(0);U+84A7(0); +U+84A8(0);U+84A8(3); +U+84A9(0);U+84A9(0); +U+84AA(0);U+84AA(0); +U+84AB(0);U+84AB(0); +U+84AC(0);U+84AC(0); +U+84AE(0);U+84AE(0); +U+84AF(0);U+84AF(5); +U+84B0(0);U+84B0(0); +U+84B1(0);U+84B1(0); +U+84B2(0);U+84B2(5); +U+84B3(0);U+84B3(0); +U+84B4(0);U+84B4(5); +U+84B5(0);U+84B5(0); +U+84B6(0);U+84B6(0); +U+84B8(0);U+84B8(5); +U+84B9(0);U+84B9(5); +U+84BA(0);U+84BA(5); + +U+84BB(0);U+84BB(0); +U+84BC(0);U+82CD(1,3);U+82CD(1,3) +U+84BD(0);U+84BD(5); +U+84BE(0);U+84BE(0); +U+84BF(0);U+84BF(5); +U+84C0(0);U+836A(1,3);U+836A(1,3) +U+84C1(0);U+84C1(5); +U+84C2(0);U+84C2(0); +U+84C4(0);U+84C4(5); +U+84C5(0);U+84C5(0); +U+84C6(0);U+5E2D(2,3);U+5E2D(2,3),U+5ED7(2,3,4) +U+84C7(0);U+84C7(0); +U+84C8(0);U+84C8(3); +U+84C9(0);U+84C9(5); +U+84CA(0);U+84CA(5); +U+84CB(0);U+76D6(1,3);U+8462(3),U+76D6(1,3) +U+84CC(0);U+84CC(0); +U+84CD(0);U+84CD(5); +U+84CE(0);U+84CE(0); +U+84CF(0);U+84CF(0); +U+84D0(0);U+84D0(5); +U+84D1(0);U+84D1(5);U+7C11(2) +U+84D2(0);U+84D2(0); +U+84D3(0);U+84D3(5); +U+84D4(0);U+84D4(0); +U+84D5(0);U+84D5(3); +U+84D6(0);U+84D6(5); +U+84D7(0);U+84D7(0); +U+84D8(0);U+84D8(3);U+8509(3,4) +U+84D9(0);U+84D9(0); +U+84DB(0);U+84DB(0); +U+84DC(0);U+84DC(0); +U+84DD(0);U+84DD(1,3);U+85CD(1,3) +U+84DE(0);U+84DE(0); +U+84DF(0);U+84DF(1,3);U+858A(1,3) +U+84E0(0);U+84E0(4);U+863A(4) +U+84E1(0);U+53C2(4);U+53C2(4),U+53C3(2,3),U+53C1(4,5),U+53C4(3,4),U+8460(4) +U+84E2(0);U+84E2(0); +U+84E3(0);U+84E3(1,3);U+8577(1,3) +U+84E4(0);U+84E4(0); +U+84E5(0);U+84E5(5);U+93A3(4) +U+84E6(0);U+84E6(1,3);U+9A40(1,3) +U+84E7(0);U+84E7(3); +U+84E8(0);U+84E8(4); +U+84E9(0);U+84E9(0); +U+84EA(0);U+84EA(0); +U+84EB(0);U+84EB(0); +U+84EC(0);U+84EC(5); +U+84EE(0);U+83B2(1,3);U+83B2(1,3) +U+84EF(0);U+82C1(1,3);U+82C1(1,3) +U+84F0(0);U+84F0(5); +U+84F1(0);U+84F1(0); +U+84F2(0);U+84F2(0); +U+84F3(0);U+5807(3);U+5807(3),U+83EB(3,4) +U+84F4(0);U+83BC(2);U+83BC(2),U+8493(2) +U+84F5(0);U+84F5(0); +U+84F6(0);U+84F6(0); +U+84F7(0);U+84F7(0); +U+84F8(0);U+84F8(0); +U+84F9(0);U+84F9(0); +U+84FA(0);U+827A(3);U+827A(3),U+517F(0,3,4),U+85DD(3,4) +U+84FB(0);U+84FB(0); +U+84FC(0);U+84FC(5); + +U+84FD(0);U+835C(1,3);U+835C(1,3) +U+84FE(0);U+84FE(0); +U+84FF(0);U+84FF(5); +U+8500(0);U+8500(0); +U+8501(0);U+8501(0); +U+8502(0);U+8502(0); +U+8503(0);U+8503(0); +U+8504(0);U+8504(0); +U+8506(0);U+83F1(2,3);U+83F1(2,3) +U+8507(0);U+66A8(4);U+66A8(4),U+66C1(4),U+81EE(4) +U+8508(0);U+8508(0); +U+8509(0);U+84D8(3,4);U+84D8(3,4) +U+850A(0);U+850A(0); +U+850B(0);U+850B(0); +U+850C(0);U+850C(5); +U+850D(0);U+7C97(3);U+7C97(3),U+89D5(2,3),U+9E81(3,4),U+9E84(3),U+9E86(3),U+9EA4(2,3) + +U+850E(0);U+850E(0); +U+850F(0);U+850F(0); +U+8511(0);U+8511(1,3);U+858E(3),U+884A(1,3,4) +U+8512(0);U+8364(3);U+8364(3),U+8477(1,3) +U+8513(0);U+8513(5); +U+8514(0);U+535C(1,3);U+535C(1,3),U+83D4(4) +U+8515(0);U+8515(4); +U+8516(0);U+8516(0); +U+8517(0);U+8517(5); +U+8518(0);U+8518(0); +U+8519(0);U+8519(0); +U+851A(0);U+851A(5); +U+851B(0);U+851B(0); +U+851C(0);U+851C(0); +U+851D(0);U+851D(0); +U+851E(0);U+848C(1,3);U+848C(1,3) +U+851F(0);U+851F(5); +U+8520(0);U+8520(0); +U+8521(0);U+8521(5); +U+8522(0);U+8522(0); +U+8523(0);U+848B(1,3);U+848B(1,3) +U+8524(0);U+8524(3); +U+8525(0);U+8471(2,3);U+8471(2,3) +U+8526(0);U+8311(1,3);U+8311(1,3) +U+8527(0);U+8527(3); +U+8528(0);U+8528(0); +U+8529(0);U+8529(0); +U+852A(0);U+852A(0); +U+852B(0);U+852B(5); +U+852C(0);U+852C(5); +U+852D(0);U+836B(1,3);U+836B(1,3),U+5ED5(0,1,3,4) +U+852E(0);U+5E3C(4);U+5E3C(4),U+5E57(1,3,4) +U+852F(0);U+852F(0); +U+8530(0);U+8530(0); +U+8531(0);U+699D(3);U+699D(3),U+6A27(3,4) +U+8534(0);U+9EBB(2,3);U+9EBB(2,3),U+75F2(0,2,3),U+75F3(2,3,4),U+6DCB(2,3,4,5) +U+8535(0);U+85CF(3);U+85CF(3) +U+8536(0);U+8536(0); +U+8537(0);U+8537(1);U+8594(1,3) +U+8538(0);U+8538(5); +U+8539(0);U+8539(1,3);U+861E(1,3) +U+853A(0);U+853A(1,3);U+85FA(1,3) +U+853B(0);U+853B(5); +U+853C(0);U+853C(1,3);U+85F9(1,3),U+8B6A(3) +U+853D(0);U+853D(5); +U+853E(0);U+85DC(2);U+85DC(2) + +U+853F(0);U+853F(4);U+848D(4) +U+8540(0);U+8540(0); +U+8541(0);U+8368(1,3);U+8368(1,3) +U+8542(0);U+8542(0); +U+8543(0);U+8543(5); +U+8544(0);U+840C(4);U+840C(4) +U+8545(0);U+85D5(3);U+85D5(3) +U+8546(0);U+8487(1,3);U+8487(1,3) +U+8547(0);U+8547(0); +U+8548(0);U+8548(5); +U+8549(0);U+8549(5); +U+854A(0);U+854A(5);U+6A64(2,3),U+854B(2,3),U+8602(2,3) +U+854B(0);U+854A(2,3);U+854A(2,3),U+6A64(0,2,3),U+8602(2,3) +U+854D(0);U+854D(0); +U+854E(0);U+835E(1,3);U+835E(1,3) +U+854F(0);U+854F(0);U+85F8(3) +U+8551(0);U+8551(0); +U+8552(0);U+836C(1,3);U+836C(1,3) +U+8553(0);U+82B8(1,3);U+82B8(1,3) +U+8554(0);U+8554(0); +U+8555(0);U+83B8(1,3);U+83B8(1,3) +U+8556(0);U+8556(5); +U+8557(0);U+8557(0); +U+8558(0);U+835B(1,3);U+835B(1,3) +U+8559(0);U+8559(5); +U+855A(0);U+843C(2,3);U+843C(2,3) +U+855B(0);U+855B(3); +U+855C(0);U+855C(3); +U+855D(0);U+855D(0); +U+855E(0);U+855E(5); +U+855F(0);U+855F(0); +U+8560(0);U+8560(0); +U+8561(0);U+8561(0); +U+8562(0);U+8489(1,3);U+8489(1,3) +U+8563(0);U+8563(3); +U+8564(0);U+8564(5); +U+8565(0);U+8565(0); +U+8566(0);U+8566(0); +U+8567(0);U+8567(0); +U+8568(0);U+8568(5); +U+8569(0);U+8361(1,3);U+76EA(2,3),U+8361(1,3),U+862F(3),U+6F52(0,1,3) +U+856A(0);U+829C(1,3);U+829C(1,3) +U+856B(0);U+8463(3);U+8463(3) +U+856C(0);U+856C(0); +U+856D(0);U+8427(1,3);U+8427(1,3) +U+856E(0);U+856E(0); +U+856F(0);U+856F(0); +U+8570(0);U+8570(0);U+8580(4) +U+8571(0);U+7A0D(4);U+7A0D(4) +U+8572(0);U+8572(1,3);U+8604(1,3) +U+8573(0);U+8573(0); +U+8574(0);U+8574(1,3,4);U+85F4(1,3),U+860A(4) +U+8575(0);U+8575(4);U+859E(4) +U+8576(0);U+8576(0); +U+8577(0);U+84E3(1,3);U+84E3(1,3) +U+8578(0);U+8578(3); +U+8579(0);U+8579(5); +U+857A(0);U+857A(5); +U+857B(0);U+857B(5); +U+857C(0);U+857C(0); +U+857D(0);U+857D(0); +U+857E(0);U+857E(5); +U+8580(0);U+8570(4);U+8570(4) + +U+8581(0);U+8581(0); +U+8582(0);U+8582(0); +U+8583(0);U+8583(0); +U+8584(0);U+8584(5); +U+8585(0);U+8585(5); +U+8586(0);U+8586(0); +U+8587(0);U+8587(5); +U+8588(0);U+835F(1,3);U+835F(1,3) +U+8589(0);U+79FD(3);U+79FD(3),U+7A62(1,3) +U+858A(0);U+84DF(1,3);U+84DF(1,3) +U+858B(0);U+858B(0); +U+858C(0);U+8297(1,3);U+8297(1,3) +U+858D(0);U+858D(0); +U+858E(0);U+8511(3);U+8511(3),U+884A(1,3,4) +U+858F(0);U+858F(5); +U+8590(0);U+8590(0); +U+8591(0);U+59DC(1,3);U+59DC(1,3) +U+8592(0);U+8592(0); +U+8594(0);U+8537(1,3);U+8537(1,3) +U+8595(0);U+8595(0); +U+8596(0);U+8596(3); +U+8598(0);U+8359(4);U+8359(4) +U+8599(0);U+5243(2);U+5243(2) +U+859A(0);U+859A(0); +U+859B(0);U+859B(5); +U+859C(0);U+859C(5); +U+859D(0);U+859D(0); +U+859E(0);U+8575(4);U+8575(4) +U+859F(0);U+83B6(4);U+83B6(4) +U+85A0(0);U+85A0(0); +U+85A1(0);U+85A1(0); +U+85A2(0);U+85A2(0); +U+85A3(0);U+85A3(0); +U+85A4(0);U+85A4(5); +U+85A5(0);U+85A5(0); +U+85A6(0);U+8350(1,3);U+8350(1,3) +U+85A7(0);U+85A7(0); +U+85A8(0);U+85A8(5); +U+85A9(0);U+8428(1,3);U+8428(1,3) +U+85AA(0);U+85AA(5); +U+85AB(0);U+85B0(4);U+85B0(4) +U+85AC(0);U+836F(4);U+836F(4),U+85E5(4),U+846F(4) +U+85AD(0);U+85AD(0); +U+85AE(0);U+85AE(1,3);U+85EA(1,3),U+7C54(1,3) +U+85AF(0);U+85AF(5);U+85F7(2) +U+85B0(0);U+85B0(5);U+85AB(4) +U+85B1(0);U+85B1(0); +U+85B3(0);U+85B3(0); +U+85B4(0);U+85B4(0); +U+85B5(0);U+85B5(0); +U+85B6(0);U+85B6(0); +U+85B7(0);U+85B7(5); +U+85B8(0);U+85B8(0); +U+85B9(0);U+85B9(5); +U+85BA(0);U+8360(1,3);U+8360(1,3),U+8415(3) +U+85BC(0);U+85BC(0); +U+85BD(0);U+85BD(0); +U+85BE(0);U+85BE(3); +U+85BF(0);U+85BF(0); +U+85C0(0);U+85C0(0); +U+85C1(0);U+85C1(5); +U+85C2(0);U+4E1B(3);U+4E1B(3),U+53E2(1,3,4),U+6B09(3) +U+85C3(0);U+85C3(3); + +U+85C4(0);U+85C4(0); +U+85C5(0);U+85C5(0); +U+85C6(0);U+85C6(0); +U+85C7(0);U+85C7(0); +U+85C8(0);U+85C8(0); +U+85C9(0);U+85C9(0),U+501F(1,3);U+501F(1,3),U+8024(3) +U+85CA(0);U+85CA(3); +U+85CB(0);U+85CB(0); +U+85CD(0);U+84DD(1,3);U+84DD(1,3) +U+85CE(0);U+8369(1,3);U+8369(1,3) +U+85CF(0);U+85CF(5);U+8535(3) +U+85D0(0);U+85D0(5); +U+85D1(0);U+85D1(0); +U+85D2(0);U+85D2(0); +U+85D3(0);U+85D3(1,3);U+861A(1,3) +U+85D4(0);U+85D4(0); +U+85D5(0);U+85D5(5);U+8545(3) +U+85D6(0);U+85D6(0); +U+85D7(0);U+85D7(0); +U+85D8(0);U+85D8(0); +U+85D9(0);U+85D9(0); +U+85DA(0);U+85DA(0); +U+85DB(0);U+85DB(0); +U+85DC(0);U+85DC(5);U+853E(2) +U+85DD(0);U+827A(1,3);U+517F(4),U+827A(1,3),U+84FA(3,4) +U+85DE(0);U+85DE(0); +U+85DF(0);U+85DF(4); +U+85E0(0);U+85E0(0); +U+85E1(0);U+837B(3);U+837B(3) +U+85E2(0);U+85E2(0); +U+85E3(0);U+85E3(0); +U+85E4(0);U+85E4(5);U+7C50(2,3),U+7C58(2,3) +U+85E5(0);U+836F(1,3);U+836F(1,3),U+85AC(4),U+846F(1,3,4) +U+85E6(0);U+85E6(0); +U+85E7(0);U+85E7(0); +U+85E8(0);U+85E8(3); +U+85E9(0);U+85E9(5);U+7C53(3) +U+85EA(0);U+85AE(1,3);U+7C54(3),U+85AE(1,3) +U+85EB(0);U+85EB(0); +U+85EC(0);U+85EC(0); +U+85ED(0);U+44D6(1,3);U+44D6(1,3) +U+85EF(0);U+85EF(0); +U+85F0(0);U+85F0(0); +U+85F1(0);U+85F1(0); +U+85F2(0);U+85F2(0); +U+85F4(0);U+8574(1,3);U+8574(1,3),U+860A(4) +U+85F5(0);U+85F5(0); +U+85F6(0);U+82C8(1,3);U+82C8(1,3) +U+85F7(0);U+85AF(2);U+85AF(2) +U+85F8(0);U+854F(3);U+854F(3) +U+85F9(0);U+853C(1,3);U+853C(1,3),U+8B6A(1,3) +U+85FA(0);U+853A(1,3);U+853A(1,3) +U+85FB(0);U+85FB(5); +U+85FD(0);U+6987(3);U+6987(3),U+6AEC(1,3) +U+85FE(0);U+85FE(0); +U+85FF(0);U+85FF(5); +U+8600(0);U+841A(1,3);U+841A(1,3) +U+8601(0);U+8601(0); +U+8602(0);U+854A(2,3);U+854A(2,3),U+6A64(0,2,3),U+854B(2,3) +U+8604(0);U+8572(1,3);U+8572(1,3) +U+8605(0);U+8605(5); +U+8606(0);U+82A6(1,3);U+82A6(1,3) +U+8607(0);U+82CF(1,3);U+56CC(4),U+82CF(1,3),U+8613(2),U+7526(1,3,4) + +U+8608(0);U+8608(0); +U+8609(0);U+8609(0); +U+860A(0);U+8574(4);U+8574(4),U+85F4(4) +U+860B(0);U+82F9(1,3);U+82F9(1,3) +U+860C(0);U+860C(0); +U+860F(0);U+8614(3,4);U+8614(3,4) +U+8611(0);U+8611(5); +U+8612(0);U+8612(0); +U+8613(0);U+82CF(4);U+82CF(4),U+8607(2),U+56CC(0,1,3,4),U+7526(1,3,4) +U+8614(0);U+8614(0);U+860F(3,4) +U+8616(0);U+8616(5);U+6AF1(4) +U+8617(0);U+6A97(4);U+6A97(4) +U+8618(0);U+8618(0); +U+8619(0);U+8619(0); +U+861A(0);U+85D3(1,3);U+85D3(1,3) +U+861B(0);U+861B(0); +U+861C(0);U+83CA(4);U+83CA(4) +U+861E(0);U+8539(1,3);U+8539(1,3) +U+861F(0);U+861F(0); +U+8620(0);U+8620(0); +U+8621(0);U+8621(0); +U+8622(0);U+830F(1,3);U+830F(1,3) +U+8623(0);U+8623(0); +U+8624(0);U+82B1(2,3);U+82B1(2,3) +U+8625(0);U+8625(0); +U+8626(0);U+8626(0); +U+8627(0);U+8627(5); +U+8628(0);U+8628(0); +U+8629(0);U+8629(5); +U+862A(0);U+862A(0); +U+862B(0);U+862B(3); +U+862C(0);U+867A(4);U+867A(4) +U+862D(0);U+5170(1,3);U+5170(1,3) +U+862E(0);U+862E(0); +U+862F(0);U+8361(3);U+8361(3),U+8569(3),U+6F52(0,3),U+76EA(3,4) +U+8630(0);U+8630(0); +U+8631(0);U+8631(0); +U+8632(0);U+8632(0); +U+8633(0);U+8633(0); +U+8634(0);U+8634(0); +U+8635(0);U+8635(0); +U+8636(0);U+8636(0); +U+8638(0);U+8638(5); +U+8639(0);U+8639(0); +U+863A(0);U+84E0(4);U+84E0(4) +U+863B(0);U+863B(0); +U+863C(0);U+863C(5); +U+863D(0);U+863D(3);U+6AD0(3) +U+863E(0);U+863E(0); +U+863F(0);U+841D(1,3);U+841D(1,3) +U+8640(0);U+9F51(3);U+9F51(3),U+97F2(3),U+9F4F(1,3) +U+8641(0);U+8641(0); +U+8642(0);U+8642(0); +U+8643(0);U+8643(0); +U+8644(0);U+8644(0); +U+8645(0);U+8645(0); +U+8646(0);U+8646(3); +U+8647(0);U+8647(0); +U+8648(0);U+8648(0); +U+8649(0);U+8649(0); +U+864A(0);U+864A(0); +U+864B(0);U+864B(0); +U+864C(0);U+864C(0); + +U+864D(0);U+864D(5); +U+864E(0);U+864E(5); +U+864F(0);U+864F(1);U+865C(1) +U+8650(0);U+8650(3); +U+8651(0);U+8651(1,3);U+616E(1,3) +U+8652(0);U+8652(4); +U+8653(0);U+8653(3); +U+8654(0);U+8654(5); +U+8655(0);U+5904(1,3);U+5904(1,3) +U+8656(0);U+8656(0);U+547C(2,3),U+5611(2,3),U+8B3C(2,3) +U+8658(0);U+8658(0); +U+8659(0);U+8659(0); +U+865A(0);U+865A(5);U+865B(3) +U+865B(0);U+865A(3);U+865A(3) +U+865C(0);U+864F(1);U+864F(1) +U+865D(0);U+865D(0); +U+865E(0);U+865E(5); +U+865F(0);U+53F7(1,3);U+53F7(1,3),U+8B79(1,3) +U+8660(0);U+8660(0); +U+8661(0);U+8661(3); +U+8662(0);U+8662(5); +U+8663(0);U+66B4(3);U+66B4(3) +U+8664(0);U+8664(0); +U+8665(0);U+8665(4); +U+8666(0);U+8666(3); +U+8667(0);U+4E8F(1,3);U+4E8F(1,3) +U+8668(0);U+8668(0); +U+8669(0);U+8669(4); +U+866A(0);U+866A(0); +U+866B(0);U+866B(1,3);U+87F2(1,3) +U+866C(0);U+866C(5);U+866F(2,3) +U+866D(0);U+866D(0); +U+866E(0);U+866E(1,3);U+87E3(1,3) +U+866F(0);U+866C(2,3);U+866C(2,3) +U+8670(0);U+8670(0); +U+8671(0);U+8671(3);U+8768(2,3) +U+8672(0);U+8672(0); +U+8673(0);U+8673(0); +U+8674(0);U+8674(0); +U+8676(0);U+8676(0); +U+8677(0);U+8677(0); +U+8678(0);U+8678(0); +U+8679(0);U+8679(5); +U+867A(0);U+867A(5);U+862C(4) +U+867B(0);U+867B(5); +U+867C(0);U+867C(5); +U+867D(0);U+867D(1,3);U+96D6(1,3) +U+867E(0);U+867E(1,3);U+8766(1,3) +U+867F(0);U+867F(1,3);U+8806(1,3) +U+8680(0);U+8680(1,3);U+8755(1,3) +U+8681(0);U+8681(1,3);U+8798(3),U+87FB(1,3) +U+8682(0);U+8682(1,3);U+879E(1,3) +U+8683(0);U+8683(4);U+8801(4) +U+8684(0);U+8684(0); +U+8685(0);U+8685(0); +U+8686(0);U+8686(0); +U+8687(0);U+8687(0); +U+8688(0);U+8688(0); +U+868A(0);U+868A(5);U+87A1(2,3),U+87C1(2,3) +U+868B(0);U+868B(5);U+8739(3) +U+868C(0);U+868C(5);U+7865(4) +U+868D(0);U+868D(5); +U+868E(0);U+868E(0); + +U+868F(0);U+868F(3); +U+8690(0);U+8690(0); +U+8691(0);U+8691(0); +U+8693(0);U+8693(5); +U+8694(0);U+86B3(4);U+86B3(4) +U+8695(0);U+8695(1,3);U+8836(1,3) +U+8696(0);U+8696(0); +U+8697(0);U+8697(0); +U+8698(0);U+86D4(2,3);U+86D4(2,3),U+75D0(0,2,3),U+8716(2,3) +U+8699(0);U+8699(0); +U+869A(0);U+869A(0); +U+869B(0);U+869B(0); +U+869C(0);U+869C(5); +U+869D(0);U+869D(5);U+8814(2,3) +U+869E(0);U+869E(0); +U+869F(0);U+869F(0); +U+86A1(0);U+86A1(4); +U+86A2(0);U+86A2(0); +U+86A3(0);U+86A3(5);U+8719(3) +U+86A4(0);U+86A4(5); +U+86A5(0);U+86A5(0); +U+86A7(0);U+86A7(5); +U+86A8(0);U+86A8(5); +U+86A9(0);U+86A9(5); +U+86AA(0);U+86AA(5); +U+86AB(0);U+86AB(0); +U+86AC(0);U+86AC(1,3);U+8706(1,3) +U+86AD(0);U+86AD(0); +U+86AE(0);U+86AE(0); +U+86AF(0);U+86AF(5); +U+86B0(0);U+86B0(5); +U+86B1(0);U+86B1(5); +U+86B2(0);U+86B2(0); +U+86B3(0);U+86B3(4);U+8694(4) +U+86B4(0);U+86B4(5); +U+86B5(0);U+86B5(5); +U+86B6(0);U+86B6(5);U+9B7D(3) +U+86B7(0);U+86B7(0); +U+86B8(0);U+86B8(4); +U+86B9(0);U+86B9(0); +U+86BA(0);U+86BA(5); +U+86BB(0);U+86BB(0); +U+86BC(0);U+86BC(0); +U+86BD(0);U+86BD(0); +U+86BE(0);U+86BE(0); +U+86BF(0);U+86BF(0); +U+86C0(0);U+86C0(5); +U+86C1(0);U+86C1(3); +U+86C2(0);U+86C2(0); +U+86C3(0);U+86C3(0); +U+86C4(0);U+86C4(5);U+86CC(3) +U+86C5(0);U+86C5(0); +U+86C6(0);U+86C6(5); +U+86C7(0);U+86C7(5); +U+86C8(0);U+86C8(0); +U+86C9(0);U+86C9(5); +U+86CA(0);U+86CA(1,3);U+8831(1,3) +U+86CB(0);U+86CB(5); +U+86CC(0);U+86C4(3);U+86C4(3) +U+86CE(0);U+86CE(1,3);U+8823(1,3) +U+86CF(0);U+86CF(1,3);U+87F6(1,3) +U+86D0(0);U+86D0(5); +U+86D1(0);U+86D1(5); + +U+86D2(0);U+86D2(0); +U+86D3(0);U+86D3(3); +U+86D4(0);U+86D4(5);U+75D0(2,3),U+8698(2,3),U+8716(2) +U+86D6(0);U+86D6(4); +U+86D7(0);U+86D7(0); +U+86D8(0);U+86D8(5); +U+86D9(0);U+86D9(5); +U+86DA(0);U+86DA(0); +U+86DB(0);U+86DB(5);U+9F04(3) +U+86DC(0);U+86DC(0); +U+86DD(0);U+86DD(0); +U+86DE(0);U+86DE(5); +U+86DF(0);U+86DF(5); +U+86E1(0);U+86E1(0); +U+86E2(0);U+86E2(0); +U+86E3(0);U+86E3(0); +U+86E4(0);U+86E4(5); +U+86E5(0);U+86E5(0); +U+86E6(0);U+86E6(0); +U+86E8(0);U+86E8(0); +U+86E9(0);U+86E9(5);U+86EC(3) +U+86EA(0);U+9713(3);U+9713(3),U+873A(2,3) +U+86EB(0);U+86EB(0); +U+86EC(0);U+86E9(3);U+86E9(3) +U+86ED(0);U+86ED(5); +U+86EE(0);U+86EE(1,3);U+883B(1,3) +U+86EF(0);U+86EF(0); +U+86F0(0);U+86F0(1,3);U+87C4(1,3) +U+86F1(0);U+86F1(1,3);U+86FA(1,3) +U+86F2(0);U+86F2(1,3);U+87EF(1,3) +U+86F3(0);U+86F3(1,3);U+8784(1,3) +U+86F4(0);U+86F4(1,3);U+8810(1,3) +U+86F5(0);U+86F5(0); +U+86F6(0);U+86F6(0); +U+86F7(0);U+86F7(3); +U+86F8(0);U+86F8(5); +U+86F9(0);U+86F9(5); +U+86FA(0);U+86F1(1,3);U+86F1(1,3) +U+86FB(0);U+8715(4);U+8715(4) +U+86FC(0);U+86FC(0); +U+86FE(0);U+86FE(5); +U+86FF(0);U+86FF(0); +U+8700(0);U+8700(5); +U+8701(0);U+8701(0); +U+8702(0);U+8702(5); +U+8703(0);U+8703(5);U+8704(3) +U+8704(0);U+8703(3);U+8703(3) +U+8705(0);U+8705(0); +U+8706(0);U+86AC(1,3);U+86AC(1,3) +U+8707(0);U+8707(5); +U+8708(0);U+8708(5); +U+8709(0);U+8709(5); +U+870A(0);U+870A(5); +U+870B(0);U+8782(2,3,4);U+8782(2,3,4) +U+870C(0);U+870C(0); +U+870D(0);U+870D(5); +U+870E(0);U+870E(3); +U+870F(0);U+870F(0); +U+8710(0);U+8710(0); +U+8711(0);U+8712(3);U+8712(3) +U+8712(0);U+8712(5);U+8711(3) +U+8713(0);U+8713(5); +U+8714(0);U+8714(0); + +U+8715(0);U+8715(5);U+86FB(4) +U+8716(0);U+86D4(2);U+86D4(2),U+75D0(0,2,3),U+8698(2,3) +U+8717(0);U+8717(1,3);U+7611(4),U+8778(1,3) +U+8718(0);U+8718(5);U+9F05(3) +U+8719(0);U+86A3(3);U+86A3(3) +U+871A(0);U+871A(5); +U+871B(0);U+871B(0); +U+871C(0);U+871C(5); +U+871E(0);U+871E(5); +U+871F(0);U+871F(0); +U+8720(0);U+8720(0); +U+8721(0);U+8721(1,3);U+881F(1,3) +U+8722(0);U+8722(5); +U+8723(0);U+8723(5); +U+8724(0);U+8724(0); +U+8725(0);U+8725(5); +U+8726(0);U+8726(3); +U+8727(0);U+8727(0); +U+8728(0);U+8776(2,3);U+8776(2,3) +U+8729(0);U+8729(5); +U+872A(0);U+872A(0); +U+872B(0);U+872B(0); +U+872C(0);U+872C(3); +U+872D(0);U+872D(0); +U+872E(0);U+872E(5);U+9B4A(4) +U+8730(0);U+8730(0); +U+8731(0);U+8731(5); +U+8732(0);U+8732(0); +U+8733(0);U+8733(0); +U+8734(0);U+8734(5); +U+8735(0);U+8735(0); +U+8736(0);U+8736(0); +U+8737(0);U+8737(5);U+8E21(4) +U+8738(0);U+8738(0); +U+8739(0);U+868B(3);U+868B(3) +U+873A(0);U+9713(2,3);U+9713(2,3),U+86EA(0,2,3) +U+873B(0);U+873B(5); +U+873C(0);U+873C(3); +U+873E(0);U+873E(5); +U+873F(0);U+873F(5); +U+8740(0);U+8740(0); +U+8741(0);U+8741(0); +U+8742(0);U+8742(0); +U+8743(0);U+8743(4); +U+8744(0);U+8744(4); +U+8746(0);U+8746(0); +U+8747(0);U+8747(1,3);U+8805(1,3) +U+8748(0);U+8748(1,3);U+87C8(1,3) +U+8749(0);U+8749(1,3);U+87EC(1,3) +U+874A(0);U+874A(0); +U+874C(0);U+874C(5); +U+874D(0);U+874D(0); +U+874E(0);U+874E(5);U+880D(2,3) +U+874F(0);U+874F(0); +U+8750(0);U+8750(0); +U+8751(0);U+8751(0); +U+8752(0);U+8752(3); +U+8753(0);U+8753(5); +U+8754(0);U+8754(0); +U+8755(0);U+8680(1,3);U+8680(1,3) +U+8756(0);U+8756(0); +U+8757(0);U+8757(5); +U+8758(0);U+8758(0); + +U+8759(0);U+8759(5); +U+875A(0);U+875A(0); +U+875B(0);U+875B(0); +U+875C(0);U+875C(0); +U+875D(0);U+875D(0); +U+875E(0);U+875E(0); +U+875F(0);U+732C(2,3);U+732C(2,3) +U+8760(0);U+8760(5); +U+8761(0);U+8815(2,3);U+8815(2,3) +U+8762(0);U+8762(0); +U+8763(0);U+8763(5); +U+8764(0);U+8764(5); +U+8765(0);U+8765(5); +U+8766(0);U+867E(1,3);U+867E(1,3) +U+8767(0);U+8767(0); +U+8768(0);U+8671(2,3);U+8671(2,3) +U+8769(0);U+8769(0); +U+876A(0);U+876A(0); +U+876B(0);U+8829(3);U+8829(3) +U+876C(0);U+876C(0); +U+876D(0);U+876D(0); +U+876E(0);U+876E(5); +U+876F(0);U+733F(2,3);U+733F(2,3) +U+8770(0);U+8770(5); +U+8772(0);U+8772(0); +U+8773(0);U+73B3(3);U+73B3(3) +U+8774(0);U+8774(5); +U+8775(0);U+8775(0); +U+8776(0);U+8776(5);U+8728(2,3) +U+8777(0);U+8777(3); +U+8778(0);U+8717(1,3);U+8717(1,3),U+7611(0,1,3,4) +U+8779(0);U+8779(0); +U+877A(0);U+877A(0); +U+877B(0);U+877B(5); +U+877C(0);U+877C(1,3);U+87BB(1,3) +U+877D(0);U+877D(5); +U+877E(0);U+877E(1,3);U+8811(1,3) +U+8780(0);U+8780(4);U+87BF(4) +U+8781(0);U+8781(0); +U+8782(0);U+8782(5);U+870B(2,3,4) +U+8783(0);U+8783(5); +U+8784(0);U+86F3(1,3);U+86F3(1,3) +U+8785(0);U+8785(5); +U+8786(0);U+8786(0); +U+8787(0);U+8787(0); +U+8788(0);U+8788(5); +U+8789(0);U+8789(0); +U+878A(0);U+878A(3); +U+878B(0);U+878B(5); +U+878C(0);U+878C(0); +U+878D(0);U+878D(5); +U+878F(0);U+878F(0); +U+8790(0);U+8790(0); +U+8791(0);U+8791(0); +U+8792(0);U+8792(0); +U+8793(0);U+8793(5); +U+8794(0);U+8794(0); +U+8795(0);U+8795(0); +U+8796(0);U+8796(0); +U+8797(0);U+8797(5);U+87B3(4) +U+8798(0);U+8681(3);U+8681(3),U+87FB(1,3) +U+879A(0);U+879A(0); +U+879B(0);U+879B(0); + +U+879C(0);U+879C(0); +U+879D(0);U+879D(0); +U+879E(0);U+8682(1,3);U+8682(1,3) +U+879F(0);U+879F(5); +U+87A0(0);U+87A0(0); +U+87A1(0);U+868A(2,3);U+868A(2,3),U+87C1(2,3) +U+87A2(0);U+8424(1,3);U+8424(1,3) +U+87A3(0);U+87A3(0); +U+87A4(0);U+949F(3);U+949F(3),U+9221(3,4),U+937E(1,3),U+9418(1,3),U+953A(0,1,3,4) +U+87A5(0);U+87A5(0); +U+87A6(0);U+87A6(0); +U+87A7(0);U+87A7(0); +U+87A8(0);U+87A8(1,3);U+87CE(1,3) +U+87A9(0);U+87A9(0); +U+87AA(0);U+87AA(0); +U+87AB(0);U+87AB(5); +U+87AC(0);U+87AC(5); +U+87AD(0);U+87AD(5); +U+87AE(0);U+87AE(3); +U+87AF(0);U+87AF(5); +U+87B0(0);U+87B0(0); +U+87B1(0);U+87B1(0); +U+87B2(0);U+87B2(0); +U+87B3(0);U+87B3(5);U+8797(4) +U+87B4(0);U+87B4(0); +U+87B5(0);U+87B5(5); +U+87B6(0);U+87B6(3); +U+87B7(0);U+87B7(3); +U+87B8(0);U+87B8(0); +U+87B9(0);U+87B9(0); +U+87BA(0);U+87BA(5); +U+87BB(0);U+877C(1,3);U+877C(1,3) +U+87BC(0);U+87BC(0); +U+87BD(0);U+87BD(5); +U+87BE(0);U+87BE(0); +U+87BF(0);U+8780(4);U+8780(4) +U+87C0(0);U+87C0(5); +U+87C1(0);U+868A(2,3);U+868A(2,3),U+87A1(2,3) +U+87C2(0);U+87C2(0); +U+87C3(0);U+87C3(0); +U+87C4(0);U+86F0(1,3);U+86F0(1,3) +U+87C5(0);U+87C5(0); +U+87C6(0);U+87C6(5);U+87C7(2,3) +U+87C7(0);U+87C6(2,3);U+87C6(2,3) +U+87C8(0);U+8748(1,3);U+8748(1,3) +U+87C9(0);U+87C9(0); +U+87CA(0);U+87CA(5); +U+87CB(0);U+87CB(5); +U+87CC(0);U+87CC(0); +U+87CD(0);U+87CD(0); +U+87CE(0);U+87A8(1,3);U+87A8(1,3) +U+87CF(0);U+87CF(1,3,4);U+8828(1,3) +U+87D0(0);U+87D0(0); +U+87D1(0);U+87D1(5); +U+87D2(0);U+87D2(5);U+880E(3) +U+87D3(0);U+87D3(5); +U+87D4(0);U+87D4(0); +U+87D5(0);U+87D5(0); +U+87D6(0);U+87D6(3); +U+87D7(0);U+87D7(3); +U+87D8(0);U+87D8(3); +U+87D9(0);U+87D9(0); +U+87DB(0);U+87DB(5); + +U+87DC(0);U+87DC(0); +U+87DD(0);U+87DD(0); +U+87DE(0);U+87DE(0); +U+87DF(0);U+87DF(3); +U+87E0(0);U+87E0(5); +U+87E1(0);U+87E1(3); +U+87E2(0);U+87E2(0); +U+87E3(0);U+866E(1,3);U+866E(1,3) +U+87E4(0);U+87E4(0); +U+87E5(0);U+87E5(5); +U+87E6(0);U+87E6(0); +U+87E7(0);U+87E7(0); +U+87E8(0);U+87E8(3); +U+87E9(0);U+87E9(0); +U+87EA(0);U+87EA(5); +U+87EB(0);U+87EB(0); +U+87EC(0);U+8749(1,3);U+8749(1,3) +U+87ED(0);U+87ED(0); +U+87EE(0);U+87EE(5); +U+87EF(0);U+86F2(1,3);U+86F2(1,3) +U+87F1(0);U+87F1(0); +U+87F2(0);U+866B(1,3);U+866B(1,3) +U+87F3(0);U+87F3(0); +U+87F4(0);U+87F4(4); +U+87F5(0);U+87F5(0); +U+87F6(0);U+86CF(1,3);U+86CF(1,3) +U+87F7(0);U+87F7(0); +U+87F8(0);U+87F8(0); +U+87F9(0);U+87F9(5);U+880F(2,3) +U+87FA(0);U+87FA(3); +U+87FB(0);U+8681(1,3);U+8681(1,3),U+8798(1,3) +U+87FC(0);U+87FC(0); +U+87FD(0);U+87FD(0); +U+87FE(0);U+87FE(5); +U+87FF(0);U+87FF(0); +U+8800(0);U+8800(0); +U+8801(0);U+8683(4);U+8683(4) +U+8802(0);U+8802(0); +U+8803(0);U+8803(5); +U+8804(0);U+8804(0); +U+8805(0);U+8747(1,3);U+8747(1,3) +U+8806(0);U+867F(1,3);U+867F(1,3) +U+8808(0);U+8808(0); +U+8809(0);U+8809(0); +U+880A(0);U+880A(5); +U+880B(0);U+880B(3); +U+880C(0);U+880C(0); +U+880D(0);U+874E(2,3);U+874E(2,3) +U+880E(0);U+87D2(3);U+87D2(3) +U+880F(0);U+87F9(2,3);U+87F9(2,3) +U+8810(0);U+86F4(1,3);U+86F4(1,3) +U+8811(0);U+877E(1,3);U+877E(1,3) +U+8813(0);U+8813(5); +U+8814(0);U+869D(2,3);U+869D(2,3) +U+8815(0);U+8815(5);U+8761(2,3) +U+8816(0);U+8816(5); +U+8817(0);U+8817(0); +U+8818(0);U+8818(0); +U+8819(0);U+8819(0); +U+881A(0);U+881A(0); +U+881B(0);U+881B(5); +U+881C(0);U+881C(0); +U+881D(0);U+881D(0); + +U+881E(0);U+881E(0); +U+881F(0);U+8721(1,3);U+8721(1,3) +U+8820(0);U+8820(0); +U+8821(0);U+8821(5); +U+8822(0);U+8822(5);U+60F7(2,3) +U+8823(0);U+86CE(1,3);U+86CE(1,3) +U+8824(0);U+8824(0); +U+8825(0);U+8825(3); +U+8826(0);U+8826(0); +U+8827(0);U+8839(3);U+8839(3) +U+8828(0);U+87CF(1,3);U+87CF(1,3) +U+8829(0);U+8829(3);U+876B(3) +U+882A(0);U+882A(0); +U+882B(0);U+5299(3);U+5299(3) +U+882C(0);U+882C(0); +U+882E(0);U+882E(0); +U+882F(0);U+882F(4); +U+8830(0);U+8830(0); +U+8831(0);U+86CA(1,3);U+86CA(1,3) +U+8832(0);U+8832(5); +U+8833(0);U+8833(0); +U+8834(0);U+8834(0); +U+8835(0);U+8835(3); +U+8836(0);U+8695(1,3);U+8695(1,3) +U+8837(0);U+883C(4);U+883C(4) +U+8838(0);U+8838(0); +U+8839(0);U+8839(5);U+8827(3) +U+883B(0);U+86EE(1,3);U+86EE(1,3) +U+883C(0);U+883C(5);U+8837(4) +U+883D(0);U+883D(0); +U+883E(0);U+883E(0); +U+883F(0);U+883F(0); +U+8840(0);U+8840(5); +U+8841(0);U+8841(0); +U+8842(0);U+8844(2,3);U+8844(2,3) +U+8843(0);U+8843(3); +U+8844(0);U+8844(5);U+8842(2,3) +U+8845(0);U+8845(1,3);U+91C1(1,3) +U+8846(0);U+4F17(1,3);U+4F17(1,3),U+773E(2) +U+8848(0);U+8848(0); +U+8849(0);U+8849(0); +U+884A(0);U+8511(1,3);U+8511(1,3),U+858E(1,3,4) +U+884B(0);U+884B(0); +U+884C(0);U+884C(5); +U+884D(0);U+884D(5); +U+884E(0);U+884E(0); +U+884F(0);U+884F(0); +U+8850(0);U+8850(0); +U+8851(0);U+8851(0); +U+8852(0);U+8852(3); +U+8853(0);U+672F(1,3);U+672F(1,3),U+672E(0,1,3,4) +U+8854(0);U+8854(1,3);U+5563(4),U+929C(1,3) +U+8855(0);U+540C(2);U+540C(2),U+4EDD(2,3,5) +U+8856(0);U+5F04(2);U+5F04(2) +U+8857(0);U+8857(5); +U+8859(0);U+8859(5); +U+885A(0);U+80E1(2);U+80E1(2),U+9B0D(1,2,3,4) +U+885B(0);U+536B(1,3);U+536B(1,3),U+885E(3) +U+885D(0);U+51B2(1,3);U+51B2(1,3),U+6C96(3,4),U+794C(1,3,4),U+8876(1,3,4),U+76C5(1,3,4) + +U+885E(0);U+536B(3);U+536B(3),U+885B(3) +U+8860(0);U+8860(0); +U+8861(0);U+8861(5); + +U+8862(0);U+8862(5); +U+8863(0);U+8863(5); +U+8864(0);U+8864(5); +U+8865(0);U+8865(1,3);U+88DC(1,3) +U+8866(0);U+8866(0); +U+8867(0);U+8867(0); +U+8868(0);U+8868(1,3);U+9336(1,3) +U+8869(0);U+8869(5);U+7D01(4) +U+886A(0);U+8898(4);U+8898(4) +U+886B(0);U+886B(5); +U+886C(0);U+886C(1,3);U+896F(1,3) +U+886D(0);U+886D(0); +U+886E(0);U+886E(5);U+7DF7(3),U+889E(3) +U+886F(0);U+886F(0); +U+8870(0);U+8870(5); +U+8871(0);U+8871(0); +U+8872(0);U+8872(5); +U+8873(0);U+8873(0); +U+8874(0);U+8874(0); +U+8875(0);U+8875(0); +U+8876(0);U+51B2(4);U+51B2(4),U+6C96(3,4),U+794C(3,4),U+885D(1,3,4),U+76C5(3,4) +U+8877(0);U+8877(5); +U+8878(0);U+8878(0); +U+8879(0);U+53EA(1);U+53EA(1),U+96BB(1,3,4) +U+887B(0);U+887B(3); +U+887C(0);U+887C(0); +U+887D(0);U+887D(5); +U+887E(0);U+887E(5); +U+887F(0);U+887F(5); +U+8880(0);U+8880(0); +U+8881(0);U+8881(5); +U+8882(0);U+8882(5); +U+8883(0);U+8883(0); +U+8884(0);U+8884(1,3);U+8956(1,3) +U+8885(0);U+8885(1,3,4);U+5ACB(2),U+5B1D(4),U+88CA(1,3),U+892D(3) +U+8886(0);U+8886(4);U+8918(4) +U+8887(0);U+8887(0); +U+8888(0);U+8888(5);U+6BE0(3) +U+8889(0);U+8889(3); +U+888A(0);U+888A(0); +U+888B(0);U+888B(5); +U+888C(0);U+888D(3);U+888D(3) +U+888D(0);U+888D(5);U+888C(3) +U+888E(0);U+888E(3); +U+888F(0);U+888F(0); +U+8890(0);U+8890(0); +U+8891(0);U+8891(0); +U+8892(0);U+8892(5);U+8962(2,3) +U+8893(0);U+8893(0); +U+8894(0);U+8894(0); +U+8895(0);U+8895(0); +U+8896(0);U+8896(5);U+890E(4) +U+8897(0);U+8897(3); +U+8898(0);U+8898(4);U+886A(4) +U+8899(0);U+8899(0); +U+889A(0);U+889A(0); +U+889B(0);U+889B(0); +U+889C(0);U+889C(1,3);U+896A(1,3,4),U+97C8(4),U+97E4(3,4) +U+889D(0);U+889D(0); +U+889E(0);U+886E(3);U+886E(3),U+7DF7(0,3) +U+889F(0);U+5E19(2,3);U+5E19(2,3) +U+88A0(0);U+88A0(4); +U+88A1(0);U+88A1(4); + +U+88A2(0);U+88A2(5); +U+88A3(0);U+88A3(3); +U+88A4(0);U+88A4(5); +U+88A5(0);U+88A5(0); +U+88A6(0);U+88A6(0); +U+88A7(0);U+88A7(0); +U+88A8(0);U+88A8(3); +U+88A9(0);U+88A9(0); +U+88AA(0);U+88AA(0); +U+88AB(0);U+88AB(5); +U+88AC(0);U+88D5(4);U+88D5(4) +U+88AD(0);U+88AD(1,3);U+8972(1,3) +U+88AE(0);U+88AE(0); +U+88AF(0);U+88AF(4);U+894F(4) +U+88B0(0);U+88B0(0); +U+88B1(0);U+88B1(5); +U+88B2(0);U+88B2(4); +U+88B3(0);U+88B3(3); +U+88B4(0);U+88E4(4);U+8932(2),U+88E4(4) +U+88B6(0);U+88B6(0); +U+88B7(0);U+88B7(5); +U+88B8(0);U+88B8(0); +U+88B9(0);U+88B9(3); +U+88BA(0);U+88BA(0); +U+88BB(0);U+88BB(0); +U+88BC(0);U+88BC(5); +U+88BD(0);U+88BD(0); +U+88BE(0);U+88BE(0); +U+88BF(0);U+88BF(0); +U+88C0(0);U+88C0(0); +U+88C1(0);U+88C1(5); +U+88C2(0);U+88C2(5); +U+88C3(0);U+88C3(0); +U+88C4(0);U+88C4(0); +U+88C5(0);U+88C5(1,3);U+88DD(1,3,4) +U+88C6(0);U+88C6(1,3);U+8960(1,3) +U+88C7(0);U+88C7(0); +U+88C8(0);U+88C8(4);U+890C(4) +U+88C9(0);U+88C9(5); +U+88CA(0);U+8885(1,3);U+5ACB(2),U+5B1D(2),U+8885(1,3),U+892D(2,3) +U+88CB(0);U+88CB(0); +U+88CC(0);U+5939(4);U+5939(4),U+593E(1,3,4) +U+88CD(0);U+88CD(0); +U+88CE(0);U+88CE(5); +U+88CF(0);U+91CC(1,3);U+88E1(2,3),U+91CC(1,3) +U+88D0(0);U+88D0(0); +U+88D1(0);U+88D1(0); +U+88D2(0);U+88D2(5); +U+88D3(0);U+88D3(0); +U+88D4(0);U+88D4(5); +U+88D5(0);U+88D5(5);U+88AC(4) +U+88D6(0);U+88D6(0); +U+88D7(0);U+88D7(0); +U+88D8(0);U+88D8(5); +U+88D9(0);U+88D9(5);U+5E2C(2,3),U+88E0(2,3) +U+88DA(0);U+88DA(0); +U+88DB(0);U+88DB(0); +U+88DC(0);U+8865(1,3);U+8865(1,3) +U+88DD(0);U+88C5(1,3);U+88C5(1,3) +U+88DE(0);U+88DE(0); +U+88DF(0);U+88DF(5); +U+88E0(0);U+88D9(2,3);U+88D9(2,3),U+5E2C(0,2,3) +U+88E1(0);U+91CC(4);U+88CF(2,3),U+91CC(4) + +U+88E2(0);U+88E2(1,3);U+8933(1,3) +U+88E3(0);U+88E3(1,3);U+895D(1,3) +U+88E4(0);U+88E4(1,3);U+8932(1,3),U+88B4(4) +U+88E5(0);U+88E5(1,3);U+8947(1,3),U+8949(3) +U+88E7(0);U+88E7(0); +U+88E8(0);U+88E8(5); +U+88EA(0);U+88EA(0); +U+88EB(0);U+88EB(0); +U+88EC(0);U+88EC(0); +U+88EE(0);U+88EE(0); +U+88EF(0);U+88EF(0); +U+88F0(0);U+88F0(5); +U+88F1(0);U+88F1(5); +U+88F2(0);U+88F2(0); +U+88F3(0);U+88F3(5); +U+88F4(0);U+88F4(5);U+88F5(3) +U+88F5(0);U+88F4(3);U+88F4(3) +U+88F6(0);U+88F6(0); +U+88F7(0);U+88F7(0); +U+88F8(0);U+88F8(5);U+81DD(2,3) +U+88F9(0);U+88F9(5);U+8901(3) +U+88FA(0);U+88FA(0); +U+88FB(0);U+88FB(0); +U+88FC(0);U+88FC(5); +U+88FD(0);U+5236(1,3);U+5236(1,3) +U+88FE(0);U+88FE(5); +U+88FF(0);U+88FF(0); +U+8900(0);U+5E3A(4);U+5E3A(4) +U+8901(0);U+88F9(3);U+88F9(3) +U+8902(0);U+8902(5); +U+8904(0);U+8904(0); +U+8905(0);U+8905(0); +U+8906(0);U+8906(0); +U+8907(0);U+590D(1,3);U+590D(1,3),U+5FA9(1,3),U+8986(1,3) +U+8908(0);U+8908(0); +U+8909(0);U+8909(0); +U+890A(0);U+890A(5);U+60FC(3) +U+890B(0);U+890B(0); +U+890C(0);U+88C8(4);U+88C8(4) +U+890D(0);U+890D(0); +U+890E(0);U+8896(4);U+8896(4) +U+8910(0);U+8910(5); +U+8911(0);U+8911(3); +U+8912(0);U+8912(5);U+8943(2,3) +U+8913(0);U+8913(5); +U+8914(0);U+526F(4);U+526F(4) +U+8915(0);U+8915(0); +U+8916(0);U+8916(0); +U+8917(0);U+8917(0); +U+8918(0);U+8886(4);U+8886(4) +U+8919(0);U+8919(5); +U+891A(0);U+891A(5); +U+891B(0);U+891B(1,3);U+8938(1,3) +U+891C(0);U+891C(0); +U+891D(0);U+891D(0); +U+891E(0);U+7F0A(4);U+7F0A(4),U+7DFC(0,1,3,4),U+7E15(1,3,4) +U+891F(0);U+891F(0); +U+8920(0);U+8920(0); +U+8921(0);U+8921(5); +U+8922(0);U+6000(3);U+6000(3),U+61F7(1,3),U+61D0(3),U+8931(3) +U+8923(0);U+8923(0); +U+8925(0);U+8925(5); +U+8926(0);U+8926(0); + +U+8927(0);U+8927(4); +U+8928(0);U+8928(0); +U+8929(0);U+8929(0); +U+892A(0);U+892A(5); +U+892B(0);U+892B(5); +U+892C(0);U+892C(0); +U+892D(0);U+8885(3);U+8885(3),U+5ACB(2,3),U+5B1D(2,3),U+88CA(2,3) +U+892E(0);U+892E(0); +U+892F(0);U+892F(0); +U+8930(0);U+8930(5); +U+8931(0);U+6000(3);U+6000(3),U+61F7(1,3),U+61D0(3),U+8922(3) +U+8932(0);U+88E4(1,3);U+88B4(2),U+88E4(1,3) +U+8933(0);U+88E2(1,3);U+88E2(1,3) +U+8934(0);U+8934(1,3);U+7E7F(3),U+8964(1,3) +U+8935(0);U+7F21(3);U+7F21(3),U+7E2D(0,1,3) +U+8936(0);U+8936(5); +U+8937(0);U+8937(0); +U+8938(0);U+891B(1,3);U+891B(1,3) +U+8939(0);U+8939(3); +U+893A(0);U+893A(0); +U+893B(0);U+4EB5(1,3);U+4EB5(1,3) +U+893C(0);U+893C(0); +U+893D(0);U+893D(0); +U+893E(0);U+893E(0); +U+893F(0);U+893F(0); +U+8940(0);U+8940(0); +U+8941(0);U+8941(4); +U+8942(0);U+8942(3); +U+8943(0);U+8912(2,3);U+8912(2,3) +U+8944(0);U+8944(5); +U+8945(0);U+8945(0); +U+8946(0);U+8946(3); +U+8947(0);U+88E5(1,3);U+88E5(1,3),U+8949(1,3) +U+8948(0);U+8948(0); +U+8949(0);U+88E5(3);U+88E5(3),U+8947(1,3) +U+894A(0);U+894A(0); +U+894B(0);U+894B(0); +U+894C(0);U+894C(0); +U+894E(0);U+894E(0); +U+894F(0);U+88AF(4);U+88AF(4) +U+8950(0);U+8950(0); +U+8951(0);U+8951(0); +U+8952(0);U+8952(0); +U+8953(0);U+8953(0); +U+8954(0);U+8954(0); +U+8955(0);U+8955(4);U+5E71(3),U+8974(4) +U+8956(0);U+8884(1,3);U+8884(1,3) +U+8957(0);U+8957(3); +U+8958(0);U+8958(0); +U+8959(0);U+8959(0); +U+895A(0);U+895A(0); +U+895B(0);U+895B(0); +U+895C(0);U+895C(3); +U+895D(0);U+88E3(1,3);U+88E3(1,3) +U+895E(0);U+895E(5); +U+895F(0);U+895F(5); +U+8960(0);U+88C6(1,3);U+88C6(1,3) +U+8961(0);U+8961(3); +U+8962(0);U+8892(2,3);U+8892(2,3) +U+8963(0);U+8963(0); +U+8964(0);U+8934(1,3);U+8934(1,3),U+7E7F(3) +U+8966(0);U+8966(5); +U+8967(0);U+8967(0); + +U+8968(0);U+8968(0); +U+8969(0);U+8969(0); +U+896A(0);U+889C(1,3);U+889C(1,3),U+97C8(2),U+97E4(2) +U+896B(0);U+896B(0); +U+896C(0);U+6446(1,3);U+6446(1,3),U+64FA(4) +U+896D(0);U+896D(3); +U+896E(0);U+896E(0); +U+896F(0);U+886C(1,3);U+886C(1,3) +U+8970(0);U+8970(0); +U+8971(0);U+8971(0); +U+8972(0);U+88AD(1,3);U+88AD(1,3) +U+8973(0);U+8973(0); +U+8974(0);U+8955(4);U+5E71(3),U+8955(4) +U+8976(0);U+8976(0); +U+8977(0);U+8977(0); +U+8978(0);U+8978(0); +U+8979(0);U+8979(0); +U+897A(0);U+897A(3); +U+897B(0);U+897B(5); +U+897C(0);U+897C(0); +U+897E(0);U+897E(0);U+8980(8,9) +U+897F(0);U+897F(5); +U+8980(0);U+8980(0);U+897E(8,9) +U+8981(0);U+8981(5); +U+8982(0);U+8982(0); +U+8983(0);U+8983(5); +U+8984(0);U+8984(0); +U+8985(0);U+8985(0); +U+8986(0);U+8986(5);U+5FA9(3),U+590D(1,3),U+8907(1,3) +U+8987(0);U+9738(2,3);U+9738(2,3) +U+8988(0);U+6838(2,3);U+6838(2,3),U+69C5(2,3,4) +U+8989(0);U+7F81(3);U+7F81(3),U+7F87(8,9),U+7F88(3),U+898A(2,3) +U+898A(0);U+7F81(2,3);U+7F81(2,3),U+7F88(2,3),U+7F87(2,3,4),U+8989(2,3) +U+898B(0);U+89C1(1,3);U+89C1(1,3) +U+898C(0);U+89C2(3);U+89C0(3),U+89C2(3),U+89B3(3) +U+898E(0);U+89C3(1,3);U+89C3(1,3) +U+898F(0);U+89C4(1,3);U+69FC(2),U+89C4(1,3),U+691D(0,2,4) +U+8991(0);U+8991(0); +U+8992(0);U+8992(0); +U+8993(0);U+89C5(1,3);U+89C5(1,3) +U+8995(0);U+77A5(3);U+77A5(3) +U+8996(0);U+89C6(1,3);U+89C6(1,3) +U+8997(0);U+8997(0); +U+8998(0);U+89C7(1,3);U+89C7(1,3) +U+899A(0);U+89C9(4);U+89BA(4),U+89C9(4),U+658D(0,3,4) +U+899B(0);U+899B(0); +U+899C(0);U+773A(2,3);U+773A(2,3) +U+899D(0);U+5EC9(4);U+5EC9(4),U+4EB7(0,2,4) +U+899E(0);U+899E(0); +U+899F(0);U+899F(0); +U+89A0(0);U+89A0(0); +U+89A1(0);U+89CB(1,3);U+89CB(1,3) +U+89A2(0);U+89A2(0); +U+89A3(0);U+89A3(0); +U+89A4(0);U+89A4(0); +U+89A5(0);U+89CD(4);U+89CD(4) +U+89A6(0);U+89CE(1,3);U+89CE(1,3) +U+89A7(0);U+89C8(4);U+89BD(3),U+89C8(4) +U+89A8(0);U+89A8(0); +U+89AA(0);U+4EB2(1,3);U+4EB2(1,3) +U+89AB(0);U+89AB(0); +U+89AC(0);U+89CA(1,3);U+89CA(1,3) +U+89AD(0);U+89AD(0); + +U+89AE(0);U+89AE(0); +U+89AF(0);U+89CF(1,3);U+89CF(1,3) +U+89B1(0);U+89B1(0); +U+89B2(0);U+89D0(1,3);U+89D0(1,3) +U+89B3(0);U+89C2(3);U+89C0(3),U+89C2(3),U+898C(0,3) +U+89B5(0);U+89B5(3);U+89B8(3) +U+89B6(0);U+89B6(0); +U+89B7(0);U+89D1(1,3);U+89D1(1,3) +U+89B8(0);U+89B8(0);U+89B5(3) +U+89B9(0);U+89B9(3); +U+89BA(0);U+89C9(1,3);U+658D(3),U+899A(4),U+89C9(1,3) +U+89BD(0);U+89C8(1,3);U+89A7(3),U+89C8(1,3) +U+89BE(0);U+89BE(0); +U+89BF(0);U+89CC(1,3);U+89CC(1,3) +U+89C0(0);U+89C2(1,3);U+898C(3),U+89B3(3),U+89C2(1,3) +U+89C1(0);U+89C1(1,3);U+898B(1,3) +U+89C2(0);U+89C2(1,3);U+898C(3),U+89B3(3),U+89C0(1,3) +U+89C3(0);U+89C3(1,3);U+898E(1,3) +U+89C4(0);U+89C4(1,3,4);U+691D(4),U+69FC(4),U+898F(1,3) +U+89C5(0);U+89C5(1,3);U+8993(1,3) +U+89C6(0);U+89C6(1,3);U+8996(1,3) +U+89C7(0);U+89C7(1,3);U+8998(1,3) +U+89C8(0);U+89C8(1,3,4);U+89A7(4),U+89BD(1,3) +U+89C9(0);U+89C9(1,3);U+658D(3),U+899A(4),U+89BA(1,3) +U+89CA(0);U+89CA(1,3);U+89AC(1,3) +U+89CB(0);U+89CB(1,3);U+89A1(1,3) +U+89CC(0);U+89CC(1,3);U+89BF(1,3) +U+89CD(0);U+89CD(4);U+89A5(4) +U+89CE(0);U+89CE(1,3);U+89A6(1,3) +U+89CF(0);U+89CF(1,3);U+89AF(1,3) +U+89D0(0);U+89D0(1,3);U+89B2(1,3) +U+89D1(0);U+89D1(1,3);U+89B7(1,3) +U+89D2(0);U+89D2(5); +U+89D3(0);U+89D3(3); +U+89D4(0);U+65A4(2,3);U+65A4(2,3),U+7B4B(3) +U+89D5(0);U+7C97(2,3);U+7C97(2,3),U+850D(2,3),U+9E81(2,3,4),U+9E84(2,3),U+9E86(2,3),U+9EA4(2,3) +U+89D6(0);U+89D6(5); +U+89D7(0);U+89D7(0); +U+89D8(0);U+89D8(0); +U+89D9(0);U+4F0B(3);U+4F0B(3) +U+89DA(0);U+89DA(5); +U+89DB(0);U+89DB(0); +U+89DC(0);U+89DC(5); +U+89DD(0);U+62B5(2);U+627A(3),U+62B5(2),U+7274(4),U+7F9D(2,3) +U+89DE(0);U+89DE(1,3);U+89F4(1,3) +U+89DF(0);U+9C91(1,3,4);U+9C91(1,3,4),U+9BAD(1,3,4) +U+89E0(0);U+89E0(0); +U+89E1(0);U+89E1(0); +U+89E2(0);U+89E2(3); +U+89E3(0);U+89E3(5);U+89E7(3) +U+89E4(0);U+89E4(0); +U+89E5(0);U+89E5(5); +U+89E6(0);U+89E6(1,3);U+89F8(1,3) +U+89E7(0);U+89E3(3);U+89E3(3) +U+89E8(0);U+89E8(0); +U+89E9(0);U+89E9(4); +U+89EA(0);U+89EA(0);U+89F2(3) +U+89EB(0);U+89EB(5); +U+89EC(0);U+89EC(0); +U+89ED(0);U+89ED(0); +U+89EF(0);U+89EF(4);U+89F6(4) +U+89F0(0);U+89F0(0); + +U+89F1(0);U+89F1(0); +U+89F2(0);U+89EA(3);U+89EA(3) +U+89F3(0);U+89F3(5); +U+89F4(0);U+89DE(1,3);U+89DE(1,3) +U+89F6(0);U+89EF(4);U+89EF(4) +U+89F7(0);U+89F7(3); +U+89F8(0);U+89E6(1,3);U+89E6(1,3) +U+89FA(0);U+89FA(0); +U+89FB(0);U+89FB(0); +U+89FC(0);U+89FC(0); +U+89FE(0);U+71D5(3);U+71D5(3),U+9DF0(2,3) +U+89FF(0);U+89FF(3); +U+8A00(0);U+8A00(5);U+8A01(8,9),U+8BA0(8,9) +U+8A01(0);U+8BA0(4);U+8A00(8,9),U+8BA0(4) +U+8A02(0);U+8BA2(1,3);U+8BA2(1,3) +U+8A03(0);U+8BA3(1,3);U+8BA3(1,3) +U+8A04(0);U+8A04(3); +U+8A07(0);U+8A07(5); +U+8A08(0);U+8BA1(1,3);U+8BA1(1,3) +U+8A09(0);U+8A09(0); +U+8A0A(0);U+8BAF(1,3);U+8BAF(1,3) +U+8A0B(0);U+8A0B(0); +U+8A0C(0);U+8BA7(1,3);U+8BA7(1,3) +U+8A0D(0);U+8A0D(0); +U+8A0E(0);U+8BA8(1,3);U+8BA8(1,3) +U+8A0F(0);U+8A0F(0); +U+8A10(0);U+8BA6(1,3);U+8BA6(1,3) +U+8A11(0);U+8A11(0); +U+8A12(0);U+8BB1(4);U+8BB1(4) +U+8A13(0);U+8BAD(1,3);U+8BAD(1,3) +U+8A15(0);U+8BAA(1,3);U+8BAA(1,3) +U+8A16(0);U+8BAB(1,3);U+8BAB(1,3) +U+8A17(0);U+6258(2,4);U+6258(2,4),U+8BAC(4) +U+8A18(0);U+8BB0(1,3);U+8BB0(1,3) +U+8A1A(0);U+8A1A(4);U+8ABE(4) +U+8A1B(0);U+8BB9(1,3);U+8B4C(2),U+8BB9(1,3) +U+8A1C(0);U+8A1C(0); +U+8A1D(0);U+8BB6(1,3);U+8BB6(1,3) +U+8A1E(0);U+5996(3);U+5996(3),U+7945(3) +U+8A1F(0);U+8BBC(1,3);U+8BBC(1,3) +U+8A22(0);U+4723(1,3);U+4723(1,3) +U+8A23(0);U+8BC0(1,3);U+8BC0(1,3) +U+8A24(0);U+8A24(3); +U+8A25(0);U+8BB7(1,3);U+8BB7(1,3) +U+8A26(0);U+8A26(0); +U+8A27(0);U+5C24(3);U+5C24(3) +U+8A28(0);U+8A28(0); +U+8A29(0);U+8BBB(1,3);U+8BBB(1,3),U+54C5(0,1,3) +U+8A2A(0);U+8BBF(1,3);U+8BBF(1,3) +U+8A2C(0);U+8A2C(3); +U+8A2D(0);U+8BBE(1,3);U+8BBE(1,3) +U+8A2E(0);U+8A2E(0); +U+8A2F(0);U+8A2F(0); +U+8A30(0);U+8C06(4);U+8C06(4),U+8AC4(1,3,4) +U+8A31(0);U+8BB8(1,3);U+8BB8(1,3),U+9126(1,3) +U+8A32(0);U+8A32(0); +U+8A34(0);U+8BC9(1,3);U+8BC9(1,3),U+612C(2,3) +U+8A35(0);U+8A35(3); +U+8A36(0);U+8BC3(1,3);U+5475(3,4),U+8BC3(1,3),U+55EC(3,4) +U+8A37(0);U+8A37(0); +U+8A38(0);U+8A38(0); +U+8A39(0);U+8A39(0); +U+8A3A(0);U+8BCA(1,3);U+8BCA(1,3) + +U+8A3B(0);U+6CE8(2,3);U+6CE8(2,3) +U+8A3C(0);U+8BC1(4);U+8B49(3),U+8BC1(4) +U+8A3E(0);U+8A3E(5);U+8A3F(3) +U+8A3F(0);U+8A3E(3);U+8A3E(3) +U+8A40(0);U+8A40(3); +U+8A41(0);U+8BC2(1,3);U+8BC2(1,3) +U+8A42(0);U+8A42(0); +U+8A43(0);U+8A43(0); +U+8A44(0);U+8A44(0); +U+8A45(0);U+8A45(0); +U+8A46(0);U+8BCB(1,3);U+8BCB(1,3),U+5467(0,1,3) +U+8A47(0);U+8A47(0); +U+8A48(0);U+8A48(5); +U+8A49(0);U+8A49(3); +U+8A4A(0);U+8A4A(0); +U+8A4C(0);U+8A4C(0); +U+8A4D(0);U+8A4D(0); +U+8A4E(0);U+8BB5(1,3);U+8BB5(1,3) +U+8A4F(0);U+8A4F(0); +U+8A50(0);U+8BC8(1,3);U+8BC8(1,3) +U+8A51(0);U+8A51(3); +U+8A52(0);U+8BD2(1,3);U+8BD2(1,3) +U+8A53(0);U+8A53(0); +U+8A54(0);U+8BCF(1,3);U+8BCF(1,3) +U+8A55(0);U+8BC4(1,3);U+8BC4(1,3) +U+8A56(0);U+8BD0(4);U+8BD0(4) +U+8A57(0);U+8BC7(1,3);U+8BC7(1,3) +U+8A58(0);U+8BCE(1,3);U+8BCE(1,3) +U+8A59(0);U+8A59(0); +U+8A5A(0);U+8A5A(0); +U+8A5B(0);U+8BC5(1,3);U+8BC5(1,3),U+8B2F(1,3) +U+8A5C(0);U+8A5C(0); +U+8A5D(0);U+8A5D(0); +U+8A5E(0);U+8BCD(1,3);U+8BCD(1,3) +U+8A5F(0);U+8A5F(1,3);U+8B8B(1,3) +U+8A60(0);U+548F(2,3);U+548F(2,3) +U+8A61(0);U+8BE9(1,3);U+8BE9(1,3) +U+8A62(0);U+8BE2(1,3);U+8BE2(1,3) +U+8A63(0);U+8BE3(1,3);U+8BE3(1,3) +U+8A65(0);U+8A65(0); +U+8A66(0);U+8BD5(1,3);U+8BD5(1,3) +U+8A67(0);U+5BDF(2);U+5BDF(2) +U+8A68(0);U+8A68(3); +U+8A69(0);U+8BD7(1,3);U+8BD7(1,3) +U+8A6A(0);U+8A6A(0); +U+8A6B(0);U+8BE7(1,3);U+8BE7(1,3),U+4F98(0,1,3) +U+8A6C(0);U+8BDF(1,3);U+8BDF(1,3) +U+8A6D(0);U+8BE1(1,3);U+8BE1(1,3) +U+8A6E(0);U+8BE0(1,3);U+8BE0(1,3) +U+8A6F(0);U+8A6F(0); +U+8A70(0);U+8BD8(1,3);U+8BD8(1,3) +U+8A71(0);U+8BDD(1,3);U+8BDD(1,3),U+8AD9(1,3) +U+8A72(0);U+8BE5(1,3);U+8BE5(1,3) +U+8A73(0);U+8BE6(1,3);U+8BE6(1,3) +U+8A74(0);U+8A74(0); +U+8A75(0);U+8BDC(4);U+8BDC(4) +U+8A76(0);U+916C(2,3);U+916C(2,3),U+9167(2,3),U+91BB(2,3) +U+8A77(0);U+8A77(0); +U+8A79(0);U+8A79(5); +U+8A7A(0);U+8A7A(3); +U+8A7B(0);U+8A7B(0);U+54AF(3) +U+8A7C(0);U+8BD9(1,3);U+8BD9(1,3) +U+8A7E(0);U+8A7E(0); + +U+8A7F(0);U+8BD6(1,3);U+8BD6(1,3) +U+8A80(0);U+8A80(0); +U+8A81(0);U+8A81(0); +U+8A82(0);U+8A82(0); +U+8A83(0);U+8A83(3); +U+8A84(0);U+8BD4(1,3);U+8BD4(1,3) +U+8A85(0);U+8BDB(1,3);U+8BDB(1,3) +U+8A86(0);U+8BD3(1,3);U+8BD3(1,3) +U+8A87(0);U+5938(1,3);U+5938(1,3) +U+8A89(0);U+8A89(1,3);U+8B7D(1,3) +U+8A8A(0);U+8A8A(1,3);U+8B04(1,3) +U+8A8B(0);U+5FCC(3);U+5FCC(3),U+8AC5(3) +U+8A8C(0);U+5FD7(2,3);U+5FD7(2,3) +U+8A8D(0);U+8BA4(1,3);U+8BA4(1,3) +U+8A8E(0);U+8A8E(0); +U+8A8F(0);U+8A8F(0); +U+8A90(0);U+8A90(0); +U+8A91(0);U+8BF3(1,3);U+8BF3(1,3) +U+8A92(0);U+8BF6(1,3);U+6B38(4),U+8BF6(1,3) +U+8A93(0);U+8A93(5); +U+8A94(0);U+8A94(0); +U+8A95(0);U+8BDE(1,3);U+8BDE(1,3) +U+8A96(0);U+6096(2,3);U+6096(2,3) +U+8A97(0);U+8A97(0); +U+8A98(0);U+8BF1(1,3);U+8BF1(1,3) +U+8A99(0);U+8A99(0); +U+8A9A(0);U+8BEE(1,3);U+8BEE(1,3) +U+8A9B(0);U+8A9B(0); +U+8A9C(0);U+8A9C(3); +U+8A9D(0);U+8A9D(0); +U+8A9E(0);U+8BED(1,3);U+8BED(1,3) +U+8AA0(0);U+8BDA(1,3);U+8BDA(1,3) +U+8AA1(0);U+8BEB(1,3);U+8BEB(1,3) +U+8AA2(0);U+8AA2(0); +U+8AA3(0);U+8BEC(1,3);U+8BEC(1,3) +U+8AA4(0);U+8BEF(1,3);U+609E(3),U+60AE(4),U+8BEF(1,3) +U+8AA5(0);U+8BF0(1,3);U+8BF0(1,3) +U+8AA6(0);U+8BF5(1,3);U+8BF5(1,3) +U+8AA7(0);U+8AA7(0); +U+8AA8(0);U+8BF2(1,3);U+8BF2(1,3) +U+8AA9(0);U+8AA9(0); +U+8AAA(0);U+8BF4(4);U+8AAC(8,9),U+8BF4(4) +U+8AAB(0);U+9707(3);U+9707(3) +U+8AAC(0);U+8BF4(1,3);U+8AAA(8,9),U+8BF4(1,3) +U+8AAE(0);U+8AAE(0); +U+8AB0(0);U+8C01(1,3);U+8C01(1,3) +U+8AB1(0);U+8AB1(0); +U+8AB2(0);U+8BFE(1,3);U+8BFE(1,3) +U+8AB3(0);U+8AB3(0); +U+8AB4(0);U+8AB4(0); +U+8AB5(0);U+8AB5(3); +U+8AB6(0);U+8C07(1,3);U+8C07(1,3) +U+8AB8(0);U+8AB8(0); +U+8AB9(0);U+8BFD(1,3);U+8BFD(1,3) +U+8ABA(0);U+8ABA(0); +U+8ABB(0);U+8ABB(0); +U+8ABC(0);U+8C0A(1,3);U+8C0A(1,3) +U+8ABD(0);U+8ABD(0); +U+8ABE(0);U+8A1A(4);U+8A1A(4) +U+8ABF(0);U+8C03(1,3);U+8C03(1,3) +U+8AC0(0);U+8AC0(3); +U+8AC1(0);U+8AC1(3); +U+8AC2(0);U+8C04(1,3);U+8C04(1,3) + +U+8AC3(0);U+8AC3(0); +U+8AC4(0);U+8C06(1,3);U+8C06(1,3),U+8A30(0,1,3,4) +U+8AC5(0);U+5FCC(3);U+5FCC(3),U+8A8B(3) +U+8AC6(0);U+8AC6(0); +U+8AC7(0);U+8C08(1,3);U+8C08(1,3) +U+8AC8(0);U+8AC8(3); +U+8AC9(0);U+8BFF(1,3);U+8BFF(1,3) +U+8ACA(0);U+8ACA(0); +U+8ACB(0);U+8BF7(1,3);U+8BF7(1,3) +U+8ACC(0);U+8C0F(4);U+8AEB(4),U+8C0F(4) +U+8ACD(0);U+8BE4(1,3);U+8BE4(1,3) +U+8ACE(0);U+8ACE(3); +U+8ACF(0);U+8BF9(1,3);U+8BF9(1,3) +U+8AD1(0);U+8BFC(1,3);U+8BFC(1,3) +U+8AD2(0);U+8C05(1,3);U+8C05(1,3) +U+8AD3(0);U+8AD3(0); +U+8AD4(0);U+8AD4(0); +U+8AD5(0);U+8AD5(3); +U+8AD6(0);U+8BBA(1,3);U+8BBA(1,3) +U+8AD7(0);U+8C02(1,3);U+8C02(1,3) +U+8AD8(0);U+8AD8(0); +U+8AD9(0);U+8BDD(3);U+8BDD(3),U+8A71(0,1,3) +U+8ADA(0);U+8ADA(0); +U+8ADB(0);U+8C00(1,3);U+8C00(1,3) +U+8ADC(0);U+8C0D(1,3);U+8C0D(1,3) +U+8ADD(0);U+8C1E(1,3);U+8C1E(1,3) +U+8ADE(0);U+8C1D(1,3);U+8C1D(1,3) +U+8ADF(0);U+8ADF(3); +U+8AE0(0);U+55A7(2,3);U+55A7(2,3),U+5405(0,2,3) +U+8AE1(0);U+8C25(4);U+8C25(4),U+8B1A(1,3,4) +U+8AE2(0);U+8BE8(1,3);U+8BE8(1,3),U+9850(1,3) +U+8AE3(0);U+8AE3(0); +U+8AE4(0);U+8C14(1,3);U+8C14(1,3) +U+8AE5(0);U+8AE5(0); +U+8AE6(0);U+8C1B(1,3);U+8C1B(1,3) +U+8AE7(0);U+8C10(1,3);U+8C10(1,3) +U+8AE8(0);U+8AE8(0); +U+8AE9(0);U+8C31(3);U+8B5C(3),U+8C31(3) +U+8AEA(0);U+8AEA(0); +U+8AEB(0);U+8C0F(1,3);U+8ACC(4),U+8C0F(1,3) +U+8AED(0);U+8C15(1,3);U+8C15(1,3) +U+8AEE(0);U+8C18(1,3);U+54A8(3),U+8C18(1,3) +U+8AEF(0);U+8AEF(0); +U+8AF0(0);U+8AF0(0); +U+8AF1(0);U+8BB3(1,3);U+8BB3(1,3) +U+8AF2(0);U+8AF2(0); +U+8AF3(0);U+8C19(1,3);U+8C19(1,3) +U+8AF4(0);U+8AF4(0); +U+8AF5(0);U+5583(3);U+5583(3),U+5A1A(3) +U+8AF6(0);U+8C0C(1,3);U+8C0C(1,3) +U+8AF7(0);U+8BBD(1,3);U+8BBD(1,3) +U+8AF8(0);U+8BF8(1,3);U+8BF8(1,3) +U+8AF9(0);U+8AF9(0); +U+8AFA(0);U+8C1A(1,3);U+8C1A(1,3) +U+8AFB(0);U+8AFB(0); +U+8AFC(0);U+8C16(1,3);U+8C16(1,3) +U+8AFD(0);U+8AFD(3); +U+8AFE(0);U+8BFA(1,3);U+8BFA(1,3) +U+8AFF(0);U+8AFF(0); +U+8B00(0);U+8C0B(1,3);U+8C0B(1,3) +U+8B01(0);U+8C12(1,3);U+8C12(1,3) +U+8B02(0);U+8C13(1,3);U+8C13(1,3) +U+8B03(0);U+8B03(0); + +U+8B04(0);U+8A8A(1,3);U+8A8A(1,3) +U+8B05(0);U+8BCC(1,3);U+8BCC(1,3) +U+8B06(0);U+8B06(0); +U+8B07(0);U+8B07(5); +U+8B08(0);U+8B08(0); +U+8B09(0);U+8B09(0); +U+8B0A(0);U+8C0E(1,3);U+8C0E(1,3) +U+8B0B(0);U+8B0B(3); +U+8B0D(0);U+8B0D(3); +U+8B0E(0);U+8C1C(1,3);U+8C1C(1,3) +U+8B0F(0);U+8B0F(0); +U+8B10(0);U+8C27(1,3);U+8C27(1,3) +U+8B11(0);U+8B11(0); +U+8B12(0);U+8B12(0); +U+8B13(0);U+8B13(3); +U+8B14(0);U+8C11(1,3);U+8C11(1,3) +U+8B15(0);U+557C(3);U+557C(3) +U+8B16(0);U+8C21(1,3);U+8C21(1,3) +U+8B17(0);U+8C24(1,3);U+8C24(1,3) +U+8B18(0);U+8B18(0); +U+8B19(0);U+8C26(1,3);U+8C26(1,3) +U+8B1A(0);U+8C25(1,3);U+8C25(1,3),U+8AE1(0,1,3,4) +U+8B1B(0);U+8BB2(1,3);U+8BB2(1,3) +U+8B1C(0);U+8B1C(0); +U+8B1D(0);U+8C22(1,3);U+8C22(1,3) +U+8B1E(0);U+8B1E(0); +U+8B1F(0);U+8B1F(0); +U+8B20(0);U+8C23(4);U+8B21(4),U+8C23(4) +U+8B21(0);U+8C23(1,3);U+8B20(4),U+8C23(1,3) +U+8B22(0);U+8B22(0); +U+8B23(0);U+8B23(3); +U+8B24(0);U+8B24(0); +U+8B25(0);U+8B25(0); +U+8B26(0);U+8B26(5); +U+8B27(0);U+8B27(0); +U+8B28(0);U+8C1F(1,3);U+8C1F(1,3),U+8B55(1,3) +U+8B2A(0);U+5546(3);U+5546(3) +U+8B2B(0);U+8C2A(1,3);U+8C2A(1,3) +U+8B2C(0);U+8C2C(1,3);U+8C2C(1,3) +U+8B2D(0);U+8C2B(1,3);U+8B7E(3),U+8C2B(1,3) +U+8B2E(0);U+8B2E(0); +U+8B2F(0);U+8BC5(3);U+8BC5(3),U+8A5B(0,1,3) +U+8B30(0);U+8B30(0); +U+8B31(0);U+8B31(0); +U+8B33(0);U+8BB4(1,3);U+8BB4(1,3) +U+8B34(0);U+8B34(0); +U+8B35(0);U+8B35(0); +U+8B36(0);U+5EB6(3);U+5EB6(3),U+5EBB(2,3) +U+8B37(0);U+8B37(3); +U+8B39(0);U+8C28(1,3);U+8C28(1,3) +U+8B3A(0);U+8B3A(0); +U+8B3B(0);U+8B3B(3); +U+8B3C(0);U+547C(2,3);U+547C(2,3),U+5611(2,3),U+8656(2,3) +U+8B3D(0);U+8B3D(0); +U+8B3E(0);U+8C29(1,3);U+8C29(1,3) +U+8B40(0);U+8B40(0); +U+8B41(0);U+54D7(2,3,4);U+54D7(2,3,4),U+5629(2,3) +U+8B42(0);U+8B42(0); +U+8B43(0);U+8B43(0); +U+8B44(0);U+8B44(0); +U+8B45(0);U+8B45(0); +U+8B46(0);U+563B(2);U+563B(2) +U+8B47(0);U+8B47(0); + +U+8B48(0);U+619D(3);U+619D(3) +U+8B49(0);U+8BC1(1,3);U+8A3C(3),U+8BC1(1,3) +U+8B4A(0);U+8B4A(0); +U+8B4B(0);U+8C30(3);U+8C30(3),U+8B95(1,3) +U+8B4C(0);U+8BB9(4);U+8A1B(2),U+8BB9(4) +U+8B4D(0);U+5E94(1,3,4);U+5E94(1,3,4),U+5FDC(4),U+61C9(1,3,4) +U+8B4E(0);U+8C32(1,3);U+8C32(1,3),U+564A(0,1,3) +U+8B4F(0);U+8BA5(1,3);U+8BA5(1,3) +U+8B50(0);U+5642(3);U+5642(3) +U+8B51(0);U+6322(4);U+6322(4),U+649F(1,3,4) +U+8B52(0);U+8B52(0); +U+8B53(0);U+8B53(3); +U+8B54(0);U+64B0(2,3);U+64B0(2,3) +U+8B55(0);U+8C1F(3);U+8C1F(3),U+8B28(0,1,3) +U+8B56(0);U+8C2E(1,3);U+8C2E(1,3) +U+8B57(0);U+8B57(0); +U+8B58(0);U+8BC6(1,3);U+8BC6(1,3) +U+8B59(0);U+8C2F(1,3);U+8C2F(1,3) +U+8B5A(0);U+8C2D(1,3);U+8C2D(1,3) +U+8B5B(0);U+8B5B(0); +U+8B5C(0);U+8C31(1,3);U+8AE9(3),U+8C31(1,3) +U+8B5D(0);U+8B5D(3); +U+8B5E(0);U+8B5E(0); +U+8B5F(0);U+566A(2,3);U+566A(2,3) +U+8B60(0);U+8B60(0); +U+8B63(0);U+8B63(0); +U+8B64(0);U+8B64(0); +U+8B65(0);U+8B65(0); +U+8B66(0);U+8B66(5); +U+8B67(0);U+8B67(0); +U+8B68(0);U+8B68(0); +U+8B6A(0);U+853C(3);U+853C(3),U+85F9(1,3) +U+8B6B(0);U+8C35(1,3);U+8C35(1,3) +U+8B6C(0);U+8B6C(5); +U+8B6D(0);U+6BC1(2,3);U+6BC1(2,3),U+6BC0(0,2,3,4) +U+8B6E(0);U+8B6E(3); +U+8B6F(0);U+8BD1(1,3);U+8BD1(1,3) +U+8B70(0);U+8BAE(1,3);U+8BAE(1,3) +U+8B71(0);U+5584(3);U+5584(3) +U+8B73(0);U+8B73(0); +U+8B74(0);U+8C34(1,3);U+8C34(1,3) +U+8B76(0);U+8B76(0); +U+8B77(0);U+62A4(1,3);U+62A4(1,3) +U+8B78(0);U+8BEA(4);U+8BEA(4) +U+8B79(0);U+53F7(3);U+53F7(3),U+865F(1,3) +U+8B7A(0);U+8B7A(0); +U+8B7B(0);U+5624(3);U+5624(3),U+56B6(1,3) +U+8B7D(0);U+8A89(1,3);U+8A89(1,3) +U+8B7E(0);U+8C2B(4);U+8B2D(3),U+8C2B(4) +U+8B7F(0);U+6167(3);U+6167(3) +U+8B80(0);U+8BFB(1,3);U+8BFB(1,3) +U+8B82(0);U+8B82(0); +U+8B83(0);U+8D5E(3,4);U+8B9A(3),U+8D5E(3,4),U+8D0A(2,3),U+8CDB(3,4) +U+8B84(0);U+8B84(0); +U+8B85(0);U+8C09(1,3);U+8C09(1,3) +U+8B86(0);U+8B86(0); +U+8B88(0);U+8B88(0); +U+8B89(0);U+8B89(0); +U+8B8A(0);U+53D8(1,3);U+5909(3),U+53D8(1,3) +U+8B8B(0);U+8A5F(1,3);U+8A5F(1,3) +U+8B8C(0);U+4729(1,3);U+4729(1,3) +U+8B8E(0);U+96E0(1,3),U+4EC7(3);U+4EC7(3),U+8B90(3),U+96E0(1,3) +U+8B90(0);U+96E0(1,3);U+4EC7(2),U+8B8E(3),U+96E0(1,3) + +U+8B91(0);U+8B91(3); +U+8B92(0);U+8C17(1,3);U+8C17(1,3) +U+8B93(0);U+8BA9(1,3);U+8BA9(1,3) +U+8B94(0);U+8B94(0); +U+8B95(0);U+8C30(1,3);U+8C30(1,3),U+8B4B(0,1,3) +U+8B96(0);U+8C36(1,3);U+8C36(1,3) +U+8B97(0);U+8B97(0); +U+8B98(0);U+8B98(3); +U+8B99(0);U+6B22(4);U+6B22(4),U+6B61(2),U+61FD(0,4),U+6B53(3,4),U+9A69(4) +U+8B9A(0);U+8D5E(4);U+8B83(3),U+8D0A(2),U+8D5E(4),U+8CDB(3,4) +U+8B9C(0);U+8C20(1,3);U+8C20(1,3) +U+8B9D(0);U+8B9D(0); +U+8B9E(0);U+8C33(1,3);U+8C33(1,3) +U+8B9F(0);U+8B9F(3); +U+8BA0(0);U+8BA0(4);U+8A00(8,9),U+8A01(4) +U+8BA1(0);U+8BA1(1,3);U+8A08(1,3) +U+8BA2(0);U+8BA2(1,3);U+8A02(1,3) +U+8BA3(0);U+8BA3(1,3);U+8A03(1,3) +U+8BA4(0);U+8BA4(1,3);U+8A8D(1,3) +U+8BA5(0);U+8BA5(1,3);U+8B4F(1,3) +U+8BA6(0);U+8BA6(1,3);U+8A10(1,3) +U+8BA7(0);U+8BA7(1,3);U+8A0C(1,3) +U+8BA8(0);U+8BA8(1,3);U+8A0E(1,3) +U+8BA9(0);U+8BA9(1,3);U+8B93(1,3) +U+8BAA(0);U+8BAA(1,3);U+8A15(1,3) +U+8BAB(0);U+8BAB(1,3);U+8A16(1,3) +U+8BAC(0);U+6258(4);U+6258(4),U+8A17(4) +U+8BAD(0);U+8BAD(1,3);U+8A13(1,3) +U+8BAE(0);U+8BAE(1,3);U+8B70(1,3) +U+8BAF(0);U+8BAF(1,3);U+8A0A(1,3) +U+8BB0(0);U+8BB0(1,3);U+8A18(1,3) +U+8BB1(0);U+8BB1(4);U+8A12(4) +U+8BB2(0);U+8BB2(1,3);U+8B1B(1,3) +U+8BB3(0);U+8BB3(1,3);U+8AF1(1,3) +U+8BB4(0);U+8BB4(1,3);U+8B33(1,3) +U+8BB5(0);U+8BB5(1,3);U+8A4E(1,3) +U+8BB6(0);U+8BB6(1,3);U+8A1D(1,3) +U+8BB7(0);U+8BB7(1,3);U+8A25(1,3) +U+8BB8(0);U+8BB8(1,3);U+8A31(1,3),U+9126(3) +U+8BB9(0);U+8BB9(1,3);U+8A1B(1,3),U+8B4C(4) +U+8BBA(0);U+8BBA(1,3);U+8AD6(1,3) +U+8BBB(0);U+8BBB(1,3);U+54C5(3),U+8A29(1,3) +U+8BBC(0);U+8BBC(1,3);U+8A1F(1,3) +U+8BBD(0);U+8BBD(1,3);U+8AF7(1,3) +U+8BBE(0);U+8BBE(1,3);U+8A2D(1,3) +U+8BBF(0);U+8BBF(1,3);U+8A2A(1,3) +U+8BC0(0);U+8BC0(1,3);U+8A23(1,3) +U+8BC1(0);U+8BC1(1,3,4);U+8A3C(4),U+8B49(1,3) +U+8BC2(0);U+8BC2(1,3);U+8A41(1,3) +U+8BC3(0);U+8BC3(1,3);U+8A36(1,3),U+5475(1,3,4,5),U+55EC(1,3,4) +U+8BC4(0);U+8BC4(1,3);U+8A55(1,3) +U+8BC5(0);U+8BC5(1,3);U+8A5B(1,3),U+8B2F(3) +U+8BC6(0);U+8BC6(1,3);U+8B58(1,3) +U+8BC7(0);U+8BC7(1,3);U+8A57(1,3) +U+8BC8(0);U+8BC8(1,3);U+8A50(1,3) +U+8BC9(0);U+8BC9(1,3);U+612C(3),U+8A34(1,3) +U+8BCA(0);U+8BCA(1,3);U+8A3A(1,3) +U+8BCB(0);U+8BCB(1,3);U+5467(3),U+8A46(1,3) +U+8BCC(0);U+8BCC(1,3);U+8B05(1,3) +U+8BCD(0);U+8BCD(1,3);U+8A5E(1,3) +U+8BCE(0);U+8BCE(1,3);U+8A58(1,3) +U+8BCF(0);U+8BCF(1,3);U+8A54(1,3) +U+8BD0(0);U+8BD0(4);U+8A56(4) + +U+8BD1(0);U+8BD1(1,3);U+8B6F(1,3) +U+8BD2(0);U+8BD2(1,3);U+8A52(1,3) +U+8BD3(0);U+8BD3(1,3);U+8A86(1,3) +U+8BD4(0);U+8BD4(1,3);U+8A84(1,3) +U+8BD5(0);U+8BD5(1,3);U+8A66(1,3) +U+8BD6(0);U+8BD6(1,3);U+8A7F(1,3) +U+8BD7(0);U+8BD7(1,3);U+8A69(1,3) +U+8BD8(0);U+8BD8(1,3);U+8A70(1,3) +U+8BD9(0);U+8BD9(1,3);U+8A7C(1,3) +U+8BDA(0);U+8BDA(1,3);U+8AA0(1,3) +U+8BDB(0);U+8BDB(1,3);U+8A85(1,3) +U+8BDC(0);U+8BDC(4);U+8A75(4) +U+8BDD(0);U+8BDD(1,3);U+8A71(1,3),U+8AD9(3) +U+8BDE(0);U+8BDE(1,3);U+8A95(1,3) +U+8BDF(0);U+8BDF(1,3);U+8A6C(1,3) +U+8BE0(0);U+8BE0(1,3);U+8A6E(1,3) +U+8BE1(0);U+8BE1(1,3);U+8A6D(1,3) +U+8BE2(0);U+8BE2(1,3);U+8A62(1,3) +U+8BE3(0);U+8BE3(1,3);U+8A63(1,3) +U+8BE4(0);U+8BE4(1,3);U+8ACD(1,3) +U+8BE5(0);U+8BE5(1,3);U+8A72(1,3) +U+8BE6(0);U+8BE6(1,3);U+8A73(1,3) +U+8BE7(0);U+8BE7(1,3);U+4F98(3),U+8A6B(1,3) +U+8BE8(0);U+8BE8(1,3);U+8AE2(1,3),U+9850(3) +U+8BE9(0);U+8BE9(1,3);U+8A61(1,3) +U+8BEA(0);U+8BEA(4);U+8B78(4) +U+8BEB(0);U+8BEB(1,3);U+8AA1(1,3) +U+8BEC(0);U+8BEC(1,3);U+8AA3(1,3) +U+8BED(0);U+8BED(1,3);U+8A9E(1,3) +U+8BEE(0);U+8BEE(1,3);U+8A9A(1,3) +U+8BEF(0);U+8BEF(1,3,4);U+609E(3),U+60AE(4),U+8AA4(1,3) +U+8BF0(0);U+8BF0(1,3);U+8AA5(1,3) +U+8BF1(0);U+8BF1(1,3);U+8A98(1,3) +U+8BF2(0);U+8BF2(1,3);U+8AA8(1,3) +U+8BF3(0);U+8BF3(1,3);U+8A91(1,3) +U+8BF4(0);U+8BF4(1,3,4);U+8AAA(4),U+8AAC(1,3) +U+8BF5(0);U+8BF5(1,3);U+8AA6(1,3) +U+8BF6(0);U+8BF6(1,3);U+8A92(1,3),U+6B38(1,3,4) +U+8BF7(0);U+8BF7(1,3);U+8ACB(1,3) +U+8BF8(0);U+8BF8(1,3);U+8AF8(1,3) +U+8BF9(0);U+8BF9(1,3);U+8ACF(1,3) +U+8BFA(0);U+8BFA(1,3);U+8AFE(1,3) +U+8BFB(0);U+8BFB(1,3);U+8B80(1,3) +U+8BFC(0);U+8BFC(1,3);U+8AD1(1,3) +U+8BFD(0);U+8BFD(1,3);U+8AB9(1,3) +U+8BFE(0);U+8BFE(1,3);U+8AB2(1,3) +U+8BFF(0);U+8BFF(1,3);U+8AC9(1,3) +U+8C00(0);U+8C00(1,3);U+8ADB(1,3) +U+8C01(0);U+8C01(1,3);U+8AB0(1,3) +U+8C02(0);U+8C02(1,3);U+8AD7(1,3) +U+8C03(0);U+8C03(1,3);U+8ABF(1,3) +U+8C04(0);U+8C04(1,3);U+8AC2(1,3) +U+8C05(0);U+8C05(1,3);U+8AD2(1,3) +U+8C06(0);U+8C06(1,3);U+8A30(4),U+8AC4(1,3) +U+8C07(0);U+8C07(1,3);U+8AB6(1,3) +U+8C08(0);U+8C08(1,3);U+8AC7(1,3) +U+8C09(0);U+8C09(1,3);U+8B85(1,3) +U+8C0A(0);U+8C0A(1,3);U+8ABC(1,3) +U+8C0B(0);U+8C0B(1,3);U+8B00(1,3) +U+8C0C(0);U+8C0C(1,3);U+8AF6(1,3) +U+8C0D(0);U+8C0D(1,3);U+8ADC(1,3) +U+8C0E(0);U+8C0E(1,3);U+8B0A(1,3) +U+8C0F(0);U+8C0F(1,3);U+8ACC(4),U+8AEB(1,3) + +U+8C10(0);U+8C10(1,3);U+8AE7(1,3) +U+8C11(0);U+8C11(1,3);U+8B14(1,3) +U+8C12(0);U+8C12(1,3);U+8B01(1,3) +U+8C13(0);U+8C13(1,3);U+8B02(1,3) +U+8C14(0);U+8C14(1,3);U+8AE4(1,3) +U+8C15(0);U+8C15(1,3);U+8AED(1,3) +U+8C16(0);U+8C16(1,3);U+8AFC(1,3) +U+8C17(0);U+8C17(1,3);U+8B92(1,3) +U+8C18(0);U+8C18(1,3);U+8AEE(1,3),U+54A8(1,3,5) +U+8C19(0);U+8C19(1,3);U+8AF3(1,3) +U+8C1A(0);U+8C1A(1,3);U+8AFA(1,3) +U+8C1B(0);U+8C1B(1,3);U+8AE6(1,3) +U+8C1C(0);U+8C1C(1,3);U+8B0E(1,3) +U+8C1D(0);U+8C1D(1,3);U+8ADE(1,3) +U+8C1E(0);U+8C1E(1,3);U+8ADD(1,3) +U+8C1F(0);U+8C1F(1,3);U+8B28(1,3),U+8B55(3) +U+8C20(0);U+8C20(1,3);U+8B9C(1,3) +U+8C21(0);U+8C21(1,3);U+8B16(1,3) +U+8C22(0);U+8C22(1,3);U+8B1D(1,3) +U+8C23(0);U+8C23(1,3,4);U+8B20(4),U+8B21(1,3) +U+8C24(0);U+8C24(1,3);U+8B17(1,3) +U+8C25(0);U+8C25(1,3);U+8AE1(4),U+8B1A(1,3) +U+8C26(0);U+8C26(1,3);U+8B19(1,3) +U+8C27(0);U+8C27(1,3);U+8B10(1,3) +U+8C28(0);U+8C28(1,3);U+8B39(1,3) +U+8C29(0);U+8C29(1,3);U+8B3E(1,3) +U+8C2A(0);U+8C2A(1,3);U+8B2B(1,3) +U+8C2B(0);U+8C2B(1,3,4);U+8B2D(1,3),U+8B7E(4) +U+8C2C(0);U+8C2C(1,3);U+8B2C(1,3) +U+8C2D(0);U+8C2D(1,3);U+8B5A(1,3) +U+8C2E(0);U+8C2E(1,3);U+8B56(1,3) +U+8C2F(0);U+8C2F(1,3);U+8B59(1,3) +U+8C30(0);U+8C30(1,3);U+8B4B(3),U+8B95(1,3) +U+8C31(0);U+8C31(1,3);U+8AE9(3),U+8B5C(1,3) +U+8C32(0);U+8C32(1,3);U+564A(3),U+8B4E(1,3) +U+8C33(0);U+8C33(1,3);U+8B9E(1,3) +U+8C34(0);U+8C34(1,3);U+8B74(1,3) +U+8C35(0);U+8C35(1,3);U+8B6B(1,3) +U+8C36(0);U+8C36(1,3);U+8B96(1,3) +U+8C37(0);U+8C37(1,3);U+7A40(1,3,4) +U+8C39(0);U+8C39(0); +U+8C3A(0);U+8C3A(0); +U+8C3B(0);U+8C3B(0); +U+8C3C(0);U+8C3C(3); +U+8C3D(0);U+8C3D(0); +U+8C3E(0);U+8C3E(0); +U+8C3F(0);U+6EAA(2,3);U+6EAA(2,3) +U+8C41(0);U+8C41(5); +U+8C42(0);U+8C42(0); +U+8C43(0);U+8C43(0); +U+8C45(0);U+8C45(3); +U+8C46(0);U+8C46(5);U+68AA(3),U+8373(2) +U+8C47(0);U+8C47(5); +U+8C48(0);U+5C82(1,3);U+5C82(1,3) +U+8C49(0);U+8C49(5); +U+8C4A(0);U+8C4A(0);U+4E30(3),U+8C50(3) +U+8C4B(0);U+767B(4);U+767B(4) +U+8C4C(0);U+8C4C(5); +U+8C4D(0);U+8C4D(0); +U+8C4E(0);U+7AD6(4);U+7AD6(4),U+7AEA(2,3) +U+8C4F(0);U+8C4F(0); +U+8C50(0);U+4E30(1,3);U+4E30(1,3),U+8C4A(3) +U+8C54(0);U+8273(4);U+8273(4),U+8276(4),U+8277(2,3) + +U+8C55(0);U+8C55(5); +U+8C56(0);U+8C56(0); +U+8C57(0);U+8C57(3);U+62FB(3) +U+8C59(0);U+8C59(0); +U+8C5A(0);U+8C5A(5); +U+8C5B(0);U+8C5B(0); +U+8C5C(0);U+8C5C(0);U+8C63(3) +U+8C5D(0);U+8C5D(0); +U+8C5E(0);U+8C5E(0); +U+8C5F(0);U+8C5F(0); +U+8C60(0);U+8C60(0); +U+8C61(0);U+8C61(5);U+50CF(3) +U+8C62(0);U+8C62(5); +U+8C63(0);U+8C63(3);U+8C5C(3) +U+8C64(0);U+8C64(3); +U+8C65(0);U+8C65(0); +U+8C66(0);U+8C66(0); +U+8C67(0);U+8C67(0); +U+8C68(0);U+8C68(3); +U+8C69(0);U+8C69(0); +U+8C6A(0);U+8C6A(5); +U+8C6B(0);U+8C6B(5); +U+8C6C(0);U+732A(2,3);U+732A(2,3) +U+8C6D(0);U+8C6D(3); +U+8C6E(0);U+8C6E(1,3);U+8C76(1,3) +U+8C6F(0);U+8C6F(0); +U+8C70(0);U+8C70(0); +U+8C71(0);U+8C71(0); +U+8C72(0);U+8C72(3); +U+8C73(0);U+8C73(5); +U+8C75(0);U+8C75(0); +U+8C76(0);U+8C6E(1,3);U+8C6E(1,3) +U+8C77(0);U+8C77(0); +U+8C78(0);U+8C78(5); +U+8C79(0);U+8C79(5); +U+8C7A(0);U+8C7A(5);U+72B2(3) +U+8C7B(0);U+8C7B(3); +U+8C7D(0);U+8C7D(0); +U+8C7E(0);U+8C7E(3); +U+8C80(0);U+8C80(3); +U+8C81(0);U+8C81(3); +U+8C82(0);U+8C82(5); +U+8C84(0);U+8C84(0); +U+8C85(0);U+8C85(5); +U+8C86(0);U+8C86(0); +U+8C88(0);U+8C88(4); +U+8C89(0);U+8C89(5);U+72E2(3) +U+8C8A(0);U+8C8A(5); +U+8C8C(0);U+8C8C(5);U+7683(3) +U+8C8D(0);U+72F8(2,3);U+72F8(2,3) +U+8C8F(0);U+8C8F(0); +U+8C90(0);U+8C90(0); +U+8C91(0);U+8C91(0); +U+8C92(0);U+8C92(3); +U+8C93(0);U+732B(2,3);U+732B(2,3) +U+8C94(0);U+8C94(5); +U+8C95(0);U+8C95(0); +U+8C96(0);U+8C96(0); +U+8C97(0);U+8C97(0); +U+8C98(0);U+8C98(5); +U+8C99(0);U+8C99(0); +U+8C9A(0);U+8C9A(0); +U+8C9C(0);U+7383(3);U+7383(3) + +U+8C9D(0);U+8D1D(1,3);U+8D1D(1,3) +U+8C9E(0);U+8D1E(1,3);U+8D1E(1,3) +U+8C9F(0);U+8D20(4);U+8D20(4) +U+8CA0(0);U+8D1F(1,3);U+8D1F(1,3) +U+8CA1(0);U+8D22(1,3);U+8D22(1,3) +U+8CA2(0);U+8D21(1,3);U+8D21(1,3) +U+8CA3(0);U+8CA3(3); +U+8CA4(0);U+8CA4(0); +U+8CA5(0);U+8CA5(0); +U+8CA7(0);U+8D2B(1,3);U+8D2B(1,3) +U+8CA8(0);U+8D27(1,3);U+8D27(1,3) +U+8CA9(0);U+8D29(1,3);U+8D29(1,3) +U+8CAA(0);U+8D2A(1,3);U+8D2A(1,3) +U+8CAB(0);U+8D2F(1,3);U+8D2F(1,3) +U+8CAC(0);U+8D23(1,3);U+8D23(1,3) +U+8CAD(0);U+8D28(3);U+8CEA(3),U+8D28(3) +U+8CAE(0);U+8D30(4);U+8CB3(4),U+8D30(4),U+4E8C(3,4,5),U+5F0D(3,4) +U+8CAF(0);U+8D2E(1,3);U+8D2E(1,3) +U+8CB0(0);U+8D33(1,3);U+8D33(1,3) +U+8CB1(0);U+8CB1(0); +U+8CB2(0);U+8D40(4);U+8D40(4) +U+8CB3(0);U+8D30(1,3);U+4E8C(3),U+8CAE(4),U+8D30(1,3),U+5F0D(3) +U+8CB4(0);U+8D35(1,3);U+8D35(1,3) +U+8CB5(0);U+8CB5(0); +U+8CB6(0);U+8D2C(1,3);U+8D2C(1,3) +U+8CB7(0);U+4E70(1,3);U+4E70(1,3) +U+8CB8(0);U+8D37(1,3);U+8D37(1,3) +U+8CB9(0);U+8CB9(0); +U+8CBA(0);U+8D36(1,3);U+8D36(1,3) +U+8CBB(0);U+8D39(1,3);U+8D39(1,3) +U+8CBC(0);U+8D34(1,3);U+8D34(1,3) +U+8CBD(0);U+8D3B(1,3);U+8D3B(1,3) +U+8CBE(0);U+8CBE(0); +U+8CBF(0);U+8D38(1,3);U+8D38(1,3) +U+8CC0(0);U+8D3A(1,3);U+8D3A(1,3) +U+8CC1(0);U+8D32(1,3);U+8D32(1,3) +U+8CC2(0);U+8D42(1,3);U+8D42(1,3) +U+8CC3(0);U+8D41(1,3);U+8D41(1,3) +U+8CC4(0);U+8D3F(1,3);U+8D3F(1,3) +U+8CC5(0);U+8D45(1,3);U+8D45(1,3),U+8CCC(1,3) +U+8CC6(0);U+8CC6(0); +U+8CC7(0);U+8D44(1,3);U+8D44(1,3) +U+8CC8(0);U+8D3E(1,3);U+8D3E(1,3) +U+8CC9(0);U+6064(2,3);U+6064(2,3),U+5379(0,2,3) +U+8CCA(0);U+8D3C(1,3);U+621D(3),U+8D3C(1,3) +U+8CCC(0);U+8D45(3);U+8D45(3),U+8CC5(0,1,3) +U+8CCE(0);U+8CCE(0); +U+8CCF(0);U+8CCF(0); +U+8CD0(0);U+8CD0(0); +U+8CD1(0);U+8D48(1,3);U+8D48(1,3) +U+8CD2(0);U+8D4A(1);U+8D4A(1) +U+8CD3(0);U+5BBE(1,3);U+5BBE(1,3),U+8CD4(3) +U+8CD4(0);U+5BBE(3);U+5BBE(3),U+8CD3(3) +U+8CD5(0);U+8D47(4);U+8D47(4) +U+8CD7(0);U+4E32(4);U+4E32(4) +U+8CD9(0);U+8D52(1,3);U+8D52(1,3) +U+8CDA(0);U+8D49(1,3);U+8D49(1,3) +U+8CDB(0);U+8D5E(4);U+8D0A(2,3),U+8D5E(4),U+8B83(0,3,4),U+8B9A(3,4) +U+8CDC(0);U+8D50(1,3);U+8D50(1,3) +U+8CDD(0);U+741B(3);U+741B(3) +U+8CDE(0);U+8D4F(1,3);U+8D4F(1,3) +U+8CDF(0);U+8CDF(0); +U+8CE0(0);U+8D54(1,3);U+8D54(1,3) + +U+8CE1(0);U+8D53(1,3);U+8D53(1,3) +U+8CE2(0);U+8D24(1,3);U+8D24(1,3) +U+8CE3(0);U+5356(1,3);U+5356(1,3),U+58F2(4) +U+8CE4(0);U+8D31(1,3);U+8D31(1,3) +U+8CE5(0);U+8CE5(0); +U+8CE6(0);U+8D4B(1,3);U+8D4B(1,3) +U+8CE7(0);U+8D55(1,3);U+8D55(1,3) +U+8CE8(0);U+8CE8(3); +U+8CEA(0);U+8D28(1,3);U+8CAD(3),U+8D28(1,3) +U+8CEB(0);U+8D4D(1,3);U+8D4D(1,3),U+9F4E(1,3) +U+8CEC(0);U+8D26(1,3);U+5E33(3),U+8D26(1,3),U+5E10(1,3) +U+8CED(0);U+8D4C(1,3);U+8D4C(1,3) +U+8CEE(0);U+8D46(3);U+8D46(3),U+8D10(1,3) +U+8CEF(0);U+8CEF(0); +U+8CF0(0);U+8CF0(0); +U+8CF1(0);U+8CF1(0); +U+8CF2(0);U+8CF2(0); +U+8CF3(0);U+8CF3(0); +U+8CF4(0);U+8D56(1,3);U+8D56(1,3),U+983C(2,3) +U+8CF5(0);U+8D57(1,3);U+8D57(1,3) +U+8CF6(0);U+8CF6(0); +U+8CF8(0);U+5269(2,3);U+5269(2,3),U+5270(2,3,4) +U+8CF9(0);U+9552(3);U+9552(3),U+93B0(1,3) +U+8CFA(0);U+8D5A(1,3);U+8D5A(1,3) +U+8CFB(0);U+8D59(1,3);U+8D59(1,3) +U+8CFC(0);U+8D2D(1,3);U+8D2D(1,3) +U+8CFD(0);U+8D5B(1,3);U+8D5B(1,3) +U+8CFE(0);U+8D5C(1,3);U+8D5C(1,3) +U+8CFF(0);U+8CFF(0); +U+8D00(0);U+8D00(0); +U+8D02(0);U+8D02(0); +U+8D03(0);U+8D03(0); +U+8D04(0);U+8D3D(1,3);U+8D3D(1,3) +U+8D05(0);U+8D58(1,3);U+8D58(1,3) +U+8D06(0);U+8D06(3); +U+8D07(0);U+8D5F(4);U+8D5F(4) +U+8D08(0);U+8D60(1,3);U+8D60(1,3) +U+8D09(0);U+8D09(0); +U+8D0A(0);U+8D5E(1,3);U+8B9A(2),U+8CDB(2,3),U+8D5E(1,3),U+8B83(0,2,3) +U+8D0B(0);U+8D5D(1,3);U+8D17(2,3),U+8D5D(1,3) +U+8D0C(0);U+8D0C(0); +U+8D0D(0);U+8D61(1,3);U+8D61(1,3) +U+8D0E(0);U+8D0E(0); +U+8D0F(0);U+8D62(1,3);U+8D62(1,3) +U+8D10(0);U+8D46(1,3);U+8D46(1,3),U+8CEE(0,1,3) +U+8D13(0);U+8D43(4);U+8D1C(3),U+8D43(4) +U+8D14(0);U+8D51(4);U+8D51(4) +U+8D15(0);U+8D15(0); +U+8D16(0);U+8D4E(1,3);U+8D4E(1,3) +U+8D17(0);U+8D5D(4);U+8D0B(2,3),U+8D5D(4) +U+8D18(0);U+8D18(0); +U+8D19(0);U+8D19(0); +U+8D1A(0);U+8D1A(0); +U+8D1B(0);U+8D63(1,3);U+8D63(1,3),U+7068(0,1,2,3) +U+8D1C(0);U+8D43(1,3);U+8D13(3),U+8D43(1,3) +U+8D1D(0);U+8D1D(1,3);U+8C9D(1,3) +U+8D1E(0);U+8D1E(1,3);U+8C9E(1,3) +U+8D1F(0);U+8D1F(1,3);U+8CA0(1,3) +U+8D20(0);U+8D20(4);U+8C9F(4) +U+8D21(0);U+8D21(1,3);U+8CA2(1,3) +U+8D22(0);U+8D22(1,3);U+8CA1(1,3) +U+8D23(0);U+8D23(1,3);U+8CAC(1,3) +U+8D24(0);U+8D24(1,3);U+8CE2(1,3) + +U+8D25(0);U+8D25(1,3);U+6557(1,3) +U+8D26(0);U+8D26(1,3);U+8CEC(1,3),U+5E10(1,3),U+5E33(0,1,3) +U+8D27(0);U+8D27(1,3);U+8CA8(1,3) +U+8D28(0);U+8D28(1,3);U+8CAD(3),U+8CEA(1,3) +U+8D29(0);U+8D29(1,3);U+8CA9(1,3) +U+8D2A(0);U+8D2A(1,3);U+8CAA(1,3) +U+8D2B(0);U+8D2B(1,3);U+8CA7(1,3) +U+8D2C(0);U+8D2C(1,3);U+8CB6(1,3) +U+8D2D(0);U+8D2D(1,3);U+8CFC(1,3) +U+8D2E(0);U+8D2E(1,3);U+8CAF(1,3,4) +U+8D2F(0);U+8D2F(1,3);U+8CAB(1,3) +U+8D30(0);U+8D30(1,3);U+8CAE(4),U+8CB3(1,3),U+4E8C(1,3,5),U+5F0D(1,3) +U+8D31(0);U+8D31(1,3);U+8CE4(1,3) +U+8D32(0);U+8D32(1,3);U+8CC1(1,3) +U+8D33(0);U+8D33(1,3);U+8CB0(1,3) +U+8D34(0);U+8D34(1,3);U+8CBC(1,3) +U+8D35(0);U+8D35(1,3);U+8CB4(1,3) +U+8D36(0);U+8D36(1,3);U+8CBA(1,3) +U+8D37(0);U+8D37(1,3);U+8CB8(1,3) +U+8D38(0);U+8D38(1,3);U+8CBF(1,3) +U+8D39(0);U+8D39(1,3);U+8CBB(1,3) +U+8D3A(0);U+8D3A(1,3);U+8CC0(1,3) +U+8D3B(0);U+8D3B(1,3);U+8CBD(1,3) +U+8D3C(0);U+8D3C(1,3);U+621D(3),U+8CCA(1,3) +U+8D3D(0);U+8D3D(1,3);U+8D04(1,3) +U+8D3E(0);U+8D3E(1,3);U+8CC8(1,3) +U+8D3F(0);U+8D3F(1,3);U+8CC4(1,3) +U+8D40(0);U+8D40(4);U+8CB2(4) +U+8D41(0);U+8D41(1,3);U+8CC3(1,3) +U+8D42(0);U+8D42(1,3);U+8CC2(1,3) +U+8D43(0);U+8D43(1,3,4);U+8D13(4),U+8D1C(1,3) +U+8D44(0);U+8D44(1,3);U+8CC7(1,3) +U+8D45(0);U+8D45(1,3);U+8CC5(1,3),U+8CCC(3) +U+8D46(0);U+8D46(1,3);U+8CEE(3),U+8D10(1,3) +U+8D47(0);U+8D47(4);U+8CD5(4) +U+8D48(0);U+8D48(1,3);U+8CD1(1,3) +U+8D49(0);U+8D49(1,3);U+8CDA(1,3) +U+8D4A(0);U+8D4A(1);U+8CD2(1) +U+8D4B(0);U+8D4B(1,3);U+8CE6(1,3) +U+8D4C(0);U+8D4C(1,3);U+8CED(1,3) +U+8D4D(0);U+8D4D(1,3);U+8CEB(1,3),U+9F4E(3) +U+8D4E(0);U+8D4E(1,3);U+8D16(1,3) +U+8D4F(0);U+8D4F(1,3);U+8CDE(1,3) +U+8D50(0);U+8D50(1,3);U+8CDC(1,3) +U+8D51(0);U+8D51(4);U+8D14(4) +U+8D52(0);U+8D52(1,3);U+8CD9(1,3) +U+8D53(0);U+8D53(1,3);U+8CE1(1,3) +U+8D54(0);U+8D54(1,3);U+8CE0(1,3) +U+8D55(0);U+8D55(1,3);U+8CE7(1,3) +U+8D56(0);U+8D56(1,3);U+8CF4(1,3),U+983C(4) +U+8D57(0);U+8D57(1,3);U+8CF5(1,3) +U+8D58(0);U+8D58(1,3);U+8D05(1,3) +U+8D59(0);U+8D59(1,3);U+8CFB(1,3) +U+8D5A(0);U+8D5A(1,3);U+8CFA(1,3) +U+8D5B(0);U+8D5B(1,3);U+8CFD(1,3) +U+8D5C(0);U+8D5C(1,3);U+8CFE(1,3) +U+8D5D(0);U+8D5D(1,3);U+8D0B(1,3),U+8D17(4) +U+8D5E(0);U+8D5E(1,3);U+8B83(3,4),U+8B9A(4),U+8CDB(4),U+8D0A(1,3) +U+8D5F(0);U+8D5F(4);U+8D07(4) +U+8D60(0);U+8D60(1,3);U+8D08(1,3) +U+8D61(0);U+8D61(1,3);U+8D0D(1,3) +U+8D62(0);U+8D62(1,3);U+8D0F(1,3) +U+8D63(0);U+8D63(1,3);U+7068(2),U+8D1B(1,3) + +U+8D64(0);U+8D64(5); +U+8D65(0);U+8D65(0); +U+8D66(0);U+8D66(5); +U+8D67(0);U+8D67(5); +U+8D68(0);U+8D68(3); +U+8D69(0);U+8D69(0); +U+8D6A(0);U+8D6A(1,3);U+7AC0(7),U+8D6C(1,3) +U+8D6B(0);U+8D6B(5); +U+8D6C(0);U+8D6A(1,3);U+8D6A(1,3),U+7AC0(1,3,7) +U+8D6D(0);U+8D6D(5); +U+8D6E(0);U+971E(3);U+971E(3) +U+8D6F(0);U+8D6F(0); +U+8D70(0);U+8D70(5);U+8D71(3) +U+8D71(0);U+8D70(3);U+8D70(3) +U+8D72(0);U+8D72(0); +U+8D73(0);U+8D73(5); +U+8D74(0);U+8D74(5); +U+8D75(0);U+8D75(1,3);U+8D99(1,3) +U+8D76(0);U+8D76(1,3);U+8D95(1,3,4) +U+8D77(0);U+8D77(5); +U+8D78(0);U+8D78(0); +U+8D79(0);U+8D79(0); +U+8D7A(0);U+8D7A(0); +U+8D7B(0);U+8D7B(0); +U+8D7D(0);U+8D7D(0); +U+8D7E(0);U+8D7E(0); +U+8D7F(0);U+8D7F(0); +U+8D80(0);U+8D80(0); +U+8D81(0);U+8D81(5);U+8D82(2,3) +U+8D82(0);U+8D81(2,3);U+8D81(2,3) +U+8D83(0);U+8D83(0); +U+8D84(0);U+8D84(5); +U+8D85(0);U+8D85(5); +U+8D86(0);U+8D86(3); +U+8D87(0);U+8D87(0); +U+8D88(0);U+8D88(0); +U+8D89(0);U+8D89(0); +U+8D8A(0);U+8D8A(5); +U+8D8B(0);U+8D8B(1,3);U+8D8D(3),U+8DA8(1,3) +U+8D8C(0);U+8D8C(0); +U+8D8D(0);U+8D8B(3);U+8D8B(3),U+8DA8(1,3) +U+8D8E(0);U+8D8E(0); +U+8D8F(0);U+8D8F(0); +U+8D90(0);U+8D90(0); +U+8D91(0);U+8D91(5); +U+8D92(0);U+8DF3(7);U+8DF3(7) +U+8D93(0);U+8D93(0); +U+8D94(0);U+8D94(5); +U+8D95(0);U+8D76(1,3);U+8D76(1,3) +U+8D96(0);U+8D96(0); +U+8D97(0);U+8D97(0); +U+8D98(0);U+8D98(0); +U+8D99(0);U+8D75(1,3);U+8D75(1,3) +U+8D9A(0);U+8D9A(0); +U+8D9B(0);U+8D9B(3); +U+8D9C(0);U+8D9C(0); +U+8D9D(0);U+8D9D(0); +U+8D9E(0);U+8D9E(0); +U+8D9F(0);U+8D9F(5);U+8E5A(2,3) +U+8DA0(0);U+8DA0(3); +U+8DA1(0);U+8DA1(0); +U+8DA2(0);U+8DA2(0); +U+8DA3(0);U+8DA3(5); + +U+8DA4(0);U+8DA4(0); +U+8DA5(0);U+8DA5(0); +U+8DA7(0);U+8DA7(0); +U+8DA8(0);U+8D8B(1,3);U+8D8B(1,3),U+8D8D(1,3) +U+8DA9(0);U+8DA9(0); +U+8DAA(0);U+8DAA(0); +U+8DAB(0);U+8DAB(3); +U+8DAC(0);U+8DAC(3); +U+8DAD(0);U+8DAD(0); +U+8DAE(0);U+8E81(3);U+8E81(3) +U+8DAF(0);U+8DAF(0); +U+8DB0(0);U+8DB0(0); +U+8DB1(0);U+8DB1(1,3);U+8DB2(1,3) +U+8DB2(0);U+8DB1(1,3);U+8DB1(1,3) +U+8DB3(0);U+8DB3(5); +U+8DB4(0);U+8DB4(5); +U+8DB5(0);U+8DB5(5); +U+8DB6(0);U+8DB6(0); +U+8DB7(0);U+8DB7(0); +U+8DB8(0);U+8DB8(1,3);U+8E89(1,3) +U+8DB9(0);U+8DB9(0); +U+8DBA(0);U+8DBA(5); +U+8DBB(0);U+8DBB(0); +U+8DBC(0);U+8DBC(5); +U+8DBD(0);U+8DBD(0); +U+8DBE(0);U+8DBE(5); +U+8DBF(0);U+8DBF(5); +U+8DC1(0);U+8DC1(0); +U+8DC2(0);U+8DC2(3); +U+8DC3(0);U+8DC3(1,3);U+8E8D(1,3) +U+8DC4(0);U+8DC4(1,3);U+8E4C(1,3) +U+8DC5(0);U+8DC5(0); +U+8DC6(0);U+8DC6(5); +U+8DC7(0);U+8DC7(0); +U+8DC8(0);U+8DC8(0); +U+8DC9(0);U+8DC9(0); +U+8DCA(0);U+8DCA(0); +U+8DCB(0);U+8DCB(5); +U+8DCC(0);U+8DCC(5); +U+8DCD(0);U+8DCD(0); +U+8DCE(0);U+8DCE(5); +U+8DCF(0);U+8DCF(5); +U+8DD0(0);U+8DD0(0); +U+8DD1(0);U+8DD1(5); +U+8DD2(0);U+8DD2(0); +U+8DD3(0);U+8DD3(0); +U+8DD4(0);U+8DD4(3); +U+8DD5(0);U+8DD5(0); +U+8DD6(0);U+8DD6(5);U+8E60(2,3,4) +U+8DD7(0);U+8DD7(5); +U+8DD8(0);U+8DD8(0); +U+8DD9(0);U+8DD9(3); +U+8DDA(0);U+8DDA(5); +U+8DDB(0);U+8DDB(5); +U+8DDC(0);U+8DDC(0); +U+8DDD(0);U+8DDD(5); +U+8DDE(0);U+8DDE(4);U+8E92(4) +U+8DDF(0);U+8DDF(5); +U+8DE0(0);U+8DE0(0); +U+8DE1(0);U+8FF9(2,3);U+8E5F(4),U+8FF9(2,3) +U+8DE2(0);U+8DE2(0); +U+8DE3(0);U+8DE3(5); +U+8DE4(0);U+8DE4(5); + +U+8DE6(0);U+8DE6(3); +U+8DE7(0);U+8DE7(0); +U+8DE8(0);U+8DE8(5); +U+8DE9(0);U+8DE9(0); +U+8DEA(0);U+8DEA(5); +U+8DEB(0);U+8DEB(5); +U+8DEC(0);U+8DEC(5);U+8E5E(3) +U+8DED(0);U+8DED(0); +U+8DEE(0);U+8DEE(0); +U+8DEF(0);U+8DEF(5); +U+8DF0(0);U+8DF0(0); +U+8DF1(0);U+8DF1(0); +U+8DF2(0);U+8DF2(0); +U+8DF3(0);U+8DF3(5);U+8D92(7) +U+8DF4(0);U+8E29(2,3);U+8E29(2,3) +U+8DF5(0);U+8DF5(1,3);U+8E10(1,3) +U+8DF6(0);U+8DF6(4);U+8E82(4) +U+8DF7(0);U+8DF7(1,3);U+8E7A(1,3),U+8E7B(3) +U+8DF8(0);U+8DF8(1,3);U+9A46(3),U+8E55(1,3) +U+8DF9(0);U+8DF9(1,3);U+8E9A(1,3) +U+8DFA(0);U+8DFA(5); +U+8DFB(0);U+8DFB(1,3);U+8E8B(1,3) +U+8DFC(0);U+5C40(2);U+5C40(2),U+4FB7(0,2) +U+8DFD(0);U+8DFD(5); +U+8DFE(0);U+8DFE(0); +U+8DFF(0);U+8DFF(0); +U+8E00(0);U+9F8A(3);U+9F8A(3),U+9F6A(1,3) +U+8E02(0);U+8E02(3);U+8E19(3) +U+8E03(0);U+8E03(0); +U+8E04(0);U+8E04(0); +U+8E05(0);U+8E05(5); +U+8E06(0);U+8E06(0); +U+8E07(0);U+8E07(0); +U+8E08(0);U+758F(4);U+758F(4) +U+8E09(0);U+8E09(5); +U+8E0A(0);U+8E0A(1,3);U+8E34(1,3,4) +U+8E0C(0);U+8E0C(1,3);U+8E8A(1,3) +U+8E0D(0);U+9AB9(3);U+9AB9(3) +U+8E0E(0);U+8E0E(0); +U+8E0F(0);U+8E0F(5); +U+8E10(0);U+8DF5(1,3);U+8DF5(1,3) +U+8E11(0);U+8E11(0); +U+8E12(0);U+8E12(0); +U+8E13(0);U+8E13(0); +U+8E14(0);U+8E14(5); +U+8E15(0);U+8E15(0); +U+8E16(0);U+8E16(3); +U+8E17(0);U+8E17(0); +U+8E18(0);U+8E18(0); +U+8E19(0);U+8E02(3);U+8E02(3) +U+8E1A(0);U+8E1A(0); +U+8E1B(0);U+8E1B(0); +U+8E1C(0);U+8E1C(0); +U+8E1D(0);U+8E1D(5); +U+8E1E(0);U+8E1E(5); +U+8E1F(0);U+8E1F(5); +U+8E20(0);U+8E20(0); +U+8E21(0);U+8737(4);U+8737(4) +U+8E22(0);U+8E22(5); +U+8E23(0);U+8E23(5);U+6B95(3) +U+8E24(0);U+8E24(0); +U+8E25(0);U+8E25(0); +U+8E26(0);U+8E26(0); + +U+8E27(0);U+8E27(0); +U+8E28(0);U+8E2A(3);U+8E2A(3),U+8E64(3) +U+8E29(0);U+8E29(5);U+8DF4(2,3) +U+8E2A(0);U+8E2A(5);U+8E28(3),U+8E64(2,3) +U+8E2B(0);U+78B0(2,3);U+78B0(2,3),U+63BD(0,2,3) +U+8E2C(0);U+8E2C(1,3);U+8E93(1,3) +U+8E2D(0);U+8E2D(0); +U+8E2E(0);U+8E2E(5); +U+8E2F(0);U+8E2F(1,3);U+8E91(1,3) +U+8E30(0);U+903E(2);U+903E(2) +U+8E31(0);U+8E31(5); +U+8E33(0);U+8E33(3); +U+8E34(0);U+8E0A(1,3);U+8E0A(1,3) +U+8E35(0);U+8E35(5); +U+8E36(0);U+8E36(0); +U+8E37(0);U+8E37(0); +U+8E38(0);U+8E38(3); +U+8E39(0);U+8E39(5); +U+8E3A(0);U+8E3A(5); +U+8E3B(0);U+8E3B(0); +U+8E3C(0);U+8E3C(3); +U+8E3D(0);U+8E3D(5); +U+8E3E(0);U+8E3E(0); +U+8E3F(0);U+8E3F(0); +U+8E40(0);U+8E40(5); +U+8E41(0);U+8E41(5); +U+8E42(0);U+8E42(5);U+79B8(3) +U+8E43(0);U+8E43(0); +U+8E44(0);U+8E44(5); +U+8E45(0);U+8E45(0); +U+8E47(0);U+8E47(5); +U+8E48(0);U+8E48(5); +U+8E49(0);U+8E49(5); +U+8E4A(0);U+8E4A(5); +U+8E4B(0);U+8E4B(5); +U+8E4C(0);U+8DC4(1,3);U+8DC4(1,3) +U+8E4D(0);U+8E4D(0); +U+8E4E(0);U+8E4E(0); +U+8E50(0);U+8E50(0); +U+8E51(0);U+8E51(1,3);U+8EA1(1,3) +U+8E52(0);U+8E52(1,3);U+8E63(1,3) +U+8E53(0);U+8E53(0); +U+8E54(0);U+6682(4);U+6682(4),U+66AB(1,3,4) +U+8E55(0);U+8DF8(1,3);U+8DF8(1,3),U+9A46(1,3) +U+8E56(0);U+6869(4);U+6869(4),U+6A01(1,3,4) +U+8E57(0);U+8E57(0); +U+8E58(0);U+8E58(0); +U+8E59(0);U+8E59(5);U+9863(3) +U+8E5A(0);U+8D9F(2,3);U+8D9F(2,3) +U+8E5B(0);U+8E5B(0); +U+8E5C(0);U+8E5C(0); +U+8E5D(0);U+8E5D(0); +U+8E5E(0);U+8DEC(3);U+8DEC(3) +U+8E5F(0);U+8FF9(2,3);U+8DE1(4),U+8FF9(2,3) +U+8E60(0);U+8DD6(2,3,4);U+8DD6(2,3,4) +U+8E61(0);U+8E61(3); +U+8E62(0);U+8E62(3); +U+8E63(0);U+8E52(1,3);U+8E52(1,3) +U+8E64(0);U+8E2A(2,3);U+8E28(3),U+8E2A(2,3) +U+8E65(0);U+8E65(0); +U+8E66(0);U+8E66(5); +U+8E67(0);U+7CDF(2);U+7CDF(2) +U+8E68(0);U+8E68(3); + +U+8E69(0);U+8E69(5); +U+8E6A(0);U+8E6A(0); +U+8E6B(0);U+8E6B(0); +U+8E6C(0);U+8E6C(5); +U+8E6D(0);U+8E6D(5); +U+8E6F(0);U+8E6F(5);U+756A(3),U+7C75(3) +U+8E70(0);U+8E70(5);U+8E95(2,3,4) +U+8E71(0);U+8E71(4); +U+8E72(0);U+8E72(5);U+58FF(4) +U+8E73(0);U+8E73(0); +U+8E74(0);U+8E74(5); +U+8E76(0);U+8E76(5); +U+8E78(0);U+8E78(3); +U+8E7A(0);U+8DF7(1,3);U+8DF7(1,3),U+8E7B(2,3) +U+8E7B(0);U+8E7B(0);U+8DF7(3),U+8E7A(2,3) +U+8E7C(0);U+8E7C(5); +U+8E7D(0);U+8E7D(0); +U+8E7E(0);U+8E7E(0); +U+8E7F(0);U+8E7F(1,3);U+8EA5(1,3) +U+8E80(0);U+8E80(0); +U+8E81(0);U+8E81(5);U+8DAE(3) +U+8E82(0);U+8DF6(4);U+8DF6(4) +U+8E83(0);U+8E83(4); +U+8E84(0);U+8E84(3); +U+8E85(0);U+8E85(5); +U+8E86(0);U+8E86(0); +U+8E87(0);U+8E87(5); +U+8E88(0);U+8E88(0); +U+8E89(0);U+8DB8(1,3);U+8DB8(1,3) +U+8E8A(0);U+8E0C(1,3);U+8E0C(1,3) +U+8E8B(0);U+8DFB(1,3);U+8DFB(1,3) +U+8E8C(0);U+8E8C(0); +U+8E8D(0);U+8DC3(1,3);U+8DC3(1,3) +U+8E8E(0);U+8E8E(0); +U+8E8F(0);U+8E8F(1,3);U+8EAA(1,3) +U+8E90(0);U+8E90(5); +U+8E91(0);U+8E2F(1,3);U+8E2F(1,3) +U+8E92(0);U+8DDE(4);U+8DDE(4) +U+8E93(0);U+8E2C(1,3);U+8E2C(1,3) +U+8E94(0);U+8E94(5); +U+8E95(0);U+8E70(2,3,4);U+8E70(2,3,4) +U+8E96(0);U+8E96(0); +U+8E97(0);U+8E97(0); +U+8E98(0);U+8E98(0); +U+8E9A(0);U+8DF9(1,3);U+8DF9(1,3) +U+8E9C(0);U+8E9C(1,3);U+8EA6(1,3) +U+8E9D(0);U+8E9D(0); +U+8E9E(0);U+8E9E(5); +U+8E9F(0);U+8E9F(3); +U+8EA0(0);U+8EA0(0); +U+8EA1(0);U+8E51(1,3);U+8E51(1,3) +U+8EA3(0);U+8EA3(3); +U+8EA4(0);U+8EA4(0); +U+8EA5(0);U+8E7F(1,3);U+8E7F(1,3) +U+8EA6(0);U+8E9C(1,3);U+8E9C(1,3) +U+8EA7(0);U+8EA7(3); +U+8EA8(0);U+8EA8(0); +U+8EA9(0);U+8EA9(0); +U+8EAA(0);U+8E8F(1,3);U+8E8F(1,3) +U+8EAB(0);U+8EAB(5); +U+8EAC(0);U+8EAC(5); +U+8EAD(0);U+803D(2,3);U+803D(2,3) +U+8EAE(0);U+8EAE(0); + +U+8EAF(0);U+8EAF(1,3);U+8EC0(1,3) +U+8EB0(0);U+4F53(3);U+4F53(3),U+9AD4(3),U+8EC6(3),U+9AB5(3) +U+8EB1(0);U+8EB1(3);U+8EB2(3,4) +U+8EB2(0);U+8EB2(5);U+8EB1(3,4) +U+8EB4(0);U+8EB4(0); +U+8EB5(0);U+8EB5(0); +U+8EB8(0);U+8EB8(0); +U+8EB9(0);U+8EB9(0); +U+8EBA(0);U+8EBA(5); +U+8EBB(0);U+8EBB(0); +U+8EBC(0);U+8EBC(0); +U+8EBD(0);U+8EBD(0); +U+8EBE(0);U+8EBE(0); +U+8EBF(0);U+8EBF(0); +U+8EC0(0);U+8EAF(1,3);U+8EAF(1,3) +U+8EC2(0);U+8EC2(0); +U+8EC3(0);U+8EC3(0); +U+8EC5(0);U+8EC5(0); +U+8EC6(0);U+4F53(3);U+4F53(3),U+9AD4(3),U+8EB0(3),U+9AB5(3) +U+8EC7(0);U+8EC7(0); +U+8EC8(0);U+8EC8(0); +U+8EC9(0);U+8EC9(0); +U+8ECA(0);U+8F66(1,3);U+8F66(1,3) +U+8ECB(0);U+8F67(1,3);U+8F67(1,3) +U+8ECC(0);U+8F68(1,3);U+8F68(1,3) +U+8ECD(0);U+519B(1,3);U+519B(1,3) +U+8ECE(0);U+8ECE(5); +U+8ECF(0);U+8ECF(0); +U+8ED0(0);U+8ED0(0); +U+8ED1(0);U+8F6A(4);U+8F6A(4) +U+8ED2(0);U+8F69(1,3);U+8F69(1,3) +U+8ED3(0);U+8ED3(0); +U+8ED4(0);U+8F6B(1,3);U+8F6B(1,3) +U+8ED5(0);U+8ED5(0); +U+8ED6(0);U+8ED6(4);U+8EE0(4) +U+8ED7(0);U+8ED7(0); +U+8ED8(0);U+8ED8(0); +U+8EDA(0);U+8EDA(0); +U+8EDB(0);U+8F6D(1);U+8F6D(1),U+6799(0,1,3),U+8EF6(1,3) +U+8EDC(0);U+8EDC(0); +U+8EDD(0);U+8EDD(0); +U+8EDE(0);U+8EDE(0); +U+8EDF(0);U+8F6F(1,3);U+8F6F(1,3) +U+8EE0(0);U+8ED6(4);U+8ED6(4) +U+8EE1(0);U+9ED4(3);U+9ED4(3) +U+8EE4(0);U+8F77(1,3);U+8F77(1,3) +U+8EE5(0);U+8EE5(0); +U+8EE6(0);U+8EE6(0); +U+8EE7(0);U+8EE7(0); +U+8EE8(0);U+8EE8(3); +U+8EE9(0);U+8EE9(0); +U+8EEA(0);U+8EEA(0); +U+8EEB(0);U+8F78(1,3);U+8F78(1,3) +U+8EEC(0);U+8EEC(3); +U+8EED(0);U+8EED(3); +U+8EEE(0);U+8EEE(0); +U+8EEF(0);U+8EEF(3); +U+8EF1(0);U+8EF1(0); +U+8EF2(0);U+8F71(1,3);U+8F42(9),U+8F71(1,3),U+6BC2(1,3,9) +U+8EF3(0);U+8EF3(0); +U+8EF4(0);U+8EF4(0); +U+8EF5(0);U+8EF5(0); +U+8EF6(0);U+8F6D(3);U+8F6D(3),U+6799(0,3),U+8EDB(1,3) + +U+8EF7(0);U+8EF7(0); +U+8EF8(0);U+8F74(1,3);U+8F74(1,3) +U+8EF9(0);U+8F75(4);U+8F75(4) +U+8EFA(0);U+8F7A(1,3);U+8F7A(1,3) +U+8EFB(0);U+8F72(1,3);U+8F72(1,3) +U+8EFC(0);U+8F76(1,3);U+8F76(1,3) +U+8EFD(0);U+8F7B(3);U+8F15(3),U+8F7B(3) +U+8EFE(0);U+8F7C(1,3);U+8F7C(1,3) +U+8EFF(0);U+8EFF(3);U+8F27(3) +U+8F00(0);U+8F00(3); +U+8F01(0);U+8F01(3); +U+8F02(0);U+8F02(0); +U+8F03(0);U+8F83(1,3);U+8F83(1,3) +U+8F04(0);U+8F04(0); +U+8F05(0);U+8F82(1,3);U+8F82(1,3) +U+8F06(0);U+8F06(0); +U+8F07(0);U+8F81(4);U+8F81(4) +U+8F08(0);U+8F80(4);U+8F80(4) +U+8F09(0);U+8F7D(1,3);U+8F7D(1,3) +U+8F0A(0);U+8F7E(1,3);U+8F7E(1,3) +U+8F0B(0);U+8F0B(0); +U+8F0D(0);U+8F0D(0); +U+8F0E(0);U+8F0E(0); +U+8F10(0);U+8F10(0); +U+8F11(0);U+8F11(0); +U+8F12(0);U+8F84(1,3);U+8F84(1,3) +U+8F13(0);U+633D(2,3);U+633D(2,3) +U+8F14(0);U+8F85(1,3);U+8F85(1,3) +U+8F15(0);U+8F7B(1,3);U+8EFD(3),U+8F7B(1,3) +U+8F16(0);U+8F16(0); +U+8F17(0);U+8F17(3); +U+8F18(0);U+8F18(0); +U+8F1A(0);U+8F1A(3); +U+8F1B(0);U+8F86(1,3);U+8F86(1,3) +U+8F1C(0);U+8F8E(1,3);U+8F8E(1,3) +U+8F1D(0);U+8F89(1,3);U+8F89(1,3) +U+8F1E(0);U+8F8B(1,3);U+8F8B(1,3) +U+8F1F(0);U+8F8D(1,3);U+8F8D(1,3) +U+8F20(0);U+8F20(3); +U+8F21(0);U+8F21(3); +U+8F22(0);U+8F22(0); +U+8F23(0);U+8F23(0); +U+8F24(0);U+8F24(0); +U+8F25(0);U+8F8A(1,3);U+8F8A(1,3) +U+8F26(0);U+8F87(1,3);U+8F87(1,3) +U+8F27(0);U+8EFF(3);U+8EFF(3) +U+8F28(0);U+8F28(3); +U+8F29(0);U+8F88(1,3);U+8F88(1,3) +U+8F2A(0);U+8F6E(1,3);U+8F6E(1,3) +U+8F2B(0);U+8F2B(0); +U+8F2C(0);U+8F8C(4);U+8F8C(4) +U+8F2E(0);U+8F2E(0); +U+8F2F(0);U+8F91(1,3);U+8F91(1,3) +U+8F30(0);U+8F30(0); +U+8F31(0);U+8F31(0); +U+8F32(0);U+8F32(3); +U+8F33(0);U+8F8F(1,3);U+8F8F(1,3) +U+8F34(0);U+8F34(3); +U+8F35(0);U+8F35(4); +U+8F36(0);U+8F36(3); +U+8F37(0);U+8F37(0); +U+8F38(0);U+8F93(1,3);U+8F93(1,3) +U+8F39(0);U+8F39(0); + +U+8F3B(0);U+8F90(1,3);U+8F90(1,3) +U+8F3C(0);U+8F92(4);U+8F40(4),U+8F92(4) +U+8F3D(0);U+8F3D(0); +U+8F3E(0);U+8F97(1,3);U+8F97(1,3) +U+8F3F(0);U+8206(1,3);U+8206(1,3),U+8F5D(1,3) +U+8F40(0);U+8F92(4);U+8F3C(4),U+8F92(4) +U+8F42(0);U+6BC2(1,3);U+6BC2(1,3),U+8EF2(9),U+8F71(4) +U+8F43(0);U+8F43(0); +U+8F44(0);U+8F96(1,3);U+8F96(1,3) +U+8F45(0);U+8F95(1,3);U+8F95(1,3) +U+8F46(0);U+8F98(1,3);U+8F98(1,3) +U+8F47(0);U+8F47(0); +U+8F48(0);U+8F48(0); +U+8F49(0);U+8F6C(1,3);U+8F6C(1,3) +U+8F4A(0);U+8F4A(0); +U+8F4B(0);U+8F4B(0); +U+8F4C(0);U+8F4C(0); +U+8F4D(0);U+8F99(1,3);U+8F99(1,3) +U+8F4E(0);U+8F7F(1,3);U+8F7F(1,3) +U+8F4F(0);U+6808(3);U+6808(3),U+68E7(1,3) +U+8F50(0);U+8F50(3); +U+8F51(0);U+8F51(0); +U+8F52(0);U+8F52(0); +U+8F53(0);U+8F53(0); +U+8F54(0);U+8F9A(1,3);U+8F9A(1,3) +U+8F55(0);U+8F55(0); +U+8F56(0);U+8F56(0); +U+8F57(0);U+8F57(4); +U+8F58(0);U+8F58(0); +U+8F59(0);U+8F59(3); +U+8F5A(0);U+8F5A(0); +U+8F5B(0);U+8F5B(0); +U+8F5D(0);U+8206(3);U+8206(3),U+8F3F(1,3) +U+8F5E(0);U+69DB(3);U+69DB(3),U+6ABB(1,3) +U+8F5F(0);U+8F70(1,3);U+8F70(1,3) +U+8F60(0);U+8F60(0); +U+8F61(0);U+8F94(1,3);U+8F94(1,3) +U+8F62(0);U+8F79(1,3);U+8F79(1,3) +U+8F63(0);U+8F63(0); +U+8F64(0);U+8F73(1,3);U+8F73(1,3) +U+8F65(0);U+8F65(0); +U+8F66(0);U+8F66(1,3);U+8ECA(1,3) +U+8F67(0);U+8F67(1,3);U+8ECB(1,3) +U+8F68(0);U+8F68(1,3);U+8ECC(1,3) +U+8F69(0);U+8F69(1,3);U+8ED2(1,3) +U+8F6A(0);U+8F6A(4);U+8ED1(4) +U+8F6B(0);U+8F6B(1,3);U+8ED4(1,3) +U+8F6C(0);U+8F6C(1,3);U+8F49(1,3) +U+8F6D(0);U+8F6D(1);U+6799(3),U+8EDB(1),U+8EF6(3) +U+8F6E(0);U+8F6E(1,3);U+8F2A(1,3) +U+8F6F(0);U+8F6F(1,3);U+8EDF(1,3) +U+8F70(0);U+8F70(1,3);U+8F5F(1,3) +U+8F71(0);U+8F71(1,3,4);U+8EF2(1,3),U+8F42(4),U+6BC2(1,3,4) +U+8F72(0);U+8F72(1,3);U+8EFB(1,3) +U+8F73(0);U+8F73(1,3);U+8F64(1,3) +U+8F74(0);U+8F74(1,3);U+8EF8(1,3) +U+8F75(0);U+8F75(4);U+8EF9(4) +U+8F76(0);U+8F76(1,3);U+8EFC(1,3) +U+8F77(0);U+8F77(1,3);U+8EE4(1,3) +U+8F78(0);U+8F78(1,3);U+8EEB(1,3) +U+8F79(0);U+8F79(1,3);U+8F62(1,3) +U+8F7A(0);U+8F7A(1,3);U+8EFA(1,3) +U+8F7B(0);U+8F7B(1,3);U+8EFD(3),U+8F15(1,3) + +U+8F7C(0);U+8F7C(1,3);U+8EFE(1,3) +U+8F7D(0);U+8F7D(1,3);U+8F09(1,3) +U+8F7E(0);U+8F7E(1,3);U+8F0A(1,3) +U+8F7F(0);U+8F7F(1,3);U+8F4E(1,3) +U+8F80(0);U+8F80(4);U+8F08(4) +U+8F81(0);U+8F81(4);U+8F07(4) +U+8F82(0);U+8F82(1,3);U+8F05(1,3) +U+8F83(0);U+8F83(1,3);U+8F03(1,3) +U+8F84(0);U+8F84(1,3);U+8F12(1,3) +U+8F85(0);U+8F85(1,3);U+8F14(1,3) +U+8F86(0);U+8F86(1,3);U+8F1B(1,3) +U+8F87(0);U+8F87(1,3);U+8F26(1,3) +U+8F88(0);U+8F88(1,3);U+8F29(1,3) +U+8F89(0);U+8F89(1,3);U+8F1D(1,3) +U+8F8A(0);U+8F8A(1,3);U+8F25(1,3) +U+8F8B(0);U+8F8B(1,3);U+8F1E(1,3) +U+8F8C(0);U+8F8C(4);U+8F2C(4) +U+8F8D(0);U+8F8D(1,3);U+8F1F(1,3) +U+8F8E(0);U+8F8E(1,3);U+8F1C(1,3) +U+8F8F(0);U+8F8F(1,3);U+8F33(1,3) +U+8F90(0);U+8F90(1,3);U+8F3B(1,3) +U+8F91(0);U+8F91(1,3);U+8F2F(1,3) +U+8F92(0);U+8F92(4);U+8F3C(4),U+8F40(4) +U+8F93(0);U+8F93(1,3);U+8F38(1,3) +U+8F94(0);U+8F94(1,3);U+8F61(1,3) +U+8F95(0);U+8F95(1,3);U+8F45(1,3) +U+8F96(0);U+8F96(1,3);U+8F44(1,3) +U+8F97(0);U+8F97(1,3);U+8F3E(1,3) +U+8F98(0);U+8F98(1,3);U+8F46(1,3) +U+8F99(0);U+8F99(1,3);U+8F4D(1,3) +U+8F9A(0);U+8F9A(1,3);U+8F54(1,3) +U+8F9B(0);U+8F9B(5); +U+8F9C(0);U+8F9C(5); +U+8F9E(0);U+8F9E(1,3);U+8FAD(1,3) +U+8F9F(0);U+8F9F(1,3);U+907F(3),U+95E2(1,3,4) +U+8FA0(0);U+7F6A(2);U+7F6A(2) +U+8FA1(0);U+8FA1(0); +U+8FA2(0);U+8FA3(2);U+8FA3(2) +U+8FA3(0);U+8FA3(5);U+8FA2(2) +U+8FA5(0);U+8FA5(0); +U+8FA6(0);U+529E(1,3);U+529E(1,3),U+8FA8(3),U+8FA7(3),U+91C6(3,4) +U+8FA7(0);U+8FA8(3);U+8FA8(3),U+529E(1,3),U+8FA6(0,3),U+91C6(3,4) +U+8FA8(0);U+8FA8(5);U+8FA6(3),U+8FA7(3),U+91C6(4),U+529E(1,3) +U+8FA9(0);U+8FA9(1,3);U+8FAF(1,3) +U+8FAA(0);U+8FAA(0); +U+8FAB(0);U+8FAB(1,3);U+8FAE(1,3) +U+8FAC(0);U+8FAC(3); +U+8FAD(0);U+8F9E(1,3);U+8F9E(1,3) +U+8FAE(0);U+8FAB(1,3);U+8FAB(1,3) +U+8FAF(0);U+8FA9(1,3);U+8FA9(1,3) +U+8FB0(0);U+8FB0(5); +U+8FB1(0);U+8FB1(5); +U+8FB2(0);U+519C(1,3);U+519C(1,3) +U+8FB4(0);U+8FB4(0); +U+8FB5(0);U+8FB5(4); +U+8FB6(0);U+8FB6(5); +U+8FB7(0);U+8FB7(0); +U+8FB8(0);U+8FB8(0); +U+8FB9(0);U+8FB9(1,3);U+9089(3),U+908A(1,3) +U+8FBB(0);U+8FBB(0); +U+8FBC(0);U+8FBC(0); +U+8FBD(0);U+8FBD(1,3);U+907C(1,3) +U+8FBE(0);U+8FBE(1,3);U+8FD6(4),U+9054(1,3) + +U+8FBF(0);U+8FBF(0); +U+8FC0(0);U+8FC0(0); +U+8FC1(0);U+8FC1(1,3);U+9077(1,3) +U+8FC2(0);U+8FC2(5); +U+8FC4(0);U+8FC4(5); +U+8FC5(0);U+8FC5(5); +U+8FC6(0);U+8FE4(3,4);U+8FE4(3,4) +U+8FC7(0);U+8FC7(1,3);U+904E(1,3) +U+8FC8(0);U+8FC8(1,3);U+9081(1,3) +U+8FC9(0);U+8FC9(0); +U+8FCB(0);U+8FCB(0); +U+8FCC(0);U+8FCC(0); +U+8FCD(0);U+8FCD(0); +U+8FCE(0);U+8FCE(5); +U+8FCF(0);U+8FCF(0); +U+8FD0(0);U+8FD0(1,3);U+904B(1,3) +U+8FD1(0);U+8FD1(5); +U+8FD2(0);U+8FD2(0); +U+8FD3(0);U+8FD3(5); +U+8FD4(0);U+8FD4(5); +U+8FD5(0);U+8FD5(5); +U+8FD6(0);U+8FBE(4);U+8FBE(4),U+9054(1,3,4) +U+8FD7(0);U+8FD7(0); +U+8FD8(0);U+8FD8(1,3);U+9084(1,3) +U+8FD9(0);U+8FD9(1,3);U+9019(1,3) +U+8FDA(0);U+8FDA(0); +U+8FDB(0);U+8FDB(1,3);U+9032(1,3) +U+8FDC(0);U+8FDC(1,3);U+903A(4),U+9060(1,3) +U+8FDD(0);U+8FDD(1,3);U+9055(1,3) +U+8FDE(0);U+8FDE(1,3);U+9023(1,3) +U+8FDF(0);U+8FDF(1,3);U+8FE1(3),U+9045(3),U+905F(3),U+9072(1,3) +U+8FE0(0);U+8FE0(0); +U+8FE1(0);U+8FDF(3);U+8FDF(3),U+9045(3),U+905F(3),U+9072(1,3) +U+8FE2(0);U+8FE2(5); +U+8FE3(0);U+8FE3(0); +U+8FE4(0);U+8FE4(5);U+8FC6(3,4) +U+8FE5(0);U+8FE5(5);U+9008(2,3) +U+8FE6(0);U+8FE6(5); +U+8FE8(0);U+8FE8(5);U+902E(3) +U+8FE9(0);U+8FE9(1,3);U+9087(1,3) +U+8FEA(0);U+8FEA(5);U+5EF8(3) +U+8FEB(0);U+8FEB(5); +U+8FEC(0);U+8FEC(0);U+5F80(3),U+5F83(2,3) +U+8FED(0);U+8FED(5);U+66E1(4),U+758A(3,4),U+53E0(2,4,5),U+7589(2,4) +U+8FEE(0);U+8FEE(5); +U+8FEF(0);U+9003(3);U+9003(3) +U+8FF0(0);U+8FF0(5); +U+8FF1(0);U+8FF1(0); +U+8FF2(0);U+8FF2(0); +U+8FF3(0);U+8FF3(4);U+9015(4),U+5F84(1,3,4),U+5F91(1,3,4) +U+8FF4(0);U+56DE(1,3);U+56DE(1,3),U+5EFB(2),U+5EFD(8,9),U+9025(2,3),U+56D8(0,1,3,4),U+56EC(1,3,4) +U+8FF5(0);U+8FF5(0); +U+8FF6(0);U+8FF6(0); +U+8FF7(0);U+8FF7(5); +U+8FF8(0);U+8FF8(5); +U+8FF9(0);U+8FF9(5);U+8DE1(2,3),U+8E5F(2,3) +U+8FFA(0);U+4E43(2);U+4E43(2),U+5EFC(4) +U+8FFB(0);U+79FB(2,3);U+79FB(2,3) +U+8FFC(0);U+8FFC(0); +U+8FFD(0);U+8FFD(5); +U+8FFE(0);U+8FFE(3); +U+8FFF(0);U+8FFF(0); + +U+9000(0);U+9000(5); +U+9001(0);U+9001(5); +U+9002(0);U+9002(1,3);U+9069(1,3) +U+9003(0);U+9003(5);U+8FEF(3) +U+9004(0);U+9004(5); +U+9005(0);U+9005(5); +U+9006(0);U+9006(5); +U+9007(0);U+9007(0); +U+9008(0);U+8FE5(2,3);U+8FE5(2,3) +U+9009(0);U+9009(1,3);U+9078(1,3) +U+900A(0);U+900A(1,3);U+613B(3),U+905C(1,3) +U+900B(0);U+900B(5); +U+900C(0);U+6538(3);U+6538(3) +U+900D(0);U+900D(5); +U+900F(0);U+900F(5); +U+9010(0);U+9010(5); +U+9011(0);U+9011(5); +U+9012(0);U+9012(1,3);U+9013(4),U+905E(1,3) +U+9013(0);U+9012(4);U+9012(4),U+905E(4) +U+9014(0);U+9014(5); +U+9015(0);U+8FF3(4);U+5F84(4),U+5F91(2,3),U+8FF3(4) +U+9016(0);U+9016(5); +U+9017(0);U+9017(5); +U+9018(0);U+9018(0); +U+9019(0);U+8FD9(1,3);U+8FD9(1,3) +U+901A(0);U+901A(5); +U+901B(0);U+901B(5); +U+901C(0);U+901C(3); +U+901D(0);U+901D(5); +U+901E(0);U+901E(5); +U+901F(0);U+901F(5); +U+9020(0);U+9020(5); +U+9021(0);U+9021(5); +U+9022(0);U+9022(5); +U+9023(0);U+8FDE(1,3);U+8FDE(1,3) +U+9024(0);U+9024(0); +U+9025(0);U+56DE(4);U+56DE(4),U+5EFB(3),U+8FF4(2,3),U+56D8(0,3,4),U+56EC(3,4),U+5EFD(2,3,4) + +U+9026(0);U+9026(1,3);U+9090(1,3) +U+9027(0);U+9027(0); +U+9028(0);U+9028(0); +U+9029(0);U+5954(2,3);U+5954(2,3),U+7287(2,3) +U+902B(0);U+902B(0); +U+902D(0);U+902D(5); +U+902E(0);U+902E(5);U+8FE8(3) +U+902F(0);U+902F(5); +U+9030(0);U+6E38(3);U+6E38(3),U+904A(3) +U+9031(0);U+5468(2,3);U+5468(2,3) +U+9032(0);U+8FDB(1,3);U+8FDB(1,3) +U+9033(0);U+9033(0); +U+9034(0);U+9034(3); +U+9035(0);U+9035(5); +U+9036(0);U+9036(5); +U+9038(0);U+9038(5);U+52AE(4) +U+903A(0);U+8FDC(4);U+8FDC(4),U+9060(4) +U+903B(0);U+903B(1,3);U+908F(1,3) +U+903C(0);U+903C(5); +U+903D(0);U+903D(0); +U+903E(0);U+903E(5);U+8E30(2) +U+903F(0);U+903F(0); +U+9041(0);U+9041(5);U+906F(2,3) +U+9042(0);U+9042(5); +U+9043(0);U+9043(0); + +U+9044(0);U+9044(5); +U+9045(0);U+8FDF(3);U+8FDF(3),U+9072(3),U+8FE1(3),U+905F(3) +U+9047(0);U+9047(5); +U+9048(0);U+9048(0); +U+9049(0);U+4FA6(4);U+4FA6(4),U+5075(1,3,4) +U+904A(0);U+6E38(2,3);U+6E38(2,3),U+9030(3) +U+904B(0);U+8FD0(1,3);U+8FD0(1,3) +U+904C(0);U+904C(3); +U+904D(0);U+904D(5);U+5FA7(2,3) +U+904E(0);U+8FC7(1,3);U+8FC7(1,3) +U+904F(0);U+904F(5); +U+9050(0);U+9050(5); +U+9051(0);U+9051(5);U+5FA8(3) +U+9052(0);U+9052(5); +U+9053(0);U+9053(5); +U+9054(0);U+8FBE(1,3);U+8FBE(1,3),U+8FD6(1,3,4) +U+9055(0);U+8FDD(1,3);U+8FDD(1,3) +U+9056(0);U+9056(0); +U+9057(0);U+9057(1,3);U+907A(1,3) +U+9058(0);U+9058(5); +U+9059(0);U+9065(4);U+9065(4) +U+905A(0);U+905A(0); +U+905B(0);U+905B(5); +U+905C(0);U+900A(1,3);U+900A(1,3),U+613B(0,1,3) +U+905D(0);U+905D(0); +U+905E(0);U+9012(1,3);U+9012(1,3),U+9013(4) +U+905F(0);U+8FDF(3);U+8FDF(3),U+9072(3),U+8FE1(3),U+9045(3) +U+9060(0);U+8FDC(1,3);U+8FDC(1,3),U+903A(4) +U+9061(0);U+6EAF(2,3);U+6CDD(3),U+6EAF(2,3) +U+9062(0);U+9062(5); +U+9063(0);U+9063(5); +U+9064(0);U+9064(0); +U+9065(0);U+9065(5);U+9059(4) +U+9066(0);U+9066(0); +U+9067(0);U+7AE0(3);U+7AE0(3) +U+9068(0);U+9068(5); +U+9069(0);U+9002(1,3);U+9002(1,3) +U+906A(0);U+906A(0); +U+906B(0);U+906B(0); +U+906C(0);U+906C(4); +U+906D(0);U+906D(5); +U+906E(0);U+906E(5); +U+906F(0);U+9041(2,3);U+9041(2,3) +U+9070(0);U+9070(0); +U+9071(0);U+9071(0); +U+9072(0);U+8FDF(1,3);U+8FDF(1,3),U+9045(3),U+905F(3),U+8FE1(1,3) +U+9073(0);U+77EC(3);U+77EC(3) +U+9074(0);U+9074(5); +U+9075(0);U+9075(5); +U+9076(0);U+7ED5(4);U+7ED5(4),U+7E5E(0,1,3,4) +U+9077(0);U+8FC1(1,3);U+8FC1(1,3) +U+9078(0);U+9009(1,3);U+9009(1,3) +U+9079(0);U+9079(0); +U+907A(0);U+9057(1,3);U+9057(1,3) +U+907B(0);U+907B(0); +U+907C(0);U+8FBD(1,3);U+8FBD(1,3) +U+907D(0);U+907D(5); +U+907E(0);U+907E(0); +U+907F(0);U+907F(5);U+8F9F(3),U+95E2(1,3,4) +U+9080(0);U+9080(5); +U+9081(0);U+8FC8(1,3);U+8FC8(1,3) +U+9082(0);U+9082(5); +U+9083(0);U+9083(5); + +U+9084(0);U+8FD8(1,3);U+8FD8(1,3) +U+9085(0);U+9085(0); +U+9086(0);U+9086(0); +U+9087(0);U+8FE9(1,3);U+8FE9(1,3) +U+9088(0);U+9088(5); +U+9089(0);U+8FB9(3);U+8FB9(3),U+908A(3) +U+908A(0);U+8FB9(1,3);U+8FB9(1,3),U+9089(3) +U+908B(0);U+908B(5); +U+908C(0);U+908C(0); +U+908D(0);U+539F(4);U+539F(4) +U+908E(0);U+908E(0); +U+908F(0);U+903B(1,3);U+903B(1,3) +U+9090(0);U+9026(1,3);U+9026(1,3) +U+9091(0);U+9091(5); +U+9092(0);U+9092(0); +U+9093(0);U+9093(1,3);U+9127(1,3) +U+9094(0);U+9094(0); +U+9095(0);U+9095(5); +U+9096(0);U+9096(0); +U+9097(0);U+9097(5); +U+9098(0);U+9098(0); +U+9099(0);U+9099(5); +U+909A(0);U+909A(0); +U+909B(0);U+909B(5); +U+909C(0);U+909C(0); +U+909D(0);U+909D(1,3);U+913A(1,3) +U+909E(0);U+909E(0); +U+909F(0);U+909F(0); +U+90A0(0);U+90A0(0); +U+90A1(0);U+90A1(5); +U+90A2(0);U+90A2(5);U+90C9(3) +U+90A3(0);U+90A3(5); +U+90A4(0);U+90A4(0); +U+90A5(0);U+90A5(0); +U+90A6(0);U+90A6(5); +U+90A7(0);U+90A7(0); +U+90A8(0);U+6751(2,3);U+6751(2,3) +U+90A9(0);U+90A9(0); +U+90AA(0);U+90AA(5); +U+90AC(0);U+90AC(1,3);U+9114(1,3) +U+90AD(0);U+90AD(0); +U+90AE(0);U+90AE(1,3);U+90F5(1,3) +U+90AF(0);U+90AF(5); +U+90B0(0);U+90B0(5); +U+90B1(0);U+90B1(5); +U+90B2(0);U+90B2(0); +U+90B3(0);U+90B3(5); +U+90B4(0);U+90B4(5); +U+90B5(0);U+90B5(5); +U+90B6(0);U+90B6(5);U+9101(3) +U+90B7(0);U+90B7(0); +U+90B8(0);U+90B8(5); +U+90B9(0);U+90B9(1,3);U+9112(1,3) +U+90BA(0);U+90BA(1,3);U+9134(1,3) +U+90BB(0);U+90BB(1,3);U+9130(1,3),U+96A3(4) +U+90BC(0);U+90BC(0); +U+90BD(0);U+90BD(3); +U+90BE(0);U+90BE(5); +U+90BF(0);U+90BF(0); +U+90C0(0);U+90C0(0); +U+90C1(0);U+90C1(1,3);U+6B1D(2,3),U+9B30(4),U+9B31(1,3) +U+90C2(0);U+90C2(0); +U+90C3(0);U+90C3(0); + +U+90C4(0);U+90C4(5);U+9699(3) +U+90C5(0);U+90C5(5); +U+90C6(0);U+90C6(0); +U+90C7(0);U+90C7(5); +U+90C8(0);U+90C8(0); +U+90C9(0);U+90A2(3);U+90A2(3) +U+90CA(0);U+90CA(5); +U+90CB(0);U+90CB(0); +U+90CE(0);U+90CE(5);U+90DE(4) +U+90CF(0);U+90CF(1,3);U+90DF(1,3) +U+90D0(0);U+90D0(1,3);U+9136(1,3) +U+90D1(0);U+90D1(1,3);U+912D(1,3) +U+90D3(0);U+90D3(1,3);U+9106(1,3) +U+90D4(0);U+90D4(0); +U+90D5(0);U+90D5(0); +U+90D6(0);U+90D6(0); +U+90D7(0);U+90D7(5); +U+90D8(0);U+5415(3);U+5415(3),U+5442(3,4) +U+90D9(0);U+90D9(0); +U+90DA(0);U+90DA(0); +U+90DB(0);U+90DB(5); +U+90DC(0);U+90DC(5); +U+90DD(0);U+90DD(5); +U+90DE(0);U+90CE(4);U+90CE(4) +U+90DF(0);U+90CF(1,3);U+90CF(1,3) +U+90E0(0);U+90E0(0); +U+90E1(0);U+90E1(5); +U+90E2(0);U+90E2(5); +U+90E3(0);U+6E24(3);U+6E24(3) +U+90E4(0);U+90E4(0); +U+90E5(0);U+90E5(0); +U+90E6(0);U+90E6(1,3);U+9148(1,3) +U+90E7(0);U+90E7(1,3);U+9116(1,3) +U+90E8(0);U+90E8(5); +U+90E9(0);U+90E9(0); +U+90EA(0);U+90EA(0); +U+90EB(0);U+90EB(5); +U+90EC(0);U+90EC(0); +U+90ED(0);U+90ED(5);U+588E(3) +U+90EE(0);U+90EE(0); +U+90EF(0);U+90EF(5); +U+90F0(0);U+9139(3);U+9139(3) +U+90F1(0);U+90F1(0); +U+90F2(0);U+83B1(3);U+83B1(3),U+840A(1,3) +U+90F3(0);U+90F3(3); +U+90F4(0);U+90F4(5); +U+90F5(0);U+90AE(1,3);U+90AE(1,3) +U+90F7(0);U+4E61(3);U+4E61(3),U+9109(3),U+9115(3,4) +U+90F8(0);U+90F8(1,3);U+9132(1,3) +U+90F9(0);U+90F9(0); +U+90FA(0);U+90FA(0); +U+90FB(0);U+90FB(0); +U+90FC(0);U+90FC(0); +U+90FD(0);U+90FD(5); +U+90FE(0);U+90FE(5); +U+90FF(0);U+90FF(0); +U+9100(0);U+9100(0); +U+9101(0);U+90B6(3);U+90B6(3) +U+9102(0);U+9102(5); +U+9103(0);U+4FDE(4);U+4FDE(4),U+516A(3,4) +U+9104(0);U+9104(5); +U+9105(0);U+9105(0); +U+9106(0);U+90D3(1,3);U+90D3(1,3) + +U+9107(0);U+9107(0); +U+9108(0);U+9108(0); +U+9109(0);U+4E61(1,3);U+4E61(1,3),U+90F7(3),U+9115(4) +U+910B(0);U+910B(3); +U+910C(0);U+910C(0); +U+910D(0);U+910D(0); +U+910E(0);U+910E(0); +U+910F(0);U+910F(0); +U+9110(0);U+9110(0); +U+9111(0);U+9111(0); +U+9112(0);U+90B9(1,3);U+90B9(1,3) +U+9113(0);U+9113(0); +U+9114(0);U+90AC(1,3);U+90AC(1,3) +U+9115(0);U+4E61(4);U+4E61(4),U+9109(4),U+90F7(3,4) +U+9116(0);U+90E7(1,3);U+90E7(1,3) +U+9117(0);U+9117(0); +U+9118(0);U+9118(0); +U+9119(0);U+9119(5); +U+911A(0);U+911A(0); +U+911B(0);U+911B(0); +U+911C(0);U+911C(0); +U+911D(0);U+911D(0); +U+911E(0);U+911E(5); +U+911F(0);U+911F(0); +U+9120(0);U+9120(0); +U+9121(0);U+9121(0); +U+9122(0);U+9122(5); +U+9123(0);U+9123(5); +U+9124(0);U+9124(0); +U+9125(0);U+9125(0); +U+9126(0);U+8BB8(3);U+8BB8(3),U+8A31(0,1,3) +U+9127(0);U+9093(1,3);U+9093(1,3) +U+9128(0);U+9128(0); +U+9129(0);U+9129(0); +U+912A(0);U+912A(3); +U+912B(0);U+912B(0); +U+912C(0);U+912C(0); +U+912D(0);U+90D1(1,3);U+90D1(1,3) +U+912E(0);U+912E(0); +U+912F(0);U+912F(5); +U+9130(0);U+90BB(1,3);U+90BB(1,3),U+96A3(2,3) +U+9131(0);U+9131(5); +U+9132(0);U+90F8(1,3);U+90F8(1,3) +U+9133(0);U+9133(0); +U+9134(0);U+90BA(1,3);U+90BA(1,3) +U+9135(0);U+9135(0); +U+9136(0);U+90D0(1,3);U+90D0(1,3) +U+9137(0);U+9146(3);U+9146(3) +U+9138(0);U+9138(0); +U+9139(0);U+9139(5);U+90F0(3) +U+913A(0);U+909D(1,3);U+909D(1,3) +U+913B(0);U+913B(0); +U+913E(0);U+913E(0); +U+913F(0);U+913F(0); +U+9140(0);U+9140(0); +U+9141(0);U+9141(0); +U+9142(0);U+9142(4);U+9147(4) +U+9143(0);U+9143(5); +U+9144(0);U+9144(0); +U+9145(0);U+9145(4); +U+9146(0);U+9146(5);U+9137(3) +U+9147(0);U+9142(4);U+9142(4) +U+9148(0);U+90E6(1,3);U+90E6(1,3) + +U+9149(0);U+9149(5);U+4E23(3) +U+914A(0);U+914A(5); +U+914B(0);U+914B(5); +U+914C(0);U+914C(5); +U+914D(0);U+914D(5); +U+914E(0);U+914E(5); +U+914F(0);U+914F(5); +U+9150(0);U+9150(5); +U+9151(0);U+9151(0); +U+9152(0);U+9152(5); +U+9153(0);U+9153(0); +U+9154(0);U+9189(3);U+9189(3) +U+9155(0);U+9155(0); +U+9156(0);U+9156(0); +U+9157(0);U+9157(5); +U+9158(0);U+9158(3); +U+915A(0);U+915A(5); +U+915B(0);U+915B(0); +U+915C(0);U+915C(0); +U+915D(0);U+915D(1,3,4);U+9196(1,3),U+919E(4) +U+915E(0);U+915E(5); +U+915F(0);U+915F(0); +U+9160(0);U+9160(0); +U+9161(0);U+9161(5); +U+9162(0);U+9162(5);U+918B(3) +U+9163(0);U+9163(5); +U+9164(0);U+9164(5); +U+9165(0);U+9165(5); +U+9166(0);U+9166(4);U+91B1(4) +U+9167(0);U+916C(2,3);U+916C(2,3),U+8A76(0,2,3),U+91BB(2,3) +U+9168(0);U+9168(0); +U+9169(0);U+9169(5); +U+916A(0);U+916A(5); +U+916B(0);U+916B(0); +U+916C(0);U+916C(5);U+8A76(2,3),U+9167(2,3),U+91BB(2,3) +U+916D(0);U+916D(0); +U+916E(0);U+916E(5); +U+916F(0);U+916F(5); +U+9170(0);U+9170(5); +U+9171(0);U+9171(1,3);U+91AC(1,3) +U+9172(0);U+9172(5); +U+9173(0);U+9173(0); +U+9174(0);U+9174(5); +U+9175(0);U+9175(5); +U+9176(0);U+9176(5); +U+9177(0);U+9177(5); +U+9178(0);U+9178(5); +U+9179(0);U+9179(5); +U+917A(0);U+917A(3); +U+917C(0);U+917C(0); +U+917D(0);U+917D(1,3);U+91C5(1,3) +U+917E(0);U+917E(1,3);U+91C3(1,3) +U+917F(0);U+917F(1,3);U+91C0(1,3) +U+9180(0);U+9180(0); +U+9181(0);U+9181(3); +U+9182(0);U+9182(0); +U+9183(0);U+814C(2);U+814C(2) +U+9184(0);U+9184(0); +U+9185(0);U+9185(5); +U+9186(0);U+76CF(4);U+76CF(4),U+7416(0,4),U+76DE(1,3,4) +U+9187(0);U+9187(5); +U+9188(0);U+9188(0); +U+9189(0);U+9189(5);U+9154(3) + +U+918A(0);U+918A(3); +U+918B(0);U+918B(5);U+9162(3) +U+918C(0);U+918C(5); +U+918D(0);U+918D(5); +U+918E(0);U+918E(0); +U+918F(0);U+918F(0); +U+9190(0);U+9190(5); +U+9191(0);U+9191(5); +U+9192(0);U+9192(5); +U+9193(0);U+9193(0); +U+9194(0);U+9194(0); +U+9196(0);U+915D(1,3);U+915D(1,3),U+919E(8,9) +U+9199(0);U+9199(0); +U+919A(0);U+919A(5); +U+919B(0);U+919B(5); +U+919C(0);U+4E11(1,3);U+4E11(1,3) +U+919D(0);U+919D(3); +U+919E(0);U+915D(4);U+915D(4),U+9196(8,9) +U+919F(0);U+919F(0); +U+91A0(0);U+91A0(0); +U+91A1(0);U+69A8(3);U+69A8(3),U+643E(0,2,3) +U+91A2(0);U+91A2(5); +U+91A3(0);U+91A3(5); +U+91A5(0);U+91A5(0); +U+91A6(0);U+91A6(0); +U+91A7(0);U+91A7(0); +U+91A8(0);U+91A8(3); +U+91AA(0);U+91AA(5); +U+91AB(0);U+533B(1,3);U+533B(1,3),U+6BC9(1,3) +U+91AC(0);U+9171(1,3);U+9171(1,3) +U+91AD(0);U+91AD(5); +U+91AE(0);U+91AE(5); +U+91AF(0);U+91AF(5); +U+91B0(0);U+91B0(0); +U+91B1(0);U+9166(4);U+9166(4) +U+91B2(0);U+91B2(3); +U+91B3(0);U+91B3(0); +U+91B4(0);U+91B4(5); +U+91B5(0);U+91B5(5); +U+91B6(0);U+91B6(3); +U+91B7(0);U+91B7(0); +U+91B9(0);U+91B9(0); +U+91BA(0);U+91BA(5); +U+91BB(0);U+916C(2,3);U+916C(2,3),U+8A76(0,2,3),U+9167(2,3) +U+91BC(0);U+5BB4(2,3);U+5BB4(2,3) +U+91BD(0);U+91BD(0); +U+91BE(0);U+91BE(3); +U+91C0(0);U+917F(1,3);U+917F(1,3) +U+91C1(0);U+8845(1,3);U+8845(1,3) +U+91C2(0);U+91C2(0); +U+91C3(0);U+917E(1,3);U+917E(1,3) +U+91C5(0);U+917D(1,3);U+917D(1,3) +U+91C6(0);U+8FA8(4);U+8FA8(4),U+529E(1,3,4),U+8FA6(0,3,4),U+8FA7(3,4) +U+91C7(0);U+91C7(5);U+63A1(2,3) +U+91C9(0);U+91C9(5); +U+91CA(0);U+91CA(1,3);U+91CB(1,3) +U+91CB(0);U+91CA(1,3);U+91CA(1,3) +U+91CC(0);U+91CC(1,3,4);U+88CF(1,3,4),U+88E1(4) +U+91CD(0);U+91CD(5);U+7DDF(3) +U+91CE(0);U+91CE(5);U+57DC(2,3) +U+91CF(0);U+91CF(5); +U+91D0(0);U+5398(2,3);U+5398(2,3) +U+91D1(0);U+91D1(5);U+91D2(8,9),U+9485(8,9) + +U+91D2(0);U+9485(4);U+91D1(8,9),U+9485(4) +U+91D3(0);U+9486(1,3);U+9486(1,3) +U+91D4(0);U+9487(1,3);U+9487(1,3) +U+91D5(0);U+948C(1,3);U+948C(1,3) +U+91D7(0);U+948A(1,3);U+948A(1,3) +U+91D8(0);U+9489(1,3);U+9489(1,3) +U+91D9(0);U+948B(1,3);U+948B(1,3) +U+91DA(0);U+91DA(3); +U+91DB(0);U+91DB(0); +U+91DC(0);U+91DC(5); +U+91DD(0);U+9488(1,3);U+9488(1,3) +U+91DE(0);U+91DE(0); +U+91DF(0);U+91DF(0); +U+91E2(0);U+91E2(0); +U+91E3(0);U+9493(1);U+9493(1),U+9B61(1,4) +U+91E4(0);U+9490(1,3);U+9490(1,3) +U+91E5(0);U+91E5(0); +U+91E6(0);U+6263(2);U+6263(2) +U+91E7(0);U+948F(1,3);U+948F(1,3) +U+91E8(0);U+91E8(0); +U+91E9(0);U+9492(1,3);U+9492(1,3) +U+91EA(0);U+91EA(0); +U+91EB(0);U+91EB(0); +U+91EC(0);U+710A(2,3);U+710A(2,3),U+92B2(2,3) +U+91ED(0);U+91ED(0); +U+91EE(0);U+91EE(0); +U+91F0(0);U+91F0(0); +U+91F1(0);U+91F1(3); +U+91F2(0);U+91F2(0); +U+91F3(0);U+91F3(0); +U+91F4(0);U+91F4(0); +U+91F5(0);U+9497(1,3);U+9497(1,3) +U+91F7(0);U+948D(1,3);U+948D(1,3) +U+91F8(0);U+91F8(0); +U+91F9(0);U+9495(1,3);U+9495(1,3) +U+91FA(0);U+948E(1,3);U+948E(1,3) +U+91FB(0);U+91FB(0); +U+91FD(0);U+91FD(0); +U+91FE(0);U+497A(1,3);U+497A(1,3) +U+91FF(0);U+91FF(3); +U+9200(0);U+94AF(1,3);U+94AF(1,3) +U+9201(0);U+94AB(1,3);U+94AB(1,3) +U+9202(0);U+9202(0); +U+9203(0);U+9498(1,3);U+9498(1,3) +U+9204(0);U+94AD(1,3);U+94AD(1,3) +U+9205(0);U+94A5(4);U+94A5(4),U+9470(1,3,4) +U+9206(0);U+94C5(2);U+94C5(2),U+925B(1,2,3) +U+9207(0);U+9207(0); +U+9208(0);U+949A(1,3);U+949A(1,3) +U+9209(0);U+94A0(1,3);U+94A0(1,3) +U+920A(0);U+920A(0); +U+920B(0);U+920B(0); +U+920C(0);U+920C(0); +U+920D(0);U+949D(1,3);U+949D(1,3) +U+920E(0);U+94A9(1,3);U+9264(2,3),U+94A9(1,3) +U+920F(0);U+920F(0); +U+9210(0);U+94A4(1,3);U+94A4(1,3) +U+9211(0);U+94A3(4);U+94A3(4) +U+9212(0);U+9491(4);U+9491(4) +U+9214(0);U+949E(1,3);U+949E(1,3) +U+9215(0);U+94AE(1,3);U+94AE(1,3) +U+9216(0);U+9216(0); +U+9217(0);U+9217(3); + +U+9218(0);U+9218(0); +U+9219(0);U+9219(0); +U+921A(0);U+921A(3); +U+921B(0);U+921B(0); +U+921C(0);U+921C(0); +U+921D(0);U+921D(0); +U+921E(0);U+94A7(1,3);U+94A7(1,3) +U+9220(0);U+9220(0); +U+9221(0);U+949F(4);U+9418(4),U+949F(4),U+87A4(0,3,4),U+937E(1,3,4),U+953A(1,3,4) +U+9223(0);U+9499(1,3);U+9499(1,3) +U+9224(0);U+9224(0); +U+9225(0);U+94AC(1,3);U+94AC(1,3) +U+9226(0);U+949B(1,3);U+949B(1,3) +U+9227(0);U+94AA(1,3);U+94AA(1,3) +U+9228(0);U+9228(0); +U+9229(0);U+9229(0); +U+922A(0);U+922A(0); +U+922B(0);U+922B(0); +U+922D(0);U+922D(0); +U+922E(0);U+94CC(1,3);U+94CC(1,3) +U+922F(0);U+922F(0); +U+9230(0);U+94C8(1,3);U+94C8(1,3) +U+9231(0);U+9231(0); +U+9232(0);U+9232(0); +U+9233(0);U+94B6(1,3);U+94B6(1,3) +U+9234(0);U+94C3(1,3);U+94C3(1,3) +U+9235(0);U+9235(0); +U+9236(0);U+9236(0); +U+9237(0);U+94B4(1,3);U+94B4(1,3) +U+9238(0);U+94B9(1);U+94B9(1) +U+9239(0);U+94CD(1,3);U+94CD(1,3) +U+923A(0);U+94B0(1,3);U+94B0(1,3) +U+923B(0);U+923B(0); +U+923C(0);U+923C(0); +U+923D(0);U+94B8(4);U+94B8(4) +U+923E(0);U+94C0(1,3);U+94C0(1,3) +U+923F(0);U+94BF(1,3);U+94BF(1,3) +U+9240(0);U+94BE(1,3);U+94BE(1,3) +U+9241(0);U+9241(0); +U+9242(0);U+9242(0); +U+9245(0);U+5DE8(2,3);U+5DE8(2,3),U+949C(4) +U+9246(0);U+94BB(4);U+94BB(4),U+947D(1,3,4),U+9409(4) +U+9247(0);U+9247(4); +U+9248(0);U+94CA(1,3);U+94CA(1,3) +U+9249(0);U+94C9(1,3);U+94C9(1,3) +U+924A(0);U+924A(0); +U+924B(0);U+94C7(4);U+94C7(4) +U+924C(0);U+548C(3);U+548C(3),U+9FA2(2,3) +U+924D(0);U+94CB(1,3);U+94CB(1,3) +U+924E(0);U+924E(0); +U+924F(0);U+924F(0); +U+9250(0);U+9250(0); +U+9251(0);U+94C2(1,3);U+94C2(1,3) +U+9252(0);U+9252(0); +U+9253(0);U+9253(0); +U+9254(0);U+9254(0); +U+9255(0);U+94B7(1,3);U+94B7(1,3) +U+9256(0);U+9256(0); +U+9257(0);U+94B3(1,3);U+7B9D(3),U+94B3(1,3),U+62D1(0,1,3,4) +U+9258(0);U+9258(0); +U+9259(0);U+9259(0); +U+925A(0);U+94C6(1,3);U+94C6(1,3) +U+925B(0);U+94C5(1,3);U+94C5(1,3),U+9206(0,1,2,3) + +U+925C(0);U+925C(0); +U+925D(0);U+925D(0); +U+925E(0);U+94BA(1,3);U+94BA(1,3) +U+925F(0);U+925F(3); +U+9260(0);U+9260(3); +U+9261(0);U+9261(0); +U+9262(0);U+94B5(1,3);U+7F3D(2,3),U+94B5(1,3) +U+9263(0);U+9263(0); +U+9264(0);U+94A9(4);U+920E(2,3),U+94A9(4) +U+9265(0);U+9265(3); +U+9266(0);U+94B2(1,3);U+94B2(1,3) +U+9267(0);U+9267(0); +U+9268(0);U+9268(4); +U+926B(0);U+926B(0); +U+926C(0);U+94BC(1,3);U+94BC(1,3) +U+926D(0);U+94BD(1,3);U+94BD(1,3) +U+926E(0);U+926E(0); +U+926F(0);U+926F(0); +U+9270(0);U+9270(0); +U+9272(0);U+9272(0); +U+9273(0);U+9273(0); +U+9274(0);U+9274(1,3,4);U+9451(4),U+9452(1,3) +U+9275(0);U+9275(0); +U+9276(0);U+94CF(1,3);U+94CF(1,3) +U+9277(0);U+9277(0); +U+9278(0);U+94F0(1,3);U+94F0(1,3) +U+9279(0);U+9279(0); +U+927A(0);U+94D2(1,3);U+94D2(1,3) +U+927B(0);U+94EC(1,3);U+94EC(1,3) +U+927C(0);U+927C(0); +U+927D(0);U+927D(0); +U+927E(0);U+927E(0); +U+927F(0);U+94EA(1,3);U+94EA(1,3) +U+9280(0);U+94F6(1,3);U+94F6(1,3) +U+9282(0);U+9282(0); +U+9283(0);U+94F3(1,3);U+94F3(1,3) +U+9285(0);U+94DC(1,3);U+94DC(1,3) +U+9286(0);U+9286(0); +U+9287(0);U+9287(0); +U+9288(0);U+9288(0); +U+9289(0);U+9289(0); +U+928A(0);U+928A(0); +U+928B(0);U+928B(3); +U+928C(0);U+928C(0); +U+928D(0);U+94DA(4);U+94DA(4) +U+928E(0);U+928E(5); +U+928F(0);U+928F(0); +U+9290(0);U+9290(0); +U+9291(0);U+94E3(1,3);U+94E3(1,3) +U+9292(0);U+9292(3); +U+9293(0);U+94E8(1,3);U+94E8(1,3) +U+9294(0);U+9294(3); +U+9295(0);U+94C1(3);U+9435(3),U+94C1(3) +U+9296(0);U+94E2(1,3);U+94E2(1,3) +U+9297(0);U+9297(0); +U+9298(0);U+94ED(1,3);U+94ED(1,3) +U+9299(0);U+9299(3); +U+929A(0);U+94EB(1,3);U+94EB(1,3) +U+929B(0);U+94E6(4);U+94E6(4) +U+929C(0);U+8854(1,3);U+8854(1,3),U+5563(0,1,3,4) +U+929D(0);U+929D(0); +U+929F(0);U+929F(0); +U+92A0(0);U+94D1(1,3);U+94D1(1,3) + +U+92A1(0);U+92A1(0); +U+92A2(0);U+92A2(0); +U+92A3(0);U+94F7(1,3);U+94F7(1,3) +U+92A4(0);U+92A4(0); +U+92A5(0);U+94F1(1,3);U+94F1(1,3) +U+92A6(0);U+94DF(1,3);U+94DF(1,3) +U+92A7(0);U+92A7(0); +U+92A8(0);U+94F5(1,3);U+94F5(1,3) +U+92A9(0);U+94E5(1,3);U+94E5(1,3) +U+92AA(0);U+94D5(1,3);U+94D5(1,3) +U+92AB(0);U+94EF(1,3);U+94EF(1,3) +U+92AC(0);U+94D0(1,3);U+94D0(1,3) +U+92AD(0);U+94B1(3);U+9322(3),U+94B1(3) +U+92AE(0);U+92AE(1,3);U+947E(1,3) +U+92AF(0);U+92AF(0); +U+92B0(0);U+92B0(0); +U+92B1(0);U+94DE(1,3);U+94DE(1,3) +U+92B2(0);U+710A(2);U+710A(2),U+91EC(2,3) +U+92B3(0);U+9510(4);U+92ED(8,9),U+9510(4) +U+92B4(0);U+92B4(0); +U+92B5(0);U+92B5(3); +U+92B6(0);U+92B6(3); +U+92B7(0);U+9500(1,3);U+9500(1,3) +U+92B8(0);U+92B8(0); +U+92B9(0);U+9508(1,3);U+93FD(2,3),U+9508(1,3) +U+92BA(0);U+92BA(0); +U+92BB(0);U+9511(1,3);U+9511(1,3) +U+92BC(0);U+9509(1,3);U+9509(1,3) +U+92BE(0);U+92BE(0); +U+92BF(0);U+92BF(0); +U+92C0(0);U+92C0(0); +U+92C1(0);U+94DD(1,3);U+94DD(1,3) +U+92C2(0);U+92C2(0); +U+92C3(0);U+9512(1,3);U+9512(1,3) +U+92C4(0);U+933D(3);U+933D(3) +U+92C5(0);U+950C(1,3);U+950C(1,3) +U+92C6(0);U+92C6(0); +U+92C7(0);U+94A1(1,3);U+94A1(1,3) +U+92C8(0);U+92C8(5); +U+92C9(0);U+92C9(0); +U+92CA(0);U+92CA(0); +U+92CB(0);U+92CB(0); +U+92CC(0);U+94E4(1,3);U+94E4(1,3) +U+92CD(0);U+92CD(0); +U+92CE(0);U+92CE(0); +U+92CF(0);U+94D7(1,3);U+94D7(1,3) +U+92D0(0);U+92D0(0); +U+92D1(0);U+92D1(0); +U+92D2(0);U+950B(1,3);U+950B(1,3) +U+92D3(0);U+92D3(0); +U+92D5(0);U+92D5(0); +U+92D6(0);U+92D6(0); +U+92D7(0);U+92D7(0); +U+92D8(0);U+92D8(0); +U+92D9(0);U+94FB(4);U+94FB(4) +U+92DA(0);U+92DA(0); +U+92DC(0);U+92DC(0); +U+92DD(0);U+950A(4);U+950A(4) +U+92DE(0);U+92DE(3); +U+92DF(0);U+9513(1,3);U+9513(1,3) +U+92E0(0);U+92E0(0); +U+92E1(0);U+92E1(0); +U+92E3(0);U+94D8(4);U+94D8(4) + +U+92E4(0);U+9504(1,3);U+8021(2,3),U+9504(1,3) +U+92E5(0);U+9503(1,3);U+9503(1,3) +U+92E6(0);U+9514(1,3);U+9514(1,3) +U+92E7(0);U+92E7(0); +U+92E8(0);U+9507(1,3);U+9507(1,3) +U+92E9(0);U+94D3(1,3);U+94D3(1,3) +U+92EA(0);U+94FA(1,3);U+8216(2,3),U+94FA(1,3) +U+92EB(0);U+92EB(0); +U+92EC(0);U+92EC(0); +U+92ED(0);U+9510(1,3);U+92B3(8,9),U+9510(1,3) +U+92EE(0);U+94D6(4);U+94D6(4) +U+92EF(0);U+9506(1,3);U+9506(1,3) +U+92F0(0);U+9502(1,3);U+9502(1,3) +U+92F1(0);U+94FD(1,3);U+94FD(1,3) +U+92F2(0);U+92F2(0); +U+92F3(0);U+94F8(4);U+9444(4),U+94F8(4) +U+92F4(0);U+92F4(0); +U+92F5(0);U+92F5(0); +U+92F6(0);U+950D(4);U+950D(4) +U+92F7(0);U+92F7(0); +U+92F8(0);U+952F(1,3);U+952F(1,3) +U+92F9(0);U+92F9(0); +U+92FA(0);U+7897(3);U+7897(3) +U+92FB(0);U+92FB(0); +U+92FC(0);U+94A2(1,3);U+94A2(1,3) +U+92FD(0);U+92FD(0); +U+92FE(0);U+92FE(0); +U+92FF(0);U+92FF(3); +U+9300(0);U+9300(0); +U+9301(0);U+951E(1,3);U+951E(1,3) +U+9302(0);U+9302(0); +U+9303(0);U+9303(0); +U+9304(0);U+5F55(4);U+5F55(4),U+9332(4),U+5F54(0,3,4) +U+9305(0);U+9305(0); +U+9306(0);U+9516(4);U+9516(4) +U+9307(0);U+952B(1,3);U+952B(1,3) +U+9308(0);U+9529(4);U+9529(4) +U+9309(0);U+9309(0); +U+930A(0);U+930A(0); +U+930B(0);U+955A(4);U+93F0(4),U+955A(4) +U+930C(0);U+930C(0); +U+930D(0);U+930D(0); +U+930E(0);U+930E(0); +U+930F(0);U+94D4(4);U+94D4(4) +U+9310(0);U+9525(1,3);U+9525(1,3) +U+9311(0);U+9311(3); +U+9312(0);U+9515(1,3);U+9515(1,3) +U+9313(0);U+9313(0); +U+9314(0);U+9314(0); +U+9315(0);U+951F(1,3);U+951F(1,3) +U+9316(0);U+9316(0); +U+9317(0);U+9317(0); +U+9318(0);U+9524(1,3);U+9524(1,3),U+939A(1,2,3) +U+9319(0);U+9531(1,3);U+9531(1,3) +U+931A(0);U+94EE(1,3);U+94EE(1,3) +U+931B(0);U+951B(1,3);U+951B(1,3) +U+931D(0);U+931D(0); +U+931E(0);U+931E(3); +U+931F(0);U+952C(4);U+952C(4) +U+9320(0);U+952D(1,3);U+952D(1,3) +U+9321(0);U+951C(4);U+951C(4) +U+9322(0);U+94B1(1,3);U+92AD(3),U+94B1(1,3) +U+9323(0);U+9323(0); + +U+9324(0);U+9324(0); +U+9325(0);U+9325(0); +U+9326(0);U+9526(1,3);U+9526(1,3) +U+9327(0);U+9327(0); +U+9328(0);U+951A(1,3);U+951A(1,3) +U+9329(0);U+9520(4);U+9520(4) +U+932A(0);U+932A(0); +U+932B(0);U+9521(1,3);U+9521(1,3) +U+932D(0);U+932D(3); +U+932E(0);U+9522(1,3);U+9522(1,3) +U+932F(0);U+9519(1,3);U+9519(1,3) +U+9332(0);U+5F55(1,3);U+5F55(1,3),U+9304(4),U+5F54(0,1,3) +U+9333(0);U+9530(1,3);U+9530(1,3) +U+9334(0);U+9334(0); +U+9335(0);U+9335(0); +U+9336(0);U+8868(1,3);U+8868(1,3) +U+9337(0);U+9337(0); +U+9338(0);U+94FC(1,3);U+94FC(1,3) +U+9339(0);U+9339(0); +U+933A(0);U+933A(0); +U+933B(0);U+933B(0); +U+933C(0);U+637A(4);U+637A(4) +U+933D(0);U+933D(3);U+92C4(3) +U+933E(0);U+933E(1,3);U+93E8(1,3) +U+933F(0);U+933F(0); +U+9340(0);U+951D(1,3);U+951D(1,3) +U+9341(0);U+9528(1,3);U+9528(1,3) +U+9342(0);U+9342(0); +U+9343(0);U+952A(4);U+952A(4) +U+9344(0);U+9344(0); +U+9345(0);U+9345(0); +U+9346(0);U+9494(1,3);U+9494(1,3) +U+9347(0);U+9534(1,3);U+9534(1,3) +U+9348(0);U+9533(4);U+9533(4) +U+9349(0);U+9349(0); +U+934A(0);U+70BC(4);U+70BC(4),U+7149(1,3,4) +U+934B(0);U+9505(1,3);U+9505(1,3) +U+934C(0);U+934C(0); +U+934D(0);U+9540(1,3);U+9540(1,3) +U+934E(0);U+934E(0); +U+934F(0);U+934F(0); +U+9350(0);U+9350(3); +U+9351(0);U+9351(3); +U+9352(0);U+9352(3); +U+9353(0);U+9353(0); +U+9354(0);U+9537(1,3);U+9537(1,3) +U+9355(0);U+9355(0); +U+9356(0);U+9356(0); +U+9357(0);U+9357(0); +U+9358(0);U+94E1(1,3);U+94E1(1,3) +U+9359(0);U+9359(0); +U+935A(0);U+9496(1,3);U+9496(1,3),U+940A(1,3) +U+935B(0);U+953B(1,3);U+7145(3),U+953B(1,3) +U+935C(0);U+935C(0); +U+935D(0);U+935D(0); +U+935E(0);U+94FF(3);U+94FF(3),U+93D7(1,3) +U+935F(0);U+935F(3); +U+9360(0);U+953D(4);U+953D(4) +U+9361(0);U+9361(0); +U+9363(0);U+9363(0); +U+9364(0);U+9538(1,3);U+9538(1,3),U+81FF(0,1,3,4) +U+9365(0);U+9532(1,3);U+9532(1,3),U+9411(1,3) +U+9366(0);U+9366(3); + +U+9367(0);U+9367(0); +U+9369(0);U+9518(1,3);U+9518(1,3) +U+936A(0);U+936A(5); +U+936C(0);U+9539(1,3);U+9539(1,3) +U+936D(0);U+936D(0); +U+936E(0);U+936E(3); +U+9370(0);U+953E(1,3);U+953E(1,3) +U+9371(0);U+9371(3);U+9437(3) +U+9372(0);U+9372(3); +U+9374(0);U+9374(0); +U+9375(0);U+952E(1,3);U+952E(1,3),U+9473(1,3) +U+9376(0);U+9536(1,3);U+9536(1,3) +U+9377(0);U+9377(0); +U+9379(0);U+9379(0); +U+937A(0);U+9517(1,3);U+9517(1,3) +U+937B(0);U+937B(0); +U+937C(0);U+937C(0); +U+937D(0);U+937D(0); +U+937E(0);U+949F(1,3);U+9418(3),U+949F(1,3),U+953A(4),U+87A4(0,1,3),U+9221(1,3,4) +U+9380(0);U+9380(0); +U+9382(0);U+9541(1,3);U+9541(1,3) +U+9383(0);U+9383(0); +U+9384(0);U+953F(1,3);U+953F(1,3) +U+9385(0);U+9385(0); +U+9386(0);U+9386(0); +U+9387(0);U+9545(1,3);U+9545(1,3) +U+9388(0);U+9388(0); +U+9389(0);U+9389(0); +U+938A(0);U+9551(1,3);U+9551(1,3) +U+938C(0);U+9570(2,3);U+9570(2,3),U+5286(0,2,3),U+942E(2,3) +U+938D(0);U+938D(0); +U+938E(0);U+938E(0); +U+938F(0);U+938F(5); +U+9390(0);U+9390(0); +U+9391(0);U+9391(0); +U+9392(0);U+9392(3); +U+9393(0);U+9393(0); +U+9394(0);U+9555(4);U+7194(2),U+9555(4) +U+9395(0);U+9395(0); +U+9396(0);U+9501(1,3);U+93C1(3),U+9501(1,3) +U+9397(0);U+9397(0); +U+9398(0);U+9549(1,3);U+9549(1,3) +U+9399(0);U+77DF(4);U+77DF(4) +U+939A(0);U+9524(2);U+9524(2),U+9318(0,1,2,3) +U+939B(0);U+9548(4);U+9548(4),U+93C4(4),U+946E(3,4) +U+939D(0);U+939D(0); +U+939E(0);U+939E(3); +U+939F(0);U+939F(0); +U+93A1(0);U+9543(1,3);U+9543(1,3) +U+93A2(0);U+94A8(1,3);U+94A8(1,3) +U+93A3(0);U+84E5(4);U+84E5(4) +U+93A4(0);U+93A4(0); +U+93A5(0);U+93A5(0); +U+93A6(0);U+954F(1,3);U+954F(1,3) +U+93A7(0);U+94E0(1,3);U+94E0(1,3) +U+93A8(0);U+93A8(0); +U+93A9(0);U+94E9(1,3);U+94E9(1,3) +U+93AA(0);U+953C(1,3);U+953C(1,3) +U+93AC(0);U+9550(1,3);U+9550(1,3) +U+93AD(0);U+9547(3);U+93AE(3),U+9547(3) +U+93AE(0);U+9547(1,3);U+93AD(3),U+9547(1,3) +U+93AF(0);U+93AF(0); +U+93B0(0);U+9552(1,3);U+9552(1,3),U+8CF9(0,1,3) + +U+93B1(0);U+93B1(0); +U+93B2(0);U+954B(4);U+954B(4),U+9482(1,3,4) +U+93B3(0);U+954D(1,3);U+954D(1,3) +U+93B4(0);U+93B4(0); +U+93B5(0);U+9553(1,3);U+9553(1,3) +U+93B6(0);U+93B6(0); +U+93B7(0);U+93B7(0); +U+93B8(0);U+954C(1,3);U+954C(1,3),U+942B(1,3,4) +U+93B9(0);U+93B9(0); +U+93BA(0);U+93BA(0); +U+93BC(0);U+93BC(0); +U+93BD(0);U+93BD(0); +U+93BE(0);U+93BE(0); +U+93BF(0);U+954E(1,3);U+954E(1,3) +U+93C0(0);U+942A(3);U+942A(3) +U+93C1(0);U+9501(3);U+9396(3),U+9501(3) +U+93C2(0);U+93C2(0); +U+93C3(0);U+955E(1,3);U+955E(1,3) +U+93C4(0);U+9548(4);U+9548(4),U+939B(0,4),U+946E(3,4) +U+93C5(0);U+93C5(0); +U+93C6(0);U+93C6(0); +U+93C7(0);U+65CB(1,3,4);U+65CB(1,3,4),U+955F(4) +U+93C8(0);U+94FE(1,3);U+94FE(1,3) +U+93C9(0);U+93C9(3); +U+93CA(0);U+93CA(5); +U+93CB(0);U+93CB(0); +U+93CC(0);U+9546(4);U+9546(4) +U+93CD(0);U+9559(4);U+9559(4) +U+93CE(0);U+6BD5(3);U+6BD5(3),U+7562(1,3),U+7F7C(3) +U+93CF(0);U+93CF(3); +U+93D0(0);U+9560(4);U+9560(4) +U+93D1(0);U+955D(1,3);U+955D(1,3) +U+93D2(0);U+93D2(0); +U+93D3(0);U+93D3(3); +U+93D4(0);U+93D4(0); +U+93D5(0);U+93D5(0); +U+93D6(0);U+93D6(5); +U+93D7(0);U+94FF(1,3);U+94FF(1,3),U+935E(0,1,3) +U+93D8(0);U+9535(1,3);U+9535(1,3) +U+93D9(0);U+93D9(0); +U+93DA(0);U+93DA(3); +U+93DB(0);U+93DB(0); +U+93DC(0);U+9557(1,3);U+9557(1,3) +U+93DD(0);U+9558(1,3);U+9558(1,3) +U+93DE(0);U+955B(1,3);U+955B(1,3) +U+93DF(0);U+94F2(1,3);U+5257(4),U+5277(2,3),U+94F2(1,3),U+522C(1,3,4) +U+93E1(0);U+955C(1,3);U+955C(1,3) +U+93E2(0);U+9556(1,3);U+9556(1,3) +U+93E3(0);U+93E3(0); +U+93E4(0);U+9542(1,3);U+9542(1,3) +U+93E6(0);U+93E6(0); +U+93E7(0);U+93E7(0); +U+93E8(0);U+933E(1,3);U+933E(1,3) +U+93E9(0);U+93E9(0); +U+93EA(0);U+93EA(0); +U+93EB(0);U+93EB(0); +U+93EC(0);U+7F45(4);U+7F45(4) +U+93ED(0);U+93ED(0); +U+93EE(0);U+93EE(0); +U+93EF(0);U+93EF(0); +U+93F0(0);U+955A(1,3);U+930B(4),U+955A(1,3) +U+93F1(0);U+93F1(0); +U+93F2(0);U+93F2(0); + +U+93F4(0);U+93F4(0); +U+93F5(0);U+94E7(1,3);U+94E7(1,3) +U+93F6(0);U+93F6(3); +U+93F7(0);U+9564(1,3);U+9564(1,3) +U+93F8(0);U+93F8(0); +U+93F9(0);U+956A(1,3);U+956A(1,3) +U+93FA(0);U+497D(1,3);U+497D(1,3) +U+93FB(0);U+93FB(0); +U+93FC(0);U+93FC(0); +U+93FD(0);U+9508(4);U+92B9(2,3),U+9508(4) +U+93FE(0);U+93FE(0); +U+93FF(0);U+93FF(0); +U+9400(0);U+532E(1,3);U+532E(1,3),U+5331(1,3) +U+9401(0);U+9401(3); +U+9403(0);U+94D9(1,3);U+94D9(1,3) +U+9404(0);U+9404(0); +U+9405(0);U+9405(0); +U+9406(0);U+9406(4); +U+9407(0);U+9407(0); +U+9408(0);U+9408(0); +U+9409(0);U+94BB(4);U+94BB(4),U+9246(0,4),U+947D(1,3,4) +U+940A(0);U+9496(3);U+9496(3),U+935A(0,1,3) +U+940B(0);U+94F4(4);U+94F4(4) +U+940C(0);U+940C(0); +U+940D(0);U+940D(0); +U+940E(0);U+940E(3); +U+940F(0);U+940F(0); +U+9410(0);U+9563(1,3);U+9563(1,3) +U+9411(0);U+9532(3);U+9532(3),U+9365(0,1,3) +U+9412(0);U+94F9(1,3);U+94F9(1,3) +U+9413(0);U+9566(1,3);U+9566(1,3) +U+9414(0);U+9561(4);U+9561(4) +U+9415(0);U+9415(3); +U+9416(0);U+9416(0); +U+9418(0);U+949F(1,3);U+9221(4),U+937E(3),U+949F(1,3),U+87A4(0,1,3),U+953A(1,3,4) +U+9419(0);U+956B(1,3);U+956B(1,3) +U+941B(0);U+941B(0); +U+941D(0);U+9562(1,3);U+9562(1,3) +U+9420(0);U+9568(1,3);U+9568(1,3) +U+9422(0);U+9422(0); +U+9423(0);U+9423(0); +U+9425(0);U+4985(1,3);U+4985(1,3) +U+9426(0);U+950E(1,3);U+950E(1,3) +U+9427(0);U+950F(1,3);U+950F(1,3) +U+9428(0);U+9544(1,3);U+9544(1,3) +U+9429(0);U+9429(0); +U+942A(0);U+942A(3);U+93C0(3) +U+942B(0);U+954C(4);U+954C(4),U+93B8(0,1,3,4) +U+942C(0);U+942C(0); +U+942D(0);U+942D(0); +U+942E(0);U+9570(1,3);U+5286(3),U+9570(1,3),U+938C(2,3) +U+942F(0);U+4983(1,3);U+4983(1,3) +U+9430(0);U+9430(0); +U+9431(0);U+5251(3);U+5251(3),U+5263(3),U+528D(1,3),U+5292(3,4),U+5294(3) +U+9432(0);U+956F(1,3);U+956F(1,3) +U+9433(0);U+956D(1,3);U+956D(1,3) +U+9434(0);U+9434(3); +U+9435(0);U+94C1(1,3);U+9295(3),U+94C1(1,3) +U+9436(0);U+956E(1,3);U+956E(1,3) +U+9437(0);U+9371(3);U+9371(3) +U+9438(0);U+94CE(1,3);U+94CE(1,3) +U+9439(0);U+9439(3); + +U+943A(0);U+94DB(1,3);U+94DB(1,3) +U+943B(0);U+943B(0); +U+943C(0);U+943C(0); +U+943D(0);U+943D(0); +U+943E(0);U+943E(5); +U+943F(0);U+9571(1,3);U+9571(1,3) +U+9440(0);U+9440(0); +U+9441(0);U+9441(0); +U+9442(0);U+9442(0); +U+9444(0);U+94F8(1,3);U+92F3(4),U+94F8(1,3) +U+9445(0);U+9445(0); +U+9446(0);U+9446(0); +U+9447(0);U+9447(0); +U+9448(0);U+9448(3); +U+9449(0);U+9449(0); +U+944A(0);U+956C(1,3);U+956C(1,3) +U+944B(0);U+944B(0); +U+944C(0);U+9554(1,3);U+9554(1,3) +U+944D(0);U+944D(0); +U+944F(0);U+944F(0); +U+9450(0);U+9450(0); +U+9451(0);U+9274(4);U+9274(4),U+9452(2,3) +U+9452(0);U+9274(1,3);U+9274(1,3),U+9451(2,3) +U+9453(0);U+9453(0); +U+9454(0);U+9572(1,3);U+9572(1,3) +U+9455(0);U+9527(1,3);U+9527(1,3) +U+9456(0);U+9456(0); +U+9457(0);U+9457(3); +U+9458(0);U+9458(0); +U+9459(0);U+9459(0); +U+945B(0);U+77FF(4);U+77FF(4),U+7926(3) +U+945C(0);U+945C(4); +U+945D(0);U+945D(0); +U+945E(0);U+9574(1,3);U+9574(1,3) +U+945F(0);U+945F(0); +U+9460(0);U+94C4(1,3);U+94C4(1,3) +U+9461(0);U+9461(0); +U+9462(0);U+9462(3); +U+9463(0);U+9573(1,3);U+9573(1,3) +U+9464(0);U+5228(2,3);U+5228(2,3) +U+9465(0);U+9565(1,3);U+9565(1,3) +U+9466(0);U+9466(0); +U+9467(0);U+9467(0); +U+9468(0);U+783B(3);U+783B(3),U+7931(1,3) +U+9469(0);U+9469(0); +U+946A(0);U+7089(4);U+7089(4),U+7210(1,3,4) +U+946B(0);U+946B(5); +U+946D(0);U+9567(1,3);U+9567(1,3) +U+946E(0);U+9548(3);U+9548(3),U+939B(0,3,4),U+93C4(3,4) +U+946F(0);U+5C16(4);U+5C16(4) +U+9470(0);U+94A5(1,3);U+94A5(1,3),U+9205(0,1,3,4) +U+9471(0);U+9575(4);U+9575(4) +U+9472(0);U+9576(1,3);U+9576(1,3) +U+9473(0);U+952E(3);U+952E(3),U+9375(0,1,3) +U+9474(0);U+9474(0); +U+9475(0);U+7F50(2,3);U+7F50(2,3) +U+9476(0);U+9476(0); +U+9477(0);U+954A(1,3);U+954A(1,3) +U+9478(0);U+9478(0); +U+9479(0);U+9569(1,3);U+9569(1,3) +U+947A(0);U+947A(0); +U+947C(0);U+9523(1,3);U+9523(1,3) +U+947D(0);U+94BB(1,3);U+94BB(1,3),U+9246(0,1,3,4),U+9409(1,3,4) + +U+947E(0);U+92AE(1,3);U+92AE(1,3) +U+947F(0);U+51FF(1,3);U+51FF(1,3) +U+9480(0);U+9480(0); +U+9481(0);U+4986(1,3);U+4986(1,3) +U+9482(0);U+954B(1,3);U+954B(1,3),U+93B2(0,1,3,4) +U+9483(0);U+9483(0); +U+9484(0);U+9484(0); +U+9485(0);U+9485(4);U+91D1(8,9),U+91D2(4) +U+9486(0);U+9486(1,3);U+91D3(1,3) +U+9487(0);U+9487(1,3);U+91D4(1,3) +U+9488(0);U+9488(1,3);U+91DD(1,3) +U+9489(0);U+9489(1,3);U+91D8(1,3) +U+948A(0);U+948A(1,3);U+91D7(1,3) +U+948B(0);U+948B(1,3);U+91D9(1,3) +U+948C(0);U+948C(1,3);U+91D5(1,3) +U+948D(0);U+948D(1,3);U+91F7(1,3) +U+948E(0);U+948E(1,3);U+91FA(1,3) +U+948F(0);U+948F(1,3);U+91E7(1,3) +U+9490(0);U+9490(1,3);U+91E4(1,3) +U+9491(0);U+9491(4);U+9212(4) +U+9492(0);U+9492(1,3);U+91E9(1,3) +U+9493(0);U+9493(1,3);U+91E3(1),U+9B61(4) +U+9494(0);U+9494(1,3);U+9346(1,3) +U+9495(0);U+9495(1,3);U+91F9(1,3) +U+9496(0);U+9496(1,3);U+935A(1,3),U+940A(3) +U+9497(0);U+9497(1,3);U+91F5(1,3) +U+9498(0);U+9498(1,3);U+9203(1,3) +U+9499(0);U+9499(1,3);U+9223(1,3) +U+949A(0);U+949A(1,3);U+9208(1,3) +U+949B(0);U+949B(1,3);U+9226(1,3) +U+949C(0);U+949C(4);U+9245(4),U+5DE8(2,3,4,5) +U+949D(0);U+949D(1,3);U+920D(1,3) +U+949E(0);U+949E(1,3);U+9214(1,3) +U+949F(0);U+949F(1,3);U+87A4(3),U+9221(4),U+937E(1,3),U+9418(1,3),U+953A(1,3,4) +U+94A0(0);U+94A0(1,3);U+9209(1,3) +U+94A1(0);U+94A1(1,3);U+92C7(1,3) +U+94A2(0);U+94A2(1,3);U+92FC(1,3) +U+94A3(0);U+94A3(4);U+9211(4) +U+94A4(0);U+94A4(1,3);U+9210(1,3) +U+94A5(0);U+94A5(1,3);U+9205(4),U+9470(1,3) +U+94A6(0);U+94A6(1,3);U+6B3D(1,3) +U+94A7(0);U+94A7(1,3);U+921E(1,3) +U+94A8(0);U+94A8(1,3);U+93A2(1,3) +U+94A9(0);U+94A9(1,3,4);U+920E(1,3),U+9264(4) +U+94AA(0);U+94AA(1,3);U+9227(1,3) +U+94AB(0);U+94AB(1,3);U+9201(1,3) +U+94AC(0);U+94AC(1,3);U+9225(1,3) +U+94AD(0);U+94AD(1,3);U+9204(1,3) +U+94AE(0);U+94AE(1,3);U+9215(1,3) +U+94AF(0);U+94AF(1,3);U+9200(1,3) +U+94B0(0);U+94B0(1,3);U+923A(1,3) +U+94B1(0);U+94B1(1,3);U+92AD(3),U+9322(1,3) +U+94B2(0);U+94B2(1,3);U+9266(1,3) +U+94B3(0);U+94B3(1,3);U+62D1(4),U+9257(1,3),U+7B9D(1,3,5) +U+94B4(0);U+94B4(1,3);U+9237(1,3) +U+94B5(0);U+94B5(1,3,4);U+7F3D(4),U+9262(1,3) +U+94B6(0);U+94B6(1,3);U+9233(1,3) +U+94B7(0);U+94B7(1,3);U+9255(1,3) +U+94B8(0);U+94B8(4);U+923D(4) +U+94B9(0);U+94B9(1);U+9238(1) +U+94BA(0);U+94BA(1,3);U+925E(1,3) +U+94BB(0);U+94BB(1,3,4);U+947D(1,3),U+9246(4),U+9409(4) + +U+94BC(0);U+94BC(1,3);U+926C(1,3) +U+94BD(0);U+94BD(1,3);U+926D(1,3) +U+94BE(0);U+94BE(1,3);U+9240(1,3) +U+94BF(0);U+94BF(1,3);U+923F(1,3) +U+94C0(0);U+94C0(1,3);U+923E(1,3) +U+94C1(0);U+94C1(1,3);U+9295(3),U+9435(1,3) +U+94C2(0);U+94C2(1,3);U+9251(1,3) +U+94C3(0);U+94C3(1,3);U+9234(1,3) +U+94C4(0);U+94C4(1,3);U+9460(1,3) +U+94C5(0);U+94C5(1,3);U+9206(2),U+925B(1,3) +U+94C6(0);U+94C6(1,3);U+925A(1,3) +U+94C7(0);U+94C7(4);U+924B(4) +U+94C8(0);U+94C8(1,3);U+9230(1,3) +U+94C9(0);U+94C9(1,3);U+9249(1,3) +U+94CA(0);U+94CA(1,3);U+9248(1,3) +U+94CB(0);U+94CB(1,3);U+924D(1,3) +U+94CC(0);U+94CC(1,3);U+922E(1,3) +U+94CD(0);U+94CD(1,3);U+9239(1,3) +U+94CE(0);U+94CE(1,3);U+9438(1,3) +U+94CF(0);U+94CF(1,3);U+9276(1,3) +U+94D0(0);U+94D0(1,3);U+92AC(1,3) +U+94D1(0);U+94D1(1,3);U+92A0(1,3) +U+94D2(0);U+94D2(1,3);U+927A(1,3) +U+94D3(0);U+94D3(1,3);U+92E9(1,3) +U+94D4(0);U+94D4(4);U+930F(4) +U+94D5(0);U+94D5(1,3);U+92AA(1,3) +U+94D6(0);U+94D6(4);U+92EE(4) +U+94D7(0);U+94D7(1,3);U+92CF(1,3) +U+94D8(0);U+94D8(4);U+92E3(4) +U+94D9(0);U+94D9(1,3);U+9403(1,3) +U+94DA(0);U+94DA(4);U+928D(4) +U+94DB(0);U+94DB(1,3);U+943A(1,3) +U+94DC(0);U+94DC(1,3);U+9285(1,3) +U+94DD(0);U+94DD(1,3);U+92C1(1,3) +U+94DE(0);U+94DE(1,3);U+92B1(1,3) +U+94DF(0);U+94DF(1,3);U+92A6(1,3) +U+94E0(0);U+94E0(1,3);U+93A7(1,3) +U+94E1(0);U+94E1(1,3);U+9358(1,3) +U+94E2(0);U+94E2(1,3);U+9296(1,3) +U+94E3(0);U+94E3(1,3);U+9291(1,3) +U+94E4(0);U+94E4(1,3);U+92CC(1,3) +U+94E5(0);U+94E5(1,3);U+92A9(1,3) +U+94E6(0);U+94E6(4);U+929B(4) +U+94E7(0);U+94E7(1,3);U+93F5(1,3) +U+94E8(0);U+94E8(1,3);U+9293(1,3) +U+94E9(0);U+94E9(1,3);U+93A9(1,3) +U+94EA(0);U+94EA(1,3);U+927F(1,3) +U+94EB(0);U+94EB(1,3);U+929A(1,3) +U+94EC(0);U+94EC(1,3);U+927B(1,3) +U+94ED(0);U+94ED(1,3);U+9298(1,3) +U+94EE(0);U+94EE(1,3);U+931A(1,3) +U+94EF(0);U+94EF(1,3);U+92AB(1,3) +U+94F0(0);U+94F0(1,3);U+9278(1,3) +U+94F1(0);U+94F1(1,3);U+92A5(1,3) +U+94F2(0);U+94F2(1,3);U+5257(4),U+5277(4),U+93DF(1,3),U+522C(1,3,4) +U+94F3(0);U+94F3(1,3);U+9283(1,3) +U+94F4(0);U+94F4(4);U+940B(4) +U+94F5(0);U+94F5(1,3);U+92A8(1,3) +U+94F6(0);U+94F6(1,3);U+9280(1,3) +U+94F7(0);U+94F7(1,3);U+92A3(1,3) +U+94F8(0);U+94F8(1,3);U+92F3(4),U+9444(1,3) +U+94F9(0);U+94F9(1,3);U+9412(1,3) +U+94FA(0);U+94FA(1,3);U+8216(4),U+92EA(1,3) + +U+94FB(0);U+94FB(4);U+92D9(4) +U+94FC(0);U+94FC(1,3);U+9338(1,3) +U+94FD(0);U+94FD(1,3);U+92F1(1,3) +U+94FE(0);U+94FE(1,3);U+93C8(1,3) +U+94FF(0);U+94FF(1,3);U+935E(3),U+93D7(1,3) +U+9500(0);U+9500(1,3);U+92B7(1,3) +U+9501(0);U+9501(1,3);U+9396(1,3),U+93C1(3) +U+9502(0);U+9502(1,3);U+92F0(1,3) +U+9503(0);U+9503(1,3);U+92E5(1,3) +U+9504(0);U+9504(1,3);U+8021(4),U+92E4(1,3) +U+9505(0);U+9505(1,3);U+934B(1,3) +U+9506(0);U+9506(1,3);U+92EF(1,3) +U+9507(0);U+9507(1,3);U+92E8(1,3) +U+9508(0);U+9508(1,3);U+92B9(1,3),U+93FD(4) +U+9509(0);U+9509(1,3);U+92BC(1,3) +U+950A(0);U+950A(4);U+92DD(4) +U+950B(0);U+950B(1,3);U+92D2(1,3) +U+950C(0);U+950C(1,3);U+92C5(1,3) +U+950D(0);U+950D(4);U+92F6(4) +U+950E(0);U+950E(1,3);U+9426(1,3) +U+950F(0);U+950F(1,3);U+9427(1,3) +U+9510(0);U+9510(1,3,4);U+92B3(4),U+92ED(1,3) +U+9511(0);U+9511(1,3);U+92BB(1,3) +U+9512(0);U+9512(1,3);U+92C3(1,3) +U+9513(0);U+9513(1,3);U+92DF(1,3) +U+9514(0);U+9514(1,3);U+92E6(1,3) +U+9515(0);U+9515(1,3);U+9312(1,3) +U+9516(0);U+9516(4);U+9306(4) +U+9517(0);U+9517(1,3);U+937A(1,3) +U+9518(0);U+9518(1,3);U+9369(1,3) +U+9519(0);U+9519(1,3);U+932F(1,3) +U+951A(0);U+951A(1,3);U+9328(1,3) +U+951B(0);U+951B(1,3);U+931B(1,3) +U+951C(0);U+951C(4);U+9321(4) +U+951D(0);U+951D(1,3);U+9340(1,3) +U+951E(0);U+951E(1,3);U+9301(1,3) +U+951F(0);U+951F(1,3);U+9315(1,3) +U+9520(0);U+9520(4);U+9329(4) +U+9521(0);U+9521(1,3);U+932B(1,3) +U+9522(0);U+9522(1,3);U+932E(1,3) +U+9523(0);U+9523(1,3);U+947C(1,3) +U+9524(0);U+9524(1,3);U+9318(1,3),U+939A(2) +U+9525(0);U+9525(1,3);U+9310(1,3) +U+9526(0);U+9526(1,3);U+9326(1,3) +U+9527(0);U+9527(1,3);U+9455(1,3) +U+9528(0);U+9528(1,3);U+9341(1,3) +U+9529(0);U+9529(4);U+9308(4) +U+952A(0);U+952A(4);U+9343(4) +U+952B(0);U+952B(1,3);U+9307(1,3) +U+952C(0);U+952C(4);U+931F(4) +U+952D(0);U+952D(1,3);U+9320(1,3) +U+952E(0);U+952E(1,3);U+9375(1,3),U+9473(3) +U+952F(0);U+952F(1,3);U+92F8(1,3) +U+9530(0);U+9530(1,3);U+9333(1,3) +U+9531(0);U+9531(1,3);U+9319(1,3) +U+9532(0);U+9532(1,3);U+9365(1,3),U+9411(3) +U+9533(0);U+9533(4);U+9348(4) +U+9534(0);U+9534(1,3);U+9347(1,3) +U+9535(0);U+9535(1,3);U+93D8(1,3) +U+9536(0);U+9536(1,3);U+9376(1,3) +U+9537(0);U+9537(1,3);U+9354(1,3) +U+9538(0);U+9538(1,3);U+81FF(4),U+9364(1,3) +U+9539(0);U+9539(1,3);U+936C(1,3) + +U+953A(0);U+953A(4);U+937E(4),U+9221(0,1,3,4),U+9418(1,3,4),U+949F(1,3,4),U+87A4(0,1,3,4) + +U+953B(0);U+953B(1,3);U+935B(1,3),U+7145(1,3,5) +U+953C(0);U+953C(1,3);U+93AA(1,3) +U+953D(0);U+953D(4);U+9360(4) +U+953E(0);U+953E(1,3);U+9370(1,3) +U+953F(0);U+953F(1,3);U+9384(1,3) +U+9540(0);U+9540(1,3);U+934D(1,3) +U+9541(0);U+9541(1,3);U+9382(1,3) +U+9542(0);U+9542(1,3);U+93E4(1,3) +U+9543(0);U+9543(1,3);U+93A1(1,3) +U+9544(0);U+9544(1,3);U+9428(1,3) +U+9545(0);U+9545(1,3);U+9387(1,3) +U+9546(0);U+9546(4);U+93CC(4) +U+9547(0);U+9547(1,3);U+93AD(3),U+93AE(1,3) +U+9548(0);U+9548(4);U+939B(4),U+93C4(4),U+946E(3) +U+9549(0);U+9549(1,3);U+9398(1,3) +U+954A(0);U+954A(1,3);U+9477(1,3) +U+954B(0);U+954B(1,3,4);U+93B2(4),U+9482(1,3) +U+954C(0);U+954C(1,3,4);U+93B8(1,3),U+942B(4) +U+954D(0);U+954D(1,3);U+93B3(1,3) +U+954E(0);U+954E(1,3);U+93BF(1,3) +U+954F(0);U+954F(1,3);U+93A6(1,3) +U+9550(0);U+9550(1,3);U+93AC(1,3) +U+9551(0);U+9551(1,3);U+938A(1,3) +U+9552(0);U+9552(1,3);U+8CF9(3),U+93B0(1,3) +U+9553(0);U+9553(1,3);U+93B5(1,3) +U+9554(0);U+9554(1,3);U+944C(1,3) +U+9555(0);U+9555(4);U+9394(4),U+7194(2,4,5) +U+9556(0);U+9556(1,3);U+93E2(1,3) +U+9557(0);U+9557(1,3);U+93DC(1,3) +U+9558(0);U+9558(1,3);U+93DD(1,3) +U+9559(0);U+9559(4);U+93CD(4) +U+955A(0);U+955A(1,3,4);U+930B(4),U+93F0(1,3) +U+955B(0);U+955B(1,3);U+93DE(1,3) +U+955C(0);U+955C(1,3);U+93E1(1,3) +U+955D(0);U+955D(1,3);U+93D1(1,3) +U+955E(0);U+955E(1,3);U+93C3(1,3) +U+955F(0);U+955F(4);U+93C7(4),U+65CB(1,3,4) +U+9560(0);U+9560(4);U+93D0(4) +U+9561(0);U+9561(4);U+9414(4) +U+9562(0);U+9562(1,3,4);U+941D(1,3) +U+9563(0);U+9563(1,3);U+9410(1,3) +U+9564(0);U+9564(1,3);U+93F7(1,3) +U+9565(0);U+9565(1,3);U+9465(1,3) +U+9566(0);U+9566(1,3);U+9413(1,3) +U+9567(0);U+9567(1,3);U+946D(1,3) +U+9568(0);U+9568(1,3);U+9420(1,3) +U+9569(0);U+9569(1,3);U+9479(1,3) +U+956A(0);U+956A(1,3);U+93F9(1,3) +U+956B(0);U+956B(1,3);U+9419(1,3) +U+956C(0);U+956C(1,3);U+944A(1,3) +U+956D(0);U+956D(1,3);U+9433(1,3) +U+956E(0);U+956E(1,3);U+9436(1,3) +U+956F(0);U+956F(1,3);U+9432(1,3) +U+9570(0);U+9570(1,3);U+5286(3),U+938C(2,3),U+942E(1,3) +U+9571(0);U+9571(1,3);U+943F(1,3) +U+9572(0);U+9572(1,3);U+9454(1,3) +U+9573(0);U+9573(1,3);U+9463(1,3) +U+9574(0);U+9574(1,3);U+945E(1,3) +U+9575(0);U+9575(4);U+9471(4) +U+9576(0);U+9576(1,3);U+9472(1,3) +U+9577(0);U+957F(1,3);U+957F(1,3) + +U+957A(0);U+957A(0); +U+957B(0);U+957B(0); +U+957C(0);U+957C(0); +U+957D(0);U+957D(0); +U+957F(0);U+957F(1,3);U+9577(1,3) +U+9580(0);U+95E8(1,3);U+95E8(1,3) +U+9581(0);U+9581(0); +U+9582(0);U+95E9(1,3);U+95E9(1,3) +U+9583(0);U+95EA(1,3);U+95EA(1,3) +U+9584(0);U+9584(0); +U+9586(0);U+95EB(4);U+95EB(4),U+95BB(4),U+960E(1,3,4) +U+9587(0);U+95ED(3);U+9589(3),U+95ED(3) +U+9588(0);U+95EC(4);U+95EC(4) +U+9589(0);U+95ED(1,3);U+9587(3),U+95ED(1,3) +U+958A(0);U+958A(0); +U+958B(0);U+5F00(1,3);U+5F00(1,3) +U+958C(0);U+95F6(4);U+95F6(4) +U+958D(0);U+958D(0); +U+958E(0);U+95F3(4);U+95F3(4) +U+958F(0);U+95F0(1,3);U+95F0(1,3) +U+9590(0);U+9590(0); +U+9591(0);U+95F2(1,3);U+95F2(1,3) +U+9592(0);U+9592(0); +U+9593(0);U+95F4(1,3);U+95F4(1,3) +U+9594(0);U+95F5(1,3);U+95F5(1,3) +U+9595(0);U+9595(0); +U+9596(0);U+9596(0); +U+9598(0);U+95F8(1,3);U+95F8(1,3) +U+9599(0);U+95F9(4);U+95F9(4),U+9B27(2,3) +U+959A(0);U+959A(0); +U+959B(0);U+959B(0); +U+959C(0);U+959C(3); +U+959D(0);U+959D(0); +U+959E(0);U+5173(3);U+5173(3),U+95A2(3),U+95D7(3),U+95DC(1,3) +U+959F(0);U+959F(0); +U+95A1(0);U+9602(1,3);U+9602(1,3) +U+95A2(0);U+5173(3);U+5173(3),U+95DC(3),U+959E(3),U+95D7(3) +U+95A3(0);U+9601(1,3);U+9601(1,3) +U+95A4(0);U+5408(1,3);U+5408(1,3),U+6546(1,3) +U+95A5(0);U+9600(1,3);U+9600(1,3) +U+95A6(0);U+95A6(0); +U+95A7(0);U+54C4(2);U+54C4(2),U+9B28(3) +U+95A8(0);U+95FA(1,3);U+95FA(1,3) +U+95A9(0);U+95FD(1,3);U+95FD(1,3) +U+95AA(0);U+95AA(0); +U+95AB(0);U+9603(1,3);U+9603(1,3) +U+95AC(0);U+9606(1,3);U+9606(1,3) +U+95AD(0);U+95FE(1,3);U+95FE(1,3) +U+95AE(0);U+95AE(0); +U+95AF(0);U+95AF(0); +U+95B0(0);U+95B0(0); +U+95B1(0);U+9605(4);U+95B2(8,9),U+9605(4) +U+95B2(0);U+9605(1,3);U+95B1(8,9),U+9605(1,3) +U+95B5(0);U+95B5(0); +U+95B6(0);U+960A(1,3);U+960A(1,3) +U+95B7(0);U+6740(3);U+6740(3),U+6BBA(1,3) +U+95B9(0);U+9609(1,3);U+9609(1,3) +U+95BA(0);U+95BA(0); +U+95BB(0);U+960E(1,3);U+95EB(3),U+9586(4),U+960E(1,3) +U+95BC(0);U+960F(1,3);U+960F(1,3) +U+95BD(0);U+960D(1,3);U+960D(1,3) +U+95BE(0);U+9608(1,3);U+9608(1,3) +U+95BF(0);U+960C(1,3);U+960C(1,3) + +U+95C0(0);U+95C0(0); +U+95C2(0);U+95C2(0); +U+95C3(0);U+9612(1,3);U+9612(1,3) +U+95C4(0);U+95C4(0); +U+95C5(0);U+95C5(3); +U+95C6(0);U+677F(1,3);U+677F(1,3) +U+95C7(0);U+6697(2);U+6697(2),U+667B(0,2,3) +U+95C8(0);U+95F1(1,3);U+95F1(1,3) +U+95C9(0);U+95C9(0); +U+95CA(0);U+9614(1,3);U+6FF6(2,3),U+9614(1,3) +U+95CB(0);U+9615(1,3);U+9615(1,3) +U+95CC(0);U+9611(1,3);U+9611(1,3) +U+95CD(0);U+9607(4);U+9607(4) +U+95CE(0);U+95CE(0); +U+95CF(0);U+95CF(0); +U+95D0(0);U+9617(1,3);U+9617(1,3) +U+95D1(0);U+95D1(3); +U+95D2(0);U+9618(4);U+9618(4) +U+95D3(0);U+95FF(1,3);U+95FF(1,3) +U+95D4(0);U+9616(1,3);U+9616(1,3) +U+95D5(0);U+9619(1,3);U+9619(1,3) +U+95D6(0);U+95EF(1,3);U+95EF(1,3) +U+95D7(0);U+5173(3);U+5173(3),U+95DC(3),U+959E(3),U+95A2(3) +U+95D8(0);U+6597(4);U+6597(4),U+9B25(4),U+9B2D(3),U+9B26(4),U+9B2A(4),U+9B2C(3,4) +U+95DA(0);U+7AA5(2,3);U+7AA5(2,3),U+7ABA(1,2,3) +U+95DB(0);U+95DB(0); +U+95DC(0);U+5173(1,3);U+5173(1,3),U+95A2(3),U+95D7(3),U+959E(1,3) +U+95DE(0);U+961A(1,3);U+961A(1,3),U+9B2B(1,3) +U+95DF(0);U+95DF(0); +U+95E0(0);U+9613(4);U+9613(4) +U+95E1(0);U+9610(1,3);U+9610(1,3),U+705B(0,1,3) +U+95E2(0);U+8F9F(1,3);U+8F9F(1,3),U+907F(1,3,4) +U+95E3(0);U+95E3(0); +U+95E4(0);U+961B(4);U+961B(4) +U+95E5(0);U+95FC(1,3);U+95FC(1,3) +U+95E6(0);U+95E6(0); +U+95E7(0);U+95E7(0); +U+95E8(0);U+95E8(1,3);U+9580(1,3) +U+95E9(0);U+95E9(1,3);U+9582(1,3) +U+95EA(0);U+95EA(1,3);U+9583(1,3) +U+95EB(0);U+95EB(4);U+9586(4),U+95BB(3),U+960E(1,3,4) +U+95EC(0);U+95EC(4);U+9588(4) +U+95ED(0);U+95ED(1,3);U+9587(3),U+9589(1,3) +U+95EE(0);U+95EE(1,3);U+554F(1,3) +U+95EF(0);U+95EF(1,3);U+95D6(1,3) +U+95F0(0);U+95F0(1,3);U+958F(1,3) +U+95F1(0);U+95F1(1,3);U+95C8(1,3) +U+95F2(0);U+95F2(1,3);U+9591(1,3) +U+95F3(0);U+95F3(4);U+958E(4) +U+95F4(0);U+95F4(1,3);U+9593(1,3) +U+95F5(0);U+95F5(1,3);U+9594(1,3) +U+95F6(0);U+95F6(4);U+958C(4) +U+95F7(0);U+95F7(1,3);U+60B6(1,3) +U+95F8(0);U+95F8(1,3);U+9598(1,3) +U+95F9(0);U+95F9(1,3,4);U+9599(4),U+9B27(1,3) +U+95FA(0);U+95FA(1,3);U+95A8(1,3) +U+95FB(0);U+95FB(1,3);U+805E(1,3) +U+95FC(0);U+95FC(1,3);U+95E5(1,3) +U+95FD(0);U+95FD(1,3);U+95A9(1,3) +U+95FE(0);U+95FE(1,3);U+95AD(1,3) +U+95FF(0);U+95FF(1,3);U+95D3(1,3) +U+9600(0);U+9600(1,3);U+95A5(1,3) +U+9601(0);U+9601(1,3);U+95A3(1,3) + +U+9602(0);U+9602(1,3);U+95A1(1,3) +U+9603(0);U+9603(1,3);U+95AB(1,3) +U+9604(0);U+9604(1,3);U+9B2E(1,3) +U+9605(0);U+9605(1,3,4);U+95B1(4),U+95B2(1,3) +U+9606(0);U+9606(1,3);U+95AC(1,3) +U+9607(0);U+9607(4);U+95CD(4) +U+9608(0);U+9608(1,3);U+95BE(1,3) +U+9609(0);U+9609(1,3);U+95B9(1,3) +U+960A(0);U+960A(1,3);U+95B6(1,3) +U+960B(0);U+960B(1,3);U+9B29(1,3) +U+960C(0);U+960C(1,3);U+95BF(1,3) +U+960D(0);U+960D(1,3);U+95BD(1,3) +U+960E(0);U+960E(1,3);U+95BB(1,3),U+95EB(1,3,4),U+9586(0,1,3,4) +U+960F(0);U+960F(1,3);U+95BC(1,3) +U+9610(0);U+9610(1,3);U+705B(3),U+95E1(1,3) +U+9611(0);U+9611(1,3);U+95CC(1,3) +U+9612(0);U+9612(1,3);U+95C3(1,3) +U+9613(0);U+9613(4);U+95E0(4) +U+9614(0);U+9614(1,3);U+6FF6(4),U+95CA(1,3) +U+9615(0);U+9615(1,3);U+95CB(1,3) +U+9616(0);U+9616(1,3);U+95D4(1,3) +U+9617(0);U+9617(1,3);U+95D0(1,3) +U+9618(0);U+9618(4);U+95D2(4) +U+9619(0);U+9619(1,3);U+95D5(1,3) +U+961A(0);U+961A(1,3);U+95DE(1,3),U+9B2B(3) +U+961B(0);U+961B(4);U+95E4(4) +U+961C(0);U+961C(5);U+5CCA(3),U+961D(3) +U+961D(0);U+961D(5);U+961C(3),U+5CCA(0,3) +U+961E(0);U+961E(0); +U+961F(0);U+961F(1,3);U+968A(1,3) +U+9620(0);U+9620(0); +U+9621(0);U+9621(5); +U+9622(0);U+9622(5); +U+9623(0);U+5C79(3);U+5C79(3) +U+9624(0);U+9624(3); +U+9627(0);U+9627(0); +U+9628(0);U+5384(2);U+5384(2) +U+962A(0);U+962A(5);U+5742(3) +U+962B(0);U+962B(3); +U+962C(0);U+5751(2,3);U+5751(2,3) +U+962D(0);U+962D(0); +U+962E(0);U+962E(5); +U+962F(0);U+5740(2,3);U+5740(2,3) +U+9630(0);U+9630(0); +U+9631(0);U+9631(5);U+7A7D(2,3) +U+9632(0);U+9632(5); +U+9633(0);U+9633(1,3);U+967D(1,3),U+661C(3) +U+9634(0);U+9634(1,3);U+9670(1,3),U+9712(4),U+9720(4) +U+9635(0);U+9635(1,3);U+9663(1,3) +U+9636(0);U+9636(1,3);U+968E(1,3),U+5826(4) +U+9637(0);U+9637(0); +U+9638(0);U+9638(3); +U+9639(0);U+9639(0); +U+963A(0);U+963A(0); +U+963B(0);U+963B(5); +U+963C(0);U+963C(5); +U+963D(0);U+963D(5); +U+963F(0);U+963F(5); +U+9640(0);U+9640(5); +U+9641(0);U+9641(0); +U+9642(0);U+9642(5); +U+9643(0);U+9643(0); +U+9644(0);U+9644(5);U+577F(2,3) + +U+9645(0);U+9645(1,3);U+969B(1,3) +U+9646(0);U+9646(1,3);U+5774(3),U+9678(1,3) +U+9647(0);U+9647(1,3);U+96B4(1,3) +U+9648(0);U+9648(1,3);U+9673(1,3),U+6576(3) +U+9649(0);U+9649(1,3);U+9658(1,3) +U+964A(0);U+964A(3); +U+964B(0);U+964B(5); +U+964C(0);U+964C(5); +U+964D(0);U+964D(5); +U+964E(0);U+964E(0); +U+964F(0);U+964F(0); +U+9650(0);U+9650(5); +U+9651(0);U+9651(3); +U+9652(0);U+9652(0); +U+9653(0);U+9653(0); +U+9654(0);U+9654(5);U+5793(3) +U+9655(0);U+9655(1,4);U+965D(1),U+965C(4) +U+9658(0);U+9649(1,3);U+9649(1,3) +U+9659(0);U+9659(0); +U+965A(0);U+965A(0); +U+965B(0);U+965B(5); +U+965C(0);U+9655(4);U+9655(4),U+965D(1,4) +U+965D(0);U+9655(1);U+9655(1),U+965C(1,4) +U+965E(0);U+5347(2,3);U+5347(2,3),U+6607(2,3) +U+965F(0);U+965F(5); +U+9660(0);U+9660(0); +U+9661(0);U+9661(5); +U+9662(0);U+9662(5); +U+9663(0);U+9635(1,3);U+9635(1,3) +U+9664(0);U+9664(5); +U+9666(0);U+9666(0); +U+9667(0);U+9667(5);U+9689(3,4) +U+9668(0);U+9668(1,3);U+9695(1,3) +U+9669(0);U+9669(1,3);U+7906(3),U+96AA(1,3),U+7877(1,3,4),U+9E7C(1,3,4),U+78B1(1,3,4) + +U+966A(0);U+966A(5); +U+966B(0);U+966B(0); +U+966C(0);U+966C(5); +U+966D(0);U+966D(3); +U+966E(0);U+966E(0); +U+966F(0);U+966F(3); +U+9670(0);U+9634(1,3);U+9634(1,3),U+9712(1,3,4),U+9720(1,3,4) +U+9671(0);U+97A0(3);U+97A0(3) +U+9672(0);U+9672(5); +U+9673(0);U+9648(1,3);U+9648(1,3),U+6576(0,1,3) +U+9674(0);U+9674(5); +U+9675(0);U+9675(5);U+740C(4) +U+9676(0);U+9676(5);U+530B(4) +U+9677(0);U+9677(5); +U+9678(0);U+9646(1,3);U+9646(1,3),U+5774(0,1,3) +U+967C(0);U+967C(0); +U+967D(0);U+9633(1,3);U+661C(3),U+9633(1,3) +U+967E(0);U+967E(4); +U+9680(0);U+9680(0); +U+9683(0);U+9683(0); +U+9684(0);U+5824(2,3);U+5824(2,3) +U+9685(0);U+9685(5); +U+9686(0);U+9686(5); +U+9687(0);U+9687(0); +U+9688(0);U+9688(5); +U+9689(0);U+9667(3,4);U+9667(3,4) +U+968A(0);U+961F(1,3);U+961F(1,3) +U+968B(0);U+968B(5); + +U+968D(0);U+968D(5); +U+968E(0);U+9636(1,3);U+5826(2,3),U+9636(1,3) +U+968F(0);U+968F(1,3);U+96A8(1,3) +U+9690(0);U+9690(1,3);U+96A0(3),U+96B1(1,3) +U+9691(0);U+9691(0); +U+9692(0);U+9692(0); +U+9693(0);U+96B3(3);U+96B3(3) +U+9694(0);U+9694(5); +U+9695(0);U+9668(1,3);U+9668(1,3) +U+9697(0);U+9697(5); +U+9698(0);U+9698(5); +U+9699(0);U+9699(5);U+90C4(3) +U+969B(0);U+9645(1,3);U+9645(1,3) +U+969C(0);U+969C(5);U+5887(3) +U+969E(0);U+6556(3);U+6556(3) +U+96A0(0);U+9690(3);U+9690(3),U+96B1(3) +U+96A1(0);U+96A1(0); +U+96A2(0);U+96A2(0); +U+96A3(0);U+90BB(4);U+90BB(4),U+9130(2,3) +U+96A4(0);U+96A4(3); +U+96A5(0);U+96A5(3); +U+96A6(0);U+96A6(0); +U+96A7(0);U+96A7(5); +U+96A8(0);U+968F(1,3);U+968F(1,3) +U+96A9(0);U+96A9(0); +U+96AA(0);U+9669(1,3);U+9669(1,3),U+7877(3,4),U+7906(3),U+9E7C(1,3,4),U+78B1(1,3,4) +U+96AC(0);U+96AC(0); +U+96AD(0);U+96AD(0); +U+96AE(0);U+96AE(0); +U+96B0(0);U+96B0(5); +U+96B1(0);U+9690(1,3);U+9690(1,3),U+96A0(3) +U+96B3(0);U+96B3(5);U+9693(3) +U+96B4(0);U+9647(1,3);U+9647(1,3) +U+96B6(0);U+96B6(1,3);U+96B7(4),U+96B8(1,3) +U+96B7(0);U+96B6(4);U+96B6(4),U+96B8(2,3) +U+96B8(0);U+96B6(1,3);U+96B6(1,3),U+96B7(2,3) +U+96B9(0);U+96B9(5); +U+96BA(0);U+96BA(0); +U+96BB(0);U+53EA(1,3);U+53EA(1,3),U+8879(1,3,4) +U+96BC(0);U+96BC(5); +U+96BD(0);U+96BD(5);U+96CB(2,3) +U+96BE(0);U+96BE(1,3);U+96E3(1,3) +U+96BF(0);U+5F0B(3);U+5F0B(3) +U+96C0(0);U+96C0(5); +U+96C1(0);U+96C1(5);U+9CEB(3),U+9D08(2,3) +U+96C2(0);U+96C2(3); +U+96C3(0);U+96C3(0); +U+96C4(0);U+96C4(5); +U+96C5(0);U+96C5(5); +U+96C6(0);U+96C6(5); +U+96C7(0);U+96C7(5);U+50F1(2,3) +U+96C8(0);U+96C8(0); +U+96C9(0);U+96C9(5);U+9D19(3) +U+96CA(0);U+96CA(3); +U+96CB(0);U+96BD(2,3);U+96BD(2,3) +U+96CC(0);U+96CC(5); +U+96CD(0);U+96CD(5);U+96DD(2,3) +U+96CE(0);U+96CE(5); +U+96CF(0);U+96CF(1,3);U+96DB(1,3),U+9DB5(3) +U+96D0(0);U+96D0(0); +U+96D1(0);U+6742(3);U+6742(3),U+96DC(3),U+96E5(3) +U+96D2(0);U+96D2(5); +U+96D3(0);U+96D3(0); + +U+96D4(0);U+96D4(0); +U+96D5(0);U+96D5(5);U+5F6B(2),U+7431(2,3),U+9D70(2,3) +U+96D6(0);U+867D(1,3);U+867D(1,3) +U+96D7(0);U+96D7(0); +U+96D8(0);U+96D8(3); +U+96D9(0);U+53CC(1,3);U+53CC(1,3) +U+96DA(0);U+96DA(0); +U+96DB(0);U+96CF(1,3);U+96CF(1,3),U+9DB5(1,3) +U+96DC(0);U+6742(1,3);U+6742(1,3),U+96D1(3),U+96E5(1,3) +U+96DD(0);U+96CD(2,3);U+96CD(2,3) +U+96DE(0);U+9E21(4);U+9CEE(8,9),U+9DC4(2,3,4),U+9E21(4) +U+96DF(0);U+96DF(4); +U+96E0(0);U+96E0(1,3);U+8B8E(1,3),U+8B90(1,3),U+4EC7(1,3,5) +U+96E1(0);U+96E1(0); +U+96E2(0);U+79BB(1,3);U+79BB(1,3) +U+96E3(0);U+96BE(1,3);U+96BE(1,3) +U+96E5(0);U+6742(3);U+6742(3),U+96D1(3),U+96DC(1,3) +U+96E8(0);U+96E8(5); +U+96E9(0);U+96E9(5); +U+96EA(0);U+96EA(5); +U+96EB(0);U+96EB(0); +U+96EC(0);U+96EC(0); +U+96ED(0);U+96ED(0); +U+96EE(0);U+96EE(0); +U+96EF(0);U+96EF(5); +U+96F0(0);U+6C1B(2,3);U+6C1B(2,3) +U+96F1(0);U+96F1(3); +U+96F2(0);U+4E91(1,3);U+4E91(1,3) +U+96F3(0);U+96F3(1,3);U+9742(1,3) +U+96F4(0);U+96F4(0); +U+96F5(0);U+96F5(0); +U+96F6(0);U+96F6(5); +U+96F7(0);U+96F7(5); +U+96F8(0);U+96F8(0); +U+96F9(0);U+96F9(5); +U+96FA(0);U+96FA(0); +U+96FB(0);U+7535(1,3);U+7535(1,3) +U+96FD(0);U+96FD(0); +U+96FE(0);U+96FE(1,3);U+9727(1,3) +U+96FF(0);U+96FF(0); +U+9700(0);U+9700(5); +U+9701(0);U+9701(1,3);U+973D(1,3) +U+9702(0);U+9702(0); +U+9703(0);U+9703(0); +U+9704(0);U+9704(5); +U+9705(0);U+9705(0); +U+9706(0);U+9706(5); +U+9707(0);U+9707(5);U+8AAB(3) +U+9708(0);U+9708(5); +U+9709(0);U+9709(1,3);U+9EF4(1,3,4) +U+970A(0);U+7075(3);U+7075(3),U+9748(3) +U+970B(0);U+970B(0); +U+970C(0);U+970C(0); +U+970D(0);U+970D(5);U+7668(7) +U+970E(0);U+970E(5); +U+970F(0);U+970F(5); +U+9710(0);U+9710(0); +U+9711(0);U+6CBE(2,3);U+6CBE(2,3) +U+9712(0);U+9634(4);U+9634(4),U+9670(1,3,4),U+9720(4) +U+9713(0);U+9713(5);U+86EA(3),U+873A(2,3) +U+9715(0);U+9715(0); +U+9716(0);U+9716(5); +U+9718(0);U+9718(0); + +U+9719(0);U+9719(0); +U+971C(0);U+971C(5); +U+971D(0);U+971D(0); +U+971E(0);U+971E(5);U+8D6E(3) +U+971F(0);U+971F(0); +U+9720(0);U+9634(4);U+9634(4),U+9670(1,3,4),U+9712(4) +U+9721(0);U+9721(0); +U+9722(0);U+9722(3); +U+9723(0);U+9723(0); +U+9724(0);U+9724(3); +U+9725(0);U+9725(0); +U+9726(0);U+9726(0); +U+9727(0);U+96FE(1,3);U+96FE(1,3) +U+9728(0);U+9728(0); +U+9729(0);U+5ED3(3);U+5ED3(3) +U+972A(0);U+972A(5); +U+972B(0);U+972B(3); +U+972C(0);U+972C(0); +U+972D(0);U+972D(1,3);U+9744(1,3) +U+972E(0);U+972E(0); +U+972F(0);U+972F(0); +U+9730(0);U+9730(5); +U+9731(0);U+9731(0); +U+9732(0);U+9732(5); +U+9735(0);U+9735(0); +U+9736(0);U+9736(0); +U+9738(0);U+9738(5);U+8987(2,3) +U+9739(0);U+9739(5); +U+973A(0);U+6EA6(3);U+6EA6(3) +U+973B(0);U+973B(0); +U+973C(0);U+973C(0); +U+973D(0);U+9701(1,3);U+9701(1,3) +U+973E(0);U+973E(5); +U+973F(0);U+973F(3); +U+9742(0);U+96F3(1,3);U+96F3(1,3) +U+9743(0);U+9743(0); +U+9744(0);U+972D(1,3);U+972D(1,3) +U+9745(0);U+9745(0); +U+9746(0);U+53C7(1,3);U+53C7(1,3) +U+9747(0);U+9747(0); +U+9748(0);U+7075(1,3);U+970A(3),U+7075(1,3) +U+9749(0);U+53C6(1,3);U+53C6(1,3) +U+974A(0);U+974A(0); +U+974B(0);U+974B(0); +U+974C(0);U+974C(0); +U+974E(0);U+974E(0); +U+974F(0);U+974F(0); +U+9750(0);U+9750(0); +U+9751(0);U+9752(4);U+9752(4) +U+9752(0);U+9752(5);U+9751(4) +U+9753(0);U+9753(1,3);U+975A(1,3) +U+9754(0);U+9754(4);U+975D(4) +U+9755(0);U+9755(0); +U+9756(0);U+9756(5); +U+9758(0);U+9758(0); +U+9759(0);U+9759(4);U+975C(4) +U+975A(0);U+9753(1,3);U+9753(1,3) +U+975B(0);U+975B(5); +U+975C(0);U+9759(4);U+9759(4) +U+975D(0);U+9754(4);U+9754(4) +U+975E(0);U+975E(5); +U+975F(0);U+975F(0); +U+9760(0);U+9760(5); + +U+9761(0);U+9761(5); +U+9762(0);U+9762(1,3);U+9EAA(4),U+9EB5(1,3) +U+9765(0);U+9765(1,3);U+9768(1,3) +U+9766(0);U+9766(0); +U+9767(0);U+9767(0); +U+9768(0);U+9765(1,3);U+9765(1,3) +U+9769(0);U+9769(5); +U+976A(0);U+976A(0); +U+976B(0);U+976B(0); +U+976C(0);U+976C(0); +U+976D(0);U+97E7(4);U+97CC(2,3),U+97E7(4),U+8095(0,3,4) +U+976E(0);U+976E(0); +U+976F(0);U+976F(0); +U+9770(0);U+9770(0); +U+9772(0);U+9772(0); +U+9773(0);U+9773(5); +U+9774(0);U+9774(5); +U+9776(0);U+9776(5); +U+9777(0);U+9777(3); +U+9778(0);U+9778(4); +U+9779(0);U+9779(0); +U+977A(0);U+977A(0); +U+977B(0);U+977C(4);U+977C(4) +U+977C(0);U+977C(5);U+977B(4) +U+977D(0);U+977D(0); +U+977E(0);U+977E(0); +U+977F(0);U+977F(0); +U+9780(0);U+9F17(3);U+9F17(3) +U+9781(0);U+9781(0); +U+9782(0);U+79F8(4);U+79F8(4),U+7A2D(2,4) +U+9783(0);U+9783(0); +U+9784(0);U+9784(0); +U+9785(0);U+9785(5); +U+9786(0);U+9786(0); +U+9788(0);U+9788(0); +U+978A(0);U+978A(0); +U+978B(0);U+978B(5); +U+978C(0);U+978D(2,3);U+978D(2,3) +U+978D(0);U+978D(5);U+978C(2,3) +U+978E(0);U+978E(0); +U+978F(0);U+5DE9(1,3);U+5DE9(1,3) +U+9790(0);U+9790(0); +U+9791(0);U+9791(1,3);U+97C3(1,3) +U+9792(0);U+9792(1,3);U+97BD(1,3),U+6A47(1,3,5),U+6A4B(1,3),U+6865(1,3) +U+9793(0);U+9793(0); +U+9794(0);U+9794(5); +U+9795(0);U+9795(0); +U+9796(0);U+9796(0); +U+9797(0);U+9797(0); +U+9798(0);U+9798(5); +U+9799(0);U+9799(0); +U+979A(0);U+979A(0); +U+979C(0);U+979C(0); +U+979D(0);U+979D(0); +U+979E(0);U+979E(3); +U+979F(0);U+979F(3); +U+97A0(0);U+97A0(5);U+9671(3) +U+97A1(0);U+97A1(0); +U+97A2(0);U+97A2(0); +U+97A3(0);U+97A3(5); +U+97A4(0);U+5E2E(4);U+5E2E(4),U+5E47(4),U+5E5A(3,4),U+5E6B(1,3,4),U+7E0D(3,4) +U+97A5(0);U+97A5(0); +U+97A6(0);U+79CB(1,3);U+79CB(1,3),U+7A50(1,3,4,7),U+9F9D(1,3,4,7) + +U+97A7(0);U+97A7(3); +U+97A8(0);U+97A8(3); +U+97AA(0);U+97AA(0); +U+97AB(0);U+97AB(5); +U+97AC(0);U+97AC(0); +U+97AD(0);U+97AD(5); +U+97AE(0);U+97AE(0); +U+97AF(0);U+97AF(1,3);U+97C9(1,3) +U+97B2(0);U+97B2(5); +U+97B3(0);U+97B3(0); +U+97B4(0);U+97B4(5); +U+97B6(0);U+97B6(0); +U+97B7(0);U+97B7(0); +U+97B8(0);U+97B8(0); +U+97B9(0);U+97B9(4); +U+97BA(0);U+97BA(0); +U+97BB(0);U+97BB(0); +U+97BC(0);U+97BC(0); +U+97BD(0);U+9792(1,3);U+6A4B(3),U+9792(1,3),U+6865(1,3),U+6A47(1,3) +U+97BF(0);U+97BF(0); +U+97C1(0);U+7F30(4);U+7F30(4),U+7E6E(0,1,3,4) +U+97C2(0);U+97C2(0); +U+97C3(0);U+9791(1,3);U+9791(1,3) +U+97C4(0);U+97C4(0); +U+97C5(0);U+97C5(0); +U+97C6(0);U+5343(1,3);U+5343(1,3),U+4EDF(1,3,4,5) +U+97C7(0);U+97C7(3); +U+97C8(0);U+889C(4);U+889C(4),U+896A(2),U+97E4(3) +U+97C9(0);U+97AF(1,3);U+97AF(1,3) +U+97CA(0);U+97CA(0); +U+97CB(0);U+97E6(1,3);U+97E6(1,3) +U+97CC(0);U+97E7(1,3);U+976D(2,3),U+97E7(1,3),U+8095(0,1,3,4) +U+97CD(0);U+97E8(1,3);U+97E8(1,3) +U+97CE(0);U+97CE(4); +U+97CF(0);U+97CF(0); +U+97D0(0);U+97D0(0); +U+97D1(0);U+97D1(0); +U+97D3(0);U+97E9(1,3);U+97E9(1,3) +U+97D4(0);U+97D4(0); +U+97D5(0);U+97D5(0); +U+97D6(0);U+97D6(0); +U+97D7(0);U+97D7(3); +U+97D8(0);U+97D8(3); +U+97D9(0);U+97EA(1,3);U+97EA(1,3) +U+97DA(0);U+97DA(0); +U+97DB(0);U+97DB(3); +U+97DC(0);U+97EC(1,3);U+97EC(1,3) +U+97DD(0);U+97DD(3); +U+97DE(0);U+97EB(1,3);U+97EB(1,3) +U+97DF(0);U+97DF(0); +U+97E0(0);U+97E0(3); +U+97E1(0);U+97E1(0); +U+97E2(0);U+97E2(0); +U+97E3(0);U+97E3(3);U+97E5(3) +U+97E4(0);U+889C(3,4);U+889C(3,4),U+896A(2),U+97C8(3) +U+97E5(0);U+97E3(3);U+97E3(3) +U+97E6(0);U+97E6(1,3);U+97CB(1,3) +U+97E7(0);U+97E7(1,3);U+8095(3),U+976D(4),U+97CC(1,3,4) +U+97E8(0);U+97E8(1,3);U+97CD(1,3) +U+97E9(0);U+97E9(1,3);U+97D3(1,3) +U+97EA(0);U+97EA(1,3);U+97D9(1,3) +U+97EB(0);U+97EB(1,3);U+97DE(1,3) +U+97EC(0);U+97EC(1,3);U+97DC(1,3) + +U+97ED(0);U+97ED(5);U+97EE(2,3) +U+97EE(0);U+97ED(2,3);U+97ED(2,3) +U+97EF(0);U+97EF(0); +U+97F0(0);U+97F0(0); +U+97F1(0);U+97F1(3); +U+97F2(0);U+9F51(3);U+9F4F(3),U+9F51(3),U+8640(0,3) +U+97F3(0);U+97F3(5); +U+97F4(0);U+97F4(0); +U+97F5(0);U+97F5(5);U+97FB(2,3) +U+97F6(0);U+97F6(5); +U+97F7(0);U+97F7(0); +U+97F8(0);U+97F8(3); +U+97F9(0);U+97F9(0); +U+97FA(0);U+97FA(0); +U+97FB(0);U+97F5(2,3);U+97F5(2,3) +U+97FD(0);U+97FD(0); +U+97FE(0);U+97FE(0); +U+97FF(0);U+54CD(1,3);U+54CD(1,3) +U+9800(0);U+9800(3); +U+9801(0);U+9875(1,3);U+9875(1,3) +U+9802(0);U+9876(1,3);U+9876(1,3) +U+9803(0);U+9877(1,3);U+9877(1,3) +U+9804(0);U+9804(0); +U+9805(0);U+9879(1,3);U+9879(1,3) +U+9806(0);U+987A(1,3);U+987A(1,3) +U+9807(0);U+9878(1,3);U+9878(1,3) +U+9808(0);U+987B(1,3);U+987B(1,3),U+9B1A(3,4) +U+9809(0);U+9890(3);U+9824(3),U+9890(3),U+984A(3) +U+980A(0);U+987C(1,3);U+987C(1,3) +U+980B(0);U+987E(3);U+9867(3),U+987E(3) +U+980C(0);U+9882(1,3);U+9882(1,3) +U+980D(0);U+980D(0); +U+980E(0);U+9880(1,3);U+9880(1,3) +U+980F(0);U+9883(1,3);U+9883(1,3) +U+9810(0);U+9884(1,3);U+9884(1,3) +U+9811(0);U+987D(1,3);U+987D(1,3) +U+9812(0);U+9881(1,3);U+670C(3),U+9881(1,3) +U+9813(0);U+987F(1,3);U+987F(1,3) +U+9814(0);U+9814(0); +U+9815(0);U+9815(0); +U+9816(0);U+9816(0); +U+9817(0);U+9887(1,3);U+9887(1,3) +U+9818(0);U+9886(1,3);U+9886(1,3) +U+9819(0);U+9819(0); +U+981A(0);U+9888(4);U+9838(4),U+9888(4),U+9D5B(3,4) +U+981B(0);U+981B(0); +U+981C(0);U+988C(1,3);U+988C(1,3) +U+981D(0);U+981D(0); +U+981E(0);U+981E(3);U+9F43(3) +U+9820(0);U+9820(0); +U+9821(0);U+9889(1,3);U+9889(1,3) +U+9822(0);U+9822(0); +U+9823(0);U+9823(0); +U+9824(0);U+9890(1,3);U+9809(3),U+9890(1,3),U+984A(3) +U+9826(0);U+988F(1,3);U+988F(1,3) +U+9827(0);U+9827(0); +U+9828(0);U+9828(0); +U+9829(0);U+9829(4); +U+982B(0);U+4FEF(2,3);U+4FEF(2,3),U+4FDB(0,2,3) +U+982D(0);U+5934(1,3);U+5934(1,3) +U+982E(0);U+9892(4);U+9892(4) +U+982F(0);U+982F(3); +U+9830(0);U+988A(1,3);U+988A(1,3) + +U+9831(0);U+9831(0); +U+9832(0);U+988B(1,3);U+988B(1,3) +U+9834(0);U+9896(1,2,3);U+7A4E(2),U+9895(4),U+9896(1,2,3) +U+9835(0);U+9835(0); +U+9836(0);U+9836(0); +U+9837(0);U+9894(1,3);U+9894(1,3) +U+9838(0);U+9888(1,3);U+981A(4),U+9888(1,3),U+9D5B(3,4) +U+9839(0);U+9893(4);U+983D(4),U+9893(4),U+7A68(0,4) +U+983B(0);U+9891(1,3);U+9891(1,3) +U+983C(0);U+8D56(4);U+8CF4(2,3),U+8D56(4) +U+983D(0);U+9893(1,3);U+9839(4),U+9893(1,3),U+7A68(0,1,3,4) +U+983F(0);U+983F(4); +U+9840(0);U+9840(0); +U+9841(0);U+9841(0); +U+9843(0);U+9843(0); +U+9844(0);U+9844(0); +U+9845(0);U+9845(0); +U+9846(0);U+9897(1,3);U+9897(1,3) +U+9848(0);U+9848(0); +U+9849(0);U+9849(3); +U+984A(0);U+9890(3);U+9890(3),U+9809(0,3),U+9824(3) +U+984C(0);U+9898(1,3);U+9898(1,3) +U+984D(0);U+989D(1,3);U+989D(1,3) +U+984E(0);U+989A(4);U+989A(4) +U+984F(0);U+989C(4);U+9854(8,9),U+989C(4) +U+9850(0);U+8BE8(3);U+8BE8(3),U+8AE2(0,1,3) +U+9851(0);U+9851(0); +U+9852(0);U+9899(1,3);U+9899(1,3) +U+9853(0);U+989B(1,3);U+989B(1,3) +U+9854(0);U+989C(1,3);U+984F(8,9),U+989C(1,3) +U+9855(0);U+663E(4);U+663E(4),U+986F(4) +U+9857(0);U+9857(0); +U+9858(0);U+613F(1,3);U+613F(1,3) +U+9859(0);U+98A1(1,3);U+98A1(1,3) +U+985A(0);U+98A0(3);U+985B(3),U+98A0(3),U+508E(0,3) +U+985B(0);U+98A0(1,3);U+985A(3),U+98A0(1,3),U+508E(0,1,3) +U+985C(0);U+985C(0); +U+985D(0);U+985D(0); +U+985E(0);U+7C7B(1,3);U+7C7B(1,3) +U+985F(0);U+985F(0); +U+9860(0);U+9860(0); +U+9861(0);U+9861(0); +U+9862(0);U+989F(1,3);U+989F(1,3) +U+9863(0);U+8E59(3);U+8E59(3) +U+9864(0);U+9864(0); +U+9865(0);U+98A2(1,3);U+98A2(1,3) +U+9867(0);U+987E(1,3);U+980B(3),U+987E(1,3) +U+9869(0);U+9869(3); +U+986A(0);U+986A(3); +U+986B(0);U+98A4(1,3);U+98A4(1,3) +U+986C(0);U+98A5(1,3);U+98A5(1,3) +U+986D(0);U+986D(0); +U+986E(0);U+986E(0); +U+986F(0);U+663E(1,3);U+663E(1,3),U+9855(4) +U+9870(0);U+98A6(1,3);U+98A6(1,3) +U+9871(0);U+9885(1,3);U+9885(1,3) +U+9872(0);U+9872(0); +U+9873(0);U+989E(1,3);U+989E(1,3) +U+9874(0);U+98A7(1,3);U+98A7(1,3) +U+9875(0);U+9875(1,3);U+9801(1,3) +U+9876(0);U+9876(1,3);U+9802(1,3) +U+9877(0);U+9877(1,3);U+9803(1,3) +U+9878(0);U+9878(1,3);U+9807(1,3) + +U+9879(0);U+9879(1,3);U+9805(1,3) +U+987A(0);U+987A(1,3);U+9806(1,3) +U+987B(0);U+987B(1,3);U+9808(1,3),U+9B1A(1) +U+987C(0);U+987C(1,3);U+980A(1,3) +U+987D(0);U+987D(1,3);U+9811(1,3) +U+987E(0);U+987E(1,3);U+980B(3),U+9867(1,3) +U+987F(0);U+987F(1,3);U+9813(1,3) +U+9880(0);U+9880(1,3);U+980E(1,3) +U+9881(0);U+9881(1,3);U+670C(3),U+9812(1,3) +U+9882(0);U+9882(1,3);U+980C(1,3) +U+9883(0);U+9883(1,3);U+980F(1,3) +U+9884(0);U+9884(1,3);U+9810(1,3) +U+9885(0);U+9885(1,3);U+9871(1,3) +U+9886(0);U+9886(1,3);U+9818(1,3) +U+9887(0);U+9887(1,3);U+9817(1,3) +U+9888(0);U+9888(1,3);U+981A(4),U+9838(1,3),U+9D5B(3) +U+9889(0);U+9889(1,3);U+9821(1,3) +U+988A(0);U+988A(1,3);U+9830(1,3) +U+988B(0);U+988B(1,3);U+9832(1,3) +U+988C(0);U+988C(1,3);U+981C(1,3) +U+988D(0);U+988D(1,3);U+6F41(1,3) +U+988E(0);U+988E(4);U+71B2(4) +U+988F(0);U+988F(1,3);U+9826(1,3) +U+9890(0);U+9890(1,3);U+9809(3),U+9824(1,3),U+984A(3) +U+9891(0);U+9891(1,3);U+983B(1,3) +U+9892(0);U+9892(4);U+982E(4) +U+9893(0);U+9893(1,3,4);U+7A68(4),U+9839(4),U+983D(1,3) +U+9894(0);U+9894(1,3);U+9837(1,3) +U+9895(0);U+9896(1,2,3);U+7A4E(8,9),U+9834(4),U+9896(1,2,3) +U+9896(0);U+9896(1,3,4);U+7A4E(1,3),U+9834(4),U+9895(4) +U+9897(0);U+9897(1,3);U+9846(1,3) +U+9898(0);U+9898(1,3);U+984C(1,3) +U+9899(0);U+9899(1,3);U+9852(1,3) +U+989A(0);U+989A(4);U+984E(4) +U+989B(0);U+989B(1,3);U+9853(1,3) +U+989C(0);U+989C(1,3,4);U+984F(4),U+9854(1,3) +U+989D(0);U+989D(1,3);U+984D(1,3) +U+989E(0);U+989E(1,3);U+9873(1,3) +U+989F(0);U+989F(1,3);U+9862(1,3) +U+98A0(0);U+98A0(1,3);U+508E(3),U+985B(1,3),U+985A(3) +U+98A1(0);U+98A1(1,3);U+9859(1,3) +U+98A2(0);U+98A2(1,3);U+9865(1,3) +U+98A3(0);U+98A3(4);U+7E87(4) +U+98A4(0);U+98A4(1,3);U+986B(1,3) +U+98A5(0);U+98A5(1,3);U+986C(1,3) +U+98A6(0);U+98A6(1,3);U+9870(1,3) +U+98A7(0);U+98A7(1,3);U+9874(1,3) +U+98A8(0);U+98CE(1,3);U+51E8(3),U+98CE(1,3),U+98CC(3) +U+98A9(0);U+98A9(0); +U+98AA(0);U+98AA(0); +U+98AB(0);U+98AB(0); +U+98AC(0);U+98AC(0); +U+98AD(0);U+98D0(4);U+98D0(4) +U+98AE(0);U+98D1(4);U+98D1(4) +U+98AF(0);U+98D2(1,3);U+98D2(1,3) +U+98B0(0);U+98B0(0); +U+98B1(0);U+53F0(1,3);U+53F0(1,3),U+6AAF(1,3,4),U+7C49(1,3,4),U+81FA(1,3,4) +U+98B2(0);U+98B2(0); +U+98B3(0);U+522E(1,3);U+522E(1,3),U+5280(1,3,4) +U+98B4(0);U+98B4(0); +U+98B5(0);U+98B5(0); +U+98B6(0);U+98D3(1,3);U+98D3(1,3) +U+98B8(0);U+98D4(1,3);U+98D4(1,3) + +U+98B9(0);U+98B9(0); +U+98BA(0);U+98CF(4);U+626C(4),U+63DA(2),U+98CF(4) +U+98BB(0);U+98D6(4);U+98D6(4) +U+98BC(0);U+98D5(1,3);U+98D5(1,3) +U+98BD(0);U+98BD(0); +U+98BE(0);U+98BE(0); +U+98BF(0);U+98BF(0); +U+98C0(0);U+98D7(1,3);U+98D7(1,3) +U+98C1(0);U+98C1(0); +U+98C2(0);U+98C2(3); +U+98C3(0);U+98D8(4);U+98C4(2,3),U+98D8(4),U+65DA(0,3,4) +U+98C4(0);U+98D8(1,3);U+98C3(2,3),U+98D8(1,3),U+65DA(0,1,3) +U+98C5(0);U+98C5(0); +U+98C6(0);U+98D9(1,3);U+98C8(3),U+98D9(1,3),U+98DA(4) +U+98C8(0);U+98DA(4);U+98C6(3),U+98DA(4),U+98D9(1,3) +U+98C9(0);U+98C9(0); +U+98CB(0);U+98CB(0); +U+98CC(0);U+98CE(3);U+98CE(3),U+51E8(0,3),U+98A8(3) +U+98CD(0);U+98CD(0); +U+98CE(0);U+98CE(1,3);U+51E8(3),U+98A8(1,3),U+98CC(3) +U+98CF(0);U+98CF(4);U+626C(4),U+98BA(4),U+63DA(1,3,4) +U+98D0(0);U+98D0(4);U+98AD(4) +U+98D1(0);U+98D1(4);U+98AE(4) +U+98D2(0);U+98D2(1,3);U+98AF(1,3) +U+98D3(0);U+98D3(1,3);U+98B6(1,3) +U+98D4(0);U+98D4(1,3);U+98B8(1,3) +U+98D5(0);U+98D5(1,3);U+98BC(1,3) +U+98D6(0);U+98D6(4);U+98BB(4) +U+98D7(0);U+98D7(1,3);U+98C0(1,3) +U+98D8(0);U+98D8(1,3);U+65DA(3),U+98C3(4),U+98C4(1,3) +U+98D9(0);U+98D9(1,3);U+98C6(1,3),U+98C8(1,3),U+98DA(1,3,4) +U+98DA(0);U+98DA(4);U+98C6(4),U+98C8(4),U+98D9(1,3,4) +U+98DB(0);U+98DE(1,3);U+98DE(1,3) +U+98DC(0);U+7FFB(2,3);U+7FFB(2,3),U+7E59(0,2,3) +U+98DD(0);U+98DD(0); +U+98DE(0);U+98DE(1,3);U+98DB(1,3) +U+98DF(0);U+98DF(5);U+98E0(8,9),U+9963(8,9) +U+98E0(0);U+9963(4);U+98DF(8,9),U+9963(4) +U+98E2(0);U+9965(1);U+9951(3,4),U+9965(1) +U+98E3(0);U+9964(4);U+9964(4) +U+98E5(0);U+9966(1,3);U+9966(1,3) +U+98E6(0);U+98E6(0); +U+98E7(0);U+98E7(5); +U+98E8(0);U+98E8(1,3);U+9957(1,3) +U+98E9(0);U+9968(1,3);U+9968(1,3) +U+98EA(0);U+996A(1,3);U+9901(2,3),U+996A(1,3) +U+98EB(0);U+996B(1,3);U+996B(1,3),U+9947(1,3) +U+98ED(0);U+996C(1,3);U+996C(1,3) +U+98EF(0);U+996D(1,3);U+98F0(3),U+996D(1,3) +U+98F0(0);U+996D(3);U+98EF(3),U+996D(3) +U+98F2(0);U+996E(1,3);U+996E(1,3) +U+98F3(0);U+98F3(0); +U+98F4(0);U+9974(1,3);U+9974(1,3) +U+98F5(0);U+98F5(0); +U+98F6(0);U+98F6(0); +U+98F7(0);U+98F7(0); +U+98F9(0);U+9971(3);U+9971(3),U+98FD(1,3) +U+98FA(0);U+98FA(3); +U+98FC(0);U+9972(1,3);U+9972(1,3) +U+98FD(0);U+9971(1,3);U+9971(1,3),U+98F9(0,1,3) +U+98FE(0);U+9970(1,3);U+991D(3),U+9970(1,3) +U+98FF(0);U+9973(1,3);U+9973(1,3) +U+9900(0);U+9900(3); + +U+9901(0);U+996A(4);U+98EA(2,3),U+996A(4) +U+9902(0);U+9902(0); +U+9903(0);U+997A(1,3);U+997A(1,3) +U+9904(0);U+9978(1,3);U+9978(1,3) +U+9905(0);U+997C(1,3);U+9920(3),U+997C(1,3) +U+9906(0);U+9906(0); +U+9907(0);U+9907(0); +U+9908(0);U+7CCD(2);U+7CCD(2) +U+9909(0);U+9977(1,3);U+9977(1,3),U+995F(1,2,3) +U+990A(0);U+517B(1,3);U+517B(1,3) +U+990B(0);U+990B(0); +U+990C(0);U+9975(1,3);U+9975(1,3) +U+990D(0);U+990D(1,3);U+995C(1,3) +U+990E(0);U+9979(1,3);U+9979(1,3) +U+990F(0);U+997B(1,3);U+997B(1,3) +U+9910(0);U+9910(5);U+55B0(3) +U+9911(0);U+997D(1,3);U+997D(1,3) +U+9912(0);U+9981(1,3);U+9981(1,3) +U+9913(0);U+997F(1,3);U+997F(1,3) +U+9914(0);U+9914(3); +U+9915(0);U+9982(4);U+9982(4) +U+9916(0);U+997E(4);U+997E(4) +U+9917(0);U+9917(0); +U+9918(0);U+9980(4),U+4F59(1,3);U+4F59(1,3),U+9980(4) +U+991A(0);U+80B4(2,3);U+80B4(2,3) +U+991B(0);U+9984(1,3);U+9984(1,3) +U+991C(0);U+9983(1,3);U+9983(1,3) +U+991D(0);U+9970(3);U+98FE(3),U+9970(3) +U+991E(0);U+996F(1,3);U+996F(1,3) +U+991F(0);U+991F(3); +U+9920(0);U+997C(3);U+9905(3),U+997C(3) +U+9921(0);U+9985(1,3);U+9985(1,3) +U+9922(0);U+9922(0); +U+9923(0);U+9923(0); +U+9924(0);U+9924(0); +U+9925(0);U+9925(0); +U+9926(0);U+9926(0); +U+9927(0);U+9927(0); +U+9928(0);U+9986(1,3);U+8218(2,3),U+9986(1,3) +U+9929(0);U+9929(0); +U+992A(0);U+992A(0); +U+992B(0);U+992B(0); +U+992C(0);U+7CCA(2,3);U+7CCA(2,3) +U+992D(0);U+992D(0); +U+992E(0);U+992E(5); +U+992F(0);U+992F(0); +U+9930(0);U+9930(0); +U+9931(0);U+7CC7(2,3);U+7CC7(2,3) +U+9932(0);U+9932(0); +U+9933(0);U+9967(1,3);U+9967(1,3) +U+9934(0);U+9934(0); +U+9935(0);U+5582(4);U+5582(4) +U+9936(0);U+9989(1,3);U+9989(1,3) +U+9937(0);U+9987(1,3);U+9987(1,3) +U+9938(0);U+9938(0); +U+9939(0);U+7CD6(2,3);U+7CD6(2,3) +U+993A(0);U+998E(1,3);U+998E(1,3) +U+993C(0);U+9969(1,3);U+9969(1,3) +U+993D(0);U+9988(4);U+994B(2,3),U+9988(4) +U+993E(0);U+998F(1,3);U+998F(1,3) +U+993F(0);U+998A(1,3);U+998A(1,3) +U+9940(0);U+9940(0); +U+9941(0);U+998C(4);U+998C(4) + +U+9942(0);U+9942(0); +U+9943(0);U+998D(1,3);U+998D(1,3) +U+9945(0);U+9992(1,3);U+9992(1,3) +U+9946(0);U+9946(0); +U+9947(0);U+996B(3);U+996B(3),U+98EB(0,1,3) +U+9948(0);U+9990(1,3);U+9990(1,3) +U+9949(0);U+9991(1,3);U+9991(1,3) +U+994A(0);U+9993(1,3);U+7CE4(3),U+9993(1,3) +U+994B(0);U+9988(1,3);U+993D(2,3),U+9988(1,3) +U+994C(0);U+9994(1,3);U+9994(1,3) +U+994E(0);U+994E(3); +U+994F(0);U+994F(0); +U+9950(0);U+9950(0); +U+9951(0);U+9965(1,3);U+98E2(3,4),U+9965(1,3) +U+9952(0);U+9976(1,3);U+9976(1,3) +U+9953(0);U+9953(0); +U+9954(0);U+9954(5); +U+9955(0);U+9955(5); +U+9956(0);U+9956(0); +U+9957(0);U+98E8(1,3);U+98E8(1,3) +U+9958(0);U+9958(3); +U+9959(0);U+9959(3); +U+995B(0);U+995B(0); +U+995C(0);U+990D(1,3);U+990D(1,3) +U+995E(0);U+998B(1,3);U+998B(1,3) +U+995F(0);U+9977(2);U+9977(2),U+9909(0,1,2,3) +U+9960(0);U+9960(0); +U+9961(0);U+9961(0); +U+9962(0);U+9995(1,3);U+9995(1,3) +U+9963(0);U+9963(4);U+98DF(8,9),U+98E0(4) +U+9964(0);U+9964(4);U+98E3(4) +U+9965(0);U+9965(1,3);U+98E2(1),U+9951(1,3) +U+9966(0);U+9966(1,3);U+98E5(1,3) +U+9967(0);U+9967(1,3);U+9933(1,3) +U+9968(0);U+9968(1,3);U+98E9(1,3) +U+9969(0);U+9969(1,3);U+993C(1,3) +U+996A(0);U+996A(1,3);U+98EA(1,3),U+9901(4) +U+996B(0);U+996B(1,3);U+98EB(1,3),U+9947(3) +U+996C(0);U+996C(1,3);U+98ED(1,3) +U+996D(0);U+996D(1,3);U+98EF(1,3),U+98F0(3) +U+996E(0);U+996E(1,3);U+98F2(1,3) +U+996F(0);U+996F(1,3);U+991E(1,3) +U+9970(0);U+9970(1,3);U+98FE(1,3),U+991D(3) +U+9971(0);U+9971(1,3);U+98F9(3),U+98FD(1,3) +U+9972(0);U+9972(1,3);U+98FC(1,3) +U+9973(0);U+9973(1,3);U+98FF(1,3) +U+9974(0);U+9974(1,3);U+98F4(1,3) +U+9975(0);U+9975(1,3);U+990C(1,3) +U+9976(0);U+9976(1,3);U+9952(1,3) +U+9977(0);U+9977(1,3);U+9909(1,3),U+995F(2) +U+9978(0);U+9978(1,3);U+9904(1,3) +U+9979(0);U+9979(1,3);U+990E(1,3) +U+997A(0);U+997A(1,3);U+9903(1,3) +U+997B(0);U+997B(1,3);U+990F(1,3) +U+997C(0);U+997C(1,3);U+9905(1,3),U+9920(3) +U+997D(0);U+997D(1,3);U+9911(1,3) +U+997E(0);U+997E(4);U+9916(4) +U+997F(0);U+997F(1,3);U+9913(1,3) +U+9980(0);U+9980(4);U+9918(4),U+4F59(1,3,4) +U+9981(0);U+9981(1,3);U+9912(1,3) +U+9982(0);U+9982(4);U+9915(4) +U+9983(0);U+9983(1,3);U+991C(1,3) +U+9984(0);U+9984(1,3);U+991B(1,3) + +U+9985(0);U+9985(1,3);U+9921(1,3) +U+9986(0);U+9986(1,3);U+8218(4),U+9928(1,3) +U+9987(0);U+9987(1,3);U+9937(1,3) +U+9988(0);U+9988(1,3);U+993D(4),U+994B(1,3) +U+9989(0);U+9989(1,3);U+9936(1,3) +U+998A(0);U+998A(1,3);U+993F(1,3) +U+998B(0);U+998B(1,3);U+995E(1,3) +U+998C(0);U+998C(4);U+9941(4) +U+998D(0);U+998D(1,3);U+9943(1,3) +U+998E(0);U+998E(1,3);U+993A(1,3) +U+998F(0);U+998F(1,3);U+993E(1,3) +U+9990(0);U+9990(1,3);U+9948(1,3) +U+9991(0);U+9991(1,3);U+9949(1,3) +U+9992(0);U+9992(1,3);U+9945(1,3) +U+9993(0);U+9993(1,3);U+7CE4(3),U+994A(1,3) +U+9994(0);U+9994(1,3);U+994C(1,3) +U+9995(0);U+9995(1,3);U+9962(1,3) +U+9996(0);U+9996(5); +U+9997(0);U+9997(5); +U+9998(0);U+9998(5);U+805D(4) +U+9999(0);U+9999(5); +U+999A(0);U+999A(0); +U+999B(0);U+999B(0); +U+999C(0);U+999C(0); +U+999D(0);U+999D(0); +U+999E(0);U+999E(0); +U+999F(0);U+999F(0); +U+99A0(0);U+99A0(0); +U+99A1(0);U+99A1(0); +U+99A2(0);U+99A2(0); +U+99A3(0);U+99A3(0); +U+99A4(0);U+99A4(0); +U+99A5(0);U+99A5(5); +U+99A6(0);U+99A6(0); +U+99A7(0);U+99A7(0); +U+99A8(0);U+99A8(5);U+99AB(3) +U+99A9(0);U+99A9(0); +U+99AA(0);U+99AA(0); +U+99AB(0);U+99A8(3);U+99A8(3) +U+99AC(0);U+9A6C(1,3);U+9A6C(1,3) +U+99AD(0);U+9A6D(1,3);U+9A6D(1,3) +U+99AE(0);U+51AF(1,3);U+51AF(1,3) +U+99AF(0);U+99AF(0); +U+99B0(0);U+99B0(0); +U+99B1(0);U+9A6E(1,3);U+99C4(3),U+9A6E(1,3) +U+99B2(0);U+99B2(3); +U+99B3(0);U+9A70(1,3);U+9A70(1,3) +U+99B4(0);U+9A6F(1,3);U+9A6F(1,3) +U+99B5(0);U+99B5(0); +U+99B6(0);U+99B6(0); +U+99B7(0);U+99B7(0); +U+99B8(0);U+99B8(0); +U+99B9(0);U+9A72(4);U+9A72(4) +U+99BA(0);U+99BA(0); +U+99BB(0);U+99BB(0); +U+99BC(0);U+99BC(0); +U+99BD(0);U+7D77(3);U+7D77(3),U+7E36(1,3) +U+99BE(0);U+99BE(0); +U+99C0(0);U+99C0(0); +U+99C1(0);U+9A73(1,3);U+99EE(2),U+9A73(1,3) +U+99C2(0);U+99C2(3); +U+99C3(0);U+99C3(0); +U+99C4(0);U+9A6E(3);U+99B1(3),U+9A6E(3) + +U+99C6(0);U+9A71(1);U+9A45(3),U+9A71(1),U+657A(0,1,4),U+99C8(1,4) +U+99C7(0);U+99C7(0); +U+99C8(0);U+9A71(4);U+9A45(2,3),U+9A71(4),U+657A(0,4),U+99C6(1,4) +U+99C9(0);U+99C9(4); +U+99CA(0);U+99CA(0); +U+99CB(0);U+99CB(0); +U+99CC(0);U+99CC(0); +U+99CD(0);U+99CD(0); +U+99CE(0);U+99CE(0); +U+99CF(0);U+99CF(0); +U+99D0(0);U+9A7B(1,3);U+9A7B(1,3) +U+99D1(0);U+9A7D(1,3);U+9A7D(1,3) +U+99D2(0);U+9A79(1,3);U+9A79(1,3) +U+99D3(0);U+99D3(0); +U+99D4(0);U+9A75(1,3);U+9A75(1,3) +U+99D5(0);U+9A7E(1,3);U+9A7E(1,3) +U+99D6(0);U+99D6(0); +U+99D7(0);U+99D7(0); +U+99D8(0);U+9A80(1,3);U+9A80(1,3) +U+99D9(0);U+9A78(1,3);U+9A78(1,3) +U+99DA(0);U+99DA(0); +U+99DB(0);U+9A76(1,3);U+9A76(1,3) +U+99DC(0);U+99DC(0); +U+99DD(0);U+9A7C(1,3);U+99DE(2,3),U+9A7C(1,3) +U+99DE(0);U+9A7C(4);U+99DD(2,3),U+9A7C(4) +U+99DF(0);U+9A77(1,3);U+9A77(1,3) +U+99E1(0);U+9A82(1,3);U+7F75(2,3),U+9A82(1,3),U+508C(0,1,3,4) +U+99E2(0);U+9A88(1,3);U+9A08(3),U+9A88(1,3) +U+99E3(0);U+99E3(0); +U+99E4(0);U+99E4(0); +U+99E5(0);U+99E5(0); +U+99E7(0);U+99E7(3); +U+99E8(0);U+99E8(0); +U+99E9(0);U+99E9(3); +U+99EA(0);U+99EA(0); +U+99EC(0);U+99EC(0); +U+99ED(0);U+9A87(1,3);U+9A87(1,3),U+99F4(1,3) +U+99EE(0);U+9A73(4);U+99C1(2),U+9A73(4) +U+99EF(0);U+99EF(0); +U+99F0(0);U+9A83(4);U+9A83(4) +U+99F1(0);U+9A86(1,3);U+9A86(1,3) +U+99F2(0);U+99F2(0); +U+99F3(0);U+99F3(0); +U+99F4(0);U+9A87(3);U+9A87(3),U+99ED(0,1,3) +U+99F6(0);U+99F6(0); +U+99F7(0);U+99F7(3); +U+99F8(0);U+9A8E(1,3);U+9A8E(1,3) +U+99F9(0);U+99F9(0); +U+99FA(0);U+99FA(0); +U+99FB(0);U+99FB(3); +U+99FC(0);U+99FC(0); +U+99FD(0);U+99FD(3); +U+99FE(0);U+99FE(0); +U+99FF(0);U+9A8F(1,3);U+9A8F(1,3) +U+9A00(0);U+9A00(0); +U+9A01(0);U+9A8B(1,3);U+9A8B(1,3) +U+9A02(0);U+9A8D(4);U+9A8D(4) +U+9A03(0);U+9A03(0);U+5446(2),U+7343(4) +U+9A04(0);U+9A04(0); +U+9A05(0);U+9A93(1,3);U+9A93(1,3) +U+9A06(0);U+9A06(0); +U+9A07(0);U+9A07(0); +U+9A08(0);U+9A88(3);U+99E2(3),U+9A88(3) + +U+9A09(0);U+9A09(0); +U+9A0A(0);U+9A0A(0); +U+9A0B(0);U+9A0B(0); +U+9A0C(0);U+9A94(4);U+9A23(3),U+9A94(4),U+9B03(2) +U+9A0D(0);U+9A92(1,3);U+9A92(1,3) +U+9A0E(0);U+9A91(1,3);U+9A91(1,3) +U+9A0F(0);U+9A90(1,3);U+9A90(1,3),U+9A39(1,3) +U+9A11(0);U+9A11(0); +U+9A14(0);U+9A14(0); +U+9A15(0);U+9A15(0); +U+9A16(0);U+9A9B(1,3);U+9A9B(1,3) +U+9A19(0);U+9A97(1,3);U+9A97(1,3) +U+9A1A(0);U+9A1A(0); +U+9A1B(0);U+9A1B(0); +U+9A1C(0);U+9A1C(0); +U+9A1D(0);U+9A1D(0); +U+9A1E(0);U+9A1E(4); +U+9A1F(0);U+9A1F(0); +U+9A20(0);U+9A20(0); +U+9A21(0);U+9A21(0); +U+9A22(0);U+9A22(0); +U+9A23(0);U+9B03(2,3);U+9A0C(3),U+9B03(2,3),U+9A94(3,4) +U+9A24(0);U+9A99(4);U+9A99(4) +U+9A25(0);U+9A25(0); +U+9A26(0);U+9A26(0); +U+9A27(0);U+9A27(0); +U+9A29(0);U+9A29(0); +U+9A2A(0);U+641C(3);U+641C(3),U+635C(0,3,4) +U+9A2B(0);U+9A9E(1,3);U+9A9E(1,3) +U+9A2C(0);U+9A2C(0); +U+9A2D(0);U+9A98(1,3);U+9A98(1,3) +U+9A2E(0);U+9A9D(1,3);U+9A9D(1,3) +U+9A2F(0);U+9A2F(0); +U+9A30(0);U+817E(1,3);U+817E(1,3) +U+9A31(0);U+9A31(0); +U+9A32(0);U+8349(4);U+8349(4),U+8278(0,2,3,4) +U+9A33(0);U+9A33(0); +U+9A34(0);U+9A34(0); +U+9A35(0);U+9A35(0); +U+9A36(0);U+9A7A(1,3);U+9A7A(1,3) +U+9A37(0);U+9A9A(1,3);U+9A9A(1,3) +U+9A38(0);U+9A9F(1,3);U+9A9F(1,3) +U+9A39(0);U+9A90(3);U+9A90(3),U+9A0F(0,1,3) +U+9A3A(0);U+9A3A(3);U+9A47(4) +U+9A3C(0);U+9A3C(0); +U+9A3D(0);U+9A3D(0); +U+9A3E(0);U+9AA1(1,3);U+9AA1(1,3) +U+9A3F(0);U+9A3F(0); +U+9A40(0);U+84E6(1,3);U+84E6(1,3) +U+9A41(0);U+9A9C(1,3);U+9A9C(1,3) +U+9A42(0);U+9A96(1,3);U+9A96(1,3) +U+9A43(0);U+9AA0(1,3);U+9AA0(1,3) +U+9A44(0);U+9AA2(1,3);U+9AA2(1,3) +U+9A45(0);U+9A71(1,3);U+99C6(3),U+99C8(2,3),U+9A71(1,3),U+657A(0,1,3,4) +U+9A46(0);U+8DF8(3);U+8DF8(3),U+8E55(1,3) +U+9A47(0);U+9A3A(4);U+9A3A(4) +U+9A48(0);U+9A48(0); +U+9A49(0);U+9A49(0); +U+9A4A(0);U+9A85(1,3);U+9A85(1,3) +U+9A4B(0);U+9A4B(0); +U+9A4C(0);U+9A95(4);U+9A95(4) +U+9A4D(0);U+9A81(1,3);U+9A81(1,3) +U+9A4E(0);U+9A4E(0); + +U+9A4F(0);U+9AA3(4);U+9AA3(4) +U+9A50(0);U+9A50(3); +U+9A52(0);U+9A52(0); +U+9A53(0);U+9A53(3); +U+9A54(0);U+9A54(0); +U+9A55(0);U+9A84(1,3);U+9A84(1,3),U+618D(0,1,3) +U+9A56(0);U+9A56(0); +U+9A57(0);U+9A8C(1,3);U+9A8C(1,3) +U+9A59(0);U+9A59(0); +U+9A5A(0);U+60CA(1,3);U+60CA(1,3) +U+9A5B(0);U+9A7F(1,3);U+9A7F(1,3) +U+9A5C(0);U+9A5C(0); +U+9A5E(0);U+9A5E(0); +U+9A5F(0);U+9AA4(1,3);U+9AA4(1,3) +U+9A60(0);U+9A60(0); +U+9A61(0);U+9A61(0); +U+9A62(0);U+9A74(1,3);U+9A74(1,3) +U+9A64(0);U+9AA7(1,3);U+9AA7(1,3) +U+9A65(0);U+9AA5(1,3);U+9AA5(1,3) +U+9A66(0);U+9AA6(4);U+9AA6(4) +U+9A67(0);U+9A67(0); +U+9A68(0);U+9A68(0); +U+9A69(0);U+6B22(4);U+6B22(4),U+6B61(2),U+61FD(0,4),U+6B53(3,4),U+8B99(4) +U+9A6A(0);U+9A8A(1,3);U+9A8A(1,3) +U+9A6B(0);U+9A89(4);U+9A89(4) +U+9A6C(0);U+9A6C(1,3);U+99AC(1,3) +U+9A6D(0);U+9A6D(1,3);U+99AD(1,3) +U+9A6E(0);U+9A6E(1,3);U+99B1(1,3),U+99C4(3) +U+9A6F(0);U+9A6F(1,3);U+99B4(1,3) +U+9A70(0);U+9A70(1,3);U+99B3(1,3) +U+9A71(0);U+9A71(1,3);U+657A(4),U+99C6(1),U+99C8(4),U+9A45(1,3) +U+9A72(0);U+9A72(4);U+99B9(4) +U+9A73(0);U+9A73(1,3);U+99C1(1,3),U+99EE(4) +U+9A74(0);U+9A74(1,3);U+9A62(1,3) +U+9A75(0);U+9A75(1,3);U+99D4(1,3) +U+9A76(0);U+9A76(1,3);U+99DB(1,3) +U+9A77(0);U+9A77(1,3);U+99DF(1,3) +U+9A78(0);U+9A78(1,3);U+99D9(1,3) +U+9A79(0);U+9A79(1,3);U+99D2(1,3) +U+9A7A(0);U+9A7A(1,3);U+9A36(1,3) +U+9A7B(0);U+9A7B(1,3);U+99D0(1,3) +U+9A7C(0);U+9A7C(1,3);U+99DE(4),U+99DD(1,3) +U+9A7D(0);U+9A7D(1,3);U+99D1(1,3) +U+9A7E(0);U+9A7E(1,3);U+99D5(1,3) +U+9A7F(0);U+9A7F(1,3);U+9A5B(1,3) +U+9A80(0);U+9A80(1,3);U+99D8(1,3) +U+9A81(0);U+9A81(1,3);U+9A4D(1,3) +U+9A82(0);U+9A82(1,3);U+508C(4),U+7F75(4),U+99E1(1,3) +U+9A83(0);U+9A83(4);U+99F0(4) +U+9A84(0);U+9A84(1,3);U+618D(3),U+9A55(1,3) +U+9A85(0);U+9A85(1,3);U+9A4A(1,3) +U+9A86(0);U+9A86(1,3);U+99F1(1,3) +U+9A87(0);U+9A87(1,3);U+99ED(1,3),U+99F4(3) +U+9A88(0);U+9A88(1,3);U+99E2(1,3),U+9A08(3) +U+9A89(0);U+9A89(4);U+9A6B(4) +U+9A8A(0);U+9A8A(1,3);U+9A6A(1,3) +U+9A8B(0);U+9A8B(1,3);U+9A01(1,3) +U+9A8C(0);U+9A8C(1,3);U+9A57(1,3) +U+9A8D(0);U+9A8D(4);U+9A02(4) +U+9A8E(0);U+9A8E(1,3);U+99F8(1,3) +U+9A8F(0);U+9A8F(1,3);U+99FF(1,3) +U+9A90(0);U+9A90(1,3);U+9A0F(1,3),U+9A39(3) +U+9A91(0);U+9A91(1,3);U+9A0E(1,3) + +U+9A92(0);U+9A92(1,3);U+9A0D(1,3) +U+9A93(0);U+9A93(1,3);U+9A05(1,3) +U+9A94(0);U+9A94(4);U+9A0C(4),U+9B03(4),U+9A23(3,4) +U+9A95(0);U+9A95(4);U+9A4C(4) +U+9A96(0);U+9A96(1,3);U+9A42(1,3) +U+9A97(0);U+9A97(1,3);U+9A19(1,3) +U+9A98(0);U+9A98(1,3);U+9A2D(1,3) +U+9A99(0);U+9A99(4);U+9A24(4) +U+9A9A(0);U+9A9A(1,3);U+9A37(1,3) +U+9A9B(0);U+9A9B(1,3);U+9A16(1,3) +U+9A9C(0);U+9A9C(1,3);U+9A41(1,3) +U+9A9D(0);U+9A9D(1,3);U+9A2E(1,3) +U+9A9E(0);U+9A9E(1,3);U+9A2B(1,3) +U+9A9F(0);U+9A9F(1,3);U+9A38(1,3) +U+9AA0(0);U+9AA0(1,3);U+9A43(1,3) +U+9AA1(0);U+9AA1(1,3);U+9A3E(1,3) +U+9AA2(0);U+9AA2(1,3);U+9A44(1,3) +U+9AA3(0);U+9AA3(4);U+9A4F(4) +U+9AA4(0);U+9AA4(1,3);U+9A5F(1,3) +U+9AA5(0);U+9AA5(1,3);U+9A65(1,3) +U+9AA6(0);U+9AA6(4);U+9A66(4) +U+9AA7(0);U+9AA7(1,3);U+9A64(1,3) +U+9AA8(0);U+9AA8(5); +U+9AAA(0);U+9AAB(3);U+9AAB(3) +U+9AAB(0);U+9AAB(3);U+9AAA(3) +U+9AAC(0);U+9AAC(0); +U+9AAD(0);U+9AAD(0); +U+9AAE(0);U+9AAE(0); +U+9AAF(0);U+80AE(1,3);U+80AE(1,3) +U+9AB0(0);U+9AB0(5); +U+9AB1(0);U+9AB1(5); +U+9AB2(0);U+9AB2(0); +U+9AB3(0);U+9AB3(0); +U+9AB4(0);U+9AB4(3);U+9ACA(3) +U+9AB5(0);U+4F53(3);U+4F53(3),U+9AD4(3),U+8EB0(3),U+8EC6(3) +U+9AB6(0);U+9AB6(5); +U+9AB7(0);U+9AB7(5); +U+9AB8(0);U+9AB8(5); +U+9AB9(0);U+9AB9(3);U+8E0D(3) +U+9ABA(0);U+9ABA(5); +U+9ABB(0);U+80EF(3);U+80EF(3) +U+9ABC(0);U+9ABC(5); +U+9ABE(0);U+9CA0(2);U+9CA0(2),U+9BC1(1,2,3) +U+9ABF(0);U+9ABF(0); +U+9AC0(0);U+9AC0(5); +U+9AC1(0);U+9AC1(5); +U+9AC2(0);U+9AC2(5); +U+9AC3(0);U+9AC3(0); +U+9AC4(0);U+9AD3(3);U+9AD3(3),U+81B8(0,3) +U+9AC5(0);U+9AC5(1,3);U+9ACF(1,3) +U+9AC6(0);U+9AC6(3); +U+9AC7(0);U+9AC7(3); +U+9AC9(0);U+9AC9(0); +U+9ACA(0);U+9AB4(3);U+9AB4(3) +U+9ACB(0);U+9ACB(1,3);U+9AD6(1,3) +U+9ACC(0);U+9ACC(1,3);U+9AD5(1,3),U+8191(1,3),U+81CF(0,1,3) +U+9ACD(0);U+9ACD(0); +U+9ACE(0);U+9ACE(0); +U+9ACF(0);U+9AC5(1,3);U+9AC5(1,3) +U+9AD0(0);U+9AD0(0); +U+9AD1(0);U+9AD1(5); +U+9AD2(0);U+810F(1,3);U+810F(1,3),U+81DF(1,3) +U+9AD3(0);U+9AD3(5);U+81B8(3),U+9AC4(3) + +U+9AD4(0);U+4F53(1,3);U+4F53(1,3),U+8EB0(3),U+8EC6(3),U+9AB5(3) +U+9AD5(0);U+9ACC(1,3);U+81CF(3),U+9ACC(1,3),U+8191(1,3) +U+9AD6(0);U+9ACB(1,3);U+9ACB(1,3) +U+9AD8(0);U+9AD8(5);U+9AD9(3) +U+9AD9(0);U+9AD8(3);U+9AD8(3) +U+9ADA(0);U+9ADA(0); +U+9ADB(0);U+9ADB(0); +U+9ADC(0);U+9ADC(0); +U+9ADD(0);U+9ADD(0); +U+9ADE(0);U+9ADE(0); +U+9ADF(0);U+9ADF(5); +U+9AE1(0);U+9AE1(5); +U+9AE2(0);U+9AE2(4); +U+9AE3(0);U+4EFF(2,3);U+4EFF(2,3),U+5023(2,3),U+5F77(2,3,4) +U+9AE5(0);U+9AEF(2,3);U+9AEF(2,3) +U+9AE6(0);U+9AE6(5);U+7266(3),U+6C02(0,2,3),U+729B(2,3) +U+9AE7(0);U+9AE7(0); +U+9AEA(0);U+53D1(4);U+53D1(4),U+9AEE(4),U+5F42(4),U+767C(1,3,4) +U+9AEB(0);U+9AEB(5); +U+9AEC(0);U+9AEC(0); +U+9AED(0);U+9AED(5); +U+9AEE(0);U+53D1(1,3);U+53D1(1,3),U+9AEA(4),U+5F42(1,3,4),U+767C(1,3) +U+9AEF(0);U+9AEF(5);U+9AE5(2,3) +U+9AF1(0);U+9AF1(0); +U+9AF2(0);U+9AF2(0); +U+9AF3(0);U+9AF3(3); +U+9AF4(0);U+4F5B(2);U+4F5B(2),U+5F7F(8,9),U+4ECF(0,2,3) +U+9AF5(0);U+9AF5(0); +U+9AF6(0);U+9AF6(0); +U+9AF7(0);U+9AF7(0); +U+9AF8(0);U+9AF8(0); +U+9AF9(0);U+9AF9(5); +U+9AFA(0);U+9AFA(3);U+9B20(3) +U+9AFB(0);U+9AFB(5); +U+9AFC(0);U+9AFC(3); +U+9AFD(0);U+9AFD(0); +U+9AFE(0);U+9AFE(0); +U+9AFF(0);U+9AFF(0); +U+9B01(0);U+75E2(4);U+75E2(4) +U+9B03(0);U+9B03(5);U+9A0C(2),U+9A23(2,3),U+9A94(4) +U+9B04(0);U+9B04(3); +U+9B05(0);U+9B05(0); +U+9B06(0);U+677E(1,3);U+677E(1,3),U+6780(1,3,4) +U+9B07(0);U+9B07(0); +U+9B08(0);U+9B08(5); +U+9B0A(0);U+9B0A(3); +U+9B0B(0);U+9B0B(0); +U+9B0C(0);U+9B0C(0); +U+9B0D(0);U+80E1(1,3);U+80E1(1,3),U+885A(1,2,3,4) +U+9B0E(0);U+760C(4);U+760C(4) +U+9B0F(0);U+9B0F(5); +U+9B10(0);U+9B10(0); +U+9B11(0);U+9B11(0); +U+9B12(0);U+9B12(4); +U+9B13(0);U+9B13(1,3);U+9B22(1,3) +U+9B15(0);U+9B15(0); +U+9B16(0);U+9B16(0); +U+9B17(0);U+9B17(0); +U+9B18(0);U+9B18(0); +U+9B19(0);U+9B19(0); +U+9B1A(0);U+987B(1);U+9808(3,4),U+987B(1) +U+9B1C(0);U+9B1C(3); +U+9B1D(0);U+9B1D(4); + +U+9B1E(0);U+9B1E(0); +U+9B1F(0);U+9B1F(5); +U+9B20(0);U+9AFA(3);U+9AFA(3) +U+9B21(0);U+9B21(3); +U+9B22(0);U+9B13(1,3);U+9B13(1,3) +U+9B23(0);U+9B23(5); +U+9B24(0);U+9B24(0); +U+9B25(0);U+6597(1,3);U+6597(1,3),U+95D8(4),U+9B26(2),U+9B2A(2),U+9B2C(2,3),U+9B2D(4) + +U+9B26(0);U+6597(4);U+6597(4),U+9B25(2),U+9B2C(4),U+9B2D(3),U+95D8(4),U+9B2A(4) +U+9B27(0);U+95F9(1,3);U+9599(2,3),U+95F9(1,3) +U+9B28(0);U+54C4(2,3);U+54C4(2,3),U+95A7(3) +U+9B29(0);U+960B(1,3);U+960B(1,3) +U+9B2A(0);U+6597(4);U+6597(4),U+9B25(2),U+9B2C(4),U+9B2D(3),U+95D8(4),U+9B26(4) +U+9B2B(0);U+961A(3);U+961A(3),U+95DE(0,1,3) +U+9B2C(0);U+6597(3);U+6597(3),U+9B25(2,3),U+9B26(4),U+9B2A(4),U+9B2D(3),U+95D8(3,4) +U+9B2D(0);U+6597(4);U+6597(4),U+95D8(3),U+9B25(4),U+9B26(3),U+9B2A(3),U+9B2C(3) +U+9B2E(0);U+9604(1,3);U+9604(1,3) +U+9B2F(0);U+9B2F(5); +U+9B30(0);U+90C1(4);U+90C1(4),U+9B31(2,3),U+6B1D(0,2,3,4) +U+9B31(0);U+90C1(1,3);U+6B1D(2,3),U+90C1(1,3),U+9B30(2,3) +U+9B32(0);U+9B32(5); +U+9B33(0);U+9B33(0); +U+9B35(0);U+9B35(0); +U+9B36(0);U+9B36(4);U+9B39(4) +U+9B37(0);U+9B37(0); +U+9B38(0);U+9B38(0); +U+9B39(0);U+9B36(4);U+9B36(4) +U+9B3A(0);U+9B3A(0); +U+9B3B(0);U+9B3B(5);U+7CA5(3) +U+9B3C(0);U+9B3C(5); +U+9B3E(0);U+9B3E(0); +U+9B3F(0);U+9B3F(0); +U+9B41(0);U+9B41(5);U+6AC6(3) +U+9B42(0);U+9B42(5); +U+9B43(0);U+9B43(5); +U+9B44(0);U+9B44(5); +U+9B45(0);U+9B45(5); +U+9B46(0);U+9B46(0); +U+9B47(0);U+9B47(1,3);U+9B58(1,3) +U+9B48(0);U+9B48(5); +U+9B49(0);U+9B49(1,3);U+9B4E(1,3) +U+9B4A(0);U+872E(4);U+872E(4) +U+9B4B(0);U+9B4B(0); +U+9B4C(0);U+9B4C(0); +U+9B4D(0);U+9B4D(5); +U+9B4E(0);U+9B49(1,3);U+9B49(1,3) +U+9B4F(0);U+9B4F(5); +U+9B51(0);U+9B51(5); +U+9B52(0);U+9B52(0); +U+9B53(0);U+9B53(0); +U+9B54(0);U+9B54(5); +U+9B55(0);U+9B55(0); +U+9B56(0);U+9B56(0); +U+9B58(0);U+9B47(1,3);U+9B47(1,3) +U+9B59(0);U+9B59(0); +U+9B5A(0);U+9C7C(1,3);U+9C7C(1,3) +U+9B5B(0);U+9C7D(1,3);U+9C7D(1,3) +U+9B5C(0);U+9B5C(0); +U+9B5D(0);U+9B5D(0); +U+9B5E(0);U+9B5E(0); +U+9B5F(0);U+9B5F(0); +U+9B60(0);U+9B60(0); + +U+9B61(0);U+9493(4);U+9493(4),U+91E3(0,1,4) +U+9B63(0);U+9B63(0); +U+9B64(0);U+9B64(0); +U+9B65(0);U+9B65(0); +U+9B66(0);U+9CA8(3);U+9CA8(3),U+9BCA(1,3),U+9BCB(3) +U+9B67(0);U+9B67(3); +U+9B68(0);U+9C80(4);U+9C80(4) +U+9B69(0);U+9B69(0); +U+9B6A(0);U+9B6A(0); +U+9B6B(0);U+9B6B(0); +U+9B6C(0);U+9B6C(0); +U+9B6D(0);U+9B6D(0); +U+9B6E(0);U+9B6E(0); +U+9B6F(0);U+9C81(1,3);U+9C81(1,3) +U+9B70(0);U+9B70(0); +U+9B71(0);U+9B71(0); +U+9B73(0);U+9B73(0); +U+9B74(0);U+9C82(1,3);U+9C82(1,3) +U+9B75(0);U+9B75(0); +U+9B76(0);U+9B76(3); +U+9B77(0);U+9C7F(1,3);U+9C7F(1,3) +U+9B78(0);U+9B78(0); +U+9B79(0);U+9B79(0); +U+9B7A(0);U+9C84(4);U+9C84(4) +U+9B7B(0);U+9B7B(0); +U+9B7C(0);U+9B7C(3);U+9C4B(3) +U+9B7D(0);U+86B6(3);U+86B6(3) +U+9B7E(0);U+9B7E(0); +U+9B7F(0);U+9B7F(0); +U+9B80(0);U+9B80(0); +U+9B81(0);U+9C85(1,3);U+9C85(1,3) +U+9B82(0);U+9B82(0); +U+9B83(0);U+9C86(1,3);U+9C86(1,3) +U+9B84(0);U+9B84(0); +U+9B85(0);U+9B85(0); +U+9B86(0);U+9B86(4); +U+9B87(0);U+9B87(3); +U+9B88(0);U+9B88(0); +U+9B8A(0);U+9C8C(4);U+9C8C(4) +U+9B8B(0);U+9C89(4);U+9C89(4) +U+9B8D(0);U+9C8F(1,3);U+9C8F(1,3) +U+9B8E(0);U+9C87(1,3);U+9C87(1,3) +U+9B8F(0);U+9B8F(3); +U+9B90(0);U+9C90(1,3);U+9C90(1,3) +U+9B91(0);U+9C8D(1,3);U+9C8D(1,3) +U+9B92(0);U+9C8B(1,3);U+9C8B(1,3) +U+9B93(0);U+9C8A(1,3);U+9C8A(1,3) +U+9B94(0);U+9B94(0); +U+9B95(0);U+9B95(0); +U+9B96(0);U+9B96(0); +U+9B97(0);U+9B97(0); +U+9B98(0);U+9B98(0); +U+9B9A(0);U+9C92(1,3);U+9C92(1,3) +U+9B9B(0);U+9B9B(0); +U+9B9C(0);U+9C98(4);U+9C98(4) +U+9B9D(0);U+9C9E(1,3);U+9C9E(1,3),U+9BD7(1,3) +U+9B9E(0);U+9C95(4);U+9C95(4) +U+9B9F(0);U+9B9F(0); +U+9BA0(0);U+9BA0(0); +U+9BA1(0);U+9BA1(0); +U+9BA2(0);U+9BA2(0); +U+9BA3(0);U+4C9F(1,3);U+4C9F(1,3) +U+9BA4(0);U+9BA4(0); + +U+9BA5(0);U+9BA5(0); +U+9BA6(0);U+9C96(1,3);U+9C96(1,3) +U+9BA7(0);U+9BA7(0); +U+9BA8(0);U+9BA8(3); +U+9BA9(0);U+9BA9(0); +U+9BAA(0);U+9C94(1,3);U+9C94(1,3) +U+9BAB(0);U+9C9B(1,3);U+9C9B(1,3) +U+9BAC(0);U+9BAC(0); +U+9BAD(0);U+9C91(1,3);U+9C91(1,3),U+89DF(0,1,3,4) +U+9BAE(0);U+9C9C(1,3);U+5C1F(2,3),U+5C20(2),U+9C9C(1,3) +U+9BAF(0);U+9BAF(0); +U+9BB0(0);U+9BB0(0); +U+9BB1(0);U+9BB1(0); +U+9BB2(0);U+9BB2(0); +U+9BB3(0);U+9C93(4);U+9C93(4) +U+9BB4(0);U+9BB4(0); +U+9BB5(0);U+9BB5(0); +U+9BB6(0);U+9CAA(4);U+9CAA(4) +U+9BB7(0);U+9BB7(3); +U+9BB8(0);U+9BB8(0); +U+9BB9(0);U+9BB9(0); +U+9BBA(0);U+9C9D(1,3);U+9C9D(1,3) +U+9BBB(0);U+9BBB(3); +U+9BBC(0);U+9BBC(0); +U+9BBD(0);U+9BBD(0); +U+9BBE(0);U+9BBE(3); +U+9BBF(0);U+9BBF(0); +U+9BC0(0);U+9CA7(1,3);U+9CA7(1,3) +U+9BC1(0);U+9CA0(1,3);U+9CA0(1,3),U+9ABE(0,1,2,3) +U+9BC3(0);U+9BC3(0); +U+9BC4(0);U+9BC4(0); +U+9BC5(0);U+9BC5(0); +U+9BC6(0);U+9BC6(0); +U+9BC7(0);U+9CA9(1,3);U+9CA9(1,3) +U+9BC8(0);U+9BC8(3); +U+9BC9(0);U+9CA4(1,3);U+9CA4(1,3) +U+9BCA(0);U+9CA8(1,3);U+9BCB(3),U+9CA8(1,3),U+9B66(0,1,3) +U+9BCB(0);U+9CA8(3);U+9BCA(3),U+9CA8(3),U+9B66(0,3) +U+9BCC(0);U+9BCC(0); +U+9BCD(0);U+9BCD(0); +U+9BCE(0);U+9BCE(0); +U+9BCF(0);U+9BCF(0); +U+9BD0(0);U+9BD0(0); +U+9BD1(0);U+9BD1(0); +U+9BD2(0);U+9CAC(4);U+9CAC(4) +U+9BD3(0);U+9BD3(0); +U+9BD4(0);U+9CBB(1,3);U+9CBB(1,3) +U+9BD5(0);U+9CAF(4);U+9CAF(4) +U+9BD6(0);U+9CAD(1,3);U+9CAD(1,3) +U+9BD7(0);U+9C9E(3);U+9C9E(3),U+9B9D(0,1,3) +U+9BD8(0);U+9BD8(0); +U+9BD9(0);U+9BD9(0); +U+9BDA(0);U+9BDA(0); +U+9BDB(0);U+9CB7(1,3);U+9CB7(1,3) +U+9BDC(0);U+9BDC(3); +U+9BDD(0);U+9CB4(4);U+9CB4(4) +U+9BDE(0);U+9BDE(0); +U+9BDF(0);U+9BDF(0); +U+9BE0(0);U+9BE0(0); +U+9BE1(0);U+9CB1(1,3);U+9CB1(1,3) +U+9BE2(0);U+9CB5(1,3);U+9CB5(1,3) +U+9BE3(0);U+9BE3(0); +U+9BE4(0);U+9CB2(1,3);U+9CB2(1,3) + +U+9BE5(0);U+9BE5(0); +U+9BE6(0);U+9BE6(3); +U+9BE7(0);U+9CB3(1,3);U+9CB3(1,3) +U+9BE8(0);U+9CB8(1,3);U+9CB8(1,3) +U+9BE9(0);U+9BE9(0); +U+9BEA(0);U+9CAE(1,3);U+9CAE(1,3) +U+9BEB(0);U+9CB0(1,3);U+9CB0(1,3) +U+9BEC(0);U+9BEC(0); +U+9BED(0);U+9BED(0); +U+9BEE(0);U+9BEE(0); +U+9BEF(0);U+9BEF(0); +U+9BF0(0);U+9CB6(1,3);U+9CB6(1,3) +U+9BF1(0);U+9BF1(0); +U+9BF2(0);U+9BF2(0); +U+9BF3(0);U+9BF3(0); +U+9BF4(0);U+9CBA(4);U+9CBA(4) +U+9BF5(0);U+9BF5(0); +U+9BF7(0);U+9CC0(4);U+9CC0(4) +U+9BF8(0);U+9BF8(0); +U+9BF9(0);U+9BF9(0); +U+9BFA(0);U+9BFA(0); +U+9BFB(0);U+9BFB(0); +U+9BFC(0);U+9BFC(4); +U+9BFD(0);U+9CAB(1,3);U+9CAB(1,3),U+9C3F(1,3) +U+9BFE(0);U+9BFE(4); +U+9BFF(0);U+9CCA(1,3);U+9CCA(1,3) +U+9C02(0);U+9C97(1,3);U+9C97(1,3) +U+9C05(0);U+9C05(0); +U+9C06(0);U+4CA0(1,3);U+4CA0(1,3) +U+9C07(0);U+9C07(0); +U+9C08(0);U+9CBD(1,3);U+9CBD(1,3) +U+9C09(0);U+9CC7(1,3);U+9CC7(1,3) +U+9C0A(0);U+9C0A(0); +U+9C0B(0);U+9C0B(0); +U+9C0C(0);U+4CA1(1,3);U+4CA1(1,3),U+9C0D(3),U+9CC5(1,3) +U+9C0D(0);U+9CC5(1,3);U+4CA1(1,3),U+9C0C(3),U+9CC5(1,3) +U+9C0E(0);U+9C0E(0); +U+9C0F(0);U+9CBE(4);U+9CBE(4) +U+9C10(0);U+9CC4(1,3);U+9CC4(1,3),U+9C77(1,3,4) +U+9C11(0);U+9C11(0); +U+9C12(0);U+9CC6(1,3);U+9CC6(1,3) +U+9C13(0);U+9CC3(1,3);U+9CC3(1,3) +U+9C14(0);U+9C14(0); +U+9C15(0);U+9C15(0); +U+9C16(0);U+9C16(0); +U+9C17(0);U+9C17(0); +U+9C18(0);U+9C18(0); +U+9C19(0);U+9C19(0); +U+9C1A(0);U+9C1A(0); +U+9C1B(0);U+9CC1(1,3);U+9CC1(1,3) +U+9C1C(0);U+9CD2(1,3);U+9CD2(1,3) +U+9C1D(0);U+9C1D(0); +U+9C1E(0);U+9C1E(0); +U+9C1F(0);U+9CD1(1,3);U+9CD1(1,3) +U+9C20(0);U+9CCB(4);U+9CCB(4) +U+9C21(0);U+9C21(0); +U+9C22(0);U+9C22(0); +U+9C23(0);U+9CA5(1,3);U+9CA5(1,3) +U+9C24(0);U+9C24(3); +U+9C25(0);U+9CCF(1,3);U+9CCF(1,3),U+9C5E(1,3) +U+9C26(0);U+9C26(0); +U+9C27(0);U+4CA2(1,3);U+4CA2(1,3) +U+9C28(0);U+9CCE(1,3);U+9CCE(1,3) + +U+9C29(0);U+9CD0(4);U+9CD0(4) +U+9C2A(0);U+9C2A(0); +U+9C2B(0);U+9CD9(3);U+9CD9(3),U+9C45(1,3) +U+9C2C(0);U+9C2C(0); +U+9C2D(0);U+9CCD(1,3);U+9CCD(1,3) +U+9C2F(0);U+9C2F(0); +U+9C30(0);U+9C30(0); +U+9C31(0);U+9CA2(1,3);U+9CA2(1,3) +U+9C32(0);U+9CCC(1,3);U+9CCC(1,3),U+9F07(1,3,4) +U+9C33(0);U+9CD3(1,3);U+9CD3(1,3) +U+9C34(0);U+9C34(0); +U+9C35(0);U+9CD8(1,3);U+9CD8(1,3) +U+9C36(0);U+9C36(0); +U+9C37(0);U+9CA6(1,3);U+9CA6(1,3) +U+9C38(0);U+9C38(0); +U+9C39(0);U+9CA3(1,3);U+9CA3(1,3) +U+9C3A(0);U+9CB9(4);U+9CB9(4) +U+9C3B(0);U+9CD7(1,3);U+9CD7(1,3) +U+9C3C(0);U+9CDB(1,3);U+9CDB(1,3) +U+9C3D(0);U+9C3D(0); +U+9C3E(0);U+9CD4(1,3);U+9CD4(1,3) +U+9C3F(0);U+9CAB(3);U+9CAB(3),U+9BFD(0,1,3) +U+9C40(0);U+9C40(4); +U+9C41(0);U+9C41(0); +U+9C43(0);U+9C43(0); +U+9C44(0);U+9C44(0); +U+9C45(0);U+9CD9(1,3);U+9CD9(1,3),U+9C2B(0,1,3) +U+9C46(0);U+9C46(0); +U+9C47(0);U+9C47(0); +U+9C48(0);U+9CD5(1,3);U+9CD5(1,3) +U+9C49(0);U+9CD6(1,3);U+9CD6(1,3),U+9F08(3,4),U+9F9E(3) +U+9C4A(0);U+9C4A(0); +U+9C4B(0);U+9B7C(3);U+9B7C(3) +U+9C4C(0);U+9C4C(0); +U+9C4D(0);U+9C4D(0); +U+9C4E(0);U+9C4E(0); +U+9C50(0);U+9C50(0); +U+9C52(0);U+9CDF(1,3);U+9CDF(1,3) +U+9C53(0);U+9CDD(3);U+9C54(2,3),U+9CDD(3) +U+9C54(0);U+9CDD(1,3);U+9C53(2,3),U+9CDD(1,3) +U+9C55(0);U+9C55(0); +U+9C56(0);U+9CDC(1,3);U+9CDC(1,3) +U+9C57(0);U+9CDE(1,3);U+9CDE(1,3) +U+9C58(0);U+9C9F(1,3);U+9C9F(1,3) +U+9C59(0);U+9C59(0); +U+9C5A(0);U+9C5A(0); +U+9C5B(0);U+9C5B(0); +U+9C5C(0);U+9C5C(0); +U+9C5D(0);U+9CBC(4);U+9CBC(4) +U+9C5E(0);U+9CCF(3);U+9CCF(3),U+9C25(0,1,3) +U+9C5F(0);U+9C8E(1,3);U+9C8E(1,3) +U+9C60(0);U+9C99(1,3);U+9C99(1,3) +U+9C62(0);U+9C62(3); +U+9C63(0);U+9CE3(1,3);U+9CE3(1,3) +U+9C65(0);U+9C65(0); +U+9C66(0);U+9C66(0); +U+9C67(0);U+9CE2(1,3);U+9CE2(1,3) +U+9C68(0);U+9CBF(1,3);U+9CBF(1,3) +U+9C69(0);U+9C69(0); +U+9C6A(0);U+9C6A(0); +U+9C6B(0);U+9C6B(0); +U+9C6C(0);U+9C6C(0); +U+9C6D(0);U+9C9A(1,3);U+9C9A(1,3) + +U+9C6E(0);U+9C6E(3); +U+9C6F(0);U+9CE0(4);U+9CE0(4) +U+9C70(0);U+9C70(0); +U+9C71(0);U+9C71(0); +U+9C72(0);U+9C72(0); +U+9C73(0);U+9C73(0); +U+9C74(0);U+9C74(0); +U+9C75(0);U+9C75(0); +U+9C77(0);U+9CC4(4);U+9CC4(4),U+9C10(0,1,3,4) +U+9C78(0);U+9C88(1,3);U+9C88(1,3) +U+9C79(0);U+9C79(0); +U+9C7A(0);U+9CA1(1,3);U+9CA1(1,3) +U+9C7C(0);U+9C7C(1,3);U+9B5A(1,3) +U+9C7D(0);U+9C7D(1,3);U+9B5B(1,3) +U+9C7E(0);U+9C7E(4); +U+9C7F(0);U+9C7F(1,3);U+9B77(1,3) +U+9C80(0);U+9C80(4);U+9B68(4) +U+9C81(0);U+9C81(1,3);U+9B6F(1,3) +U+9C82(0);U+9C82(1,3);U+9B74(1,3) +U+9C83(0);U+9C83(6); +U+9C84(0);U+9C84(4);U+9B7A(4) +U+9C85(0);U+9C85(1,3);U+9B81(1,3) +U+9C86(0);U+9C86(1,3);U+9B83(1,3) +U+9C87(0);U+9C87(1,3);U+9B8E(1,3) +U+9C88(0);U+9C88(1,3);U+9C78(1,3) +U+9C89(0);U+9C89(4);U+9B8B(4) +U+9C8A(0);U+9C8A(1,3);U+9B93(1,3) +U+9C8B(0);U+9C8B(1,3);U+9B92(1,3) +U+9C8C(0);U+9C8C(4);U+9B8A(4) +U+9C8D(0);U+9C8D(1,3);U+9B91(1,3) +U+9C8E(0);U+9C8E(1,3);U+9C5F(1,3) +U+9C8F(0);U+9C8F(1,3);U+9B8D(1,3) +U+9C90(0);U+9C90(1,3);U+9B90(1,3) +U+9C91(0);U+9C91(1,3);U+89DF(1,3,4),U+9BAD(1,3) +U+9C92(0);U+9C92(1,3);U+9B9A(1,3) +U+9C93(0);U+9C93(4);U+9BB3(4) +U+9C94(0);U+9C94(1,3);U+9BAA(1,3) +U+9C95(0);U+9C95(4);U+9B9E(4) +U+9C96(0);U+9C96(1,3);U+9BA6(1,3) +U+9C97(0);U+9C97(1,3);U+9C02(1,3) +U+9C98(0);U+9C98(4);U+9B9C(4) +U+9C99(0);U+9C99(1,3);U+9C60(1,3) +U+9C9A(0);U+9C9A(1,3);U+9C6D(1,3) +U+9C9B(0);U+9C9B(1,3);U+9BAB(1,3) +U+9C9C(0);U+9C9C(1,3);U+5C1F(3),U+5C20(2),U+9BAE(1,3) +U+9C9D(0);U+9C9D(1,3);U+9BBA(1,3) +U+9C9E(0);U+9C9E(1,3);U+9B9D(1,3),U+9BD7(3) +U+9C9F(0);U+9C9F(1,3);U+9C58(1,3) +U+9CA0(0);U+9CA0(1,3);U+9ABE(2),U+9BC1(1,3) +U+9CA1(0);U+9CA1(1,3);U+9C7A(1,3) +U+9CA2(0);U+9CA2(1,3);U+9C31(1,3) +U+9CA3(0);U+9CA3(1,3);U+9C39(1,3) +U+9CA4(0);U+9CA4(1,3);U+9BC9(1,3) +U+9CA5(0);U+9CA5(1,3);U+9C23(1,3) +U+9CA6(0);U+9CA6(1,3);U+9C37(1,3) +U+9CA7(0);U+9CA7(1,3);U+9BC0(1,3) +U+9CA8(0);U+9CA8(1,3);U+9B66(3),U+9BCA(1,3),U+9BCB(3) +U+9CA9(0);U+9CA9(1,3);U+9BC7(1,3) +U+9CAA(0);U+9CAA(4);U+9BB6(4) +U+9CAB(0);U+9CAB(1,3);U+9BFD(1,3),U+9C3F(3) +U+9CAC(0);U+9CAC(4);U+9BD2(4) +U+9CAD(0);U+9CAD(1,3);U+9BD6(1,3) +U+9CAE(0);U+9CAE(1,3);U+9BEA(1,3) + +U+9CAF(0);U+9CAF(4);U+9BD5(4) +U+9CB0(0);U+9CB0(1,3);U+9BEB(1,3) +U+9CB1(0);U+9CB1(1,3);U+9BE1(1,3) +U+9CB2(0);U+9CB2(1,3);U+9BE4(1,3) +U+9CB3(0);U+9CB3(1,3);U+9BE7(1,3) +U+9CB4(0);U+9CB4(4);U+9BDD(4) +U+9CB5(0);U+9CB5(1,3);U+9BE2(1,3) +U+9CB6(0);U+9CB6(1,3);U+9BF0(1,3) +U+9CB7(0);U+9CB7(1,3);U+9BDB(1,3) +U+9CB8(0);U+9CB8(1,3);U+9BE8(1,3) +U+9CB9(0);U+9CB9(4);U+9C3A(4) +U+9CBA(0);U+9CBA(4);U+9BF4(4) +U+9CBB(0);U+9CBB(1,3);U+9BD4(1,3) +U+9CBC(0);U+9CBC(4);U+9C5D(4) +U+9CBD(0);U+9CBD(1,3);U+9C08(1,3) +U+9CBE(0);U+9CBE(4);U+9C0F(4) +U+9CBF(0);U+9CBF(1,3);U+9C68(1,3) +U+9CC0(0);U+9CC0(4);U+9BF7(4) +U+9CC1(0);U+9CC1(1,3);U+9C1B(1,3) +U+9CC2(0);U+9CC2(4); +U+9CC3(0);U+9CC3(1,3);U+9C13(1,3) +U+9CC4(0);U+9CC4(1,3,4);U+9C10(1,3),U+9C77(4) +U+9CC5(0);U+9CC5(1,3);U+9C0D(1,3),U+4CA1(1,3),U+9C0C(1,3) +U+9CC6(0);U+9CC6(1,3);U+9C12(1,3) +U+9CC7(0);U+9CC7(1,3);U+9C09(1,3) +U+9CC8(0);U+9CC8(4); +U+9CC9(0);U+9CC9(4); +U+9CCA(0);U+9CCA(1,3);U+9BFF(1,3) +U+9CCB(0);U+9CCB(4);U+9C20(4) +U+9CCC(0);U+9CCC(1,3,4);U+9C32(1,3),U+9F07(4) +U+9CCD(0);U+9CCD(1,3);U+9C2D(1,3) +U+9CCE(0);U+9CCE(1,3);U+9C28(1,3) +U+9CCF(0);U+9CCF(1,3);U+9C25(1,3),U+9C5E(3) +U+9CD0(0);U+9CD0(4);U+9C29(4) +U+9CD1(0);U+9CD1(1,3);U+9C1F(1,3) +U+9CD2(0);U+9CD2(1,3);U+9C1C(1,3) +U+9CD3(0);U+9CD3(1,3);U+9C33(1,3) +U+9CD4(0);U+9CD4(1,3);U+9C3E(1,3) +U+9CD5(0);U+9CD5(1,3);U+9C48(1,3) +U+9CD6(0);U+9CD6(1,3);U+9C49(1,3),U+9F9E(3),U+9F08(1,3,4) +U+9CD7(0);U+9CD7(1,3);U+9C3B(1,3) +U+9CD8(0);U+9CD8(1,3);U+9C35(1,3) +U+9CD9(0);U+9CD9(1,3);U+9C2B(3),U+9C45(1,3) +U+9CDA(0);U+9CDA(6); +U+9CDB(0);U+9CDB(1,3);U+9C3C(1,3) +U+9CDC(0);U+9CDC(1,3);U+9C56(1,3) +U+9CDD(0);U+9CDD(1,3);U+9C53(3),U+9C54(1,3) +U+9CDE(0);U+9CDE(1,3);U+9C57(1,3) +U+9CDF(0);U+9CDF(1,3);U+9C52(1,3) +U+9CE0(0);U+9CE0(4);U+9C6F(4) +U+9CE1(0);U+9CE1(4); +U+9CE2(0);U+9CE2(1,3);U+9C67(1,3) +U+9CE3(0);U+9CE3(1,3);U+9C63(1,3) +U+9CE4(0);U+9CE4(6); +U+9CE5(0);U+9E1F(1,3);U+9E1F(1,3) +U+9CE6(0);U+9CE6(3); +U+9CE7(0);U+51EB(4);U+51EB(4),U+9CEC(1,3,4) +U+9CE8(0);U+9CE8(0); +U+9CE9(0);U+9E20(1,3);U+9E20(1,3) +U+9CEA(0);U+9CEA(0); +U+9CEB(0);U+96C1(3);U+96C1(3),U+9D08(3) +U+9CEC(0);U+51EB(1,3);U+51EB(1,3),U+9CE7(1,3,4) +U+9CED(0);U+9CED(0); + +U+9CEE(0);U+9E21(4);U+96DE(8,9),U+9DC4(4),U+9E21(4) +U+9CEF(0);U+51E4(3);U+51E4(3),U+9CF3(3) +U+9CF0(0);U+9CF0(0); +U+9CF1(0);U+9CF1(4); +U+9CF2(0);U+9E24(4);U+9E24(4) +U+9CF3(0);U+51E4(1,3);U+51E4(1,3),U+9CEF(3) +U+9CF4(0);U+9E23(1,3);U+9E23(1,3) +U+9CF5(0);U+9E28(3);U+9E28(3),U+9D07(1,3) +U+9CF6(0);U+9E22(1,3);U+9E22(1,3) +U+9CF7(0);U+9CF7(0); +U+9CF8(0);U+9CF8(0); +U+9CF9(0);U+9CF9(3); +U+9CFA(0);U+9CFA(0); +U+9CFB(0);U+9CFB(0); +U+9CFC(0);U+9CFC(3); +U+9CFD(0);U+9CFD(0); +U+9CFE(0);U+4D13(1,3);U+4D13(1,3) +U+9CFF(0);U+9CFF(0); +U+9D00(0);U+9D00(0); +U+9D01(0);U+9D01(0); +U+9D02(0);U+9D02(3);U+9D03(3) +U+9D03(0);U+9D02(3);U+9D02(3) +U+9D04(0);U+9D04(3); +U+9D05(0);U+9D05(0); +U+9D06(0);U+9E29(1,3);U+9E29(1,3) +U+9D07(0);U+9E28(1,3);U+9E28(1,3),U+9CF5(0,1,3) +U+9D08(0);U+96C1(2,3);U+96C1(2,3),U+9CEB(3) +U+9D09(0);U+9E26(1,3);U+9D76(2,3),U+9E26(1,3) +U+9D0A(0);U+9D0A(0); +U+9D0B(0);U+9D0B(0); +U+9D0F(0);U+9D0F(0); +U+9D10(0);U+9D10(0); +U+9D12(0);U+9E30(1,3);U+9E30(1,3) +U+9D13(0);U+9D13(0); +U+9D14(0);U+9D14(0); +U+9D15(0);U+9E35(1,3);U+9E35(1,3) +U+9D16(0);U+9D16(0); +U+9D17(0);U+9D17(0); +U+9D18(0);U+9D18(0); +U+9D19(0);U+96C9(3);U+96C9(3) +U+9D1A(0);U+9D1A(3); +U+9D1B(0);U+9E33(1,3);U+9E33(1,3) +U+9D1C(0);U+9D1C(0); +U+9D1D(0);U+9E32(1,3);U+9E32(1,3) +U+9D1E(0);U+9E2E(1,3);U+9E2E(1,3) +U+9D1F(0);U+9E31(1,3);U+9E31(1,3) +U+9D20(0);U+9D20(0); +U+9D21(0);U+9D21(0); +U+9D22(0);U+9D22(0); +U+9D23(0);U+9E2A(1,3);U+9E2A(1,3) +U+9D24(0);U+9D24(0); +U+9D25(0);U+9D25(3); +U+9D26(0);U+9E2F(1,3);U+9E2F(1,3) +U+9D28(0);U+9E2D(1,3);U+9E2D(1,3) +U+9D29(0);U+9D29(0); +U+9D2B(0);U+9D2B(0); +U+9D2D(0);U+9D2D(0); +U+9D2E(0);U+9D2E(0); +U+9D2F(0);U+9E38(1,3);U+9E38(1,3) +U+9D30(0);U+9E39(1,3);U+9E39(1,3) +U+9D31(0);U+9D31(0); +U+9D32(0);U+9D32(0); +U+9D33(0);U+9D33(3); + +U+9D34(0);U+9E3B(1,3);U+9E3B(1,3) +U+9D36(0);U+9D36(0); +U+9D37(0);U+4D15(1,3);U+4D15(1,3) +U+9D38(0);U+9D38(0); +U+9D39(0);U+9D39(0); +U+9D3A(0);U+9D3A(0); +U+9D3B(0);U+9E3F(1,3);U+9E3F(1,3) +U+9D3D(0);U+9D3D(3); +U+9D3E(0);U+9D3E(0); +U+9D3F(0);U+9E3D(1,3);U+9E3D(1,3) +U+9D40(0);U+9D40(0); +U+9D41(0);U+4D14(1,3);U+4D14(1,3) +U+9D42(0);U+9E3A(1,3);U+9E3A(1,3) +U+9D43(0);U+9E3C(1,3);U+9E3C(1,3) +U+9D45(0);U+9D45(0); +U+9D46(0);U+9D46(0); +U+9D47(0);U+9D47(0); +U+9D48(0);U+9D48(0); +U+9D49(0);U+9E3E(4);U+9E1E(4),U+9E3E(4) +U+9D4A(0);U+9D4A(0); +U+9D4B(0);U+9D4B(0); +U+9D4C(0);U+9D4C(3); +U+9D4D(0);U+9D4D(0); +U+9D4E(0);U+9D4E(0); +U+9D4F(0);U+9D4F(0); +U+9D50(0);U+9E40(4);U+9E40(4) +U+9D51(0);U+9E43(1,3);U+9E43(1,3) +U+9D52(0);U+9E46(1,3);U+9E46(1,3) +U+9D53(0);U+9E41(1,3);U+9E41(1,3) +U+9D54(0);U+9D54(3); +U+9D55(0);U+9D55(4); +U+9D56(0);U+9D56(0); +U+9D57(0);U+9D57(0); +U+9D58(0);U+9D58(0); +U+9D59(0);U+9D59(3); +U+9D5A(0);U+9D5A(0); +U+9D5B(0);U+9888(3);U+9888(3),U+981A(0,3,4),U+9838(3,4) +U+9D5C(0);U+9E48(1,3);U+9E48(1,3) +U+9D5D(0);U+9E45(1,3);U+9D5E(2,3),U+9E45(1,3) +U+9D5E(0);U+9E45(4);U+9D5D(2,3),U+9E45(4) +U+9D5F(0);U+9D5F(0); +U+9D60(0);U+9E44(1,3);U+9E44(1,3) +U+9D61(0);U+9E49(1,3);U+9E49(1,3) +U+9D62(0);U+9D62(0); +U+9D63(0);U+9D63(0); +U+9D64(0);U+9D64(0); +U+9D65(0);U+9D65(0); +U+9D66(0);U+9D66(0); +U+9D67(0);U+9D67(0); +U+9D68(0);U+9D68(0); +U+9D69(0);U+9D69(0); +U+9D6A(0);U+9E4C(1,3);U+9E4C(1,3) +U+9D6B(0);U+9D6B(0); +U+9D6C(0);U+9E4F(1,3);U+9E4F(1,3) +U+9D6E(0);U+9E50(1,3);U+9E50(1,3) +U+9D6F(0);U+9E4E(4);U+9E4E(4) +U+9D70(0);U+96D5(2,3);U+96D5(2,3),U+5F6B(2,3),U+7431(2,3) +U+9D71(0);U+9D71(0); +U+9D72(0);U+9E4A(1,3);U+9E4A(1,3) +U+9D73(0);U+9D73(0); +U+9D74(0);U+9D74(0); +U+9D75(0);U+9D75(0); +U+9D76(0);U+9E26(4);U+9D09(2,3),U+9E26(4) + +U+9D77(0);U+9E53(4);U+9E53(4) +U+9D78(0);U+9D78(0); +U+9D79(0);U+9D79(0); +U+9D7A(0);U+9D7A(0); +U+9D7B(0);U+9D7B(0); +U+9D7C(0);U+9D7C(0); +U+9D7D(0);U+9D7D(0); +U+9D7E(0);U+9E4D(4);U+9E4D(4),U+9DA4(4) +U+9D7F(0);U+9D7F(0); +U+9D80(0);U+9D80(0); +U+9D81(0);U+9D81(0); +U+9D82(0);U+9D82(3); +U+9D83(0);U+9D83(0); +U+9D84(0);U+4D16(1,3);U+4D16(1,3) +U+9D85(0);U+9D85(3); +U+9D86(0);U+9D86(0); +U+9D87(0);U+9E2B(1,3);U+9E2B(1,3) +U+9D88(0);U+9D88(0); +U+9D89(0);U+9E51(1,3);U+9E51(1,3) +U+9D8A(0);U+9E52(1,3);U+9E52(1,3) +U+9D8B(0);U+9D8B(0); +U+9D8C(0);U+9D8C(0); +U+9D8D(0);U+9D8D(0); +U+9D8E(0);U+9D8E(0); +U+9D90(0);U+9D90(0); +U+9D91(0);U+9D91(0); +U+9D92(0);U+9D92(3);U+9DD8(3) +U+9D93(0);U+9E4B(1,3);U+9E4B(1,3) +U+9D94(0);U+9D94(0); +U+9D96(0);U+9E59(1,3);U+9E59(1,3) +U+9D97(0);U+9D97(3); +U+9D98(0);U+9E55(1,3);U+9E55(1,3) +U+9D99(0);U+9D99(0); +U+9D9A(0);U+9E57(1,3);U+9E57(1,3) +U+9D9B(0);U+9D9B(0); +U+9D9C(0);U+9D9C(0); +U+9D9D(0);U+9D9D(0); +U+9D9E(0);U+9D9E(0); +U+9D9F(0);U+9D9F(0); +U+9DA0(0);U+9DA0(0); +U+9DA1(0);U+9E56(1,3);U+9E56(1,3) +U+9DA2(0);U+9DA2(0); +U+9DA3(0);U+9DA3(0); +U+9DA4(0);U+9E4D(4);U+9E4D(4),U+9D7E(0,4) +U+9DA5(0);U+9E5B(1,3);U+9E5B(1,3) +U+9DA6(0);U+9DA6(0); +U+9DA7(0);U+9DA7(0); +U+9DA8(0);U+9DA8(0); +U+9DA9(0);U+9E5C(1,3);U+9E5C(1,3) +U+9DAA(0);U+4D17(1,3);U+4D17(1,3) +U+9DAB(0);U+9DAB(0); +U+9DAC(0);U+9E27(1,3);U+9E27(1,3) +U+9DAD(0);U+9DAD(3); +U+9DAF(0);U+83BA(1,3);U+83BA(1,3) +U+9DB0(0);U+9DB0(0); +U+9DB1(0);U+9DB1(0); +U+9DB2(0);U+9E5F(4);U+9E5F(4) +U+9DB3(0);U+9DB3(3); +U+9DB4(0);U+9E64(1,3);U+9E64(1,3) +U+9DB5(0);U+96CF(3);U+96CF(3),U+96DB(1,3) +U+9DB6(0);U+9DB6(0); +U+9DB7(0);U+9DB7(0); +U+9DB8(0);U+9DB8(0); + +U+9DB9(0);U+9E60(4);U+9E60(4) +U+9DBA(0);U+9E61(1,3);U+9E61(1,3) +U+9DBB(0);U+9E58(1,3);U+9E58(1,3) +U+9DBC(0);U+9E63(1,3);U+9E63(1,3) +U+9DBE(0);U+7FF0(3);U+7FF0(3) +U+9DBF(0);U+9E5A(2,3);U+9E5A(2,3) +U+9DC1(0);U+9E62(4);U+9E62(4) +U+9DC2(0);U+9E5E(1);U+9E5E(1) +U+9DC3(0);U+9DC3(0); +U+9DC4(0);U+9E21(1,3);U+96DE(2,3,4),U+9CEE(4),U+9E21(1,3) +U+9DC5(0);U+9DC5(0); +U+9DC7(0);U+9DC7(0); +U+9DC8(0);U+4D18(3);U+4D18(3),U+9DC9(1,3) +U+9DC9(0);U+4D18(1,3);U+4D18(1,3),U+9DC8(1,3) +U+9DCA(0);U+9E5D(4);U+9E5D(4) +U+9DCB(0);U+9DCB(0); +U+9DCC(0);U+9DCC(0); +U+9DCD(0);U+67AD(3);U+67AD(3),U+689F(1,3) +U+9DCE(0);U+9DCE(0); +U+9DCF(0);U+9DCF(0); +U+9DD0(0);U+9DD0(0); +U+9DD1(0);U+9DD1(0); +U+9DD2(0);U+9DD2(0); +U+9DD3(0);U+9E67(1,3);U+9E67(1,3) +U+9DD4(0);U+9DD4(3); +U+9DD5(0);U+9DD5(0); +U+9DD6(0);U+9E65(1,3);U+9E65(1,3) +U+9DD7(0);U+9E25(1,3);U+9E25(1,3) +U+9DD8(0);U+9D92(3);U+9D92(3) +U+9DD9(0);U+9E37(1,3);U+9E37(1,3) +U+9DDA(0);U+9E68(1,3);U+9E68(1,3) +U+9DDB(0);U+9DDB(0); +U+9DDC(0);U+9DDC(0); +U+9DDD(0);U+9DDD(0); +U+9DDE(0);U+9DDE(3); +U+9DDF(0);U+9DDF(0); +U+9DE0(0);U+9DE0(0); +U+9DE1(0);U+9DE1(0); +U+9DE2(0);U+9DE2(0); +U+9DE3(0);U+9DE3(0); +U+9DE4(0);U+9DE4(0); +U+9DE5(0);U+9E36(1,3);U+9E36(1,3) +U+9DE6(0);U+9E6A(1,3);U+9E6A(1,3) +U+9DE7(0);U+9DE7(0); +U+9DE8(0);U+9DE8(0); +U+9DE9(0);U+9DE9(0); +U+9DEB(0);U+9E54(4);U+9E54(4) +U+9DEC(0);U+9DEC(0); +U+9DED(0);U+9DED(0); +U+9DEE(0);U+9DEE(0); +U+9DEF(0);U+9E69(1,3);U+9E69(1,3) +U+9DF0(0);U+71D5(2,3);U+71D5(2,3),U+89FE(2,3) +U+9DF1(0);U+9DF1(3); +U+9DF2(0);U+9E6B(1,3);U+9E6B(1,3) +U+9DF3(0);U+9E47(1,3);U+9E47(1,3),U+9DF4(1,3) +U+9DF4(0);U+9E47(1);U+9E47(1),U+9DF3(0,1,3) +U+9DF5(0);U+9DF5(0); +U+9DF6(0);U+9DF6(0); +U+9DF7(0);U+9DF7(3); +U+9DF8(0);U+9E6C(1,3);U+9E6C(1,3) +U+9DF9(0);U+9E70(1,3);U+9E70(1,3) +U+9DFA(0);U+9E6D(1,3);U+9E6D(1,3) +U+9DFB(0);U+9DFB(3); + +U+9DFD(0);U+9E34(4);U+9E34(4) +U+9DFE(0);U+9DFE(0); +U+9DFF(0);U+4D19(3);U+4D19(3),U+9E0A(1,3) +U+9E00(0);U+9E00(0); +U+9E01(0);U+9E01(0); +U+9E02(0);U+9E02(0); +U+9E03(0);U+9E03(0); +U+9E04(0);U+9E04(0); +U+9E05(0);U+9E05(0); +U+9E06(0);U+9E06(0); +U+9E07(0);U+9E6F(1,3);U+9E6F(1,3) +U+9E08(0);U+9E08(0); +U+9E09(0);U+9E09(3); +U+9E0A(0);U+4D19(1,3);U+4D19(1,3),U+9DFF(1,3) +U+9E0B(0);U+9E0B(0); +U+9E0C(0);U+9E71(4);U+9E71(4) +U+9E0D(0);U+9E0D(3); +U+9E0F(0);U+9E72(4);U+9E72(4) +U+9E10(0);U+9E10(0); +U+9E11(0);U+9E11(0); +U+9E12(0);U+9E12(0); +U+9E13(0);U+9E13(3); +U+9E14(0);U+9E14(0); +U+9E15(0);U+9E2C(1,3);U+9E2C(1,3) +U+9E17(0);U+9E17(0); +U+9E18(0);U+9E74(4);U+9E74(4) +U+9E19(0);U+9E19(0); +U+9E1A(0);U+9E66(1,3);U+9E66(1,3) +U+9E1B(0);U+9E73(1,3);U+9E73(1,3) +U+9E1D(0);U+9E42(1,3);U+9E42(1,3) +U+9E1E(0);U+9E3E(1,3);U+9D49(4),U+9E3E(1,3) +U+9E1F(0);U+9E1F(1,3);U+9CE5(1,3) +U+9E20(0);U+9E20(1,3);U+9CE9(1,3) +U+9E21(0);U+9E21(1,3);U+96DE(4),U+9CEE(4),U+9DC4(1,3) +U+9E22(0);U+9E22(1,3);U+9CF6(1,3) +U+9E23(0);U+9E23(1,3);U+9CF4(1,3) +U+9E24(0);U+9E24(4);U+9CF2(4) +U+9E25(0);U+9E25(1,3);U+9DD7(1,3) +U+9E26(0);U+9E26(1,3);U+9D09(1,3),U+9D76(4) +U+9E27(0);U+9E27(1,3);U+9DAC(1,3) +U+9E28(0);U+9E28(1,3);U+9CF5(3),U+9D07(1,3) +U+9E29(0);U+9E29(1,3);U+9D06(1,3) +U+9E2A(0);U+9E2A(1,3);U+9D23(1,3) +U+9E2B(0);U+9E2B(1,3);U+9D87(1,3) +U+9E2C(0);U+9E2C(1,3);U+9E15(1,3) +U+9E2D(0);U+9E2D(1,3);U+9D28(1,3) +U+9E2E(0);U+9E2E(1,3);U+9D1E(1,3) +U+9E2F(0);U+9E2F(1,3);U+9D26(1,3) +U+9E30(0);U+9E30(1,3);U+9D12(1,3) +U+9E31(0);U+9E31(1,3);U+9D1F(1,3) +U+9E32(0);U+9E32(1,3);U+9D1D(1,3) +U+9E33(0);U+9E33(1,3);U+9D1B(1,3) +U+9E34(0);U+9E34(4);U+9DFD(4) +U+9E35(0);U+9E35(1,3);U+9D15(1,3) +U+9E36(0);U+9E36(1,3);U+9DE5(1,3) +U+9E37(0);U+9E37(1,3);U+9DD9(1,3) +U+9E38(0);U+9E38(1,3);U+9D2F(1,3) +U+9E39(0);U+9E39(1,3);U+9D30(1,3) +U+9E3A(0);U+9E3A(1,3);U+9D42(1,3) +U+9E3B(0);U+9E3B(1,3);U+9D34(1,3) +U+9E3C(0);U+9E3C(1,3);U+9D43(1,3) +U+9E3D(0);U+9E3D(1,3);U+9D3F(1,3) +U+9E3E(0);U+9E3E(1,3);U+9D49(4),U+9E1E(1,3) + +U+9E3F(0);U+9E3F(1,3);U+9D3B(1,3) +U+9E40(0);U+9E40(4);U+9D50(4) +U+9E41(0);U+9E41(1,3);U+9D53(1,3) +U+9E42(0);U+9E42(1,3);U+9E1D(1,3) +U+9E43(0);U+9E43(1,3);U+9D51(1,3) +U+9E44(0);U+9E44(1,3);U+9D60(1,3) +U+9E45(0);U+9E45(1,3);U+9D5D(1,3),U+9D5E(4) +U+9E46(0);U+9E46(1,3);U+9D52(1,3) +U+9E47(0);U+9E47(1,3);U+9DF4(1),U+9DF3(1,3) +U+9E48(0);U+9E48(1,3);U+9D5C(1,3) +U+9E49(0);U+9E49(1,3);U+9D61(1,3) +U+9E4A(0);U+9E4A(1,3);U+9D72(1,3) +U+9E4B(0);U+9E4B(1,3);U+9D93(1,3) +U+9E4C(0);U+9E4C(1,3);U+9D6A(1,3) +U+9E4D(0);U+9E4D(4);U+9D7E(4),U+9DA4(4) +U+9E4E(0);U+9E4E(4);U+9D6F(4) +U+9E4F(0);U+9E4F(1,3);U+9D6C(1,3) +U+9E50(0);U+9E50(1,3);U+9D6E(1,3) +U+9E51(0);U+9E51(1,3);U+9D89(1,3) +U+9E52(0);U+9E52(1,3);U+9D8A(1,3) +U+9E53(0);U+9E53(4);U+9D77(4) +U+9E54(0);U+9E54(4);U+9DEB(4) +U+9E55(0);U+9E55(1,3);U+9D98(1,3) +U+9E56(0);U+9E56(1,3);U+9DA1(1,3) +U+9E57(0);U+9E57(1,3);U+9D9A(1,3) +U+9E58(0);U+9E58(1,3);U+9DBB(1,3) +U+9E59(0);U+9E59(1,3);U+9D96(1,3) +U+9E5A(0);U+9E5A(1,3);U+9DBF(2,3) +U+9E5B(0);U+9E5B(1,3);U+9DA5(1,3) +U+9E5C(0);U+9E5C(1,3);U+9DA9(1,3) +U+9E5D(0);U+9E5D(4);U+9DCA(4) +U+9E5E(0);U+9E5E(1);U+9DC2(1) +U+9E5F(0);U+9E5F(4);U+9DB2(4) +U+9E60(0);U+9E60(4);U+9DB9(4) +U+9E61(0);U+9E61(1,3);U+9DBA(1,3) +U+9E62(0);U+9E62(4);U+9DC1(4) +U+9E63(0);U+9E63(1,3);U+9DBC(1,3) +U+9E64(0);U+9E64(1,3);U+9DB4(1,3) +U+9E65(0);U+9E65(1,3);U+9DD6(1,3) +U+9E66(0);U+9E66(1,3);U+9E1A(1,3) +U+9E67(0);U+9E67(1,3);U+9DD3(1,3) +U+9E68(0);U+9E68(1,3);U+9DDA(1,3) +U+9E69(0);U+9E69(1,3);U+9DEF(1,3) +U+9E6A(0);U+9E6A(1,3);U+9DE6(1,3) +U+9E6B(0);U+9E6B(1,3);U+9DF2(1,3) +U+9E6C(0);U+9E6C(1,3);U+9DF8(1,3) +U+9E6D(0);U+9E6D(1,3);U+9DFA(1,3) +U+9E6E(0);U+9E6E(6); +U+9E6F(0);U+9E6F(1,3);U+9E07(1,3) +U+9E70(0);U+9E70(1,3);U+9DF9(1,3) +U+9E71(0);U+9E71(4);U+9E0C(4) +U+9E72(0);U+9E72(4);U+9E0F(4) +U+9E73(0);U+9E73(1,3);U+9E1B(1,3) +U+9E74(0);U+9E74(4);U+9E18(4) +U+9E75(0);U+5364(1,3);U+5364(1,3),U+6EF7(4) +U+9E76(0);U+9E76(0); +U+9E77(0);U+9E77(0); +U+9E79(0);U+54B8(1,3);U+54B8(1,3) +U+9E7A(0);U+9E7E(1,3);U+9E7E(1,3) +U+9E7C(0);U+7877(1,3);U+7877(1,3),U+78B1(3,4),U+7906(1,3,4),U+96AA(1,3,4),U+9669(1,3,4) + +U+9E7D(0);U+76D0(1,3);U+5869(3),U+76D0(1,3) +U+9E7E(0);U+9E7E(1,3);U+9E7A(1,3) + +U+9E7F(0);U+9E7F(5); +U+9E80(0);U+9E80(0); +U+9E81(0);U+7C97(4);U+7C97(4),U+850D(3,4),U+89D5(2,3,4),U+9E84(3,4),U+9E86(3,4),U+9EA4(2,3,4) + +U+9E82(0);U+9E82(5); +U+9E83(0);U+9E83(0); +U+9E84(0);U+7C97(3);U+7C97(3),U+850D(3),U+89D5(2,3),U+9E81(3,4),U+9E86(3),U+9EA4(2,3) + +U+9E85(0);U+9E85(3); +U+9E86(0);U+7C97(3);U+7C97(3),U+850D(3),U+89D5(2,3),U+9E81(3,4),U+9E84(3),U+9EA4(2,3) + +U+9E87(0);U+9E87(5); +U+9E88(0);U+9E88(5); +U+9E89(0);U+9E89(0); +U+9E8A(0);U+9E8B(3);U+9E8B(3) +U+9E8B(0);U+9E8B(5);U+9E8A(3) +U+9E8C(0);U+9E8C(0); +U+9E8D(0);U+9E8D(0); +U+9E8E(0);U+9E8E(0); +U+9E91(0);U+9E91(0); +U+9E92(0);U+9E92(5); +U+9E93(0);U+9E93(5); +U+9E94(0);U+9E94(0); +U+9E96(0);U+9E96(4);U+9EA0(4) +U+9E97(0);U+4E3D(1,3);U+4E3D(1,3) +U+9E99(0);U+9E99(0); +U+9E9A(0);U+9E9A(0); +U+9E9B(0);U+9E9B(3); +U+9E9C(0);U+9E9C(0); +U+9E9D(0);U+9E9D(5); +U+9E9F(0);U+9E9F(5); +U+9EA0(0);U+9E96(4);U+9E96(4) +U+9EA1(0);U+9EA1(0); +U+9EA3(0);U+9EA3(0); +U+9EA4(0);U+7C97(2,3);U+7C97(2,3),U+850D(2,3),U+89D5(2,3),U+9E81(2,3,4),U+9E84(2,3),U+9E86(2,3) +U+9EA5(0);U+9EA6(1,3);U+9EA6(1,3) +U+9EA6(0);U+9EA6(1,3);U+9EA5(1,3) +U+9EA7(0);U+9EA7(3); +U+9EA8(0);U+9EA8(0); +U+9EA9(0);U+9EB8(1,3);U+9EB8(1,3) +U+9EAA(0);U+9762(4);U+9762(4),U+9EB5(2,3) +U+9EAD(0);U+9EAD(0); +U+9EAE(0);U+9EAE(0); +U+9EAF(0);U+66F2(1,3);U+66F2(1,3),U+9EB4(1,3,4) +U+9EB0(0);U+9EB0(3); +U+9EB2(0);U+9EB2(0); +U+9EB3(0);U+9EB3(0); +U+9EB4(0);U+66F2(4);U+66F2(4),U+9EAF(1,3,4) +U+9EB5(0);U+9762(1,3);U+9762(1,3),U+9EAA(2,3) +U+9EB6(0);U+9EB6(0); +U+9EB7(0);U+9EB7(0); +U+9EB8(0);U+9EB8(1,3);U+9EA9(1,3) +U+9EBB(0);U+9EBB(5);U+75F2(3),U+75F3(4),U+8534(2,3),U+6DCB(2,3,4,5) +U+9EBC(0);U+4E48(4);U+4E48(4),U+5E85(8,9),U+9EBD(3),U+5E7A(3,4) +U+9EBD(0);U+9EBD(0),U+4E48(1,3);U+4E48(1,3),U+5E85(4),U+9EBC(3),U+5E7A(1,3) +U+9EBE(0);U+9EBE(5); +U+9EBF(0);U+9EBF(0); +U+9EC0(0);U+9EC0(3); +U+9EC1(0);U+9EC1(0); +U+9EC2(0);U+9EC2(0); +U+9EC3(0);U+9EC4(4);U+9EC4(4) +U+9EC4(0);U+9EC4(5);U+9EC3(4) + +U+9EC5(0);U+9EC5(0); +U+9EC6(0);U+9EC6(0); +U+9EC7(0);U+9EC7(0); +U+9EC8(0);U+9EC8(0); +U+9EC9(0);U+9EC9(1,3);U+9ECC(1,3) +U+9ECA(0);U+9ECA(0); +U+9ECB(0);U+9ECB(0); +U+9ECC(0);U+9EC9(1,3);U+9EC9(1,3) +U+9ECD(0);U+9ECD(5); +U+9ECE(0);U+9ECE(5);U+83DE(3) +U+9ECF(0);U+9ECF(5); +U+9ED0(0);U+9ED0(3); +U+9ED1(0);U+9ED1(5);U+9ED2(4) +U+9ED2(0);U+9ED1(4);U+9ED1(4) +U+9ED3(0);U+9ED3(3); +U+9ED4(0);U+9ED4(5);U+8EE1(3) +U+9ED5(0);U+9ED5(0); +U+9ED6(0);U+9ED6(0); +U+9ED7(0);U+9ED7(0); +U+9ED8(0);U+9ED8(5);U+9ED9(4) +U+9ED9(0);U+9ED8(4);U+9ED8(4) +U+9EDA(0);U+9EDA(0); +U+9EDB(0);U+9EDB(5); +U+9EDC(0);U+9EDC(5); +U+9EDD(0);U+9EDD(5); +U+9EDE(0);U+70B9(1,3);U+594C(4),U+70B9(1,3) +U+9EDF(0);U+9EDF(5); +U+9EE0(0);U+9EE0(5); +U+9EE1(0);U+9EE1(1,3);U+9EF6(1,3) +U+9EE2(0);U+9EE2(5); +U+9EE3(0);U+9EE3(0); +U+9EE4(0);U+9EE4(0); +U+9EE5(0);U+9EE5(5); +U+9EE6(0);U+9EE6(0); +U+9EE7(0);U+9EE7(5); +U+9EE8(0);U+515A(1,3);U+515A(1,3) +U+9EE9(0);U+9EE9(1,3);U+9EF7(1,3) +U+9EEA(0);U+9EEA(4);U+9EF2(4) +U+9EEB(0);U+9EEB(0); +U+9EED(0);U+9EED(0); +U+9EEE(0);U+9EEE(0); +U+9EEF(0);U+9EEF(5); +U+9EF0(0);U+9EF0(3); +U+9EF2(0);U+9EEA(4);U+9EEA(4) +U+9EF3(0);U+9EF3(0); +U+9EF4(0);U+9709(1,3);U+9709(1,3) +U+9EF5(0);U+9EF5(0); +U+9EF6(0);U+9EE1(1,3);U+9EE1(1,3) +U+9EF7(0);U+9EE9(1,3);U+9EE9(1,3) +U+9EF8(0);U+9EF8(0); +U+9EF9(0);U+9EF9(5); +U+9EFA(0);U+9EFA(0); +U+9EFB(0);U+9EFB(5); +U+9EFC(0);U+9EFC(5); +U+9EFD(0);U+9EFE(1,3);U+9EFE(1,3) +U+9EFE(0);U+9EFE(1,3);U+9EFD(1,3) +U+9EFF(0);U+9F0B(1,3);U+9F0B(1,3) +U+9F00(0);U+9F00(0); +U+9F01(0);U+9F01(0); +U+9F02(0);U+9F0C(4);U+9F0C(4) +U+9F04(0);U+86DB(3);U+86DB(3) +U+9F05(0);U+8718(3);U+8718(3) +U+9F06(0);U+9F06(0); + +U+9F07(0);U+9CCC(4);U+9CCC(4),U+9C32(0,1,3,4) +U+9F08(0);U+9F08(4);U+9C49(3,4),U+9CD6(1,3,4),U+9F9E(3,4) +U+9F09(0);U+9F0D(1,3);U+9F0D(1,3) +U+9F0A(0);U+9F0A(0); +U+9F0B(0);U+9F0B(1,3);U+9EFF(1,3) +U+9F0C(0);U+9F0C(0);U+9F02(4) +U+9F0D(0);U+9F0D(1,3);U+9F09(1,3) +U+9F0E(0);U+9F0E(5); +U+9F0F(0);U+9F0F(0); +U+9F10(0);U+9F10(5); +U+9F12(0);U+9F12(3); +U+9F13(0);U+9F13(5);U+76B7(2,3),U+76BC(7) +U+9F15(0);U+51AC(1,3);U+51AC(1,3) +U+9F16(0);U+9F16(0); +U+9F17(0);U+9F17(5);U+9780(3) +U+9F18(0);U+9F18(3); +U+9F19(0);U+9F19(5); +U+9F1A(0);U+9F1A(0); +U+9F1B(0);U+9F1B(3); +U+9F1C(0);U+9F1C(0); +U+9F1D(0);U+9F1D(0); +U+9F1E(0);U+9F1E(4); +U+9F1F(0);U+9F1F(0); +U+9F20(0);U+9F20(5); +U+9F22(0);U+9F22(5); +U+9F23(0);U+9F23(0); +U+9F24(0);U+9F24(0); +U+9F25(0);U+9F25(0); +U+9F27(0);U+9F27(0); +U+9F28(0);U+9F28(0); +U+9F29(0);U+9F29(0); +U+9F2A(0);U+9F2A(3); +U+9F2B(0);U+9F2B(0); +U+9F2C(0);U+9F2C(5); +U+9F2D(0);U+9F2D(0); +U+9F2E(0);U+9F2E(0); +U+9F2F(0);U+9F2F(5); +U+9F30(0);U+9F33(4);U+9F33(4) +U+9F31(0);U+9F31(0); +U+9F32(0);U+9F32(0); +U+9F33(0);U+9F33(0);U+9F30(4) +U+9F34(0);U+9F39(2,3);U+9F39(2,3) +U+9F35(0);U+9F35(0); +U+9F36(0);U+9F36(0); +U+9F37(0);U+9F37(5); +U+9F38(0);U+9F38(0); +U+9F39(0);U+9F39(5);U+9F34(2,3) +U+9F3A(0);U+9F3A(0); +U+9F3B(0);U+9F3B(5); +U+9F3C(0);U+9F3C(0); +U+9F3D(0);U+9F3D(5); +U+9F3E(0);U+9F3E(5);U+54FB(3) +U+9F3F(0);U+9F3F(0);U+9F40(4) +U+9F40(0);U+9F3F(4);U+9F3F(4) +U+9F41(0);U+9F41(0); +U+9F42(0);U+9F42(3); +U+9F43(0);U+981E(3);U+981E(3) +U+9F44(0);U+9F44(5); +U+9F46(0);U+9F46(0); +U+9F47(0);U+9F47(3); +U+9F48(0);U+9F48(0); +U+9F49(0);U+9F49(3); +U+9F4A(0);U+9F50(1,3);U+4E9D(3),U+6589(3),U+9F50(1,3) + +U+9F4B(0);U+658B(1,3);U+658B(1,3),U+658E(4) +U+9F4C(0);U+9F4C(0); +U+9F4D(0);U+9F4D(3); +U+9F4E(0);U+8D4D(3);U+8D4D(3),U+8CEB(0,1,3) +U+9F4F(0);U+9F51(1);U+97F2(3),U+9F51(1),U+8640(0,1,3) +U+9F50(0);U+9F50(1,3);U+4E9D(3,4),U+6589(3),U+9F4A(1,3) +U+9F51(0);U+9F51(1);U+8640(3),U+97F2(3),U+9F4F(1) +U+9F52(0);U+9F7F(1,3);U+6B6F(3),U+9F7F(1,3) +U+9F54(0);U+9F80(1,3);U+9F80(1,3) +U+9F55(0);U+9F81(4);U+9F81(4) +U+9F56(0);U+9F56(0); +U+9F57(0);U+9F82(4);U+9F82(4) +U+9F58(0);U+9F58(3); +U+9F59(0);U+9F85(1,3);U+9F85(1,3) +U+9F5A(0);U+9F5A(0); +U+9F5B(0);U+9F5B(3);U+9F65(3) +U+9F5C(0);U+9F87(1,3);U+9F87(1,3) +U+9F5D(0);U+9F5D(3); +U+9F5E(0);U+9F5E(3); +U+9F5F(0);U+9F83(1,3);U+9F83(1,3) +U+9F60(0);U+9F86(1,3);U+9F86(1,3) +U+9F61(0);U+9F84(1,3);U+9F84(1,3) +U+9F63(0);U+51FA(1,3);U+51FA(1,3),U+5C80(3) +U+9F64(0);U+9F64(0); +U+9F65(0);U+9F5B(3);U+9F5B(3) +U+9F66(0);U+9F88(1,3);U+9F88(1,3) +U+9F67(0);U+556E(4);U+556E(4),U+5699(2,3),U+56D3(3) +U+9F68(0);U+9F68(0); +U+9F69(0);U+54AC(2,3);U+54AC(2,3) +U+9F6A(0);U+9F8A(1,3);U+9F8A(1,3),U+8E00(0,1,3) +U+9F6B(0);U+9F73(3);U+9F73(3) +U+9F6C(0);U+9F89(1,3);U+9F89(1,3) +U+9F6E(0);U+9F6E(0); +U+9F6F(0);U+9F6F(3); +U+9F70(0);U+9F70(3); +U+9F71(0);U+9F71(0); +U+9F72(0);U+9F8B(1,3);U+9F8B(1,3) +U+9F73(0);U+9F73(3);U+9F6B(3) +U+9F74(0);U+9F74(3); +U+9F75(0);U+9F75(0); +U+9F76(0);U+816D(2,3);U+816D(2,3) +U+9F77(0);U+9F8C(1,3);U+9F8C(1,3) +U+9F78(0);U+9F78(0); +U+9F79(0);U+9F79(0); +U+9F7A(0);U+9F7A(0); +U+9F7B(0);U+9F7B(0); +U+9F7C(0);U+9F7C(4); +U+9F7D(0);U+9F7D(0); +U+9F7E(0);U+9F7E(0); +U+9F7F(0);U+9F7F(1,3);U+6B6F(3),U+9F52(1,3) +U+9F80(0);U+9F80(1,3);U+9F54(1,3) +U+9F81(0);U+9F81(4);U+9F55(4) +U+9F82(0);U+9F82(4);U+9F57(4) +U+9F83(0);U+9F83(1,3);U+9F5F(1,3) +U+9F84(0);U+9F84(1,3);U+9F61(1,3) +U+9F85(0);U+9F85(1,3);U+9F59(1,3) +U+9F86(0);U+9F86(1,3);U+9F60(1,3) +U+9F87(0);U+9F87(1,3);U+9F5C(1,3) +U+9F88(0);U+9F88(1,3);U+9F66(1,3) +U+9F89(0);U+9F89(1,3);U+9F6C(1,3) +U+9F8A(0);U+9F8A(1,3);U+8E00(3),U+9F6A(1,3) +U+9F8B(0);U+9F8B(1,3);U+9F72(1,3) +U+9F8C(0);U+9F8C(1,3);U+9F77(1,3) + +U+9F8D(0);U+9F99(1,3);U+7ADC(3),U+9F99(1,3),U+9F92(3) +U+9F8E(0);U+5E9E(1,3,4);U+5390(4),U+5E9E(1,3,4),U+9F90(4) +U+9F8F(0);U+9F8F(0); +U+9F90(0);U+5E9E(1,3);U+5390(8,9),U+5E9E(1,3),U+9F8E(4) +U+9F91(0);U+4DAE(1,3);U+4DAE(1,3) +U+9F92(0);U+9F99(3);U+9F99(3),U+7ADC(0,3),U+9F8D(3) +U+9F93(0);U+9F93(0); +U+9F94(0);U+9F9A(1,3);U+9F9A(1,3) +U+9F95(0);U+9F9B(1,3);U+9F9B(1,3) +U+9F96(0);U+9F96(4);U+9F98(4) +U+9F97(0);U+9F97(3); +U+9F98(0);U+9F96(4);U+9F96(4) +U+9F99(0);U+9F99(1,3);U+9F92(3),U+7ADC(7),U+9F8D(1,3) +U+9F9A(0);U+9F9A(1,3);U+9F94(1,3) +U+9F9B(0);U+9F9B(1,3);U+9F95(1,3) +U+9F9C(0);U+9F9F(1);U+4E80(4),U+9F9F(1) +U+9F9D(0);U+79CB(7);U+79CB(7),U+7A50(4),U+97A6(1,3,4,7) +U+9F9E(0);U+9CD6(3);U+9C49(3),U+9CD6(3),U+9F08(3,4) +U+9F9F(0);U+9F9F(1);U+4E80(4),U+9F9C(1) +U+9FA0(0);U+9FA0(5); +U+9FA2(0);U+548C(2,3);U+548C(2,3),U+924C(2,3) +U+9FA4(0);U+9FA4(0); +U+9FA5(0);U+9FA5(0); diff --git a/java/com/google/domain/registry/idn/Cyrillic-IDN.txt b/java/com/google/domain/registry/idn/Cyrillic-IDN.txt new file mode 100644 index 000000000..6b9690154 --- /dev/null +++ b/java/com/google/domain/registry/idn/Cyrillic-IDN.txt @@ -0,0 +1,57 @@ +# Registry: Charleston Road Registry Inc. +# Script: Cyrillic +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Cyrillic script. +# The hyphen (U+002D), as well as the digits zero to nine (U+0030 .. U+0039), for +# purposes of Internationalised Domain Name registration are considered to form +# part of the Cyrillic script. + +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0430 ## \ CYRILLIC SMALL LETTER A +U+0431 ## ^ CYRILLIC SMALL LETTER BE +U+0432 ## _ CYRILLIC SMALL LETTER VE +U+0433 ## ` CYRILLIC SMALL LETTER GHE +U+0434 ## a CYRILLIC SMALL LETTER DE +U+0435 ## b CYRILLIC SMALL LETTER IE +U+0436 ## c CYRILLIC SMALL LETTER ZHE +U+0437 ## f CYRILLIC SMALL LETTER ZE +U+0438 ## h CYRILLIC SMALL LETTER I +U+0439 ## i CYRILLIC SMALL LETTER SHORT I +U+043A ## j CYRILLIC SMALL LETTER KA +U+043B ## l CYRILLIC SMALL LETTER EL +U+043C ## m CYRILLIC SMALL LETTER EM +U+043D ## n CYRILLIC SMALL LETTER EN +U+043E ## o CYRILLIC SMALL LETTER O +U+043F ## q CYRILLIC SMALL LETTER PE +U+0440 ## r CYRILLIC SMALL LETTER ER +U+0441 ## s CYRILLIC SMALL LETTER ES +U+0442 ## t CYRILLIC SMALL LETTER TE +U+0443 ## u CYRILLIC SMALL LETTER U +U+0444 ## v CYRILLIC SMALL LETTER EF +U+0445 ## w CYRILLIC SMALL LETTER HA +U+0446 ## x CYRILLIC SMALL LETTER TSE +U+0447 ## y CYRILLIC SMALL LETTER CHE +U+0448 ## z CYRILLIC SMALL LETTER SHA +U+0449 ## { CYRILLIC SMALL LETTER SHCHA +U+044A ## | CYRILLIC SMALL LETTER HARD SIGN +U+044B ## } CYRILLIC SMALL LETTER YERU +U+044C ## ~ CYRILLIC SMALL LETTER SOFT SIGN +U+044D ## ^? CYRILLIC SMALL LETTER E + +U+044E ## * CYRILLIC SMALL LETTER YU +U+044F ## 5 CYRILLIC SMALL LETTER YA diff --git a/java/com/google/domain/registry/idn/Devanagari-IDN.txt b/java/com/google/domain/registry/idn/Devanagari-IDN.txt new file mode 100644 index 000000000..99d84c3ff --- /dev/null +++ b/java/com/google/domain/registry/idn/Devanagari-IDN.txt @@ -0,0 +1,152 @@ +# Registry: Charleston Road Registry Inc. +# Script: Devanagari +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Devanagari script. + +# Common codepoints (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0900 # DEVANAGARI SIGN INVERTED CANDRABINDU +U+0901 # DEVANAGARI SIGN CANDRABINDU +U+0902 # DEVANAGARI SIGN ANUSVARA +U+0903 # DEVANAGARI SIGN VISARGA +U+0904 # DEVANAGARI LETTER SHORT A +U+0905 # DEVANAGARI LETTER A +U+0906 # DEVANAGARI LETTER AA +U+0907 # DEVANAGARI LETTER I +U+0908 # DEVANAGARI LETTER II +U+0909 # DEVANAGARI LETTER U +U+090A # DEVANAGARI LETTER UU +U+090B # DEVANAGARI LETTER VOCALIC R +U+090C # DEVANAGARI LETTER VOCALIC L +U+090D # DEVANAGARI LETTER CANDRA E +U+090E # DEVANAGARI LETTER SHORT E +U+090F # DEVANAGARI LETTER E +U+0910 # DEVANAGARI LETTER AI +U+0911 # DEVANAGARI LETTER CANDRA O +U+0912 # DEVANAGARI LETTER SHORT O +U+0913 # DEVANAGARI LETTER O +U+0914 # DEVANAGARI LETTER AU +U+0915 # DEVANAGARI LETTER KA +U+0916 # DEVANAGARI LETTER KHA +U+0917 # DEVANAGARI LETTER GA +U+0918 # DEVANAGARI LETTER GHA +U+0919 # DEVANAGARI LETTER NGA +U+091A # DEVANAGARI LETTER CA +U+091B # DEVANAGARI LETTER CHA +U+091C # DEVANAGARI LETTER JA +U+091D # DEVANAGARI LETTER JHA +U+091E # DEVANAGARI LETTER NYA +U+091F # DEVANAGARI LETTER TTA +U+0920 # DEVANAGARI LETTER TTHA +U+0921 # DEVANAGARI LETTER DDA +U+0922 # DEVANAGARI LETTER DDHA +U+0923 # DEVANAGARI LETTER NNA +U+0924 # DEVANAGARI LETTER TA +U+0925 # DEVANAGARI LETTER THA +U+0926 # DEVANAGARI LETTER DA +U+0927 # DEVANAGARI LETTER DHA +U+0928 # DEVANAGARI LETTER NA +U+0929 # DEVANAGARI LETTER NNNA +U+092A # DEVANAGARI LETTER PA +U+092B # DEVANAGARI LETTER PHA +U+092C # DEVANAGARI LETTER BA +U+092D # DEVANAGARI LETTER BHA +U+092E # DEVANAGARI LETTER MA +U+092F # DEVANAGARI LETTER YA +U+0930 # DEVANAGARI LETTER RA +U+0931 # DEVANAGARI LETTER RRA +U+0932 # DEVANAGARI LETTER LA +U+0933 # DEVANAGARI LETTER LLA +U+0934 # DEVANAGARI LETTER LLLA +U+0935 # DEVANAGARI LETTER VA +U+0936 # DEVANAGARI LETTER SHA +U+0937 # DEVANAGARI LETTER SSA +U+0938 # DEVANAGARI LETTER SA +U+0939 # DEVANAGARI LETTER HA +U+093C # DEVANAGARI SIGN NUKTA +U+093D # DEVANAGARI SIGN AVAGRAHA +U+093E # DEVANAGARI VOWEL SIGN AA +U+093F # DEVANAGARI VOWEL SIGN I +U+0940 # DEVANAGARI VOWEL SIGN II +U+0941 # DEVANAGARI VOWEL SIGN U +U+0942 # DEVANAGARI VOWEL SIGN UU +U+0943 # DEVANAGARI VOWEL SIGN VOCALIC R +U+0944 # DEVANAGARI VOWEL SIGN VOCALIC RR +U+0945 # DEVANAGARI VOWEL SIGN CANDRA E +U+0946 # DEVANAGARI VOWEL SIGN SHORT E +U+0947 # DEVANAGARI VOWEL SIGN E +U+0948 # DEVANAGARI VOWEL SIGN AI +U+0949 # DEVANAGARI VOWEL SIGN CANDRA O +U+094A # DEVANAGARI VOWEL SIGN SHORT O +U+094B # DEVANAGARI VOWEL SIGN O +U+094C # DEVANAGARI VOWEL SIGN AU +U+094D # DEVANAGARI SIGN VIRAMA +U+094E # DEVANAGARI VOWEL SIGN PRISHTHAMATRA E +U+0950 # DEVANAGARI OM +U+0953 # DEVANAGARI GRAVE ACCENT +U+0954 # DEVANAGARI ACUTE ACCENT +U+0955 # DEVANAGARI VOWEL SIGN CANDRA LONG E +U+0960 # DEVANAGARI LETTER VOCALIC RR +U+0961 # DEVANAGARI LETTER VOCALIC LL +U+0962 # DEVANAGARI VOWEL SIGN VOCALIC L +U+0963 # DEVANAGARI VOWEL SIGN VOCALIC LL +U+0966 # DEVANAGARI DIGIT ZERO +U+0967 # DEVANAGARI DIGIT ONE +U+0968 # DEVANAGARI DIGIT TWO +U+0969 # DEVANAGARI DIGIT THREE +U+096A # DEVANAGARI DIGIT FOUR +U+096B # DEVANAGARI DIGIT FIVE +U+096C # DEVANAGARI DIGIT SIX +U+096D # DEVANAGARI DIGIT SEVEN +U+096E # DEVANAGARI DIGIT EIGHT +U+096F # DEVANAGARI DIGIT NINE +U+0971 # DEVANAGARI SIGN HIGH SPACING DOT +U+0972 # DEVANAGARI LETTER CANDRA A +U+0979 # DEVANAGARI LETTER ZHA +U+097A # DEVANAGARI LETTER HEAVY YA +U+097B # DEVANAGARI LETTER GGA +U+097C # DEVANAGARI LETTER JJA +U+097D # DEVANAGARI LETTER GLOTTAL STOP +U+097E # DEVANAGARI LETTER DDDA +U+097F # DEVANAGARI LETTER BBA +U+A8E0 # COMBINING DEVANAGARI DIGIT ZERO +U+A8E1 # COMBINING DEVANAGARI DIGIT ONE +U+A8E2 # COMBINING DEVANAGARI DIGIT TWO +U+A8E3 # COMBINING DEVANAGARI DIGIT THREE +U+A8E4 # COMBINING DEVANAGARI DIGIT FOUR +U+A8E5 # COMBINING DEVANAGARI DIGIT FIVE +U+A8E6 # COMBINING DEVANAGARI DIGIT SIX +U+A8E7 # COMBINING DEVANAGARI DIGIT SEVEN +U+A8E8 # COMBINING DEVANAGARI DIGIT EIGHT +U+A8E9 # COMBINING DEVANAGARI DIGIT NINE +U+A8EA # COMBINING DEVANAGARI LETTER A +U+A8EB # COMBINING DEVANAGARI LETTER U +U+A8EC # COMBINING DEVANAGARI LETTER KA +U+A8ED # COMBINING DEVANAGARI LETTER NA +U+A8EE # COMBINING DEVANAGARI LETTER PA +U+A8EF # COMBINING DEVANAGARI LETTER RA +U+A8F0 # COMBINING DEVANAGARI LETTER VI +U+A8F1 # COMBINING DEVANAGARI SIGN AVAGRAHA +U+A8F2 # DEVANAGARI SIGN SPACING CANDRABINDU +U+A8F3 # DEVANAGARI SIGN CANDRABINDU VIRAMA +U+A8F4 # DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA +U+A8F5 # DEVANAGARI SIGN CANDRABINDU TWO +U+A8F6 # DEVANAGARI SIGN CANDRABINDU THREE +U+A8F7 # DEVANAGARI SIGN CANDRABINDU AVAGRAHA +U+A8FB # DEVANAGARI HEADSTROKE diff --git a/java/com/google/domain/registry/idn/Ethiopic-IDN.txt b/java/com/google/domain/registry/idn/Ethiopic-IDN.txt new file mode 100644 index 000000000..7bd85fea4 --- /dev/null +++ b/java/com/google/domain/registry/idn/Ethiopic-IDN.txt @@ -0,0 +1,480 @@ +# Registry: Charleston Road Registry Inc. +# Script: Ethiopic +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Ethiopic script. + +# Codepoints allowed from the Ethiopic script. +U+1200 # ETHIOPIC SYLLABLE HA +U+1201 # ETHIOPIC SYLLABLE HU +U+1202 # ETHIOPIC SYLLABLE HI +U+1203 # ETHIOPIC SYLLABLE HAA +U+1204 # ETHIOPIC SYLLABLE HEE +U+1205 # ETHIOPIC SYLLABLE HE +U+1206 # ETHIOPIC SYLLABLE HO +U+1207 # ETHIOPIC SYLLABLE HOA +U+1208 # ETHIOPIC SYLLABLE LA +U+1209 # ETHIOPIC SYLLABLE LU +U+120A # ETHIOPIC SYLLABLE LI +U+120B # ETHIOPIC SYLLABLE LAA +U+120C # ETHIOPIC SYLLABLE LEE +U+120D # ETHIOPIC SYLLABLE LE +U+120E # ETHIOPIC SYLLABLE LO +U+120F # ETHIOPIC SYLLABLE LWA +U+1210 # ETHIOPIC SYLLABLE HHA +U+1211 # ETHIOPIC SYLLABLE HHU +U+1212 # ETHIOPIC SYLLABLE HHI +U+1213 # ETHIOPIC SYLLABLE HHAA +U+1214 # ETHIOPIC SYLLABLE HHEE +U+1215 # ETHIOPIC SYLLABLE HHE +U+1216 # ETHIOPIC SYLLABLE HHO +U+1217 # ETHIOPIC SYLLABLE HHWA +U+1218 # ETHIOPIC SYLLABLE MA +U+1219 # ETHIOPIC SYLLABLE MU +U+121A # ETHIOPIC SYLLABLE MI +U+121B # ETHIOPIC SYLLABLE MAA +U+121C # ETHIOPIC SYLLABLE MEE +U+121D # ETHIOPIC SYLLABLE ME +U+121E # ETHIOPIC SYLLABLE MO +U+121F # ETHIOPIC SYLLABLE MWA +U+1220 # ETHIOPIC SYLLABLE SZA +U+1221 # ETHIOPIC SYLLABLE SZU +U+1222 # ETHIOPIC SYLLABLE SZI +U+1223 # ETHIOPIC SYLLABLE SZAA +U+1224 # ETHIOPIC SYLLABLE SZEE +U+1225 # ETHIOPIC SYLLABLE SZE +U+1226 # ETHIOPIC SYLLABLE SZO +U+1227 # ETHIOPIC SYLLABLE SZWA +U+1228 # ETHIOPIC SYLLABLE RA +U+1229 # ETHIOPIC SYLLABLE RU +U+122A # ETHIOPIC SYLLABLE RI +U+122B # ETHIOPIC SYLLABLE RAA +U+122C # ETHIOPIC SYLLABLE REE +U+122D # ETHIOPIC SYLLABLE RE +U+122E # ETHIOPIC SYLLABLE RO +U+122F # ETHIOPIC SYLLABLE RWA +U+1230 # ETHIOPIC SYLLABLE SA +U+1231 # ETHIOPIC SYLLABLE SU +U+1232 # ETHIOPIC SYLLABLE SI +U+1233 # ETHIOPIC SYLLABLE SAA +U+1234 # ETHIOPIC SYLLABLE SEE +U+1235 # ETHIOPIC SYLLABLE SE +U+1236 # ETHIOPIC SYLLABLE SO +U+1237 # ETHIOPIC SYLLABLE SWA +U+1238 # ETHIOPIC SYLLABLE SHA +U+1239 # ETHIOPIC SYLLABLE SHU +U+123A # ETHIOPIC SYLLABLE SHI +U+123B # ETHIOPIC SYLLABLE SHAA +U+123C # ETHIOPIC SYLLABLE SHEE +U+123D # ETHIOPIC SYLLABLE SHE +U+123E # ETHIOPIC SYLLABLE SHO +U+123F # ETHIOPIC SYLLABLE SHWA +U+1240 # ETHIOPIC SYLLABLE QA +U+1241 # ETHIOPIC SYLLABLE QU +U+1242 # ETHIOPIC SYLLABLE QI +U+1243 # ETHIOPIC SYLLABLE QAA +U+1244 # ETHIOPIC SYLLABLE QEE +U+1245 # ETHIOPIC SYLLABLE QE +U+1246 # ETHIOPIC SYLLABLE QO +U+1247 # ETHIOPIC SYLLABLE QOA +U+1248 # ETHIOPIC SYLLABLE QWA +U+124A # ETHIOPIC SYLLABLE QWI +U+124B # ETHIOPIC SYLLABLE QWAA +U+124C # ETHIOPIC SYLLABLE QWEE +U+124D # ETHIOPIC SYLLABLE QWE +U+1250 # ETHIOPIC SYLLABLE QHA +U+1251 # ETHIOPIC SYLLABLE QHU +U+1252 # ETHIOPIC SYLLABLE QHI +U+1253 # ETHIOPIC SYLLABLE QHAA +U+1254 # ETHIOPIC SYLLABLE QHEE +U+1255 # ETHIOPIC SYLLABLE QHE +U+1256 # ETHIOPIC SYLLABLE QHO +U+1258 # ETHIOPIC SYLLABLE QHWA +U+125A # ETHIOPIC SYLLABLE QHWI +U+125B # ETHIOPIC SYLLABLE QHWAA +U+125C # ETHIOPIC SYLLABLE QHWEE +U+125D # ETHIOPIC SYLLABLE QHWE +U+1260 # ETHIOPIC SYLLABLE BA +U+1261 # ETHIOPIC SYLLABLE BU +U+1262 # ETHIOPIC SYLLABLE BI +U+1263 # ETHIOPIC SYLLABLE BAA +U+1264 # ETHIOPIC SYLLABLE BEE +U+1265 # ETHIOPIC SYLLABLE BE +U+1266 # ETHIOPIC SYLLABLE BO +U+1267 # ETHIOPIC SYLLABLE BWA +U+1268 # ETHIOPIC SYLLABLE VA +U+1269 # ETHIOPIC SYLLABLE VU +U+126A # ETHIOPIC SYLLABLE VI +U+126B # ETHIOPIC SYLLABLE VAA +U+126C # ETHIOPIC SYLLABLE VEE +U+126D # ETHIOPIC SYLLABLE VE +U+126E # ETHIOPIC SYLLABLE VO +U+126F # ETHIOPIC SYLLABLE VWA +U+1270 # ETHIOPIC SYLLABLE TA +U+1271 # ETHIOPIC SYLLABLE TU +U+1272 # ETHIOPIC SYLLABLE TI +U+1273 # ETHIOPIC SYLLABLE TAA +U+1274 # ETHIOPIC SYLLABLE TEE +U+1275 # ETHIOPIC SYLLABLE TE +U+1276 # ETHIOPIC SYLLABLE TO +U+1277 # ETHIOPIC SYLLABLE TWA +U+1278 # ETHIOPIC SYLLABLE CA +U+1279 # ETHIOPIC SYLLABLE CU +U+127A # ETHIOPIC SYLLABLE CI +U+127B # ETHIOPIC SYLLABLE CAA +U+127C # ETHIOPIC SYLLABLE CEE +U+127D # ETHIOPIC SYLLABLE CE +U+127E # ETHIOPIC SYLLABLE CO +U+127F # ETHIOPIC SYLLABLE CWA +U+1280 # ETHIOPIC SYLLABLE XA +U+1281 # ETHIOPIC SYLLABLE XU +U+1282 # ETHIOPIC SYLLABLE XI +U+1283 # ETHIOPIC SYLLABLE XAA +U+1284 # ETHIOPIC SYLLABLE XEE +U+1285 # ETHIOPIC SYLLABLE XE +U+1286 # ETHIOPIC SYLLABLE XO +U+1287 # ETHIOPIC SYLLABLE XOA +U+1288 # ETHIOPIC SYLLABLE XWA +U+128A # ETHIOPIC SYLLABLE XWI +U+128B # ETHIOPIC SYLLABLE XWAA +U+128C # ETHIOPIC SYLLABLE XWEE +U+128D # ETHIOPIC SYLLABLE XWE +U+1290 # ETHIOPIC SYLLABLE NA +U+1291 # ETHIOPIC SYLLABLE NU +U+1292 # ETHIOPIC SYLLABLE NI +U+1293 # ETHIOPIC SYLLABLE NAA +U+1294 # ETHIOPIC SYLLABLE NEE +U+1295 # ETHIOPIC SYLLABLE NE +U+1296 # ETHIOPIC SYLLABLE NO +U+1297 # ETHIOPIC SYLLABLE NWA +U+1298 # ETHIOPIC SYLLABLE NYA +U+1299 # ETHIOPIC SYLLABLE NYU +U+129A # ETHIOPIC SYLLABLE NYI +U+129B # ETHIOPIC SYLLABLE NYAA +U+129C # ETHIOPIC SYLLABLE NYEE +U+129D # ETHIOPIC SYLLABLE NYE +U+129E # ETHIOPIC SYLLABLE NYO +U+129F # ETHIOPIC SYLLABLE NYWA +U+12A0 # ETHIOPIC SYLLABLE GLOTTAL A +U+12A1 # ETHIOPIC SYLLABLE GLOTTAL U +U+12A2 # ETHIOPIC SYLLABLE GLOTTAL I +U+12A3 # ETHIOPIC SYLLABLE GLOTTAL AA +U+12A4 # ETHIOPIC SYLLABLE GLOTTAL EE +U+12A5 # ETHIOPIC SYLLABLE GLOTTAL E +U+12A6 # ETHIOPIC SYLLABLE GLOTTAL O +U+12A7 # ETHIOPIC SYLLABLE GLOTTAL WA +U+12A8 # ETHIOPIC SYLLABLE KA +U+12A9 # ETHIOPIC SYLLABLE KU +U+12AA # ETHIOPIC SYLLABLE KI +U+12AB # ETHIOPIC SYLLABLE KAA +U+12AC # ETHIOPIC SYLLABLE KEE +U+12AD # ETHIOPIC SYLLABLE KE +U+12AE # ETHIOPIC SYLLABLE KO +U+12AF # ETHIOPIC SYLLABLE KOA +U+12B0 # ETHIOPIC SYLLABLE KWA +U+12B2 # ETHIOPIC SYLLABLE KWI +U+12B3 # ETHIOPIC SYLLABLE KWAA +U+12B4 # ETHIOPIC SYLLABLE KWEE +U+12B5 # ETHIOPIC SYLLABLE KWE +U+12B8 # ETHIOPIC SYLLABLE KXA +U+12B9 # ETHIOPIC SYLLABLE KXU +U+12BA # ETHIOPIC SYLLABLE KXI +U+12BB # ETHIOPIC SYLLABLE KXAA +U+12BC # ETHIOPIC SYLLABLE KXEE +U+12BD # ETHIOPIC SYLLABLE KXE +U+12BE # ETHIOPIC SYLLABLE KXO +U+12C0 # ETHIOPIC SYLLABLE KXWA +U+12C2 # ETHIOPIC SYLLABLE KXWI +U+12C3 # ETHIOPIC SYLLABLE KXWAA +U+12C4 # ETHIOPIC SYLLABLE KXWEE +U+12C5 # ETHIOPIC SYLLABLE KXWE +U+12C8 # ETHIOPIC SYLLABLE WA +U+12C9 # ETHIOPIC SYLLABLE WU +U+12CA # ETHIOPIC SYLLABLE WI +U+12CB # ETHIOPIC SYLLABLE WAA +U+12CC # ETHIOPIC SYLLABLE WEE +U+12CD # ETHIOPIC SYLLABLE WE +U+12CE # ETHIOPIC SYLLABLE WO +U+12CF # ETHIOPIC SYLLABLE WOA +U+12D0 # ETHIOPIC SYLLABLE PHARYNGEAL A +U+12D1 # ETHIOPIC SYLLABLE PHARYNGEAL U +U+12D2 # ETHIOPIC SYLLABLE PHARYNGEAL I +U+12D3 # ETHIOPIC SYLLABLE PHARYNGEAL AA +U+12D4 # ETHIOPIC SYLLABLE PHARYNGEAL EE +U+12D5 # ETHIOPIC SYLLABLE PHARYNGEAL E +U+12D6 # ETHIOPIC SYLLABLE PHARYNGEAL O +U+12D8 # ETHIOPIC SYLLABLE ZA +U+12D9 # ETHIOPIC SYLLABLE ZU +U+12DA # ETHIOPIC SYLLABLE ZI +U+12DB # ETHIOPIC SYLLABLE ZAA +U+12DC # ETHIOPIC SYLLABLE ZEE +U+12DD # ETHIOPIC SYLLABLE ZE +U+12DE # ETHIOPIC SYLLABLE ZO +U+12DF # ETHIOPIC SYLLABLE ZWA +U+12E0 # ETHIOPIC SYLLABLE ZHA +U+12E1 # ETHIOPIC SYLLABLE ZHU +U+12E2 # ETHIOPIC SYLLABLE ZHI +U+12E3 # ETHIOPIC SYLLABLE ZHAA +U+12E4 # ETHIOPIC SYLLABLE ZHEE +U+12E5 # ETHIOPIC SYLLABLE ZHE +U+12E6 # ETHIOPIC SYLLABLE ZHO +U+12E7 # ETHIOPIC SYLLABLE ZHWA +U+12E8 # ETHIOPIC SYLLABLE YA +U+12E9 # ETHIOPIC SYLLABLE YU +U+12EA # ETHIOPIC SYLLABLE YI +U+12EB # ETHIOPIC SYLLABLE YAA +U+12EC # ETHIOPIC SYLLABLE YEE +U+12ED # ETHIOPIC SYLLABLE YE +U+12EE # ETHIOPIC SYLLABLE YO +U+12EF # ETHIOPIC SYLLABLE YOA +U+12F0 # ETHIOPIC SYLLABLE DA +U+12F1 # ETHIOPIC SYLLABLE DU +U+12F2 # ETHIOPIC SYLLABLE DI +U+12F3 # ETHIOPIC SYLLABLE DAA +U+12F4 # ETHIOPIC SYLLABLE DEE +U+12F5 # ETHIOPIC SYLLABLE DE +U+12F6 # ETHIOPIC SYLLABLE DO +U+12F7 # ETHIOPIC SYLLABLE DWA +U+12F8 # ETHIOPIC SYLLABLE DDA +U+12F9 # ETHIOPIC SYLLABLE DDU +U+12FA # ETHIOPIC SYLLABLE DDI +U+12FB # ETHIOPIC SYLLABLE DDAA +U+12FC # ETHIOPIC SYLLABLE DDEE +U+12FD # ETHIOPIC SYLLABLE DDE +U+12FE # ETHIOPIC SYLLABLE DDO +U+12FF # ETHIOPIC SYLLABLE DDWA +U+1300 # ETHIOPIC SYLLABLE JA +U+1301 # ETHIOPIC SYLLABLE JU +U+1302 # ETHIOPIC SYLLABLE JI +U+1303 # ETHIOPIC SYLLABLE JAA +U+1304 # ETHIOPIC SYLLABLE JEE +U+1305 # ETHIOPIC SYLLABLE JE +U+1306 # ETHIOPIC SYLLABLE JO +U+1307 # ETHIOPIC SYLLABLE JWA +U+1308 # ETHIOPIC SYLLABLE GA +U+1309 # ETHIOPIC SYLLABLE GU +U+130A # ETHIOPIC SYLLABLE GI +U+130B # ETHIOPIC SYLLABLE GAA +U+130C # ETHIOPIC SYLLABLE GEE +U+130D # ETHIOPIC SYLLABLE GE +U+130E # ETHIOPIC SYLLABLE GO +U+130F # ETHIOPIC SYLLABLE GOA +U+1310 # ETHIOPIC SYLLABLE GWA +U+1312 # ETHIOPIC SYLLABLE GWI +U+1313 # ETHIOPIC SYLLABLE GWAA +U+1314 # ETHIOPIC SYLLABLE GWEE +U+1315 # ETHIOPIC SYLLABLE GWE +U+1318 # ETHIOPIC SYLLABLE GGA +U+1319 # ETHIOPIC SYLLABLE GGU +U+131A # ETHIOPIC SYLLABLE GGI +U+131B # ETHIOPIC SYLLABLE GGAA +U+131C # ETHIOPIC SYLLABLE GGEE +U+131D # ETHIOPIC SYLLABLE GGE +U+131E # ETHIOPIC SYLLABLE GGO +U+131F # ETHIOPIC SYLLABLE GGWAA +U+1320 # ETHIOPIC SYLLABLE THA +U+1321 # ETHIOPIC SYLLABLE THU +U+1322 # ETHIOPIC SYLLABLE THI +U+1323 # ETHIOPIC SYLLABLE THAA +U+1324 # ETHIOPIC SYLLABLE THEE +U+1325 # ETHIOPIC SYLLABLE THE +U+1326 # ETHIOPIC SYLLABLE THO +U+1327 # ETHIOPIC SYLLABLE THWA +U+1328 # ETHIOPIC SYLLABLE CHA +U+1329 # ETHIOPIC SYLLABLE CHU +U+132A # ETHIOPIC SYLLABLE CHI +U+132B # ETHIOPIC SYLLABLE CHAA +U+132C # ETHIOPIC SYLLABLE CHEE +U+132D # ETHIOPIC SYLLABLE CHE +U+132E # ETHIOPIC SYLLABLE CHO +U+132F # ETHIOPIC SYLLABLE CHWA +U+1330 # ETHIOPIC SYLLABLE PHA +U+1331 # ETHIOPIC SYLLABLE PHU +U+1332 # ETHIOPIC SYLLABLE PHI +U+1333 # ETHIOPIC SYLLABLE PHAA +U+1334 # ETHIOPIC SYLLABLE PHEE +U+1335 # ETHIOPIC SYLLABLE PHE +U+1336 # ETHIOPIC SYLLABLE PHO +U+1337 # ETHIOPIC SYLLABLE PHWA +U+1338 # ETHIOPIC SYLLABLE TSA +U+1339 # ETHIOPIC SYLLABLE TSU +U+133A # ETHIOPIC SYLLABLE TSI +U+133B # ETHIOPIC SYLLABLE TSAA +U+133C # ETHIOPIC SYLLABLE TSEE +U+133D # ETHIOPIC SYLLABLE TSE +U+133E # ETHIOPIC SYLLABLE TSO +U+133F # ETHIOPIC SYLLABLE TSWA +U+1340 # ETHIOPIC SYLLABLE TZA +U+1341 # ETHIOPIC SYLLABLE TZU +U+1342 # ETHIOPIC SYLLABLE TZI +U+1343 # ETHIOPIC SYLLABLE TZAA +U+1344 # ETHIOPIC SYLLABLE TZEE +U+1345 # ETHIOPIC SYLLABLE TZE +U+1346 # ETHIOPIC SYLLABLE TZO +U+1347 # ETHIOPIC SYLLABLE TZOA +U+1348 # ETHIOPIC SYLLABLE FA +U+1349 # ETHIOPIC SYLLABLE FU +U+134A # ETHIOPIC SYLLABLE FI +U+134B # ETHIOPIC SYLLABLE FAA +U+134C # ETHIOPIC SYLLABLE FEE +U+134D # ETHIOPIC SYLLABLE FE +U+134E # ETHIOPIC SYLLABLE FO +U+134F # ETHIOPIC SYLLABLE FWA +U+1350 # ETHIOPIC SYLLABLE PA +U+1351 # ETHIOPIC SYLLABLE PU +U+1352 # ETHIOPIC SYLLABLE PI +U+1353 # ETHIOPIC SYLLABLE PAA +U+1354 # ETHIOPIC SYLLABLE PEE +U+1355 # ETHIOPIC SYLLABLE PE +U+1356 # ETHIOPIC SYLLABLE PO +U+1357 # ETHIOPIC SYLLABLE PWA +U+1358 # ETHIOPIC SYLLABLE RYA +U+1359 # ETHIOPIC SYLLABLE MYA +U+135A # ETHIOPIC SYLLABLE FYA +U+135D # ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK +U+135E # ETHIOPIC COMBINING VOWEL LENGTH MARK +U+135F # ETHIOPIC COMBINING GEMINATION MARK +U+1380 # ETHIOPIC SYLLABLE SEBATBEIT MWA +U+1381 # ETHIOPIC SYLLABLE MWI +U+1382 # ETHIOPIC SYLLABLE MWEE +U+1383 # ETHIOPIC SYLLABLE MWE +U+1384 # ETHIOPIC SYLLABLE SEBATBEIT BWA +U+1385 # ETHIOPIC SYLLABLE BWI +U+1386 # ETHIOPIC SYLLABLE BWEE +U+1387 # ETHIOPIC SYLLABLE BWE +U+1388 # ETHIOPIC SYLLABLE SEBATBEIT FWA +U+1389 # ETHIOPIC SYLLABLE FWI +U+138A # ETHIOPIC SYLLABLE FWEE +U+138B # ETHIOPIC SYLLABLE FWE +U+138C # ETHIOPIC SYLLABLE SEBATBEIT PWA +U+138D # ETHIOPIC SYLLABLE PWI +U+138E # ETHIOPIC SYLLABLE PWEE +U+138F # ETHIOPIC SYLLABLE PWE +U+2D80 # ETHIOPIC SYLLABLE LOA +U+2D81 # ETHIOPIC SYLLABLE MOA +U+2D82 # ETHIOPIC SYLLABLE ROA +U+2D83 # ETHIOPIC SYLLABLE SOA +U+2D84 # ETHIOPIC SYLLABLE SHOA +U+2D85 # ETHIOPIC SYLLABLE BOA +U+2D86 # ETHIOPIC SYLLABLE TOA +U+2D87 # ETHIOPIC SYLLABLE COA +U+2D88 # ETHIOPIC SYLLABLE NOA +U+2D89 # ETHIOPIC SYLLABLE NYOA +U+2D8A # ETHIOPIC SYLLABLE GLOTTAL OA +U+2D8B # ETHIOPIC SYLLABLE ZOA +U+2D8C # ETHIOPIC SYLLABLE DOA +U+2D8D # ETHIOPIC SYLLABLE DDOA +U+2D8E # ETHIOPIC SYLLABLE JOA +U+2D8F # ETHIOPIC SYLLABLE THOA +U+2D90 # ETHIOPIC SYLLABLE CHOA +U+2D91 # ETHIOPIC SYLLABLE PHOA +U+2D92 # ETHIOPIC SYLLABLE POA +U+2D93 # ETHIOPIC SYLLABLE GGWA +U+2D94 # ETHIOPIC SYLLABLE GGWI +U+2D95 # ETHIOPIC SYLLABLE GGWEE +U+2D96 # ETHIOPIC SYLLABLE GGWE +U+2DA0 # ETHIOPIC SYLLABLE SSA +U+2DA1 # ETHIOPIC SYLLABLE SSU +U+2DA2 # ETHIOPIC SYLLABLE SSI +U+2DA3 # ETHIOPIC SYLLABLE SSAA +U+2DA4 # ETHIOPIC SYLLABLE SSEE +U+2DA5 # ETHIOPIC SYLLABLE SSE +U+2DA6 # ETHIOPIC SYLLABLE SSO +U+2DA8 # ETHIOPIC SYLLABLE CCA +U+2DA9 # ETHIOPIC SYLLABLE CCU +U+2DAA # ETHIOPIC SYLLABLE CCI +U+2DAB # ETHIOPIC SYLLABLE CCAA +U+2DAC # ETHIOPIC SYLLABLE CCEE +U+2DAD # ETHIOPIC SYLLABLE CCE +U+2DAE # ETHIOPIC SYLLABLE CCO +U+2DB0 # ETHIOPIC SYLLABLE ZZA +U+2DB1 # ETHIOPIC SYLLABLE ZZU +U+2DB2 # ETHIOPIC SYLLABLE ZZI +U+2DB3 # ETHIOPIC SYLLABLE ZZAA +U+2DB4 # ETHIOPIC SYLLABLE ZZEE +U+2DB5 # ETHIOPIC SYLLABLE ZZE +U+2DB6 # ETHIOPIC SYLLABLE ZZO +U+2DB8 # ETHIOPIC SYLLABLE CCHA +U+2DB9 # ETHIOPIC SYLLABLE CCHU +U+2DBA # ETHIOPIC SYLLABLE CCHI +U+2DBB # ETHIOPIC SYLLABLE CCHAA +U+2DBC # ETHIOPIC SYLLABLE CCHEE +U+2DBD # ETHIOPIC SYLLABLE CCHE +U+2DBE # ETHIOPIC SYLLABLE CCHO +U+2DC0 # ETHIOPIC SYLLABLE QYA +U+2DC1 # ETHIOPIC SYLLABLE QYU +U+2DC2 # ETHIOPIC SYLLABLE QYI +U+2DC3 # ETHIOPIC SYLLABLE QYAA +U+2DC4 # ETHIOPIC SYLLABLE QYEE +U+2DC5 # ETHIOPIC SYLLABLE QYE +U+2DC6 # ETHIOPIC SYLLABLE QYO +U+2DC8 # ETHIOPIC SYLLABLE KYA +U+2DC9 # ETHIOPIC SYLLABLE KYU +U+2DCA # ETHIOPIC SYLLABLE KYI +U+2DCB # ETHIOPIC SYLLABLE KYAA +U+2DCC # ETHIOPIC SYLLABLE KYEE +U+2DCD # ETHIOPIC SYLLABLE KYE +U+2DCE # ETHIOPIC SYLLABLE KYO +U+2DD0 # ETHIOPIC SYLLABLE XYA +U+2DD1 # ETHIOPIC SYLLABLE XYU +U+2DD2 # ETHIOPIC SYLLABLE XYI +U+2DD3 # ETHIOPIC SYLLABLE XYAA +U+2DD4 # ETHIOPIC SYLLABLE XYEE +U+2DD5 # ETHIOPIC SYLLABLE XYE +U+2DD6 # ETHIOPIC SYLLABLE XYO +U+2DD8 # ETHIOPIC SYLLABLE GYA +U+2DD9 # ETHIOPIC SYLLABLE GYU +U+2DDA # ETHIOPIC SYLLABLE GYI +U+2DDB # ETHIOPIC SYLLABLE GYAA +U+2DDC # ETHIOPIC SYLLABLE GYEE +U+2DDD # ETHIOPIC SYLLABLE GYE +U+2DDE # ETHIOPIC SYLLABLE GYO +U+AB01 # ETHIOPIC SYLLABLE TTHU +U+AB02 # ETHIOPIC SYLLABLE TTHI +U+AB03 # ETHIOPIC SYLLABLE TTHAA +U+AB04 # ETHIOPIC SYLLABLE TTHEE +U+AB05 # ETHIOPIC SYLLABLE TTHE +U+AB06 # ETHIOPIC SYLLABLE TTHO +U+AB09 # ETHIOPIC SYLLABLE DDHU +U+AB0A # ETHIOPIC SYLLABLE DDHI +U+AB0B # ETHIOPIC SYLLABLE DDHAA +U+AB0C # ETHIOPIC SYLLABLE DDHEE +U+AB0D # ETHIOPIC SYLLABLE DDHE +U+AB0E # ETHIOPIC SYLLABLE DDHO +U+AB11 # ETHIOPIC SYLLABLE DZU +U+AB12 # ETHIOPIC SYLLABLE DZI +U+AB13 # ETHIOPIC SYLLABLE DZAA +U+AB14 # ETHIOPIC SYLLABLE DZEE +U+AB15 # ETHIOPIC SYLLABLE DZE +U+AB16 # ETHIOPIC SYLLABLE DZO +U+AB20 # ETHIOPIC SYLLABLE CCHHA +U+AB21 # ETHIOPIC SYLLABLE CCHHU +U+AB22 # ETHIOPIC SYLLABLE CCHHI +U+AB23 # ETHIOPIC SYLLABLE CCHHAA +U+AB24 # ETHIOPIC SYLLABLE CCHHEE +U+AB25 # ETHIOPIC SYLLABLE CCHHE +U+AB26 # ETHIOPIC SYLLABLE CCHHO +U+AB28 # ETHIOPIC SYLLABLE BBA +U+AB29 # ETHIOPIC SYLLABLE BBU +U+AB2A # ETHIOPIC SYLLABLE BBI +U+AB2B # ETHIOPIC SYLLABLE BBAA +U+AB2C # ETHIOPIC SYLLABLE BBEE +U+AB2D # ETHIOPIC SYLLABLE BBE +U+AB2E # ETHIOPIC SYLLABLE BBO + +# Common codepoints (allowed in all scripts). +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE diff --git a/java/com/google/domain/registry/idn/Georgian-IDN.txt b/java/com/google/domain/registry/idn/Georgian-IDN.txt new file mode 100644 index 000000000..62b33756b --- /dev/null +++ b/java/com/google/domain/registry/idn/Georgian-IDN.txt @@ -0,0 +1,105 @@ +# Registry: Charleston Road Registry Inc. +# Script: Georgian +# +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Georgian script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+10D0 # GEORGIAN SMALL LETTER AN +U+10D1 # GEORGIAN SMALL LETTER BAN +U+10D2 # GEORGIAN SMALL LETTER GAN +U+10D3 # GEORGIAN SMALL LETTER DON +U+10D4 # GEORGIAN SMALL LETTER EN +U+10D5 # GEORGIAN SMALL LETTER VIN +U+10D6 # GEORGIAN SMALL LETTER ZEN +U+10D7 # GEORGIAN SMALL LETTER TAN +U+10D8 # GEORGIAN SMALL LETTER IN +U+10D9 # GEORGIAN SMALL LETTER KAN +U+10DA # GEORGIAN SMALL LETTER LAS +U+10DB # GEORGIAN SMALL LETTER MAN +U+10DC # GEORGIAN SMALL LETTER NAR +U+10DD # GEORGIAN SMALL LETTER ON +U+10DE # GEORGIAN SMALL LETTER PAR +U+10DF # GEORGIAN SMALL LETTER ZHAR +U+10E0 # GEORGIAN SMALL LETTER RAE +U+10E1 # GEORGIAN SMALL LETTER SAN +U+10E2 # GEORGIAN SMALL LETTER TAR +U+10E3 # GEORGIAN SMALL LETTER UN +U+10E4 # GEORGIAN SMALL LETTER PHAR +U+10E5 # GEORGIAN SMALL LETTER KHAR +U+10E6 # GEORGIAN SMALL LETTER GHAN +U+10E7 # GEORGIAN SMALL LETTER QAR +U+10E8 # GEORGIAN SMALL LETTER SHIN +U+10E9 # GEORGIAN SMALL LETTER CHIN +U+10EA # GEORGIAN SMALL LETTER CAN +U+10EB # GEORGIAN SMALL LETTER JIL +U+10EC # GEORGIAN SMALL LETTER CIL +U+10ED # GEORGIAN SMALL LETTER CHAR +U+10EE # GEORGIAN SMALL LETTER XAN +U+10EF # GEORGIAN SMALL LETTER JHAN +U+10F0 # GEORGIAN SMALL LETTER HAE +U+10F1 # GEORGIAN SMALL LETTER HE +U+10F2 # GEORGIAN SMALL LETTER HIE +U+10F3 # GEORGIAN SMALL LETTER WE +U+10F4 # GEORGIAN SMALL LETTER HAR +U+10F5 # GEORGIAN SMALL LETTER HOE +U+10F6 # GEORGIAN SMALL LETTER FI +U+10F7 # GEORGIAN LETTER YN +U+10F8 # GEORGIAN LETTER ELIFI +U+10F9 # GEORGIAN LETTER TURNED GAN +U+10FA # GEORGIAN LETTER AIN +U+2D00 # GEORGIAN SMALL LETTER AN +U+2D01 # GEORGIAN SMALL LETTER BAN +U+2D02 # GEORGIAN SMALL LETTER GAN +U+2D03 # GEORGIAN SMALL LETTER DON +U+2D04 # GEORGIAN SMALL LETTER EN +U+2D05 # GEORGIAN SMALL LETTER VIN +U+2D06 # GEORGIAN SMALL LETTER ZEN +U+2D07 # GEORGIAN SMALL LETTER TAN +U+2D08 # GEORGIAN SMALL LETTER IN +U+2D09 # GEORGIAN SMALL LETTER KAN +U+2D0A # GEORGIAN SMALL LETTER LAS +U+2D0B # GEORGIAN SMALL LETTER MAN +U+2D0C # GEORGIAN SMALL LETTER NAR +U+2D0D # GEORGIAN SMALL LETTER ON +U+2D0E # GEORGIAN SMALL LETTER PAR +U+2D0F # GEORGIAN SMALL LETTER ZHAR +U+2D10 # GEORGIAN SMALL LETTER RAE +U+2D11 # GEORGIAN SMALL LETTER SAN +U+2D12 # GEORGIAN SMALL LETTER TAR +U+2D13 # GEORGIAN SMALL LETTER UN +U+2D14 # GEORGIAN SMALL LETTER PHAR +U+2D15 # GEORGIAN SMALL LETTER KHAR +U+2D16 # GEORGIAN SMALL LETTER GHAN +U+2D17 # GEORGIAN SMALL LETTER QAR +U+2D18 # GEORGIAN SMALL LETTER SHIN +U+2D19 # GEORGIAN SMALL LETTER CHIN +U+2D1A # GEORGIAN SMALL LETTER CAN +U+2D1B # GEORGIAN SMALL LETTER JIL +U+2D1C # GEORGIAN SMALL LETTER CIL +U+2D1D # GEORGIAN SMALL LETTER CHAR +U+2D1E # GEORGIAN SMALL LETTER XAN +U+2D1F # GEORGIAN SMALL LETTER JHAN +U+2D20 # GEORGIAN SMALL LETTER HAE +U+2D21 # GEORGIAN SMALL LETTER HE +U+2D22 # GEORGIAN SMALL LETTER HIE +U+2D23 # GEORGIAN SMALL LETTER WE +U+2D24 # GEORGIAN SMALL LETTER HAR +U+2D25 # GEORGIAN SMALL LETTER HOE diff --git a/java/com/google/domain/registry/idn/Greek-IDN.txt b/java/com/google/domain/registry/idn/Greek-IDN.txt new file mode 100644 index 000000000..90e6fb85f --- /dev/null +++ b/java/com/google/domain/registry/idn/Greek-IDN.txt @@ -0,0 +1,136 @@ +# Registry: Charleston Road Registry Inc. +# +# Script: Greek +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Greek script. +# The hyphen (U+002D), as well as the digits zero to nine (U+0030 .. U+0039), for +# purposes of Internationalised Domain Name registration are considered to form +# part of the Greek script. + +###### Greek +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0390 ## W GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS U+03AC ## ά GREEK SMALL LETTER ALPHA WITH TONOS +U+03AD ## έ GREEK SMALL LETTER EPSILON WITH TONOS +U+03AE ## ή GREEK SMALL LETTER ETA WITH TONOS +U+03AF ## ί GREEK SMALL LETTER IOTA WITH TONOS +U+03B0 ## d GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS U+03B1 ## α GREEK SMALL LETTER ALPHA +U+03B2 ## β GREEK SMALL LETTER BETA +U+03B3 ## γ GREEK SMALL LETTER GAMMA +U+03B4 ## δ GREEK SMALL LETTER DELTA +U+03B5 ## ε GREEK SMALL LETTER EPSILON +U+03B6 ## ζ GREEK SMALL LETTER ZETA +U+03B7 ## η GREEK SMALL LETTER ETA +U+03B8 ## θ GREEK SMALL LETTER THETA +U+03B9 ## ι GREEK SMALL LETTER IOTA +U+03BA ## κ GREEK SMALL LETTER KAPPA +U+03BB ## λ GREEK SMALL LETTER LAMDA +U+03BC ## μ GREEK SMALL LETTER MU +U+03BD ## ν GREEK SMALL LETTER NU +U+03BE ## ξ GREEK SMALL LETTER XI +U+03BF ## ο GREEK SMALL LETTER OMICRON +U+03C0 ## π GREEK SMALL LETTER PI +U+03C1 ## ρ GREEK SMALL LETTER RHO +U+03C2 ## ς GREEK SMALL LETTER FINAL SIGMA +U+03C3 ## σ GREEK SMALL LETTER SIGMA +U+03C4 ## τ GREEK SMALL LETTER TAU +U+03C5 ## υ GREEK SMALL LETTER UPSILON +U+03C6 ## φ GREEK SMALL LETTER PHI +U+03C7 ## χ GREEK SMALL LETTER CHI +U+03C8 ## ψ GREEK SMALL LETTER PSI +U+03C9 ## ω GREEK SMALL LETTER OMEGA +U+03CA ## Ç GREEK SMALL LETTER IOTA WITH DIALYTIKA +U+03CB ## É GREEK SMALL LETTER UPSILON WITH DIALYTIKA +U+03CC ## ό GREEK SMALL LETTER OMICRON WITH TONOS +U+03CD ## ύ GREEK SMALL LETTER UPSILON WITH TONOS +U+03CE ## ώ GREEK SMALL LETTER OMEGA WITH TONOS +###### Greek extended +U+1F00 ## ἀ GREEK SMALL LETTER ALPHA WITH PSILI +U+1F01 ## ἁ GREEK SMALL LETTER ALPHA WITH DASIA +U+1F02 ## ἂ GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA +U+1F03 ## ἃ GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA + +U+1F04 ## ἄ GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA U+1F05 ## ἅ GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA +U+1F06 ## ἆ GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI U+1F07 ## ἇ GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI U+1F10 ## ἐ GREEK SMALL LETTER EPSILON WITH PSILI +U+1F11 ## ἑ GREEK SMALL LETTER EPSILON WITH DASIA +U+1F12 ## ἒ GREEK SMALL LETTER EPSILON WITH PSILI +U+1F13 ## ἓ GREEK SMALL LETTER EPSILON WITH DASIA +U+1F14 ## ἔ GREEK SMALL LETTER EPSILON WITH PSILI +U+1F15 ## ἕ GREEK SMALL LETTER EPSILON WITH DASIA +U+1F20 ## ἠ GREEK SMALL LETTER ETA WITH PSILI +U+1F21 ## ἡ GREEK SMALL LETTER ETA WITH DASIA +U+1F22 ## ἢ GREEK SMALL LETTER ETA WITH PSILI +U+1F23 ## ἣ GREEK SMALL LETTER ETA WITH DASIA +U+1F24 ## ἤ GREEK SMALL LETTER ETA WITH PSILI +U+1F25 ## ἥ GREEK SMALL LETTER ETA WITH DASIA +U+1F26 ## ἦ GREEK SMALL LETTER ETA WITH PSILI +U+1F27 ## ἧ GREEK SMALL LETTER ETA WITH DASIA +U+1F30 ## ἰ GREEK SMALL LETTER IOTA WITH PSILI +U+1F31 ## ἱ GREEK SMALL LETTER IOTA WITH DASIA +U+1F32 ## ἲ GREEK SMALL LETTER IOTA WITH PSILI +U+1F33 ## ἳ GREEK SMALL LETTER IOTA WITH DASIA +U+1F34 ## ἴ GREEK SMALL LETTER IOTA WITH PSILI +U+1F35 ## ἵ GREEK SMALL LETTER IOTA WITH DASIA +U+1F36 ## ἶ GREEK SMALL LETTER IOTA WITH PSILI +U+1F37 ## ἷ GREEK SMALL LETTER IOTA WITH DASIA +U+1F40 ## ὀ GREEK SMALL LETTER OMICRON WITH PSILI +U+1F41 ## ὁ GREEK SMALL LETTER OMICRON WITH DASIA +U+1F42 ## ὂ GREEK SMALL LETTER OMICRON WITH PSILI +U+1F43 ## ὃ GREEK SMALL LETTER OMICRON WITH DASIA +U+1F44 ## ὄ GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA +U+1F45 ## ὅ GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA +U+1F50 ## ὐ GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA +U+1F51 ## ὑ GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA +U+1F52 ## ὒ GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI +U+1F53 ## ὓ GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI +U+1F54 ## ὔ GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA +U+1F55 ## ὕ GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA +U+1F56 ## ὖ GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA +U+1F57 ## ὗ GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA +U+1F60 ## ὠ GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA +U+1F61 ## ὡ GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA +U+1F62 ## ὢ GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA +U+1F63 ## ὣ GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA +U+1F64 ## ὤ GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI +U+1F65 ## ὥ GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI +U+1F66 ## ὦ GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA +U+1F67 ## ὧ GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA +U+1F70 ## ὰ GREEK SMALL LETTER ALPHA WITH VARIA AND OXIA +U+1F72 ## ὲ GREEK SMALL LETTER EPSILON WITH VARIA AND VARIA +U+1F74 ## ὴ GREEK SMALL LETTER ETA WITH VARIA AND OXIA +U+1F76 ## ὶ GREEK SMALL LETTER IOTA WITH VARIA AND PERISPOMENI +U+1F78 ## ὸ GREEK SMALL LETTER OMICROM WITH VARIA AND VARIA +U+1F7A ## ὺ GREEK SMALL LETTER UPSILON WITH VARIA AND OXIA +U+1F7C ## ὼ GREEK SMALL LETTER OMEGA WITH VARIA AND PERISPOMENI + +U+1FB0 ## ᾰ GREEK SMALL LETTER ALPHA WITH VRACHY +U+1FB1 ## ᾱ GREEK SMALL LETTER ALPHA WITH MACRON +U+1FB6 ## ᾶ GREEK SMALL LETTER ALPHA WITH PERISPOMENI +U+1FC6 ## ῆ GREEK SMALL LETTER ETA WITH PERISPOMENI +U+1FD0 ## ῐ GREEK SMALL LETTER IOTA WITH VRACHY +U+1FD1 ## ῑ GREEK SMALL LETTER IOTA WITH MACRON +U+1FD2 ## ῒ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA +U+1FD6 ## ῖ GREEK SMALL LETTER IOTA WITH PERISPOMENI +U+1FD7 ## ῗ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI +U+1FE0 ## ῠ GREEK SMALL LETTER UPSILON WITH VRACHY +U+1FE1 ## ῡ GREEK SMALL LETTER UPSILON WITH MACRON +U+1FE2 ## ῢ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA +U+1FE4 ## ῤ GREEK SMALL LETTER RHO WITH PSILI +U+1FE5 ## ῥ GREEK SMALL LETTER RHO WITH DASIA +U+1FE6 ## ῦ GREEK SMALL LETTER UPSILON WITH PERISPOMENI +U+1FE7 ## ῧ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI +U+1FF6 ## ῶ GREEK SMALL LETTER OMEGA WITH PERISPOMENI diff --git a/java/com/google/domain/registry/idn/Gurmukhi-IDN.txt b/java/com/google/domain/registry/idn/Gurmukhi-IDN.txt new file mode 100644 index 000000000..af02761fc --- /dev/null +++ b/java/com/google/domain/registry/idn/Gurmukhi-IDN.txt @@ -0,0 +1,97 @@ +# Registry: Charleston Road Registry Inc. +# +# Script: Gurmukhi +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Gurmukhi script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0A01 # GURMUKHI SIGN ADAK BINDI +U+0A02 # GURMUKHI SIGN BINDI +U+0A03 # GURMUKHI SIGN VISARGA +U+0A05 # GURMUKHI LETTER A +U+0A06 # GURMUKHI LETTER AA +U+0A07 # GURMUKHI LETTER I +U+0A08 # GURMUKHI LETTER II +U+0A09 # GURMUKHI LETTER U +U+0A0A # GURMUKHI LETTER UU +U+0A0F # GURMUKHI LETTER EE +U+0A10 # GURMUKHI LETTER AI +U+0A13 # GURMUKHI LETTER OO +U+0A14 # GURMUKHI LETTER AU +U+0A15 # GURMUKHI LETTER KA +U+0A16 # GURMUKHI LETTER KHA +U+0A17 # GURMUKHI LETTER GA +U+0A18 # GURMUKHI LETTER GHA +U+0A19 # GURMUKHI LETTER NGA +U+0A1A # GURMUKHI LETTER CA +U+0A1B # GURMUKHI LETTER CHA +U+0A1C # GURMUKHI LETTER JA +U+0A1D # GURMUKHI LETTER JHA +U+0A1E # GURMUKHI LETTER NYA +U+0A1F # GURMUKHI LETTER TTA +U+0A20 # GURMUKHI LETTER TTHA +U+0A21 # GURMUKHI LETTER DDA +U+0A22 # GURMUKHI LETTER DDHA +U+0A23 # GURMUKHI LETTER NNA +U+0A24 # GURMUKHI LETTER TA +U+0A25 # GURMUKHI LETTER THA +U+0A26 # GURMUKHI LETTER DA +U+0A27 # GURMUKHI LETTER DHA +U+0A28 # GURMUKHI LETTER NA +U+0A2A # GURMUKHI LETTER PA +U+0A2B # GURMUKHI LETTER PHA +U+0A2C # GURMUKHI LETTER BA +U+0A2D # GURMUKHI LETTER BHA +U+0A2E # GURMUKHI LETTER MA +U+0A2F # GURMUKHI LETTER YA +U+0A30 # GURMUKHI LETTER RA +U+0A32 # GURMUKHI LETTER LA +U+0A35 # GURMUKHI LETTER VA +U+0A38 # GURMUKHI LETTER SA +U+0A39 # GURMUKHI LETTER HA +U+0A3C # GURMUKHI SIGN NUKTA +U+0A3E # GURMUKHI VOWEL SIGN AA +U+0A3F # GURMUKHI VOWEL SIGN I +U+0A40 # GURMUKHI VOWEL SIGN II +U+0A41 # GURMUKHI VOWEL SIGN U +U+0A42 # GURMUKHI VOWEL SIGN UU +U+0A47 # GURMUKHI VOWEL SIGN EE +U+0A48 # GURMUKHI VOWEL SIGN AI +U+0A4B # GURMUKHI VOWEL SIGN OO +U+0A4C # GURMUKHI VOWEL SIGN AU +U+0A4D # GURMUKHI SIGN VIRAMA +U+0A51 # GURMUKHI SIGN UDAAT +U+0A5C # GURMUKHI LETTER RRA +U+0A66 # GURMUKHI DIGIT ZERO +U+0A67 # GURMUKHI DIGIT ONE +U+0A68 # GURMUKHI DIGIT TWO +U+0A69 # GURMUKHI DIGIT THREE +U+0A6A # GURMUKHI DIGIT FOUR +U+0A6B # GURMUKHI DIGIT FIVE +U+0A6C # GURMUKHI DIGIT SIX +U+0A6D # GURMUKHI DIGIT SEVEN +U+0A6E # GURMUKHI DIGIT EIGHT +U+0A6F # GURMUKHI DIGIT NINE +U+0A70 # GURMUKHI TIPPI +U+0A71 # GURMUKHI ADDAK +U+0A72 # GURMUKHI IRI +U+0A73 # GURMUKHI URA +U+0A74 # GURMUKHI EK ONKAR +U+0A75 # GURMUKHI SIGN YAKASH diff --git a/java/com/google/domain/registry/idn/Hebrew-IDN.txt b/java/com/google/domain/registry/idn/Hebrew-IDN.txt new file mode 100644 index 000000000..293cf14ec --- /dev/null +++ b/java/com/google/domain/registry/idn/Hebrew-IDN.txt @@ -0,0 +1,55 @@ +# Registry: Charleston Road Registry Inc. +# Script: Hebrew +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Hebrew script. +# +# Code Point +# +U+002D # HYPHEN-MINUS +# +U+0030 # DIGIT ZERO + +# Character + +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +# +U+05D0 # HEBREW LETTER ALEF +U+05D1 # HEBREW LETTER BET +U+05D2 # HEBREW LETTER GIMEL +U+05D3 # HEBREW LETTER DALET +U+05D4 # HEBREW LETTER HE +U+05D5 # HEBREW LETTER VAV +U+05D6 # HEBREW LETTER ZAYIN +U+05D7 # HEBREW LETTER HET +U+05D8 # HEBREW LETTER TET +U+05D9 # HEBREW LETTER YOD +U+05DA # HEBREW LETTER FINAL KAF +U+05DB # HEBREW LETTER KAF +U+05DC # HEBREW LETTER LAMED +U+05DD # HEBREW LETTER FINAL MEM +U+05DE # HEBREW LETTER MEM +U+05DF # HEBREW LETTER FINAL NUN +U+05E0 # HEBREW LETTER NUN +U+05E1 # HEBREW LETTER SAMEKH +U+05E2 # HEBREW LETTER AYIN +U+05E3 # HEBREW LETTER FINAL PE +U+05E4 # HEBREW LETTER PE +U+05E5 # HEBREW LETTER FINAL TSADI +U+05E6 # HEBREW LETTER TSADI +U+05E7 # HEBREW LETTER QOF +U+05E8 # HEBREW LETTER RESH +U+05E9 # HEBREW LETTER SHIN +U+05EA # HEBREW LETTER TAV diff --git a/java/com/google/domain/registry/idn/Japanese-IDN.txt b/java/com/google/domain/registry/idn/Japanese-IDN.txt new file mode 100644 index 000000000..ce5640071 --- /dev/null +++ b/java/com/google/domain/registry/idn/Japanese-IDN.txt @@ -0,0 +1,6589 @@ +# Registry: Charleston Road Registry Inc. +# +# Script: Japanese +# +# Version: 1.0 +# +# Effective Date: 04-12-2012 +# +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# +# Telephone: +1 (650) 253-0000 +# +# Website: www.charlestonroadregistry.com +# +# Notes: This table describes codepoints allowed for the Japanese script. + + + +U+002D(1);U+002D(1); # HYPHEN-MINUS +U+0030(1);U+0030(1); # DIGIT ZERO +U+0031(1);U+0031(1); # DIGIT ONE +U+0032(1);U+0032(1); # DIGIT TWO +U+0033(1);U+0033(1); # DIGIT THREE +U+0034(1);U+0034(1); # DIGIT FOUR +U+0035(1);U+0035(1); # DIGIT FIVE +U+0036(1);U+0036(1); # DIGIT SIX +U+0037(1);U+0037(1); # DIGIT SEVEN +U+0038(1);U+0038(1); # DIGIT EIGHT +U+0039(1);U+0039(1); # DIGIT NINE +U+0061(1);U+0061(1); # LATIN SMALL LETTER A +U+0062(1);U+0062(1); # LATIN SMALL LETTER B +U+0063(1);U+0063(1); # LATIN SMALL LETTER C +U+0064(1);U+0064(1); # LATIN SMALL LETTER D +U+0065(1);U+0065(1); # LATIN SMALL LETTER E +U+0066(1);U+0066(1); # LATIN SMALL LETTER F +U+0067(1);U+0067(1); # LATIN SMALL LETTER G +U+0068(1);U+0068(1); # LATIN SMALL LETTER H +U+0069(1);U+0069(1); # LATIN SMALL LETTER I +U+006A(1);U+006A(1); # LATIN SMALL LETTER J +U+006B(1);U+006B(1); # LATIN SMALL LETTER K +U+006C(1);U+006C(1); # LATIN SMALL LETTER L +U+006D(1);U+006D(1); # LATIN SMALL LETTER M +U+006E(1);U+006E(1); # LATIN SMALL LETTER N +U+006F(1);U+006F(1); # LATIN SMALL LETTER O +U+0070(1);U+0070(1); # LATIN SMALL LETTER P +U+0071(1);U+0071(1); # LATIN SMALL LETTER Q +U+0072(1);U+0072(1); # LATIN SMALL LETTER R +U+0073(1);U+0073(1); # LATIN SMALL LETTER S +U+0074(1);U+0074(1); # LATIN SMALL LETTER T +U+0075(1);U+0075(1); # LATIN SMALL LETTER U +U+0076(1);U+0076(1); # LATIN SMALL LETTER V +U+0077(1);U+0077(1); # LATIN SMALL LETTER W +U+0078(1);U+0078(1); # LATIN SMALL LETTER X +U+0079(1);U+0079(1); # LATIN SMALL LETTER Y +U+007A(1);U+007A(1); # LATIN SMALL LETTER Z +U+3005(2,3);U+3005(2,3); # 01-25, IDEOGRAPHIC ITERATION MARK +U+3006(2,3);U+3006(2,3); # 01-26, IDEOGRAPHIC CLOSING MARK +U+3007(2,3);U+3007(2,3); # 01-27, IDEOGRAPHIC NUMBER ZERO +U+3041(2,3);U+3041(2,3); # 04-01, HIRAGANA LETTER SMALL A +U+3042(2,3);U+3042(2,3); # 04-02, HIRAGANA LETTER A +U+3043(2,3);U+3043(2,3); # 04-03, HIRAGANA LETTER SMALL I +U+3044(2,3);U+3044(2,3); # 04-04, HIRAGANA LETTER I +U+3045(2,3);U+3045(2,3); # 04-05, HIRAGANA LETTER SMALL U +U+3046(2,3);U+3046(2,3); # 04-06, HIRAGANA LETTER U +U+3047(2,3);U+3047(2,3); # 04-07, HIRAGANA LETTER SMALL E +U+3048(2,3);U+3048(2,3); # 04-08, HIRAGANA LETTER E +U+3049(2,3);U+3049(2,3); # 04-09, HIRAGANA LETTER SMALL O +U+304A(2,3);U+304A(2,3); # 04-10, HIRAGANA LETTER O +U+304B(2,3);U+304B(2,3); # 04-11, HIRAGANA LETTER KA +U+304C(2,3);U+304C(2,3); # 04-12, HIRAGANA LETTER GA +U+304D(2,3);U+304D(2,3); # 04-13, HIRAGANA LETTER KI +U+304E(2,3);U+304E(2,3); # 04-14, HIRAGANA LETTER GI +U+304F(2,3);U+304F(2,3); # 04-15, HIRAGANA LETTER KU +U+3050(2,3);U+3050(2,3); # 04-16, HIRAGANA LETTER GU +U+3051(2,3);U+3051(2,3); # 04-17, HIRAGANA LETTER KE +U+3052(2,3);U+3052(2,3); # 04-18, HIRAGANA LETTER GE +U+3053(2,3);U+3053(2,3); # 04-19, HIRAGANA LETTER KO +U+3054(2,3);U+3054(2,3); # 04-20, HIRAGANA LETTER GO +U+3055(2,3);U+3055(2,3); # 04-21, HIRAGANA LETTER SA +U+3056(2,3);U+3056(2,3); # 04-22, HIRAGANA LETTER ZA +U+3057(2,3);U+3057(2,3); # 04-23, HIRAGANA LETTER SI +U+3058(2,3);U+3058(2,3); # 04-24, HIRAGANA LETTER ZI +U+3059(2,3);U+3059(2,3); # 04-25, HIRAGANA LETTER SU +U+305A(2,3);U+305A(2,3); # 04-26, HIRAGANA LETTER ZU +U+305B(2,3);U+305B(2,3); # 04-27, HIRAGANA LETTER SE +U+305C(2,3);U+305C(2,3); # 04-28, HIRAGANA LETTER ZE +U+305D(2,3);U+305D(2,3); # 04-29, HIRAGANA LETTER SO +U+305E(2,3);U+305E(2,3); # 04-30, HIRAGANA LETTER ZO +U+305F(2,3);U+305F(2,3); # 04-31, HIRAGANA LETTER TA +U+3060(2,3);U+3060(2,3); # 04-32, HIRAGANA LETTER DA +U+3061(2,3);U+3061(2,3); # 04-33, HIRAGANA LETTER TI +U+3062(2,3);U+3062(2,3); # 04-34, HIRAGANA LETTER DI +U+3063(2,3);U+3063(2,3); # 04-35, HIRAGANA LETTER SMALL TU +U+3064(2,3);U+3064(2,3); # 04-36, HIRAGANA LETTER TU +U+3065(2,3);U+3065(2,3); # 04-37, HIRAGANA LETTER DU +U+3066(2,3);U+3066(2,3); # 04-38, HIRAGANA LETTER TE +U+3067(2,3);U+3067(2,3); # 04-39, HIRAGANA LETTER DE +U+3068(2,3);U+3068(2,3); # 04-40, HIRAGANA LETTER TO +U+3069(2,3);U+3069(2,3); # 04-41, HIRAGANA LETTER DO +U+306A(2,3);U+306A(2,3); # 04-42, HIRAGANA LETTER NA +U+306B(2,3);U+306B(2,3); # 04-43, HIRAGANA LETTER NI +U+306C(2,3);U+306C(2,3); # 04-44, HIRAGANA LETTER NU +U+306D(2,3);U+306D(2,3); # 04-45, HIRAGANA LETTER NE +U+306E(2,3);U+306E(2,3); # 04-46, HIRAGANA LETTER NO +U+306F(2,3);U+306F(2,3); # 04-47, HIRAGANA LETTER HA +U+3070(2,3);U+3070(2,3); # 04-48, HIRAGANA LETTER BA +U+3071(2,3);U+3071(2,3); # 04-49, HIRAGANA LETTER PA +U+3072(2,3);U+3072(2,3); # 04-50, HIRAGANA LETTER HI +U+3073(2,3);U+3073(2,3); # 04-51, HIRAGANA LETTER BI +U+3074(2,3);U+3074(2,3); # 04-52, HIRAGANA LETTER PI +U+3075(2,3);U+3075(2,3); # 04-53, HIRAGANA LETTER HU +U+3076(2,3);U+3076(2,3); # 04-54, HIRAGANA LETTER BU +U+3077(2,3);U+3077(2,3); # 04-55, HIRAGANA LETTER PU +U+3078(2,3);U+3078(2,3); # 04-56, HIRAGANA LETTER HE +U+3079(2,3);U+3079(2,3); # 04-57, HIRAGANA LETTER BE +U+307A(2,3);U+307A(2,3); # 04-58, HIRAGANA LETTER PE +U+307B(2,3);U+307B(2,3); # 04-59, HIRAGANA LETTER HO +U+307C(2,3);U+307C(2,3); # 04-60, HIRAGANA LETTER BO +U+307D(2,3);U+307D(2,3); # 04-61, HIRAGANA LETTER PO +U+307E(2,3);U+307E(2,3); # 04-62, HIRAGANA LETTER MA +U+307F(2,3);U+307F(2,3); # 04-63, HIRAGANA LETTER MI +U+3080(2,3);U+3080(2,3); # 04-64, HIRAGANA LETTER MU +U+3081(2,3);U+3081(2,3); # 04-65, HIRAGANA LETTER ME +U+3082(2,3);U+3082(2,3); # 04-66, HIRAGANA LETTER MO +U+3083(2,3);U+3083(2,3); # 04-67, HIRAGANA LETTER SMALL YA +U+3084(2,3);U+3084(2,3); # 04-68, HIRAGANA LETTER YA +U+3085(2,3);U+3085(2,3); # 04-69, HIRAGANA LETTER SMALL YU +U+3086(2,3);U+3086(2,3); # 04-70, HIRAGANA LETTER YU +U+3087(2,3);U+3087(2,3); # 04-71, HIRAGANA LETTER SMALL YO +U+3088(2,3);U+3088(2,3); # 04-72, HIRAGANA LETTER YO +U+3089(2,3);U+3089(2,3); # 04-73, HIRAGANA LETTER RA +U+308A(2,3);U+308A(2,3); # 04-74, HIRAGANA LETTER RI +U+308B(2,3);U+308B(2,3); # 04-75, HIRAGANA LETTER RU +U+308C(2,3);U+308C(2,3); # 04-76, HIRAGANA LETTER RE +U+308D(2,3);U+308D(2,3); # 04-77, HIRAGANA LETTER RO +U+308E(2,3);U+308E(2,3); # 04-78, HIRAGANA LETTER SMALL WA +U+308F(2,3);U+308F(2,3); # 04-79, HIRAGANA LETTER WA +U+3090(2,3);U+3090(2,3); # 04-80, HIRAGANA LETTER WI +U+3091(2,3);U+3091(2,3); # 04-81, HIRAGANA LETTER WE +U+3092(2,3);U+3092(2,3); # 04-82, HIRAGANA LETTER WO +U+3093(2,3);U+3093(2,3); # 04-83, HIRAGANA LETTER N +U+309D(2,3);U+309D(2,3); # 01-21, HIRAGANA ITERATION MARK +U+309E(2,3);U+309E(2,3); # 01-22, HIRAGANA VOICED ITERATION MARK +U+30A1(2,3);U+30A1(2,3); # 05-01, KATAKANA LETTER SMALL A +U+30A2(2,3);U+30A2(2,3); # 05-02, KATAKANA LETTER A +U+30A3(2,3);U+30A3(2,3); # 05-03, KATAKANA LETTER SMALL I +U+30A4(2,3);U+30A4(2,3); # 05-04, KATAKANA LETTER I +U+30A5(2,3);U+30A5(2,3); # 05-05, KATAKANA LETTER SMALL U +U+30A6(2,3);U+30A6(2,3); # 05-06, KATAKANA LETTER U +U+30A7(2,3);U+30A7(2,3); # 05-07, KATAKANA LETTER SMALL E +U+30A8(2,3);U+30A8(2,3); # 05-08, KATAKANA LETTER E +U+30A9(2,3);U+30A9(2,3); # 05-09, KATAKANA LETTER SMALL O +U+30AA(2,3);U+30AA(2,3); # 05-10, KATAKANA LETTER O +U+30AB(2,3);U+30AB(2,3); # 05-11, KATAKANA LETTER KA +U+30AC(2,3);U+30AC(2,3); # 05-12, KATAKANA LETTER GA +U+30AD(2,3);U+30AD(2,3); # 05-13, KATAKANA LETTER KI +U+30AE(2,3);U+30AE(2,3); # 05-14, KATAKANA LETTER GI +U+30AF(2,3);U+30AF(2,3); # 05-15, KATAKANA LETTER KU +U+30B0(2,3);U+30B0(2,3); # 05-16, KATAKANA LETTER GU +U+30B1(2,3);U+30B1(2,3); # 05-17, KATAKANA LETTER KE +U+30B2(2,3);U+30B2(2,3); # 05-18, KATAKANA LETTER GE +U+30B3(2,3);U+30B3(2,3); # 05-19, KATAKANA LETTER KO +U+30B4(2,3);U+30B4(2,3); # 05-20, KATAKANA LETTER GO +U+30B5(2,3);U+30B5(2,3); # 05-21, KATAKANA LETTER SA +U+30B6(2,3);U+30B6(2,3); # 05-22, KATAKANA LETTER ZA +U+30B7(2,3);U+30B7(2,3); # 05-23, KATAKANA LETTER SI +U+30B8(2,3);U+30B8(2,3); # 05-24, KATAKANA LETTER ZI +U+30B9(2,3);U+30B9(2,3); # 05-25, KATAKANA LETTER SU +U+30BA(2,3);U+30BA(2,3); # 05-26, KATAKANA LETTER ZU +U+30BB(2,3);U+30BB(2,3); # 05-27, KATAKANA LETTER SE +U+30BC(2,3);U+30BC(2,3); # 05-28, KATAKANA LETTER ZE +U+30BD(2,3);U+30BD(2,3); # 05-29, KATAKANA LETTER SO +U+30BE(2,3);U+30BE(2,3); # 05-30, KATAKANA LETTER ZO +U+30BF(2,3);U+30BF(2,3); # 05-31, KATAKANA LETTER TA +U+30C0(2,3);U+30C0(2,3); # 05-32, KATAKANA LETTER DA +U+30C1(2,3);U+30C1(2,3); # 05-33, KATAKANA LETTER TI +U+30C2(2,3);U+30C2(2,3); # 05-34, KATAKANA LETTER DI +U+30C3(2,3);U+30C3(2,3); # 05-35, KATAKANA LETTER SMALL TU +U+30C4(2,3);U+30C4(2,3); # 05-36, KATAKANA LETTER TU +U+30C5(2,3);U+30C5(2,3); # 05-37, KATAKANA LETTER DU +U+30C6(2,3);U+30C6(2,3); # 05-38, KATAKANA LETTER TE +U+30C7(2,3);U+30C7(2,3); # 05-39, KATAKANA LETTER DE +U+30C8(2,3);U+30C8(2,3); # 05-40, KATAKANA LETTER TO +U+30C9(2,3);U+30C9(2,3); # 05-41, KATAKANA LETTER DO +U+30CA(2,3);U+30CA(2,3); # 05-42, KATAKANA LETTER NA +U+30CB(2,3);U+30CB(2,3); # 05-43, KATAKANA LETTER NI +U+30CC(2,3);U+30CC(2,3); # 05-44, KATAKANA LETTER NU +U+30CD(2,3);U+30CD(2,3); # 05-45, KATAKANA LETTER NE +U+30CE(2,3);U+30CE(2,3); # 05-46, KATAKANA LETTER NO +U+30CF(2,3);U+30CF(2,3); # 05-47, KATAKANA LETTER HA +U+30D0(2,3);U+30D0(2,3); # 05-48, KATAKANA LETTER BA +U+30D1(2,3);U+30D1(2,3); # 05-49, KATAKANA LETTER PA +U+30D2(2,3);U+30D2(2,3); # 05-50, KATAKANA LETTER HI +U+30D3(2,3);U+30D3(2,3); # 05-51, KATAKANA LETTER BI +U+30D4(2,3);U+30D4(2,3); # 05-52, KATAKANA LETTER PI +U+30D5(2,3);U+30D5(2,3); # 05-53, KATAKANA LETTER HU +U+30D6(2,3);U+30D6(2,3); # 05-54, KATAKANA LETTER BU +U+30D7(2,3);U+30D7(2,3); # 05-55, KATAKANA LETTER PU +U+30D8(2,3);U+30D8(2,3); # 05-56, KATAKANA LETTER HE +U+30D9(2,3);U+30D9(2,3); # 05-57, KATAKANA LETTER BE +U+30DA(2,3);U+30DA(2,3); # 05-58, KATAKANA LETTER PE +U+30DB(2,3);U+30DB(2,3); # 05-59, KATAKANA LETTER HO +U+30DC(2,3);U+30DC(2,3); # 05-60, KATAKANA LETTER BO +U+30DD(2,3);U+30DD(2,3); # 05-61, KATAKANA LETTER PO +U+30DE(2,3);U+30DE(2,3); # 05-62, KATAKANA LETTER MA +U+30DF(2,3);U+30DF(2,3); # 05-63, KATAKANA LETTER MI +U+30E0(2,3);U+30E0(2,3); # 05-64, KATAKANA LETTER MU +U+30E1(2,3);U+30E1(2,3); # 05-65, KATAKANA LETTER ME +U+30E2(2,3);U+30E2(2,3); # 05-66, KATAKANA LETTER MO +U+30E3(2,3);U+30E3(2,3); # 05-67, KATAKANA LETTER SMALL YA +U+30E4(2,3);U+30E4(2,3); # 05-68, KATAKANA LETTER YA +U+30E5(2,3);U+30E5(2,3); # 05-69, KATAKANA LETTER SMALL YU +U+30E6(2,3);U+30E6(2,3); # 05-70, KATAKANA LETTER YU +U+30E7(2,3);U+30E7(2,3); # 05-71, KATAKANA LETTER SMALL YO +U+30E8(2,3);U+30E8(2,3); # 05-72, KATAKANA LETTER YO +U+30E9(2,3);U+30E9(2,3); # 05-73, KATAKANA LETTER RA +U+30EA(2,3);U+30EA(2,3); # 05-74, KATAKANA LETTER RI +U+30EB(2,3);U+30EB(2,3); # 05-75, KATAKANA LETTER RU +U+30EC(2,3);U+30EC(2,3); # 05-76, KATAKANA LETTER RE +U+30ED(2,3);U+30ED(2,3); # 05-77, KATAKANA LETTER RO +U+30EE(2,3);U+30EE(2,3); # 05-78, KATAKANA LETTER SMALL WA +U+30EF(2,3);U+30EF(2,3); # 05-79, KATAKANA LETTER WA +U+30F0(2,3);U+30F0(2,3); # 05-80, KATAKANA LETTER WI +U+30F1(2,3);U+30F1(2,3); # 05-81, KATAKANA LETTER WE +U+30F2(2,3);U+30F2(2,3); # 05-82, KATAKANA LETTER WO +U+30F3(2,3);U+30F3(2,3); # 05-83, KATAKANA LETTER N +U+30F4(2,3);U+30F4(2,3); # 05-84, KATAKANA LETTER VU +U+30F5(2,3);U+30F5(2,3); # 05-85, KATAKANA LETTER SMALL KA +U+30F6(2,3);U+30F6(2,3); # 05-86, KATAKANA LETTER SMALL KE +U+30FB(2,3);U+30FB(2,3); # 01-06, KATAKANA MIDDLE DOT +U+30FC(2,3);U+30FC(2,3); # 01-28, KATAKANA-HIRAGANA PROLONGED SOUND MARK +U+30FD(2,3);U+30FD(2,3); # 01-19, KATAKANA ITERATION MARK +U+30FE(2,3);U+30FE(2,3); # 01-20, KATAKANA VOICED ITERATION MARK +U+4E00(2,3);U+4E00(2,3); # 16-76, CJK UNIFIED IDEOGRAPH-4E00 +U+4E01(2,3);U+4E01(2,3); # 35-90, CJK UNIFIED IDEOGRAPH-4E01 +U+4E03(2,3);U+4E03(2,3); # 28-23, CJK UNIFIED IDEOGRAPH-4E03 +U+4E07(2,3);U+4E07(2,3); # 43-92, CJK UNIFIED IDEOGRAPH-4E07 +U+4E08(2,3);U+4E08(2,3); # 30-70, CJK UNIFIED IDEOGRAPH-4E08 +U+4E09(2,3);U+4E09(2,3); # 27-16, CJK UNIFIED IDEOGRAPH-4E09 +U+4E0A(2,3);U+4E0A(2,3); # 30-69, CJK UNIFIED IDEOGRAPH-4E0A +U+4E0B(2,3);U+4E0B(2,3); # 18-28, CJK UNIFIED IDEOGRAPH-4E0B +U+4E0D(2,3);U+4E0D(2,3); # 41-52, CJK UNIFIED IDEOGRAPH-4E0D +U+4E0E(2,3);U+4E0E(2,3); # 45-31, CJK UNIFIED IDEOGRAPH-4E0E +U+4E10(2,3);U+4E10(2,3); # 48-02, CJK UNIFIED IDEOGRAPH-4E10 +U+4E11(2,3);U+4E11(2,3); # 17-15, CJK UNIFIED IDEOGRAPH-4E11 +U+4E14(2,3);U+4E14(2,3); # 19-78, CJK UNIFIED IDEOGRAPH-4E14 +U+4E15(2,3);U+4E15(2,3); # 48-03, CJK UNIFIED IDEOGRAPH-4E15 +U+4E16(2,3);U+4E16(2,3); # 32-04, CJK UNIFIED IDEOGRAPH-4E16 +U+4E17(2,3);U+4E17(2,3); # 50-34, CJK UNIFIED IDEOGRAPH-4E17 +U+4E18(2,3);U+4E18(2,3); # 21-54, CJK UNIFIED IDEOGRAPH-4E18 +U+4E19(2,3);U+4E19(2,3); # 42-26, CJK UNIFIED IDEOGRAPH-4E19 +U+4E1E(2,3);U+4E1E(2,3); # 30-71, CJK UNIFIED IDEOGRAPH-4E1E +U+4E21(2,3);U+4E21(2,3); # 46-30, CJK UNIFIED IDEOGRAPH-4E21 +U+4E26(2,3);U+4E26(2,3); # 42-34, CJK UNIFIED IDEOGRAPH-4E26 +U+4E2A(2,3);U+4E2A(2,3); # 48-04, CJK UNIFIED IDEOGRAPH-4E2A +U+4E2D(2,3);U+4E2D(2,3); # 35-70, CJK UNIFIED IDEOGRAPH-4E2D +U+4E31(2,3);U+4E31(2,3); # 48-05, CJK UNIFIED IDEOGRAPH-4E31 +U+4E32(2,3);U+4E32(2,3); # 22-90, CJK UNIFIED IDEOGRAPH-4E32 +U+4E36(2,3);U+4E36(2,3); # 48-06, CJK UNIFIED IDEOGRAPH-4E36 +U+4E38(2,3);U+4E38(2,3); # 20-61, CJK UNIFIED IDEOGRAPH-4E38 +U+4E39(2,3);U+4E39(2,3); # 35-16, CJK UNIFIED IDEOGRAPH-4E39 +U+4E3B(2,3);U+4E3B(2,3); # 28-71, CJK UNIFIED IDEOGRAPH-4E3B +U+4E3C(2,3);U+4E3C(2,3); # 48-07, CJK UNIFIED IDEOGRAPH-4E3C +U+4E3F(2,3);U+4E3F(2,3); # 48-08, CJK UNIFIED IDEOGRAPH-4E3F +U+4E42(2,3);U+4E42(2,3); # 48-09, CJK UNIFIED IDEOGRAPH-4E42 +U+4E43(2,3);U+4E43(2,3); # 39-21, CJK UNIFIED IDEOGRAPH-4E43 +U+4E45(2,3);U+4E45(2,3); # 21-55, CJK UNIFIED IDEOGRAPH-4E45 +U+4E4B(2,3);U+4E4B(2,3); # 39-23, CJK UNIFIED IDEOGRAPH-4E4B +U+4E4D(2,3);U+4E4D(2,3); # 38-67, CJK UNIFIED IDEOGRAPH-4E4D +U+4E4E(2,3);U+4E4E(2,3); # 24-35, CJK UNIFIED IDEOGRAPH-4E4E +U+4E4F(2,3);U+4E4F(2,3); # 43-19, CJK UNIFIED IDEOGRAPH-4E4F +U+4E55(2,3);U+4E55(2,3); # 73-41, CJK UNIFIED IDEOGRAPH-4E55 +U+4E56(2,3);U+4E56(2,3); # 48-10, CJK UNIFIED IDEOGRAPH-4E56 +U+4E57(2,3);U+4E57(2,3); # 30-72, CJK UNIFIED IDEOGRAPH-4E57 +U+4E58(2,3);U+4E58(2,3); # 48-11, CJK UNIFIED IDEOGRAPH-4E58 +U+4E59(2,3);U+4E59(2,3); # 18-21, CJK UNIFIED IDEOGRAPH-4E59 +U+4E5D(2,3);U+4E5D(2,3); # 22-69, CJK UNIFIED IDEOGRAPH-4E5D +U+4E5E(2,3);U+4E5E(2,3); # 24-80, CJK UNIFIED IDEOGRAPH-4E5E +U+4E5F(2,3);U+4E5F(2,3); # 44-73, CJK UNIFIED IDEOGRAPH-4E5F +U+4E62(2,3);U+4E62(2,3); # 54-06, CJK UNIFIED IDEOGRAPH-4E62 +U+4E71(2,3);U+4E71(2,3); # 45-80, CJK UNIFIED IDEOGRAPH-4E71 +U+4E73(2,3);U+4E73(2,3); # 38-93, CJK UNIFIED IDEOGRAPH-4E73 +U+4E7E(2,3);U+4E7E(2,3); # 20-05, CJK UNIFIED IDEOGRAPH-4E7E +U+4E80(2,3);U+4E80(2,3); # 21-21, CJK UNIFIED IDEOGRAPH-4E80 +U+4E82(2,3);U+4E82(2,3); # 48-12, CJK UNIFIED IDEOGRAPH-4E82 +U+4E85(2,3);U+4E85(2,3); # 48-13, CJK UNIFIED IDEOGRAPH-4E85 +U+4E86(2,3);U+4E86(2,3); # 46-27, CJK UNIFIED IDEOGRAPH-4E86 +U+4E88(2,3);U+4E88(2,3); # 45-29, CJK UNIFIED IDEOGRAPH-4E88 +U+4E89(2,3);U+4E89(2,3); # 33-72, CJK UNIFIED IDEOGRAPH-4E89 +U+4E8A(2,3);U+4E8A(2,3); # 48-15, CJK UNIFIED IDEOGRAPH-4E8A +U+4E8B(2,3);U+4E8B(2,3); # 27-86, CJK UNIFIED IDEOGRAPH-4E8B +U+4E8C(2,3);U+4E8C(2,3); # 38-83, CJK UNIFIED IDEOGRAPH-4E8C +U+4E8E(2,3);U+4E8E(2,3); # 48-18, CJK UNIFIED IDEOGRAPH-4E8E +U+4E91(2,3);U+4E91(2,3); # 17-30, CJK UNIFIED IDEOGRAPH-4E91 +U+4E92(2,3);U+4E92(2,3); # 24-63, CJK UNIFIED IDEOGRAPH-4E92 +U+4E94(2,3);U+4E94(2,3); # 24-62, CJK UNIFIED IDEOGRAPH-4E94 +U+4E95(2,3);U+4E95(2,3); # 16-70, CJK UNIFIED IDEOGRAPH-4E95 +U+4E98(2,3);U+4E98(2,3); # 47-43, CJK UNIFIED IDEOGRAPH-4E98 +U+4E99(2,3);U+4E99(2,3); # 47-42, CJK UNIFIED IDEOGRAPH-4E99 +U+4E9B(2,3);U+4E9B(2,3); # 26-19, CJK UNIFIED IDEOGRAPH-4E9B +U+4E9C(2,3);U+4E9C(2,3); # 16-01, CJK UNIFIED IDEOGRAPH-4E9C +U+4E9E(2,3);U+4E9E(2,3); # 48-19, CJK UNIFIED IDEOGRAPH-4E9E +U+4E9F(2,3);U+4E9F(2,3); # 48-20, CJK UNIFIED IDEOGRAPH-4E9F +U+4EA0(2,3);U+4EA0(2,3); # 48-21, CJK UNIFIED IDEOGRAPH-4EA0 +U+4EA1(2,3);U+4EA1(2,3); # 43-20, CJK UNIFIED IDEOGRAPH-4EA1 +U+4EA2(2,3);U+4EA2(2,3); # 48-22, CJK UNIFIED IDEOGRAPH-4EA2 +U+4EA4(2,3);U+4EA4(2,3); # 24-82, CJK UNIFIED IDEOGRAPH-4EA4 +U+4EA5(2,3);U+4EA5(2,3); # 16-71, CJK UNIFIED IDEOGRAPH-4EA5 +U+4EA6(2,3);U+4EA6(2,3); # 43-82, CJK UNIFIED IDEOGRAPH-4EA6 +U+4EA8(2,3);U+4EA8(2,3); # 21-92, CJK UNIFIED IDEOGRAPH-4EA8 +U+4EAB(2,3);U+4EAB(2,3); # 21-93, CJK UNIFIED IDEOGRAPH-4EAB +U+4EAC(2,3);U+4EAC(2,3); # 21-94, CJK UNIFIED IDEOGRAPH-4EAC +U+4EAD(2,3);U+4EAD(2,3); # 36-66, CJK UNIFIED IDEOGRAPH-4EAD +U+4EAE(2,3);U+4EAE(2,3); # 46-28, CJK UNIFIED IDEOGRAPH-4EAE +U+4EB0(2,3);U+4EB0(2,3); # 48-23, CJK UNIFIED IDEOGRAPH-4EB0 +U+4EB3(2,3);U+4EB3(2,3); # 48-24, CJK UNIFIED IDEOGRAPH-4EB3 +U+4EB6(2,3);U+4EB6(2,3); # 48-25, CJK UNIFIED IDEOGRAPH-4EB6 +U+4EBA(2,3);U+4EBA(2,3); # 31-45, CJK UNIFIED IDEOGRAPH-4EBA +U+4EC0(2,3);U+4EC0(2,3); # 29-26, CJK UNIFIED IDEOGRAPH-4EC0 +U+4EC1(2,3);U+4EC1(2,3); # 31-46, CJK UNIFIED IDEOGRAPH-4EC1 +U+4EC2(2,3);U+4EC2(2,3); # 48-30, CJK UNIFIED IDEOGRAPH-4EC2 +U+4EC4(2,3);U+4EC4(2,3); # 48-28, CJK UNIFIED IDEOGRAPH-4EC4 +U+4EC6(2,3);U+4EC6(2,3); # 48-29, CJK UNIFIED IDEOGRAPH-4EC6 +U+4EC7(2,3);U+4EC7(2,3); # 21-56, CJK UNIFIED IDEOGRAPH-4EC7 +U+4ECA(2,3);U+4ECA(2,3); # 26-03, CJK UNIFIED IDEOGRAPH-4ECA +U+4ECB(2,3);U+4ECB(2,3); # 18-80, CJK UNIFIED IDEOGRAPH-4ECB +U+4ECD(2,3);U+4ECD(2,3); # 48-27, CJK UNIFIED IDEOGRAPH-4ECD +U+4ECE(2,3);U+4ECE(2,3); # 48-26, CJK UNIFIED IDEOGRAPH-4ECE +U+4ECF(2,3);U+4ECF(2,3); # 42-09, CJK UNIFIED IDEOGRAPH-4ECF +U+4ED4(2,3);U+4ED4(2,3); # 27-38, CJK UNIFIED IDEOGRAPH-4ED4 +U+4ED5(2,3);U+4ED5(2,3); # 27-37, CJK UNIFIED IDEOGRAPH-4ED5 +U+4ED6(2,3);U+4ED6(2,3); # 34-30, CJK UNIFIED IDEOGRAPH-4ED6 +U+4ED7(2,3);U+4ED7(2,3); # 48-31, CJK UNIFIED IDEOGRAPH-4ED7 +U+4ED8(2,3);U+4ED8(2,3); # 41-53, CJK UNIFIED IDEOGRAPH-4ED8 +U+4ED9(2,3);U+4ED9(2,3); # 32-71, CJK UNIFIED IDEOGRAPH-4ED9 +U+4EDD(2,3);U+4EDD(2,3); # 01-24, CJK UNIFIED IDEOGRAPH-4EDD +U+4EDE(2,3);U+4EDE(2,3); # 48-32, CJK UNIFIED IDEOGRAPH-4EDE +U+4EDF(2,3);U+4EDF(2,3); # 48-34, CJK UNIFIED IDEOGRAPH-4EDF +U+4EE3(2,3);U+4EE3(2,3); # 34-69, CJK UNIFIED IDEOGRAPH-4EE3 +U+4EE4(2,3);U+4EE4(2,3); # 46-65, CJK UNIFIED IDEOGRAPH-4EE4 +U+4EE5(2,3);U+4EE5(2,3); # 16-42, CJK UNIFIED IDEOGRAPH-4EE5 +U+4EED(2,3);U+4EED(2,3); # 48-33, CJK UNIFIED IDEOGRAPH-4EED +U+4EEE(2,3);U+4EEE(2,3); # 18-30, CJK UNIFIED IDEOGRAPH-4EEE +U+4EF0(2,3);U+4EF0(2,3); # 22-36, CJK UNIFIED IDEOGRAPH-4EF0 +U+4EF2(2,3);U+4EF2(2,3); # 35-71, CJK UNIFIED IDEOGRAPH-4EF2 +U+4EF6(2,3);U+4EF6(2,3); # 23-79, CJK UNIFIED IDEOGRAPH-4EF6 +U+4EF7(2,3);U+4EF7(2,3); # 48-35, CJK UNIFIED IDEOGRAPH-4EF7 +U+4EFB(2,3);U+4EFB(2,3); # 39-04, CJK UNIFIED IDEOGRAPH-4EFB +U+4F01(2,3);U+4F01(2,3); # 20-75, CJK UNIFIED IDEOGRAPH-4F01 +U+4F09(2,3);U+4F09(2,3); # 48-36, CJK UNIFIED IDEOGRAPH-4F09 +U+4F0A(2,3);U+4F0A(2,3); # 16-43, CJK UNIFIED IDEOGRAPH-4F0A +U+4F0D(2,3);U+4F0D(2,3); # 24-64, CJK UNIFIED IDEOGRAPH-4F0D +U+4F0E(2,3);U+4F0E(2,3); # 20-76, CJK UNIFIED IDEOGRAPH-4F0E +U+4F0F(2,3);U+4F0F(2,3); # 41-90, CJK UNIFIED IDEOGRAPH-4F0F +U+4F10(2,3);U+4F10(2,3); # 40-18, CJK UNIFIED IDEOGRAPH-4F10 +U+4F11(2,3);U+4F11(2,3); # 21-57, CJK UNIFIED IDEOGRAPH-4F11 +U+4F1A(2,3);U+4F1A(2,3); # 18-81, CJK UNIFIED IDEOGRAPH-4F1A +U+4F1C(2,3);U+4F1C(2,3); # 48-71, CJK UNIFIED IDEOGRAPH-4F1C +U+4F1D(2,3);U+4F1D(2,3); # 37-33, CJK UNIFIED IDEOGRAPH-4F1D +U+4F2F(2,3);U+4F2F(2,3); # 39-76, CJK UNIFIED IDEOGRAPH-4F2F +U+4F30(2,3);U+4F30(2,3); # 48-38, CJK UNIFIED IDEOGRAPH-4F30 +U+4F34(2,3);U+4F34(2,3); # 40-28, CJK UNIFIED IDEOGRAPH-4F34 +U+4F36(2,3);U+4F36(2,3); # 46-66, CJK UNIFIED IDEOGRAPH-4F36 +U+4F38(2,3);U+4F38(2,3); # 31-13, CJK UNIFIED IDEOGRAPH-4F38 +U+4F3A(2,3);U+4F3A(2,3); # 27-39, CJK UNIFIED IDEOGRAPH-4F3A +U+4F3C(2,3);U+4F3C(2,3); # 27-87, CJK UNIFIED IDEOGRAPH-4F3C +U+4F3D(2,3);U+4F3D(2,3); # 18-32, CJK UNIFIED IDEOGRAPH-4F3D +U+4F43(2,3);U+4F43(2,3); # 36-49, CJK UNIFIED IDEOGRAPH-4F43 +U+4F46(2,3);U+4F46(2,3); # 35-02, CJK UNIFIED IDEOGRAPH-4F46 +U+4F47(2,3);U+4F47(2,3); # 48-42, CJK UNIFIED IDEOGRAPH-4F47 +U+4F4D(2,3);U+4F4D(2,3); # 16-44, CJK UNIFIED IDEOGRAPH-4F4D +U+4F4E(2,3);U+4F4E(2,3); # 36-67, CJK UNIFIED IDEOGRAPH-4F4E +U+4F4F(2,3);U+4F4F(2,3); # 29-27, CJK UNIFIED IDEOGRAPH-4F4F +U+4F50(2,3);U+4F50(2,3); # 26-20, CJK UNIFIED IDEOGRAPH-4F50 +U+4F51(2,3);U+4F51(2,3); # 45-04, CJK UNIFIED IDEOGRAPH-4F51 +U+4F53(2,3);U+4F53(2,3); # 34-46, CJK UNIFIED IDEOGRAPH-4F53 +U+4F55(2,3);U+4F55(2,3); # 18-31, CJK UNIFIED IDEOGRAPH-4F55 +U+4F57(2,3);U+4F57(2,3); # 48-41, CJK UNIFIED IDEOGRAPH-4F57 +U+4F59(2,3);U+4F59(2,3); # 45-30, CJK UNIFIED IDEOGRAPH-4F59 +U+4F5A(2,3);U+4F5A(2,3); # 48-37, CJK UNIFIED IDEOGRAPH-4F5A +U+4F5B(2,3);U+4F5B(2,3); # 48-39, CJK UNIFIED IDEOGRAPH-4F5B +U+4F5C(2,3);U+4F5C(2,3); # 26-78, CJK UNIFIED IDEOGRAPH-4F5C +U+4F5D(2,3);U+4F5D(2,3); # 48-40, CJK UNIFIED IDEOGRAPH-4F5D +U+4F5E(2,3);U+4F5E(2,3); # 53-04, CJK UNIFIED IDEOGRAPH-4F5E +U+4F69(2,3);U+4F69(2,3); # 48-48, CJK UNIFIED IDEOGRAPH-4F69 +U+4F6F(2,3);U+4F6F(2,3); # 48-51, CJK UNIFIED IDEOGRAPH-4F6F +U+4F70(2,3);U+4F70(2,3); # 48-49, CJK UNIFIED IDEOGRAPH-4F70 +U+4F73(2,3);U+4F73(2,3); # 18-34, CJK UNIFIED IDEOGRAPH-4F73 +U+4F75(2,3);U+4F75(2,3); # 42-27, CJK UNIFIED IDEOGRAPH-4F75 +U+4F76(2,3);U+4F76(2,3); # 48-43, CJK UNIFIED IDEOGRAPH-4F76 +U+4F7B(2,3);U+4F7B(2,3); # 48-47, CJK UNIFIED IDEOGRAPH-4F7B +U+4F7C(2,3);U+4F7C(2,3); # 24-83, CJK UNIFIED IDEOGRAPH-4F7C +U+4F7F(2,3);U+4F7F(2,3); # 27-40, CJK UNIFIED IDEOGRAPH-4F7F +U+4F83(2,3);U+4F83(2,3); # 20-06, CJK UNIFIED IDEOGRAPH-4F83 +U+4F86(2,3);U+4F86(2,3); # 48-52, CJK UNIFIED IDEOGRAPH-4F86 +U+4F88(2,3);U+4F88(2,3); # 48-44, CJK UNIFIED IDEOGRAPH-4F88 +U+4F8B(2,3);U+4F8B(2,3); # 46-67, CJK UNIFIED IDEOGRAPH-4F8B +U+4F8D(2,3);U+4F8D(2,3); # 27-88, CJK UNIFIED IDEOGRAPH-4F8D +U+4F8F(2,3);U+4F8F(2,3); # 48-45, CJK UNIFIED IDEOGRAPH-4F8F +U+4F91(2,3);U+4F91(2,3); # 48-50, CJK UNIFIED IDEOGRAPH-4F91 +U+4F96(2,3);U+4F96(2,3); # 48-53, CJK UNIFIED IDEOGRAPH-4F96 +U+4F98(2,3);U+4F98(2,3); # 48-46, CJK UNIFIED IDEOGRAPH-4F98 +U+4F9B(2,3);U+4F9B(2,3); # 22-01, CJK UNIFIED IDEOGRAPH-4F9B +U+4F9D(2,3);U+4F9D(2,3); # 16-45, CJK UNIFIED IDEOGRAPH-4F9D +U+4FA0(2,3);U+4FA0(2,3); # 22-02, CJK UNIFIED IDEOGRAPH-4FA0 +U+4FA1(2,3);U+4FA1(2,3); # 18-33, CJK UNIFIED IDEOGRAPH-4FA1 +U+4FAB(2,3);U+4FAB(2,3); # 53-05, CJK UNIFIED IDEOGRAPH-4FAB +U+4FAD(2,3);U+4FAD(2,3); # 43-89, CJK UNIFIED IDEOGRAPH-4FAD +U+4FAE(2,3);U+4FAE(2,3); # 41-78, CJK UNIFIED IDEOGRAPH-4FAE +U+4FAF(2,3);U+4FAF(2,3); # 24-84, CJK UNIFIED IDEOGRAPH-4FAF +U+4FB5(2,3);U+4FB5(2,3); # 31-15, CJK UNIFIED IDEOGRAPH-4FB5 +U+4FB6(2,3);U+4FB6(2,3); # 46-23, CJK UNIFIED IDEOGRAPH-4FB6 +U+4FBF(2,3);U+4FBF(2,3); # 42-56, CJK UNIFIED IDEOGRAPH-4FBF +U+4FC2(2,3);U+4FC2(2,3); # 23-24, CJK UNIFIED IDEOGRAPH-4FC2 +U+4FC3(2,3);U+4FC3(2,3); # 34-05, CJK UNIFIED IDEOGRAPH-4FC3 +U+4FC4(2,3);U+4FC4(2,3); # 18-68, CJK UNIFIED IDEOGRAPH-4FC4 +U+4FCA(2,3);U+4FCA(2,3); # 29-51, CJK UNIFIED IDEOGRAPH-4FCA +U+4FCE(2,3);U+4FCE(2,3); # 48-57, CJK UNIFIED IDEOGRAPH-4FCE +U+4FD0(2,3);U+4FD0(2,3); # 48-62, CJK UNIFIED IDEOGRAPH-4FD0 +U+4FD1(2,3);U+4FD1(2,3); # 48-60, CJK UNIFIED IDEOGRAPH-4FD1 +U+4FD4(2,3);U+4FD4(2,3); # 48-55, CJK UNIFIED IDEOGRAPH-4FD4 +U+4FD7(2,3);U+4FD7(2,3); # 34-15, CJK UNIFIED IDEOGRAPH-4FD7 +U+4FD8(2,3);U+4FD8(2,3); # 48-58, CJK UNIFIED IDEOGRAPH-4FD8 +U+4FDA(2,3);U+4FDA(2,3); # 48-61, CJK UNIFIED IDEOGRAPH-4FDA +U+4FDB(2,3);U+4FDB(2,3); # 48-59, CJK UNIFIED IDEOGRAPH-4FDB +U+4FDD(2,3);U+4FDD(2,3); # 42-61, CJK UNIFIED IDEOGRAPH-4FDD +U+4FDF(2,3);U+4FDF(2,3); # 48-56, CJK UNIFIED IDEOGRAPH-4FDF +U+4FE1(2,3);U+4FE1(2,3); # 31-14, CJK UNIFIED IDEOGRAPH-4FE1 +U+4FE3(2,3);U+4FE3(2,3); # 43-83, CJK UNIFIED IDEOGRAPH-4FE3 +U+4FE4(2,3);U+4FE4(2,3); # 48-63, CJK UNIFIED IDEOGRAPH-4FE4 +U+4FE5(2,3);U+4FE5(2,3); # 48-64, CJK UNIFIED IDEOGRAPH-4FE5 +U+4FEE(2,3);U+4FEE(2,3); # 29-04, CJK UNIFIED IDEOGRAPH-4FEE +U+4FEF(2,3);U+4FEF(2,3); # 48-77, CJK UNIFIED IDEOGRAPH-4FEF +U+4FF3(2,3);U+4FF3(2,3); # 39-48, CJK UNIFIED IDEOGRAPH-4FF3 +U+4FF5(2,3);U+4FF5(2,3); # 41-22, CJK UNIFIED IDEOGRAPH-4FF5 +U+4FF6(2,3);U+4FF6(2,3); # 48-72, CJK UNIFIED IDEOGRAPH-4FF6 +U+4FF8(2,3);U+4FF8(2,3); # 42-80, CJK UNIFIED IDEOGRAPH-4FF8 +U+4FFA(2,3);U+4FFA(2,3); # 18-22, CJK UNIFIED IDEOGRAPH-4FFA +U+4FFE(2,3);U+4FFE(2,3); # 48-76, CJK UNIFIED IDEOGRAPH-4FFE +U+5005(2,3);U+5005(2,3); # 48-70, CJK UNIFIED IDEOGRAPH-5005 +U+5006(2,3);U+5006(2,3); # 48-79, CJK UNIFIED IDEOGRAPH-5006 +U+5009(2,3);U+5009(2,3); # 33-50, CJK UNIFIED IDEOGRAPH-5009 +U+500B(2,3);U+500B(2,3); # 24-36, CJK UNIFIED IDEOGRAPH-500B +U+500D(2,3);U+500D(2,3); # 39-60, CJK UNIFIED IDEOGRAPH-500D +U+500F(2,3);U+500F(2,3); # 64-39, CJK UNIFIED IDEOGRAPH-500F +U+5011(2,3);U+5011(2,3); # 48-78, CJK UNIFIED IDEOGRAPH-5011 +U+5012(2,3);U+5012(2,3); # 37-61, CJK UNIFIED IDEOGRAPH-5012 +U+5014(2,3);U+5014(2,3); # 48-67, CJK UNIFIED IDEOGRAPH-5014 +U+5016(2,3);U+5016(2,3); # 24-86, CJK UNIFIED IDEOGRAPH-5016 +U+5019(2,3);U+5019(2,3); # 24-85, CJK UNIFIED IDEOGRAPH-5019 +U+501A(2,3);U+501A(2,3); # 48-65, CJK UNIFIED IDEOGRAPH-501A +U+501F(2,3);U+501F(2,3); # 28-58, CJK UNIFIED IDEOGRAPH-501F +U+5021(2,3);U+5021(2,3); # 48-73, CJK UNIFIED IDEOGRAPH-5021 +U+5023(2,3);U+5023(2,3); # 42-79, CJK UNIFIED IDEOGRAPH-5023 +U+5024(2,3);U+5024(2,3); # 35-45, CJK UNIFIED IDEOGRAPH-5024 +U+5025(2,3);U+5025(2,3); # 48-69, CJK UNIFIED IDEOGRAPH-5025 +U+5026(2,3);U+5026(2,3); # 23-81, CJK UNIFIED IDEOGRAPH-5026 +U+5028(2,3);U+5028(2,3); # 48-66, CJK UNIFIED IDEOGRAPH-5028 +U+5029(2,3);U+5029(2,3); # 48-74, CJK UNIFIED IDEOGRAPH-5029 +U+502A(2,3);U+502A(2,3); # 48-68, CJK UNIFIED IDEOGRAPH-502A +U+502B(2,3);U+502B(2,3); # 46-49, CJK UNIFIED IDEOGRAPH-502B +U+502C(2,3);U+502C(2,3); # 48-75, CJK UNIFIED IDEOGRAPH-502C +U+502D(2,3);U+502D(2,3); # 47-33, CJK UNIFIED IDEOGRAPH-502D +U+5036(2,3);U+5036(2,3); # 22-70, CJK UNIFIED IDEOGRAPH-5036 +U+5039(2,3);U+5039(2,3); # 23-80, CJK UNIFIED IDEOGRAPH-5039 +U+5043(2,3);U+5043(2,3); # 48-80, CJK UNIFIED IDEOGRAPH-5043 +U+5047(2,3);U+5047(2,3); # 48-81, CJK UNIFIED IDEOGRAPH-5047 +U+5048(2,3);U+5048(2,3); # 48-85, CJK UNIFIED IDEOGRAPH-5048 +U+5049(2,3);U+5049(2,3); # 16-46, CJK UNIFIED IDEOGRAPH-5049 +U+504F(2,3);U+504F(2,3); # 42-48, CJK UNIFIED IDEOGRAPH-504F +U+5050(2,3);U+5050(2,3); # 48-84, CJK UNIFIED IDEOGRAPH-5050 +U+5055(2,3);U+5055(2,3); # 48-83, CJK UNIFIED IDEOGRAPH-5055 +U+5056(2,3);U+5056(2,3); # 48-87, CJK UNIFIED IDEOGRAPH-5056 +U+505A(2,3);U+505A(2,3); # 48-86, CJK UNIFIED IDEOGRAPH-505A +U+505C(2,3);U+505C(2,3); # 36-68, CJK UNIFIED IDEOGRAPH-505C +U+5065(2,3);U+5065(2,3); # 23-82, CJK UNIFIED IDEOGRAPH-5065 +U+506C(2,3);U+506C(2,3); # 48-88, CJK UNIFIED IDEOGRAPH-506C +U+5072(2,3);U+5072(2,3); # 28-37, CJK UNIFIED IDEOGRAPH-5072 +U+5074(2,3);U+5074(2,3); # 34-06, CJK UNIFIED IDEOGRAPH-5074 +U+5075(2,3);U+5075(2,3); # 36-69, CJK UNIFIED IDEOGRAPH-5075 +U+5076(2,3);U+5076(2,3); # 22-86, CJK UNIFIED IDEOGRAPH-5076 +U+5078(2,3);U+5078(2,3); # 48-89, CJK UNIFIED IDEOGRAPH-5078 +U+507D(2,3);U+507D(2,3); # 21-22, CJK UNIFIED IDEOGRAPH-507D +U+5080(2,3);U+5080(2,3); # 48-90, CJK UNIFIED IDEOGRAPH-5080 +U+5085(2,3);U+5085(2,3); # 48-92, CJK UNIFIED IDEOGRAPH-5085 +U+508D(2,3);U+508D(2,3); # 43-21, CJK UNIFIED IDEOGRAPH-508D +U+5091(2,3);U+5091(2,3); # 23-70, CJK UNIFIED IDEOGRAPH-5091 +U+5098(2,3);U+5098(2,3); # 27-17, CJK UNIFIED IDEOGRAPH-5098 +U+5099(2,3);U+5099(2,3); # 40-87, CJK UNIFIED IDEOGRAPH-5099 +U+509A(2,3);U+509A(2,3); # 48-91, CJK UNIFIED IDEOGRAPH-509A +U+50AC(2,3);U+50AC(2,3); # 26-37, CJK UNIFIED IDEOGRAPH-50AC +U+50AD(2,3);U+50AD(2,3); # 45-35, CJK UNIFIED IDEOGRAPH-50AD +U+50B2(2,3);U+50B2(2,3); # 48-94, CJK UNIFIED IDEOGRAPH-50B2 +U+50B3(2,3);U+50B3(2,3); # 49-03, CJK UNIFIED IDEOGRAPH-50B3 +U+50B4(2,3);U+50B4(2,3); # 48-93, CJK UNIFIED IDEOGRAPH-50B4 +U+50B5(2,3);U+50B5(2,3); # 26-36, CJK UNIFIED IDEOGRAPH-50B5 +U+50B7(2,3);U+50B7(2,3); # 29-93, CJK UNIFIED IDEOGRAPH-50B7 +U+50BE(2,3);U+50BE(2,3); # 23-25, CJK UNIFIED IDEOGRAPH-50BE +U+50C2(2,3);U+50C2(2,3); # 49-04, CJK UNIFIED IDEOGRAPH-50C2 +U+50C5(2,3);U+50C5(2,3); # 22-47, CJK UNIFIED IDEOGRAPH-50C5 +U+50C9(2,3);U+50C9(2,3); # 49-01, CJK UNIFIED IDEOGRAPH-50C9 +U+50CA(2,3);U+50CA(2,3); # 49-02, CJK UNIFIED IDEOGRAPH-50CA +U+50CD(2,3);U+50CD(2,3); # 38-15, CJK UNIFIED IDEOGRAPH-50CD +U+50CF(2,3);U+50CF(2,3); # 33-92, CJK UNIFIED IDEOGRAPH-50CF +U+50D1(2,3);U+50D1(2,3); # 22-03, CJK UNIFIED IDEOGRAPH-50D1 +U+50D5(2,3);U+50D5(2,3); # 43-45, CJK UNIFIED IDEOGRAPH-50D5 +U+50D6(2,3);U+50D6(2,3); # 49-05, CJK UNIFIED IDEOGRAPH-50D6 +U+50DA(2,3);U+50DA(2,3); # 46-29, CJK UNIFIED IDEOGRAPH-50DA +U+50DE(2,3);U+50DE(2,3); # 49-06, CJK UNIFIED IDEOGRAPH-50DE +U+50E3(2,3);U+50E3(2,3); # 49-09, CJK UNIFIED IDEOGRAPH-50E3 +U+50E5(2,3);U+50E5(2,3); # 49-07, CJK UNIFIED IDEOGRAPH-50E5 +U+50E7(2,3);U+50E7(2,3); # 33-46, CJK UNIFIED IDEOGRAPH-50E7 +U+50ED(2,3);U+50ED(2,3); # 49-08, CJK UNIFIED IDEOGRAPH-50ED +U+50EE(2,3);U+50EE(2,3); # 49-10, CJK UNIFIED IDEOGRAPH-50EE +U+50F5(2,3);U+50F5(2,3); # 49-12, CJK UNIFIED IDEOGRAPH-50F5 +U+50F9(2,3);U+50F9(2,3); # 49-11, CJK UNIFIED IDEOGRAPH-50F9 +U+50FB(2,3);U+50FB(2,3); # 42-40, CJK UNIFIED IDEOGRAPH-50FB +U+5100(2,3);U+5100(2,3); # 21-23, CJK UNIFIED IDEOGRAPH-5100 +U+5101(2,3);U+5101(2,3); # 49-14, CJK UNIFIED IDEOGRAPH-5101 +U+5102(2,3);U+5102(2,3); # 49-15, CJK UNIFIED IDEOGRAPH-5102 +U+5104(2,3);U+5104(2,3); # 18-15, CJK UNIFIED IDEOGRAPH-5104 +U+5109(2,3);U+5109(2,3); # 49-13, CJK UNIFIED IDEOGRAPH-5109 +U+5112(2,3);U+5112(2,3); # 28-84, CJK UNIFIED IDEOGRAPH-5112 +U+5114(2,3);U+5114(2,3); # 49-18, CJK UNIFIED IDEOGRAPH-5114 +U+5115(2,3);U+5115(2,3); # 49-17, CJK UNIFIED IDEOGRAPH-5115 +U+5116(2,3);U+5116(2,3); # 49-16, CJK UNIFIED IDEOGRAPH-5116 +U+5118(2,3);U+5118(2,3); # 48-54, CJK UNIFIED IDEOGRAPH-5118 +U+511A(2,3);U+511A(2,3); # 49-19, CJK UNIFIED IDEOGRAPH-511A +U+511F(2,3);U+511F(2,3); # 29-94, CJK UNIFIED IDEOGRAPH-511F +U+5121(2,3);U+5121(2,3); # 49-20, CJK UNIFIED IDEOGRAPH-5121 +U+512A(2,3);U+512A(2,3); # 45-05, CJK UNIFIED IDEOGRAPH-512A +U+5132(2,3);U+5132(2,3); # 44-57, CJK UNIFIED IDEOGRAPH-5132 +U+5137(2,3);U+5137(2,3); # 49-22, CJK UNIFIED IDEOGRAPH-5137 +U+513A(2,3);U+513A(2,3); # 49-21, CJK UNIFIED IDEOGRAPH-513A +U+513B(2,3);U+513B(2,3); # 49-24, CJK UNIFIED IDEOGRAPH-513B +U+513C(2,3);U+513C(2,3); # 49-23, CJK UNIFIED IDEOGRAPH-513C +U+513F(2,3);U+513F(2,3); # 49-25, CJK UNIFIED IDEOGRAPH-513F +U+5140(2,3);U+5140(2,3); # 49-26, CJK UNIFIED IDEOGRAPH-5140 +U+5141(2,3);U+5141(2,3); # 16-84, CJK UNIFIED IDEOGRAPH-5141 +U+5143(2,3);U+5143(2,3); # 24-21, CJK UNIFIED IDEOGRAPH-5143 +U+5144(2,3);U+5144(2,3); # 23-27, CJK UNIFIED IDEOGRAPH-5144 +U+5145(2,3);U+5145(2,3); # 29-28, CJK UNIFIED IDEOGRAPH-5145 +U+5146(2,3);U+5146(2,3); # 35-91, CJK UNIFIED IDEOGRAPH-5146 +U+5147(2,3);U+5147(2,3); # 22-04, CJK UNIFIED IDEOGRAPH-5147 +U+5148(2,3);U+5148(2,3); # 32-72, CJK UNIFIED IDEOGRAPH-5148 +U+5149(2,3);U+5149(2,3); # 24-87, CJK UNIFIED IDEOGRAPH-5149 +U+514B(2,3);U+514B(2,3); # 25-78, CJK UNIFIED IDEOGRAPH-514B +U+514C(2,3);U+514C(2,3); # 49-28, CJK UNIFIED IDEOGRAPH-514C +U+514D(2,3);U+514D(2,3); # 44-40, CJK UNIFIED IDEOGRAPH-514D +U+514E(2,3);U+514E(2,3); # 37-38, CJK UNIFIED IDEOGRAPH-514E +U+5150(2,3);U+5150(2,3); # 27-89, CJK UNIFIED IDEOGRAPH-5150 +U+5152(2,3);U+5152(2,3); # 49-27, CJK UNIFIED IDEOGRAPH-5152 +U+5154(2,3);U+5154(2,3); # 49-29, CJK UNIFIED IDEOGRAPH-5154 +U+515A(2,3);U+515A(2,3); # 37-62, CJK UNIFIED IDEOGRAPH-515A +U+515C(2,3);U+515C(2,3); # 19-85, CJK UNIFIED IDEOGRAPH-515C +U+5162(2,3);U+5162(2,3); # 49-30, CJK UNIFIED IDEOGRAPH-5162 +U+5165(2,3);U+5165(2,3); # 38-94, CJK UNIFIED IDEOGRAPH-5165 +U+5168(2,3);U+5168(2,3); # 33-20, CJK UNIFIED IDEOGRAPH-5168 +U+5169(2,3);U+5169(2,3); # 49-32, CJK UNIFIED IDEOGRAPH-5169 +U+516A(2,3);U+516A(2,3); # 49-33, CJK UNIFIED IDEOGRAPH-516A +U+516B(2,3);U+516B(2,3); # 40-12, CJK UNIFIED IDEOGRAPH-516B +U+516C(2,3);U+516C(2,3); # 24-88, CJK UNIFIED IDEOGRAPH-516C +U+516D(2,3);U+516D(2,3); # 47-27, CJK UNIFIED IDEOGRAPH-516D +U+516E(2,3);U+516E(2,3); # 49-34, CJK UNIFIED IDEOGRAPH-516E +U+5171(2,3);U+5171(2,3); # 22-06, CJK UNIFIED IDEOGRAPH-5171 +U+5175(2,3);U+5175(2,3); # 42-28, CJK UNIFIED IDEOGRAPH-5175 +U+5176(2,3);U+5176(2,3); # 34-22, CJK UNIFIED IDEOGRAPH-5176 +U+5177(2,3);U+5177(2,3); # 22-81, CJK UNIFIED IDEOGRAPH-5177 +U+5178(2,3);U+5178(2,3); # 37-21, CJK UNIFIED IDEOGRAPH-5178 +U+517C(2,3);U+517C(2,3); # 23-83, CJK UNIFIED IDEOGRAPH-517C +U+5180(2,3);U+5180(2,3); # 49-35, CJK UNIFIED IDEOGRAPH-5180 +U+5182(2,3);U+5182(2,3); # 49-36, CJK UNIFIED IDEOGRAPH-5182 +U+5185(2,3);U+5185(2,3); # 38-66, CJK UNIFIED IDEOGRAPH-5185 +U+5186(2,3);U+5186(2,3); # 17-63, CJK UNIFIED IDEOGRAPH-5186 +U+5189(2,3);U+5189(2,3); # 49-39, CJK UNIFIED IDEOGRAPH-5189 +U+518A(2,3);U+518A(2,3); # 26-93, CJK UNIFIED IDEOGRAPH-518A +U+518C(2,3);U+518C(2,3); # 49-38, CJK UNIFIED IDEOGRAPH-518C +U+518D(2,3);U+518D(2,3); # 26-38, CJK UNIFIED IDEOGRAPH-518D +U+518F(2,3);U+518F(2,3); # 49-40, CJK UNIFIED IDEOGRAPH-518F +U+5190(2,3);U+5190(2,3); # 70-78, CJK UNIFIED IDEOGRAPH-5190 +U+5191(2,3);U+5191(2,3); # 49-41, CJK UNIFIED IDEOGRAPH-5191 +U+5192(2,3);U+5192(2,3); # 43-33, CJK UNIFIED IDEOGRAPH-5192 +U+5193(2,3);U+5193(2,3); # 49-42, CJK UNIFIED IDEOGRAPH-5193 +U+5195(2,3);U+5195(2,3); # 49-43, CJK UNIFIED IDEOGRAPH-5195 +U+5196(2,3);U+5196(2,3); # 49-44, CJK UNIFIED IDEOGRAPH-5196 +U+5197(2,3);U+5197(2,3); # 30-73, CJK UNIFIED IDEOGRAPH-5197 +U+5199(2,3);U+5199(2,3); # 28-44, CJK UNIFIED IDEOGRAPH-5199 +U+51A0(2,3);U+51A0(2,3); # 20-07, CJK UNIFIED IDEOGRAPH-51A0 +U+51A2(2,3);U+51A2(2,3); # 49-47, CJK UNIFIED IDEOGRAPH-51A2 +U+51A4(2,3);U+51A4(2,3); # 49-45, CJK UNIFIED IDEOGRAPH-51A4 +U+51A5(2,3);U+51A5(2,3); # 44-29, CJK UNIFIED IDEOGRAPH-51A5 +U+51A6(2,3);U+51A6(2,3); # 49-46, CJK UNIFIED IDEOGRAPH-51A6 +U+51A8(2,3);U+51A8(2,3); # 41-58, CJK UNIFIED IDEOGRAPH-51A8 +U+51A9(2,3);U+51A9(2,3); # 49-48, CJK UNIFIED IDEOGRAPH-51A9 +U+51AA(2,3);U+51AA(2,3); # 49-49, CJK UNIFIED IDEOGRAPH-51AA +U+51AB(2,3);U+51AB(2,3); # 49-50, CJK UNIFIED IDEOGRAPH-51AB +U+51AC(2,3);U+51AC(2,3); # 37-63, CJK UNIFIED IDEOGRAPH-51AC +U+51B0(2,3);U+51B0(2,3); # 49-54, CJK UNIFIED IDEOGRAPH-51B0 +U+51B1(2,3);U+51B1(2,3); # 49-52, CJK UNIFIED IDEOGRAPH-51B1 +U+51B2(2,3);U+51B2(2,3); # 49-53, CJK UNIFIED IDEOGRAPH-51B2 +U+51B3(2,3);U+51B3(2,3); # 49-51, CJK UNIFIED IDEOGRAPH-51B3 +U+51B4(2,3);U+51B4(2,3); # 26-67, CJK UNIFIED IDEOGRAPH-51B4 +U+51B5(2,3);U+51B5(2,3); # 49-55, CJK UNIFIED IDEOGRAPH-51B5 +U+51B6(2,3);U+51B6(2,3); # 44-74, CJK UNIFIED IDEOGRAPH-51B6 +U+51B7(2,3);U+51B7(2,3); # 46-68, CJK UNIFIED IDEOGRAPH-51B7 +U+51BD(2,3);U+51BD(2,3); # 49-56, CJK UNIFIED IDEOGRAPH-51BD +U+51C4(2,3);U+51C4(2,3); # 32-08, CJK UNIFIED IDEOGRAPH-51C4 +U+51C5(2,3);U+51C5(2,3); # 49-57, CJK UNIFIED IDEOGRAPH-51C5 +U+51C6(2,3);U+51C6(2,3); # 29-58, CJK UNIFIED IDEOGRAPH-51C6 +U+51C9(2,3);U+51C9(2,3); # 49-58, CJK UNIFIED IDEOGRAPH-51C9 +U+51CB(2,3);U+51CB(2,3); # 35-92, CJK UNIFIED IDEOGRAPH-51CB +U+51CC(2,3);U+51CC(2,3); # 46-31, CJK UNIFIED IDEOGRAPH-51CC +U+51CD(2,3);U+51CD(2,3); # 37-64, CJK UNIFIED IDEOGRAPH-51CD +U+51D6(2,3);U+51D6(2,3); # 50-37, CJK UNIFIED IDEOGRAPH-51D6 +U+51DB(2,3);U+51DB(2,3); # 49-59, CJK UNIFIED IDEOGRAPH-51DB +U+51DC(2,3);U+51DC(2,3); # 84-05, CJK UNIFIED IDEOGRAPH-51DC +U+51DD(2,3);U+51DD(2,3); # 22-37, CJK UNIFIED IDEOGRAPH-51DD +U+51E0(2,3);U+51E0(2,3); # 49-60, CJK UNIFIED IDEOGRAPH-51E0 +U+51E1(2,3);U+51E1(2,3); # 43-62, CJK UNIFIED IDEOGRAPH-51E1 +U+51E6(2,3);U+51E6(2,3); # 29-72, CJK UNIFIED IDEOGRAPH-51E6 +U+51E7(2,3);U+51E7(2,3); # 34-92, CJK UNIFIED IDEOGRAPH-51E7 +U+51E9(2,3);U+51E9(2,3); # 49-62, CJK UNIFIED IDEOGRAPH-51E9 +U+51EA(2,3);U+51EA(2,3); # 38-68, CJK UNIFIED IDEOGRAPH-51EA +U+51ED(2,3);U+51ED(2,3); # 49-63, CJK UNIFIED IDEOGRAPH-51ED +U+51F0(2,3);U+51F0(2,3); # 49-64, CJK UNIFIED IDEOGRAPH-51F0 +U+51F1(2,3);U+51F1(2,3); # 19-14, CJK UNIFIED IDEOGRAPH-51F1 +U+51F5(2,3);U+51F5(2,3); # 49-65, CJK UNIFIED IDEOGRAPH-51F5 +U+51F6(2,3);U+51F6(2,3); # 22-07, CJK UNIFIED IDEOGRAPH-51F6 +U+51F8(2,3);U+51F8(2,3); # 38-44, CJK UNIFIED IDEOGRAPH-51F8 +U+51F9(2,3);U+51F9(2,3); # 17-90, CJK UNIFIED IDEOGRAPH-51F9 +U+51FA(2,3);U+51FA(2,3); # 29-48, CJK UNIFIED IDEOGRAPH-51FA +U+51FD(2,3);U+51FD(2,3); # 40-01, CJK UNIFIED IDEOGRAPH-51FD +U+51FE(2,3);U+51FE(2,3); # 49-66, CJK UNIFIED IDEOGRAPH-51FE +U+5200(2,3);U+5200(2,3); # 37-65, CJK UNIFIED IDEOGRAPH-5200 +U+5203(2,3);U+5203(2,3); # 31-47, CJK UNIFIED IDEOGRAPH-5203 +U+5204(2,3);U+5204(2,3); # 49-67, CJK UNIFIED IDEOGRAPH-5204 +U+5206(2,3);U+5206(2,3); # 42-12, CJK UNIFIED IDEOGRAPH-5206 +U+5207(2,3);U+5207(2,3); # 32-58, CJK UNIFIED IDEOGRAPH-5207 +U+5208(2,3);U+5208(2,3); # 20-02, CJK UNIFIED IDEOGRAPH-5208 +U+520A(2,3);U+520A(2,3); # 20-09, CJK UNIFIED IDEOGRAPH-520A +U+520B(2,3);U+520B(2,3); # 49-68, CJK UNIFIED IDEOGRAPH-520B +U+520E(2,3);U+520E(2,3); # 49-70, CJK UNIFIED IDEOGRAPH-520E +U+5211(2,3);U+5211(2,3); # 23-26, CJK UNIFIED IDEOGRAPH-5211 +U+5214(2,3);U+5214(2,3); # 49-69, CJK UNIFIED IDEOGRAPH-5214 +U+5217(2,3);U+5217(2,3); # 46-83, CJK UNIFIED IDEOGRAPH-5217 +U+521D(2,3);U+521D(2,3); # 29-73, CJK UNIFIED IDEOGRAPH-521D +U+5224(2,3);U+5224(2,3); # 40-29, CJK UNIFIED IDEOGRAPH-5224 +U+5225(2,3);U+5225(2,3); # 42-44, CJK UNIFIED IDEOGRAPH-5225 +U+5227(2,3);U+5227(2,3); # 49-71, CJK UNIFIED IDEOGRAPH-5227 +U+5229(2,3);U+5229(2,3); # 45-88, CJK UNIFIED IDEOGRAPH-5229 +U+522A(2,3);U+522A(2,3); # 49-72, CJK UNIFIED IDEOGRAPH-522A +U+522E(2,3);U+522E(2,3); # 49-73, CJK UNIFIED IDEOGRAPH-522E +U+5230(2,3);U+5230(2,3); # 37-94, CJK UNIFIED IDEOGRAPH-5230 +U+5233(2,3);U+5233(2,3); # 49-74, CJK UNIFIED IDEOGRAPH-5233 +U+5236(2,3);U+5236(2,3); # 32-09, CJK UNIFIED IDEOGRAPH-5236 +U+5237(2,3);U+5237(2,3); # 26-94, CJK UNIFIED IDEOGRAPH-5237 +U+5238(2,3);U+5238(2,3); # 23-84, CJK UNIFIED IDEOGRAPH-5238 +U+5239(2,3);U+5239(2,3); # 49-75, CJK UNIFIED IDEOGRAPH-5239 +U+523A(2,3);U+523A(2,3); # 27-41, CJK UNIFIED IDEOGRAPH-523A +U+523B(2,3);U+523B(2,3); # 25-79, CJK UNIFIED IDEOGRAPH-523B +U+5243(2,3);U+5243(2,3); # 36-70, CJK UNIFIED IDEOGRAPH-5243 +U+5244(2,3);U+5244(2,3); # 49-77, CJK UNIFIED IDEOGRAPH-5244 +U+5247(2,3);U+5247(2,3); # 34-07, CJK UNIFIED IDEOGRAPH-5247 +U+524A(2,3);U+524A(2,3); # 26-79, CJK UNIFIED IDEOGRAPH-524A +U+524B(2,3);U+524B(2,3); # 49-78, CJK UNIFIED IDEOGRAPH-524B +U+524C(2,3);U+524C(2,3); # 49-79, CJK UNIFIED IDEOGRAPH-524C +U+524D(2,3);U+524D(2,3); # 33-16, CJK UNIFIED IDEOGRAPH-524D +U+524F(2,3);U+524F(2,3); # 49-76, CJK UNIFIED IDEOGRAPH-524F +U+5254(2,3);U+5254(2,3); # 49-81, CJK UNIFIED IDEOGRAPH-5254 +U+5256(2,3);U+5256(2,3); # 43-22, CJK UNIFIED IDEOGRAPH-5256 +U+525B(2,3);U+525B(2,3); # 25-68, CJK UNIFIED IDEOGRAPH-525B +U+525E(2,3);U+525E(2,3); # 49-80, CJK UNIFIED IDEOGRAPH-525E +U+5263(2,3);U+5263(2,3); # 23-85, CJK UNIFIED IDEOGRAPH-5263 +U+5264(2,3);U+5264(2,3); # 26-62, CJK UNIFIED IDEOGRAPH-5264 +U+5265(2,3);U+5265(2,3); # 39-77, CJK UNIFIED IDEOGRAPH-5265 +U+5269(2,3);U+5269(2,3); # 49-84, CJK UNIFIED IDEOGRAPH-5269 +U+526A(2,3);U+526A(2,3); # 49-82, CJK UNIFIED IDEOGRAPH-526A +U+526F(2,3);U+526F(2,3); # 41-91, CJK UNIFIED IDEOGRAPH-526F +U+5270(2,3);U+5270(2,3); # 30-74, CJK UNIFIED IDEOGRAPH-5270 +U+5271(2,3);U+5271(2,3); # 49-91, CJK UNIFIED IDEOGRAPH-5271 +U+5272(2,3);U+5272(2,3); # 19-68, CJK UNIFIED IDEOGRAPH-5272 +U+5273(2,3);U+5273(2,3); # 49-85, CJK UNIFIED IDEOGRAPH-5273 +U+5274(2,3);U+5274(2,3); # 49-83, CJK UNIFIED IDEOGRAPH-5274 +U+5275(2,3);U+5275(2,3); # 33-47, CJK UNIFIED IDEOGRAPH-5275 +U+527D(2,3);U+527D(2,3); # 49-87, CJK UNIFIED IDEOGRAPH-527D +U+527F(2,3);U+527F(2,3); # 49-86, CJK UNIFIED IDEOGRAPH-527F +U+5283(2,3);U+5283(2,3); # 19-36, CJK UNIFIED IDEOGRAPH-5283 +U+5287(2,3);U+5287(2,3); # 23-64, CJK UNIFIED IDEOGRAPH-5287 +U+5288(2,3);U+5288(2,3); # 49-92, CJK UNIFIED IDEOGRAPH-5288 +U+5289(2,3);U+5289(2,3); # 46-13, CJK UNIFIED IDEOGRAPH-5289 +U+528D(2,3);U+528D(2,3); # 49-88, CJK UNIFIED IDEOGRAPH-528D +U+5291(2,3);U+5291(2,3); # 49-93, CJK UNIFIED IDEOGRAPH-5291 +U+5292(2,3);U+5292(2,3); # 49-90, CJK UNIFIED IDEOGRAPH-5292 +U+5294(2,3);U+5294(2,3); # 49-89, CJK UNIFIED IDEOGRAPH-5294 +U+529B(2,3);U+529B(2,3); # 46-47, CJK UNIFIED IDEOGRAPH-529B +U+529F(2,3);U+529F(2,3); # 24-89, CJK UNIFIED IDEOGRAPH-529F +U+52A0(2,3);U+52A0(2,3); # 18-35, CJK UNIFIED IDEOGRAPH-52A0 +U+52A3(2,3);U+52A3(2,3); # 46-84, CJK UNIFIED IDEOGRAPH-52A3 +U+52A9(2,3);U+52A9(2,3); # 29-85, CJK UNIFIED IDEOGRAPH-52A9 +U+52AA(2,3);U+52AA(2,3); # 37-56, CJK UNIFIED IDEOGRAPH-52AA +U+52AB(2,3);U+52AB(2,3); # 25-69, CJK UNIFIED IDEOGRAPH-52AB +U+52AC(2,3);U+52AC(2,3); # 50-02, CJK UNIFIED IDEOGRAPH-52AC +U+52AD(2,3);U+52AD(2,3); # 50-03, CJK UNIFIED IDEOGRAPH-52AD +U+52B1(2,3);U+52B1(2,3); # 46-69, CJK UNIFIED IDEOGRAPH-52B1 +U+52B4(2,3);U+52B4(2,3); # 47-11, CJK UNIFIED IDEOGRAPH-52B4 +U+52B5(2,3);U+52B5(2,3); # 50-05, CJK UNIFIED IDEOGRAPH-52B5 +U+52B9(2,3);U+52B9(2,3); # 24-90, CJK UNIFIED IDEOGRAPH-52B9 +U+52BC(2,3);U+52BC(2,3); # 50-04, CJK UNIFIED IDEOGRAPH-52BC +U+52BE(2,3);U+52BE(2,3); # 19-15, CJK UNIFIED IDEOGRAPH-52BE +U+52C1(2,3);U+52C1(2,3); # 50-06, CJK UNIFIED IDEOGRAPH-52C1 +U+52C3(2,3);U+52C3(2,3); # 43-54, CJK UNIFIED IDEOGRAPH-52C3 +U+52C5(2,3);U+52C5(2,3); # 36-28, CJK UNIFIED IDEOGRAPH-52C5 +U+52C7(2,3);U+52C7(2,3); # 45-06, CJK UNIFIED IDEOGRAPH-52C7 +U+52C9(2,3);U+52C9(2,3); # 42-57, CJK UNIFIED IDEOGRAPH-52C9 +U+52CD(2,3);U+52CD(2,3); # 50-07, CJK UNIFIED IDEOGRAPH-52CD +U+52D2(2,3);U+52D2(2,3); # 80-53, CJK UNIFIED IDEOGRAPH-52D2 +U+52D5(2,3);U+52D5(2,3); # 38-16, CJK UNIFIED IDEOGRAPH-52D5 +U+52D7(2,3);U+52D7(2,3); # 50-08, CJK UNIFIED IDEOGRAPH-52D7 +U+52D8(2,3);U+52D8(2,3); # 20-10, CJK UNIFIED IDEOGRAPH-52D8 +U+52D9(2,3);U+52D9(2,3); # 44-19, CJK UNIFIED IDEOGRAPH-52D9 +U+52DD(2,3);U+52DD(2,3); # 30-01, CJK UNIFIED IDEOGRAPH-52DD +U+52DE(2,3);U+52DE(2,3); # 50-09, CJK UNIFIED IDEOGRAPH-52DE +U+52DF(2,3);U+52DF(2,3); # 42-71, CJK UNIFIED IDEOGRAPH-52DF +U+52E0(2,3);U+52E0(2,3); # 50-13, CJK UNIFIED IDEOGRAPH-52E0 +U+52E2(2,3);U+52E2(2,3); # 32-10, CJK UNIFIED IDEOGRAPH-52E2 +U+52E3(2,3);U+52E3(2,3); # 50-10, CJK UNIFIED IDEOGRAPH-52E3 +U+52E4(2,3);U+52E4(2,3); # 22-48, CJK UNIFIED IDEOGRAPH-52E4 +U+52E6(2,3);U+52E6(2,3); # 50-11, CJK UNIFIED IDEOGRAPH-52E6 +U+52E7(2,3);U+52E7(2,3); # 20-11, CJK UNIFIED IDEOGRAPH-52E7 +U+52F2(2,3);U+52F2(2,3); # 23-14, CJK UNIFIED IDEOGRAPH-52F2 +U+52F3(2,3);U+52F3(2,3); # 50-14, CJK UNIFIED IDEOGRAPH-52F3 +U+52F5(2,3);U+52F5(2,3); # 50-15, CJK UNIFIED IDEOGRAPH-52F5 +U+52F8(2,3);U+52F8(2,3); # 50-16, CJK UNIFIED IDEOGRAPH-52F8 +U+52F9(2,3);U+52F9(2,3); # 50-17, CJK UNIFIED IDEOGRAPH-52F9 +U+52FA(2,3);U+52FA(2,3); # 28-59, CJK UNIFIED IDEOGRAPH-52FA +U+52FE(2,3);U+52FE(2,3); # 24-91, CJK UNIFIED IDEOGRAPH-52FE +U+52FF(2,3);U+52FF(2,3); # 44-62, CJK UNIFIED IDEOGRAPH-52FF +U+5301(2,3);U+5301(2,3); # 44-72, CJK UNIFIED IDEOGRAPH-5301 +U+5302(2,3);U+5302(2,3); # 38-87, CJK UNIFIED IDEOGRAPH-5302 +U+5305(2,3);U+5305(2,3); # 42-81, CJK UNIFIED IDEOGRAPH-5305 +U+5306(2,3);U+5306(2,3); # 50-18, CJK UNIFIED IDEOGRAPH-5306 +U+5308(2,3);U+5308(2,3); # 50-19, CJK UNIFIED IDEOGRAPH-5308 +U+530D(2,3);U+530D(2,3); # 50-21, CJK UNIFIED IDEOGRAPH-530D +U+530F(2,3);U+530F(2,3); # 50-23, CJK UNIFIED IDEOGRAPH-530F +U+5310(2,3);U+5310(2,3); # 50-22, CJK UNIFIED IDEOGRAPH-5310 +U+5315(2,3);U+5315(2,3); # 50-24, CJK UNIFIED IDEOGRAPH-5315 +U+5316(2,3);U+5316(2,3); # 18-29, CJK UNIFIED IDEOGRAPH-5316 +U+5317(2,3);U+5317(2,3); # 43-44, CJK UNIFIED IDEOGRAPH-5317 +U+5319(2,3);U+5319(2,3); # 26-92, CJK UNIFIED IDEOGRAPH-5319 +U+531A(2,3);U+531A(2,3); # 50-25, CJK UNIFIED IDEOGRAPH-531A +U+531D(2,3);U+531D(2,3); # 33-57, CJK UNIFIED IDEOGRAPH-531D +U+5320(2,3);U+5320(2,3); # 30-02, CJK UNIFIED IDEOGRAPH-5320 +U+5321(2,3);U+5321(2,3); # 22-09, CJK UNIFIED IDEOGRAPH-5321 +U+5323(2,3);U+5323(2,3); # 50-26, CJK UNIFIED IDEOGRAPH-5323 +U+532A(2,3);U+532A(2,3); # 40-59, CJK UNIFIED IDEOGRAPH-532A +U+532F(2,3);U+532F(2,3); # 50-27, CJK UNIFIED IDEOGRAPH-532F +U+5331(2,3);U+5331(2,3); # 50-28, CJK UNIFIED IDEOGRAPH-5331 +U+5333(2,3);U+5333(2,3); # 50-29, CJK UNIFIED IDEOGRAPH-5333 +U+5338(2,3);U+5338(2,3); # 50-30, CJK UNIFIED IDEOGRAPH-5338 +U+5339(2,3);U+5339(2,3); # 41-04, CJK UNIFIED IDEOGRAPH-5339 +U+533A(2,3);U+533A(2,3); # 22-72, CJK UNIFIED IDEOGRAPH-533A +U+533B(2,3);U+533B(2,3); # 16-69, CJK UNIFIED IDEOGRAPH-533B +U+533F(2,3);U+533F(2,3); # 38-31, CJK UNIFIED IDEOGRAPH-533F +U+5340(2,3);U+5340(2,3); # 50-31, CJK UNIFIED IDEOGRAPH-5340 +U+5341(2,3);U+5341(2,3); # 29-29, CJK UNIFIED IDEOGRAPH-5341 +U+5343(2,3);U+5343(2,3); # 32-73, CJK UNIFIED IDEOGRAPH-5343 +U+5345(2,3);U+5345(2,3); # 50-33, CJK UNIFIED IDEOGRAPH-5345 +U+5346(2,3);U+5346(2,3); # 50-32, CJK UNIFIED IDEOGRAPH-5346 +U+5347(2,3);U+5347(2,3); # 30-03, CJK UNIFIED IDEOGRAPH-5347 +U+5348(2,3);U+5348(2,3); # 24-65, CJK UNIFIED IDEOGRAPH-5348 +U+5349(2,3);U+5349(2,3); # 50-35, CJK UNIFIED IDEOGRAPH-5349 +U+534A(2,3);U+534A(2,3); # 40-30, CJK UNIFIED IDEOGRAPH-534A +U+534D(2,3);U+534D(2,3); # 50-36, CJK UNIFIED IDEOGRAPH-534D +U+5351(2,3);U+5351(2,3); # 40-60, CJK UNIFIED IDEOGRAPH-5351 +U+5352(2,3);U+5352(2,3); # 34-20, CJK UNIFIED IDEOGRAPH-5352 +U+5353(2,3);U+5353(2,3); # 34-78, CJK UNIFIED IDEOGRAPH-5353 +U+5354(2,3);U+5354(2,3); # 22-08, CJK UNIFIED IDEOGRAPH-5354 +U+5357(2,3);U+5357(2,3); # 38-78, CJK UNIFIED IDEOGRAPH-5357 +U+5358(2,3);U+5358(2,3); # 35-17, CJK UNIFIED IDEOGRAPH-5358 +U+535A(2,3);U+535A(2,3); # 39-78, CJK UNIFIED IDEOGRAPH-535A +U+535C(2,3);U+535C(2,3); # 43-46, CJK UNIFIED IDEOGRAPH-535C +U+535E(2,3);U+535E(2,3); # 50-38, CJK UNIFIED IDEOGRAPH-535E +U+5360(2,3);U+5360(2,3); # 32-74, CJK UNIFIED IDEOGRAPH-5360 +U+5366(2,3);U+5366(2,3); # 23-21, CJK UNIFIED IDEOGRAPH-5366 +U+5369(2,3);U+5369(2,3); # 50-39, CJK UNIFIED IDEOGRAPH-5369 +U+536E(2,3);U+536E(2,3); # 50-40, CJK UNIFIED IDEOGRAPH-536E +U+536F(2,3);U+536F(2,3); # 17-12, CJK UNIFIED IDEOGRAPH-536F +U+5370(2,3);U+5370(2,3); # 16-85, CJK UNIFIED IDEOGRAPH-5370 +U+5371(2,3);U+5371(2,3); # 20-77, CJK UNIFIED IDEOGRAPH-5371 +U+5373(2,3);U+5373(2,3); # 34-08, CJK UNIFIED IDEOGRAPH-5373 +U+5374(2,3);U+5374(2,3); # 21-49, CJK UNIFIED IDEOGRAPH-5374 +U+5375(2,3);U+5375(2,3); # 45-81, CJK UNIFIED IDEOGRAPH-5375 +U+5377(2,3);U+5377(2,3); # 50-43, CJK UNIFIED IDEOGRAPH-5377 +U+5378(2,3);U+5378(2,3); # 18-23, CJK UNIFIED IDEOGRAPH-5378 +U+537B(2,3);U+537B(2,3); # 50-42, CJK UNIFIED IDEOGRAPH-537B +U+537F(2,3);U+537F(2,3); # 22-10, CJK UNIFIED IDEOGRAPH-537F +U+5382(2,3);U+5382(2,3); # 50-44, CJK UNIFIED IDEOGRAPH-5382 +U+5384(2,3);U+5384(2,3); # 44-81, CJK UNIFIED IDEOGRAPH-5384 +U+5396(2,3);U+5396(2,3); # 50-45, CJK UNIFIED IDEOGRAPH-5396 +U+5398(2,3);U+5398(2,3); # 46-50, CJK UNIFIED IDEOGRAPH-5398 +U+539A(2,3);U+539A(2,3); # 24-92, CJK UNIFIED IDEOGRAPH-539A +U+539F(2,3);U+539F(2,3); # 24-22, CJK UNIFIED IDEOGRAPH-539F +U+53A0(2,3);U+53A0(2,3); # 50-46, CJK UNIFIED IDEOGRAPH-53A0 +U+53A5(2,3);U+53A5(2,3); # 50-48, CJK UNIFIED IDEOGRAPH-53A5 +U+53A6(2,3);U+53A6(2,3); # 50-47, CJK UNIFIED IDEOGRAPH-53A6 +U+53A8(2,3);U+53A8(2,3); # 31-63, CJK UNIFIED IDEOGRAPH-53A8 +U+53A9(2,3);U+53A9(2,3); # 17-25, CJK UNIFIED IDEOGRAPH-53A9 +U+53AD(2,3);U+53AD(2,3); # 17-62, CJK UNIFIED IDEOGRAPH-53AD +U+53AE(2,3);U+53AE(2,3); # 50-49, CJK UNIFIED IDEOGRAPH-53AE +U+53B0(2,3);U+53B0(2,3); # 50-50, CJK UNIFIED IDEOGRAPH-53B0 +U+53B3(2,3);U+53B3(2,3); # 24-23, CJK UNIFIED IDEOGRAPH-53B3 +U+53B6(2,3);U+53B6(2,3); # 50-51, CJK UNIFIED IDEOGRAPH-53B6 +U+53BB(2,3);U+53BB(2,3); # 21-78, CJK UNIFIED IDEOGRAPH-53BB +U+53C2(2,3);U+53C2(2,3); # 27-18, CJK UNIFIED IDEOGRAPH-53C2 +U+53C3(2,3);U+53C3(2,3); # 50-52, CJK UNIFIED IDEOGRAPH-53C3 +U+53C8(2,3);U+53C8(2,3); # 43-84, CJK UNIFIED IDEOGRAPH-53C8 +U+53C9(2,3);U+53C9(2,3); # 26-21, CJK UNIFIED IDEOGRAPH-53C9 +U+53CA(2,3);U+53CA(2,3); # 21-58, CJK UNIFIED IDEOGRAPH-53CA +U+53CB(2,3);U+53CB(2,3); # 45-07, CJK UNIFIED IDEOGRAPH-53CB +U+53CC(2,3);U+53CC(2,3); # 33-48, CJK UNIFIED IDEOGRAPH-53CC +U+53CD(2,3);U+53CD(2,3); # 40-31, CJK UNIFIED IDEOGRAPH-53CD +U+53CE(2,3);U+53CE(2,3); # 28-93, CJK UNIFIED IDEOGRAPH-53CE +U+53D4(2,3);U+53D4(2,3); # 29-39, CJK UNIFIED IDEOGRAPH-53D4 +U+53D6(2,3);U+53D6(2,3); # 28-72, CJK UNIFIED IDEOGRAPH-53D6 +U+53D7(2,3);U+53D7(2,3); # 28-85, CJK UNIFIED IDEOGRAPH-53D7 +U+53D9(2,3);U+53D9(2,3); # 29-86, CJK UNIFIED IDEOGRAPH-53D9 +U+53DB(2,3);U+53DB(2,3); # 40-32, CJK UNIFIED IDEOGRAPH-53DB +U+53DF(2,3);U+53DF(2,3); # 50-55, CJK UNIFIED IDEOGRAPH-53DF +U+53E1(2,3);U+53E1(2,3); # 17-35, CJK UNIFIED IDEOGRAPH-53E1 +U+53E2(2,3);U+53E2(2,3); # 33-49, CJK UNIFIED IDEOGRAPH-53E2 +U+53E3(2,3);U+53E3(2,3); # 24-93, CJK UNIFIED IDEOGRAPH-53E3 +U+53E4(2,3);U+53E4(2,3); # 24-37, CJK UNIFIED IDEOGRAPH-53E4 +U+53E5(2,3);U+53E5(2,3); # 22-71, CJK UNIFIED IDEOGRAPH-53E5 +U+53E8(2,3);U+53E8(2,3); # 50-59, CJK UNIFIED IDEOGRAPH-53E8 +U+53E9(2,3);U+53E9(2,3); # 35-01, CJK UNIFIED IDEOGRAPH-53E9 +U+53EA(2,3);U+53EA(2,3); # 34-94, CJK UNIFIED IDEOGRAPH-53EA +U+53EB(2,3);U+53EB(2,3); # 22-11, CJK UNIFIED IDEOGRAPH-53EB +U+53EC(2,3);U+53EC(2,3); # 30-04, CJK UNIFIED IDEOGRAPH-53EC +U+53ED(2,3);U+53ED(2,3); # 50-60, CJK UNIFIED IDEOGRAPH-53ED +U+53EE(2,3);U+53EE(2,3); # 50-58, CJK UNIFIED IDEOGRAPH-53EE +U+53EF(2,3);U+53EF(2,3); # 18-36, CJK UNIFIED IDEOGRAPH-53EF +U+53F0(2,3);U+53F0(2,3); # 34-70, CJK UNIFIED IDEOGRAPH-53F0 +U+53F1(2,3);U+53F1(2,3); # 28-24, CJK UNIFIED IDEOGRAPH-53F1 +U+53F2(2,3);U+53F2(2,3); # 27-43, CJK UNIFIED IDEOGRAPH-53F2 +U+53F3(2,3);U+53F3(2,3); # 17-06, CJK UNIFIED IDEOGRAPH-53F3 +U+53F6(2,3);U+53F6(2,3); # 19-80, CJK UNIFIED IDEOGRAPH-53F6 +U+53F7(2,3);U+53F7(2,3); # 25-70, CJK UNIFIED IDEOGRAPH-53F7 +U+53F8(2,3);U+53F8(2,3); # 27-42, CJK UNIFIED IDEOGRAPH-53F8 +U+53FA(2,3);U+53FA(2,3); # 50-61, CJK UNIFIED IDEOGRAPH-53FA +U+5401(2,3);U+5401(2,3); # 50-62, CJK UNIFIED IDEOGRAPH-5401 +U+5403(2,3);U+5403(2,3); # 21-41, CJK UNIFIED IDEOGRAPH-5403 +U+5404(2,3);U+5404(2,3); # 19-38, CJK UNIFIED IDEOGRAPH-5404 +U+5408(2,3);U+5408(2,3); # 25-71, CJK UNIFIED IDEOGRAPH-5408 +U+5409(2,3);U+5409(2,3); # 21-40, CJK UNIFIED IDEOGRAPH-5409 +U+540A(2,3);U+540A(2,3); # 36-63, CJK UNIFIED IDEOGRAPH-540A +U+540B(2,3);U+540B(2,3); # 17-05, CJK UNIFIED IDEOGRAPH-540B +U+540C(2,3);U+540C(2,3); # 38-17, CJK UNIFIED IDEOGRAPH-540C +U+540D(2,3);U+540D(2,3); # 44-30, CJK UNIFIED IDEOGRAPH-540D +U+540E(2,3);U+540E(2,3); # 25-01, CJK UNIFIED IDEOGRAPH-540E +U+540F(2,3);U+540F(2,3); # 45-89, CJK UNIFIED IDEOGRAPH-540F +U+5410(2,3);U+5410(2,3); # 37-39, CJK UNIFIED IDEOGRAPH-5410 +U+5411(2,3);U+5411(2,3); # 24-94, CJK UNIFIED IDEOGRAPH-5411 +U+541B(2,3);U+541B(2,3); # 23-15, CJK UNIFIED IDEOGRAPH-541B +U+541D(2,3);U+541D(2,3); # 50-71, CJK UNIFIED IDEOGRAPH-541D +U+541F(2,3);U+541F(2,3); # 22-67, CJK UNIFIED IDEOGRAPH-541F +U+5420(2,3);U+5420(2,3); # 43-42, CJK UNIFIED IDEOGRAPH-5420 +U+5426(2,3);U+5426(2,3); # 40-61, CJK UNIFIED IDEOGRAPH-5426 +U+5429(2,3);U+5429(2,3); # 50-70, CJK UNIFIED IDEOGRAPH-5429 +U+542B(2,3);U+542B(2,3); # 20-62, CJK UNIFIED IDEOGRAPH-542B +U+542C(2,3);U+542C(2,3); # 50-65, CJK UNIFIED IDEOGRAPH-542C +U+542D(2,3);U+542D(2,3); # 50-66, CJK UNIFIED IDEOGRAPH-542D +U+542E(2,3);U+542E(2,3); # 50-68, CJK UNIFIED IDEOGRAPH-542E +U+5436(2,3);U+5436(2,3); # 50-69, CJK UNIFIED IDEOGRAPH-5436 +U+5438(2,3);U+5438(2,3); # 21-59, CJK UNIFIED IDEOGRAPH-5438 +U+5439(2,3);U+5439(2,3); # 31-65, CJK UNIFIED IDEOGRAPH-5439 +U+543B(2,3);U+543B(2,3); # 42-13, CJK UNIFIED IDEOGRAPH-543B +U+543C(2,3);U+543C(2,3); # 50-67, CJK UNIFIED IDEOGRAPH-543C +U+543D(2,3);U+543D(2,3); # 50-63, CJK UNIFIED IDEOGRAPH-543D +U+543E(2,3);U+543E(2,3); # 24-67, CJK UNIFIED IDEOGRAPH-543E +U+5440(2,3);U+5440(2,3); # 50-64, CJK UNIFIED IDEOGRAPH-5440 +U+5442(2,3);U+5442(2,3); # 47-04, CJK UNIFIED IDEOGRAPH-5442 +U+5446(2,3);U+5446(2,3); # 42-82, CJK UNIFIED IDEOGRAPH-5446 +U+5448(2,3);U+5448(2,3); # 36-72, CJK UNIFIED IDEOGRAPH-5448 +U+5449(2,3);U+5449(2,3); # 24-66, CJK UNIFIED IDEOGRAPH-5449 +U+544A(2,3);U+544A(2,3); # 25-80, CJK UNIFIED IDEOGRAPH-544A +U+544E(2,3);U+544E(2,3); # 50-72, CJK UNIFIED IDEOGRAPH-544E +U+5451(2,3);U+5451(2,3); # 38-61, CJK UNIFIED IDEOGRAPH-5451 +U+545F(2,3);U+545F(2,3); # 50-76, CJK UNIFIED IDEOGRAPH-545F +U+5468(2,3);U+5468(2,3); # 28-94, CJK UNIFIED IDEOGRAPH-5468 +U+546A(2,3);U+546A(2,3); # 28-86, CJK UNIFIED IDEOGRAPH-546A +U+5470(2,3);U+5470(2,3); # 50-79, CJK UNIFIED IDEOGRAPH-5470 +U+5471(2,3);U+5471(2,3); # 50-77, CJK UNIFIED IDEOGRAPH-5471 +U+5473(2,3);U+5473(2,3); # 44-03, CJK UNIFIED IDEOGRAPH-5473 +U+5475(2,3);U+5475(2,3); # 50-74, CJK UNIFIED IDEOGRAPH-5475 +U+5476(2,3);U+5476(2,3); # 50-83, CJK UNIFIED IDEOGRAPH-5476 +U+5477(2,3);U+5477(2,3); # 50-78, CJK UNIFIED IDEOGRAPH-5477 +U+547B(2,3);U+547B(2,3); # 50-81, CJK UNIFIED IDEOGRAPH-547B +U+547C(2,3);U+547C(2,3); # 24-38, CJK UNIFIED IDEOGRAPH-547C +U+547D(2,3);U+547D(2,3); # 44-31, CJK UNIFIED IDEOGRAPH-547D +U+5480(2,3);U+5480(2,3); # 50-82, CJK UNIFIED IDEOGRAPH-5480 +U+5484(2,3);U+5484(2,3); # 50-84, CJK UNIFIED IDEOGRAPH-5484 +U+5486(2,3);U+5486(2,3); # 50-86, CJK UNIFIED IDEOGRAPH-5486 +U+548B(2,3);U+548B(2,3); # 26-80, CJK UNIFIED IDEOGRAPH-548B +U+548C(2,3);U+548C(2,3); # 47-34, CJK UNIFIED IDEOGRAPH-548C +U+548E(2,3);U+548E(2,3); # 50-75, CJK UNIFIED IDEOGRAPH-548E +U+548F(2,3);U+548F(2,3); # 50-73, CJK UNIFIED IDEOGRAPH-548F +U+5490(2,3);U+5490(2,3); # 50-85, CJK UNIFIED IDEOGRAPH-5490 +U+5492(2,3);U+5492(2,3); # 50-80, CJK UNIFIED IDEOGRAPH-5492 +U+54A2(2,3);U+54A2(2,3); # 50-88, CJK UNIFIED IDEOGRAPH-54A2 +U+54A4(2,3);U+54A4(2,3); # 51-03, CJK UNIFIED IDEOGRAPH-54A4 +U+54A5(2,3);U+54A5(2,3); # 50-90, CJK UNIFIED IDEOGRAPH-54A5 +U+54A8(2,3);U+54A8(2,3); # 50-94, CJK UNIFIED IDEOGRAPH-54A8 +U+54AB(2,3);U+54AB(2,3); # 51-01, CJK UNIFIED IDEOGRAPH-54AB +U+54AC(2,3);U+54AC(2,3); # 50-91, CJK UNIFIED IDEOGRAPH-54AC +U+54AF(2,3);U+54AF(2,3); # 51-30, CJK UNIFIED IDEOGRAPH-54AF +U+54B2(2,3);U+54B2(2,3); # 26-73, CJK UNIFIED IDEOGRAPH-54B2 +U+54B3(2,3);U+54B3(2,3); # 19-17, CJK UNIFIED IDEOGRAPH-54B3 +U+54B8(2,3);U+54B8(2,3); # 50-89, CJK UNIFIED IDEOGRAPH-54B8 +U+54BC(2,3);U+54BC(2,3); # 51-05, CJK UNIFIED IDEOGRAPH-54BC +U+54BD(2,3);U+54BD(2,3); # 16-86, CJK UNIFIED IDEOGRAPH-54BD +U+54BE(2,3);U+54BE(2,3); # 51-04, CJK UNIFIED IDEOGRAPH-54BE +U+54C0(2,3);U+54C0(2,3); # 16-05, CJK UNIFIED IDEOGRAPH-54C0 +U+54C1(2,3);U+54C1(2,3); # 41-42, CJK UNIFIED IDEOGRAPH-54C1 +U+54C2(2,3);U+54C2(2,3); # 51-02, CJK UNIFIED IDEOGRAPH-54C2 +U+54C4(2,3);U+54C4(2,3); # 50-92, CJK UNIFIED IDEOGRAPH-54C4 +U+54C7(2,3);U+54C7(2,3); # 50-87, CJK UNIFIED IDEOGRAPH-54C7 +U+54C8(2,3);U+54C8(2,3); # 50-93, CJK UNIFIED IDEOGRAPH-54C8 +U+54C9(2,3);U+54C9(2,3); # 26-40, CJK UNIFIED IDEOGRAPH-54C9 +U+54D8(2,3);U+54D8(2,3); # 51-06, CJK UNIFIED IDEOGRAPH-54D8 +U+54E1(2,3);U+54E1(2,3); # 16-87, CJK UNIFIED IDEOGRAPH-54E1 +U+54E2(2,3);U+54E2(2,3); # 51-15, CJK UNIFIED IDEOGRAPH-54E2 +U+54E5(2,3);U+54E5(2,3); # 51-07, CJK UNIFIED IDEOGRAPH-54E5 +U+54E6(2,3);U+54E6(2,3); # 51-08, CJK UNIFIED IDEOGRAPH-54E6 +U+54E8(2,3);U+54E8(2,3); # 30-05, CJK UNIFIED IDEOGRAPH-54E8 +U+54E9(2,3);U+54E9(2,3); # 43-73, CJK UNIFIED IDEOGRAPH-54E9 +U+54ED(2,3);U+54ED(2,3); # 51-13, CJK UNIFIED IDEOGRAPH-54ED +U+54EE(2,3);U+54EE(2,3); # 51-12, CJK UNIFIED IDEOGRAPH-54EE +U+54F2(2,3);U+54F2(2,3); # 37-15, CJK UNIFIED IDEOGRAPH-54F2 +U+54FA(2,3);U+54FA(2,3); # 51-14, CJK UNIFIED IDEOGRAPH-54FA +U+54FD(2,3);U+54FD(2,3); # 51-11, CJK UNIFIED IDEOGRAPH-54FD +U+5504(2,3);U+5504(2,3); # 17-20, CJK UNIFIED IDEOGRAPH-5504 +U+5506(2,3);U+5506(2,3); # 26-22, CJK UNIFIED IDEOGRAPH-5506 +U+5507(2,3);U+5507(2,3); # 31-16, CJK UNIFIED IDEOGRAPH-5507 +U+550F(2,3);U+550F(2,3); # 51-09, CJK UNIFIED IDEOGRAPH-550F +U+5510(2,3);U+5510(2,3); # 37-66, CJK UNIFIED IDEOGRAPH-5510 +U+5514(2,3);U+5514(2,3); # 51-10, CJK UNIFIED IDEOGRAPH-5514 +U+5516(2,3);U+5516(2,3); # 16-02, CJK UNIFIED IDEOGRAPH-5516 +U+552E(2,3);U+552E(2,3); # 51-20, CJK UNIFIED IDEOGRAPH-552E +U+552F(2,3);U+552F(2,3); # 45-03, CJK UNIFIED IDEOGRAPH-552F +U+5531(2,3);U+5531(2,3); # 30-07, CJK UNIFIED IDEOGRAPH-5531 +U+5533(2,3);U+5533(2,3); # 51-26, CJK UNIFIED IDEOGRAPH-5533 +U+5538(2,3);U+5538(2,3); # 51-25, CJK UNIFIED IDEOGRAPH-5538 +U+5539(2,3);U+5539(2,3); # 51-16, CJK UNIFIED IDEOGRAPH-5539 +U+553E(2,3);U+553E(2,3); # 34-35, CJK UNIFIED IDEOGRAPH-553E +U+5540(2,3);U+5540(2,3); # 51-17, CJK UNIFIED IDEOGRAPH-5540 +U+5544(2,3);U+5544(2,3); # 34-79, CJK UNIFIED IDEOGRAPH-5544 +U+5545(2,3);U+5545(2,3); # 51-22, CJK UNIFIED IDEOGRAPH-5545 +U+5546(2,3);U+5546(2,3); # 30-06, CJK UNIFIED IDEOGRAPH-5546 +U+554C(2,3);U+554C(2,3); # 51-19, CJK UNIFIED IDEOGRAPH-554C +U+554F(2,3);U+554F(2,3); # 44-68, CJK UNIFIED IDEOGRAPH-554F +U+5553(2,3);U+5553(2,3); # 23-28, CJK UNIFIED IDEOGRAPH-5553 +U+5556(2,3);U+5556(2,3); # 51-23, CJK UNIFIED IDEOGRAPH-5556 +U+5557(2,3);U+5557(2,3); # 51-24, CJK UNIFIED IDEOGRAPH-5557 +U+555C(2,3);U+555C(2,3); # 51-21, CJK UNIFIED IDEOGRAPH-555C +U+555D(2,3);U+555D(2,3); # 51-27, CJK UNIFIED IDEOGRAPH-555D +U+5563(2,3);U+5563(2,3); # 51-18, CJK UNIFIED IDEOGRAPH-5563 +U+557B(2,3);U+557B(2,3); # 51-33, CJK UNIFIED IDEOGRAPH-557B +U+557C(2,3);U+557C(2,3); # 51-38, CJK UNIFIED IDEOGRAPH-557C +U+557E(2,3);U+557E(2,3); # 51-34, CJK UNIFIED IDEOGRAPH-557E +U+5580(2,3);U+5580(2,3); # 51-29, CJK UNIFIED IDEOGRAPH-5580 +U+5583(2,3);U+5583(2,3); # 51-39, CJK UNIFIED IDEOGRAPH-5583 +U+5584(2,3);U+5584(2,3); # 33-17, CJK UNIFIED IDEOGRAPH-5584 +U+5587(2,3);U+5587(2,3); # 51-41, CJK UNIFIED IDEOGRAPH-5587 +U+5589(2,3);U+5589(2,3); # 25-02, CJK UNIFIED IDEOGRAPH-5589 +U+558A(2,3);U+558A(2,3); # 51-31, CJK UNIFIED IDEOGRAPH-558A +U+558B(2,3);U+558B(2,3); # 35-93, CJK UNIFIED IDEOGRAPH-558B +U+5598(2,3);U+5598(2,3); # 51-35, CJK UNIFIED IDEOGRAPH-5598 +U+5599(2,3);U+5599(2,3); # 51-28, CJK UNIFIED IDEOGRAPH-5599 +U+559A(2,3);U+559A(2,3); # 20-13, CJK UNIFIED IDEOGRAPH-559A +U+559C(2,3);U+559C(2,3); # 20-78, CJK UNIFIED IDEOGRAPH-559C +U+559D(2,3);U+559D(2,3); # 19-69, CJK UNIFIED IDEOGRAPH-559D +U+559E(2,3);U+559E(2,3); # 51-36, CJK UNIFIED IDEOGRAPH-559E +U+559F(2,3);U+559F(2,3); # 51-32, CJK UNIFIED IDEOGRAPH-559F +U+55A7(2,3);U+55A7(2,3); # 23-86, CJK UNIFIED IDEOGRAPH-55A7 +U+55A8(2,3);U+55A8(2,3); # 51-42, CJK UNIFIED IDEOGRAPH-55A8 +U+55A9(2,3);U+55A9(2,3); # 51-40, CJK UNIFIED IDEOGRAPH-55A9 +U+55AA(2,3);U+55AA(2,3); # 33-51, CJK UNIFIED IDEOGRAPH-55AA +U+55AB(2,3);U+55AB(2,3); # 21-42, CJK UNIFIED IDEOGRAPH-55AB +U+55AC(2,3);U+55AC(2,3); # 22-12, CJK UNIFIED IDEOGRAPH-55AC +U+55AE(2,3);U+55AE(2,3); # 51-37, CJK UNIFIED IDEOGRAPH-55AE +U+55B0(2,3);U+55B0(2,3); # 22-84, CJK UNIFIED IDEOGRAPH-55B0 +U+55B6(2,3);U+55B6(2,3); # 17-36, CJK UNIFIED IDEOGRAPH-55B6 +U+55C4(2,3);U+55C4(2,3); # 51-46, CJK UNIFIED IDEOGRAPH-55C4 +U+55C5(2,3);U+55C5(2,3); # 51-44, CJK UNIFIED IDEOGRAPH-55C5 +U+55C7(2,3);U+55C7(2,3); # 52-07, CJK UNIFIED IDEOGRAPH-55C7 +U+55D4(2,3);U+55D4(2,3); # 51-49, CJK UNIFIED IDEOGRAPH-55D4 +U+55DA(2,3);U+55DA(2,3); # 51-43, CJK UNIFIED IDEOGRAPH-55DA +U+55DC(2,3);U+55DC(2,3); # 51-47, CJK UNIFIED IDEOGRAPH-55DC +U+55DF(2,3);U+55DF(2,3); # 51-45, CJK UNIFIED IDEOGRAPH-55DF +U+55E3(2,3);U+55E3(2,3); # 27-44, CJK UNIFIED IDEOGRAPH-55E3 +U+55E4(2,3);U+55E4(2,3); # 51-48, CJK UNIFIED IDEOGRAPH-55E4 +U+55F7(2,3);U+55F7(2,3); # 51-51, CJK UNIFIED IDEOGRAPH-55F7 +U+55F9(2,3);U+55F9(2,3); # 51-56, CJK UNIFIED IDEOGRAPH-55F9 +U+55FD(2,3);U+55FD(2,3); # 51-54, CJK UNIFIED IDEOGRAPH-55FD +U+55FE(2,3);U+55FE(2,3); # 51-53, CJK UNIFIED IDEOGRAPH-55FE +U+5606(2,3);U+5606(2,3); # 35-18, CJK UNIFIED IDEOGRAPH-5606 +U+5609(2,3);U+5609(2,3); # 18-37, CJK UNIFIED IDEOGRAPH-5609 +U+5614(2,3);U+5614(2,3); # 51-50, CJK UNIFIED IDEOGRAPH-5614 +U+5616(2,3);U+5616(2,3); # 51-52, CJK UNIFIED IDEOGRAPH-5616 +U+5617(2,3);U+5617(2,3); # 30-08, CJK UNIFIED IDEOGRAPH-5617 +U+5618(2,3);U+5618(2,3); # 17-19, CJK UNIFIED IDEOGRAPH-5618 +U+561B(2,3);U+561B(2,3); # 51-55, CJK UNIFIED IDEOGRAPH-561B +U+5629(2,3);U+5629(2,3); # 18-62, CJK UNIFIED IDEOGRAPH-5629 +U+562F(2,3);U+562F(2,3); # 51-66, CJK UNIFIED IDEOGRAPH-562F +U+5631(2,3);U+5631(2,3); # 30-92, CJK UNIFIED IDEOGRAPH-5631 +U+5632(2,3);U+5632(2,3); # 51-62, CJK UNIFIED IDEOGRAPH-5632 +U+5634(2,3);U+5634(2,3); # 51-60, CJK UNIFIED IDEOGRAPH-5634 +U+5636(2,3);U+5636(2,3); # 51-61, CJK UNIFIED IDEOGRAPH-5636 +U+5638(2,3);U+5638(2,3); # 51-63, CJK UNIFIED IDEOGRAPH-5638 +U+5642(2,3);U+5642(2,3); # 17-29, CJK UNIFIED IDEOGRAPH-5642 +U+564C(2,3);U+564C(2,3); # 33-25, CJK UNIFIED IDEOGRAPH-564C +U+564E(2,3);U+564E(2,3); # 51-57, CJK UNIFIED IDEOGRAPH-564E +U+5650(2,3);U+5650(2,3); # 51-58, CJK UNIFIED IDEOGRAPH-5650 +U+565B(2,3);U+565B(2,3); # 19-90, CJK UNIFIED IDEOGRAPH-565B +U+5664(2,3);U+5664(2,3); # 51-65, CJK UNIFIED IDEOGRAPH-5664 +U+5668(2,3);U+5668(2,3); # 20-79, CJK UNIFIED IDEOGRAPH-5668 +U+566A(2,3);U+566A(2,3); # 51-68, CJK UNIFIED IDEOGRAPH-566A +U+566B(2,3);U+566B(2,3); # 51-64, CJK UNIFIED IDEOGRAPH-566B +U+566C(2,3);U+566C(2,3); # 51-67, CJK UNIFIED IDEOGRAPH-566C +U+5674(2,3);U+5674(2,3); # 42-14, CJK UNIFIED IDEOGRAPH-5674 +U+5678(2,3);U+5678(2,3); # 38-53, CJK UNIFIED IDEOGRAPH-5678 +U+567A(2,3);U+567A(2,3); # 40-24, CJK UNIFIED IDEOGRAPH-567A +U+5680(2,3);U+5680(2,3); # 51-70, CJK UNIFIED IDEOGRAPH-5680 +U+5686(2,3);U+5686(2,3); # 51-69, CJK UNIFIED IDEOGRAPH-5686 +U+5687(2,3);U+5687(2,3); # 19-37, CJK UNIFIED IDEOGRAPH-5687 +U+568A(2,3);U+568A(2,3); # 51-71, CJK UNIFIED IDEOGRAPH-568A +U+568F(2,3);U+568F(2,3); # 51-74, CJK UNIFIED IDEOGRAPH-568F +U+5694(2,3);U+5694(2,3); # 51-73, CJK UNIFIED IDEOGRAPH-5694 +U+56A0(2,3);U+56A0(2,3); # 51-72, CJK UNIFIED IDEOGRAPH-56A0 +U+56A2(2,3);U+56A2(2,3); # 39-25, CJK UNIFIED IDEOGRAPH-56A2 +U+56A5(2,3);U+56A5(2,3); # 51-75, CJK UNIFIED IDEOGRAPH-56A5 +U+56AE(2,3);U+56AE(2,3); # 51-76, CJK UNIFIED IDEOGRAPH-56AE +U+56B4(2,3);U+56B4(2,3); # 51-78, CJK UNIFIED IDEOGRAPH-56B4 +U+56B6(2,3);U+56B6(2,3); # 51-77, CJK UNIFIED IDEOGRAPH-56B6 +U+56BC(2,3);U+56BC(2,3); # 51-80, CJK UNIFIED IDEOGRAPH-56BC +U+56C0(2,3);U+56C0(2,3); # 51-83, CJK UNIFIED IDEOGRAPH-56C0 +U+56C1(2,3);U+56C1(2,3); # 51-81, CJK UNIFIED IDEOGRAPH-56C1 +U+56C2(2,3);U+56C2(2,3); # 51-79, CJK UNIFIED IDEOGRAPH-56C2 +U+56C3(2,3);U+56C3(2,3); # 51-82, CJK UNIFIED IDEOGRAPH-56C3 +U+56C8(2,3);U+56C8(2,3); # 51-84, CJK UNIFIED IDEOGRAPH-56C8 +U+56CE(2,3);U+56CE(2,3); # 51-85, CJK UNIFIED IDEOGRAPH-56CE +U+56D1(2,3);U+56D1(2,3); # 51-86, CJK UNIFIED IDEOGRAPH-56D1 +U+56D3(2,3);U+56D3(2,3); # 51-87, CJK UNIFIED IDEOGRAPH-56D3 +U+56D7(2,3);U+56D7(2,3); # 51-88, CJK UNIFIED IDEOGRAPH-56D7 +U+56D8(2,3);U+56D8(2,3); # 49-37, CJK UNIFIED IDEOGRAPH-56D8 +U+56DA(2,3);U+56DA(2,3); # 28-92, CJK UNIFIED IDEOGRAPH-56DA +U+56DB(2,3);U+56DB(2,3); # 27-45, CJK UNIFIED IDEOGRAPH-56DB +U+56DE(2,3);U+56DE(2,3); # 18-83, CJK UNIFIED IDEOGRAPH-56DE +U+56E0(2,3);U+56E0(2,3); # 16-88, CJK UNIFIED IDEOGRAPH-56E0 +U+56E3(2,3);U+56E3(2,3); # 35-36, CJK UNIFIED IDEOGRAPH-56E3 +U+56EE(2,3);U+56EE(2,3); # 51-89, CJK UNIFIED IDEOGRAPH-56EE +U+56F0(2,3);U+56F0(2,3); # 26-04, CJK UNIFIED IDEOGRAPH-56F0 +U+56F2(2,3);U+56F2(2,3); # 16-47, CJK UNIFIED IDEOGRAPH-56F2 +U+56F3(2,3);U+56F3(2,3); # 31-62, CJK UNIFIED IDEOGRAPH-56F3 +U+56F9(2,3);U+56F9(2,3); # 51-90, CJK UNIFIED IDEOGRAPH-56F9 +U+56FA(2,3);U+56FA(2,3); # 24-39, CJK UNIFIED IDEOGRAPH-56FA +U+56FD(2,3);U+56FD(2,3); # 25-81, CJK UNIFIED IDEOGRAPH-56FD +U+56FF(2,3);U+56FF(2,3); # 51-92, CJK UNIFIED IDEOGRAPH-56FF +U+5700(2,3);U+5700(2,3); # 51-91, CJK UNIFIED IDEOGRAPH-5700 +U+5703(2,3);U+5703(2,3); # 42-64, CJK UNIFIED IDEOGRAPH-5703 +U+5704(2,3);U+5704(2,3); # 51-93, CJK UNIFIED IDEOGRAPH-5704 +U+5708(2,3);U+5708(2,3); # 52-01, CJK UNIFIED IDEOGRAPH-5708 +U+5709(2,3);U+5709(2,3); # 51-94, CJK UNIFIED IDEOGRAPH-5709 +U+570B(2,3);U+570B(2,3); # 52-02, CJK UNIFIED IDEOGRAPH-570B +U+570D(2,3);U+570D(2,3); # 52-03, CJK UNIFIED IDEOGRAPH-570D +U+570F(2,3);U+570F(2,3); # 23-87, CJK UNIFIED IDEOGRAPH-570F +U+5712(2,3);U+5712(2,3); # 17-64, CJK UNIFIED IDEOGRAPH-5712 +U+5713(2,3);U+5713(2,3); # 52-04, CJK UNIFIED IDEOGRAPH-5713 +U+5716(2,3);U+5716(2,3); # 52-06, CJK UNIFIED IDEOGRAPH-5716 +U+5718(2,3);U+5718(2,3); # 52-05, CJK UNIFIED IDEOGRAPH-5718 +U+571C(2,3);U+571C(2,3); # 52-08, CJK UNIFIED IDEOGRAPH-571C +U+571F(2,3);U+571F(2,3); # 37-58, CJK UNIFIED IDEOGRAPH-571F +U+5726(2,3);U+5726(2,3); # 52-09, CJK UNIFIED IDEOGRAPH-5726 +U+5727(2,3);U+5727(2,3); # 16-21, CJK UNIFIED IDEOGRAPH-5727 +U+5728(2,3);U+5728(2,3); # 26-63, CJK UNIFIED IDEOGRAPH-5728 +U+572D(2,3);U+572D(2,3); # 23-29, CJK UNIFIED IDEOGRAPH-572D +U+5730(2,3);U+5730(2,3); # 35-47, CJK UNIFIED IDEOGRAPH-5730 +U+5737(2,3);U+5737(2,3); # 52-10, CJK UNIFIED IDEOGRAPH-5737 +U+5738(2,3);U+5738(2,3); # 52-11, CJK UNIFIED IDEOGRAPH-5738 +U+573B(2,3);U+573B(2,3); # 52-13, CJK UNIFIED IDEOGRAPH-573B +U+5740(2,3);U+5740(2,3); # 52-14, CJK UNIFIED IDEOGRAPH-5740 +U+5742(2,3);U+5742(2,3); # 26-68, CJK UNIFIED IDEOGRAPH-5742 +U+5747(2,3);U+5747(2,3); # 22-49, CJK UNIFIED IDEOGRAPH-5747 +U+574A(2,3);U+574A(2,3); # 43-23, CJK UNIFIED IDEOGRAPH-574A +U+574E(2,3);U+574E(2,3); # 52-12, CJK UNIFIED IDEOGRAPH-574E +U+574F(2,3);U+574F(2,3); # 52-15, CJK UNIFIED IDEOGRAPH-574F +U+5750(2,3);U+5750(2,3); # 26-33, CJK UNIFIED IDEOGRAPH-5750 +U+5751(2,3);U+5751(2,3); # 25-03, CJK UNIFIED IDEOGRAPH-5751 +U+5761(2,3);U+5761(2,3); # 52-19, CJK UNIFIED IDEOGRAPH-5761 +U+5764(2,3);U+5764(2,3); # 26-05, CJK UNIFIED IDEOGRAPH-5764 +U+5766(2,3);U+5766(2,3); # 35-19, CJK UNIFIED IDEOGRAPH-5766 +U+5769(2,3);U+5769(2,3); # 52-16, CJK UNIFIED IDEOGRAPH-5769 +U+576A(2,3);U+576A(2,3); # 36-58, CJK UNIFIED IDEOGRAPH-576A +U+577F(2,3);U+577F(2,3); # 52-20, CJK UNIFIED IDEOGRAPH-577F +U+5782(2,3);U+5782(2,3); # 31-66, CJK UNIFIED IDEOGRAPH-5782 +U+5788(2,3);U+5788(2,3); # 52-18, CJK UNIFIED IDEOGRAPH-5788 +U+5789(2,3);U+5789(2,3); # 52-21, CJK UNIFIED IDEOGRAPH-5789 +U+578B(2,3);U+578B(2,3); # 23-31, CJK UNIFIED IDEOGRAPH-578B +U+5793(2,3);U+5793(2,3); # 52-22, CJK UNIFIED IDEOGRAPH-5793 +U+57A0(2,3);U+57A0(2,3); # 52-23, CJK UNIFIED IDEOGRAPH-57A0 +U+57A2(2,3);U+57A2(2,3); # 25-04, CJK UNIFIED IDEOGRAPH-57A2 +U+57A3(2,3);U+57A3(2,3); # 19-32, CJK UNIFIED IDEOGRAPH-57A3 +U+57A4(2,3);U+57A4(2,3); # 52-25, CJK UNIFIED IDEOGRAPH-57A4 +U+57AA(2,3);U+57AA(2,3); # 52-26, CJK UNIFIED IDEOGRAPH-57AA +U+57B0(2,3);U+57B0(2,3); # 52-27, CJK UNIFIED IDEOGRAPH-57B0 +U+57B3(2,3);U+57B3(2,3); # 52-24, CJK UNIFIED IDEOGRAPH-57B3 +U+57C0(2,3);U+57C0(2,3); # 52-17, CJK UNIFIED IDEOGRAPH-57C0 +U+57C3(2,3);U+57C3(2,3); # 52-28, CJK UNIFIED IDEOGRAPH-57C3 +U+57C6(2,3);U+57C6(2,3); # 52-29, CJK UNIFIED IDEOGRAPH-57C6 +U+57CB(2,3);U+57CB(2,3); # 43-68, CJK UNIFIED IDEOGRAPH-57CB +U+57CE(2,3);U+57CE(2,3); # 30-75, CJK UNIFIED IDEOGRAPH-57CE +U+57D2(2,3);U+57D2(2,3); # 52-31, CJK UNIFIED IDEOGRAPH-57D2 +U+57D3(2,3);U+57D3(2,3); # 52-32, CJK UNIFIED IDEOGRAPH-57D3 +U+57D4(2,3);U+57D4(2,3); # 52-30, CJK UNIFIED IDEOGRAPH-57D4 +U+57D6(2,3);U+57D6(2,3); # 52-34, CJK UNIFIED IDEOGRAPH-57D6 +U+57DC(2,3);U+57DC(2,3); # 39-24, CJK UNIFIED IDEOGRAPH-57DC +U+57DF(2,3);U+57DF(2,3); # 16-72, CJK UNIFIED IDEOGRAPH-57DF +U+57E0(2,3);U+57E0(2,3); # 41-54, CJK UNIFIED IDEOGRAPH-57E0 +U+57E3(2,3);U+57E3(2,3); # 52-35, CJK UNIFIED IDEOGRAPH-57E3 +U+57F4(2,3);U+57F4(2,3); # 30-93, CJK UNIFIED IDEOGRAPH-57F4 +U+57F7(2,3);U+57F7(2,3); # 28-25, CJK UNIFIED IDEOGRAPH-57F7 +U+57F9(2,3);U+57F9(2,3); # 39-61, CJK UNIFIED IDEOGRAPH-57F9 +U+57FA(2,3);U+57FA(2,3); # 20-80, CJK UNIFIED IDEOGRAPH-57FA +U+57FC(2,3);U+57FC(2,3); # 26-75, CJK UNIFIED IDEOGRAPH-57FC +U+5800(2,3);U+5800(2,3); # 43-57, CJK UNIFIED IDEOGRAPH-5800 +U+5802(2,3);U+5802(2,3); # 38-18, CJK UNIFIED IDEOGRAPH-5802 +U+5805(2,3);U+5805(2,3); # 23-88, CJK UNIFIED IDEOGRAPH-5805 +U+5806(2,3);U+5806(2,3); # 34-47, CJK UNIFIED IDEOGRAPH-5806 +U+580A(2,3);U+580A(2,3); # 52-33, CJK UNIFIED IDEOGRAPH-580A +U+580B(2,3);U+580B(2,3); # 52-36, CJK UNIFIED IDEOGRAPH-580B +U+5815(2,3);U+5815(2,3); # 34-36, CJK UNIFIED IDEOGRAPH-5815 +U+5819(2,3);U+5819(2,3); # 52-37, CJK UNIFIED IDEOGRAPH-5819 +U+581D(2,3);U+581D(2,3); # 52-38, CJK UNIFIED IDEOGRAPH-581D +U+5821(2,3);U+5821(2,3); # 52-40, CJK UNIFIED IDEOGRAPH-5821 +U+5824(2,3);U+5824(2,3); # 36-73, CJK UNIFIED IDEOGRAPH-5824 +U+582A(2,3);U+582A(2,3); # 20-14, CJK UNIFIED IDEOGRAPH-582A +U+582F(2,3);U+582F(2,3); # 84-01, CJK UNIFIED IDEOGRAPH-582F +U+5830(2,3);U+5830(2,3); # 17-65, CJK UNIFIED IDEOGRAPH-5830 +U+5831(2,3);U+5831(2,3); # 42-83, CJK UNIFIED IDEOGRAPH-5831 +U+5834(2,3);U+5834(2,3); # 30-76, CJK UNIFIED IDEOGRAPH-5834 +U+5835(2,3);U+5835(2,3); # 37-40, CJK UNIFIED IDEOGRAPH-5835 +U+583A(2,3);U+583A(2,3); # 26-70, CJK UNIFIED IDEOGRAPH-583A +U+583D(2,3);U+583D(2,3); # 52-46, CJK UNIFIED IDEOGRAPH-583D +U+5840(2,3);U+5840(2,3); # 42-29, CJK UNIFIED IDEOGRAPH-5840 +U+5841(2,3);U+5841(2,3); # 46-61, CJK UNIFIED IDEOGRAPH-5841 +U+584A(2,3);U+584A(2,3); # 18-84, CJK UNIFIED IDEOGRAPH-584A +U+584B(2,3);U+584B(2,3); # 52-42, CJK UNIFIED IDEOGRAPH-584B +U+5851(2,3);U+5851(2,3); # 33-26, CJK UNIFIED IDEOGRAPH-5851 +U+5852(2,3);U+5852(2,3); # 52-45, CJK UNIFIED IDEOGRAPH-5852 +U+5854(2,3);U+5854(2,3); # 37-67, CJK UNIFIED IDEOGRAPH-5854 +U+5857(2,3);U+5857(2,3); # 37-41, CJK UNIFIED IDEOGRAPH-5857 +U+5858(2,3);U+5858(2,3); # 37-68, CJK UNIFIED IDEOGRAPH-5858 +U+5859(2,3);U+5859(2,3); # 40-25, CJK UNIFIED IDEOGRAPH-5859 +U+585A(2,3);U+585A(2,3); # 36-45, CJK UNIFIED IDEOGRAPH-585A +U+585E(2,3);U+585E(2,3); # 26-41, CJK UNIFIED IDEOGRAPH-585E +U+5862(2,3);U+5862(2,3); # 52-41, CJK UNIFIED IDEOGRAPH-5862 +U+5869(2,3);U+5869(2,3); # 17-86, CJK UNIFIED IDEOGRAPH-5869 +U+586B(2,3);U+586B(2,3); # 37-22, CJK UNIFIED IDEOGRAPH-586B +U+5870(2,3);U+5870(2,3); # 52-43, CJK UNIFIED IDEOGRAPH-5870 +U+5872(2,3);U+5872(2,3); # 52-39, CJK UNIFIED IDEOGRAPH-5872 +U+5875(2,3);U+5875(2,3); # 31-48, CJK UNIFIED IDEOGRAPH-5875 +U+5879(2,3);U+5879(2,3); # 52-47, CJK UNIFIED IDEOGRAPH-5879 +U+587E(2,3);U+587E(2,3); # 29-46, CJK UNIFIED IDEOGRAPH-587E +U+5883(2,3);U+5883(2,3); # 22-13, CJK UNIFIED IDEOGRAPH-5883 +U+5885(2,3);U+5885(2,3); # 52-48, CJK UNIFIED IDEOGRAPH-5885 +U+5893(2,3);U+5893(2,3); # 42-72, CJK UNIFIED IDEOGRAPH-5893 +U+5897(2,3);U+5897(2,3); # 33-93, CJK UNIFIED IDEOGRAPH-5897 +U+589C(2,3);U+589C(2,3); # 36-38, CJK UNIFIED IDEOGRAPH-589C +U+589F(2,3);U+589F(2,3); # 52-50, CJK UNIFIED IDEOGRAPH-589F +U+58A8(2,3);U+58A8(2,3); # 43-47, CJK UNIFIED IDEOGRAPH-58A8 +U+58AB(2,3);U+58AB(2,3); # 52-51, CJK UNIFIED IDEOGRAPH-58AB +U+58AE(2,3);U+58AE(2,3); # 52-56, CJK UNIFIED IDEOGRAPH-58AE +U+58B3(2,3);U+58B3(2,3); # 42-15, CJK UNIFIED IDEOGRAPH-58B3 +U+58B8(2,3);U+58B8(2,3); # 52-55, CJK UNIFIED IDEOGRAPH-58B8 +U+58B9(2,3);U+58B9(2,3); # 52-49, CJK UNIFIED IDEOGRAPH-58B9 +U+58BA(2,3);U+58BA(2,3); # 52-52, CJK UNIFIED IDEOGRAPH-58BA +U+58BB(2,3);U+58BB(2,3); # 52-54, CJK UNIFIED IDEOGRAPH-58BB +U+58BE(2,3);U+58BE(2,3); # 26-06, CJK UNIFIED IDEOGRAPH-58BE +U+58C1(2,3);U+58C1(2,3); # 42-41, CJK UNIFIED IDEOGRAPH-58C1 +U+58C5(2,3);U+58C5(2,3); # 52-57, CJK UNIFIED IDEOGRAPH-58C5 +U+58C7(2,3);U+58C7(2,3); # 35-37, CJK UNIFIED IDEOGRAPH-58C7 +U+58CA(2,3);U+58CA(2,3); # 18-85, CJK UNIFIED IDEOGRAPH-58CA +U+58CC(2,3);U+58CC(2,3); # 30-77, CJK UNIFIED IDEOGRAPH-58CC +U+58D1(2,3);U+58D1(2,3); # 52-59, CJK UNIFIED IDEOGRAPH-58D1 +U+58D3(2,3);U+58D3(2,3); # 52-58, CJK UNIFIED IDEOGRAPH-58D3 +U+58D5(2,3);U+58D5(2,3); # 25-72, CJK UNIFIED IDEOGRAPH-58D5 +U+58D7(2,3);U+58D7(2,3); # 52-60, CJK UNIFIED IDEOGRAPH-58D7 +U+58D8(2,3);U+58D8(2,3); # 52-62, CJK UNIFIED IDEOGRAPH-58D8 +U+58D9(2,3);U+58D9(2,3); # 52-61, CJK UNIFIED IDEOGRAPH-58D9 +U+58DC(2,3);U+58DC(2,3); # 52-64, CJK UNIFIED IDEOGRAPH-58DC +U+58DE(2,3);U+58DE(2,3); # 52-53, CJK UNIFIED IDEOGRAPH-58DE +U+58DF(2,3);U+58DF(2,3); # 52-66, CJK UNIFIED IDEOGRAPH-58DF +U+58E4(2,3);U+58E4(2,3); # 52-65, CJK UNIFIED IDEOGRAPH-58E4 +U+58E5(2,3);U+58E5(2,3); # 52-63, CJK UNIFIED IDEOGRAPH-58E5 +U+58EB(2,3);U+58EB(2,3); # 27-46, CJK UNIFIED IDEOGRAPH-58EB +U+58EC(2,3);U+58EC(2,3); # 31-49, CJK UNIFIED IDEOGRAPH-58EC +U+58EE(2,3);U+58EE(2,3); # 33-52, CJK UNIFIED IDEOGRAPH-58EE +U+58EF(2,3);U+58EF(2,3); # 52-67, CJK UNIFIED IDEOGRAPH-58EF +U+58F0(2,3);U+58F0(2,3); # 32-28, CJK UNIFIED IDEOGRAPH-58F0 +U+58F1(2,3);U+58F1(2,3); # 16-77, CJK UNIFIED IDEOGRAPH-58F1 +U+58F2(2,3);U+58F2(2,3); # 39-68, CJK UNIFIED IDEOGRAPH-58F2 +U+58F7(2,3);U+58F7(2,3); # 36-59, CJK UNIFIED IDEOGRAPH-58F7 +U+58F9(2,3);U+58F9(2,3); # 52-69, CJK UNIFIED IDEOGRAPH-58F9 +U+58FA(2,3);U+58FA(2,3); # 52-68, CJK UNIFIED IDEOGRAPH-58FA +U+58FB(2,3);U+58FB(2,3); # 52-70, CJK UNIFIED IDEOGRAPH-58FB +U+58FC(2,3);U+58FC(2,3); # 52-71, CJK UNIFIED IDEOGRAPH-58FC +U+58FD(2,3);U+58FD(2,3); # 52-72, CJK UNIFIED IDEOGRAPH-58FD +U+5902(2,3);U+5902(2,3); # 52-73, CJK UNIFIED IDEOGRAPH-5902 +U+5909(2,3);U+5909(2,3); # 42-49, CJK UNIFIED IDEOGRAPH-5909 +U+590A(2,3);U+590A(2,3); # 52-74, CJK UNIFIED IDEOGRAPH-590A +U+590F(2,3);U+590F(2,3); # 18-38, CJK UNIFIED IDEOGRAPH-590F +U+5910(2,3);U+5910(2,3); # 52-75, CJK UNIFIED IDEOGRAPH-5910 +U+5915(2,3);U+5915(2,3); # 45-28, CJK UNIFIED IDEOGRAPH-5915 +U+5916(2,3);U+5916(2,3); # 19-16, CJK UNIFIED IDEOGRAPH-5916 +U+5918(2,3);U+5918(2,3); # 50-41, CJK UNIFIED IDEOGRAPH-5918 +U+5919(2,3);U+5919(2,3); # 29-40, CJK UNIFIED IDEOGRAPH-5919 +U+591A(2,3);U+591A(2,3); # 34-31, CJK UNIFIED IDEOGRAPH-591A +U+591B(2,3);U+591B(2,3); # 52-76, CJK UNIFIED IDEOGRAPH-591B +U+591C(2,3);U+591C(2,3); # 44-75, CJK UNIFIED IDEOGRAPH-591C +U+5922(2,3);U+5922(2,3); # 44-20, CJK UNIFIED IDEOGRAPH-5922 +U+5925(2,3);U+5925(2,3); # 52-78, CJK UNIFIED IDEOGRAPH-5925 +U+5927(2,3);U+5927(2,3); # 34-71, CJK UNIFIED IDEOGRAPH-5927 +U+5929(2,3);U+5929(2,3); # 37-23, CJK UNIFIED IDEOGRAPH-5929 +U+592A(2,3);U+592A(2,3); # 34-32, CJK UNIFIED IDEOGRAPH-592A +U+592B(2,3);U+592B(2,3); # 41-55, CJK UNIFIED IDEOGRAPH-592B +U+592C(2,3);U+592C(2,3); # 52-79, CJK UNIFIED IDEOGRAPH-592C +U+592D(2,3);U+592D(2,3); # 52-80, CJK UNIFIED IDEOGRAPH-592D +U+592E(2,3);U+592E(2,3); # 17-91, CJK UNIFIED IDEOGRAPH-592E +U+5931(2,3);U+5931(2,3); # 28-26, CJK UNIFIED IDEOGRAPH-5931 +U+5932(2,3);U+5932(2,3); # 52-81, CJK UNIFIED IDEOGRAPH-5932 +U+5937(2,3);U+5937(2,3); # 16-48, CJK UNIFIED IDEOGRAPH-5937 +U+5938(2,3);U+5938(2,3); # 52-82, CJK UNIFIED IDEOGRAPH-5938 +U+593E(2,3);U+593E(2,3); # 52-83, CJK UNIFIED IDEOGRAPH-593E +U+5944(2,3);U+5944(2,3); # 17-66, CJK UNIFIED IDEOGRAPH-5944 +U+5947(2,3);U+5947(2,3); # 20-81, CJK UNIFIED IDEOGRAPH-5947 +U+5948(2,3);U+5948(2,3); # 38-64, CJK UNIFIED IDEOGRAPH-5948 +U+5949(2,3);U+5949(2,3); # 42-84, CJK UNIFIED IDEOGRAPH-5949 +U+594E(2,3);U+594E(2,3); # 52-87, CJK UNIFIED IDEOGRAPH-594E +U+594F(2,3);U+594F(2,3); # 33-53, CJK UNIFIED IDEOGRAPH-594F +U+5950(2,3);U+5950(2,3); # 52-86, CJK UNIFIED IDEOGRAPH-5950 +U+5951(2,3);U+5951(2,3); # 23-32, CJK UNIFIED IDEOGRAPH-5951 +U+5954(2,3);U+5954(2,3); # 43-59, CJK UNIFIED IDEOGRAPH-5954 +U+5955(2,3);U+5955(2,3); # 52-85, CJK UNIFIED IDEOGRAPH-5955 +U+5957(2,3);U+5957(2,3); # 37-69, CJK UNIFIED IDEOGRAPH-5957 +U+5958(2,3);U+5958(2,3); # 52-89, CJK UNIFIED IDEOGRAPH-5958 +U+595A(2,3);U+595A(2,3); # 52-88, CJK UNIFIED IDEOGRAPH-595A +U+5960(2,3);U+5960(2,3); # 52-91, CJK UNIFIED IDEOGRAPH-5960 +U+5962(2,3);U+5962(2,3); # 52-90, CJK UNIFIED IDEOGRAPH-5962 +U+5965(2,3);U+5965(2,3); # 17-92, CJK UNIFIED IDEOGRAPH-5965 +U+5967(2,3);U+5967(2,3); # 52-92, CJK UNIFIED IDEOGRAPH-5967 +U+5968(2,3);U+5968(2,3); # 30-09, CJK UNIFIED IDEOGRAPH-5968 +U+5969(2,3);U+5969(2,3); # 52-94, CJK UNIFIED IDEOGRAPH-5969 +U+596A(2,3);U+596A(2,3); # 35-05, CJK UNIFIED IDEOGRAPH-596A +U+596C(2,3);U+596C(2,3); # 52-93, CJK UNIFIED IDEOGRAPH-596C +U+596E(2,3);U+596E(2,3); # 42-19, CJK UNIFIED IDEOGRAPH-596E +U+5973(2,3);U+5973(2,3); # 29-87, CJK UNIFIED IDEOGRAPH-5973 +U+5974(2,3);U+5974(2,3); # 37-59, CJK UNIFIED IDEOGRAPH-5974 +U+5978(2,3);U+5978(2,3); # 53-01, CJK UNIFIED IDEOGRAPH-5978 +U+597D(2,3);U+597D(2,3); # 25-05, CJK UNIFIED IDEOGRAPH-597D +U+5981(2,3);U+5981(2,3); # 53-02, CJK UNIFIED IDEOGRAPH-5981 +U+5982(2,3);U+5982(2,3); # 39-01, CJK UNIFIED IDEOGRAPH-5982 +U+5983(2,3);U+5983(2,3); # 40-62, CJK UNIFIED IDEOGRAPH-5983 +U+5984(2,3);U+5984(2,3); # 44-49, CJK UNIFIED IDEOGRAPH-5984 +U+598A(2,3);U+598A(2,3); # 39-05, CJK UNIFIED IDEOGRAPH-598A +U+598D(2,3);U+598D(2,3); # 53-11, CJK UNIFIED IDEOGRAPH-598D +U+5993(2,3);U+5993(2,3); # 21-24, CJK UNIFIED IDEOGRAPH-5993 +U+5996(2,3);U+5996(2,3); # 45-37, CJK UNIFIED IDEOGRAPH-5996 +U+5999(2,3);U+5999(2,3); # 44-15, CJK UNIFIED IDEOGRAPH-5999 +U+599B(2,3);U+599B(2,3); # 54-12, CJK UNIFIED IDEOGRAPH-599B +U+599D(2,3);U+599D(2,3); # 53-03, CJK UNIFIED IDEOGRAPH-599D +U+59A3(2,3);U+59A3(2,3); # 53-06, CJK UNIFIED IDEOGRAPH-59A3 +U+59A5(2,3);U+59A5(2,3); # 34-37, CJK UNIFIED IDEOGRAPH-59A5 +U+59A8(2,3);U+59A8(2,3); # 43-24, CJK UNIFIED IDEOGRAPH-59A8 +U+59AC(2,3);U+59AC(2,3); # 37-42, CJK UNIFIED IDEOGRAPH-59AC +U+59B2(2,3);U+59B2(2,3); # 53-07, CJK UNIFIED IDEOGRAPH-59B2 +U+59B9(2,3);U+59B9(2,3); # 43-69, CJK UNIFIED IDEOGRAPH-59B9 +U+59BB(2,3);U+59BB(2,3); # 26-42, CJK UNIFIED IDEOGRAPH-59BB +U+59BE(2,3);U+59BE(2,3); # 30-10, CJK UNIFIED IDEOGRAPH-59BE +U+59C6(2,3);U+59C6(2,3); # 53-08, CJK UNIFIED IDEOGRAPH-59C6 +U+59C9(2,3);U+59C9(2,3); # 27-48, CJK UNIFIED IDEOGRAPH-59C9 +U+59CB(2,3);U+59CB(2,3); # 27-47, CJK UNIFIED IDEOGRAPH-59CB +U+59D0(2,3);U+59D0(2,3); # 16-25, CJK UNIFIED IDEOGRAPH-59D0 +U+59D1(2,3);U+59D1(2,3); # 24-40, CJK UNIFIED IDEOGRAPH-59D1 +U+59D3(2,3);U+59D3(2,3); # 32-11, CJK UNIFIED IDEOGRAPH-59D3 +U+59D4(2,3);U+59D4(2,3); # 16-49, CJK UNIFIED IDEOGRAPH-59D4 +U+59D9(2,3);U+59D9(2,3); # 53-12, CJK UNIFIED IDEOGRAPH-59D9 +U+59DA(2,3);U+59DA(2,3); # 53-13, CJK UNIFIED IDEOGRAPH-59DA +U+59DC(2,3);U+59DC(2,3); # 53-10, CJK UNIFIED IDEOGRAPH-59DC +U+59E5(2,3);U+59E5(2,3); # 17-24, CJK UNIFIED IDEOGRAPH-59E5 +U+59E6(2,3);U+59E6(2,3); # 20-15, CJK UNIFIED IDEOGRAPH-59E6 +U+59E8(2,3);U+59E8(2,3); # 53-09, CJK UNIFIED IDEOGRAPH-59E8 +U+59EA(2,3);U+59EA(2,3); # 44-37, CJK UNIFIED IDEOGRAPH-59EA +U+59EB(2,3);U+59EB(2,3); # 41-17, CJK UNIFIED IDEOGRAPH-59EB +U+59F6(2,3);U+59F6(2,3); # 16-08, CJK UNIFIED IDEOGRAPH-59F6 +U+59FB(2,3);U+59FB(2,3); # 16-89, CJK UNIFIED IDEOGRAPH-59FB +U+59FF(2,3);U+59FF(2,3); # 27-49, CJK UNIFIED IDEOGRAPH-59FF +U+5A01(2,3);U+5A01(2,3); # 16-50, CJK UNIFIED IDEOGRAPH-5A01 +U+5A03(2,3);U+5A03(2,3); # 16-03, CJK UNIFIED IDEOGRAPH-5A03 +U+5A09(2,3);U+5A09(2,3); # 53-18, CJK UNIFIED IDEOGRAPH-5A09 +U+5A11(2,3);U+5A11(2,3); # 53-16, CJK UNIFIED IDEOGRAPH-5A11 +U+5A18(2,3);U+5A18(2,3); # 44-28, CJK UNIFIED IDEOGRAPH-5A18 +U+5A1A(2,3);U+5A1A(2,3); # 53-19, CJK UNIFIED IDEOGRAPH-5A1A +U+5A1C(2,3);U+5A1C(2,3); # 53-17, CJK UNIFIED IDEOGRAPH-5A1C +U+5A1F(2,3);U+5A1F(2,3); # 53-15, CJK UNIFIED IDEOGRAPH-5A1F +U+5A20(2,3);U+5A20(2,3); # 31-17, CJK UNIFIED IDEOGRAPH-5A20 +U+5A25(2,3);U+5A25(2,3); # 53-14, CJK UNIFIED IDEOGRAPH-5A25 +U+5A29(2,3);U+5A29(2,3); # 42-58, CJK UNIFIED IDEOGRAPH-5A29 +U+5A2F(2,3);U+5A2F(2,3); # 24-68, CJK UNIFIED IDEOGRAPH-5A2F +U+5A35(2,3);U+5A35(2,3); # 53-23, CJK UNIFIED IDEOGRAPH-5A35 +U+5A36(2,3);U+5A36(2,3); # 53-24, CJK UNIFIED IDEOGRAPH-5A36 +U+5A3C(2,3);U+5A3C(2,3); # 30-11, CJK UNIFIED IDEOGRAPH-5A3C +U+5A40(2,3);U+5A40(2,3); # 53-20, CJK UNIFIED IDEOGRAPH-5A40 +U+5A41(2,3);U+5A41(2,3); # 47-12, CJK UNIFIED IDEOGRAPH-5A41 +U+5A46(2,3);U+5A46(2,3); # 39-44, CJK UNIFIED IDEOGRAPH-5A46 +U+5A49(2,3);U+5A49(2,3); # 53-22, CJK UNIFIED IDEOGRAPH-5A49 +U+5A5A(2,3);U+5A5A(2,3); # 26-07, CJK UNIFIED IDEOGRAPH-5A5A +U+5A62(2,3);U+5A62(2,3); # 53-25, CJK UNIFIED IDEOGRAPH-5A62 +U+5A66(2,3);U+5A66(2,3); # 41-56, CJK UNIFIED IDEOGRAPH-5A66 +U+5A6A(2,3);U+5A6A(2,3); # 53-26, CJK UNIFIED IDEOGRAPH-5A6A +U+5A6C(2,3);U+5A6C(2,3); # 53-21, CJK UNIFIED IDEOGRAPH-5A6C +U+5A7F(2,3);U+5A7F(2,3); # 44-27, CJK UNIFIED IDEOGRAPH-5A7F +U+5A92(2,3);U+5A92(2,3); # 39-62, CJK UNIFIED IDEOGRAPH-5A92 +U+5A9A(2,3);U+5A9A(2,3); # 53-27, CJK UNIFIED IDEOGRAPH-5A9A +U+5A9B(2,3);U+5A9B(2,3); # 41-18, CJK UNIFIED IDEOGRAPH-5A9B +U+5ABC(2,3);U+5ABC(2,3); # 53-28, CJK UNIFIED IDEOGRAPH-5ABC +U+5ABD(2,3);U+5ABD(2,3); # 53-32, CJK UNIFIED IDEOGRAPH-5ABD +U+5ABE(2,3);U+5ABE(2,3); # 53-29, CJK UNIFIED IDEOGRAPH-5ABE +U+5AC1(2,3);U+5AC1(2,3); # 18-39, CJK UNIFIED IDEOGRAPH-5AC1 +U+5AC2(2,3);U+5AC2(2,3); # 53-31, CJK UNIFIED IDEOGRAPH-5AC2 +U+5AC9(2,3);U+5AC9(2,3); # 28-27, CJK UNIFIED IDEOGRAPH-5AC9 +U+5ACB(2,3);U+5ACB(2,3); # 53-30, CJK UNIFIED IDEOGRAPH-5ACB +U+5ACC(2,3);U+5ACC(2,3); # 23-89, CJK UNIFIED IDEOGRAPH-5ACC +U+5AD0(2,3);U+5AD0(2,3); # 53-44, CJK UNIFIED IDEOGRAPH-5AD0 +U+5AD6(2,3);U+5AD6(2,3); # 53-37, CJK UNIFIED IDEOGRAPH-5AD6 +U+5AD7(2,3);U+5AD7(2,3); # 53-34, CJK UNIFIED IDEOGRAPH-5AD7 +U+5AE1(2,3);U+5AE1(2,3); # 35-68, CJK UNIFIED IDEOGRAPH-5AE1 +U+5AE3(2,3);U+5AE3(2,3); # 53-33, CJK UNIFIED IDEOGRAPH-5AE3 +U+5AE6(2,3);U+5AE6(2,3); # 53-35, CJK UNIFIED IDEOGRAPH-5AE6 +U+5AE9(2,3);U+5AE9(2,3); # 53-36, CJK UNIFIED IDEOGRAPH-5AE9 +U+5AFA(2,3);U+5AFA(2,3); # 53-38, CJK UNIFIED IDEOGRAPH-5AFA +U+5AFB(2,3);U+5AFB(2,3); # 53-39, CJK UNIFIED IDEOGRAPH-5AFB +U+5B09(2,3);U+5B09(2,3); # 20-82, CJK UNIFIED IDEOGRAPH-5B09 +U+5B0B(2,3);U+5B0B(2,3); # 53-41, CJK UNIFIED IDEOGRAPH-5B0B +U+5B0C(2,3);U+5B0C(2,3); # 53-40, CJK UNIFIED IDEOGRAPH-5B0C +U+5B16(2,3);U+5B16(2,3); # 53-42, CJK UNIFIED IDEOGRAPH-5B16 +U+5B22(2,3);U+5B22(2,3); # 30-78, CJK UNIFIED IDEOGRAPH-5B22 +U+5B2A(2,3);U+5B2A(2,3); # 53-45, CJK UNIFIED IDEOGRAPH-5B2A +U+5B2C(2,3);U+5B2C(2,3); # 36-60, CJK UNIFIED IDEOGRAPH-5B2C +U+5B30(2,3);U+5B30(2,3); # 17-37, CJK UNIFIED IDEOGRAPH-5B30 +U+5B32(2,3);U+5B32(2,3); # 53-43, CJK UNIFIED IDEOGRAPH-5B32 +U+5B36(2,3);U+5B36(2,3); # 53-46, CJK UNIFIED IDEOGRAPH-5B36 +U+5B3E(2,3);U+5B3E(2,3); # 53-47, CJK UNIFIED IDEOGRAPH-5B3E +U+5B40(2,3);U+5B40(2,3); # 53-50, CJK UNIFIED IDEOGRAPH-5B40 +U+5B43(2,3);U+5B43(2,3); # 53-48, CJK UNIFIED IDEOGRAPH-5B43 +U+5B45(2,3);U+5B45(2,3); # 53-49, CJK UNIFIED IDEOGRAPH-5B45 +U+5B50(2,3);U+5B50(2,3); # 27-50, CJK UNIFIED IDEOGRAPH-5B50 +U+5B51(2,3);U+5B51(2,3); # 53-51, CJK UNIFIED IDEOGRAPH-5B51 +U+5B54(2,3);U+5B54(2,3); # 25-06, CJK UNIFIED IDEOGRAPH-5B54 +U+5B55(2,3);U+5B55(2,3); # 53-52, CJK UNIFIED IDEOGRAPH-5B55 +U+5B57(2,3);U+5B57(2,3); # 27-90, CJK UNIFIED IDEOGRAPH-5B57 +U+5B58(2,3);U+5B58(2,3); # 34-24, CJK UNIFIED IDEOGRAPH-5B58 +U+5B5A(2,3);U+5B5A(2,3); # 53-53, CJK UNIFIED IDEOGRAPH-5B5A +U+5B5B(2,3);U+5B5B(2,3); # 53-54, CJK UNIFIED IDEOGRAPH-5B5B +U+5B5C(2,3);U+5B5C(2,3); # 27-58, CJK UNIFIED IDEOGRAPH-5B5C +U+5B5D(2,3);U+5B5D(2,3); # 25-07, CJK UNIFIED IDEOGRAPH-5B5D +U+5B5F(2,3);U+5B5F(2,3); # 44-50, CJK UNIFIED IDEOGRAPH-5B5F +U+5B63(2,3);U+5B63(2,3); # 21-08, CJK UNIFIED IDEOGRAPH-5B63 +U+5B64(2,3);U+5B64(2,3); # 24-41, CJK UNIFIED IDEOGRAPH-5B64 +U+5B65(2,3);U+5B65(2,3); # 53-55, CJK UNIFIED IDEOGRAPH-5B65 +U+5B66(2,3);U+5B66(2,3); # 19-56, CJK UNIFIED IDEOGRAPH-5B66 +U+5B69(2,3);U+5B69(2,3); # 53-56, CJK UNIFIED IDEOGRAPH-5B69 +U+5B6B(2,3);U+5B6B(2,3); # 34-25, CJK UNIFIED IDEOGRAPH-5B6B +U+5B70(2,3);U+5B70(2,3); # 53-57, CJK UNIFIED IDEOGRAPH-5B70 +U+5B71(2,3);U+5B71(2,3); # 54-03, CJK UNIFIED IDEOGRAPH-5B71 +U+5B73(2,3);U+5B73(2,3); # 53-58, CJK UNIFIED IDEOGRAPH-5B73 +U+5B75(2,3);U+5B75(2,3); # 53-59, CJK UNIFIED IDEOGRAPH-5B75 +U+5B78(2,3);U+5B78(2,3); # 53-60, CJK UNIFIED IDEOGRAPH-5B78 +U+5B7A(2,3);U+5B7A(2,3); # 53-62, CJK UNIFIED IDEOGRAPH-5B7A +U+5B80(2,3);U+5B80(2,3); # 53-63, CJK UNIFIED IDEOGRAPH-5B80 +U+5B83(2,3);U+5B83(2,3); # 53-64, CJK UNIFIED IDEOGRAPH-5B83 +U+5B85(2,3);U+5B85(2,3); # 34-80, CJK UNIFIED IDEOGRAPH-5B85 +U+5B87(2,3);U+5B87(2,3); # 17-07, CJK UNIFIED IDEOGRAPH-5B87 +U+5B88(2,3);U+5B88(2,3); # 28-73, CJK UNIFIED IDEOGRAPH-5B88 +U+5B89(2,3);U+5B89(2,3); # 16-34, CJK UNIFIED IDEOGRAPH-5B89 +U+5B8B(2,3);U+5B8B(2,3); # 33-55, CJK UNIFIED IDEOGRAPH-5B8B +U+5B8C(2,3);U+5B8C(2,3); # 20-16, CJK UNIFIED IDEOGRAPH-5B8C +U+5B8D(2,3);U+5B8D(2,3); # 28-21, CJK UNIFIED IDEOGRAPH-5B8D +U+5B8F(2,3);U+5B8F(2,3); # 25-08, CJK UNIFIED IDEOGRAPH-5B8F +U+5B95(2,3);U+5B95(2,3); # 37-70, CJK UNIFIED IDEOGRAPH-5B95 +U+5B97(2,3);U+5B97(2,3); # 29-01, CJK UNIFIED IDEOGRAPH-5B97 +U+5B98(2,3);U+5B98(2,3); # 20-17, CJK UNIFIED IDEOGRAPH-5B98 +U+5B99(2,3);U+5B99(2,3); # 35-72, CJK UNIFIED IDEOGRAPH-5B99 +U+5B9A(2,3);U+5B9A(2,3); # 36-74, CJK UNIFIED IDEOGRAPH-5B9A +U+5B9B(2,3);U+5B9B(2,3); # 16-24, CJK UNIFIED IDEOGRAPH-5B9B +U+5B9C(2,3);U+5B9C(2,3); # 21-25, CJK UNIFIED IDEOGRAPH-5B9C +U+5B9D(2,3);U+5B9D(2,3); # 42-85, CJK UNIFIED IDEOGRAPH-5B9D +U+5B9F(2,3);U+5B9F(2,3); # 28-34, CJK UNIFIED IDEOGRAPH-5B9F +U+5BA2(2,3);U+5BA2(2,3); # 21-50, CJK UNIFIED IDEOGRAPH-5BA2 +U+5BA3(2,3);U+5BA3(2,3); # 32-75, CJK UNIFIED IDEOGRAPH-5BA3 +U+5BA4(2,3);U+5BA4(2,3); # 28-28, CJK UNIFIED IDEOGRAPH-5BA4 +U+5BA5(2,3);U+5BA5(2,3); # 45-08, CJK UNIFIED IDEOGRAPH-5BA5 +U+5BA6(2,3);U+5BA6(2,3); # 53-65, CJK UNIFIED IDEOGRAPH-5BA6 +U+5BAE(2,3);U+5BAE(2,3); # 21-60, CJK UNIFIED IDEOGRAPH-5BAE +U+5BB0(2,3);U+5BB0(2,3); # 26-43, CJK UNIFIED IDEOGRAPH-5BB0 +U+5BB3(2,3);U+5BB3(2,3); # 19-18, CJK UNIFIED IDEOGRAPH-5BB3 +U+5BB4(2,3);U+5BB4(2,3); # 17-67, CJK UNIFIED IDEOGRAPH-5BB4 +U+5BB5(2,3);U+5BB5(2,3); # 30-12, CJK UNIFIED IDEOGRAPH-5BB5 +U+5BB6(2,3);U+5BB6(2,3); # 18-40, CJK UNIFIED IDEOGRAPH-5BB6 +U+5BB8(2,3);U+5BB8(2,3); # 53-66, CJK UNIFIED IDEOGRAPH-5BB8 +U+5BB9(2,3);U+5BB9(2,3); # 45-38, CJK UNIFIED IDEOGRAPH-5BB9 +U+5BBF(2,3);U+5BBF(2,3); # 29-41, CJK UNIFIED IDEOGRAPH-5BBF +U+5BC2(2,3);U+5BC2(2,3); # 28-68, CJK UNIFIED IDEOGRAPH-5BC2 +U+5BC3(2,3);U+5BC3(2,3); # 53-67, CJK UNIFIED IDEOGRAPH-5BC3 +U+5BC4(2,3);U+5BC4(2,3); # 20-83, CJK UNIFIED IDEOGRAPH-5BC4 +U+5BC5(2,3);U+5BC5(2,3); # 38-50, CJK UNIFIED IDEOGRAPH-5BC5 +U+5BC6(2,3);U+5BC6(2,3); # 44-09, CJK UNIFIED IDEOGRAPH-5BC6 +U+5BC7(2,3);U+5BC7(2,3); # 53-68, CJK UNIFIED IDEOGRAPH-5BC7 +U+5BC9(2,3);U+5BC9(2,3); # 53-69, CJK UNIFIED IDEOGRAPH-5BC9 +U+5BCC(2,3);U+5BCC(2,3); # 41-57, CJK UNIFIED IDEOGRAPH-5BCC +U+5BD0(2,3);U+5BD0(2,3); # 53-71, CJK UNIFIED IDEOGRAPH-5BD0 +U+5BD2(2,3);U+5BD2(2,3); # 20-08, CJK UNIFIED IDEOGRAPH-5BD2 +U+5BD3(2,3);U+5BD3(2,3); # 22-87, CJK UNIFIED IDEOGRAPH-5BD3 +U+5BD4(2,3);U+5BD4(2,3); # 53-70, CJK UNIFIED IDEOGRAPH-5BD4 +U+5BDB(2,3);U+5BDB(2,3); # 20-18, CJK UNIFIED IDEOGRAPH-5BDB +U+5BDD(2,3);U+5BDD(2,3); # 31-18, CJK UNIFIED IDEOGRAPH-5BDD +U+5BDE(2,3);U+5BDE(2,3); # 53-75, CJK UNIFIED IDEOGRAPH-5BDE +U+5BDF(2,3);U+5BDF(2,3); # 27-01, CJK UNIFIED IDEOGRAPH-5BDF +U+5BE1(2,3);U+5BE1(2,3); # 18-41, CJK UNIFIED IDEOGRAPH-5BE1 +U+5BE2(2,3);U+5BE2(2,3); # 53-74, CJK UNIFIED IDEOGRAPH-5BE2 +U+5BE4(2,3);U+5BE4(2,3); # 53-72, CJK UNIFIED IDEOGRAPH-5BE4 +U+5BE5(2,3);U+5BE5(2,3); # 53-76, CJK UNIFIED IDEOGRAPH-5BE5 +U+5BE6(2,3);U+5BE6(2,3); # 53-73, CJK UNIFIED IDEOGRAPH-5BE6 +U+5BE7(2,3);U+5BE7(2,3); # 39-11, CJK UNIFIED IDEOGRAPH-5BE7 +U+5BE8(2,3);U+5BE8(2,3); # 60-45, CJK UNIFIED IDEOGRAPH-5BE8 +U+5BE9(2,3);U+5BE9(2,3); # 31-19, CJK UNIFIED IDEOGRAPH-5BE9 +U+5BEB(2,3);U+5BEB(2,3); # 53-77, CJK UNIFIED IDEOGRAPH-5BEB +U+5BEE(2,3);U+5BEE(2,3); # 46-32, CJK UNIFIED IDEOGRAPH-5BEE +U+5BF0(2,3);U+5BF0(2,3); # 53-78, CJK UNIFIED IDEOGRAPH-5BF0 +U+5BF3(2,3);U+5BF3(2,3); # 53-80, CJK UNIFIED IDEOGRAPH-5BF3 +U+5BF5(2,3);U+5BF5(2,3); # 35-94, CJK UNIFIED IDEOGRAPH-5BF5 +U+5BF6(2,3);U+5BF6(2,3); # 53-79, CJK UNIFIED IDEOGRAPH-5BF6 +U+5BF8(2,3);U+5BF8(2,3); # 32-03, CJK UNIFIED IDEOGRAPH-5BF8 +U+5BFA(2,3);U+5BFA(2,3); # 27-91, CJK UNIFIED IDEOGRAPH-5BFA +U+5BFE(2,3);U+5BFE(2,3); # 34-48, CJK UNIFIED IDEOGRAPH-5BFE +U+5BFF(2,3);U+5BFF(2,3); # 28-87, CJK UNIFIED IDEOGRAPH-5BFF +U+5C01(2,3);U+5C01(2,3); # 41-85, CJK UNIFIED IDEOGRAPH-5C01 +U+5C02(2,3);U+5C02(2,3); # 32-76, CJK UNIFIED IDEOGRAPH-5C02 +U+5C04(2,3);U+5C04(2,3); # 28-45, CJK UNIFIED IDEOGRAPH-5C04 +U+5C05(2,3);U+5C05(2,3); # 53-81, CJK UNIFIED IDEOGRAPH-5C05 +U+5C06(2,3);U+5C06(2,3); # 30-13, CJK UNIFIED IDEOGRAPH-5C06 +U+5C07(2,3);U+5C07(2,3); # 53-82, CJK UNIFIED IDEOGRAPH-5C07 +U+5C08(2,3);U+5C08(2,3); # 53-83, CJK UNIFIED IDEOGRAPH-5C08 +U+5C09(2,3);U+5C09(2,3); # 16-51, CJK UNIFIED IDEOGRAPH-5C09 +U+5C0A(2,3);U+5C0A(2,3); # 34-26, CJK UNIFIED IDEOGRAPH-5C0A +U+5C0B(2,3);U+5C0B(2,3); # 31-50, CJK UNIFIED IDEOGRAPH-5C0B +U+5C0D(2,3);U+5C0D(2,3); # 53-84, CJK UNIFIED IDEOGRAPH-5C0D +U+5C0E(2,3);U+5C0E(2,3); # 38-19, CJK UNIFIED IDEOGRAPH-5C0E +U+5C0F(2,3);U+5C0F(2,3); # 30-14, CJK UNIFIED IDEOGRAPH-5C0F +U+5C11(2,3);U+5C11(2,3); # 30-15, CJK UNIFIED IDEOGRAPH-5C11 +U+5C13(2,3);U+5C13(2,3); # 53-85, CJK UNIFIED IDEOGRAPH-5C13 +U+5C16(2,3);U+5C16(2,3); # 32-77, CJK UNIFIED IDEOGRAPH-5C16 +U+5C1A(2,3);U+5C1A(2,3); # 30-16, CJK UNIFIED IDEOGRAPH-5C1A +U+5C20(2,3);U+5C20(2,3); # 53-86, CJK UNIFIED IDEOGRAPH-5C20 +U+5C22(2,3);U+5C22(2,3); # 53-87, CJK UNIFIED IDEOGRAPH-5C22 +U+5C24(2,3);U+5C24(2,3); # 44-64, CJK UNIFIED IDEOGRAPH-5C24 +U+5C28(2,3);U+5C28(2,3); # 53-88, CJK UNIFIED IDEOGRAPH-5C28 +U+5C2D(2,3);U+5C2D(2,3); # 22-38, CJK UNIFIED IDEOGRAPH-5C2D +U+5C31(2,3);U+5C31(2,3); # 29-02, CJK UNIFIED IDEOGRAPH-5C31 +U+5C38(2,3);U+5C38(2,3); # 53-89, CJK UNIFIED IDEOGRAPH-5C38 +U+5C39(2,3);U+5C39(2,3); # 53-90, CJK UNIFIED IDEOGRAPH-5C39 +U+5C3A(2,3);U+5C3A(2,3); # 28-60, CJK UNIFIED IDEOGRAPH-5C3A +U+5C3B(2,3);U+5C3B(2,3); # 31-12, CJK UNIFIED IDEOGRAPH-5C3B +U+5C3C(2,3);U+5C3C(2,3); # 38-84, CJK UNIFIED IDEOGRAPH-5C3C +U+5C3D(2,3);U+5C3D(2,3); # 31-52, CJK UNIFIED IDEOGRAPH-5C3D +U+5C3E(2,3);U+5C3E(2,3); # 40-88, CJK UNIFIED IDEOGRAPH-5C3E +U+5C3F(2,3);U+5C3F(2,3); # 39-02, CJK UNIFIED IDEOGRAPH-5C3F +U+5C40(2,3);U+5C40(2,3); # 22-41, CJK UNIFIED IDEOGRAPH-5C40 +U+5C41(2,3);U+5C41(2,3); # 53-91, CJK UNIFIED IDEOGRAPH-5C41 +U+5C45(2,3);U+5C45(2,3); # 21-79, CJK UNIFIED IDEOGRAPH-5C45 +U+5C46(2,3);U+5C46(2,3); # 53-92, CJK UNIFIED IDEOGRAPH-5C46 +U+5C48(2,3);U+5C48(2,3); # 22-94, CJK UNIFIED IDEOGRAPH-5C48 +U+5C4A(2,3);U+5C4A(2,3); # 38-47, CJK UNIFIED IDEOGRAPH-5C4A +U+5C4B(2,3);U+5C4B(2,3); # 18-16, CJK UNIFIED IDEOGRAPH-5C4B +U+5C4D(2,3);U+5C4D(2,3); # 27-51, CJK UNIFIED IDEOGRAPH-5C4D +U+5C4E(2,3);U+5C4E(2,3); # 53-93, CJK UNIFIED IDEOGRAPH-5C4E +U+5C4F(2,3);U+5C4F(2,3); # 54-02, CJK UNIFIED IDEOGRAPH-5C4F +U+5C50(2,3);U+5C50(2,3); # 54-01, CJK UNIFIED IDEOGRAPH-5C50 +U+5C51(2,3);U+5C51(2,3); # 22-93, CJK UNIFIED IDEOGRAPH-5C51 +U+5C53(2,3);U+5C53(2,3); # 53-94, CJK UNIFIED IDEOGRAPH-5C53 +U+5C55(2,3);U+5C55(2,3); # 37-24, CJK UNIFIED IDEOGRAPH-5C55 +U+5C5E(2,3);U+5C5E(2,3); # 34-16, CJK UNIFIED IDEOGRAPH-5C5E +U+5C60(2,3);U+5C60(2,3); # 37-43, CJK UNIFIED IDEOGRAPH-5C60 +U+5C61(2,3);U+5C61(2,3); # 28-40, CJK UNIFIED IDEOGRAPH-5C61 +U+5C64(2,3);U+5C64(2,3); # 33-56, CJK UNIFIED IDEOGRAPH-5C64 +U+5C65(2,3);U+5C65(2,3); # 45-90, CJK UNIFIED IDEOGRAPH-5C65 +U+5C6C(2,3);U+5C6C(2,3); # 54-04, CJK UNIFIED IDEOGRAPH-5C6C +U+5C6E(2,3);U+5C6E(2,3); # 54-05, CJK UNIFIED IDEOGRAPH-5C6E +U+5C6F(2,3);U+5C6F(2,3); # 38-54, CJK UNIFIED IDEOGRAPH-5C6F +U+5C71(2,3);U+5C71(2,3); # 27-19, CJK UNIFIED IDEOGRAPH-5C71 +U+5C76(2,3);U+5C76(2,3); # 54-07, CJK UNIFIED IDEOGRAPH-5C76 +U+5C79(2,3);U+5C79(2,3); # 54-08, CJK UNIFIED IDEOGRAPH-5C79 +U+5C8C(2,3);U+5C8C(2,3); # 54-09, CJK UNIFIED IDEOGRAPH-5C8C +U+5C90(2,3);U+5C90(2,3); # 20-84, CJK UNIFIED IDEOGRAPH-5C90 +U+5C91(2,3);U+5C91(2,3); # 54-10, CJK UNIFIED IDEOGRAPH-5C91 +U+5C94(2,3);U+5C94(2,3); # 54-11, CJK UNIFIED IDEOGRAPH-5C94 +U+5CA1(2,3);U+5CA1(2,3); # 18-12, CJK UNIFIED IDEOGRAPH-5CA1 +U+5CA8(2,3);U+5CA8(2,3); # 33-27, CJK UNIFIED IDEOGRAPH-5CA8 +U+5CA9(2,3);U+5CA9(2,3); # 20-68, CJK UNIFIED IDEOGRAPH-5CA9 +U+5CAB(2,3);U+5CAB(2,3); # 54-13, CJK UNIFIED IDEOGRAPH-5CAB +U+5CAC(2,3);U+5CAC(2,3); # 44-08, CJK UNIFIED IDEOGRAPH-5CAC +U+5CB1(2,3);U+5CB1(2,3); # 34-50, CJK UNIFIED IDEOGRAPH-5CB1 +U+5CB3(2,3);U+5CB3(2,3); # 19-57, CJK UNIFIED IDEOGRAPH-5CB3 +U+5CB6(2,3);U+5CB6(2,3); # 54-15, CJK UNIFIED IDEOGRAPH-5CB6 +U+5CB7(2,3);U+5CB7(2,3); # 54-17, CJK UNIFIED IDEOGRAPH-5CB7 +U+5CB8(2,3);U+5CB8(2,3); # 20-63, CJK UNIFIED IDEOGRAPH-5CB8 +U+5CBB(2,3);U+5CBB(2,3); # 54-14, CJK UNIFIED IDEOGRAPH-5CBB +U+5CBC(2,3);U+5CBC(2,3); # 54-16, CJK UNIFIED IDEOGRAPH-5CBC +U+5CBE(2,3);U+5CBE(2,3); # 54-19, CJK UNIFIED IDEOGRAPH-5CBE +U+5CC5(2,3);U+5CC5(2,3); # 54-18, CJK UNIFIED IDEOGRAPH-5CC5 +U+5CC7(2,3);U+5CC7(2,3); # 54-20, CJK UNIFIED IDEOGRAPH-5CC7 +U+5CD9(2,3);U+5CD9(2,3); # 54-21, CJK UNIFIED IDEOGRAPH-5CD9 +U+5CE0(2,3);U+5CE0(2,3); # 38-29, CJK UNIFIED IDEOGRAPH-5CE0 +U+5CE1(2,3);U+5CE1(2,3); # 22-14, CJK UNIFIED IDEOGRAPH-5CE1 +U+5CE8(2,3);U+5CE8(2,3); # 18-69, CJK UNIFIED IDEOGRAPH-5CE8 +U+5CE9(2,3);U+5CE9(2,3); # 54-22, CJK UNIFIED IDEOGRAPH-5CE9 +U+5CEA(2,3);U+5CEA(2,3); # 54-27, CJK UNIFIED IDEOGRAPH-5CEA +U+5CED(2,3);U+5CED(2,3); # 54-25, CJK UNIFIED IDEOGRAPH-5CED +U+5CEF(2,3);U+5CEF(2,3); # 42-87, CJK UNIFIED IDEOGRAPH-5CEF +U+5CF0(2,3);U+5CF0(2,3); # 42-86, CJK UNIFIED IDEOGRAPH-5CF0 +U+5CF6(2,3);U+5CF6(2,3); # 37-71, CJK UNIFIED IDEOGRAPH-5CF6 +U+5CFA(2,3);U+5CFA(2,3); # 54-24, CJK UNIFIED IDEOGRAPH-5CFA +U+5CFB(2,3);U+5CFB(2,3); # 29-52, CJK UNIFIED IDEOGRAPH-5CFB +U+5CFD(2,3);U+5CFD(2,3); # 54-23, CJK UNIFIED IDEOGRAPH-5CFD +U+5D07(2,3);U+5D07(2,3); # 31-82, CJK UNIFIED IDEOGRAPH-5D07 +U+5D0B(2,3);U+5D0B(2,3); # 54-28, CJK UNIFIED IDEOGRAPH-5D0B +U+5D0E(2,3);U+5D0E(2,3); # 26-74, CJK UNIFIED IDEOGRAPH-5D0E +U+5D11(2,3);U+5D11(2,3); # 54-34, CJK UNIFIED IDEOGRAPH-5D11 +U+5D14(2,3);U+5D14(2,3); # 54-35, CJK UNIFIED IDEOGRAPH-5D14 +U+5D15(2,3);U+5D15(2,3); # 54-29, CJK UNIFIED IDEOGRAPH-5D15 +U+5D16(2,3);U+5D16(2,3); # 19-19, CJK UNIFIED IDEOGRAPH-5D16 +U+5D17(2,3);U+5D17(2,3); # 54-30, CJK UNIFIED IDEOGRAPH-5D17 +U+5D18(2,3);U+5D18(2,3); # 54-39, CJK UNIFIED IDEOGRAPH-5D18 +U+5D19(2,3);U+5D19(2,3); # 54-38, CJK UNIFIED IDEOGRAPH-5D19 +U+5D1A(2,3);U+5D1A(2,3); # 54-37, CJK UNIFIED IDEOGRAPH-5D1A +U+5D1B(2,3);U+5D1B(2,3); # 54-33, CJK UNIFIED IDEOGRAPH-5D1B +U+5D1F(2,3);U+5D1F(2,3); # 54-32, CJK UNIFIED IDEOGRAPH-5D1F +U+5D22(2,3);U+5D22(2,3); # 54-36, CJK UNIFIED IDEOGRAPH-5D22 +U+5D29(2,3);U+5D29(2,3); # 42-88, CJK UNIFIED IDEOGRAPH-5D29 +U+5D4B(2,3);U+5D4B(2,3); # 54-43, CJK UNIFIED IDEOGRAPH-5D4B +U+5D4C(2,3);U+5D4C(2,3); # 54-40, CJK UNIFIED IDEOGRAPH-5D4C +U+5D4E(2,3);U+5D4E(2,3); # 54-42, CJK UNIFIED IDEOGRAPH-5D4E +U+5D50(2,3);U+5D50(2,3); # 45-82, CJK UNIFIED IDEOGRAPH-5D50 +U+5D52(2,3);U+5D52(2,3); # 54-41, CJK UNIFIED IDEOGRAPH-5D52 +U+5D5C(2,3);U+5D5C(2,3); # 54-31, CJK UNIFIED IDEOGRAPH-5D5C +U+5D69(2,3);U+5D69(2,3); # 31-83, CJK UNIFIED IDEOGRAPH-5D69 +U+5D6C(2,3);U+5D6C(2,3); # 54-44, CJK UNIFIED IDEOGRAPH-5D6C +U+5D6F(2,3);U+5D6F(2,3); # 26-23, CJK UNIFIED IDEOGRAPH-5D6F +U+5D73(2,3);U+5D73(2,3); # 54-45, CJK UNIFIED IDEOGRAPH-5D73 +U+5D76(2,3);U+5D76(2,3); # 54-46, CJK UNIFIED IDEOGRAPH-5D76 +U+5D82(2,3);U+5D82(2,3); # 54-49, CJK UNIFIED IDEOGRAPH-5D82 +U+5D84(2,3);U+5D84(2,3); # 54-48, CJK UNIFIED IDEOGRAPH-5D84 +U+5D87(2,3);U+5D87(2,3); # 54-47, CJK UNIFIED IDEOGRAPH-5D87 +U+5D8B(2,3);U+5D8B(2,3); # 37-72, CJK UNIFIED IDEOGRAPH-5D8B +U+5D8C(2,3);U+5D8C(2,3); # 54-26, CJK UNIFIED IDEOGRAPH-5D8C +U+5D90(2,3);U+5D90(2,3); # 54-55, CJK UNIFIED IDEOGRAPH-5D90 +U+5D9D(2,3);U+5D9D(2,3); # 54-51, CJK UNIFIED IDEOGRAPH-5D9D +U+5DA2(2,3);U+5DA2(2,3); # 54-50, CJK UNIFIED IDEOGRAPH-5DA2 +U+5DAC(2,3);U+5DAC(2,3); # 54-52, CJK UNIFIED IDEOGRAPH-5DAC +U+5DAE(2,3);U+5DAE(2,3); # 54-53, CJK UNIFIED IDEOGRAPH-5DAE +U+5DB7(2,3);U+5DB7(2,3); # 54-56, CJK UNIFIED IDEOGRAPH-5DB7 +U+5DBA(2,3);U+5DBA(2,3); # 46-70, CJK UNIFIED IDEOGRAPH-5DBA +U+5DBC(2,3);U+5DBC(2,3); # 54-57, CJK UNIFIED IDEOGRAPH-5DBC +U+5DBD(2,3);U+5DBD(2,3); # 54-54, CJK UNIFIED IDEOGRAPH-5DBD +U+5DC9(2,3);U+5DC9(2,3); # 54-58, CJK UNIFIED IDEOGRAPH-5DC9 +U+5DCC(2,3);U+5DCC(2,3); # 20-64, CJK UNIFIED IDEOGRAPH-5DCC +U+5DCD(2,3);U+5DCD(2,3); # 54-59, CJK UNIFIED IDEOGRAPH-5DCD +U+5DD2(2,3);U+5DD2(2,3); # 54-61, CJK UNIFIED IDEOGRAPH-5DD2 +U+5DD3(2,3);U+5DD3(2,3); # 54-60, CJK UNIFIED IDEOGRAPH-5DD3 +U+5DD6(2,3);U+5DD6(2,3); # 54-62, CJK UNIFIED IDEOGRAPH-5DD6 +U+5DDB(2,3);U+5DDB(2,3); # 54-63, CJK UNIFIED IDEOGRAPH-5DDB +U+5DDD(2,3);U+5DDD(2,3); # 32-78, CJK UNIFIED IDEOGRAPH-5DDD +U+5DDE(2,3);U+5DDE(2,3); # 29-03, CJK UNIFIED IDEOGRAPH-5DDE +U+5DE1(2,3);U+5DE1(2,3); # 29-68, CJK UNIFIED IDEOGRAPH-5DE1 +U+5DE3(2,3);U+5DE3(2,3); # 33-67, CJK UNIFIED IDEOGRAPH-5DE3 +U+5DE5(2,3);U+5DE5(2,3); # 25-09, CJK UNIFIED IDEOGRAPH-5DE5 +U+5DE6(2,3);U+5DE6(2,3); # 26-24, CJK UNIFIED IDEOGRAPH-5DE6 +U+5DE7(2,3);U+5DE7(2,3); # 25-10, CJK UNIFIED IDEOGRAPH-5DE7 +U+5DE8(2,3);U+5DE8(2,3); # 21-80, CJK UNIFIED IDEOGRAPH-5DE8 +U+5DEB(2,3);U+5DEB(2,3); # 54-64, CJK UNIFIED IDEOGRAPH-5DEB +U+5DEE(2,3);U+5DEE(2,3); # 26-25, CJK UNIFIED IDEOGRAPH-5DEE +U+5DF1(2,3);U+5DF1(2,3); # 24-42, CJK UNIFIED IDEOGRAPH-5DF1 +U+5DF2(2,3);U+5DF2(2,3); # 54-65, CJK UNIFIED IDEOGRAPH-5DF2 +U+5DF3(2,3);U+5DF3(2,3); # 44-06, CJK UNIFIED IDEOGRAPH-5DF3 +U+5DF4(2,3);U+5DF4(2,3); # 39-35, CJK UNIFIED IDEOGRAPH-5DF4 +U+5DF5(2,3);U+5DF5(2,3); # 54-66, CJK UNIFIED IDEOGRAPH-5DF5 +U+5DF7(2,3);U+5DF7(2,3); # 25-11, CJK UNIFIED IDEOGRAPH-5DF7 +U+5DFB(2,3);U+5DFB(2,3); # 20-12, CJK UNIFIED IDEOGRAPH-5DFB +U+5DFD(2,3);U+5DFD(2,3); # 35-07, CJK UNIFIED IDEOGRAPH-5DFD +U+5DFE(2,3);U+5DFE(2,3); # 22-50, CJK UNIFIED IDEOGRAPH-5DFE +U+5E02(2,3);U+5E02(2,3); # 27-52, CJK UNIFIED IDEOGRAPH-5E02 +U+5E03(2,3);U+5E03(2,3); # 41-59, CJK UNIFIED IDEOGRAPH-5E03 +U+5E06(2,3);U+5E06(2,3); # 40-33, CJK UNIFIED IDEOGRAPH-5E06 +U+5E0B(2,3);U+5E0B(2,3); # 54-67, CJK UNIFIED IDEOGRAPH-5E0B +U+5E0C(2,3);U+5E0C(2,3); # 20-85, CJK UNIFIED IDEOGRAPH-5E0C +U+5E11(2,3);U+5E11(2,3); # 54-70, CJK UNIFIED IDEOGRAPH-5E11 +U+5E16(2,3);U+5E16(2,3); # 36-01, CJK UNIFIED IDEOGRAPH-5E16 +U+5E19(2,3);U+5E19(2,3); # 54-69, CJK UNIFIED IDEOGRAPH-5E19 +U+5E1A(2,3);U+5E1A(2,3); # 54-68, CJK UNIFIED IDEOGRAPH-5E1A +U+5E1B(2,3);U+5E1B(2,3); # 54-71, CJK UNIFIED IDEOGRAPH-5E1B +U+5E1D(2,3);U+5E1D(2,3); # 36-75, CJK UNIFIED IDEOGRAPH-5E1D +U+5E25(2,3);U+5E25(2,3); # 31-67, CJK UNIFIED IDEOGRAPH-5E25 +U+5E2B(2,3);U+5E2B(2,3); # 27-53, CJK UNIFIED IDEOGRAPH-5E2B +U+5E2D(2,3);U+5E2D(2,3); # 32-42, CJK UNIFIED IDEOGRAPH-5E2D +U+5E2F(2,3);U+5E2F(2,3); # 34-51, CJK UNIFIED IDEOGRAPH-5E2F +U+5E30(2,3);U+5E30(2,3); # 21-02, CJK UNIFIED IDEOGRAPH-5E30 +U+5E33(2,3);U+5E33(2,3); # 36-02, CJK UNIFIED IDEOGRAPH-5E33 +U+5E36(2,3);U+5E36(2,3); # 54-72, CJK UNIFIED IDEOGRAPH-5E36 +U+5E37(2,3);U+5E37(2,3); # 54-73, CJK UNIFIED IDEOGRAPH-5E37 +U+5E38(2,3);U+5E38(2,3); # 30-79, CJK UNIFIED IDEOGRAPH-5E38 +U+5E3D(2,3);U+5E3D(2,3); # 43-25, CJK UNIFIED IDEOGRAPH-5E3D +U+5E40(2,3);U+5E40(2,3); # 54-76, CJK UNIFIED IDEOGRAPH-5E40 +U+5E43(2,3);U+5E43(2,3); # 54-75, CJK UNIFIED IDEOGRAPH-5E43 +U+5E44(2,3);U+5E44(2,3); # 54-74, CJK UNIFIED IDEOGRAPH-5E44 +U+5E45(2,3);U+5E45(2,3); # 41-93, CJK UNIFIED IDEOGRAPH-5E45 +U+5E47(2,3);U+5E47(2,3); # 54-83, CJK UNIFIED IDEOGRAPH-5E47 +U+5E4C(2,3);U+5E4C(2,3); # 43-58, CJK UNIFIED IDEOGRAPH-5E4C +U+5E4E(2,3);U+5E4E(2,3); # 54-77, CJK UNIFIED IDEOGRAPH-5E4E +U+5E54(2,3);U+5E54(2,3); # 54-79, CJK UNIFIED IDEOGRAPH-5E54 +U+5E55(2,3);U+5E55(2,3); # 43-75, CJK UNIFIED IDEOGRAPH-5E55 +U+5E57(2,3);U+5E57(2,3); # 54-78, CJK UNIFIED IDEOGRAPH-5E57 +U+5E5F(2,3);U+5E5F(2,3); # 54-80, CJK UNIFIED IDEOGRAPH-5E5F +U+5E61(2,3);U+5E61(2,3); # 40-08, CJK UNIFIED IDEOGRAPH-5E61 +U+5E62(2,3);U+5E62(2,3); # 54-81, CJK UNIFIED IDEOGRAPH-5E62 +U+5E63(2,3);U+5E63(2,3); # 42-30, CJK UNIFIED IDEOGRAPH-5E63 +U+5E64(2,3);U+5E64(2,3); # 54-82, CJK UNIFIED IDEOGRAPH-5E64 +U+5E72(2,3);U+5E72(2,3); # 20-19, CJK UNIFIED IDEOGRAPH-5E72 +U+5E73(2,3);U+5E73(2,3); # 42-31, CJK UNIFIED IDEOGRAPH-5E73 +U+5E74(2,3);U+5E74(2,3); # 39-15, CJK UNIFIED IDEOGRAPH-5E74 +U+5E75(2,3);U+5E75(2,3); # 54-84, CJK UNIFIED IDEOGRAPH-5E75 +U+5E76(2,3);U+5E76(2,3); # 54-85, CJK UNIFIED IDEOGRAPH-5E76 +U+5E78(2,3);U+5E78(2,3); # 25-12, CJK UNIFIED IDEOGRAPH-5E78 +U+5E79(2,3);U+5E79(2,3); # 20-20, CJK UNIFIED IDEOGRAPH-5E79 +U+5E7A(2,3);U+5E7A(2,3); # 54-86, CJK UNIFIED IDEOGRAPH-5E7A +U+5E7B(2,3);U+5E7B(2,3); # 24-24, CJK UNIFIED IDEOGRAPH-5E7B +U+5E7C(2,3);U+5E7C(2,3); # 45-36, CJK UNIFIED IDEOGRAPH-5E7C +U+5E7D(2,3);U+5E7D(2,3); # 45-09, CJK UNIFIED IDEOGRAPH-5E7D +U+5E7E(2,3);U+5E7E(2,3); # 20-86, CJK UNIFIED IDEOGRAPH-5E7E +U+5E7F(2,3);U+5E7F(2,3); # 54-88, CJK UNIFIED IDEOGRAPH-5E7F +U+5E81(2,3);U+5E81(2,3); # 36-03, CJK UNIFIED IDEOGRAPH-5E81 +U+5E83(2,3);U+5E83(2,3); # 25-13, CJK UNIFIED IDEOGRAPH-5E83 +U+5E84(2,3);U+5E84(2,3); # 30-17, CJK UNIFIED IDEOGRAPH-5E84 +U+5E87(2,3);U+5E87(2,3); # 40-63, CJK UNIFIED IDEOGRAPH-5E87 +U+5E8A(2,3);U+5E8A(2,3); # 30-18, CJK UNIFIED IDEOGRAPH-5E8A +U+5E8F(2,3);U+5E8F(2,3); # 29-88, CJK UNIFIED IDEOGRAPH-5E8F +U+5E95(2,3);U+5E95(2,3); # 36-76, CJK UNIFIED IDEOGRAPH-5E95 +U+5E96(2,3);U+5E96(2,3); # 42-89, CJK UNIFIED IDEOGRAPH-5E96 +U+5E97(2,3);U+5E97(2,3); # 37-25, CJK UNIFIED IDEOGRAPH-5E97 +U+5E9A(2,3);U+5E9A(2,3); # 25-14, CJK UNIFIED IDEOGRAPH-5E9A +U+5E9C(2,3);U+5E9C(2,3); # 41-60, CJK UNIFIED IDEOGRAPH-5E9C +U+5EA0(2,3);U+5EA0(2,3); # 54-89, CJK UNIFIED IDEOGRAPH-5EA0 +U+5EA6(2,3);U+5EA6(2,3); # 37-57, CJK UNIFIED IDEOGRAPH-5EA6 +U+5EA7(2,3);U+5EA7(2,3); # 26-34, CJK UNIFIED IDEOGRAPH-5EA7 +U+5EAB(2,3);U+5EAB(2,3); # 24-43, CJK UNIFIED IDEOGRAPH-5EAB +U+5EAD(2,3);U+5EAD(2,3); # 36-77, CJK UNIFIED IDEOGRAPH-5EAD +U+5EB5(2,3);U+5EB5(2,3); # 16-35, CJK UNIFIED IDEOGRAPH-5EB5 +U+5EB6(2,3);U+5EB6(2,3); # 29-78, CJK UNIFIED IDEOGRAPH-5EB6 +U+5EB7(2,3);U+5EB7(2,3); # 25-15, CJK UNIFIED IDEOGRAPH-5EB7 +U+5EB8(2,3);U+5EB8(2,3); # 45-39, CJK UNIFIED IDEOGRAPH-5EB8 +U+5EC1(2,3);U+5EC1(2,3); # 54-90, CJK UNIFIED IDEOGRAPH-5EC1 +U+5EC2(2,3);U+5EC2(2,3); # 54-91, CJK UNIFIED IDEOGRAPH-5EC2 +U+5EC3(2,3);U+5EC3(2,3); # 39-49, CJK UNIFIED IDEOGRAPH-5EC3 +U+5EC8(2,3);U+5EC8(2,3); # 54-92, CJK UNIFIED IDEOGRAPH-5EC8 +U+5EC9(2,3);U+5EC9(2,3); # 46-87, CJK UNIFIED IDEOGRAPH-5EC9 +U+5ECA(2,3);U+5ECA(2,3); # 47-13, CJK UNIFIED IDEOGRAPH-5ECA +U+5ECF(2,3);U+5ECF(2,3); # 54-94, CJK UNIFIED IDEOGRAPH-5ECF +U+5ED0(2,3);U+5ED0(2,3); # 54-93, CJK UNIFIED IDEOGRAPH-5ED0 +U+5ED3(2,3);U+5ED3(2,3); # 19-39, CJK UNIFIED IDEOGRAPH-5ED3 +U+5ED6(2,3);U+5ED6(2,3); # 55-01, CJK UNIFIED IDEOGRAPH-5ED6 +U+5EDA(2,3);U+5EDA(2,3); # 55-04, CJK UNIFIED IDEOGRAPH-5EDA +U+5EDB(2,3);U+5EDB(2,3); # 55-05, CJK UNIFIED IDEOGRAPH-5EDB +U+5EDD(2,3);U+5EDD(2,3); # 55-03, CJK UNIFIED IDEOGRAPH-5EDD +U+5EDF(2,3);U+5EDF(2,3); # 41-32, CJK UNIFIED IDEOGRAPH-5EDF +U+5EE0(2,3);U+5EE0(2,3); # 30-19, CJK UNIFIED IDEOGRAPH-5EE0 +U+5EE1(2,3);U+5EE1(2,3); # 55-07, CJK UNIFIED IDEOGRAPH-5EE1 +U+5EE2(2,3);U+5EE2(2,3); # 55-06, CJK UNIFIED IDEOGRAPH-5EE2 +U+5EE3(2,3);U+5EE3(2,3); # 55-02, CJK UNIFIED IDEOGRAPH-5EE3 +U+5EE8(2,3);U+5EE8(2,3); # 55-08, CJK UNIFIED IDEOGRAPH-5EE8 +U+5EE9(2,3);U+5EE9(2,3); # 55-09, CJK UNIFIED IDEOGRAPH-5EE9 +U+5EEC(2,3);U+5EEC(2,3); # 55-10, CJK UNIFIED IDEOGRAPH-5EEC +U+5EF0(2,3);U+5EF0(2,3); # 55-13, CJK UNIFIED IDEOGRAPH-5EF0 +U+5EF1(2,3);U+5EF1(2,3); # 55-11, CJK UNIFIED IDEOGRAPH-5EF1 +U+5EF3(2,3);U+5EF3(2,3); # 55-12, CJK UNIFIED IDEOGRAPH-5EF3 +U+5EF4(2,3);U+5EF4(2,3); # 55-14, CJK UNIFIED IDEOGRAPH-5EF4 +U+5EF6(2,3);U+5EF6(2,3); # 17-68, CJK UNIFIED IDEOGRAPH-5EF6 +U+5EF7(2,3);U+5EF7(2,3); # 36-78, CJK UNIFIED IDEOGRAPH-5EF7 +U+5EF8(2,3);U+5EF8(2,3); # 55-15, CJK UNIFIED IDEOGRAPH-5EF8 +U+5EFA(2,3);U+5EFA(2,3); # 23-90, CJK UNIFIED IDEOGRAPH-5EFA +U+5EFB(2,3);U+5EFB(2,3); # 18-86, CJK UNIFIED IDEOGRAPH-5EFB +U+5EFC(2,3);U+5EFC(2,3); # 39-22, CJK UNIFIED IDEOGRAPH-5EFC +U+5EFE(2,3);U+5EFE(2,3); # 55-16, CJK UNIFIED IDEOGRAPH-5EFE +U+5EFF(2,3);U+5EFF(2,3); # 38-91, CJK UNIFIED IDEOGRAPH-5EFF +U+5F01(2,3);U+5F01(2,3); # 42-59, CJK UNIFIED IDEOGRAPH-5F01 +U+5F03(2,3);U+5F03(2,3); # 55-17, CJK UNIFIED IDEOGRAPH-5F03 +U+5F04(2,3);U+5F04(2,3); # 47-14, CJK UNIFIED IDEOGRAPH-5F04 +U+5F09(2,3);U+5F09(2,3); # 55-18, CJK UNIFIED IDEOGRAPH-5F09 +U+5F0A(2,3);U+5F0A(2,3); # 42-32, CJK UNIFIED IDEOGRAPH-5F0A +U+5F0B(2,3);U+5F0B(2,3); # 55-21, CJK UNIFIED IDEOGRAPH-5F0B +U+5F0C(2,3);U+5F0C(2,3); # 48-01, CJK UNIFIED IDEOGRAPH-5F0C +U+5F0D(2,3);U+5F0D(2,3); # 48-17, CJK UNIFIED IDEOGRAPH-5F0D +U+5F0F(2,3);U+5F0F(2,3); # 28-16, CJK UNIFIED IDEOGRAPH-5F0F +U+5F10(2,3);U+5F10(2,3); # 38-85, CJK UNIFIED IDEOGRAPH-5F10 +U+5F11(2,3);U+5F11(2,3); # 55-22, CJK UNIFIED IDEOGRAPH-5F11 +U+5F13(2,3);U+5F13(2,3); # 21-61, CJK UNIFIED IDEOGRAPH-5F13 +U+5F14(2,3);U+5F14(2,3); # 36-04, CJK UNIFIED IDEOGRAPH-5F14 +U+5F15(2,3);U+5F15(2,3); # 16-90, CJK UNIFIED IDEOGRAPH-5F15 +U+5F16(2,3);U+5F16(2,3); # 55-23, CJK UNIFIED IDEOGRAPH-5F16 +U+5F17(2,3);U+5F17(2,3); # 42-06, CJK UNIFIED IDEOGRAPH-5F17 +U+5F18(2,3);U+5F18(2,3); # 25-16, CJK UNIFIED IDEOGRAPH-5F18 +U+5F1B(2,3);U+5F1B(2,3); # 35-48, CJK UNIFIED IDEOGRAPH-5F1B +U+5F1F(2,3);U+5F1F(2,3); # 36-79, CJK UNIFIED IDEOGRAPH-5F1F +U+5F25(2,3);U+5F25(2,3); # 44-79, CJK UNIFIED IDEOGRAPH-5F25 +U+5F26(2,3);U+5F26(2,3); # 24-25, CJK UNIFIED IDEOGRAPH-5F26 +U+5F27(2,3);U+5F27(2,3); # 24-44, CJK UNIFIED IDEOGRAPH-5F27 +U+5F29(2,3);U+5F29(2,3); # 55-24, CJK UNIFIED IDEOGRAPH-5F29 +U+5F2D(2,3);U+5F2D(2,3); # 55-25, CJK UNIFIED IDEOGRAPH-5F2D +U+5F2F(2,3);U+5F2F(2,3); # 55-31, CJK UNIFIED IDEOGRAPH-5F2F +U+5F31(2,3);U+5F31(2,3); # 28-69, CJK UNIFIED IDEOGRAPH-5F31 +U+5F35(2,3);U+5F35(2,3); # 36-05, CJK UNIFIED IDEOGRAPH-5F35 +U+5F37(2,3);U+5F37(2,3); # 22-15, CJK UNIFIED IDEOGRAPH-5F37 +U+5F38(2,3);U+5F38(2,3); # 55-26, CJK UNIFIED IDEOGRAPH-5F38 +U+5F3C(2,3);U+5F3C(2,3); # 41-11, CJK UNIFIED IDEOGRAPH-5F3C +U+5F3E(2,3);U+5F3E(2,3); # 35-38, CJK UNIFIED IDEOGRAPH-5F3E +U+5F41(2,3);U+5F41(2,3); # 55-27, CJK UNIFIED IDEOGRAPH-5F41 +U+5F48(2,3);U+5F48(2,3); # 55-28, CJK UNIFIED IDEOGRAPH-5F48 +U+5F4A(2,3);U+5F4A(2,3); # 22-16, CJK UNIFIED IDEOGRAPH-5F4A +U+5F4C(2,3);U+5F4C(2,3); # 55-29, CJK UNIFIED IDEOGRAPH-5F4C +U+5F4E(2,3);U+5F4E(2,3); # 55-30, CJK UNIFIED IDEOGRAPH-5F4E +U+5F51(2,3);U+5F51(2,3); # 55-32, CJK UNIFIED IDEOGRAPH-5F51 +U+5F53(2,3);U+5F53(2,3); # 37-86, CJK UNIFIED IDEOGRAPH-5F53 +U+5F56(2,3);U+5F56(2,3); # 55-33, CJK UNIFIED IDEOGRAPH-5F56 +U+5F57(2,3);U+5F57(2,3); # 55-34, CJK UNIFIED IDEOGRAPH-5F57 +U+5F59(2,3);U+5F59(2,3); # 55-35, CJK UNIFIED IDEOGRAPH-5F59 +U+5F5C(2,3);U+5F5C(2,3); # 55-20, CJK UNIFIED IDEOGRAPH-5F5C +U+5F5D(2,3);U+5F5D(2,3); # 55-19, CJK UNIFIED IDEOGRAPH-5F5D +U+5F61(2,3);U+5F61(2,3); # 55-36, CJK UNIFIED IDEOGRAPH-5F61 +U+5F62(2,3);U+5F62(2,3); # 23-33, CJK UNIFIED IDEOGRAPH-5F62 +U+5F66(2,3);U+5F66(2,3); # 41-07, CJK UNIFIED IDEOGRAPH-5F66 +U+5F69(2,3);U+5F69(2,3); # 26-44, CJK UNIFIED IDEOGRAPH-5F69 +U+5F6A(2,3);U+5F6A(2,3); # 41-23, CJK UNIFIED IDEOGRAPH-5F6A +U+5F6B(2,3);U+5F6B(2,3); # 36-06, CJK UNIFIED IDEOGRAPH-5F6B +U+5F6C(2,3);U+5F6C(2,3); # 41-43, CJK UNIFIED IDEOGRAPH-5F6C +U+5F6D(2,3);U+5F6D(2,3); # 55-37, CJK UNIFIED IDEOGRAPH-5F6D +U+5F70(2,3);U+5F70(2,3); # 30-20, CJK UNIFIED IDEOGRAPH-5F70 +U+5F71(2,3);U+5F71(2,3); # 17-38, CJK UNIFIED IDEOGRAPH-5F71 +U+5F73(2,3);U+5F73(2,3); # 55-38, CJK UNIFIED IDEOGRAPH-5F73 +U+5F77(2,3);U+5F77(2,3); # 55-39, CJK UNIFIED IDEOGRAPH-5F77 +U+5F79(2,3);U+5F79(2,3); # 44-82, CJK UNIFIED IDEOGRAPH-5F79 +U+5F7C(2,3);U+5F7C(2,3); # 40-64, CJK UNIFIED IDEOGRAPH-5F7C +U+5F7F(2,3);U+5F7F(2,3); # 55-42, CJK UNIFIED IDEOGRAPH-5F7F +U+5F80(2,3);U+5F80(2,3); # 17-93, CJK UNIFIED IDEOGRAPH-5F80 +U+5F81(2,3);U+5F81(2,3); # 32-12, CJK UNIFIED IDEOGRAPH-5F81 +U+5F82(2,3);U+5F82(2,3); # 55-41, CJK UNIFIED IDEOGRAPH-5F82 +U+5F83(2,3);U+5F83(2,3); # 55-40, CJK UNIFIED IDEOGRAPH-5F83 +U+5F84(2,3);U+5F84(2,3); # 23-34, CJK UNIFIED IDEOGRAPH-5F84 +U+5F85(2,3);U+5F85(2,3); # 34-52, CJK UNIFIED IDEOGRAPH-5F85 +U+5F87(2,3);U+5F87(2,3); # 55-46, CJK UNIFIED IDEOGRAPH-5F87 +U+5F88(2,3);U+5F88(2,3); # 55-44, CJK UNIFIED IDEOGRAPH-5F88 +U+5F8A(2,3);U+5F8A(2,3); # 55-43, CJK UNIFIED IDEOGRAPH-5F8A +U+5F8B(2,3);U+5F8B(2,3); # 46-07, CJK UNIFIED IDEOGRAPH-5F8B +U+5F8C(2,3);U+5F8C(2,3); # 24-69, CJK UNIFIED IDEOGRAPH-5F8C +U+5F90(2,3);U+5F90(2,3); # 29-89, CJK UNIFIED IDEOGRAPH-5F90 +U+5F91(2,3);U+5F91(2,3); # 55-45, CJK UNIFIED IDEOGRAPH-5F91 +U+5F92(2,3);U+5F92(2,3); # 37-44, CJK UNIFIED IDEOGRAPH-5F92 +U+5F93(2,3);U+5F93(2,3); # 29-30, CJK UNIFIED IDEOGRAPH-5F93 +U+5F97(2,3);U+5F97(2,3); # 38-32, CJK UNIFIED IDEOGRAPH-5F97 +U+5F98(2,3);U+5F98(2,3); # 55-49, CJK UNIFIED IDEOGRAPH-5F98 +U+5F99(2,3);U+5F99(2,3); # 55-48, CJK UNIFIED IDEOGRAPH-5F99 +U+5F9E(2,3);U+5F9E(2,3); # 55-47, CJK UNIFIED IDEOGRAPH-5F9E +U+5FA0(2,3);U+5FA0(2,3); # 55-50, CJK UNIFIED IDEOGRAPH-5FA0 +U+5FA1(2,3);U+5FA1(2,3); # 24-70, CJK UNIFIED IDEOGRAPH-5FA1 +U+5FA8(2,3);U+5FA8(2,3); # 55-51, CJK UNIFIED IDEOGRAPH-5FA8 +U+5FA9(2,3);U+5FA9(2,3); # 41-92, CJK UNIFIED IDEOGRAPH-5FA9 +U+5FAA(2,3);U+5FAA(2,3); # 29-59, CJK UNIFIED IDEOGRAPH-5FAA +U+5FAD(2,3);U+5FAD(2,3); # 55-52, CJK UNIFIED IDEOGRAPH-5FAD +U+5FAE(2,3);U+5FAE(2,3); # 40-89, CJK UNIFIED IDEOGRAPH-5FAE +U+5FB3(2,3);U+5FB3(2,3); # 38-33, CJK UNIFIED IDEOGRAPH-5FB3 +U+5FB4(2,3);U+5FB4(2,3); # 36-07, CJK UNIFIED IDEOGRAPH-5FB4 +U+5FB9(2,3);U+5FB9(2,3); # 37-16, CJK UNIFIED IDEOGRAPH-5FB9 +U+5FBC(2,3);U+5FBC(2,3); # 55-53, CJK UNIFIED IDEOGRAPH-5FBC +U+5FBD(2,3);U+5FBD(2,3); # 21-11, CJK UNIFIED IDEOGRAPH-5FBD +U+5FC3(2,3);U+5FC3(2,3); # 31-20, CJK UNIFIED IDEOGRAPH-5FC3 +U+5FC5(2,3);U+5FC5(2,3); # 41-12, CJK UNIFIED IDEOGRAPH-5FC5 +U+5FCC(2,3);U+5FCC(2,3); # 20-87, CJK UNIFIED IDEOGRAPH-5FCC +U+5FCD(2,3);U+5FCD(2,3); # 39-06, CJK UNIFIED IDEOGRAPH-5FCD +U+5FD6(2,3);U+5FD6(2,3); # 55-54, CJK UNIFIED IDEOGRAPH-5FD6 +U+5FD7(2,3);U+5FD7(2,3); # 27-54, CJK UNIFIED IDEOGRAPH-5FD7 +U+5FD8(2,3);U+5FD8(2,3); # 43-26, CJK UNIFIED IDEOGRAPH-5FD8 +U+5FD9(2,3);U+5FD9(2,3); # 43-27, CJK UNIFIED IDEOGRAPH-5FD9 +U+5FDC(2,3);U+5FDC(2,3); # 17-94, CJK UNIFIED IDEOGRAPH-5FDC +U+5FDD(2,3);U+5FDD(2,3); # 55-59, CJK UNIFIED IDEOGRAPH-5FDD +U+5FE0(2,3);U+5FE0(2,3); # 35-73, CJK UNIFIED IDEOGRAPH-5FE0 +U+5FE4(2,3);U+5FE4(2,3); # 55-56, CJK UNIFIED IDEOGRAPH-5FE4 +U+5FEB(2,3);U+5FEB(2,3); # 18-87, CJK UNIFIED IDEOGRAPH-5FEB +U+5FF0(2,3);U+5FF0(2,3); # 56-13, CJK UNIFIED IDEOGRAPH-5FF0 +U+5FF1(2,3);U+5FF1(2,3); # 55-58, CJK UNIFIED IDEOGRAPH-5FF1 +U+5FF5(2,3);U+5FF5(2,3); # 39-16, CJK UNIFIED IDEOGRAPH-5FF5 +U+5FF8(2,3);U+5FF8(2,3); # 55-57, CJK UNIFIED IDEOGRAPH-5FF8 +U+5FFB(2,3);U+5FFB(2,3); # 55-55, CJK UNIFIED IDEOGRAPH-5FFB +U+5FFD(2,3);U+5FFD(2,3); # 25-90, CJK UNIFIED IDEOGRAPH-5FFD +U+5FFF(2,3);U+5FFF(2,3); # 55-61, CJK UNIFIED IDEOGRAPH-5FFF +U+600E(2,3);U+600E(2,3); # 55-67, CJK UNIFIED IDEOGRAPH-600E +U+600F(2,3);U+600F(2,3); # 55-73, CJK UNIFIED IDEOGRAPH-600F +U+6010(2,3);U+6010(2,3); # 55-65, CJK UNIFIED IDEOGRAPH-6010 +U+6012(2,3);U+6012(2,3); # 37-60, CJK UNIFIED IDEOGRAPH-6012 +U+6015(2,3);U+6015(2,3); # 55-70, CJK UNIFIED IDEOGRAPH-6015 +U+6016(2,3);U+6016(2,3); # 41-61, CJK UNIFIED IDEOGRAPH-6016 +U+6019(2,3);U+6019(2,3); # 55-64, CJK UNIFIED IDEOGRAPH-6019 +U+601B(2,3);U+601B(2,3); # 55-69, CJK UNIFIED IDEOGRAPH-601B +U+601C(2,3);U+601C(2,3); # 46-71, CJK UNIFIED IDEOGRAPH-601C +U+601D(2,3);U+601D(2,3); # 27-55, CJK UNIFIED IDEOGRAPH-601D +U+6020(2,3);U+6020(2,3); # 34-53, CJK UNIFIED IDEOGRAPH-6020 +U+6021(2,3);U+6021(2,3); # 55-62, CJK UNIFIED IDEOGRAPH-6021 +U+6025(2,3);U+6025(2,3); # 21-62, CJK UNIFIED IDEOGRAPH-6025 +U+6026(2,3);U+6026(2,3); # 55-72, CJK UNIFIED IDEOGRAPH-6026 +U+6027(2,3);U+6027(2,3); # 32-13, CJK UNIFIED IDEOGRAPH-6027 +U+6028(2,3);U+6028(2,3); # 17-69, CJK UNIFIED IDEOGRAPH-6028 +U+6029(2,3);U+6029(2,3); # 55-66, CJK UNIFIED IDEOGRAPH-6029 +U+602A(2,3);U+602A(2,3); # 18-88, CJK UNIFIED IDEOGRAPH-602A +U+602B(2,3);U+602B(2,3); # 55-71, CJK UNIFIED IDEOGRAPH-602B +U+602F(2,3);U+602F(2,3); # 22-17, CJK UNIFIED IDEOGRAPH-602F +U+6031(2,3);U+6031(2,3); # 55-68, CJK UNIFIED IDEOGRAPH-6031 +U+603A(2,3);U+603A(2,3); # 55-74, CJK UNIFIED IDEOGRAPH-603A +U+6041(2,3);U+6041(2,3); # 55-76, CJK UNIFIED IDEOGRAPH-6041 +U+6042(2,3);U+6042(2,3); # 55-86, CJK UNIFIED IDEOGRAPH-6042 +U+6043(2,3);U+6043(2,3); # 55-84, CJK UNIFIED IDEOGRAPH-6043 +U+6046(2,3);U+6046(2,3); # 55-81, CJK UNIFIED IDEOGRAPH-6046 +U+604A(2,3);U+604A(2,3); # 55-80, CJK UNIFIED IDEOGRAPH-604A +U+604B(2,3);U+604B(2,3); # 46-88, CJK UNIFIED IDEOGRAPH-604B +U+604D(2,3);U+604D(2,3); # 55-82, CJK UNIFIED IDEOGRAPH-604D +U+6050(2,3);U+6050(2,3); # 22-18, CJK UNIFIED IDEOGRAPH-6050 +U+6052(2,3);U+6052(2,3); # 25-17, CJK UNIFIED IDEOGRAPH-6052 +U+6055(2,3);U+6055(2,3); # 29-90, CJK UNIFIED IDEOGRAPH-6055 +U+6059(2,3);U+6059(2,3); # 55-89, CJK UNIFIED IDEOGRAPH-6059 +U+605A(2,3);U+605A(2,3); # 55-75, CJK UNIFIED IDEOGRAPH-605A +U+605F(2,3);U+605F(2,3); # 55-79, CJK UNIFIED IDEOGRAPH-605F +U+6060(2,3);U+6060(2,3); # 55-63, CJK UNIFIED IDEOGRAPH-6060 +U+6062(2,3);U+6062(2,3); # 18-90, CJK UNIFIED IDEOGRAPH-6062 +U+6063(2,3);U+6063(2,3); # 55-83, CJK UNIFIED IDEOGRAPH-6063 +U+6064(2,3);U+6064(2,3); # 55-85, CJK UNIFIED IDEOGRAPH-6064 +U+6065(2,3);U+6065(2,3); # 35-49, CJK UNIFIED IDEOGRAPH-6065 +U+6068(2,3);U+6068(2,3); # 26-08, CJK UNIFIED IDEOGRAPH-6068 +U+6069(2,3);U+6069(2,3); # 18-24, CJK UNIFIED IDEOGRAPH-6069 +U+606A(2,3);U+606A(2,3); # 55-77, CJK UNIFIED IDEOGRAPH-606A +U+606B(2,3);U+606B(2,3); # 55-88, CJK UNIFIED IDEOGRAPH-606B +U+606C(2,3);U+606C(2,3); # 55-87, CJK UNIFIED IDEOGRAPH-606C +U+606D(2,3);U+606D(2,3); # 22-19, CJK UNIFIED IDEOGRAPH-606D +U+606F(2,3);U+606F(2,3); # 34-09, CJK UNIFIED IDEOGRAPH-606F +U+6070(2,3);U+6070(2,3); # 19-70, CJK UNIFIED IDEOGRAPH-6070 +U+6075(2,3);U+6075(2,3); # 23-35, CJK UNIFIED IDEOGRAPH-6075 +U+6077(2,3);U+6077(2,3); # 55-78, CJK UNIFIED IDEOGRAPH-6077 +U+6081(2,3);U+6081(2,3); # 55-90, CJK UNIFIED IDEOGRAPH-6081 +U+6083(2,3);U+6083(2,3); # 55-93, CJK UNIFIED IDEOGRAPH-6083 +U+6084(2,3);U+6084(2,3); # 56-01, CJK UNIFIED IDEOGRAPH-6084 +U+6089(2,3);U+6089(2,3); # 28-29, CJK UNIFIED IDEOGRAPH-6089 +U+608B(2,3);U+608B(2,3); # 56-07, CJK UNIFIED IDEOGRAPH-608B +U+608C(2,3);U+608C(2,3); # 36-80, CJK UNIFIED IDEOGRAPH-608C +U+608D(2,3);U+608D(2,3); # 55-91, CJK UNIFIED IDEOGRAPH-608D +U+6092(2,3);U+6092(2,3); # 56-05, CJK UNIFIED IDEOGRAPH-6092 +U+6094(2,3);U+6094(2,3); # 18-89, CJK UNIFIED IDEOGRAPH-6094 +U+6096(2,3);U+6096(2,3); # 56-03, CJK UNIFIED IDEOGRAPH-6096 +U+6097(2,3);U+6097(2,3); # 56-04, CJK UNIFIED IDEOGRAPH-6097 +U+609A(2,3);U+609A(2,3); # 55-94, CJK UNIFIED IDEOGRAPH-609A +U+609B(2,3);U+609B(2,3); # 56-02, CJK UNIFIED IDEOGRAPH-609B +U+609F(2,3);U+609F(2,3); # 24-71, CJK UNIFIED IDEOGRAPH-609F +U+60A0(2,3);U+60A0(2,3); # 45-10, CJK UNIFIED IDEOGRAPH-60A0 +U+60A3(2,3);U+60A3(2,3); # 20-21, CJK UNIFIED IDEOGRAPH-60A3 +U+60A6(2,3);U+60A6(2,3); # 17-57, CJK UNIFIED IDEOGRAPH-60A6 +U+60A7(2,3);U+60A7(2,3); # 56-06, CJK UNIFIED IDEOGRAPH-60A7 +U+60A9(2,3);U+60A9(2,3); # 39-26, CJK UNIFIED IDEOGRAPH-60A9 +U+60AA(2,3);U+60AA(2,3); # 16-13, CJK UNIFIED IDEOGRAPH-60AA +U+60B2(2,3);U+60B2(2,3); # 40-65, CJK UNIFIED IDEOGRAPH-60B2 +U+60B3(2,3);U+60B3(2,3); # 55-60, CJK UNIFIED IDEOGRAPH-60B3 +U+60B4(2,3);U+60B4(2,3); # 56-12, CJK UNIFIED IDEOGRAPH-60B4 +U+60B5(2,3);U+60B5(2,3); # 56-16, CJK UNIFIED IDEOGRAPH-60B5 +U+60B6(2,3);U+60B6(2,3); # 44-69, CJK UNIFIED IDEOGRAPH-60B6 +U+60B8(2,3);U+60B8(2,3); # 56-09, CJK UNIFIED IDEOGRAPH-60B8 +U+60BC(2,3);U+60BC(2,3); # 37-73, CJK UNIFIED IDEOGRAPH-60BC +U+60BD(2,3);U+60BD(2,3); # 56-14, CJK UNIFIED IDEOGRAPH-60BD +U+60C5(2,3);U+60C5(2,3); # 30-80, CJK UNIFIED IDEOGRAPH-60C5 +U+60C6(2,3);U+60C6(2,3); # 56-15, CJK UNIFIED IDEOGRAPH-60C6 +U+60C7(2,3);U+60C7(2,3); # 38-55, CJK UNIFIED IDEOGRAPH-60C7 +U+60D1(2,3);U+60D1(2,3); # 47-39, CJK UNIFIED IDEOGRAPH-60D1 +U+60D3(2,3);U+60D3(2,3); # 56-11, CJK UNIFIED IDEOGRAPH-60D3 +U+60D8(2,3);U+60D8(2,3); # 56-17, CJK UNIFIED IDEOGRAPH-60D8 +U+60DA(2,3);U+60DA(2,3); # 25-91, CJK UNIFIED IDEOGRAPH-60DA +U+60DC(2,3);U+60DC(2,3); # 32-43, CJK UNIFIED IDEOGRAPH-60DC +U+60DF(2,3);U+60DF(2,3); # 16-52, CJK UNIFIED IDEOGRAPH-60DF +U+60E0(2,3);U+60E0(2,3); # 56-10, CJK UNIFIED IDEOGRAPH-60E0 +U+60E1(2,3);U+60E1(2,3); # 56-08, CJK UNIFIED IDEOGRAPH-60E1 +U+60E3(2,3);U+60E3(2,3); # 33-58, CJK UNIFIED IDEOGRAPH-60E3 +U+60E7(2,3);U+60E7(2,3); # 55-92, CJK UNIFIED IDEOGRAPH-60E7 +U+60E8(2,3);U+60E8(2,3); # 27-20, CJK UNIFIED IDEOGRAPH-60E8 +U+60F0(2,3);U+60F0(2,3); # 34-38, CJK UNIFIED IDEOGRAPH-60F0 +U+60F1(2,3);U+60F1(2,3); # 56-29, CJK UNIFIED IDEOGRAPH-60F1 +U+60F3(2,3);U+60F3(2,3); # 33-59, CJK UNIFIED IDEOGRAPH-60F3 +U+60F4(2,3);U+60F4(2,3); # 56-24, CJK UNIFIED IDEOGRAPH-60F4 +U+60F6(2,3);U+60F6(2,3); # 56-21, CJK UNIFIED IDEOGRAPH-60F6 +U+60F7(2,3);U+60F7(2,3); # 56-22, CJK UNIFIED IDEOGRAPH-60F7 +U+60F9(2,3);U+60F9(2,3); # 28-70, CJK UNIFIED IDEOGRAPH-60F9 +U+60FA(2,3);U+60FA(2,3); # 56-25, CJK UNIFIED IDEOGRAPH-60FA +U+60FB(2,3);U+60FB(2,3); # 56-28, CJK UNIFIED IDEOGRAPH-60FB +U+6100(2,3);U+6100(2,3); # 56-23, CJK UNIFIED IDEOGRAPH-6100 +U+6101(2,3);U+6101(2,3); # 29-05, CJK UNIFIED IDEOGRAPH-6101 +U+6103(2,3);U+6103(2,3); # 56-26, CJK UNIFIED IDEOGRAPH-6103 +U+6106(2,3);U+6106(2,3); # 56-20, CJK UNIFIED IDEOGRAPH-6106 +U+6108(2,3);U+6108(2,3); # 44-92, CJK UNIFIED IDEOGRAPH-6108 +U+6109(2,3);U+6109(2,3); # 44-91, CJK UNIFIED IDEOGRAPH-6109 +U+610D(2,3);U+610D(2,3); # 56-30, CJK UNIFIED IDEOGRAPH-610D +U+610E(2,3);U+610E(2,3); # 56-31, CJK UNIFIED IDEOGRAPH-610E +U+610F(2,3);U+610F(2,3); # 16-53, CJK UNIFIED IDEOGRAPH-610F +U+6115(2,3);U+6115(2,3); # 56-19, CJK UNIFIED IDEOGRAPH-6115 +U+611A(2,3);U+611A(2,3); # 22-82, CJK UNIFIED IDEOGRAPH-611A +U+611B(2,3);U+611B(2,3); # 16-06, CJK UNIFIED IDEOGRAPH-611B +U+611F(2,3);U+611F(2,3); # 20-22, CJK UNIFIED IDEOGRAPH-611F +U+6121(2,3);U+6121(2,3); # 56-27, CJK UNIFIED IDEOGRAPH-6121 +U+6127(2,3);U+6127(2,3); # 56-35, CJK UNIFIED IDEOGRAPH-6127 +U+6128(2,3);U+6128(2,3); # 56-34, CJK UNIFIED IDEOGRAPH-6128 +U+612C(2,3);U+612C(2,3); # 56-39, CJK UNIFIED IDEOGRAPH-612C +U+6134(2,3);U+6134(2,3); # 56-40, CJK UNIFIED IDEOGRAPH-6134 +U+613C(2,3);U+613C(2,3); # 56-38, CJK UNIFIED IDEOGRAPH-613C +U+613D(2,3);U+613D(2,3); # 56-41, CJK UNIFIED IDEOGRAPH-613D +U+613E(2,3);U+613E(2,3); # 56-33, CJK UNIFIED IDEOGRAPH-613E +U+613F(2,3);U+613F(2,3); # 56-37, CJK UNIFIED IDEOGRAPH-613F +U+6142(2,3);U+6142(2,3); # 56-42, CJK UNIFIED IDEOGRAPH-6142 +U+6144(2,3);U+6144(2,3); # 56-43, CJK UNIFIED IDEOGRAPH-6144 +U+6147(2,3);U+6147(2,3); # 56-32, CJK UNIFIED IDEOGRAPH-6147 +U+6148(2,3);U+6148(2,3); # 27-92, CJK UNIFIED IDEOGRAPH-6148 +U+614A(2,3);U+614A(2,3); # 56-36, CJK UNIFIED IDEOGRAPH-614A +U+614B(2,3);U+614B(2,3); # 34-54, CJK UNIFIED IDEOGRAPH-614B +U+614C(2,3);U+614C(2,3); # 25-18, CJK UNIFIED IDEOGRAPH-614C +U+614D(2,3);U+614D(2,3); # 56-18, CJK UNIFIED IDEOGRAPH-614D +U+614E(2,3);U+614E(2,3); # 31-21, CJK UNIFIED IDEOGRAPH-614E +U+6153(2,3);U+6153(2,3); # 56-56, CJK UNIFIED IDEOGRAPH-6153 +U+6155(2,3);U+6155(2,3); # 42-73, CJK UNIFIED IDEOGRAPH-6155 +U+6158(2,3);U+6158(2,3); # 56-46, CJK UNIFIED IDEOGRAPH-6158 +U+6159(2,3);U+6159(2,3); # 56-47, CJK UNIFIED IDEOGRAPH-6159 +U+615A(2,3);U+615A(2,3); # 56-48, CJK UNIFIED IDEOGRAPH-615A +U+615D(2,3);U+615D(2,3); # 56-55, CJK UNIFIED IDEOGRAPH-615D +U+615F(2,3);U+615F(2,3); # 56-54, CJK UNIFIED IDEOGRAPH-615F +U+6162(2,3);U+6162(2,3); # 43-93, CJK UNIFIED IDEOGRAPH-6162 +U+6163(2,3);U+6163(2,3); # 20-23, CJK UNIFIED IDEOGRAPH-6163 +U+6165(2,3);U+6165(2,3); # 56-52, CJK UNIFIED IDEOGRAPH-6165 +U+6167(2,3);U+6167(2,3); # 23-37, CJK UNIFIED IDEOGRAPH-6167 +U+6168(2,3);U+6168(2,3); # 19-20, CJK UNIFIED IDEOGRAPH-6168 +U+616B(2,3);U+616B(2,3); # 56-49, CJK UNIFIED IDEOGRAPH-616B +U+616E(2,3);U+616E(2,3); # 46-24, CJK UNIFIED IDEOGRAPH-616E +U+616F(2,3);U+616F(2,3); # 56-51, CJK UNIFIED IDEOGRAPH-616F +U+6170(2,3);U+6170(2,3); # 16-54, CJK UNIFIED IDEOGRAPH-6170 +U+6171(2,3);U+6171(2,3); # 56-53, CJK UNIFIED IDEOGRAPH-6171 +U+6173(2,3);U+6173(2,3); # 56-44, CJK UNIFIED IDEOGRAPH-6173 +U+6174(2,3);U+6174(2,3); # 56-50, CJK UNIFIED IDEOGRAPH-6174 +U+6175(2,3);U+6175(2,3); # 56-57, CJK UNIFIED IDEOGRAPH-6175 +U+6176(2,3);U+6176(2,3); # 23-36, CJK UNIFIED IDEOGRAPH-6176 +U+6177(2,3);U+6177(2,3); # 56-45, CJK UNIFIED IDEOGRAPH-6177 +U+617E(2,3);U+617E(2,3); # 45-61, CJK UNIFIED IDEOGRAPH-617E +U+6182(2,3);U+6182(2,3); # 45-11, CJK UNIFIED IDEOGRAPH-6182 +U+6187(2,3);U+6187(2,3); # 56-60, CJK UNIFIED IDEOGRAPH-6187 +U+618A(2,3);U+618A(2,3); # 56-64, CJK UNIFIED IDEOGRAPH-618A +U+618E(2,3);U+618E(2,3); # 33-94, CJK UNIFIED IDEOGRAPH-618E +U+6190(2,3);U+6190(2,3); # 46-89, CJK UNIFIED IDEOGRAPH-6190 +U+6191(2,3);U+6191(2,3); # 56-65, CJK UNIFIED IDEOGRAPH-6191 +U+6194(2,3);U+6194(2,3); # 56-62, CJK UNIFIED IDEOGRAPH-6194 +U+6196(2,3);U+6196(2,3); # 56-59, CJK UNIFIED IDEOGRAPH-6196 +U+6199(2,3);U+6199(2,3); # 56-58, CJK UNIFIED IDEOGRAPH-6199 +U+619A(2,3);U+619A(2,3); # 56-63, CJK UNIFIED IDEOGRAPH-619A +U+61A4(2,3);U+61A4(2,3); # 42-16, CJK UNIFIED IDEOGRAPH-61A4 +U+61A7(2,3);U+61A7(2,3); # 38-20, CJK UNIFIED IDEOGRAPH-61A7 +U+61A9(2,3);U+61A9(2,3); # 23-38, CJK UNIFIED IDEOGRAPH-61A9 +U+61AB(2,3);U+61AB(2,3); # 56-66, CJK UNIFIED IDEOGRAPH-61AB +U+61AC(2,3);U+61AC(2,3); # 56-61, CJK UNIFIED IDEOGRAPH-61AC +U+61AE(2,3);U+61AE(2,3); # 56-67, CJK UNIFIED IDEOGRAPH-61AE +U+61B2(2,3);U+61B2(2,3); # 23-91, CJK UNIFIED IDEOGRAPH-61B2 +U+61B6(2,3);U+61B6(2,3); # 18-17, CJK UNIFIED IDEOGRAPH-61B6 +U+61BA(2,3);U+61BA(2,3); # 56-75, CJK UNIFIED IDEOGRAPH-61BA +U+61BE(2,3);U+61BE(2,3); # 20-24, CJK UNIFIED IDEOGRAPH-61BE +U+61C3(2,3);U+61C3(2,3); # 56-73, CJK UNIFIED IDEOGRAPH-61C3 +U+61C6(2,3);U+61C6(2,3); # 56-74, CJK UNIFIED IDEOGRAPH-61C6 +U+61C7(2,3);U+61C7(2,3); # 26-09, CJK UNIFIED IDEOGRAPH-61C7 +U+61C8(2,3);U+61C8(2,3); # 56-72, CJK UNIFIED IDEOGRAPH-61C8 +U+61C9(2,3);U+61C9(2,3); # 56-70, CJK UNIFIED IDEOGRAPH-61C9 +U+61CA(2,3);U+61CA(2,3); # 56-69, CJK UNIFIED IDEOGRAPH-61CA +U+61CB(2,3);U+61CB(2,3); # 56-76, CJK UNIFIED IDEOGRAPH-61CB +U+61CC(2,3);U+61CC(2,3); # 56-68, CJK UNIFIED IDEOGRAPH-61CC +U+61CD(2,3);U+61CD(2,3); # 56-78, CJK UNIFIED IDEOGRAPH-61CD +U+61D0(2,3);U+61D0(2,3); # 18-91, CJK UNIFIED IDEOGRAPH-61D0 +U+61E3(2,3);U+61E3(2,3); # 56-80, CJK UNIFIED IDEOGRAPH-61E3 +U+61E6(2,3);U+61E6(2,3); # 56-79, CJK UNIFIED IDEOGRAPH-61E6 +U+61F2(2,3);U+61F2(2,3); # 36-08, CJK UNIFIED IDEOGRAPH-61F2 +U+61F4(2,3);U+61F4(2,3); # 56-83, CJK UNIFIED IDEOGRAPH-61F4 +U+61F6(2,3);U+61F6(2,3); # 56-81, CJK UNIFIED IDEOGRAPH-61F6 +U+61F7(2,3);U+61F7(2,3); # 56-71, CJK UNIFIED IDEOGRAPH-61F7 +U+61F8(2,3);U+61F8(2,3); # 23-92, CJK UNIFIED IDEOGRAPH-61F8 +U+61FA(2,3);U+61FA(2,3); # 56-82, CJK UNIFIED IDEOGRAPH-61FA +U+61FC(2,3);U+61FC(2,3); # 56-86, CJK UNIFIED IDEOGRAPH-61FC +U+61FD(2,3);U+61FD(2,3); # 56-85, CJK UNIFIED IDEOGRAPH-61FD +U+61FE(2,3);U+61FE(2,3); # 56-87, CJK UNIFIED IDEOGRAPH-61FE +U+61FF(2,3);U+61FF(2,3); # 56-84, CJK UNIFIED IDEOGRAPH-61FF +U+6200(2,3);U+6200(2,3); # 56-88, CJK UNIFIED IDEOGRAPH-6200 +U+6208(2,3);U+6208(2,3); # 56-89, CJK UNIFIED IDEOGRAPH-6208 +U+6209(2,3);U+6209(2,3); # 56-90, CJK UNIFIED IDEOGRAPH-6209 +U+620A(2,3);U+620A(2,3); # 42-74, CJK UNIFIED IDEOGRAPH-620A +U+620C(2,3);U+620C(2,3); # 56-92, CJK UNIFIED IDEOGRAPH-620C +U+620D(2,3);U+620D(2,3); # 56-91, CJK UNIFIED IDEOGRAPH-620D +U+620E(2,3);U+620E(2,3); # 29-31, CJK UNIFIED IDEOGRAPH-620E +U+6210(2,3);U+6210(2,3); # 32-14, CJK UNIFIED IDEOGRAPH-6210 +U+6211(2,3);U+6211(2,3); # 18-70, CJK UNIFIED IDEOGRAPH-6211 +U+6212(2,3);U+6212(2,3); # 18-92, CJK UNIFIED IDEOGRAPH-6212 +U+6214(2,3);U+6214(2,3); # 56-93, CJK UNIFIED IDEOGRAPH-6214 +U+6216(2,3);U+6216(2,3); # 16-31, CJK UNIFIED IDEOGRAPH-6216 +U+621A(2,3);U+621A(2,3); # 32-44, CJK UNIFIED IDEOGRAPH-621A +U+621B(2,3);U+621B(2,3); # 56-94, CJK UNIFIED IDEOGRAPH-621B +U+621D(2,3);U+621D(2,3); # 76-35, CJK UNIFIED IDEOGRAPH-621D +U+621E(2,3);U+621E(2,3); # 57-01, CJK UNIFIED IDEOGRAPH-621E +U+621F(2,3);U+621F(2,3); # 23-65, CJK UNIFIED IDEOGRAPH-621F +U+6221(2,3);U+6221(2,3); # 57-02, CJK UNIFIED IDEOGRAPH-6221 +U+6226(2,3);U+6226(2,3); # 32-79, CJK UNIFIED IDEOGRAPH-6226 +U+622A(2,3);U+622A(2,3); # 57-03, CJK UNIFIED IDEOGRAPH-622A +U+622E(2,3);U+622E(2,3); # 57-04, CJK UNIFIED IDEOGRAPH-622E +U+622F(2,3);U+622F(2,3); # 21-26, CJK UNIFIED IDEOGRAPH-622F +U+6230(2,3);U+6230(2,3); # 57-05, CJK UNIFIED IDEOGRAPH-6230 +U+6232(2,3);U+6232(2,3); # 57-06, CJK UNIFIED IDEOGRAPH-6232 +U+6233(2,3);U+6233(2,3); # 57-07, CJK UNIFIED IDEOGRAPH-6233 +U+6234(2,3);U+6234(2,3); # 34-55, CJK UNIFIED IDEOGRAPH-6234 +U+6238(2,3);U+6238(2,3); # 24-45, CJK UNIFIED IDEOGRAPH-6238 +U+623B(2,3);U+623B(2,3); # 44-65, CJK UNIFIED IDEOGRAPH-623B +U+623F(2,3);U+623F(2,3); # 43-28, CJK UNIFIED IDEOGRAPH-623F +U+6240(2,3);U+6240(2,3); # 29-74, CJK UNIFIED IDEOGRAPH-6240 +U+6241(2,3);U+6241(2,3); # 57-08, CJK UNIFIED IDEOGRAPH-6241 +U+6247(2,3);U+6247(2,3); # 32-80, CJK UNIFIED IDEOGRAPH-6247 +U+6248(2,3);U+6248(2,3); # 78-29, CJK UNIFIED IDEOGRAPH-6248 +U+6249(2,3);U+6249(2,3); # 40-66, CJK UNIFIED IDEOGRAPH-6249 +U+624B(2,3);U+624B(2,3); # 28-74, CJK UNIFIED IDEOGRAPH-624B +U+624D(2,3);U+624D(2,3); # 26-45, CJK UNIFIED IDEOGRAPH-624D +U+624E(2,3);U+624E(2,3); # 57-09, CJK UNIFIED IDEOGRAPH-624E +U+6253(2,3);U+6253(2,3); # 34-39, CJK UNIFIED IDEOGRAPH-6253 +U+6255(2,3);U+6255(2,3); # 42-07, CJK UNIFIED IDEOGRAPH-6255 +U+6258(2,3);U+6258(2,3); # 34-81, CJK UNIFIED IDEOGRAPH-6258 +U+625B(2,3);U+625B(2,3); # 57-12, CJK UNIFIED IDEOGRAPH-625B +U+625E(2,3);U+625E(2,3); # 57-10, CJK UNIFIED IDEOGRAPH-625E +U+6260(2,3);U+6260(2,3); # 57-13, CJK UNIFIED IDEOGRAPH-6260 +U+6263(2,3);U+6263(2,3); # 57-11, CJK UNIFIED IDEOGRAPH-6263 +U+6268(2,3);U+6268(2,3); # 57-14, CJK UNIFIED IDEOGRAPH-6268 +U+626E(2,3);U+626E(2,3); # 42-17, CJK UNIFIED IDEOGRAPH-626E +U+6271(2,3);U+6271(2,3); # 16-23, CJK UNIFIED IDEOGRAPH-6271 +U+6276(2,3);U+6276(2,3); # 41-62, CJK UNIFIED IDEOGRAPH-6276 +U+6279(2,3);U+6279(2,3); # 40-67, CJK UNIFIED IDEOGRAPH-6279 +U+627C(2,3);U+627C(2,3); # 57-15, CJK UNIFIED IDEOGRAPH-627C +U+627E(2,3);U+627E(2,3); # 57-18, CJK UNIFIED IDEOGRAPH-627E +U+627F(2,3);U+627F(2,3); # 30-21, CJK UNIFIED IDEOGRAPH-627F +U+6280(2,3);U+6280(2,3); # 21-27, CJK UNIFIED IDEOGRAPH-6280 +U+6282(2,3);U+6282(2,3); # 57-16, CJK UNIFIED IDEOGRAPH-6282 +U+6283(2,3);U+6283(2,3); # 57-23, CJK UNIFIED IDEOGRAPH-6283 +U+6284(2,3);U+6284(2,3); # 30-22, CJK UNIFIED IDEOGRAPH-6284 +U+6289(2,3);U+6289(2,3); # 57-17, CJK UNIFIED IDEOGRAPH-6289 +U+628A(2,3);U+628A(2,3); # 39-36, CJK UNIFIED IDEOGRAPH-628A +U+6291(2,3);U+6291(2,3); # 45-62, CJK UNIFIED IDEOGRAPH-6291 +U+6292(2,3);U+6292(2,3); # 57-19, CJK UNIFIED IDEOGRAPH-6292 +U+6293(2,3);U+6293(2,3); # 57-20, CJK UNIFIED IDEOGRAPH-6293 +U+6294(2,3);U+6294(2,3); # 57-24, CJK UNIFIED IDEOGRAPH-6294 +U+6295(2,3);U+6295(2,3); # 37-74, CJK UNIFIED IDEOGRAPH-6295 +U+6296(2,3);U+6296(2,3); # 57-21, CJK UNIFIED IDEOGRAPH-6296 +U+6297(2,3);U+6297(2,3); # 25-19, CJK UNIFIED IDEOGRAPH-6297 +U+6298(2,3);U+6298(2,3); # 32-62, CJK UNIFIED IDEOGRAPH-6298 +U+629B(2,3);U+629B(2,3); # 57-38, CJK UNIFIED IDEOGRAPH-629B +U+629C(2,3);U+629C(2,3); # 40-20, CJK UNIFIED IDEOGRAPH-629C +U+629E(2,3);U+629E(2,3); # 34-82, CJK UNIFIED IDEOGRAPH-629E +U+62AB(2,3);U+62AB(2,3); # 40-68, CJK UNIFIED IDEOGRAPH-62AB +U+62AC(2,3);U+62AC(2,3); # 58-13, CJK UNIFIED IDEOGRAPH-62AC +U+62B1(2,3);U+62B1(2,3); # 42-90, CJK UNIFIED IDEOGRAPH-62B1 +U+62B5(2,3);U+62B5(2,3); # 36-81, CJK UNIFIED IDEOGRAPH-62B5 +U+62B9(2,3);U+62B9(2,3); # 43-85, CJK UNIFIED IDEOGRAPH-62B9 +U+62BB(2,3);U+62BB(2,3); # 57-27, CJK UNIFIED IDEOGRAPH-62BB +U+62BC(2,3);U+62BC(2,3); # 18-01, CJK UNIFIED IDEOGRAPH-62BC +U+62BD(2,3);U+62BD(2,3); # 35-74, CJK UNIFIED IDEOGRAPH-62BD +U+62C2(2,3);U+62C2(2,3); # 57-36, CJK UNIFIED IDEOGRAPH-62C2 +U+62C5(2,3);U+62C5(2,3); # 35-20, CJK UNIFIED IDEOGRAPH-62C5 +U+62C6(2,3);U+62C6(2,3); # 57-30, CJK UNIFIED IDEOGRAPH-62C6 +U+62C7(2,3);U+62C7(2,3); # 57-37, CJK UNIFIED IDEOGRAPH-62C7 +U+62C8(2,3);U+62C8(2,3); # 57-32, CJK UNIFIED IDEOGRAPH-62C8 +U+62C9(2,3);U+62C9(2,3); # 57-39, CJK UNIFIED IDEOGRAPH-62C9 +U+62CA(2,3);U+62CA(2,3); # 57-35, CJK UNIFIED IDEOGRAPH-62CA +U+62CC(2,3);U+62CC(2,3); # 57-34, CJK UNIFIED IDEOGRAPH-62CC +U+62CD(2,3);U+62CD(2,3); # 39-79, CJK UNIFIED IDEOGRAPH-62CD +U+62CF(2,3);U+62CF(2,3); # 57-28, CJK UNIFIED IDEOGRAPH-62CF +U+62D0(2,3);U+62D0(2,3); # 18-93, CJK UNIFIED IDEOGRAPH-62D0 +U+62D1(2,3);U+62D1(2,3); # 57-26, CJK UNIFIED IDEOGRAPH-62D1 +U+62D2(2,3);U+62D2(2,3); # 21-81, CJK UNIFIED IDEOGRAPH-62D2 +U+62D3(2,3);U+62D3(2,3); # 34-83, CJK UNIFIED IDEOGRAPH-62D3 +U+62D4(2,3);U+62D4(2,3); # 57-22, CJK UNIFIED IDEOGRAPH-62D4 +U+62D7(2,3);U+62D7(2,3); # 57-25, CJK UNIFIED IDEOGRAPH-62D7 +U+62D8(2,3);U+62D8(2,3); # 25-20, CJK UNIFIED IDEOGRAPH-62D8 +U+62D9(2,3);U+62D9(2,3); # 32-59, CJK UNIFIED IDEOGRAPH-62D9 +U+62DB(2,3);U+62DB(2,3); # 30-23, CJK UNIFIED IDEOGRAPH-62DB +U+62DC(2,3);U+62DC(2,3); # 57-33, CJK UNIFIED IDEOGRAPH-62DC +U+62DD(2,3);U+62DD(2,3); # 39-50, CJK UNIFIED IDEOGRAPH-62DD +U+62E0(2,3);U+62E0(2,3); # 21-82, CJK UNIFIED IDEOGRAPH-62E0 +U+62E1(2,3);U+62E1(2,3); # 19-40, CJK UNIFIED IDEOGRAPH-62E1 +U+62EC(2,3);U+62EC(2,3); # 19-71, CJK UNIFIED IDEOGRAPH-62EC +U+62ED(2,3);U+62ED(2,3); # 31-01, CJK UNIFIED IDEOGRAPH-62ED +U+62EE(2,3);U+62EE(2,3); # 57-41, CJK UNIFIED IDEOGRAPH-62EE +U+62EF(2,3);U+62EF(2,3); # 57-46, CJK UNIFIED IDEOGRAPH-62EF +U+62F1(2,3);U+62F1(2,3); # 57-42, CJK UNIFIED IDEOGRAPH-62F1 +U+62F3(2,3);U+62F3(2,3); # 23-93, CJK UNIFIED IDEOGRAPH-62F3 +U+62F5(2,3);U+62F5(2,3); # 57-47, CJK UNIFIED IDEOGRAPH-62F5 +U+62F6(2,3);U+62F6(2,3); # 27-02, CJK UNIFIED IDEOGRAPH-62F6 +U+62F7(2,3);U+62F7(2,3); # 25-73, CJK UNIFIED IDEOGRAPH-62F7 +U+62FE(2,3);U+62FE(2,3); # 29-06, CJK UNIFIED IDEOGRAPH-62FE +U+62FF(2,3);U+62FF(2,3); # 57-29, CJK UNIFIED IDEOGRAPH-62FF +U+6301(2,3);U+6301(2,3); # 27-93, CJK UNIFIED IDEOGRAPH-6301 +U+6302(2,3);U+6302(2,3); # 57-44, CJK UNIFIED IDEOGRAPH-6302 +U+6307(2,3);U+6307(2,3); # 27-56, CJK UNIFIED IDEOGRAPH-6307 +U+6308(2,3);U+6308(2,3); # 57-45, CJK UNIFIED IDEOGRAPH-6308 +U+6309(2,3);U+6309(2,3); # 16-36, CJK UNIFIED IDEOGRAPH-6309 +U+630C(2,3);U+630C(2,3); # 57-40, CJK UNIFIED IDEOGRAPH-630C +U+6311(2,3);U+6311(2,3); # 36-09, CJK UNIFIED IDEOGRAPH-6311 +U+6319(2,3);U+6319(2,3); # 21-83, CJK UNIFIED IDEOGRAPH-6319 +U+631F(2,3);U+631F(2,3); # 22-20, CJK UNIFIED IDEOGRAPH-631F +U+6327(2,3);U+6327(2,3); # 57-43, CJK UNIFIED IDEOGRAPH-6327 +U+6328(2,3);U+6328(2,3); # 16-07, CJK UNIFIED IDEOGRAPH-6328 +U+632B(2,3);U+632B(2,3); # 26-35, CJK UNIFIED IDEOGRAPH-632B +U+632F(2,3);U+632F(2,3); # 31-22, CJK UNIFIED IDEOGRAPH-632F +U+633A(2,3);U+633A(2,3); # 36-82, CJK UNIFIED IDEOGRAPH-633A +U+633D(2,3);U+633D(2,3); # 40-52, CJK UNIFIED IDEOGRAPH-633D +U+633E(2,3);U+633E(2,3); # 57-49, CJK UNIFIED IDEOGRAPH-633E +U+633F(2,3);U+633F(2,3); # 33-62, CJK UNIFIED IDEOGRAPH-633F +U+6349(2,3);U+6349(2,3); # 34-10, CJK UNIFIED IDEOGRAPH-6349 +U+634C(2,3);U+634C(2,3); # 27-11, CJK UNIFIED IDEOGRAPH-634C +U+634D(2,3);U+634D(2,3); # 57-50, CJK UNIFIED IDEOGRAPH-634D +U+634F(2,3);U+634F(2,3); # 57-52, CJK UNIFIED IDEOGRAPH-634F +U+6350(2,3);U+6350(2,3); # 57-48, CJK UNIFIED IDEOGRAPH-6350 +U+6355(2,3);U+6355(2,3); # 42-65, CJK UNIFIED IDEOGRAPH-6355 +U+6357(2,3);U+6357(2,3); # 36-29, CJK UNIFIED IDEOGRAPH-6357 +U+635C(2,3);U+635C(2,3); # 33-60, CJK UNIFIED IDEOGRAPH-635C +U+6367(2,3);U+6367(2,3); # 42-91, CJK UNIFIED IDEOGRAPH-6367 +U+6368(2,3);U+6368(2,3); # 28-46, CJK UNIFIED IDEOGRAPH-6368 +U+6369(2,3);U+6369(2,3); # 57-64, CJK UNIFIED IDEOGRAPH-6369 +U+636B(2,3);U+636B(2,3); # 57-63, CJK UNIFIED IDEOGRAPH-636B +U+636E(2,3);U+636E(2,3); # 31-88, CJK UNIFIED IDEOGRAPH-636E +U+6372(2,3);U+6372(2,3); # 23-94, CJK UNIFIED IDEOGRAPH-6372 +U+6376(2,3);U+6376(2,3); # 57-57, CJK UNIFIED IDEOGRAPH-6376 +U+6377(2,3);U+6377(2,3); # 30-25, CJK UNIFIED IDEOGRAPH-6377 +U+637A(2,3);U+637A(2,3); # 38-72, CJK UNIFIED IDEOGRAPH-637A +U+637B(2,3);U+637B(2,3); # 39-17, CJK UNIFIED IDEOGRAPH-637B +U+6380(2,3);U+6380(2,3); # 57-55, CJK UNIFIED IDEOGRAPH-6380 +U+6383(2,3);U+6383(2,3); # 33-61, CJK UNIFIED IDEOGRAPH-6383 +U+6388(2,3);U+6388(2,3); # 28-88, CJK UNIFIED IDEOGRAPH-6388 +U+6389(2,3);U+6389(2,3); # 57-60, CJK UNIFIED IDEOGRAPH-6389 +U+638C(2,3);U+638C(2,3); # 30-24, CJK UNIFIED IDEOGRAPH-638C +U+638E(2,3);U+638E(2,3); # 57-54, CJK UNIFIED IDEOGRAPH-638E +U+638F(2,3);U+638F(2,3); # 57-59, CJK UNIFIED IDEOGRAPH-638F +U+6392(2,3);U+6392(2,3); # 39-51, CJK UNIFIED IDEOGRAPH-6392 +U+6396(2,3);U+6396(2,3); # 57-53, CJK UNIFIED IDEOGRAPH-6396 +U+6398(2,3);U+6398(2,3); # 23-01, CJK UNIFIED IDEOGRAPH-6398 +U+639B(2,3);U+639B(2,3); # 19-61, CJK UNIFIED IDEOGRAPH-639B +U+639F(2,3);U+639F(2,3); # 57-61, CJK UNIFIED IDEOGRAPH-639F +U+63A0(2,3);U+63A0(2,3); # 46-11, CJK UNIFIED IDEOGRAPH-63A0 +U+63A1(2,3);U+63A1(2,3); # 26-46, CJK UNIFIED IDEOGRAPH-63A1 +U+63A2(2,3);U+63A2(2,3); # 35-21, CJK UNIFIED IDEOGRAPH-63A2 +U+63A3(2,3);U+63A3(2,3); # 57-58, CJK UNIFIED IDEOGRAPH-63A3 +U+63A5(2,3);U+63A5(2,3); # 32-60, CJK UNIFIED IDEOGRAPH-63A5 +U+63A7(2,3);U+63A7(2,3); # 25-21, CJK UNIFIED IDEOGRAPH-63A7 +U+63A8(2,3);U+63A8(2,3); # 31-68, CJK UNIFIED IDEOGRAPH-63A8 +U+63A9(2,3);U+63A9(2,3); # 17-70, CJK UNIFIED IDEOGRAPH-63A9 +U+63AA(2,3);U+63AA(2,3); # 33-28, CJK UNIFIED IDEOGRAPH-63AA +U+63AB(2,3);U+63AB(2,3); # 57-56, CJK UNIFIED IDEOGRAPH-63AB +U+63AC(2,3);U+63AC(2,3); # 21-37, CJK UNIFIED IDEOGRAPH-63AC +U+63B2(2,3);U+63B2(2,3); # 23-39, CJK UNIFIED IDEOGRAPH-63B2 +U+63B4(2,3);U+63B4(2,3); # 36-47, CJK UNIFIED IDEOGRAPH-63B4 +U+63B5(2,3);U+63B5(2,3); # 57-62, CJK UNIFIED IDEOGRAPH-63B5 +U+63BB(2,3);U+63BB(2,3); # 33-63, CJK UNIFIED IDEOGRAPH-63BB +U+63BE(2,3);U+63BE(2,3); # 57-65, CJK UNIFIED IDEOGRAPH-63BE +U+63C0(2,3);U+63C0(2,3); # 57-67, CJK UNIFIED IDEOGRAPH-63C0 +U+63C3(2,3);U+63C3(2,3); # 34-23, CJK UNIFIED IDEOGRAPH-63C3 +U+63C4(2,3);U+63C4(2,3); # 57-73, CJK UNIFIED IDEOGRAPH-63C4 +U+63C6(2,3);U+63C6(2,3); # 57-68, CJK UNIFIED IDEOGRAPH-63C6 +U+63C9(2,3);U+63C9(2,3); # 57-70, CJK UNIFIED IDEOGRAPH-63C9 +U+63CF(2,3);U+63CF(2,3); # 41-33, CJK UNIFIED IDEOGRAPH-63CF +U+63D0(2,3);U+63D0(2,3); # 36-83, CJK UNIFIED IDEOGRAPH-63D0 +U+63D2(2,3);U+63D2(2,3); # 57-71, CJK UNIFIED IDEOGRAPH-63D2 +U+63D6(2,3);U+63D6(2,3); # 45-12, CJK UNIFIED IDEOGRAPH-63D6 +U+63DA(2,3);U+63DA(2,3); # 45-40, CJK UNIFIED IDEOGRAPH-63DA +U+63DB(2,3);U+63DB(2,3); # 20-25, CJK UNIFIED IDEOGRAPH-63DB +U+63E1(2,3);U+63E1(2,3); # 16-14, CJK UNIFIED IDEOGRAPH-63E1 +U+63E3(2,3);U+63E3(2,3); # 57-69, CJK UNIFIED IDEOGRAPH-63E3 +U+63E9(2,3);U+63E9(2,3); # 57-66, CJK UNIFIED IDEOGRAPH-63E9 +U+63EE(2,3);U+63EE(2,3); # 20-88, CJK UNIFIED IDEOGRAPH-63EE +U+63F4(2,3);U+63F4(2,3); # 17-71, CJK UNIFIED IDEOGRAPH-63F4 +U+63F6(2,3);U+63F6(2,3); # 57-72, CJK UNIFIED IDEOGRAPH-63F6 +U+63FA(2,3);U+63FA(2,3); # 45-41, CJK UNIFIED IDEOGRAPH-63FA +U+6406(2,3);U+6406(2,3); # 57-76, CJK UNIFIED IDEOGRAPH-6406 +U+640D(2,3);U+640D(2,3); # 34-27, CJK UNIFIED IDEOGRAPH-640D +U+640F(2,3);U+640F(2,3); # 57-83, CJK UNIFIED IDEOGRAPH-640F +U+6413(2,3);U+6413(2,3); # 57-77, CJK UNIFIED IDEOGRAPH-6413 +U+6416(2,3);U+6416(2,3); # 57-74, CJK UNIFIED IDEOGRAPH-6416 +U+6417(2,3);U+6417(2,3); # 57-81, CJK UNIFIED IDEOGRAPH-6417 +U+641C(2,3);U+641C(2,3); # 57-51, CJK UNIFIED IDEOGRAPH-641C +U+6426(2,3);U+6426(2,3); # 57-78, CJK UNIFIED IDEOGRAPH-6426 +U+6428(2,3);U+6428(2,3); # 57-82, CJK UNIFIED IDEOGRAPH-6428 +U+642C(2,3);U+642C(2,3); # 40-34, CJK UNIFIED IDEOGRAPH-642C +U+642D(2,3);U+642D(2,3); # 37-75, CJK UNIFIED IDEOGRAPH-642D +U+6434(2,3);U+6434(2,3); # 57-75, CJK UNIFIED IDEOGRAPH-6434 +U+6436(2,3);U+6436(2,3); # 57-79, CJK UNIFIED IDEOGRAPH-6436 +U+643A(2,3);U+643A(2,3); # 23-40, CJK UNIFIED IDEOGRAPH-643A +U+643E(2,3);U+643E(2,3); # 26-81, CJK UNIFIED IDEOGRAPH-643E +U+6442(2,3);U+6442(2,3); # 32-61, CJK UNIFIED IDEOGRAPH-6442 +U+644E(2,3);U+644E(2,3); # 57-87, CJK UNIFIED IDEOGRAPH-644E +U+6458(2,3);U+6458(2,3); # 37-06, CJK UNIFIED IDEOGRAPH-6458 +U+6467(2,3);U+6467(2,3); # 57-84, CJK UNIFIED IDEOGRAPH-6467 +U+6469(2,3);U+6469(2,3); # 43-64, CJK UNIFIED IDEOGRAPH-6469 +U+646F(2,3);U+646F(2,3); # 57-85, CJK UNIFIED IDEOGRAPH-646F +U+6476(2,3);U+6476(2,3); # 57-86, CJK UNIFIED IDEOGRAPH-6476 +U+6478(2,3);U+6478(2,3); # 44-46, CJK UNIFIED IDEOGRAPH-6478 +U+647A(2,3);U+647A(2,3); # 32-02, CJK UNIFIED IDEOGRAPH-647A +U+6483(2,3);U+6483(2,3); # 23-66, CJK UNIFIED IDEOGRAPH-6483 +U+6488(2,3);U+6488(2,3); # 57-93, CJK UNIFIED IDEOGRAPH-6488 +U+6492(2,3);U+6492(2,3); # 27-21, CJK UNIFIED IDEOGRAPH-6492 +U+6493(2,3);U+6493(2,3); # 57-90, CJK UNIFIED IDEOGRAPH-6493 +U+6495(2,3);U+6495(2,3); # 57-89, CJK UNIFIED IDEOGRAPH-6495 +U+649A(2,3);U+649A(2,3); # 39-18, CJK UNIFIED IDEOGRAPH-649A +U+649E(2,3);U+649E(2,3); # 38-21, CJK UNIFIED IDEOGRAPH-649E +U+64A4(2,3);U+64A4(2,3); # 37-17, CJK UNIFIED IDEOGRAPH-64A4 +U+64A5(2,3);U+64A5(2,3); # 57-91, CJK UNIFIED IDEOGRAPH-64A5 +U+64A9(2,3);U+64A9(2,3); # 57-92, CJK UNIFIED IDEOGRAPH-64A9 +U+64AB(2,3);U+64AB(2,3); # 41-79, CJK UNIFIED IDEOGRAPH-64AB +U+64AD(2,3);U+64AD(2,3); # 39-37, CJK UNIFIED IDEOGRAPH-64AD +U+64AE(2,3);U+64AE(2,3); # 27-03, CJK UNIFIED IDEOGRAPH-64AE +U+64B0(2,3);U+64B0(2,3); # 32-81, CJK UNIFIED IDEOGRAPH-64B0 +U+64B2(2,3);U+64B2(2,3); # 43-48, CJK UNIFIED IDEOGRAPH-64B2 +U+64B9(2,3);U+64B9(2,3); # 19-41, CJK UNIFIED IDEOGRAPH-64B9 +U+64BB(2,3);U+64BB(2,3); # 58-05, CJK UNIFIED IDEOGRAPH-64BB +U+64BC(2,3);U+64BC(2,3); # 57-94, CJK UNIFIED IDEOGRAPH-64BC +U+64C1(2,3);U+64C1(2,3); # 45-42, CJK UNIFIED IDEOGRAPH-64C1 +U+64C2(2,3);U+64C2(2,3); # 58-07, CJK UNIFIED IDEOGRAPH-64C2 +U+64C5(2,3);U+64C5(2,3); # 58-03, CJK UNIFIED IDEOGRAPH-64C5 +U+64C7(2,3);U+64C7(2,3); # 58-04, CJK UNIFIED IDEOGRAPH-64C7 +U+64CD(2,3);U+64CD(2,3); # 33-64, CJK UNIFIED IDEOGRAPH-64CD +U+64D2(2,3);U+64D2(2,3); # 58-02, CJK UNIFIED IDEOGRAPH-64D2 +U+64D4(2,3);U+64D4(2,3); # 57-31, CJK UNIFIED IDEOGRAPH-64D4 +U+64D8(2,3);U+64D8(2,3); # 58-06, CJK UNIFIED IDEOGRAPH-64D8 +U+64DA(2,3);U+64DA(2,3); # 58-01, CJK UNIFIED IDEOGRAPH-64DA +U+64E0(2,3);U+64E0(2,3); # 58-11, CJK UNIFIED IDEOGRAPH-64E0 +U+64E1(2,3);U+64E1(2,3); # 58-12, CJK UNIFIED IDEOGRAPH-64E1 +U+64E2(2,3);U+64E2(2,3); # 37-07, CJK UNIFIED IDEOGRAPH-64E2 +U+64E3(2,3);U+64E3(2,3); # 58-14, CJK UNIFIED IDEOGRAPH-64E3 +U+64E6(2,3);U+64E6(2,3); # 27-04, CJK UNIFIED IDEOGRAPH-64E6 +U+64E7(2,3);U+64E7(2,3); # 58-09, CJK UNIFIED IDEOGRAPH-64E7 +U+64EC(2,3);U+64EC(2,3); # 21-28, CJK UNIFIED IDEOGRAPH-64EC +U+64EF(2,3);U+64EF(2,3); # 58-15, CJK UNIFIED IDEOGRAPH-64EF +U+64F1(2,3);U+64F1(2,3); # 58-08, CJK UNIFIED IDEOGRAPH-64F1 +U+64F2(2,3);U+64F2(2,3); # 58-19, CJK UNIFIED IDEOGRAPH-64F2 +U+64F4(2,3);U+64F4(2,3); # 58-18, CJK UNIFIED IDEOGRAPH-64F4 +U+64F6(2,3);U+64F6(2,3); # 58-17, CJK UNIFIED IDEOGRAPH-64F6 +U+64FA(2,3);U+64FA(2,3); # 58-20, CJK UNIFIED IDEOGRAPH-64FA +U+64FD(2,3);U+64FD(2,3); # 58-22, CJK UNIFIED IDEOGRAPH-64FD +U+64FE(2,3);U+64FE(2,3); # 30-81, CJK UNIFIED IDEOGRAPH-64FE +U+6500(2,3);U+6500(2,3); # 58-21, CJK UNIFIED IDEOGRAPH-6500 +U+6505(2,3);U+6505(2,3); # 58-25, CJK UNIFIED IDEOGRAPH-6505 +U+6518(2,3);U+6518(2,3); # 58-23, CJK UNIFIED IDEOGRAPH-6518 +U+651C(2,3);U+651C(2,3); # 58-24, CJK UNIFIED IDEOGRAPH-651C +U+651D(2,3);U+651D(2,3); # 57-80, CJK UNIFIED IDEOGRAPH-651D +U+6523(2,3);U+6523(2,3); # 58-27, CJK UNIFIED IDEOGRAPH-6523 +U+6524(2,3);U+6524(2,3); # 58-26, CJK UNIFIED IDEOGRAPH-6524 +U+652A(2,3);U+652A(2,3); # 57-88, CJK UNIFIED IDEOGRAPH-652A +U+652B(2,3);U+652B(2,3); # 58-28, CJK UNIFIED IDEOGRAPH-652B +U+652C(2,3);U+652C(2,3); # 58-16, CJK UNIFIED IDEOGRAPH-652C +U+652F(2,3);U+652F(2,3); # 27-57, CJK UNIFIED IDEOGRAPH-652F +U+6534(2,3);U+6534(2,3); # 58-29, CJK UNIFIED IDEOGRAPH-6534 +U+6535(2,3);U+6535(2,3); # 58-30, CJK UNIFIED IDEOGRAPH-6535 +U+6536(2,3);U+6536(2,3); # 58-32, CJK UNIFIED IDEOGRAPH-6536 +U+6537(2,3);U+6537(2,3); # 58-31, CJK UNIFIED IDEOGRAPH-6537 +U+6538(2,3);U+6538(2,3); # 58-33, CJK UNIFIED IDEOGRAPH-6538 +U+6539(2,3);U+6539(2,3); # 18-94, CJK UNIFIED IDEOGRAPH-6539 +U+653B(2,3);U+653B(2,3); # 25-22, CJK UNIFIED IDEOGRAPH-653B +U+653E(2,3);U+653E(2,3); # 42-92, CJK UNIFIED IDEOGRAPH-653E +U+653F(2,3);U+653F(2,3); # 32-15, CJK UNIFIED IDEOGRAPH-653F +U+6545(2,3);U+6545(2,3); # 24-46, CJK UNIFIED IDEOGRAPH-6545 +U+6548(2,3);U+6548(2,3); # 58-35, CJK UNIFIED IDEOGRAPH-6548 +U+654D(2,3);U+654D(2,3); # 58-38, CJK UNIFIED IDEOGRAPH-654D +U+654F(2,3);U+654F(2,3); # 41-50, CJK UNIFIED IDEOGRAPH-654F +U+6551(2,3);U+6551(2,3); # 21-63, CJK UNIFIED IDEOGRAPH-6551 +U+6555(2,3);U+6555(2,3); # 58-37, CJK UNIFIED IDEOGRAPH-6555 +U+6556(2,3);U+6556(2,3); # 58-36, CJK UNIFIED IDEOGRAPH-6556 +U+6557(2,3);U+6557(2,3); # 39-52, CJK UNIFIED IDEOGRAPH-6557 +U+6558(2,3);U+6558(2,3); # 58-39, CJK UNIFIED IDEOGRAPH-6558 +U+6559(2,3);U+6559(2,3); # 22-21, CJK UNIFIED IDEOGRAPH-6559 +U+655D(2,3);U+655D(2,3); # 58-41, CJK UNIFIED IDEOGRAPH-655D +U+655E(2,3);U+655E(2,3); # 58-40, CJK UNIFIED IDEOGRAPH-655E +U+6562(2,3);U+6562(2,3); # 20-26, CJK UNIFIED IDEOGRAPH-6562 +U+6563(2,3);U+6563(2,3); # 27-22, CJK UNIFIED IDEOGRAPH-6563 +U+6566(2,3);U+6566(2,3); # 38-56, CJK UNIFIED IDEOGRAPH-6566 +U+656C(2,3);U+656C(2,3); # 23-41, CJK UNIFIED IDEOGRAPH-656C +U+6570(2,3);U+6570(2,3); # 31-84, CJK UNIFIED IDEOGRAPH-6570 +U+6572(2,3);U+6572(2,3); # 58-42, CJK UNIFIED IDEOGRAPH-6572 +U+6574(2,3);U+6574(2,3); # 32-16, CJK UNIFIED IDEOGRAPH-6574 +U+6575(2,3);U+6575(2,3); # 37-08, CJK UNIFIED IDEOGRAPH-6575 +U+6577(2,3);U+6577(2,3); # 41-63, CJK UNIFIED IDEOGRAPH-6577 +U+6578(2,3);U+6578(2,3); # 58-43, CJK UNIFIED IDEOGRAPH-6578 +U+6582(2,3);U+6582(2,3); # 58-44, CJK UNIFIED IDEOGRAPH-6582 +U+6583(2,3);U+6583(2,3); # 58-45, CJK UNIFIED IDEOGRAPH-6583 +U+6587(2,3);U+6587(2,3); # 42-24, CJK UNIFIED IDEOGRAPH-6587 +U+6588(2,3);U+6588(2,3); # 53-61, CJK UNIFIED IDEOGRAPH-6588 +U+6589(2,3);U+6589(2,3); # 32-38, CJK UNIFIED IDEOGRAPH-6589 +U+658C(2,3);U+658C(2,3); # 41-44, CJK UNIFIED IDEOGRAPH-658C +U+658E(2,3);U+658E(2,3); # 26-56, CJK UNIFIED IDEOGRAPH-658E +U+6590(2,3);U+6590(2,3); # 40-69, CJK UNIFIED IDEOGRAPH-6590 +U+6591(2,3);U+6591(2,3); # 40-35, CJK UNIFIED IDEOGRAPH-6591 +U+6597(2,3);U+6597(2,3); # 37-45, CJK UNIFIED IDEOGRAPH-6597 +U+6599(2,3);U+6599(2,3); # 46-33, CJK UNIFIED IDEOGRAPH-6599 +U+659B(2,3);U+659B(2,3); # 58-47, CJK UNIFIED IDEOGRAPH-659B +U+659C(2,3);U+659C(2,3); # 28-48, CJK UNIFIED IDEOGRAPH-659C +U+659F(2,3);U+659F(2,3); # 58-48, CJK UNIFIED IDEOGRAPH-659F +U+65A1(2,3);U+65A1(2,3); # 16-22, CJK UNIFIED IDEOGRAPH-65A1 +U+65A4(2,3);U+65A4(2,3); # 22-52, CJK UNIFIED IDEOGRAPH-65A4 +U+65A5(2,3);U+65A5(2,3); # 32-45, CJK UNIFIED IDEOGRAPH-65A5 +U+65A7(2,3);U+65A7(2,3); # 41-64, CJK UNIFIED IDEOGRAPH-65A7 +U+65AB(2,3);U+65AB(2,3); # 58-49, CJK UNIFIED IDEOGRAPH-65AB +U+65AC(2,3);U+65AC(2,3); # 27-34, CJK UNIFIED IDEOGRAPH-65AC +U+65AD(2,3);U+65AD(2,3); # 35-39, CJK UNIFIED IDEOGRAPH-65AD +U+65AF(2,3);U+65AF(2,3); # 27-59, CJK UNIFIED IDEOGRAPH-65AF +U+65B0(2,3);U+65B0(2,3); # 31-23, CJK UNIFIED IDEOGRAPH-65B0 +U+65B7(2,3);U+65B7(2,3); # 58-50, CJK UNIFIED IDEOGRAPH-65B7 +U+65B9(2,3);U+65B9(2,3); # 42-93, CJK UNIFIED IDEOGRAPH-65B9 +U+65BC(2,3);U+65BC(2,3); # 17-87, CJK UNIFIED IDEOGRAPH-65BC +U+65BD(2,3);U+65BD(2,3); # 27-60, CJK UNIFIED IDEOGRAPH-65BD +U+65C1(2,3);U+65C1(2,3); # 58-53, CJK UNIFIED IDEOGRAPH-65C1 +U+65C3(2,3);U+65C3(2,3); # 58-51, CJK UNIFIED IDEOGRAPH-65C3 +U+65C4(2,3);U+65C4(2,3); # 58-54, CJK UNIFIED IDEOGRAPH-65C4 +U+65C5(2,3);U+65C5(2,3); # 46-25, CJK UNIFIED IDEOGRAPH-65C5 +U+65C6(2,3);U+65C6(2,3); # 58-52, CJK UNIFIED IDEOGRAPH-65C6 +U+65CB(2,3);U+65CB(2,3); # 32-91, CJK UNIFIED IDEOGRAPH-65CB +U+65CC(2,3);U+65CC(2,3); # 58-55, CJK UNIFIED IDEOGRAPH-65CC +U+65CF(2,3);U+65CF(2,3); # 34-18, CJK UNIFIED IDEOGRAPH-65CF +U+65D2(2,3);U+65D2(2,3); # 58-56, CJK UNIFIED IDEOGRAPH-65D2 +U+65D7(2,3);U+65D7(2,3); # 20-90, CJK UNIFIED IDEOGRAPH-65D7 +U+65D9(2,3);U+65D9(2,3); # 58-58, CJK UNIFIED IDEOGRAPH-65D9 +U+65DB(2,3);U+65DB(2,3); # 58-57, CJK UNIFIED IDEOGRAPH-65DB +U+65E0(2,3);U+65E0(2,3); # 58-59, CJK UNIFIED IDEOGRAPH-65E0 +U+65E1(2,3);U+65E1(2,3); # 58-60, CJK UNIFIED IDEOGRAPH-65E1 +U+65E2(2,3);U+65E2(2,3); # 20-91, CJK UNIFIED IDEOGRAPH-65E2 +U+65E5(2,3);U+65E5(2,3); # 38-92, CJK UNIFIED IDEOGRAPH-65E5 +U+65E6(2,3);U+65E6(2,3); # 35-22, CJK UNIFIED IDEOGRAPH-65E6 +U+65E7(2,3);U+65E7(2,3); # 21-76, CJK UNIFIED IDEOGRAPH-65E7 +U+65E8(2,3);U+65E8(2,3); # 27-61, CJK UNIFIED IDEOGRAPH-65E8 +U+65E9(2,3);U+65E9(2,3); # 33-65, CJK UNIFIED IDEOGRAPH-65E9 +U+65EC(2,3);U+65EC(2,3); # 29-60, CJK UNIFIED IDEOGRAPH-65EC +U+65ED(2,3);U+65ED(2,3); # 16-16, CJK UNIFIED IDEOGRAPH-65ED +U+65F1(2,3);U+65F1(2,3); # 58-61, CJK UNIFIED IDEOGRAPH-65F1 +U+65FA(2,3);U+65FA(2,3); # 18-02, CJK UNIFIED IDEOGRAPH-65FA +U+65FB(2,3);U+65FB(2,3); # 58-65, CJK UNIFIED IDEOGRAPH-65FB +U+6602(2,3);U+6602(2,3); # 25-23, CJK UNIFIED IDEOGRAPH-6602 +U+6603(2,3);U+6603(2,3); # 58-64, CJK UNIFIED IDEOGRAPH-6603 +U+6606(2,3);U+6606(2,3); # 26-11, CJK UNIFIED IDEOGRAPH-6606 +U+6607(2,3);U+6607(2,3); # 30-26, CJK UNIFIED IDEOGRAPH-6607 +U+660A(2,3);U+660A(2,3); # 58-63, CJK UNIFIED IDEOGRAPH-660A +U+660C(2,3);U+660C(2,3); # 30-27, CJK UNIFIED IDEOGRAPH-660C +U+660E(2,3);U+660E(2,3); # 44-32, CJK UNIFIED IDEOGRAPH-660E +U+660F(2,3);U+660F(2,3); # 26-10, CJK UNIFIED IDEOGRAPH-660F +U+6613(2,3);U+6613(2,3); # 16-55, CJK UNIFIED IDEOGRAPH-6613 +U+6614(2,3);U+6614(2,3); # 32-46, CJK UNIFIED IDEOGRAPH-6614 +U+661C(2,3);U+661C(2,3); # 58-70, CJK UNIFIED IDEOGRAPH-661C +U+661F(2,3);U+661F(2,3); # 32-17, CJK UNIFIED IDEOGRAPH-661F +U+6620(2,3);U+6620(2,3); # 17-39, CJK UNIFIED IDEOGRAPH-6620 +U+6625(2,3);U+6625(2,3); # 29-53, CJK UNIFIED IDEOGRAPH-6625 +U+6627(2,3);U+6627(2,3); # 43-70, CJK UNIFIED IDEOGRAPH-6627 +U+6628(2,3);U+6628(2,3); # 26-82, CJK UNIFIED IDEOGRAPH-6628 +U+662D(2,3);U+662D(2,3); # 30-28, CJK UNIFIED IDEOGRAPH-662D +U+662F(2,3);U+662F(2,3); # 32-07, CJK UNIFIED IDEOGRAPH-662F +U+6634(2,3);U+6634(2,3); # 58-69, CJK UNIFIED IDEOGRAPH-6634 +U+6635(2,3);U+6635(2,3); # 58-67, CJK UNIFIED IDEOGRAPH-6635 +U+6636(2,3);U+6636(2,3); # 58-68, CJK UNIFIED IDEOGRAPH-6636 +U+663C(2,3);U+663C(2,3); # 35-75, CJK UNIFIED IDEOGRAPH-663C +U+663F(2,3);U+663F(2,3); # 59-06, CJK UNIFIED IDEOGRAPH-663F +U+6641(2,3);U+6641(2,3); # 58-74, CJK UNIFIED IDEOGRAPH-6641 +U+6642(2,3);U+6642(2,3); # 27-94, CJK UNIFIED IDEOGRAPH-6642 +U+6643(2,3);U+6643(2,3); # 25-24, CJK UNIFIED IDEOGRAPH-6643 +U+6644(2,3);U+6644(2,3); # 58-72, CJK UNIFIED IDEOGRAPH-6644 +U+6649(2,3);U+6649(2,3); # 58-73, CJK UNIFIED IDEOGRAPH-6649 +U+664B(2,3);U+664B(2,3); # 31-24, CJK UNIFIED IDEOGRAPH-664B +U+664F(2,3);U+664F(2,3); # 58-71, CJK UNIFIED IDEOGRAPH-664F +U+6652(2,3);U+6652(2,3); # 27-15, CJK UNIFIED IDEOGRAPH-6652 +U+665D(2,3);U+665D(2,3); # 58-76, CJK UNIFIED IDEOGRAPH-665D +U+665E(2,3);U+665E(2,3); # 58-75, CJK UNIFIED IDEOGRAPH-665E +U+665F(2,3);U+665F(2,3); # 58-80, CJK UNIFIED IDEOGRAPH-665F +U+6662(2,3);U+6662(2,3); # 58-81, CJK UNIFIED IDEOGRAPH-6662 +U+6664(2,3);U+6664(2,3); # 58-77, CJK UNIFIED IDEOGRAPH-6664 +U+6666(2,3);U+6666(2,3); # 19-02, CJK UNIFIED IDEOGRAPH-6666 +U+6667(2,3);U+6667(2,3); # 58-78, CJK UNIFIED IDEOGRAPH-6667 +U+6668(2,3);U+6668(2,3); # 58-79, CJK UNIFIED IDEOGRAPH-6668 +U+6669(2,3);U+6669(2,3); # 40-53, CJK UNIFIED IDEOGRAPH-6669 +U+666E(2,3);U+666E(2,3); # 41-65, CJK UNIFIED IDEOGRAPH-666E +U+666F(2,3);U+666F(2,3); # 23-42, CJK UNIFIED IDEOGRAPH-666F +U+6670(2,3);U+6670(2,3); # 58-82, CJK UNIFIED IDEOGRAPH-6670 +U+6674(2,3);U+6674(2,3); # 32-18, CJK UNIFIED IDEOGRAPH-6674 +U+6676(2,3);U+6676(2,3); # 30-29, CJK UNIFIED IDEOGRAPH-6676 +U+667A(2,3);U+667A(2,3); # 35-50, CJK UNIFIED IDEOGRAPH-667A +U+6681(2,3);U+6681(2,3); # 22-39, CJK UNIFIED IDEOGRAPH-6681 +U+6683(2,3);U+6683(2,3); # 58-83, CJK UNIFIED IDEOGRAPH-6683 +U+6684(2,3);U+6684(2,3); # 58-87, CJK UNIFIED IDEOGRAPH-6684 +U+6687(2,3);U+6687(2,3); # 18-43, CJK UNIFIED IDEOGRAPH-6687 +U+6688(2,3);U+6688(2,3); # 58-84, CJK UNIFIED IDEOGRAPH-6688 +U+6689(2,3);U+6689(2,3); # 58-86, CJK UNIFIED IDEOGRAPH-6689 +U+668E(2,3);U+668E(2,3); # 58-85, CJK UNIFIED IDEOGRAPH-668E +U+6691(2,3);U+6691(2,3); # 29-75, CJK UNIFIED IDEOGRAPH-6691 +U+6696(2,3);U+6696(2,3); # 35-40, CJK UNIFIED IDEOGRAPH-6696 +U+6697(2,3);U+6697(2,3); # 16-37, CJK UNIFIED IDEOGRAPH-6697 +U+6698(2,3);U+6698(2,3); # 58-88, CJK UNIFIED IDEOGRAPH-6698 +U+669D(2,3);U+669D(2,3); # 58-89, CJK UNIFIED IDEOGRAPH-669D +U+66A2(2,3);U+66A2(2,3); # 36-10, CJK UNIFIED IDEOGRAPH-66A2 +U+66A6(2,3);U+66A6(2,3); # 46-81, CJK UNIFIED IDEOGRAPH-66A6 +U+66AB(2,3);U+66AB(2,3); # 27-35, CJK UNIFIED IDEOGRAPH-66AB +U+66AE(2,3);U+66AE(2,3); # 42-75, CJK UNIFIED IDEOGRAPH-66AE +U+66B4(2,3);U+66B4(2,3); # 43-29, CJK UNIFIED IDEOGRAPH-66B4 +U+66B8(2,3);U+66B8(2,3); # 59-02, CJK UNIFIED IDEOGRAPH-66B8 +U+66B9(2,3);U+66B9(2,3); # 58-91, CJK UNIFIED IDEOGRAPH-66B9 +U+66BC(2,3);U+66BC(2,3); # 58-94, CJK UNIFIED IDEOGRAPH-66BC +U+66BE(2,3);U+66BE(2,3); # 58-93, CJK UNIFIED IDEOGRAPH-66BE +U+66C1(2,3);U+66C1(2,3); # 58-90, CJK UNIFIED IDEOGRAPH-66C1 +U+66C4(2,3);U+66C4(2,3); # 59-01, CJK UNIFIED IDEOGRAPH-66C4 +U+66C7(2,3);U+66C7(2,3); # 38-62, CJK UNIFIED IDEOGRAPH-66C7 +U+66C9(2,3);U+66C9(2,3); # 58-92, CJK UNIFIED IDEOGRAPH-66C9 +U+66D6(2,3);U+66D6(2,3); # 59-03, CJK UNIFIED IDEOGRAPH-66D6 +U+66D9(2,3);U+66D9(2,3); # 29-76, CJK UNIFIED IDEOGRAPH-66D9 +U+66DA(2,3);U+66DA(2,3); # 59-04, CJK UNIFIED IDEOGRAPH-66DA +U+66DC(2,3);U+66DC(2,3); # 45-43, CJK UNIFIED IDEOGRAPH-66DC +U+66DD(2,3);U+66DD(2,3); # 39-88, CJK UNIFIED IDEOGRAPH-66DD +U+66E0(2,3);U+66E0(2,3); # 59-05, CJK UNIFIED IDEOGRAPH-66E0 +U+66E6(2,3);U+66E6(2,3); # 59-07, CJK UNIFIED IDEOGRAPH-66E6 +U+66E9(2,3);U+66E9(2,3); # 59-08, CJK UNIFIED IDEOGRAPH-66E9 +U+66F0(2,3);U+66F0(2,3); # 59-09, CJK UNIFIED IDEOGRAPH-66F0 +U+66F2(2,3);U+66F2(2,3); # 22-42, CJK UNIFIED IDEOGRAPH-66F2 +U+66F3(2,3);U+66F3(2,3); # 17-40, CJK UNIFIED IDEOGRAPH-66F3 +U+66F4(2,3);U+66F4(2,3); # 25-25, CJK UNIFIED IDEOGRAPH-66F4 +U+66F5(2,3);U+66F5(2,3); # 59-10, CJK UNIFIED IDEOGRAPH-66F5 +U+66F7(2,3);U+66F7(2,3); # 59-11, CJK UNIFIED IDEOGRAPH-66F7 +U+66F8(2,3);U+66F8(2,3); # 29-81, CJK UNIFIED IDEOGRAPH-66F8 +U+66F9(2,3);U+66F9(2,3); # 33-66, CJK UNIFIED IDEOGRAPH-66F9 +U+66FC(2,3);U+66FC(2,3); # 50-56, CJK UNIFIED IDEOGRAPH-66FC +U+66FD(2,3);U+66FD(2,3); # 33-30, CJK UNIFIED IDEOGRAPH-66FD +U+66FE(2,3);U+66FE(2,3); # 33-29, CJK UNIFIED IDEOGRAPH-66FE +U+66FF(2,3);U+66FF(2,3); # 34-56, CJK UNIFIED IDEOGRAPH-66FF +U+6700(2,3);U+6700(2,3); # 26-39, CJK UNIFIED IDEOGRAPH-6700 +U+6703(2,3);U+6703(2,3); # 48-82, CJK UNIFIED IDEOGRAPH-6703 +U+6708(2,3);U+6708(2,3); # 23-78, CJK UNIFIED IDEOGRAPH-6708 +U+6709(2,3);U+6709(2,3); # 45-13, CJK UNIFIED IDEOGRAPH-6709 +U+670B(2,3);U+670B(2,3); # 42-94, CJK UNIFIED IDEOGRAPH-670B +U+670D(2,3);U+670D(2,3); # 41-94, CJK UNIFIED IDEOGRAPH-670D +U+670F(2,3);U+670F(2,3); # 59-12, CJK UNIFIED IDEOGRAPH-670F +U+6714(2,3);U+6714(2,3); # 26-83, CJK UNIFIED IDEOGRAPH-6714 +U+6715(2,3);U+6715(2,3); # 36-31, CJK UNIFIED IDEOGRAPH-6715 +U+6716(2,3);U+6716(2,3); # 59-13, CJK UNIFIED IDEOGRAPH-6716 +U+6717(2,3);U+6717(2,3); # 47-15, CJK UNIFIED IDEOGRAPH-6717 +U+671B(2,3);U+671B(2,3); # 43-30, CJK UNIFIED IDEOGRAPH-671B +U+671D(2,3);U+671D(2,3); # 36-11, CJK UNIFIED IDEOGRAPH-671D +U+671E(2,3);U+671E(2,3); # 59-14, CJK UNIFIED IDEOGRAPH-671E +U+671F(2,3);U+671F(2,3); # 20-92, CJK UNIFIED IDEOGRAPH-671F +U+6726(2,3);U+6726(2,3); # 59-15, CJK UNIFIED IDEOGRAPH-6726 +U+6727(2,3);U+6727(2,3); # 59-16, CJK UNIFIED IDEOGRAPH-6727 +U+6728(2,3);U+6728(2,3); # 44-58, CJK UNIFIED IDEOGRAPH-6728 +U+672A(2,3);U+672A(2,3); # 44-04, CJK UNIFIED IDEOGRAPH-672A +U+672B(2,3);U+672B(2,3); # 43-86, CJK UNIFIED IDEOGRAPH-672B +U+672C(2,3);U+672C(2,3); # 43-60, CJK UNIFIED IDEOGRAPH-672C +U+672D(2,3);U+672D(2,3); # 27-05, CJK UNIFIED IDEOGRAPH-672D +U+672E(2,3);U+672E(2,3); # 59-18, CJK UNIFIED IDEOGRAPH-672E +U+6731(2,3);U+6731(2,3); # 28-75, CJK UNIFIED IDEOGRAPH-6731 +U+6734(2,3);U+6734(2,3); # 43-49, CJK UNIFIED IDEOGRAPH-6734 +U+6736(2,3);U+6736(2,3); # 59-20, CJK UNIFIED IDEOGRAPH-6736 +U+6737(2,3);U+6737(2,3); # 59-23, CJK UNIFIED IDEOGRAPH-6737 +U+6738(2,3);U+6738(2,3); # 59-22, CJK UNIFIED IDEOGRAPH-6738 +U+673A(2,3);U+673A(2,3); # 20-89, CJK UNIFIED IDEOGRAPH-673A +U+673D(2,3);U+673D(2,3); # 21-64, CJK UNIFIED IDEOGRAPH-673D +U+673F(2,3);U+673F(2,3); # 59-19, CJK UNIFIED IDEOGRAPH-673F +U+6741(2,3);U+6741(2,3); # 59-21, CJK UNIFIED IDEOGRAPH-6741 +U+6746(2,3);U+6746(2,3); # 59-24, CJK UNIFIED IDEOGRAPH-6746 +U+6749(2,3);U+6749(2,3); # 31-89, CJK UNIFIED IDEOGRAPH-6749 +U+674E(2,3);U+674E(2,3); # 45-91, CJK UNIFIED IDEOGRAPH-674E +U+674F(2,3);U+674F(2,3); # 16-41, CJK UNIFIED IDEOGRAPH-674F +U+6750(2,3);U+6750(2,3); # 26-64, CJK UNIFIED IDEOGRAPH-6750 +U+6751(2,3);U+6751(2,3); # 34-28, CJK UNIFIED IDEOGRAPH-6751 +U+6753(2,3);U+6753(2,3); # 28-61, CJK UNIFIED IDEOGRAPH-6753 +U+6756(2,3);U+6756(2,3); # 30-83, CJK UNIFIED IDEOGRAPH-6756 +U+6759(2,3);U+6759(2,3); # 59-27, CJK UNIFIED IDEOGRAPH-6759 +U+675C(2,3);U+675C(2,3); # 37-46, CJK UNIFIED IDEOGRAPH-675C +U+675E(2,3);U+675E(2,3); # 59-25, CJK UNIFIED IDEOGRAPH-675E +U+675F(2,3);U+675F(2,3); # 34-11, CJK UNIFIED IDEOGRAPH-675F +U+6760(2,3);U+6760(2,3); # 59-26, CJK UNIFIED IDEOGRAPH-6760 +U+6761(2,3);U+6761(2,3); # 30-82, CJK UNIFIED IDEOGRAPH-6761 +U+6762(2,3);U+6762(2,3); # 44-61, CJK UNIFIED IDEOGRAPH-6762 +U+6763(2,3);U+6763(2,3); # 59-28, CJK UNIFIED IDEOGRAPH-6763 +U+6764(2,3);U+6764(2,3); # 59-29, CJK UNIFIED IDEOGRAPH-6764 +U+6765(2,3);U+6765(2,3); # 45-72, CJK UNIFIED IDEOGRAPH-6765 +U+676A(2,3);U+676A(2,3); # 59-34, CJK UNIFIED IDEOGRAPH-676A +U+676D(2,3);U+676D(2,3); # 25-26, CJK UNIFIED IDEOGRAPH-676D +U+676F(2,3);U+676F(2,3); # 39-53, CJK UNIFIED IDEOGRAPH-676F +U+6770(2,3);U+6770(2,3); # 59-31, CJK UNIFIED IDEOGRAPH-6770 +U+6771(2,3);U+6771(2,3); # 37-76, CJK UNIFIED IDEOGRAPH-6771 +U+6772(2,3);U+6772(2,3); # 58-62, CJK UNIFIED IDEOGRAPH-6772 +U+6773(2,3);U+6773(2,3); # 58-66, CJK UNIFIED IDEOGRAPH-6773 +U+6775(2,3);U+6775(2,3); # 21-47, CJK UNIFIED IDEOGRAPH-6775 +U+6777(2,3);U+6777(2,3); # 39-39, CJK UNIFIED IDEOGRAPH-6777 +U+677C(2,3);U+677C(2,3); # 59-33, CJK UNIFIED IDEOGRAPH-677C +U+677E(2,3);U+677E(2,3); # 30-30, CJK UNIFIED IDEOGRAPH-677E +U+677F(2,3);U+677F(2,3); # 40-36, CJK UNIFIED IDEOGRAPH-677F +U+6785(2,3);U+6785(2,3); # 59-39, CJK UNIFIED IDEOGRAPH-6785 +U+6787(2,3);U+6787(2,3); # 40-90, CJK UNIFIED IDEOGRAPH-6787 +U+6789(2,3);U+6789(2,3); # 59-30, CJK UNIFIED IDEOGRAPH-6789 +U+678B(2,3);U+678B(2,3); # 59-36, CJK UNIFIED IDEOGRAPH-678B +U+678C(2,3);U+678C(2,3); # 59-35, CJK UNIFIED IDEOGRAPH-678C +U+6790(2,3);U+6790(2,3); # 32-47, CJK UNIFIED IDEOGRAPH-6790 +U+6795(2,3);U+6795(2,3); # 43-77, CJK UNIFIED IDEOGRAPH-6795 +U+6797(2,3);U+6797(2,3); # 46-51, CJK UNIFIED IDEOGRAPH-6797 +U+679A(2,3);U+679A(2,3); # 43-71, CJK UNIFIED IDEOGRAPH-679A +U+679C(2,3);U+679C(2,3); # 18-44, CJK UNIFIED IDEOGRAPH-679C +U+679D(2,3);U+679D(2,3); # 27-62, CJK UNIFIED IDEOGRAPH-679D +U+67A0(2,3);U+67A0(2,3); # 47-40, CJK UNIFIED IDEOGRAPH-67A0 +U+67A1(2,3);U+67A1(2,3); # 59-38, CJK UNIFIED IDEOGRAPH-67A1 +U+67A2(2,3);U+67A2(2,3); # 31-85, CJK UNIFIED IDEOGRAPH-67A2 +U+67A6(2,3);U+67A6(2,3); # 59-37, CJK UNIFIED IDEOGRAPH-67A6 +U+67A9(2,3);U+67A9(2,3); # 59-32, CJK UNIFIED IDEOGRAPH-67A9 +U+67AF(2,3);U+67AF(2,3); # 24-47, CJK UNIFIED IDEOGRAPH-67AF +U+67B3(2,3);U+67B3(2,3); # 59-44, CJK UNIFIED IDEOGRAPH-67B3 +U+67B4(2,3);U+67B4(2,3); # 59-42, CJK UNIFIED IDEOGRAPH-67B4 +U+67B6(2,3);U+67B6(2,3); # 18-45, CJK UNIFIED IDEOGRAPH-67B6 +U+67B7(2,3);U+67B7(2,3); # 59-40, CJK UNIFIED IDEOGRAPH-67B7 +U+67B8(2,3);U+67B8(2,3); # 59-46, CJK UNIFIED IDEOGRAPH-67B8 +U+67B9(2,3);U+67B9(2,3); # 59-52, CJK UNIFIED IDEOGRAPH-67B9 +U+67C1(2,3);U+67C1(2,3); # 34-40, CJK UNIFIED IDEOGRAPH-67C1 +U+67C4(2,3);U+67C4(2,3); # 42-33, CJK UNIFIED IDEOGRAPH-67C4 +U+67C6(2,3);U+67C6(2,3); # 59-54, CJK UNIFIED IDEOGRAPH-67C6 +U+67CA(2,3);U+67CA(2,3); # 41-02, CJK UNIFIED IDEOGRAPH-67CA +U+67CE(2,3);U+67CE(2,3); # 59-53, CJK UNIFIED IDEOGRAPH-67CE +U+67CF(2,3);U+67CF(2,3); # 39-80, CJK UNIFIED IDEOGRAPH-67CF +U+67D0(2,3);U+67D0(2,3); # 43-31, CJK UNIFIED IDEOGRAPH-67D0 +U+67D1(2,3);U+67D1(2,3); # 20-27, CJK UNIFIED IDEOGRAPH-67D1 +U+67D3(2,3);U+67D3(2,3); # 32-87, CJK UNIFIED IDEOGRAPH-67D3 +U+67D4(2,3);U+67D4(2,3); # 29-32, CJK UNIFIED IDEOGRAPH-67D4 +U+67D8(2,3);U+67D8(2,3); # 36-51, CJK UNIFIED IDEOGRAPH-67D8 +U+67DA(2,3);U+67DA(2,3); # 45-14, CJK UNIFIED IDEOGRAPH-67DA +U+67DD(2,3);U+67DD(2,3); # 59-49, CJK UNIFIED IDEOGRAPH-67DD +U+67DE(2,3);U+67DE(2,3); # 59-48, CJK UNIFIED IDEOGRAPH-67DE +U+67E2(2,3);U+67E2(2,3); # 59-50, CJK UNIFIED IDEOGRAPH-67E2 +U+67E4(2,3);U+67E4(2,3); # 59-47, CJK UNIFIED IDEOGRAPH-67E4 +U+67E7(2,3);U+67E7(2,3); # 59-55, CJK UNIFIED IDEOGRAPH-67E7 +U+67E9(2,3);U+67E9(2,3); # 59-45, CJK UNIFIED IDEOGRAPH-67E9 +U+67EC(2,3);U+67EC(2,3); # 59-43, CJK UNIFIED IDEOGRAPH-67EC +U+67EE(2,3);U+67EE(2,3); # 59-51, CJK UNIFIED IDEOGRAPH-67EE +U+67EF(2,3);U+67EF(2,3); # 59-41, CJK UNIFIED IDEOGRAPH-67EF +U+67F1(2,3);U+67F1(2,3); # 35-76, CJK UNIFIED IDEOGRAPH-67F1 +U+67F3(2,3);U+67F3(2,3); # 44-88, CJK UNIFIED IDEOGRAPH-67F3 +U+67F4(2,3);U+67F4(2,3); # 28-38, CJK UNIFIED IDEOGRAPH-67F4 +U+67F5(2,3);U+67F5(2,3); # 26-84, CJK UNIFIED IDEOGRAPH-67F5 +U+67FB(2,3);U+67FB(2,3); # 26-26, CJK UNIFIED IDEOGRAPH-67FB +U+67FE(2,3);U+67FE(2,3); # 43-79, CJK UNIFIED IDEOGRAPH-67FE +U+67FF(2,3);U+67FF(2,3); # 19-33, CJK UNIFIED IDEOGRAPH-67FF +U+6802(2,3);U+6802(2,3); # 36-46, CJK UNIFIED IDEOGRAPH-6802 +U+6803(2,3);U+6803(2,3); # 38-42, CJK UNIFIED IDEOGRAPH-6803 +U+6804(2,3);U+6804(2,3); # 17-41, CJK UNIFIED IDEOGRAPH-6804 +U+6813(2,3);U+6813(2,3); # 32-82, CJK UNIFIED IDEOGRAPH-6813 +U+6816(2,3);U+6816(2,3); # 32-20, CJK UNIFIED IDEOGRAPH-6816 +U+6817(2,3);U+6817(2,3); # 23-10, CJK UNIFIED IDEOGRAPH-6817 +U+681E(2,3);U+681E(2,3); # 59-57, CJK UNIFIED IDEOGRAPH-681E +U+6821(2,3);U+6821(2,3); # 25-27, CJK UNIFIED IDEOGRAPH-6821 +U+6822(2,3);U+6822(2,3); # 19-92, CJK UNIFIED IDEOGRAPH-6822 +U+6829(2,3);U+6829(2,3); # 59-59, CJK UNIFIED IDEOGRAPH-6829 +U+682A(2,3);U+682A(2,3); # 19-84, CJK UNIFIED IDEOGRAPH-682A +U+682B(2,3);U+682B(2,3); # 59-65, CJK UNIFIED IDEOGRAPH-682B +U+6832(2,3);U+6832(2,3); # 59-62, CJK UNIFIED IDEOGRAPH-6832 +U+6834(2,3);U+6834(2,3); # 32-83, CJK UNIFIED IDEOGRAPH-6834 +U+6838(2,3);U+6838(2,3); # 19-43, CJK UNIFIED IDEOGRAPH-6838 +U+6839(2,3);U+6839(2,3); # 26-12, CJK UNIFIED IDEOGRAPH-6839 +U+683C(2,3);U+683C(2,3); # 19-42, CJK UNIFIED IDEOGRAPH-683C +U+683D(2,3);U+683D(2,3); # 26-47, CJK UNIFIED IDEOGRAPH-683D +U+6840(2,3);U+6840(2,3); # 59-60, CJK UNIFIED IDEOGRAPH-6840 +U+6841(2,3);U+6841(2,3); # 23-69, CJK UNIFIED IDEOGRAPH-6841 +U+6842(2,3);U+6842(2,3); # 23-43, CJK UNIFIED IDEOGRAPH-6842 +U+6843(2,3);U+6843(2,3); # 37-77, CJK UNIFIED IDEOGRAPH-6843 +U+6846(2,3);U+6846(2,3); # 59-58, CJK UNIFIED IDEOGRAPH-6846 +U+6848(2,3);U+6848(2,3); # 16-38, CJK UNIFIED IDEOGRAPH-6848 +U+684D(2,3);U+684D(2,3); # 59-61, CJK UNIFIED IDEOGRAPH-684D +U+684E(2,3);U+684E(2,3); # 59-63, CJK UNIFIED IDEOGRAPH-684E +U+6850(2,3);U+6850(2,3); # 22-45, CJK UNIFIED IDEOGRAPH-6850 +U+6851(2,3);U+6851(2,3); # 23-12, CJK UNIFIED IDEOGRAPH-6851 +U+6853(2,3);U+6853(2,3); # 20-28, CJK UNIFIED IDEOGRAPH-6853 +U+6854(2,3);U+6854(2,3); # 21-43, CJK UNIFIED IDEOGRAPH-6854 +U+6859(2,3);U+6859(2,3); # 59-66, CJK UNIFIED IDEOGRAPH-6859 +U+685C(2,3);U+685C(2,3); # 26-89, CJK UNIFIED IDEOGRAPH-685C +U+685D(2,3);U+685D(2,3); # 43-81, CJK UNIFIED IDEOGRAPH-685D +U+685F(2,3);U+685F(2,3); # 27-23, CJK UNIFIED IDEOGRAPH-685F +U+6863(2,3);U+6863(2,3); # 59-67, CJK UNIFIED IDEOGRAPH-6863 +U+6867(2,3);U+6867(2,3); # 41-16, CJK UNIFIED IDEOGRAPH-6867 +U+6874(2,3);U+6874(2,3); # 59-79, CJK UNIFIED IDEOGRAPH-6874 +U+6876(2,3);U+6876(2,3); # 18-19, CJK UNIFIED IDEOGRAPH-6876 +U+6877(2,3);U+6877(2,3); # 59-68, CJK UNIFIED IDEOGRAPH-6877 +U+687E(2,3);U+687E(2,3); # 59-85, CJK UNIFIED IDEOGRAPH-687E +U+687F(2,3);U+687F(2,3); # 59-69, CJK UNIFIED IDEOGRAPH-687F +U+6881(2,3);U+6881(2,3); # 46-34, CJK UNIFIED IDEOGRAPH-6881 +U+6883(2,3);U+6883(2,3); # 59-76, CJK UNIFIED IDEOGRAPH-6883 +U+6885(2,3);U+6885(2,3); # 39-63, CJK UNIFIED IDEOGRAPH-6885 +U+688D(2,3);U+688D(2,3); # 59-84, CJK UNIFIED IDEOGRAPH-688D +U+688F(2,3);U+688F(2,3); # 59-71, CJK UNIFIED IDEOGRAPH-688F +U+6893(2,3);U+6893(2,3); # 16-20, CJK UNIFIED IDEOGRAPH-6893 +U+6894(2,3);U+6894(2,3); # 59-73, CJK UNIFIED IDEOGRAPH-6894 +U+6897(2,3);U+6897(2,3); # 25-28, CJK UNIFIED IDEOGRAPH-6897 +U+689B(2,3);U+689B(2,3); # 59-75, CJK UNIFIED IDEOGRAPH-689B +U+689D(2,3);U+689D(2,3); # 59-74, CJK UNIFIED IDEOGRAPH-689D +U+689F(2,3);U+689F(2,3); # 59-70, CJK UNIFIED IDEOGRAPH-689F +U+68A0(2,3);U+68A0(2,3); # 59-81, CJK UNIFIED IDEOGRAPH-68A0 +U+68A2(2,3);U+68A2(2,3); # 30-31, CJK UNIFIED IDEOGRAPH-68A2 +U+68A6(2,3);U+68A6(2,3); # 52-77, CJK UNIFIED IDEOGRAPH-68A6 +U+68A7(2,3);U+68A7(2,3); # 24-72, CJK UNIFIED IDEOGRAPH-68A7 +U+68A8(2,3);U+68A8(2,3); # 45-92, CJK UNIFIED IDEOGRAPH-68A8 +U+68AD(2,3);U+68AD(2,3); # 59-72, CJK UNIFIED IDEOGRAPH-68AD +U+68AF(2,3);U+68AF(2,3); # 36-84, CJK UNIFIED IDEOGRAPH-68AF +U+68B0(2,3);U+68B0(2,3); # 19-03, CJK UNIFIED IDEOGRAPH-68B0 +U+68B1(2,3);U+68B1(2,3); # 26-13, CJK UNIFIED IDEOGRAPH-68B1 +U+68B3(2,3);U+68B3(2,3); # 59-64, CJK UNIFIED IDEOGRAPH-68B3 +U+68B5(2,3);U+68B5(2,3); # 59-80, CJK UNIFIED IDEOGRAPH-68B5 +U+68B6(2,3);U+68B6(2,3); # 19-65, CJK UNIFIED IDEOGRAPH-68B6 +U+68B9(2,3);U+68B9(2,3); # 59-78, CJK UNIFIED IDEOGRAPH-68B9 +U+68BA(2,3);U+68BA(2,3); # 59-82, CJK UNIFIED IDEOGRAPH-68BA +U+68BC(2,3);U+68BC(2,3); # 37-78, CJK UNIFIED IDEOGRAPH-68BC +U+68C4(2,3);U+68C4(2,3); # 20-94, CJK UNIFIED IDEOGRAPH-68C4 +U+68C6(2,3);U+68C6(2,3); # 60-18, CJK UNIFIED IDEOGRAPH-68C6 +U+68C9(2,3);U+68C9(2,3); # 44-41, CJK UNIFIED IDEOGRAPH-68C9 +U+68CA(2,3);U+68CA(2,3); # 59-87, CJK UNIFIED IDEOGRAPH-68CA +U+68CB(2,3);U+68CB(2,3); # 20-93, CJK UNIFIED IDEOGRAPH-68CB +U+68CD(2,3);U+68CD(2,3); # 59-94, CJK UNIFIED IDEOGRAPH-68CD +U+68D2(2,3);U+68D2(2,3); # 43-32, CJK UNIFIED IDEOGRAPH-68D2 +U+68D4(2,3);U+68D4(2,3); # 60-01, CJK UNIFIED IDEOGRAPH-68D4 +U+68D5(2,3);U+68D5(2,3); # 60-03, CJK UNIFIED IDEOGRAPH-68D5 +U+68D7(2,3);U+68D7(2,3); # 60-07, CJK UNIFIED IDEOGRAPH-68D7 +U+68D8(2,3);U+68D8(2,3); # 59-89, CJK UNIFIED IDEOGRAPH-68D8 +U+68DA(2,3);U+68DA(2,3); # 35-10, CJK UNIFIED IDEOGRAPH-68DA +U+68DF(2,3);U+68DF(2,3); # 37-79, CJK UNIFIED IDEOGRAPH-68DF +U+68E0(2,3);U+68E0(2,3); # 60-11, CJK UNIFIED IDEOGRAPH-68E0 +U+68E1(2,3);U+68E1(2,3); # 59-92, CJK UNIFIED IDEOGRAPH-68E1 +U+68E3(2,3);U+68E3(2,3); # 60-08, CJK UNIFIED IDEOGRAPH-68E3 +U+68E7(2,3);U+68E7(2,3); # 60-02, CJK UNIFIED IDEOGRAPH-68E7 +U+68EE(2,3);U+68EE(2,3); # 31-25, CJK UNIFIED IDEOGRAPH-68EE +U+68EF(2,3);U+68EF(2,3); # 60-12, CJK UNIFIED IDEOGRAPH-68EF +U+68F2(2,3);U+68F2(2,3); # 32-19, CJK UNIFIED IDEOGRAPH-68F2 +U+68F9(2,3);U+68F9(2,3); # 60-10, CJK UNIFIED IDEOGRAPH-68F9 +U+68FA(2,3);U+68FA(2,3); # 20-29, CJK UNIFIED IDEOGRAPH-68FA +U+6900(2,3);U+6900(2,3); # 47-48, CJK UNIFIED IDEOGRAPH-6900 +U+6901(2,3);U+6901(2,3); # 59-86, CJK UNIFIED IDEOGRAPH-6901 +U+6904(2,3);U+6904(2,3); # 60-06, CJK UNIFIED IDEOGRAPH-6904 +U+6905(2,3);U+6905(2,3); # 16-56, CJK UNIFIED IDEOGRAPH-6905 +U+6908(2,3);U+6908(2,3); # 59-88, CJK UNIFIED IDEOGRAPH-6908 +U+690B(2,3);U+690B(2,3); # 44-26, CJK UNIFIED IDEOGRAPH-690B +U+690C(2,3);U+690C(2,3); # 59-93, CJK UNIFIED IDEOGRAPH-690C +U+690D(2,3);U+690D(2,3); # 31-02, CJK UNIFIED IDEOGRAPH-690D +U+690E(2,3);U+690E(2,3); # 36-39, CJK UNIFIED IDEOGRAPH-690E +U+690F(2,3);U+690F(2,3); # 59-83, CJK UNIFIED IDEOGRAPH-690F +U+6912(2,3);U+6912(2,3); # 60-05, CJK UNIFIED IDEOGRAPH-6912 +U+6919(2,3);U+6919(2,3); # 31-90, CJK UNIFIED IDEOGRAPH-6919 +U+691A(2,3);U+691A(2,3); # 60-15, CJK UNIFIED IDEOGRAPH-691A +U+691B(2,3);U+691B(2,3); # 19-81, CJK UNIFIED IDEOGRAPH-691B +U+691C(2,3);U+691C(2,3); # 24-01, CJK UNIFIED IDEOGRAPH-691C +U+6921(2,3);U+6921(2,3); # 60-17, CJK UNIFIED IDEOGRAPH-6921 +U+6922(2,3);U+6922(2,3); # 59-90, CJK UNIFIED IDEOGRAPH-6922 +U+6923(2,3);U+6923(2,3); # 60-16, CJK UNIFIED IDEOGRAPH-6923 +U+6925(2,3);U+6925(2,3); # 60-09, CJK UNIFIED IDEOGRAPH-6925 +U+6926(2,3);U+6926(2,3); # 59-91, CJK UNIFIED IDEOGRAPH-6926 +U+6928(2,3);U+6928(2,3); # 60-13, CJK UNIFIED IDEOGRAPH-6928 +U+692A(2,3);U+692A(2,3); # 60-14, CJK UNIFIED IDEOGRAPH-692A +U+6930(2,3);U+6930(2,3); # 60-31, CJK UNIFIED IDEOGRAPH-6930 +U+6934(2,3);U+6934(2,3); # 38-46, CJK UNIFIED IDEOGRAPH-6934 +U+6936(2,3);U+6936(2,3); # 60-04, CJK UNIFIED IDEOGRAPH-6936 +U+6939(2,3);U+6939(2,3); # 60-27, CJK UNIFIED IDEOGRAPH-6939 +U+693D(2,3);U+693D(2,3); # 60-29, CJK UNIFIED IDEOGRAPH-693D +U+693F(2,3);U+693F(2,3); # 36-56, CJK UNIFIED IDEOGRAPH-693F +U+694A(2,3);U+694A(2,3); # 45-44, CJK UNIFIED IDEOGRAPH-694A +U+6953(2,3);U+6953(2,3); # 41-86, CJK UNIFIED IDEOGRAPH-6953 +U+6954(2,3);U+6954(2,3); # 60-24, CJK UNIFIED IDEOGRAPH-6954 +U+6955(2,3);U+6955(2,3); # 34-42, CJK UNIFIED IDEOGRAPH-6955 +U+6959(2,3);U+6959(2,3); # 60-30, CJK UNIFIED IDEOGRAPH-6959 +U+695A(2,3);U+695A(2,3); # 33-31, CJK UNIFIED IDEOGRAPH-695A +U+695C(2,3);U+695C(2,3); # 60-21, CJK UNIFIED IDEOGRAPH-695C +U+695D(2,3);U+695D(2,3); # 60-34, CJK UNIFIED IDEOGRAPH-695D +U+695E(2,3);U+695E(2,3); # 60-33, CJK UNIFIED IDEOGRAPH-695E +U+6960(2,3);U+6960(2,3); # 38-79, CJK UNIFIED IDEOGRAPH-6960 +U+6961(2,3);U+6961(2,3); # 60-32, CJK UNIFIED IDEOGRAPH-6961 +U+6962(2,3);U+6962(2,3); # 38-74, CJK UNIFIED IDEOGRAPH-6962 +U+696A(2,3);U+696A(2,3); # 60-36, CJK UNIFIED IDEOGRAPH-696A +U+696B(2,3);U+696B(2,3); # 60-23, CJK UNIFIED IDEOGRAPH-696B +U+696D(2,3);U+696D(2,3); # 22-40, CJK UNIFIED IDEOGRAPH-696D +U+696E(2,3);U+696E(2,3); # 60-26, CJK UNIFIED IDEOGRAPH-696E +U+696F(2,3);U+696F(2,3); # 29-61, CJK UNIFIED IDEOGRAPH-696F +U+6973(2,3);U+6973(2,3); # 39-64, CJK UNIFIED IDEOGRAPH-6973 +U+6974(2,3);U+6974(2,3); # 60-28, CJK UNIFIED IDEOGRAPH-6974 +U+6975(2,3);U+6975(2,3); # 22-43, CJK UNIFIED IDEOGRAPH-6975 +U+6977(2,3);U+6977(2,3); # 60-20, CJK UNIFIED IDEOGRAPH-6977 +U+6978(2,3);U+6978(2,3); # 60-22, CJK UNIFIED IDEOGRAPH-6978 +U+6979(2,3);U+6979(2,3); # 60-19, CJK UNIFIED IDEOGRAPH-6979 +U+697C(2,3);U+697C(2,3); # 47-16, CJK UNIFIED IDEOGRAPH-697C +U+697D(2,3);U+697D(2,3); # 19-58, CJK UNIFIED IDEOGRAPH-697D +U+697E(2,3);U+697E(2,3); # 60-25, CJK UNIFIED IDEOGRAPH-697E +U+6981(2,3);U+6981(2,3); # 60-35, CJK UNIFIED IDEOGRAPH-6981 +U+6982(2,3);U+6982(2,3); # 19-21, CJK UNIFIED IDEOGRAPH-6982 +U+698A(2,3);U+698A(2,3); # 26-71, CJK UNIFIED IDEOGRAPH-698A +U+698E(2,3);U+698E(2,3); # 17-61, CJK UNIFIED IDEOGRAPH-698E +U+6991(2,3);U+6991(2,3); # 60-52, CJK UNIFIED IDEOGRAPH-6991 +U+6994(2,3);U+6994(2,3); # 47-17, CJK UNIFIED IDEOGRAPH-6994 +U+6995(2,3);U+6995(2,3); # 60-55, CJK UNIFIED IDEOGRAPH-6995 +U+699B(2,3);U+699B(2,3); # 31-26, CJK UNIFIED IDEOGRAPH-699B +U+699C(2,3);U+699C(2,3); # 60-54, CJK UNIFIED IDEOGRAPH-699C +U+69A0(2,3);U+69A0(2,3); # 60-53, CJK UNIFIED IDEOGRAPH-69A0 +U+69A7(2,3);U+69A7(2,3); # 60-50, CJK UNIFIED IDEOGRAPH-69A7 +U+69AE(2,3);U+69AE(2,3); # 60-38, CJK UNIFIED IDEOGRAPH-69AE +U+69B1(2,3);U+69B1(2,3); # 60-67, CJK UNIFIED IDEOGRAPH-69B1 +U+69B2(2,3);U+69B2(2,3); # 60-37, CJK UNIFIED IDEOGRAPH-69B2 +U+69B4(2,3);U+69B4(2,3); # 60-56, CJK UNIFIED IDEOGRAPH-69B4 +U+69BB(2,3);U+69BB(2,3); # 60-48, CJK UNIFIED IDEOGRAPH-69BB +U+69BE(2,3);U+69BE(2,3); # 60-43, CJK UNIFIED IDEOGRAPH-69BE +U+69BF(2,3);U+69BF(2,3); # 60-40, CJK UNIFIED IDEOGRAPH-69BF +U+69C1(2,3);U+69C1(2,3); # 60-41, CJK UNIFIED IDEOGRAPH-69C1 +U+69C3(2,3);U+69C3(2,3); # 60-49, CJK UNIFIED IDEOGRAPH-69C3 +U+69C7(2,3);U+69C7(2,3); # 84-02, CJK UNIFIED IDEOGRAPH-69C7 +U+69CA(2,3);U+69CA(2,3); # 60-46, CJK UNIFIED IDEOGRAPH-69CA +U+69CB(2,3);U+69CB(2,3); # 25-29, CJK UNIFIED IDEOGRAPH-69CB +U+69CC(2,3);U+69CC(2,3); # 36-40, CJK UNIFIED IDEOGRAPH-69CC +U+69CD(2,3);U+69CD(2,3); # 33-68, CJK UNIFIED IDEOGRAPH-69CD +U+69CE(2,3);U+69CE(2,3); # 60-44, CJK UNIFIED IDEOGRAPH-69CE +U+69D0(2,3);U+69D0(2,3); # 60-39, CJK UNIFIED IDEOGRAPH-69D0 +U+69D3(2,3);U+69D3(2,3); # 60-42, CJK UNIFIED IDEOGRAPH-69D3 +U+69D8(2,3);U+69D8(2,3); # 45-45, CJK UNIFIED IDEOGRAPH-69D8 +U+69D9(2,3);U+69D9(2,3); # 43-74, CJK UNIFIED IDEOGRAPH-69D9 +U+69DD(2,3);U+69DD(2,3); # 60-47, CJK UNIFIED IDEOGRAPH-69DD +U+69DE(2,3);U+69DE(2,3); # 60-57, CJK UNIFIED IDEOGRAPH-69DE +U+69E7(2,3);U+69E7(2,3); # 60-65, CJK UNIFIED IDEOGRAPH-69E7 +U+69E8(2,3);U+69E8(2,3); # 60-58, CJK UNIFIED IDEOGRAPH-69E8 +U+69EB(2,3);U+69EB(2,3); # 60-71, CJK UNIFIED IDEOGRAPH-69EB +U+69ED(2,3);U+69ED(2,3); # 60-69, CJK UNIFIED IDEOGRAPH-69ED +U+69F2(2,3);U+69F2(2,3); # 60-64, CJK UNIFIED IDEOGRAPH-69F2 +U+69F9(2,3);U+69F9(2,3); # 60-63, CJK UNIFIED IDEOGRAPH-69F9 +U+69FB(2,3);U+69FB(2,3); # 36-48, CJK UNIFIED IDEOGRAPH-69FB +U+69FD(2,3);U+69FD(2,3); # 33-69, CJK UNIFIED IDEOGRAPH-69FD +U+69FF(2,3);U+69FF(2,3); # 60-61, CJK UNIFIED IDEOGRAPH-69FF +U+6A02(2,3);U+6A02(2,3); # 60-59, CJK UNIFIED IDEOGRAPH-6A02 +U+6A05(2,3);U+6A05(2,3); # 60-66, CJK UNIFIED IDEOGRAPH-6A05 +U+6A0A(2,3);U+6A0A(2,3); # 60-72, CJK UNIFIED IDEOGRAPH-6A0A +U+6A0B(2,3);U+6A0B(2,3); # 40-85, CJK UNIFIED IDEOGRAPH-6A0B +U+6A0C(2,3);U+6A0C(2,3); # 60-78, CJK UNIFIED IDEOGRAPH-6A0C +U+6A12(2,3);U+6A12(2,3); # 60-73, CJK UNIFIED IDEOGRAPH-6A12 +U+6A13(2,3);U+6A13(2,3); # 60-76, CJK UNIFIED IDEOGRAPH-6A13 +U+6A14(2,3);U+6A14(2,3); # 60-70, CJK UNIFIED IDEOGRAPH-6A14 +U+6A17(2,3);U+6A17(2,3); # 35-84, CJK UNIFIED IDEOGRAPH-6A17 +U+6A19(2,3);U+6A19(2,3); # 41-24, CJK UNIFIED IDEOGRAPH-6A19 +U+6A1B(2,3);U+6A1B(2,3); # 60-60, CJK UNIFIED IDEOGRAPH-6A1B +U+6A1E(2,3);U+6A1E(2,3); # 60-68, CJK UNIFIED IDEOGRAPH-6A1E +U+6A1F(2,3);U+6A1F(2,3); # 30-32, CJK UNIFIED IDEOGRAPH-6A1F +U+6A21(2,3);U+6A21(2,3); # 44-47, CJK UNIFIED IDEOGRAPH-6A21 +U+6A22(2,3);U+6A22(2,3); # 60-88, CJK UNIFIED IDEOGRAPH-6A22 +U+6A23(2,3);U+6A23(2,3); # 60-75, CJK UNIFIED IDEOGRAPH-6A23 +U+6A29(2,3);U+6A29(2,3); # 24-02, CJK UNIFIED IDEOGRAPH-6A29 +U+6A2A(2,3);U+6A2A(2,3); # 18-03, CJK UNIFIED IDEOGRAPH-6A2A +U+6A2B(2,3);U+6A2B(2,3); # 19-63, CJK UNIFIED IDEOGRAPH-6A2B +U+6A2E(2,3);U+6A2E(2,3); # 60-51, CJK UNIFIED IDEOGRAPH-6A2E +U+6A35(2,3);U+6A35(2,3); # 30-33, CJK UNIFIED IDEOGRAPH-6A35 +U+6A36(2,3);U+6A36(2,3); # 60-80, CJK UNIFIED IDEOGRAPH-6A36 +U+6A38(2,3);U+6A38(2,3); # 60-87, CJK UNIFIED IDEOGRAPH-6A38 +U+6A39(2,3);U+6A39(2,3); # 28-89, CJK UNIFIED IDEOGRAPH-6A39 +U+6A3A(2,3);U+6A3A(2,3); # 19-82, CJK UNIFIED IDEOGRAPH-6A3A +U+6A3D(2,3);U+6A3D(2,3); # 35-14, CJK UNIFIED IDEOGRAPH-6A3D +U+6A44(2,3);U+6A44(2,3); # 60-77, CJK UNIFIED IDEOGRAPH-6A44 +U+6A47(2,3);U+6A47(2,3); # 60-82, CJK UNIFIED IDEOGRAPH-6A47 +U+6A48(2,3);U+6A48(2,3); # 60-86, CJK UNIFIED IDEOGRAPH-6A48 +U+6A4B(2,3);U+6A4B(2,3); # 22-22, CJK UNIFIED IDEOGRAPH-6A4B +U+6A58(2,3);U+6A58(2,3); # 21-44, CJK UNIFIED IDEOGRAPH-6A58 +U+6A59(2,3);U+6A59(2,3); # 60-84, CJK UNIFIED IDEOGRAPH-6A59 +U+6A5F(2,3);U+6A5F(2,3); # 21-01, CJK UNIFIED IDEOGRAPH-6A5F +U+6A61(2,3);U+6A61(2,3); # 38-43, CJK UNIFIED IDEOGRAPH-6A61 +U+6A62(2,3);U+6A62(2,3); # 60-83, CJK UNIFIED IDEOGRAPH-6A62 +U+6A66(2,3);U+6A66(2,3); # 60-85, CJK UNIFIED IDEOGRAPH-6A66 +U+6A72(2,3);U+6A72(2,3); # 60-79, CJK UNIFIED IDEOGRAPH-6A72 +U+6A78(2,3);U+6A78(2,3); # 60-81, CJK UNIFIED IDEOGRAPH-6A78 +U+6A7F(2,3);U+6A7F(2,3); # 19-64, CJK UNIFIED IDEOGRAPH-6A7F +U+6A80(2,3);U+6A80(2,3); # 35-41, CJK UNIFIED IDEOGRAPH-6A80 +U+6A84(2,3);U+6A84(2,3); # 60-92, CJK UNIFIED IDEOGRAPH-6A84 +U+6A8D(2,3);U+6A8D(2,3); # 60-90, CJK UNIFIED IDEOGRAPH-6A8D +U+6A8E(2,3);U+6A8E(2,3); # 24-73, CJK UNIFIED IDEOGRAPH-6A8E +U+6A90(2,3);U+6A90(2,3); # 60-89, CJK UNIFIED IDEOGRAPH-6A90 +U+6A97(2,3);U+6A97(2,3); # 61-01, CJK UNIFIED IDEOGRAPH-6A97 +U+6A9C(2,3);U+6A9C(2,3); # 59-56, CJK UNIFIED IDEOGRAPH-6A9C +U+6AA0(2,3);U+6AA0(2,3); # 60-91, CJK UNIFIED IDEOGRAPH-6AA0 +U+6AA2(2,3);U+6AA2(2,3); # 60-93, CJK UNIFIED IDEOGRAPH-6AA2 +U+6AA3(2,3);U+6AA3(2,3); # 60-94, CJK UNIFIED IDEOGRAPH-6AA3 +U+6AAA(2,3);U+6AAA(2,3); # 61-12, CJK UNIFIED IDEOGRAPH-6AAA +U+6AAC(2,3);U+6AAC(2,3); # 61-08, CJK UNIFIED IDEOGRAPH-6AAC +U+6AAE(2,3);U+6AAE(2,3); # 59-77, CJK UNIFIED IDEOGRAPH-6AAE +U+6AB3(2,3);U+6AB3(2,3); # 61-07, CJK UNIFIED IDEOGRAPH-6AB3 +U+6AB8(2,3);U+6AB8(2,3); # 61-06, CJK UNIFIED IDEOGRAPH-6AB8 +U+6ABB(2,3);U+6ABB(2,3); # 61-03, CJK UNIFIED IDEOGRAPH-6ABB +U+6AC1(2,3);U+6AC1(2,3); # 60-74, CJK UNIFIED IDEOGRAPH-6AC1 +U+6AC2(2,3);U+6AC2(2,3); # 61-05, CJK UNIFIED IDEOGRAPH-6AC2 +U+6AC3(2,3);U+6AC3(2,3); # 61-04, CJK UNIFIED IDEOGRAPH-6AC3 +U+6AD1(2,3);U+6AD1(2,3); # 61-10, CJK UNIFIED IDEOGRAPH-6AD1 +U+6AD3(2,3);U+6AD3(2,3); # 47-06, CJK UNIFIED IDEOGRAPH-6AD3 +U+6ADA(2,3);U+6ADA(2,3); # 61-13, CJK UNIFIED IDEOGRAPH-6ADA +U+6ADB(2,3);U+6ADB(2,3); # 22-91, CJK UNIFIED IDEOGRAPH-6ADB +U+6ADE(2,3);U+6ADE(2,3); # 61-09, CJK UNIFIED IDEOGRAPH-6ADE +U+6ADF(2,3);U+6ADF(2,3); # 61-11, CJK UNIFIED IDEOGRAPH-6ADF +U+6AE8(2,3);U+6AE8(2,3); # 40-07, CJK UNIFIED IDEOGRAPH-6AE8 +U+6AEA(2,3);U+6AEA(2,3); # 61-14, CJK UNIFIED IDEOGRAPH-6AEA +U+6AFA(2,3);U+6AFA(2,3); # 61-18, CJK UNIFIED IDEOGRAPH-6AFA +U+6AFB(2,3);U+6AFB(2,3); # 61-15, CJK UNIFIED IDEOGRAPH-6AFB +U+6B04(2,3);U+6B04(2,3); # 45-83, CJK UNIFIED IDEOGRAPH-6B04 +U+6B05(2,3);U+6B05(2,3); # 61-16, CJK UNIFIED IDEOGRAPH-6B05 +U+6B0A(2,3);U+6B0A(2,3); # 60-62, CJK UNIFIED IDEOGRAPH-6B0A +U+6B12(2,3);U+6B12(2,3); # 61-19, CJK UNIFIED IDEOGRAPH-6B12 +U+6B16(2,3);U+6B16(2,3); # 61-20, CJK UNIFIED IDEOGRAPH-6B16 +U+6B1D(2,3);U+6B1D(2,3); # 17-21, CJK UNIFIED IDEOGRAPH-6B1D +U+6B1F(2,3);U+6B1F(2,3); # 61-22, CJK UNIFIED IDEOGRAPH-6B1F +U+6B20(2,3);U+6B20(2,3); # 23-71, CJK UNIFIED IDEOGRAPH-6B20 +U+6B21(2,3);U+6B21(2,3); # 28-01, CJK UNIFIED IDEOGRAPH-6B21 +U+6B23(2,3);U+6B23(2,3); # 22-53, CJK UNIFIED IDEOGRAPH-6B23 +U+6B27(2,3);U+6B27(2,3); # 18-04, CJK UNIFIED IDEOGRAPH-6B27 +U+6B32(2,3);U+6B32(2,3); # 45-63, CJK UNIFIED IDEOGRAPH-6B32 +U+6B37(2,3);U+6B37(2,3); # 61-24, CJK UNIFIED IDEOGRAPH-6B37 +U+6B38(2,3);U+6B38(2,3); # 61-23, CJK UNIFIED IDEOGRAPH-6B38 +U+6B39(2,3);U+6B39(2,3); # 61-26, CJK UNIFIED IDEOGRAPH-6B39 +U+6B3A(2,3);U+6B3A(2,3); # 21-29, CJK UNIFIED IDEOGRAPH-6B3A +U+6B3D(2,3);U+6B3D(2,3); # 22-54, CJK UNIFIED IDEOGRAPH-6B3D +U+6B3E(2,3);U+6B3E(2,3); # 20-30, CJK UNIFIED IDEOGRAPH-6B3E +U+6B43(2,3);U+6B43(2,3); # 61-29, CJK UNIFIED IDEOGRAPH-6B43 +U+6B47(2,3);U+6B47(2,3); # 61-28, CJK UNIFIED IDEOGRAPH-6B47 +U+6B49(2,3);U+6B49(2,3); # 61-30, CJK UNIFIED IDEOGRAPH-6B49 +U+6B4C(2,3);U+6B4C(2,3); # 18-46, CJK UNIFIED IDEOGRAPH-6B4C +U+6B4E(2,3);U+6B4E(2,3); # 35-23, CJK UNIFIED IDEOGRAPH-6B4E +U+6B50(2,3);U+6B50(2,3); # 61-31, CJK UNIFIED IDEOGRAPH-6B50 +U+6B53(2,3);U+6B53(2,3); # 20-31, CJK UNIFIED IDEOGRAPH-6B53 +U+6B54(2,3);U+6B54(2,3); # 61-33, CJK UNIFIED IDEOGRAPH-6B54 +U+6B59(2,3);U+6B59(2,3); # 61-32, CJK UNIFIED IDEOGRAPH-6B59 +U+6B5B(2,3);U+6B5B(2,3); # 61-34, CJK UNIFIED IDEOGRAPH-6B5B +U+6B5F(2,3);U+6B5F(2,3); # 61-35, CJK UNIFIED IDEOGRAPH-6B5F +U+6B61(2,3);U+6B61(2,3); # 61-36, CJK UNIFIED IDEOGRAPH-6B61 +U+6B62(2,3);U+6B62(2,3); # 27-63, CJK UNIFIED IDEOGRAPH-6B62 +U+6B63(2,3);U+6B63(2,3); # 32-21, CJK UNIFIED IDEOGRAPH-6B63 +U+6B64(2,3);U+6B64(2,3); # 26-01, CJK UNIFIED IDEOGRAPH-6B64 +U+6B66(2,3);U+6B66(2,3); # 41-80, CJK UNIFIED IDEOGRAPH-6B66 +U+6B69(2,3);U+6B69(2,3); # 42-66, CJK UNIFIED IDEOGRAPH-6B69 +U+6B6A(2,3);U+6B6A(2,3); # 47-36, CJK UNIFIED IDEOGRAPH-6B6A +U+6B6F(2,3);U+6B6F(2,3); # 27-85, CJK UNIFIED IDEOGRAPH-6B6F +U+6B73(2,3);U+6B73(2,3); # 26-48, CJK UNIFIED IDEOGRAPH-6B73 +U+6B74(2,3);U+6B74(2,3); # 46-82, CJK UNIFIED IDEOGRAPH-6B74 +U+6B78(2,3);U+6B78(2,3); # 61-37, CJK UNIFIED IDEOGRAPH-6B78 +U+6B79(2,3);U+6B79(2,3); # 61-38, CJK UNIFIED IDEOGRAPH-6B79 +U+6B7B(2,3);U+6B7B(2,3); # 27-64, CJK UNIFIED IDEOGRAPH-6B7B +U+6B7F(2,3);U+6B7F(2,3); # 61-39, CJK UNIFIED IDEOGRAPH-6B7F +U+6B80(2,3);U+6B80(2,3); # 61-40, CJK UNIFIED IDEOGRAPH-6B80 +U+6B83(2,3);U+6B83(2,3); # 61-42, CJK UNIFIED IDEOGRAPH-6B83 +U+6B84(2,3);U+6B84(2,3); # 61-41, CJK UNIFIED IDEOGRAPH-6B84 +U+6B86(2,3);U+6B86(2,3); # 43-56, CJK UNIFIED IDEOGRAPH-6B86 +U+6B89(2,3);U+6B89(2,3); # 29-62, CJK UNIFIED IDEOGRAPH-6B89 +U+6B8A(2,3);U+6B8A(2,3); # 28-76, CJK UNIFIED IDEOGRAPH-6B8A +U+6B8B(2,3);U+6B8B(2,3); # 27-36, CJK UNIFIED IDEOGRAPH-6B8B +U+6B8D(2,3);U+6B8D(2,3); # 61-43, CJK UNIFIED IDEOGRAPH-6B8D +U+6B95(2,3);U+6B95(2,3); # 61-45, CJK UNIFIED IDEOGRAPH-6B95 +U+6B96(2,3);U+6B96(2,3); # 31-03, CJK UNIFIED IDEOGRAPH-6B96 +U+6B98(2,3);U+6B98(2,3); # 61-44, CJK UNIFIED IDEOGRAPH-6B98 +U+6B9E(2,3);U+6B9E(2,3); # 61-46, CJK UNIFIED IDEOGRAPH-6B9E +U+6BA4(2,3);U+6BA4(2,3); # 61-47, CJK UNIFIED IDEOGRAPH-6BA4 +U+6BAA(2,3);U+6BAA(2,3); # 61-48, CJK UNIFIED IDEOGRAPH-6BAA +U+6BAB(2,3);U+6BAB(2,3); # 61-49, CJK UNIFIED IDEOGRAPH-6BAB +U+6BAF(2,3);U+6BAF(2,3); # 61-50, CJK UNIFIED IDEOGRAPH-6BAF +U+6BB1(2,3);U+6BB1(2,3); # 61-52, CJK UNIFIED IDEOGRAPH-6BB1 +U+6BB2(2,3);U+6BB2(2,3); # 61-51, CJK UNIFIED IDEOGRAPH-6BB2 +U+6BB3(2,3);U+6BB3(2,3); # 61-53, CJK UNIFIED IDEOGRAPH-6BB3 +U+6BB4(2,3);U+6BB4(2,3); # 18-05, CJK UNIFIED IDEOGRAPH-6BB4 +U+6BB5(2,3);U+6BB5(2,3); # 35-42, CJK UNIFIED IDEOGRAPH-6BB5 +U+6BB7(2,3);U+6BB7(2,3); # 61-54, CJK UNIFIED IDEOGRAPH-6BB7 +U+6BBA(2,3);U+6BBA(2,3); # 27-06, CJK UNIFIED IDEOGRAPH-6BBA +U+6BBB(2,3);U+6BBB(2,3); # 19-44, CJK UNIFIED IDEOGRAPH-6BBB +U+6BBC(2,3);U+6BBC(2,3); # 61-55, CJK UNIFIED IDEOGRAPH-6BBC +U+6BBF(2,3);U+6BBF(2,3); # 37-34, CJK UNIFIED IDEOGRAPH-6BBF +U+6BC0(2,3);U+6BC0(2,3); # 52-44, CJK UNIFIED IDEOGRAPH-6BC0 +U+6BC5(2,3);U+6BC5(2,3); # 21-03, CJK UNIFIED IDEOGRAPH-6BC5 +U+6BC6(2,3);U+6BC6(2,3); # 61-56, CJK UNIFIED IDEOGRAPH-6BC6 +U+6BCB(2,3);U+6BCB(2,3); # 61-57, CJK UNIFIED IDEOGRAPH-6BCB +U+6BCD(2,3);U+6BCD(2,3); # 42-76, CJK UNIFIED IDEOGRAPH-6BCD +U+6BCE(2,3);U+6BCE(2,3); # 43-72, CJK UNIFIED IDEOGRAPH-6BCE +U+6BD2(2,3);U+6BD2(2,3); # 38-39, CJK UNIFIED IDEOGRAPH-6BD2 +U+6BD3(2,3);U+6BD3(2,3); # 61-58, CJK UNIFIED IDEOGRAPH-6BD3 +U+6BD4(2,3);U+6BD4(2,3); # 40-70, CJK UNIFIED IDEOGRAPH-6BD4 +U+6BD8(2,3);U+6BD8(2,3); # 40-91, CJK UNIFIED IDEOGRAPH-6BD8 +U+6BDB(2,3);U+6BDB(2,3); # 44-51, CJK UNIFIED IDEOGRAPH-6BDB +U+6BDF(2,3);U+6BDF(2,3); # 61-59, CJK UNIFIED IDEOGRAPH-6BDF +U+6BEB(2,3);U+6BEB(2,3); # 61-61, CJK UNIFIED IDEOGRAPH-6BEB +U+6BEC(2,3);U+6BEC(2,3); # 61-60, CJK UNIFIED IDEOGRAPH-6BEC +U+6BEF(2,3);U+6BEF(2,3); # 61-63, CJK UNIFIED IDEOGRAPH-6BEF +U+6BF3(2,3);U+6BF3(2,3); # 61-62, CJK UNIFIED IDEOGRAPH-6BF3 +U+6C08(2,3);U+6C08(2,3); # 61-65, CJK UNIFIED IDEOGRAPH-6C08 +U+6C0F(2,3);U+6C0F(2,3); # 27-65, CJK UNIFIED IDEOGRAPH-6C0F +U+6C11(2,3);U+6C11(2,3); # 44-17, CJK UNIFIED IDEOGRAPH-6C11 +U+6C13(2,3);U+6C13(2,3); # 61-66, CJK UNIFIED IDEOGRAPH-6C13 +U+6C14(2,3);U+6C14(2,3); # 61-67, CJK UNIFIED IDEOGRAPH-6C14 +U+6C17(2,3);U+6C17(2,3); # 21-04, CJK UNIFIED IDEOGRAPH-6C17 +U+6C1B(2,3);U+6C1B(2,3); # 61-68, CJK UNIFIED IDEOGRAPH-6C1B +U+6C23(2,3);U+6C23(2,3); # 61-70, CJK UNIFIED IDEOGRAPH-6C23 +U+6C24(2,3);U+6C24(2,3); # 61-69, CJK UNIFIED IDEOGRAPH-6C24 +U+6C34(2,3);U+6C34(2,3); # 31-69, CJK UNIFIED IDEOGRAPH-6C34 +U+6C37(2,3);U+6C37(2,3); # 41-25, CJK UNIFIED IDEOGRAPH-6C37 +U+6C38(2,3);U+6C38(2,3); # 17-42, CJK UNIFIED IDEOGRAPH-6C38 +U+6C3E(2,3);U+6C3E(2,3); # 40-37, CJK UNIFIED IDEOGRAPH-6C3E +U+6C40(2,3);U+6C40(2,3); # 36-85, CJK UNIFIED IDEOGRAPH-6C40 +U+6C41(2,3);U+6C41(2,3); # 29-33, CJK UNIFIED IDEOGRAPH-6C41 +U+6C42(2,3);U+6C42(2,3); # 21-65, CJK UNIFIED IDEOGRAPH-6C42 +U+6C4E(2,3);U+6C4E(2,3); # 40-38, CJK UNIFIED IDEOGRAPH-6C4E +U+6C50(2,3);U+6C50(2,3); # 28-14, CJK UNIFIED IDEOGRAPH-6C50 +U+6C55(2,3);U+6C55(2,3); # 61-72, CJK UNIFIED IDEOGRAPH-6C55 +U+6C57(2,3);U+6C57(2,3); # 20-32, CJK UNIFIED IDEOGRAPH-6C57 +U+6C5A(2,3);U+6C5A(2,3); # 17-88, CJK UNIFIED IDEOGRAPH-6C5A +U+6C5D(2,3);U+6C5D(2,3); # 38-82, CJK UNIFIED IDEOGRAPH-6C5D +U+6C5E(2,3);U+6C5E(2,3); # 61-71, CJK UNIFIED IDEOGRAPH-6C5E +U+6C5F(2,3);U+6C5F(2,3); # 25-30, CJK UNIFIED IDEOGRAPH-6C5F +U+6C60(2,3);U+6C60(2,3); # 35-51, CJK UNIFIED IDEOGRAPH-6C60 +U+6C62(2,3);U+6C62(2,3); # 61-73, CJK UNIFIED IDEOGRAPH-6C62 +U+6C68(2,3);U+6C68(2,3); # 61-81, CJK UNIFIED IDEOGRAPH-6C68 +U+6C6A(2,3);U+6C6A(2,3); # 61-74, CJK UNIFIED IDEOGRAPH-6C6A +U+6C70(2,3);U+6C70(2,3); # 34-33, CJK UNIFIED IDEOGRAPH-6C70 +U+6C72(2,3);U+6C72(2,3); # 21-66, CJK UNIFIED IDEOGRAPH-6C72 +U+6C73(2,3);U+6C73(2,3); # 61-82, CJK UNIFIED IDEOGRAPH-6C73 +U+6C7A(2,3);U+6C7A(2,3); # 23-72, CJK UNIFIED IDEOGRAPH-6C7A +U+6C7D(2,3);U+6C7D(2,3); # 21-05, CJK UNIFIED IDEOGRAPH-6C7D +U+6C7E(2,3);U+6C7E(2,3); # 61-80, CJK UNIFIED IDEOGRAPH-6C7E +U+6C81(2,3);U+6C81(2,3); # 61-78, CJK UNIFIED IDEOGRAPH-6C81 +U+6C82(2,3);U+6C82(2,3); # 61-75, CJK UNIFIED IDEOGRAPH-6C82 +U+6C83(2,3);U+6C83(2,3); # 45-64, CJK UNIFIED IDEOGRAPH-6C83 +U+6C88(2,3);U+6C88(2,3); # 36-32, CJK UNIFIED IDEOGRAPH-6C88 +U+6C8C(2,3);U+6C8C(2,3); # 38-57, CJK UNIFIED IDEOGRAPH-6C8C +U+6C8D(2,3);U+6C8D(2,3); # 61-76, CJK UNIFIED IDEOGRAPH-6C8D +U+6C90(2,3);U+6C90(2,3); # 61-84, CJK UNIFIED IDEOGRAPH-6C90 +U+6C92(2,3);U+6C92(2,3); # 61-83, CJK UNIFIED IDEOGRAPH-6C92 +U+6C93(2,3);U+6C93(2,3); # 23-03, CJK UNIFIED IDEOGRAPH-6C93 +U+6C96(2,3);U+6C96(2,3); # 18-13, CJK UNIFIED IDEOGRAPH-6C96 +U+6C99(2,3);U+6C99(2,3); # 26-27, CJK UNIFIED IDEOGRAPH-6C99 +U+6C9A(2,3);U+6C9A(2,3); # 61-77, CJK UNIFIED IDEOGRAPH-6C9A +U+6C9B(2,3);U+6C9B(2,3); # 61-79, CJK UNIFIED IDEOGRAPH-6C9B +U+6CA1(2,3);U+6CA1(2,3); # 43-55, CJK UNIFIED IDEOGRAPH-6CA1 +U+6CA2(2,3);U+6CA2(2,3); # 34-84, CJK UNIFIED IDEOGRAPH-6CA2 +U+6CAB(2,3);U+6CAB(2,3); # 43-87, CJK UNIFIED IDEOGRAPH-6CAB +U+6CAE(2,3);U+6CAE(2,3); # 61-92, CJK UNIFIED IDEOGRAPH-6CAE +U+6CB1(2,3);U+6CB1(2,3); # 61-93, CJK UNIFIED IDEOGRAPH-6CB1 +U+6CB3(2,3);U+6CB3(2,3); # 18-47, CJK UNIFIED IDEOGRAPH-6CB3 +U+6CB8(2,3);U+6CB8(2,3); # 42-08, CJK UNIFIED IDEOGRAPH-6CB8 +U+6CB9(2,3);U+6CB9(2,3); # 44-93, CJK UNIFIED IDEOGRAPH-6CB9 +U+6CBA(2,3);U+6CBA(2,3); # 62-01, CJK UNIFIED IDEOGRAPH-6CBA +U+6CBB(2,3);U+6CBB(2,3); # 28-03, CJK UNIFIED IDEOGRAPH-6CBB +U+6CBC(2,3);U+6CBC(2,3); # 30-34, CJK UNIFIED IDEOGRAPH-6CBC +U+6CBD(2,3);U+6CBD(2,3); # 61-88, CJK UNIFIED IDEOGRAPH-6CBD +U+6CBE(2,3);U+6CBE(2,3); # 61-94, CJK UNIFIED IDEOGRAPH-6CBE +U+6CBF(2,3);U+6CBF(2,3); # 17-72, CJK UNIFIED IDEOGRAPH-6CBF +U+6CC1(2,3);U+6CC1(2,3); # 22-23, CJK UNIFIED IDEOGRAPH-6CC1 +U+6CC4(2,3);U+6CC4(2,3); # 61-85, CJK UNIFIED IDEOGRAPH-6CC4 +U+6CC5(2,3);U+6CC5(2,3); # 61-90, CJK UNIFIED IDEOGRAPH-6CC5 +U+6CC9(2,3);U+6CC9(2,3); # 32-84, CJK UNIFIED IDEOGRAPH-6CC9 +U+6CCA(2,3);U+6CCA(2,3); # 39-81, CJK UNIFIED IDEOGRAPH-6CCA +U+6CCC(2,3);U+6CCC(2,3); # 40-71, CJK UNIFIED IDEOGRAPH-6CCC +U+6CD3(2,3);U+6CD3(2,3); # 61-87, CJK UNIFIED IDEOGRAPH-6CD3 +U+6CD5(2,3);U+6CD5(2,3); # 43-01, CJK UNIFIED IDEOGRAPH-6CD5 +U+6CD7(2,3);U+6CD7(2,3); # 61-89, CJK UNIFIED IDEOGRAPH-6CD7 +U+6CD9(2,3);U+6CD9(2,3); # 62-04, CJK UNIFIED IDEOGRAPH-6CD9 +U+6CDB(2,3);U+6CDB(2,3); # 62-02, CJK UNIFIED IDEOGRAPH-6CDB +U+6CDD(2,3);U+6CDD(2,3); # 61-91, CJK UNIFIED IDEOGRAPH-6CDD +U+6CE1(2,3);U+6CE1(2,3); # 43-02, CJK UNIFIED IDEOGRAPH-6CE1 +U+6CE2(2,3);U+6CE2(2,3); # 39-40, CJK UNIFIED IDEOGRAPH-6CE2 +U+6CE3(2,3);U+6CE3(2,3); # 21-67, CJK UNIFIED IDEOGRAPH-6CE3 +U+6CE5(2,3);U+6CE5(2,3); # 37-05, CJK UNIFIED IDEOGRAPH-6CE5 +U+6CE8(2,3);U+6CE8(2,3); # 35-77, CJK UNIFIED IDEOGRAPH-6CE8 +U+6CEA(2,3);U+6CEA(2,3); # 62-05, CJK UNIFIED IDEOGRAPH-6CEA +U+6CEF(2,3);U+6CEF(2,3); # 62-03, CJK UNIFIED IDEOGRAPH-6CEF +U+6CF0(2,3);U+6CF0(2,3); # 34-57, CJK UNIFIED IDEOGRAPH-6CF0 +U+6CF1(2,3);U+6CF1(2,3); # 61-86, CJK UNIFIED IDEOGRAPH-6CF1 +U+6CF3(2,3);U+6CF3(2,3); # 17-43, CJK UNIFIED IDEOGRAPH-6CF3 +U+6D0B(2,3);U+6D0B(2,3); # 45-46, CJK UNIFIED IDEOGRAPH-6D0B +U+6D0C(2,3);U+6D0C(2,3); # 62-16, CJK UNIFIED IDEOGRAPH-6D0C +U+6D12(2,3);U+6D12(2,3); # 62-15, CJK UNIFIED IDEOGRAPH-6D12 +U+6D17(2,3);U+6D17(2,3); # 32-86, CJK UNIFIED IDEOGRAPH-6D17 +U+6D19(2,3);U+6D19(2,3); # 62-12, CJK UNIFIED IDEOGRAPH-6D19 +U+6D1B(2,3);U+6D1B(2,3); # 45-76, CJK UNIFIED IDEOGRAPH-6D1B +U+6D1E(2,3);U+6D1E(2,3); # 38-22, CJK UNIFIED IDEOGRAPH-6D1E +U+6D1F(2,3);U+6D1F(2,3); # 62-06, CJK UNIFIED IDEOGRAPH-6D1F +U+6D25(2,3);U+6D25(2,3); # 36-37, CJK UNIFIED IDEOGRAPH-6D25 +U+6D29(2,3);U+6D29(2,3); # 17-44, CJK UNIFIED IDEOGRAPH-6D29 +U+6D2A(2,3);U+6D2A(2,3); # 25-31, CJK UNIFIED IDEOGRAPH-6D2A +U+6D2B(2,3);U+6D2B(2,3); # 62-09, CJK UNIFIED IDEOGRAPH-6D2B +U+6D32(2,3);U+6D32(2,3); # 29-07, CJK UNIFIED IDEOGRAPH-6D32 +U+6D33(2,3);U+6D33(2,3); # 62-14, CJK UNIFIED IDEOGRAPH-6D33 +U+6D35(2,3);U+6D35(2,3); # 62-13, CJK UNIFIED IDEOGRAPH-6D35 +U+6D36(2,3);U+6D36(2,3); # 62-08, CJK UNIFIED IDEOGRAPH-6D36 +U+6D38(2,3);U+6D38(2,3); # 62-11, CJK UNIFIED IDEOGRAPH-6D38 +U+6D3B(2,3);U+6D3B(2,3); # 19-72, CJK UNIFIED IDEOGRAPH-6D3B +U+6D3D(2,3);U+6D3D(2,3); # 62-10, CJK UNIFIED IDEOGRAPH-6D3D +U+6D3E(2,3);U+6D3E(2,3); # 39-41, CJK UNIFIED IDEOGRAPH-6D3E +U+6D41(2,3);U+6D41(2,3); # 46-14, CJK UNIFIED IDEOGRAPH-6D41 +U+6D44(2,3);U+6D44(2,3); # 30-84, CJK UNIFIED IDEOGRAPH-6D44 +U+6D45(2,3);U+6D45(2,3); # 32-85, CJK UNIFIED IDEOGRAPH-6D45 +U+6D59(2,3);U+6D59(2,3); # 62-22, CJK UNIFIED IDEOGRAPH-6D59 +U+6D5A(2,3);U+6D5A(2,3); # 62-20, CJK UNIFIED IDEOGRAPH-6D5A +U+6D5C(2,3);U+6D5C(2,3); # 41-45, CJK UNIFIED IDEOGRAPH-6D5C +U+6D63(2,3);U+6D63(2,3); # 62-17, CJK UNIFIED IDEOGRAPH-6D63 +U+6D64(2,3);U+6D64(2,3); # 62-19, CJK UNIFIED IDEOGRAPH-6D64 +U+6D66(2,3);U+6D66(2,3); # 17-26, CJK UNIFIED IDEOGRAPH-6D66 +U+6D69(2,3);U+6D69(2,3); # 25-32, CJK UNIFIED IDEOGRAPH-6D69 +U+6D6A(2,3);U+6D6A(2,3); # 47-18, CJK UNIFIED IDEOGRAPH-6D6A +U+6D6C(2,3);U+6D6C(2,3); # 19-29, CJK UNIFIED IDEOGRAPH-6D6C +U+6D6E(2,3);U+6D6E(2,3); # 41-66, CJK UNIFIED IDEOGRAPH-6D6E +U+6D74(2,3);U+6D74(2,3); # 45-65, CJK UNIFIED IDEOGRAPH-6D74 +U+6D77(2,3);U+6D77(2,3); # 19-04, CJK UNIFIED IDEOGRAPH-6D77 +U+6D78(2,3);U+6D78(2,3); # 31-27, CJK UNIFIED IDEOGRAPH-6D78 +U+6D79(2,3);U+6D79(2,3); # 62-21, CJK UNIFIED IDEOGRAPH-6D79 +U+6D85(2,3);U+6D85(2,3); # 62-26, CJK UNIFIED IDEOGRAPH-6D85 +U+6D88(2,3);U+6D88(2,3); # 30-35, CJK UNIFIED IDEOGRAPH-6D88 +U+6D8C(2,3);U+6D8C(2,3); # 45-16, CJK UNIFIED IDEOGRAPH-6D8C +U+6D8E(2,3);U+6D8E(2,3); # 62-23, CJK UNIFIED IDEOGRAPH-6D8E +U+6D93(2,3);U+6D93(2,3); # 62-18, CJK UNIFIED IDEOGRAPH-6D93 +U+6D95(2,3);U+6D95(2,3); # 62-24, CJK UNIFIED IDEOGRAPH-6D95 +U+6D99(2,3);U+6D99(2,3); # 46-62, CJK UNIFIED IDEOGRAPH-6D99 +U+6D9B(2,3);U+6D9B(2,3); # 37-83, CJK UNIFIED IDEOGRAPH-6D9B +U+6D9C(2,3);U+6D9C(2,3); # 38-34, CJK UNIFIED IDEOGRAPH-6D9C +U+6DAF(2,3);U+6DAF(2,3); # 19-22, CJK UNIFIED IDEOGRAPH-6DAF +U+6DB2(2,3);U+6DB2(2,3); # 17-53, CJK UNIFIED IDEOGRAPH-6DB2 +U+6DB5(2,3);U+6DB5(2,3); # 62-30, CJK UNIFIED IDEOGRAPH-6DB5 +U+6DB8(2,3);U+6DB8(2,3); # 62-33, CJK UNIFIED IDEOGRAPH-6DB8 +U+6DBC(2,3);U+6DBC(2,3); # 46-35, CJK UNIFIED IDEOGRAPH-6DBC +U+6DC0(2,3);U+6DC0(2,3); # 45-68, CJK UNIFIED IDEOGRAPH-6DC0 +U+6DC5(2,3);U+6DC5(2,3); # 62-40, CJK UNIFIED IDEOGRAPH-6DC5 +U+6DC6(2,3);U+6DC6(2,3); # 62-34, CJK UNIFIED IDEOGRAPH-6DC6 +U+6DC7(2,3);U+6DC7(2,3); # 62-31, CJK UNIFIED IDEOGRAPH-6DC7 +U+6DCB(2,3);U+6DCB(2,3); # 46-52, CJK UNIFIED IDEOGRAPH-6DCB +U+6DCC(2,3);U+6DCC(2,3); # 62-37, CJK UNIFIED IDEOGRAPH-6DCC +U+6DD1(2,3);U+6DD1(2,3); # 29-42, CJK UNIFIED IDEOGRAPH-6DD1 +U+6DD2(2,3);U+6DD2(2,3); # 62-39, CJK UNIFIED IDEOGRAPH-6DD2 +U+6DD5(2,3);U+6DD5(2,3); # 62-44, CJK UNIFIED IDEOGRAPH-6DD5 +U+6DD8(2,3);U+6DD8(2,3); # 37-81, CJK UNIFIED IDEOGRAPH-6DD8 +U+6DD9(2,3);U+6DD9(2,3); # 62-42, CJK UNIFIED IDEOGRAPH-6DD9 +U+6DDE(2,3);U+6DDE(2,3); # 62-36, CJK UNIFIED IDEOGRAPH-6DDE +U+6DE1(2,3);U+6DE1(2,3); # 35-24, CJK UNIFIED IDEOGRAPH-6DE1 +U+6DE4(2,3);U+6DE4(2,3); # 62-43, CJK UNIFIED IDEOGRAPH-6DE4 +U+6DE6(2,3);U+6DE6(2,3); # 62-32, CJK UNIFIED IDEOGRAPH-6DE6 +U+6DE8(2,3);U+6DE8(2,3); # 62-38, CJK UNIFIED IDEOGRAPH-6DE8 +U+6DEA(2,3);U+6DEA(2,3); # 62-45, CJK UNIFIED IDEOGRAPH-6DEA +U+6DEB(2,3);U+6DEB(2,3); # 16-92, CJK UNIFIED IDEOGRAPH-6DEB +U+6DEC(2,3);U+6DEC(2,3); # 62-35, CJK UNIFIED IDEOGRAPH-6DEC +U+6DEE(2,3);U+6DEE(2,3); # 62-46, CJK UNIFIED IDEOGRAPH-6DEE +U+6DF1(2,3);U+6DF1(2,3); # 31-28, CJK UNIFIED IDEOGRAPH-6DF1 +U+6DF3(2,3);U+6DF3(2,3); # 29-63, CJK UNIFIED IDEOGRAPH-6DF3 +U+6DF5(2,3);U+6DF5(2,3); # 42-05, CJK UNIFIED IDEOGRAPH-6DF5 +U+6DF7(2,3);U+6DF7(2,3); # 26-14, CJK UNIFIED IDEOGRAPH-6DF7 +U+6DF9(2,3);U+6DF9(2,3); # 62-27, CJK UNIFIED IDEOGRAPH-6DF9 +U+6DFA(2,3);U+6DFA(2,3); # 62-41, CJK UNIFIED IDEOGRAPH-6DFA +U+6DFB(2,3);U+6DFB(2,3); # 37-26, CJK UNIFIED IDEOGRAPH-6DFB +U+6E05(2,3);U+6E05(2,3); # 32-22, CJK UNIFIED IDEOGRAPH-6E05 +U+6E07(2,3);U+6E07(2,3); # 19-73, CJK UNIFIED IDEOGRAPH-6E07 +U+6E08(2,3);U+6E08(2,3); # 26-49, CJK UNIFIED IDEOGRAPH-6E08 +U+6E09(2,3);U+6E09(2,3); # 30-36, CJK UNIFIED IDEOGRAPH-6E09 +U+6E0A(2,3);U+6E0A(2,3); # 62-29, CJK UNIFIED IDEOGRAPH-6E0A +U+6E0B(2,3);U+6E0B(2,3); # 29-34, CJK UNIFIED IDEOGRAPH-6E0B +U+6E13(2,3);U+6E13(2,3); # 23-44, CJK UNIFIED IDEOGRAPH-6E13 +U+6E15(2,3);U+6E15(2,3); # 62-28, CJK UNIFIED IDEOGRAPH-6E15 +U+6E19(2,3);U+6E19(2,3); # 62-50, CJK UNIFIED IDEOGRAPH-6E19 +U+6E1A(2,3);U+6E1A(2,3); # 29-77, CJK UNIFIED IDEOGRAPH-6E1A +U+6E1B(2,3);U+6E1B(2,3); # 24-26, CJK UNIFIED IDEOGRAPH-6E1B +U+6E1D(2,3);U+6E1D(2,3); # 62-65, CJK UNIFIED IDEOGRAPH-6E1D +U+6E1F(2,3);U+6E1F(2,3); # 62-59, CJK UNIFIED IDEOGRAPH-6E1F +U+6E20(2,3);U+6E20(2,3); # 21-84, CJK UNIFIED IDEOGRAPH-6E20 +U+6E21(2,3);U+6E21(2,3); # 37-47, CJK UNIFIED IDEOGRAPH-6E21 +U+6E23(2,3);U+6E23(2,3); # 62-54, CJK UNIFIED IDEOGRAPH-6E23 +U+6E24(2,3);U+6E24(2,3); # 62-63, CJK UNIFIED IDEOGRAPH-6E24 +U+6E25(2,3);U+6E25(2,3); # 16-15, CJK UNIFIED IDEOGRAPH-6E25 +U+6E26(2,3);U+6E26(2,3); # 17-18, CJK UNIFIED IDEOGRAPH-6E26 +U+6E29(2,3);U+6E29(2,3); # 18-25, CJK UNIFIED IDEOGRAPH-6E29 +U+6E2B(2,3);U+6E2B(2,3); # 62-56, CJK UNIFIED IDEOGRAPH-6E2B +U+6E2C(2,3);U+6E2C(2,3); # 34-12, CJK UNIFIED IDEOGRAPH-6E2C +U+6E2D(2,3);U+6E2D(2,3); # 62-47, CJK UNIFIED IDEOGRAPH-6E2D +U+6E2E(2,3);U+6E2E(2,3); # 62-49, CJK UNIFIED IDEOGRAPH-6E2E +U+6E2F(2,3);U+6E2F(2,3); # 25-33, CJK UNIFIED IDEOGRAPH-6E2F +U+6E38(2,3);U+6E38(2,3); # 62-66, CJK UNIFIED IDEOGRAPH-6E38 +U+6E3A(2,3);U+6E3A(2,3); # 62-61, CJK UNIFIED IDEOGRAPH-6E3A +U+6E3E(2,3);U+6E3E(2,3); # 62-53, CJK UNIFIED IDEOGRAPH-6E3E +U+6E43(2,3);U+6E43(2,3); # 62-60, CJK UNIFIED IDEOGRAPH-6E43 +U+6E4A(2,3);U+6E4A(2,3); # 44-11, CJK UNIFIED IDEOGRAPH-6E4A +U+6E4D(2,3);U+6E4D(2,3); # 62-58, CJK UNIFIED IDEOGRAPH-6E4D +U+6E4E(2,3);U+6E4E(2,3); # 62-62, CJK UNIFIED IDEOGRAPH-6E4E +U+6E56(2,3);U+6E56(2,3); # 24-48, CJK UNIFIED IDEOGRAPH-6E56 +U+6E58(2,3);U+6E58(2,3); # 30-37, CJK UNIFIED IDEOGRAPH-6E58 +U+6E5B(2,3);U+6E5B(2,3); # 35-25, CJK UNIFIED IDEOGRAPH-6E5B +U+6E5F(2,3);U+6E5F(2,3); # 62-52, CJK UNIFIED IDEOGRAPH-6E5F +U+6E67(2,3);U+6E67(2,3); # 45-15, CJK UNIFIED IDEOGRAPH-6E67 +U+6E6B(2,3);U+6E6B(2,3); # 62-55, CJK UNIFIED IDEOGRAPH-6E6B +U+6E6E(2,3);U+6E6E(2,3); # 62-48, CJK UNIFIED IDEOGRAPH-6E6E +U+6E6F(2,3);U+6E6F(2,3); # 37-82, CJK UNIFIED IDEOGRAPH-6E6F +U+6E72(2,3);U+6E72(2,3); # 62-51, CJK UNIFIED IDEOGRAPH-6E72 +U+6E76(2,3);U+6E76(2,3); # 62-57, CJK UNIFIED IDEOGRAPH-6E76 +U+6E7E(2,3);U+6E7E(2,3); # 47-49, CJK UNIFIED IDEOGRAPH-6E7E +U+6E7F(2,3);U+6E7F(2,3); # 28-30, CJK UNIFIED IDEOGRAPH-6E7F +U+6E80(2,3);U+6E80(2,3); # 43-94, CJK UNIFIED IDEOGRAPH-6E80 +U+6E82(2,3);U+6E82(2,3); # 62-67, CJK UNIFIED IDEOGRAPH-6E82 +U+6E8C(2,3);U+6E8C(2,3); # 40-14, CJK UNIFIED IDEOGRAPH-6E8C +U+6E8F(2,3);U+6E8F(2,3); # 62-79, CJK UNIFIED IDEOGRAPH-6E8F +U+6E90(2,3);U+6E90(2,3); # 24-27, CJK UNIFIED IDEOGRAPH-6E90 +U+6E96(2,3);U+6E96(2,3); # 29-64, CJK UNIFIED IDEOGRAPH-6E96 +U+6E98(2,3);U+6E98(2,3); # 62-69, CJK UNIFIED IDEOGRAPH-6E98 +U+6E9C(2,3);U+6E9C(2,3); # 46-15, CJK UNIFIED IDEOGRAPH-6E9C +U+6E9D(2,3);U+6E9D(2,3); # 25-34, CJK UNIFIED IDEOGRAPH-6E9D +U+6E9F(2,3);U+6E9F(2,3); # 62-82, CJK UNIFIED IDEOGRAPH-6E9F +U+6EA2(2,3);U+6EA2(2,3); # 16-78, CJK UNIFIED IDEOGRAPH-6EA2 +U+6EA5(2,3);U+6EA5(2,3); # 62-80, CJK UNIFIED IDEOGRAPH-6EA5 +U+6EAA(2,3);U+6EAA(2,3); # 62-68, CJK UNIFIED IDEOGRAPH-6EAA +U+6EAF(2,3);U+6EAF(2,3); # 62-74, CJK UNIFIED IDEOGRAPH-6EAF +U+6EB2(2,3);U+6EB2(2,3); # 62-76, CJK UNIFIED IDEOGRAPH-6EB2 +U+6EB6(2,3);U+6EB6(2,3); # 45-47, CJK UNIFIED IDEOGRAPH-6EB6 +U+6EB7(2,3);U+6EB7(2,3); # 62-71, CJK UNIFIED IDEOGRAPH-6EB7 +U+6EBA(2,3);U+6EBA(2,3); # 37-14, CJK UNIFIED IDEOGRAPH-6EBA +U+6EBD(2,3);U+6EBD(2,3); # 62-73, CJK UNIFIED IDEOGRAPH-6EBD +U+6EC2(2,3);U+6EC2(2,3); # 62-81, CJK UNIFIED IDEOGRAPH-6EC2 +U+6EC4(2,3);U+6EC4(2,3); # 62-75, CJK UNIFIED IDEOGRAPH-6EC4 +U+6EC5(2,3);U+6EC5(2,3); # 44-39, CJK UNIFIED IDEOGRAPH-6EC5 +U+6EC9(2,3);U+6EC9(2,3); # 62-70, CJK UNIFIED IDEOGRAPH-6EC9 +U+6ECB(2,3);U+6ECB(2,3); # 28-02, CJK UNIFIED IDEOGRAPH-6ECB +U+6ECC(2,3);U+6ECC(2,3); # 62-94, CJK UNIFIED IDEOGRAPH-6ECC +U+6ED1(2,3);U+6ED1(2,3); # 19-74, CJK UNIFIED IDEOGRAPH-6ED1 +U+6ED3(2,3);U+6ED3(2,3); # 62-72, CJK UNIFIED IDEOGRAPH-6ED3 +U+6ED4(2,3);U+6ED4(2,3); # 62-77, CJK UNIFIED IDEOGRAPH-6ED4 +U+6ED5(2,3);U+6ED5(2,3); # 62-78, CJK UNIFIED IDEOGRAPH-6ED5 +U+6EDD(2,3);U+6EDD(2,3); # 34-76, CJK UNIFIED IDEOGRAPH-6EDD +U+6EDE(2,3);U+6EDE(2,3); # 34-58, CJK UNIFIED IDEOGRAPH-6EDE +U+6EEC(2,3);U+6EEC(2,3); # 62-86, CJK UNIFIED IDEOGRAPH-6EEC +U+6EEF(2,3);U+6EEF(2,3); # 62-92, CJK UNIFIED IDEOGRAPH-6EEF +U+6EF2(2,3);U+6EF2(2,3); # 62-90, CJK UNIFIED IDEOGRAPH-6EF2 +U+6EF4(2,3);U+6EF4(2,3); # 37-09, CJK UNIFIED IDEOGRAPH-6EF4 +U+6EF7(2,3);U+6EF7(2,3); # 63-03, CJK UNIFIED IDEOGRAPH-6EF7 +U+6EF8(2,3);U+6EF8(2,3); # 62-87, CJK UNIFIED IDEOGRAPH-6EF8 +U+6EFE(2,3);U+6EFE(2,3); # 62-88, CJK UNIFIED IDEOGRAPH-6EFE +U+6EFF(2,3);U+6EFF(2,3); # 62-64, CJK UNIFIED IDEOGRAPH-6EFF +U+6F01(2,3);U+6F01(2,3); # 21-89, CJK UNIFIED IDEOGRAPH-6F01 +U+6F02(2,3);U+6F02(2,3); # 41-26, CJK UNIFIED IDEOGRAPH-6F02 +U+6F06(2,3);U+6F06(2,3); # 28-31, CJK UNIFIED IDEOGRAPH-6F06 +U+6F09(2,3);U+6F09(2,3); # 25-87, CJK UNIFIED IDEOGRAPH-6F09 +U+6F0F(2,3);U+6F0F(2,3); # 47-19, CJK UNIFIED IDEOGRAPH-6F0F +U+6F11(2,3);U+6F11(2,3); # 62-84, CJK UNIFIED IDEOGRAPH-6F11 +U+6F13(2,3);U+6F13(2,3); # 63-02, CJK UNIFIED IDEOGRAPH-6F13 +U+6F14(2,3);U+6F14(2,3); # 17-73, CJK UNIFIED IDEOGRAPH-6F14 +U+6F15(2,3);U+6F15(2,3); # 33-70, CJK UNIFIED IDEOGRAPH-6F15 +U+6F20(2,3);U+6F20(2,3); # 39-89, CJK UNIFIED IDEOGRAPH-6F20 +U+6F22(2,3);U+6F22(2,3); # 20-33, CJK UNIFIED IDEOGRAPH-6F22 +U+6F23(2,3);U+6F23(2,3); # 46-90, CJK UNIFIED IDEOGRAPH-6F23 +U+6F2B(2,3);U+6F2B(2,3); # 44-01, CJK UNIFIED IDEOGRAPH-6F2B +U+6F2C(2,3);U+6F2C(2,3); # 36-50, CJK UNIFIED IDEOGRAPH-6F2C +U+6F31(2,3);U+6F31(2,3); # 62-91, CJK UNIFIED IDEOGRAPH-6F31 +U+6F32(2,3);U+6F32(2,3); # 62-93, CJK UNIFIED IDEOGRAPH-6F32 +U+6F38(2,3);U+6F38(2,3); # 33-18, CJK UNIFIED IDEOGRAPH-6F38 +U+6F3E(2,3);U+6F3E(2,3); # 63-01, CJK UNIFIED IDEOGRAPH-6F3E +U+6F3F(2,3);U+6F3F(2,3); # 62-89, CJK UNIFIED IDEOGRAPH-6F3F +U+6F41(2,3);U+6F41(2,3); # 62-83, CJK UNIFIED IDEOGRAPH-6F41 +U+6F45(2,3);U+6F45(2,3); # 20-35, CJK UNIFIED IDEOGRAPH-6F45 +U+6F54(2,3);U+6F54(2,3); # 23-73, CJK UNIFIED IDEOGRAPH-6F54 +U+6F58(2,3);U+6F58(2,3); # 63-15, CJK UNIFIED IDEOGRAPH-6F58 +U+6F5B(2,3);U+6F5B(2,3); # 63-10, CJK UNIFIED IDEOGRAPH-6F5B +U+6F5C(2,3);U+6F5C(2,3); # 32-88, CJK UNIFIED IDEOGRAPH-6F5C +U+6F5F(2,3);U+6F5F(2,3); # 19-67, CJK UNIFIED IDEOGRAPH-6F5F +U+6F64(2,3);U+6F64(2,3); # 29-65, CJK UNIFIED IDEOGRAPH-6F64 +U+6F66(2,3);U+6F66(2,3); # 63-19, CJK UNIFIED IDEOGRAPH-6F66 +U+6F6D(2,3);U+6F6D(2,3); # 63-12, CJK UNIFIED IDEOGRAPH-6F6D +U+6F6E(2,3);U+6F6E(2,3); # 36-12, CJK UNIFIED IDEOGRAPH-6F6E +U+6F6F(2,3);U+6F6F(2,3); # 63-09, CJK UNIFIED IDEOGRAPH-6F6F +U+6F70(2,3);U+6F70(2,3); # 36-57, CJK UNIFIED IDEOGRAPH-6F70 +U+6F74(2,3);U+6F74(2,3); # 63-44, CJK UNIFIED IDEOGRAPH-6F74 +U+6F78(2,3);U+6F78(2,3); # 63-06, CJK UNIFIED IDEOGRAPH-6F78 +U+6F7A(2,3);U+6F7A(2,3); # 63-05, CJK UNIFIED IDEOGRAPH-6F7A +U+6F7C(2,3);U+6F7C(2,3); # 63-14, CJK UNIFIED IDEOGRAPH-6F7C +U+6F80(2,3);U+6F80(2,3); # 63-08, CJK UNIFIED IDEOGRAPH-6F80 +U+6F81(2,3);U+6F81(2,3); # 63-07, CJK UNIFIED IDEOGRAPH-6F81 +U+6F82(2,3);U+6F82(2,3); # 63-13, CJK UNIFIED IDEOGRAPH-6F82 +U+6F84(2,3);U+6F84(2,3); # 32-01, CJK UNIFIED IDEOGRAPH-6F84 +U+6F86(2,3);U+6F86(2,3); # 63-04, CJK UNIFIED IDEOGRAPH-6F86 +U+6F8E(2,3);U+6F8E(2,3); # 63-16, CJK UNIFIED IDEOGRAPH-6F8E +U+6F91(2,3);U+6F91(2,3); # 63-17, CJK UNIFIED IDEOGRAPH-6F91 +U+6F97(2,3);U+6F97(2,3); # 20-34, CJK UNIFIED IDEOGRAPH-6F97 +U+6FA1(2,3);U+6FA1(2,3); # 63-22, CJK UNIFIED IDEOGRAPH-6FA1 +U+6FA3(2,3);U+6FA3(2,3); # 63-21, CJK UNIFIED IDEOGRAPH-6FA3 +U+6FA4(2,3);U+6FA4(2,3); # 63-23, CJK UNIFIED IDEOGRAPH-6FA4 +U+6FAA(2,3);U+6FAA(2,3); # 63-26, CJK UNIFIED IDEOGRAPH-6FAA +U+6FB1(2,3);U+6FB1(2,3); # 37-35, CJK UNIFIED IDEOGRAPH-6FB1 +U+6FB3(2,3);U+6FB3(2,3); # 63-20, CJK UNIFIED IDEOGRAPH-6FB3 +U+6FB9(2,3);U+6FB9(2,3); # 63-24, CJK UNIFIED IDEOGRAPH-6FB9 +U+6FC0(2,3);U+6FC0(2,3); # 23-67, CJK UNIFIED IDEOGRAPH-6FC0 +U+6FC1(2,3);U+6FC1(2,3); # 34-89, CJK UNIFIED IDEOGRAPH-6FC1 +U+6FC2(2,3);U+6FC2(2,3); # 63-18, CJK UNIFIED IDEOGRAPH-6FC2 +U+6FC3(2,3);U+6FC3(2,3); # 39-27, CJK UNIFIED IDEOGRAPH-6FC3 +U+6FC6(2,3);U+6FC6(2,3); # 63-25, CJK UNIFIED IDEOGRAPH-6FC6 +U+6FD4(2,3);U+6FD4(2,3); # 63-30, CJK UNIFIED IDEOGRAPH-6FD4 +U+6FD5(2,3);U+6FD5(2,3); # 63-28, CJK UNIFIED IDEOGRAPH-6FD5 +U+6FD8(2,3);U+6FD8(2,3); # 63-31, CJK UNIFIED IDEOGRAPH-6FD8 +U+6FDB(2,3);U+6FDB(2,3); # 63-34, CJK UNIFIED IDEOGRAPH-6FDB +U+6FDF(2,3);U+6FDF(2,3); # 63-27, CJK UNIFIED IDEOGRAPH-6FDF +U+6FE0(2,3);U+6FE0(2,3); # 25-74, CJK UNIFIED IDEOGRAPH-6FE0 +U+6FE1(2,3);U+6FE1(2,3); # 39-08, CJK UNIFIED IDEOGRAPH-6FE1 +U+6FE4(2,3);U+6FE4(2,3); # 62-25, CJK UNIFIED IDEOGRAPH-6FE4 +U+6FEB(2,3);U+6FEB(2,3); # 45-84, CJK UNIFIED IDEOGRAPH-6FEB +U+6FEC(2,3);U+6FEC(2,3); # 63-29, CJK UNIFIED IDEOGRAPH-6FEC +U+6FEE(2,3);U+6FEE(2,3); # 63-33, CJK UNIFIED IDEOGRAPH-6FEE +U+6FEF(2,3);U+6FEF(2,3); # 34-85, CJK UNIFIED IDEOGRAPH-6FEF +U+6FF1(2,3);U+6FF1(2,3); # 63-32, CJK UNIFIED IDEOGRAPH-6FF1 +U+6FF3(2,3);U+6FF3(2,3); # 63-11, CJK UNIFIED IDEOGRAPH-6FF3 +U+6FF6(2,3);U+6FF6(2,3); # 79-73, CJK UNIFIED IDEOGRAPH-6FF6 +U+6FFA(2,3);U+6FFA(2,3); # 63-37, CJK UNIFIED IDEOGRAPH-6FFA +U+6FFE(2,3);U+6FFE(2,3); # 63-41, CJK UNIFIED IDEOGRAPH-6FFE +U+7001(2,3);U+7001(2,3); # 63-39, CJK UNIFIED IDEOGRAPH-7001 +U+7009(2,3);U+7009(2,3); # 63-35, CJK UNIFIED IDEOGRAPH-7009 +U+700B(2,3);U+700B(2,3); # 63-36, CJK UNIFIED IDEOGRAPH-700B +U+700F(2,3);U+700F(2,3); # 63-40, CJK UNIFIED IDEOGRAPH-700F +U+7011(2,3);U+7011(2,3); # 63-38, CJK UNIFIED IDEOGRAPH-7011 +U+7015(2,3);U+7015(2,3); # 41-46, CJK UNIFIED IDEOGRAPH-7015 +U+7018(2,3);U+7018(2,3); # 63-46, CJK UNIFIED IDEOGRAPH-7018 +U+701A(2,3);U+701A(2,3); # 63-43, CJK UNIFIED IDEOGRAPH-701A +U+701B(2,3);U+701B(2,3); # 63-42, CJK UNIFIED IDEOGRAPH-701B +U+701D(2,3);U+701D(2,3); # 63-45, CJK UNIFIED IDEOGRAPH-701D +U+701E(2,3);U+701E(2,3); # 38-52, CJK UNIFIED IDEOGRAPH-701E +U+701F(2,3);U+701F(2,3); # 63-47, CJK UNIFIED IDEOGRAPH-701F +U+7026(2,3);U+7026(2,3); # 35-85, CJK UNIFIED IDEOGRAPH-7026 +U+7027(2,3);U+7027(2,3); # 34-77, CJK UNIFIED IDEOGRAPH-7027 +U+702C(2,3);U+702C(2,3); # 32-05, CJK UNIFIED IDEOGRAPH-702C +U+7030(2,3);U+7030(2,3); # 63-48, CJK UNIFIED IDEOGRAPH-7030 +U+7032(2,3);U+7032(2,3); # 63-50, CJK UNIFIED IDEOGRAPH-7032 +U+703E(2,3);U+703E(2,3); # 63-49, CJK UNIFIED IDEOGRAPH-703E +U+704C(2,3);U+704C(2,3); # 62-85, CJK UNIFIED IDEOGRAPH-704C +U+7051(2,3);U+7051(2,3); # 63-51, CJK UNIFIED IDEOGRAPH-7051 +U+7058(2,3);U+7058(2,3); # 38-71, CJK UNIFIED IDEOGRAPH-7058 +U+7063(2,3);U+7063(2,3); # 63-52, CJK UNIFIED IDEOGRAPH-7063 +U+706B(2,3);U+706B(2,3); # 18-48, CJK UNIFIED IDEOGRAPH-706B +U+706F(2,3);U+706F(2,3); # 37-84, CJK UNIFIED IDEOGRAPH-706F +U+7070(2,3);U+7070(2,3); # 19-05, CJK UNIFIED IDEOGRAPH-7070 +U+7078(2,3);U+7078(2,3); # 21-68, CJK UNIFIED IDEOGRAPH-7078 +U+707C(2,3);U+707C(2,3); # 28-62, CJK UNIFIED IDEOGRAPH-707C +U+707D(2,3);U+707D(2,3); # 26-50, CJK UNIFIED IDEOGRAPH-707D +U+7089(2,3);U+7089(2,3); # 47-07, CJK UNIFIED IDEOGRAPH-7089 +U+708A(2,3);U+708A(2,3); # 31-70, CJK UNIFIED IDEOGRAPH-708A +U+708E(2,3);U+708E(2,3); # 17-74, CJK UNIFIED IDEOGRAPH-708E +U+7092(2,3);U+7092(2,3); # 63-54, CJK UNIFIED IDEOGRAPH-7092 +U+7099(2,3);U+7099(2,3); # 63-53, CJK UNIFIED IDEOGRAPH-7099 +U+70AC(2,3);U+70AC(2,3); # 63-57, CJK UNIFIED IDEOGRAPH-70AC +U+70AD(2,3);U+70AD(2,3); # 35-26, CJK UNIFIED IDEOGRAPH-70AD +U+70AE(2,3);U+70AE(2,3); # 63-60, CJK UNIFIED IDEOGRAPH-70AE +U+70AF(2,3);U+70AF(2,3); # 63-55, CJK UNIFIED IDEOGRAPH-70AF +U+70B3(2,3);U+70B3(2,3); # 63-59, CJK UNIFIED IDEOGRAPH-70B3 +U+70B8(2,3);U+70B8(2,3); # 63-58, CJK UNIFIED IDEOGRAPH-70B8 +U+70B9(2,3);U+70B9(2,3); # 37-32, CJK UNIFIED IDEOGRAPH-70B9 +U+70BA(2,3);U+70BA(2,3); # 16-57, CJK UNIFIED IDEOGRAPH-70BA +U+70C8(2,3);U+70C8(2,3); # 46-85, CJK UNIFIED IDEOGRAPH-70C8 +U+70CB(2,3);U+70CB(2,3); # 63-62, CJK UNIFIED IDEOGRAPH-70CB +U+70CF(2,3);U+70CF(2,3); # 17-08, CJK UNIFIED IDEOGRAPH-70CF +U+70D9(2,3);U+70D9(2,3); # 63-64, CJK UNIFIED IDEOGRAPH-70D9 +U+70DD(2,3);U+70DD(2,3); # 63-63, CJK UNIFIED IDEOGRAPH-70DD +U+70DF(2,3);U+70DF(2,3); # 63-61, CJK UNIFIED IDEOGRAPH-70DF +U+70F1(2,3);U+70F1(2,3); # 63-56, CJK UNIFIED IDEOGRAPH-70F1 +U+70F9(2,3);U+70F9(2,3); # 43-03, CJK UNIFIED IDEOGRAPH-70F9 +U+70FD(2,3);U+70FD(2,3); # 63-66, CJK UNIFIED IDEOGRAPH-70FD +U+7109(2,3);U+7109(2,3); # 63-65, CJK UNIFIED IDEOGRAPH-7109 +U+7114(2,3);U+7114(2,3); # 17-75, CJK UNIFIED IDEOGRAPH-7114 +U+7119(2,3);U+7119(2,3); # 63-68, CJK UNIFIED IDEOGRAPH-7119 +U+711A(2,3);U+711A(2,3); # 42-18, CJK UNIFIED IDEOGRAPH-711A +U+711C(2,3);U+711C(2,3); # 63-67, CJK UNIFIED IDEOGRAPH-711C +U+7121(2,3);U+7121(2,3); # 44-21, CJK UNIFIED IDEOGRAPH-7121 +U+7126(2,3);U+7126(2,3); # 30-39, CJK UNIFIED IDEOGRAPH-7126 +U+7136(2,3);U+7136(2,3); # 33-19, CJK UNIFIED IDEOGRAPH-7136 +U+713C(2,3);U+713C(2,3); # 30-38, CJK UNIFIED IDEOGRAPH-713C +U+7149(2,3);U+7149(2,3); # 46-91, CJK UNIFIED IDEOGRAPH-7149 +U+714C(2,3);U+714C(2,3); # 63-74, CJK UNIFIED IDEOGRAPH-714C +U+714E(2,3);U+714E(2,3); # 32-89, CJK UNIFIED IDEOGRAPH-714E +U+7155(2,3);U+7155(2,3); # 63-70, CJK UNIFIED IDEOGRAPH-7155 +U+7156(2,3);U+7156(2,3); # 63-75, CJK UNIFIED IDEOGRAPH-7156 +U+7159(2,3);U+7159(2,3); # 17-76, CJK UNIFIED IDEOGRAPH-7159 +U+7162(2,3);U+7162(2,3); # 63-73, CJK UNIFIED IDEOGRAPH-7162 +U+7164(2,3);U+7164(2,3); # 39-65, CJK UNIFIED IDEOGRAPH-7164 +U+7165(2,3);U+7165(2,3); # 63-69, CJK UNIFIED IDEOGRAPH-7165 +U+7166(2,3);U+7166(2,3); # 63-72, CJK UNIFIED IDEOGRAPH-7166 +U+7167(2,3);U+7167(2,3); # 30-40, CJK UNIFIED IDEOGRAPH-7167 +U+7169(2,3);U+7169(2,3); # 40-49, CJK UNIFIED IDEOGRAPH-7169 +U+716C(2,3);U+716C(2,3); # 63-76, CJK UNIFIED IDEOGRAPH-716C +U+716E(2,3);U+716E(2,3); # 28-49, CJK UNIFIED IDEOGRAPH-716E +U+717D(2,3);U+717D(2,3); # 32-90, CJK UNIFIED IDEOGRAPH-717D +U+7184(2,3);U+7184(2,3); # 63-79, CJK UNIFIED IDEOGRAPH-7184 +U+7188(2,3);U+7188(2,3); # 63-71, CJK UNIFIED IDEOGRAPH-7188 +U+718A(2,3);U+718A(2,3); # 23-07, CJK UNIFIED IDEOGRAPH-718A +U+718F(2,3);U+718F(2,3); # 63-77, CJK UNIFIED IDEOGRAPH-718F +U+7194(2,3);U+7194(2,3); # 45-48, CJK UNIFIED IDEOGRAPH-7194 +U+7195(2,3);U+7195(2,3); # 63-80, CJK UNIFIED IDEOGRAPH-7195 +U+7199(2,3);U+7199(2,3); # 84-06, CJK UNIFIED IDEOGRAPH-7199 +U+719F(2,3);U+719F(2,3); # 29-47, CJK UNIFIED IDEOGRAPH-719F +U+71A8(2,3);U+71A8(2,3); # 63-81, CJK UNIFIED IDEOGRAPH-71A8 +U+71AC(2,3);U+71AC(2,3); # 63-82, CJK UNIFIED IDEOGRAPH-71AC +U+71B1(2,3);U+71B1(2,3); # 39-14, CJK UNIFIED IDEOGRAPH-71B1 +U+71B9(2,3);U+71B9(2,3); # 63-84, CJK UNIFIED IDEOGRAPH-71B9 +U+71BE(2,3);U+71BE(2,3); # 63-85, CJK UNIFIED IDEOGRAPH-71BE +U+71C3(2,3);U+71C3(2,3); # 39-19, CJK UNIFIED IDEOGRAPH-71C3 +U+71C8(2,3);U+71C8(2,3); # 37-85, CJK UNIFIED IDEOGRAPH-71C8 +U+71C9(2,3);U+71C9(2,3); # 63-87, CJK UNIFIED IDEOGRAPH-71C9 +U+71CE(2,3);U+71CE(2,3); # 63-89, CJK UNIFIED IDEOGRAPH-71CE +U+71D0(2,3);U+71D0(2,3); # 46-53, CJK UNIFIED IDEOGRAPH-71D0 +U+71D2(2,3);U+71D2(2,3); # 63-86, CJK UNIFIED IDEOGRAPH-71D2 +U+71D4(2,3);U+71D4(2,3); # 63-88, CJK UNIFIED IDEOGRAPH-71D4 +U+71D5(2,3);U+71D5(2,3); # 17-77, CJK UNIFIED IDEOGRAPH-71D5 +U+71D7(2,3);U+71D7(2,3); # 63-83, CJK UNIFIED IDEOGRAPH-71D7 +U+71DF(2,3);U+71DF(2,3); # 51-59, CJK UNIFIED IDEOGRAPH-71DF +U+71E0(2,3);U+71E0(2,3); # 63-90, CJK UNIFIED IDEOGRAPH-71E0 +U+71E5(2,3);U+71E5(2,3); # 33-71, CJK UNIFIED IDEOGRAPH-71E5 +U+71E6(2,3);U+71E6(2,3); # 27-24, CJK UNIFIED IDEOGRAPH-71E6 +U+71E7(2,3);U+71E7(2,3); # 63-92, CJK UNIFIED IDEOGRAPH-71E7 +U+71EC(2,3);U+71EC(2,3); # 63-91, CJK UNIFIED IDEOGRAPH-71EC +U+71ED(2,3);U+71ED(2,3); # 31-04, CJK UNIFIED IDEOGRAPH-71ED +U+71EE(2,3);U+71EE(2,3); # 50-57, CJK UNIFIED IDEOGRAPH-71EE +U+71F5(2,3);U+71F5(2,3); # 63-93, CJK UNIFIED IDEOGRAPH-71F5 +U+71F9(2,3);U+71F9(2,3); # 64-01, CJK UNIFIED IDEOGRAPH-71F9 +U+71FB(2,3);U+71FB(2,3); # 63-78, CJK UNIFIED IDEOGRAPH-71FB +U+71FC(2,3);U+71FC(2,3); # 63-94, CJK UNIFIED IDEOGRAPH-71FC +U+71FF(2,3);U+71FF(2,3); # 64-02, CJK UNIFIED IDEOGRAPH-71FF +U+7206(2,3);U+7206(2,3); # 39-90, CJK UNIFIED IDEOGRAPH-7206 +U+720D(2,3);U+720D(2,3); # 64-03, CJK UNIFIED IDEOGRAPH-720D +U+7210(2,3);U+7210(2,3); # 64-04, CJK UNIFIED IDEOGRAPH-7210 +U+721B(2,3);U+721B(2,3); # 64-05, CJK UNIFIED IDEOGRAPH-721B +U+7228(2,3);U+7228(2,3); # 64-06, CJK UNIFIED IDEOGRAPH-7228 +U+722A(2,3);U+722A(2,3); # 36-62, CJK UNIFIED IDEOGRAPH-722A +U+722C(2,3);U+722C(2,3); # 64-08, CJK UNIFIED IDEOGRAPH-722C +U+722D(2,3);U+722D(2,3); # 64-07, CJK UNIFIED IDEOGRAPH-722D +U+7230(2,3);U+7230(2,3); # 64-09, CJK UNIFIED IDEOGRAPH-7230 +U+7232(2,3);U+7232(2,3); # 64-10, CJK UNIFIED IDEOGRAPH-7232 +U+7235(2,3);U+7235(2,3); # 28-63, CJK UNIFIED IDEOGRAPH-7235 +U+7236(2,3);U+7236(2,3); # 41-67, CJK UNIFIED IDEOGRAPH-7236 +U+723A(2,3);U+723A(2,3); # 44-76, CJK UNIFIED IDEOGRAPH-723A +U+723B(2,3);U+723B(2,3); # 64-11, CJK UNIFIED IDEOGRAPH-723B +U+723C(2,3);U+723C(2,3); # 64-12, CJK UNIFIED IDEOGRAPH-723C +U+723D(2,3);U+723D(2,3); # 33-54, CJK UNIFIED IDEOGRAPH-723D +U+723E(2,3);U+723E(2,3); # 28-04, CJK UNIFIED IDEOGRAPH-723E +U+723F(2,3);U+723F(2,3); # 64-13, CJK UNIFIED IDEOGRAPH-723F +U+7240(2,3);U+7240(2,3); # 64-14, CJK UNIFIED IDEOGRAPH-7240 +U+7246(2,3);U+7246(2,3); # 64-15, CJK UNIFIED IDEOGRAPH-7246 +U+7247(2,3);U+7247(2,3); # 42-50, CJK UNIFIED IDEOGRAPH-7247 +U+7248(2,3);U+7248(2,3); # 40-39, CJK UNIFIED IDEOGRAPH-7248 +U+724B(2,3);U+724B(2,3); # 64-16, CJK UNIFIED IDEOGRAPH-724B +U+724C(2,3);U+724C(2,3); # 39-55, CJK UNIFIED IDEOGRAPH-724C +U+7252(2,3);U+7252(2,3); # 36-13, CJK UNIFIED IDEOGRAPH-7252 +U+7258(2,3);U+7258(2,3); # 64-17, CJK UNIFIED IDEOGRAPH-7258 +U+7259(2,3);U+7259(2,3); # 18-71, CJK UNIFIED IDEOGRAPH-7259 +U+725B(2,3);U+725B(2,3); # 21-77, CJK UNIFIED IDEOGRAPH-725B +U+725D(2,3);U+725D(2,3); # 44-38, CJK UNIFIED IDEOGRAPH-725D +U+725F(2,3);U+725F(2,3); # 44-22, CJK UNIFIED IDEOGRAPH-725F +U+7261(2,3);U+7261(2,3); # 18-20, CJK UNIFIED IDEOGRAPH-7261 +U+7262(2,3);U+7262(2,3); # 47-20, CJK UNIFIED IDEOGRAPH-7262 +U+7267(2,3);U+7267(2,3); # 43-50, CJK UNIFIED IDEOGRAPH-7267 +U+7269(2,3);U+7269(2,3); # 42-10, CJK UNIFIED IDEOGRAPH-7269 +U+7272(2,3);U+7272(2,3); # 32-23, CJK UNIFIED IDEOGRAPH-7272 +U+7274(2,3);U+7274(2,3); # 64-18, CJK UNIFIED IDEOGRAPH-7274 +U+7279(2,3);U+7279(2,3); # 38-35, CJK UNIFIED IDEOGRAPH-7279 +U+727D(2,3);U+727D(2,3); # 24-03, CJK UNIFIED IDEOGRAPH-727D +U+727E(2,3);U+727E(2,3); # 64-19, CJK UNIFIED IDEOGRAPH-727E +U+7280(2,3);U+7280(2,3); # 26-52, CJK UNIFIED IDEOGRAPH-7280 +U+7281(2,3);U+7281(2,3); # 64-21, CJK UNIFIED IDEOGRAPH-7281 +U+7282(2,3);U+7282(2,3); # 64-20, CJK UNIFIED IDEOGRAPH-7282 +U+7287(2,3);U+7287(2,3); # 64-22, CJK UNIFIED IDEOGRAPH-7287 +U+7292(2,3);U+7292(2,3); # 64-23, CJK UNIFIED IDEOGRAPH-7292 +U+7296(2,3);U+7296(2,3); # 64-24, CJK UNIFIED IDEOGRAPH-7296 +U+72A0(2,3);U+72A0(2,3); # 21-30, CJK UNIFIED IDEOGRAPH-72A0 +U+72A2(2,3);U+72A2(2,3); # 64-25, CJK UNIFIED IDEOGRAPH-72A2 +U+72A7(2,3);U+72A7(2,3); # 64-26, CJK UNIFIED IDEOGRAPH-72A7 +U+72AC(2,3);U+72AC(2,3); # 24-04, CJK UNIFIED IDEOGRAPH-72AC +U+72AF(2,3);U+72AF(2,3); # 40-40, CJK UNIFIED IDEOGRAPH-72AF +U+72B2(2,3);U+72B2(2,3); # 64-28, CJK UNIFIED IDEOGRAPH-72B2 +U+72B6(2,3);U+72B6(2,3); # 30-85, CJK UNIFIED IDEOGRAPH-72B6 +U+72B9(2,3);U+72B9(2,3); # 64-27, CJK UNIFIED IDEOGRAPH-72B9 +U+72C2(2,3);U+72C2(2,3); # 22-24, CJK UNIFIED IDEOGRAPH-72C2 +U+72C3(2,3);U+72C3(2,3); # 64-29, CJK UNIFIED IDEOGRAPH-72C3 +U+72C4(2,3);U+72C4(2,3); # 64-31, CJK UNIFIED IDEOGRAPH-72C4 +U+72C6(2,3);U+72C6(2,3); # 64-30, CJK UNIFIED IDEOGRAPH-72C6 +U+72CE(2,3);U+72CE(2,3); # 64-32, CJK UNIFIED IDEOGRAPH-72CE +U+72D0(2,3);U+72D0(2,3); # 24-49, CJK UNIFIED IDEOGRAPH-72D0 +U+72D2(2,3);U+72D2(2,3); # 64-33, CJK UNIFIED IDEOGRAPH-72D2 +U+72D7(2,3);U+72D7(2,3); # 22-73, CJK UNIFIED IDEOGRAPH-72D7 +U+72D9(2,3);U+72D9(2,3); # 33-32, CJK UNIFIED IDEOGRAPH-72D9 +U+72DB(2,3);U+72DB(2,3); # 25-93, CJK UNIFIED IDEOGRAPH-72DB +U+72E0(2,3);U+72E0(2,3); # 64-35, CJK UNIFIED IDEOGRAPH-72E0 +U+72E1(2,3);U+72E1(2,3); # 64-36, CJK UNIFIED IDEOGRAPH-72E1 +U+72E2(2,3);U+72E2(2,3); # 64-34, CJK UNIFIED IDEOGRAPH-72E2 +U+72E9(2,3);U+72E9(2,3); # 28-77, CJK UNIFIED IDEOGRAPH-72E9 +U+72EC(2,3);U+72EC(2,3); # 38-40, CJK UNIFIED IDEOGRAPH-72EC +U+72ED(2,3);U+72ED(2,3); # 22-25, CJK UNIFIED IDEOGRAPH-72ED +U+72F7(2,3);U+72F7(2,3); # 64-38, CJK UNIFIED IDEOGRAPH-72F7 +U+72F8(2,3);U+72F8(2,3); # 35-12, CJK UNIFIED IDEOGRAPH-72F8 +U+72F9(2,3);U+72F9(2,3); # 64-37, CJK UNIFIED IDEOGRAPH-72F9 +U+72FC(2,3);U+72FC(2,3); # 47-21, CJK UNIFIED IDEOGRAPH-72FC +U+72FD(2,3);U+72FD(2,3); # 39-66, CJK UNIFIED IDEOGRAPH-72FD +U+730A(2,3);U+730A(2,3); # 64-41, CJK UNIFIED IDEOGRAPH-730A +U+7316(2,3);U+7316(2,3); # 64-43, CJK UNIFIED IDEOGRAPH-7316 +U+7317(2,3);U+7317(2,3); # 64-40, CJK UNIFIED IDEOGRAPH-7317 +U+731B(2,3);U+731B(2,3); # 44-52, CJK UNIFIED IDEOGRAPH-731B +U+731C(2,3);U+731C(2,3); # 64-42, CJK UNIFIED IDEOGRAPH-731C +U+731D(2,3);U+731D(2,3); # 64-44, CJK UNIFIED IDEOGRAPH-731D +U+731F(2,3);U+731F(2,3); # 46-36, CJK UNIFIED IDEOGRAPH-731F +U+7325(2,3);U+7325(2,3); # 64-48, CJK UNIFIED IDEOGRAPH-7325 +U+7329(2,3);U+7329(2,3); # 64-47, CJK UNIFIED IDEOGRAPH-7329 +U+732A(2,3);U+732A(2,3); # 35-86, CJK UNIFIED IDEOGRAPH-732A +U+732B(2,3);U+732B(2,3); # 39-13, CJK UNIFIED IDEOGRAPH-732B +U+732E(2,3);U+732E(2,3); # 24-05, CJK UNIFIED IDEOGRAPH-732E +U+732F(2,3);U+732F(2,3); # 64-46, CJK UNIFIED IDEOGRAPH-732F +U+7334(2,3);U+7334(2,3); # 64-45, CJK UNIFIED IDEOGRAPH-7334 +U+7336(2,3);U+7336(2,3); # 45-17, CJK UNIFIED IDEOGRAPH-7336 +U+7337(2,3);U+7337(2,3); # 45-18, CJK UNIFIED IDEOGRAPH-7337 +U+733E(2,3);U+733E(2,3); # 64-49, CJK UNIFIED IDEOGRAPH-733E +U+733F(2,3);U+733F(2,3); # 17-78, CJK UNIFIED IDEOGRAPH-733F +U+7344(2,3);U+7344(2,3); # 25-86, CJK UNIFIED IDEOGRAPH-7344 +U+7345(2,3);U+7345(2,3); # 27-66, CJK UNIFIED IDEOGRAPH-7345 +U+734E(2,3);U+734E(2,3); # 64-50, CJK UNIFIED IDEOGRAPH-734E +U+734F(2,3);U+734F(2,3); # 64-51, CJK UNIFIED IDEOGRAPH-734F +U+7357(2,3);U+7357(2,3); # 64-53, CJK UNIFIED IDEOGRAPH-7357 +U+7363(2,3);U+7363(2,3); # 29-35, CJK UNIFIED IDEOGRAPH-7363 +U+7368(2,3);U+7368(2,3); # 64-55, CJK UNIFIED IDEOGRAPH-7368 +U+736A(2,3);U+736A(2,3); # 64-54, CJK UNIFIED IDEOGRAPH-736A +U+7370(2,3);U+7370(2,3); # 64-56, CJK UNIFIED IDEOGRAPH-7370 +U+7372(2,3);U+7372(2,3); # 19-45, CJK UNIFIED IDEOGRAPH-7372 +U+7375(2,3);U+7375(2,3); # 64-58, CJK UNIFIED IDEOGRAPH-7375 +U+7378(2,3);U+7378(2,3); # 64-57, CJK UNIFIED IDEOGRAPH-7378 +U+737A(2,3);U+737A(2,3); # 64-60, CJK UNIFIED IDEOGRAPH-737A +U+737B(2,3);U+737B(2,3); # 64-59, CJK UNIFIED IDEOGRAPH-737B +U+7384(2,3);U+7384(2,3); # 24-28, CJK UNIFIED IDEOGRAPH-7384 +U+7387(2,3);U+7387(2,3); # 46-08, CJK UNIFIED IDEOGRAPH-7387 +U+7389(2,3);U+7389(2,3); # 22-44, CJK UNIFIED IDEOGRAPH-7389 +U+738B(2,3);U+738B(2,3); # 18-06, CJK UNIFIED IDEOGRAPH-738B +U+7396(2,3);U+7396(2,3); # 22-74, CJK UNIFIED IDEOGRAPH-7396 +U+73A9(2,3);U+73A9(2,3); # 20-65, CJK UNIFIED IDEOGRAPH-73A9 +U+73B2(2,3);U+73B2(2,3); # 46-72, CJK UNIFIED IDEOGRAPH-73B2 +U+73B3(2,3);U+73B3(2,3); # 64-62, CJK UNIFIED IDEOGRAPH-73B3 +U+73BB(2,3);U+73BB(2,3); # 64-64, CJK UNIFIED IDEOGRAPH-73BB +U+73C0(2,3);U+73C0(2,3); # 64-65, CJK UNIFIED IDEOGRAPH-73C0 +U+73C2(2,3);U+73C2(2,3); # 18-49, CJK UNIFIED IDEOGRAPH-73C2 +U+73C8(2,3);U+73C8(2,3); # 64-61, CJK UNIFIED IDEOGRAPH-73C8 +U+73CA(2,3);U+73CA(2,3); # 27-25, CJK UNIFIED IDEOGRAPH-73CA +U+73CD(2,3);U+73CD(2,3); # 36-33, CJK UNIFIED IDEOGRAPH-73CD +U+73CE(2,3);U+73CE(2,3); # 64-63, CJK UNIFIED IDEOGRAPH-73CE +U+73DE(2,3);U+73DE(2,3); # 64-68, CJK UNIFIED IDEOGRAPH-73DE +U+73E0(2,3);U+73E0(2,3); # 28-78, CJK UNIFIED IDEOGRAPH-73E0 +U+73E5(2,3);U+73E5(2,3); # 64-66, CJK UNIFIED IDEOGRAPH-73E5 +U+73EA(2,3);U+73EA(2,3); # 23-30, CJK UNIFIED IDEOGRAPH-73EA +U+73ED(2,3);U+73ED(2,3); # 40-41, CJK UNIFIED IDEOGRAPH-73ED +U+73EE(2,3);U+73EE(2,3); # 64-67, CJK UNIFIED IDEOGRAPH-73EE +U+73F1(2,3);U+73F1(2,3); # 64-94, CJK UNIFIED IDEOGRAPH-73F1 +U+73F8(2,3);U+73F8(2,3); # 64-73, CJK UNIFIED IDEOGRAPH-73F8 +U+73FE(2,3);U+73FE(2,3); # 24-29, CJK UNIFIED IDEOGRAPH-73FE +U+7403(2,3);U+7403(2,3); # 21-69, CJK UNIFIED IDEOGRAPH-7403 +U+7405(2,3);U+7405(2,3); # 64-70, CJK UNIFIED IDEOGRAPH-7405 +U+7406(2,3);U+7406(2,3); # 45-93, CJK UNIFIED IDEOGRAPH-7406 +U+7409(2,3);U+7409(2,3); # 46-16, CJK UNIFIED IDEOGRAPH-7409 +U+7422(2,3);U+7422(2,3); # 34-86, CJK UNIFIED IDEOGRAPH-7422 +U+7425(2,3);U+7425(2,3); # 64-72, CJK UNIFIED IDEOGRAPH-7425 +U+7432(2,3);U+7432(2,3); # 64-74, CJK UNIFIED IDEOGRAPH-7432 +U+7433(2,3);U+7433(2,3); # 46-54, CJK UNIFIED IDEOGRAPH-7433 +U+7434(2,3);U+7434(2,3); # 22-55, CJK UNIFIED IDEOGRAPH-7434 +U+7435(2,3);U+7435(2,3); # 40-92, CJK UNIFIED IDEOGRAPH-7435 +U+7436(2,3);U+7436(2,3); # 39-42, CJK UNIFIED IDEOGRAPH-7436 +U+743A(2,3);U+743A(2,3); # 64-75, CJK UNIFIED IDEOGRAPH-743A +U+743F(2,3);U+743F(2,3); # 64-77, CJK UNIFIED IDEOGRAPH-743F +U+7441(2,3);U+7441(2,3); # 64-80, CJK UNIFIED IDEOGRAPH-7441 +U+7455(2,3);U+7455(2,3); # 64-76, CJK UNIFIED IDEOGRAPH-7455 +U+7459(2,3);U+7459(2,3); # 64-79, CJK UNIFIED IDEOGRAPH-7459 +U+745A(2,3);U+745A(2,3); # 24-74, CJK UNIFIED IDEOGRAPH-745A +U+745B(2,3);U+745B(2,3); # 17-45, CJK UNIFIED IDEOGRAPH-745B +U+745C(2,3);U+745C(2,3); # 64-81, CJK UNIFIED IDEOGRAPH-745C +U+745E(2,3);U+745E(2,3); # 31-80, CJK UNIFIED IDEOGRAPH-745E +U+745F(2,3);U+745F(2,3); # 64-78, CJK UNIFIED IDEOGRAPH-745F +U+7460(2,3);U+7460(2,3); # 46-60, CJK UNIFIED IDEOGRAPH-7460 +U+7463(2,3);U+7463(2,3); # 64-84, CJK UNIFIED IDEOGRAPH-7463 +U+7464(2,3);U+7464(2,3); # 84-04, CJK UNIFIED IDEOGRAPH-7464 +U+7469(2,3);U+7469(2,3); # 64-82, CJK UNIFIED IDEOGRAPH-7469 +U+746A(2,3);U+746A(2,3); # 64-85, CJK UNIFIED IDEOGRAPH-746A +U+746F(2,3);U+746F(2,3); # 64-71, CJK UNIFIED IDEOGRAPH-746F +U+7470(2,3);U+7470(2,3); # 64-83, CJK UNIFIED IDEOGRAPH-7470 +U+7473(2,3);U+7473(2,3); # 26-28, CJK UNIFIED IDEOGRAPH-7473 +U+7476(2,3);U+7476(2,3); # 64-86, CJK UNIFIED IDEOGRAPH-7476 +U+747E(2,3);U+747E(2,3); # 64-87, CJK UNIFIED IDEOGRAPH-747E +U+7483(2,3);U+7483(2,3); # 45-94, CJK UNIFIED IDEOGRAPH-7483 +U+748B(2,3);U+748B(2,3); # 64-88, CJK UNIFIED IDEOGRAPH-748B +U+749E(2,3);U+749E(2,3); # 64-89, CJK UNIFIED IDEOGRAPH-749E +U+74A2(2,3);U+74A2(2,3); # 64-69, CJK UNIFIED IDEOGRAPH-74A2 +U+74A7(2,3);U+74A7(2,3); # 64-90, CJK UNIFIED IDEOGRAPH-74A7 +U+74B0(2,3);U+74B0(2,3); # 20-36, CJK UNIFIED IDEOGRAPH-74B0 +U+74BD(2,3);U+74BD(2,3); # 28-05, CJK UNIFIED IDEOGRAPH-74BD +U+74CA(2,3);U+74CA(2,3); # 64-91, CJK UNIFIED IDEOGRAPH-74CA +U+74CF(2,3);U+74CF(2,3); # 64-92, CJK UNIFIED IDEOGRAPH-74CF +U+74D4(2,3);U+74D4(2,3); # 64-93, CJK UNIFIED IDEOGRAPH-74D4 +U+74DC(2,3);U+74DC(2,3); # 17-27, CJK UNIFIED IDEOGRAPH-74DC +U+74E0(2,3);U+74E0(2,3); # 65-01, CJK UNIFIED IDEOGRAPH-74E0 +U+74E2(2,3);U+74E2(2,3); # 41-27, CJK UNIFIED IDEOGRAPH-74E2 +U+74E3(2,3);U+74E3(2,3); # 65-02, CJK UNIFIED IDEOGRAPH-74E3 +U+74E6(2,3);U+74E6(2,3); # 20-04, CJK UNIFIED IDEOGRAPH-74E6 +U+74E7(2,3);U+74E7(2,3); # 65-03, CJK UNIFIED IDEOGRAPH-74E7 +U+74E9(2,3);U+74E9(2,3); # 65-04, CJK UNIFIED IDEOGRAPH-74E9 +U+74EE(2,3);U+74EE(2,3); # 65-05, CJK UNIFIED IDEOGRAPH-74EE +U+74F0(2,3);U+74F0(2,3); # 65-07, CJK UNIFIED IDEOGRAPH-74F0 +U+74F1(2,3);U+74F1(2,3); # 65-08, CJK UNIFIED IDEOGRAPH-74F1 +U+74F2(2,3);U+74F2(2,3); # 65-06, CJK UNIFIED IDEOGRAPH-74F2 +U+74F6(2,3);U+74F6(2,3); # 41-51, CJK UNIFIED IDEOGRAPH-74F6 +U+74F7(2,3);U+74F7(2,3); # 65-10, CJK UNIFIED IDEOGRAPH-74F7 +U+74F8(2,3);U+74F8(2,3); # 65-09, CJK UNIFIED IDEOGRAPH-74F8 +U+7503(2,3);U+7503(2,3); # 65-12, CJK UNIFIED IDEOGRAPH-7503 +U+7504(2,3);U+7504(2,3); # 65-11, CJK UNIFIED IDEOGRAPH-7504 +U+7505(2,3);U+7505(2,3); # 65-13, CJK UNIFIED IDEOGRAPH-7505 +U+750C(2,3);U+750C(2,3); # 65-14, CJK UNIFIED IDEOGRAPH-750C +U+750D(2,3);U+750D(2,3); # 65-16, CJK UNIFIED IDEOGRAPH-750D +U+750E(2,3);U+750E(2,3); # 65-15, CJK UNIFIED IDEOGRAPH-750E +U+7511(2,3);U+7511(2,3); # 25-89, CJK UNIFIED IDEOGRAPH-7511 +U+7513(2,3);U+7513(2,3); # 65-18, CJK UNIFIED IDEOGRAPH-7513 +U+7515(2,3);U+7515(2,3); # 65-17, CJK UNIFIED IDEOGRAPH-7515 +U+7518(2,3);U+7518(2,3); # 20-37, CJK UNIFIED IDEOGRAPH-7518 +U+751A(2,3);U+751A(2,3); # 31-51, CJK UNIFIED IDEOGRAPH-751A +U+751C(2,3);U+751C(2,3); # 37-28, CJK UNIFIED IDEOGRAPH-751C +U+751E(2,3);U+751E(2,3); # 65-19, CJK UNIFIED IDEOGRAPH-751E +U+751F(2,3);U+751F(2,3); # 32-24, CJK UNIFIED IDEOGRAPH-751F +U+7523(2,3);U+7523(2,3); # 27-26, CJK UNIFIED IDEOGRAPH-7523 +U+7525(2,3);U+7525(2,3); # 17-89, CJK UNIFIED IDEOGRAPH-7525 +U+7526(2,3);U+7526(2,3); # 65-20, CJK UNIFIED IDEOGRAPH-7526 +U+7528(2,3);U+7528(2,3); # 45-49, CJK UNIFIED IDEOGRAPH-7528 +U+752B(2,3);U+752B(2,3); # 42-67, CJK UNIFIED IDEOGRAPH-752B +U+752C(2,3);U+752C(2,3); # 65-21, CJK UNIFIED IDEOGRAPH-752C +U+7530(2,3);U+7530(2,3); # 37-36, CJK UNIFIED IDEOGRAPH-7530 +U+7531(2,3);U+7531(2,3); # 45-19, CJK UNIFIED IDEOGRAPH-7531 +U+7532(2,3);U+7532(2,3); # 25-35, CJK UNIFIED IDEOGRAPH-7532 +U+7533(2,3);U+7533(2,3); # 31-29, CJK UNIFIED IDEOGRAPH-7533 +U+7537(2,3);U+7537(2,3); # 35-43, CJK UNIFIED IDEOGRAPH-7537 +U+7538(2,3);U+7538(2,3); # 50-20, CJK UNIFIED IDEOGRAPH-7538 +U+753A(2,3);U+753A(2,3); # 36-14, CJK UNIFIED IDEOGRAPH-753A +U+753B(2,3);U+753B(2,3); # 18-72, CJK UNIFIED IDEOGRAPH-753B +U+753C(2,3);U+753C(2,3); # 65-22, CJK UNIFIED IDEOGRAPH-753C +U+7544(2,3);U+7544(2,3); # 65-23, CJK UNIFIED IDEOGRAPH-7544 +U+7546(2,3);U+7546(2,3); # 65-28, CJK UNIFIED IDEOGRAPH-7546 +U+7549(2,3);U+7549(2,3); # 65-26, CJK UNIFIED IDEOGRAPH-7549 +U+754A(2,3);U+754A(2,3); # 65-25, CJK UNIFIED IDEOGRAPH-754A +U+754B(2,3);U+754B(2,3); # 58-34, CJK UNIFIED IDEOGRAPH-754B +U+754C(2,3);U+754C(2,3); # 19-06, CJK UNIFIED IDEOGRAPH-754C +U+754D(2,3);U+754D(2,3); # 65-24, CJK UNIFIED IDEOGRAPH-754D +U+754F(2,3);U+754F(2,3); # 16-58, CJK UNIFIED IDEOGRAPH-754F +U+7551(2,3);U+7551(2,3); # 40-10, CJK UNIFIED IDEOGRAPH-7551 +U+7554(2,3);U+7554(2,3); # 40-42, CJK UNIFIED IDEOGRAPH-7554 +U+7559(2,3);U+7559(2,3); # 46-17, CJK UNIFIED IDEOGRAPH-7559 +U+755A(2,3);U+755A(2,3); # 65-29, CJK UNIFIED IDEOGRAPH-755A +U+755B(2,3);U+755B(2,3); # 65-27, CJK UNIFIED IDEOGRAPH-755B +U+755C(2,3);U+755C(2,3); # 35-60, CJK UNIFIED IDEOGRAPH-755C +U+755D(2,3);U+755D(2,3); # 32-06, CJK UNIFIED IDEOGRAPH-755D +U+7560(2,3);U+7560(2,3); # 40-11, CJK UNIFIED IDEOGRAPH-7560 +U+7562(2,3);U+7562(2,3); # 41-13, CJK UNIFIED IDEOGRAPH-7562 +U+7564(2,3);U+7564(2,3); # 65-31, CJK UNIFIED IDEOGRAPH-7564 +U+7565(2,3);U+7565(2,3); # 46-12, CJK UNIFIED IDEOGRAPH-7565 +U+7566(2,3);U+7566(2,3); # 23-45, CJK UNIFIED IDEOGRAPH-7566 +U+7567(2,3);U+7567(2,3); # 65-32, CJK UNIFIED IDEOGRAPH-7567 +U+7569(2,3);U+7569(2,3); # 65-30, CJK UNIFIED IDEOGRAPH-7569 +U+756A(2,3);U+756A(2,3); # 40-54, CJK UNIFIED IDEOGRAPH-756A +U+756B(2,3);U+756B(2,3); # 65-33, CJK UNIFIED IDEOGRAPH-756B +U+756D(2,3);U+756D(2,3); # 65-34, CJK UNIFIED IDEOGRAPH-756D +U+7570(2,3);U+7570(2,3); # 16-59, CJK UNIFIED IDEOGRAPH-7570 +U+7573(2,3);U+7573(2,3); # 30-86, CJK UNIFIED IDEOGRAPH-7573 +U+7574(2,3);U+7574(2,3); # 65-39, CJK UNIFIED IDEOGRAPH-7574 +U+7576(2,3);U+7576(2,3); # 65-36, CJK UNIFIED IDEOGRAPH-7576 +U+7577(2,3);U+7577(2,3); # 38-77, CJK UNIFIED IDEOGRAPH-7577 +U+7578(2,3);U+7578(2,3); # 65-35, CJK UNIFIED IDEOGRAPH-7578 +U+757F(2,3);U+757F(2,3); # 21-06, CJK UNIFIED IDEOGRAPH-757F +U+7582(2,3);U+7582(2,3); # 65-42, CJK UNIFIED IDEOGRAPH-7582 +U+7586(2,3);U+7586(2,3); # 65-37, CJK UNIFIED IDEOGRAPH-7586 +U+7587(2,3);U+7587(2,3); # 65-38, CJK UNIFIED IDEOGRAPH-7587 +U+7589(2,3);U+7589(2,3); # 65-41, CJK UNIFIED IDEOGRAPH-7589 +U+758A(2,3);U+758A(2,3); # 65-40, CJK UNIFIED IDEOGRAPH-758A +U+758B(2,3);U+758B(2,3); # 41-05, CJK UNIFIED IDEOGRAPH-758B +U+758E(2,3);U+758E(2,3); # 33-34, CJK UNIFIED IDEOGRAPH-758E +U+758F(2,3);U+758F(2,3); # 33-33, CJK UNIFIED IDEOGRAPH-758F +U+7591(2,3);U+7591(2,3); # 21-31, CJK UNIFIED IDEOGRAPH-7591 +U+7594(2,3);U+7594(2,3); # 65-43, CJK UNIFIED IDEOGRAPH-7594 +U+759A(2,3);U+759A(2,3); # 65-44, CJK UNIFIED IDEOGRAPH-759A +U+759D(2,3);U+759D(2,3); # 65-45, CJK UNIFIED IDEOGRAPH-759D +U+75A3(2,3);U+75A3(2,3); # 65-47, CJK UNIFIED IDEOGRAPH-75A3 +U+75A5(2,3);U+75A5(2,3); # 65-46, CJK UNIFIED IDEOGRAPH-75A5 +U+75AB(2,3);U+75AB(2,3); # 17-54, CJK UNIFIED IDEOGRAPH-75AB +U+75B1(2,3);U+75B1(2,3); # 65-55, CJK UNIFIED IDEOGRAPH-75B1 +U+75B2(2,3);U+75B2(2,3); # 40-72, CJK UNIFIED IDEOGRAPH-75B2 +U+75B3(2,3);U+75B3(2,3); # 65-49, CJK UNIFIED IDEOGRAPH-75B3 +U+75B5(2,3);U+75B5(2,3); # 65-51, CJK UNIFIED IDEOGRAPH-75B5 +U+75B8(2,3);U+75B8(2,3); # 65-53, CJK UNIFIED IDEOGRAPH-75B8 +U+75B9(2,3);U+75B9(2,3); # 31-30, CJK UNIFIED IDEOGRAPH-75B9 +U+75BC(2,3);U+75BC(2,3); # 65-54, CJK UNIFIED IDEOGRAPH-75BC +U+75BD(2,3);U+75BD(2,3); # 65-52, CJK UNIFIED IDEOGRAPH-75BD +U+75BE(2,3);U+75BE(2,3); # 28-32, CJK UNIFIED IDEOGRAPH-75BE +U+75C2(2,3);U+75C2(2,3); # 65-48, CJK UNIFIED IDEOGRAPH-75C2 +U+75C3(2,3);U+75C3(2,3); # 65-50, CJK UNIFIED IDEOGRAPH-75C3 +U+75C5(2,3);U+75C5(2,3); # 41-34, CJK UNIFIED IDEOGRAPH-75C5 +U+75C7(2,3);U+75C7(2,3); # 30-41, CJK UNIFIED IDEOGRAPH-75C7 +U+75CA(2,3);U+75CA(2,3); # 65-57, CJK UNIFIED IDEOGRAPH-75CA +U+75CD(2,3);U+75CD(2,3); # 65-56, CJK UNIFIED IDEOGRAPH-75CD +U+75D2(2,3);U+75D2(2,3); # 65-58, CJK UNIFIED IDEOGRAPH-75D2 +U+75D4(2,3);U+75D4(2,3); # 28-06, CJK UNIFIED IDEOGRAPH-75D4 +U+75D5(2,3);U+75D5(2,3); # 26-15, CJK UNIFIED IDEOGRAPH-75D5 +U+75D8(2,3);U+75D8(2,3); # 37-87, CJK UNIFIED IDEOGRAPH-75D8 +U+75D9(2,3);U+75D9(2,3); # 65-59, CJK UNIFIED IDEOGRAPH-75D9 +U+75DB(2,3);U+75DB(2,3); # 36-43, CJK UNIFIED IDEOGRAPH-75DB +U+75DE(2,3);U+75DE(2,3); # 65-61, CJK UNIFIED IDEOGRAPH-75DE +U+75E2(2,3);U+75E2(2,3); # 46-01, CJK UNIFIED IDEOGRAPH-75E2 +U+75E3(2,3);U+75E3(2,3); # 65-60, CJK UNIFIED IDEOGRAPH-75E3 +U+75E9(2,3);U+75E9(2,3); # 33-73, CJK UNIFIED IDEOGRAPH-75E9 +U+75F0(2,3);U+75F0(2,3); # 65-66, CJK UNIFIED IDEOGRAPH-75F0 +U+75F2(2,3);U+75F2(2,3); # 65-68, CJK UNIFIED IDEOGRAPH-75F2 +U+75F3(2,3);U+75F3(2,3); # 65-69, CJK UNIFIED IDEOGRAPH-75F3 +U+75F4(2,3);U+75F4(2,3); # 35-52, CJK UNIFIED IDEOGRAPH-75F4 +U+75FA(2,3);U+75FA(2,3); # 65-67, CJK UNIFIED IDEOGRAPH-75FA +U+75FC(2,3);U+75FC(2,3); # 65-64, CJK UNIFIED IDEOGRAPH-75FC +U+75FE(2,3);U+75FE(2,3); # 65-62, CJK UNIFIED IDEOGRAPH-75FE +U+75FF(2,3);U+75FF(2,3); # 65-63, CJK UNIFIED IDEOGRAPH-75FF +U+7601(2,3);U+7601(2,3); # 65-65, CJK UNIFIED IDEOGRAPH-7601 +U+7609(2,3);U+7609(2,3); # 65-72, CJK UNIFIED IDEOGRAPH-7609 +U+760B(2,3);U+760B(2,3); # 65-70, CJK UNIFIED IDEOGRAPH-760B +U+760D(2,3);U+760D(2,3); # 65-71, CJK UNIFIED IDEOGRAPH-760D +U+761F(2,3);U+761F(2,3); # 65-73, CJK UNIFIED IDEOGRAPH-761F +U+7620(2,3);U+7620(2,3); # 65-75, CJK UNIFIED IDEOGRAPH-7620 +U+7621(2,3);U+7621(2,3); # 65-76, CJK UNIFIED IDEOGRAPH-7621 +U+7622(2,3);U+7622(2,3); # 65-77, CJK UNIFIED IDEOGRAPH-7622 +U+7624(2,3);U+7624(2,3); # 65-78, CJK UNIFIED IDEOGRAPH-7624 +U+7627(2,3);U+7627(2,3); # 65-74, CJK UNIFIED IDEOGRAPH-7627 +U+7630(2,3);U+7630(2,3); # 65-80, CJK UNIFIED IDEOGRAPH-7630 +U+7634(2,3);U+7634(2,3); # 65-79, CJK UNIFIED IDEOGRAPH-7634 +U+763B(2,3);U+763B(2,3); # 65-81, CJK UNIFIED IDEOGRAPH-763B +U+7642(2,3);U+7642(2,3); # 46-37, CJK UNIFIED IDEOGRAPH-7642 +U+7646(2,3);U+7646(2,3); # 65-84, CJK UNIFIED IDEOGRAPH-7646 +U+7647(2,3);U+7647(2,3); # 65-82, CJK UNIFIED IDEOGRAPH-7647 +U+7648(2,3);U+7648(2,3); # 65-83, CJK UNIFIED IDEOGRAPH-7648 +U+764C(2,3);U+764C(2,3); # 20-66, CJK UNIFIED IDEOGRAPH-764C +U+7652(2,3);U+7652(2,3); # 44-94, CJK UNIFIED IDEOGRAPH-7652 +U+7656(2,3);U+7656(2,3); # 42-42, CJK UNIFIED IDEOGRAPH-7656 +U+7658(2,3);U+7658(2,3); # 65-86, CJK UNIFIED IDEOGRAPH-7658 +U+765C(2,3);U+765C(2,3); # 65-85, CJK UNIFIED IDEOGRAPH-765C +U+7661(2,3);U+7661(2,3); # 65-87, CJK UNIFIED IDEOGRAPH-7661 +U+7662(2,3);U+7662(2,3); # 65-88, CJK UNIFIED IDEOGRAPH-7662 +U+7667(2,3);U+7667(2,3); # 65-92, CJK UNIFIED IDEOGRAPH-7667 +U+7668(2,3);U+7668(2,3); # 65-89, CJK UNIFIED IDEOGRAPH-7668 +U+7669(2,3);U+7669(2,3); # 65-90, CJK UNIFIED IDEOGRAPH-7669 +U+766A(2,3);U+766A(2,3); # 65-91, CJK UNIFIED IDEOGRAPH-766A +U+766C(2,3);U+766C(2,3); # 65-93, CJK UNIFIED IDEOGRAPH-766C +U+7670(2,3);U+7670(2,3); # 65-94, CJK UNIFIED IDEOGRAPH-7670 +U+7672(2,3);U+7672(2,3); # 66-01, CJK UNIFIED IDEOGRAPH-7672 +U+7676(2,3);U+7676(2,3); # 66-02, CJK UNIFIED IDEOGRAPH-7676 +U+7678(2,3);U+7678(2,3); # 66-03, CJK UNIFIED IDEOGRAPH-7678 +U+767A(2,3);U+767A(2,3); # 40-15, CJK UNIFIED IDEOGRAPH-767A +U+767B(2,3);U+767B(2,3); # 37-48, CJK UNIFIED IDEOGRAPH-767B +U+767C(2,3);U+767C(2,3); # 66-04, CJK UNIFIED IDEOGRAPH-767C +U+767D(2,3);U+767D(2,3); # 39-82, CJK UNIFIED IDEOGRAPH-767D +U+767E(2,3);U+767E(2,3); # 41-20, CJK UNIFIED IDEOGRAPH-767E +U+7680(2,3);U+7680(2,3); # 66-05, CJK UNIFIED IDEOGRAPH-7680 +U+7683(2,3);U+7683(2,3); # 66-06, CJK UNIFIED IDEOGRAPH-7683 +U+7684(2,3);U+7684(2,3); # 37-10, CJK UNIFIED IDEOGRAPH-7684 +U+7686(2,3);U+7686(2,3); # 19-07, CJK UNIFIED IDEOGRAPH-7686 +U+7687(2,3);U+7687(2,3); # 25-36, CJK UNIFIED IDEOGRAPH-7687 +U+7688(2,3);U+7688(2,3); # 66-07, CJK UNIFIED IDEOGRAPH-7688 +U+768B(2,3);U+768B(2,3); # 66-08, CJK UNIFIED IDEOGRAPH-768B +U+768E(2,3);U+768E(2,3); # 66-09, CJK UNIFIED IDEOGRAPH-768E +U+7690(2,3);U+7690(2,3); # 27-09, CJK UNIFIED IDEOGRAPH-7690 +U+7693(2,3);U+7693(2,3); # 66-11, CJK UNIFIED IDEOGRAPH-7693 +U+7696(2,3);U+7696(2,3); # 66-10, CJK UNIFIED IDEOGRAPH-7696 +U+7699(2,3);U+7699(2,3); # 66-12, CJK UNIFIED IDEOGRAPH-7699 +U+769A(2,3);U+769A(2,3); # 66-13, CJK UNIFIED IDEOGRAPH-769A +U+76AE(2,3);U+76AE(2,3); # 40-73, CJK UNIFIED IDEOGRAPH-76AE +U+76B0(2,3);U+76B0(2,3); # 66-14, CJK UNIFIED IDEOGRAPH-76B0 +U+76B4(2,3);U+76B4(2,3); # 66-15, CJK UNIFIED IDEOGRAPH-76B4 +U+76B7(2,3);U+76B7(2,3); # 83-73, CJK UNIFIED IDEOGRAPH-76B7 +U+76B8(2,3);U+76B8(2,3); # 66-16, CJK UNIFIED IDEOGRAPH-76B8 +U+76B9(2,3);U+76B9(2,3); # 66-17, CJK UNIFIED IDEOGRAPH-76B9 +U+76BA(2,3);U+76BA(2,3); # 66-18, CJK UNIFIED IDEOGRAPH-76BA +U+76BF(2,3);U+76BF(2,3); # 27-14, CJK UNIFIED IDEOGRAPH-76BF +U+76C2(2,3);U+76C2(2,3); # 66-19, CJK UNIFIED IDEOGRAPH-76C2 +U+76C3(2,3);U+76C3(2,3); # 39-54, CJK UNIFIED IDEOGRAPH-76C3 +U+76C6(2,3);U+76C6(2,3); # 43-63, CJK UNIFIED IDEOGRAPH-76C6 +U+76C8(2,3);U+76C8(2,3); # 17-46, CJK UNIFIED IDEOGRAPH-76C8 +U+76CA(2,3);U+76CA(2,3); # 17-55, CJK UNIFIED IDEOGRAPH-76CA +U+76CD(2,3);U+76CD(2,3); # 66-20, CJK UNIFIED IDEOGRAPH-76CD +U+76D2(2,3);U+76D2(2,3); # 66-22, CJK UNIFIED IDEOGRAPH-76D2 +U+76D6(2,3);U+76D6(2,3); # 66-21, CJK UNIFIED IDEOGRAPH-76D6 +U+76D7(2,3);U+76D7(2,3); # 37-80, CJK UNIFIED IDEOGRAPH-76D7 +U+76DB(2,3);U+76DB(2,3); # 32-25, CJK UNIFIED IDEOGRAPH-76DB +U+76DC(2,3);U+76DC(2,3); # 61-25, CJK UNIFIED IDEOGRAPH-76DC +U+76DE(2,3);U+76DE(2,3); # 66-23, CJK UNIFIED IDEOGRAPH-76DE +U+76DF(2,3);U+76DF(2,3); # 44-33, CJK UNIFIED IDEOGRAPH-76DF +U+76E1(2,3);U+76E1(2,3); # 66-24, CJK UNIFIED IDEOGRAPH-76E1 +U+76E3(2,3);U+76E3(2,3); # 20-38, CJK UNIFIED IDEOGRAPH-76E3 +U+76E4(2,3);U+76E4(2,3); # 40-55, CJK UNIFIED IDEOGRAPH-76E4 +U+76E5(2,3);U+76E5(2,3); # 66-25, CJK UNIFIED IDEOGRAPH-76E5 +U+76E7(2,3);U+76E7(2,3); # 66-26, CJK UNIFIED IDEOGRAPH-76E7 +U+76EA(2,3);U+76EA(2,3); # 66-27, CJK UNIFIED IDEOGRAPH-76EA +U+76EE(2,3);U+76EE(2,3); # 44-60, CJK UNIFIED IDEOGRAPH-76EE +U+76F2(2,3);U+76F2(2,3); # 44-53, CJK UNIFIED IDEOGRAPH-76F2 +U+76F4(2,3);U+76F4(2,3); # 36-30, CJK UNIFIED IDEOGRAPH-76F4 +U+76F8(2,3);U+76F8(2,3); # 33-74, CJK UNIFIED IDEOGRAPH-76F8 +U+76FB(2,3);U+76FB(2,3); # 66-29, CJK UNIFIED IDEOGRAPH-76FB +U+76FE(2,3);U+76FE(2,3); # 29-66, CJK UNIFIED IDEOGRAPH-76FE +U+7701(2,3);U+7701(2,3); # 30-42, CJK UNIFIED IDEOGRAPH-7701 +U+7704(2,3);U+7704(2,3); # 66-32, CJK UNIFIED IDEOGRAPH-7704 +U+7707(2,3);U+7707(2,3); # 66-31, CJK UNIFIED IDEOGRAPH-7707 +U+7708(2,3);U+7708(2,3); # 66-30, CJK UNIFIED IDEOGRAPH-7708 +U+7709(2,3);U+7709(2,3); # 40-93, CJK UNIFIED IDEOGRAPH-7709 +U+770B(2,3);U+770B(2,3); # 20-39, CJK UNIFIED IDEOGRAPH-770B +U+770C(2,3);U+770C(2,3); # 24-09, CJK UNIFIED IDEOGRAPH-770C +U+771B(2,3);U+771B(2,3); # 66-38, CJK UNIFIED IDEOGRAPH-771B +U+771E(2,3);U+771E(2,3); # 66-35, CJK UNIFIED IDEOGRAPH-771E +U+771F(2,3);U+771F(2,3); # 31-31, CJK UNIFIED IDEOGRAPH-771F +U+7720(2,3);U+7720(2,3); # 44-18, CJK UNIFIED IDEOGRAPH-7720 +U+7724(2,3);U+7724(2,3); # 66-34, CJK UNIFIED IDEOGRAPH-7724 +U+7725(2,3);U+7725(2,3); # 66-36, CJK UNIFIED IDEOGRAPH-7725 +U+7726(2,3);U+7726(2,3); # 66-37, CJK UNIFIED IDEOGRAPH-7726 +U+7729(2,3);U+7729(2,3); # 66-33, CJK UNIFIED IDEOGRAPH-7729 +U+7737(2,3);U+7737(2,3); # 66-39, CJK UNIFIED IDEOGRAPH-7737 +U+7738(2,3);U+7738(2,3); # 66-40, CJK UNIFIED IDEOGRAPH-7738 +U+773A(2,3);U+773A(2,3); # 36-15, CJK UNIFIED IDEOGRAPH-773A +U+773C(2,3);U+773C(2,3); # 20-67, CJK UNIFIED IDEOGRAPH-773C +U+7740(2,3);U+7740(2,3); # 35-69, CJK UNIFIED IDEOGRAPH-7740 +U+7747(2,3);U+7747(2,3); # 66-41, CJK UNIFIED IDEOGRAPH-7747 +U+775A(2,3);U+775A(2,3); # 66-42, CJK UNIFIED IDEOGRAPH-775A +U+775B(2,3);U+775B(2,3); # 66-45, CJK UNIFIED IDEOGRAPH-775B +U+7761(2,3);U+7761(2,3); # 31-71, CJK UNIFIED IDEOGRAPH-7761 +U+7763(2,3);U+7763(2,3); # 38-36, CJK UNIFIED IDEOGRAPH-7763 +U+7765(2,3);U+7765(2,3); # 66-46, CJK UNIFIED IDEOGRAPH-7765 +U+7766(2,3);U+7766(2,3); # 43-51, CJK UNIFIED IDEOGRAPH-7766 +U+7768(2,3);U+7768(2,3); # 66-43, CJK UNIFIED IDEOGRAPH-7768 +U+776B(2,3);U+776B(2,3); # 66-44, CJK UNIFIED IDEOGRAPH-776B +U+7779(2,3);U+7779(2,3); # 66-49, CJK UNIFIED IDEOGRAPH-7779 +U+777E(2,3);U+777E(2,3); # 66-48, CJK UNIFIED IDEOGRAPH-777E +U+777F(2,3);U+777F(2,3); # 66-47, CJK UNIFIED IDEOGRAPH-777F +U+778B(2,3);U+778B(2,3); # 66-51, CJK UNIFIED IDEOGRAPH-778B +U+778E(2,3);U+778E(2,3); # 66-50, CJK UNIFIED IDEOGRAPH-778E +U+7791(2,3);U+7791(2,3); # 66-52, CJK UNIFIED IDEOGRAPH-7791 +U+779E(2,3);U+779E(2,3); # 66-54, CJK UNIFIED IDEOGRAPH-779E +U+77A0(2,3);U+77A0(2,3); # 66-53, CJK UNIFIED IDEOGRAPH-77A0 +U+77A5(2,3);U+77A5(2,3); # 42-45, CJK UNIFIED IDEOGRAPH-77A5 +U+77AC(2,3);U+77AC(2,3); # 29-54, CJK UNIFIED IDEOGRAPH-77AC +U+77AD(2,3);U+77AD(2,3); # 46-38, CJK UNIFIED IDEOGRAPH-77AD +U+77B0(2,3);U+77B0(2,3); # 66-55, CJK UNIFIED IDEOGRAPH-77B0 +U+77B3(2,3);U+77B3(2,3); # 38-23, CJK UNIFIED IDEOGRAPH-77B3 +U+77B6(2,3);U+77B6(2,3); # 66-56, CJK UNIFIED IDEOGRAPH-77B6 +U+77B9(2,3);U+77B9(2,3); # 66-57, CJK UNIFIED IDEOGRAPH-77B9 +U+77BB(2,3);U+77BB(2,3); # 66-61, CJK UNIFIED IDEOGRAPH-77BB +U+77BC(2,3);U+77BC(2,3); # 66-59, CJK UNIFIED IDEOGRAPH-77BC +U+77BD(2,3);U+77BD(2,3); # 66-60, CJK UNIFIED IDEOGRAPH-77BD +U+77BF(2,3);U+77BF(2,3); # 66-58, CJK UNIFIED IDEOGRAPH-77BF +U+77C7(2,3);U+77C7(2,3); # 66-62, CJK UNIFIED IDEOGRAPH-77C7 +U+77CD(2,3);U+77CD(2,3); # 66-63, CJK UNIFIED IDEOGRAPH-77CD +U+77D7(2,3);U+77D7(2,3); # 66-64, CJK UNIFIED IDEOGRAPH-77D7 +U+77DA(2,3);U+77DA(2,3); # 66-65, CJK UNIFIED IDEOGRAPH-77DA +U+77DB(2,3);U+77DB(2,3); # 44-23, CJK UNIFIED IDEOGRAPH-77DB +U+77DC(2,3);U+77DC(2,3); # 66-66, CJK UNIFIED IDEOGRAPH-77DC +U+77E2(2,3);U+77E2(2,3); # 44-80, CJK UNIFIED IDEOGRAPH-77E2 +U+77E3(2,3);U+77E3(2,3); # 66-67, CJK UNIFIED IDEOGRAPH-77E3 +U+77E5(2,3);U+77E5(2,3); # 35-46, CJK UNIFIED IDEOGRAPH-77E5 +U+77E7(2,3);U+77E7(2,3); # 39-74, CJK UNIFIED IDEOGRAPH-77E7 +U+77E9(2,3);U+77E9(2,3); # 22-75, CJK UNIFIED IDEOGRAPH-77E9 +U+77ED(2,3);U+77ED(2,3); # 35-27, CJK UNIFIED IDEOGRAPH-77ED +U+77EE(2,3);U+77EE(2,3); # 66-68, CJK UNIFIED IDEOGRAPH-77EE +U+77EF(2,3);U+77EF(2,3); # 22-26, CJK UNIFIED IDEOGRAPH-77EF +U+77F3(2,3);U+77F3(2,3); # 32-48, CJK UNIFIED IDEOGRAPH-77F3 +U+77FC(2,3);U+77FC(2,3); # 66-69, CJK UNIFIED IDEOGRAPH-77FC +U+7802(2,3);U+7802(2,3); # 26-29, CJK UNIFIED IDEOGRAPH-7802 +U+780C(2,3);U+780C(2,3); # 66-70, CJK UNIFIED IDEOGRAPH-780C +U+7812(2,3);U+7812(2,3); # 66-71, CJK UNIFIED IDEOGRAPH-7812 +U+7814(2,3);U+7814(2,3); # 24-06, CJK UNIFIED IDEOGRAPH-7814 +U+7815(2,3);U+7815(2,3); # 26-53, CJK UNIFIED IDEOGRAPH-7815 +U+7820(2,3);U+7820(2,3); # 66-73, CJK UNIFIED IDEOGRAPH-7820 +U+7825(2,3);U+7825(2,3); # 37-54, CJK UNIFIED IDEOGRAPH-7825 +U+7826(2,3);U+7826(2,3); # 26-54, CJK UNIFIED IDEOGRAPH-7826 +U+7827(2,3);U+7827(2,3); # 21-46, CJK UNIFIED IDEOGRAPH-7827 +U+7832(2,3);U+7832(2,3); # 43-04, CJK UNIFIED IDEOGRAPH-7832 +U+7834(2,3);U+7834(2,3); # 39-43, CJK UNIFIED IDEOGRAPH-7834 +U+783A(2,3);U+783A(2,3); # 37-55, CJK UNIFIED IDEOGRAPH-783A +U+783F(2,3);U+783F(2,3); # 25-60, CJK UNIFIED IDEOGRAPH-783F +U+7845(2,3);U+7845(2,3); # 66-75, CJK UNIFIED IDEOGRAPH-7845 +U+785D(2,3);U+785D(2,3); # 30-43, CJK UNIFIED IDEOGRAPH-785D +U+786B(2,3);U+786B(2,3); # 46-18, CJK UNIFIED IDEOGRAPH-786B +U+786C(2,3);U+786C(2,3); # 25-37, CJK UNIFIED IDEOGRAPH-786C +U+786F(2,3);U+786F(2,3); # 24-07, CJK UNIFIED IDEOGRAPH-786F +U+7872(2,3);U+7872(2,3); # 40-03, CJK UNIFIED IDEOGRAPH-7872 +U+7874(2,3);U+7874(2,3); # 66-77, CJK UNIFIED IDEOGRAPH-7874 +U+787C(2,3);U+787C(2,3); # 66-79, CJK UNIFIED IDEOGRAPH-787C +U+7881(2,3);U+7881(2,3); # 24-75, CJK UNIFIED IDEOGRAPH-7881 +U+7886(2,3);U+7886(2,3); # 66-78, CJK UNIFIED IDEOGRAPH-7886 +U+7887(2,3);U+7887(2,3); # 36-86, CJK UNIFIED IDEOGRAPH-7887 +U+788C(2,3);U+788C(2,3); # 66-81, CJK UNIFIED IDEOGRAPH-788C +U+788D(2,3);U+788D(2,3); # 19-23, CJK UNIFIED IDEOGRAPH-788D +U+788E(2,3);U+788E(2,3); # 66-76, CJK UNIFIED IDEOGRAPH-788E +U+7891(2,3);U+7891(2,3); # 40-74, CJK UNIFIED IDEOGRAPH-7891 +U+7893(2,3);U+7893(2,3); # 17-16, CJK UNIFIED IDEOGRAPH-7893 +U+7895(2,3);U+7895(2,3); # 26-76, CJK UNIFIED IDEOGRAPH-7895 +U+7897(2,3);U+7897(2,3); # 47-50, CJK UNIFIED IDEOGRAPH-7897 +U+789A(2,3);U+789A(2,3); # 66-80, CJK UNIFIED IDEOGRAPH-789A +U+78A3(2,3);U+78A3(2,3); # 66-82, CJK UNIFIED IDEOGRAPH-78A3 +U+78A7(2,3);U+78A7(2,3); # 42-43, CJK UNIFIED IDEOGRAPH-78A7 +U+78A9(2,3);U+78A9(2,3); # 32-57, CJK UNIFIED IDEOGRAPH-78A9 +U+78AA(2,3);U+78AA(2,3); # 66-84, CJK UNIFIED IDEOGRAPH-78AA +U+78AF(2,3);U+78AF(2,3); # 66-85, CJK UNIFIED IDEOGRAPH-78AF +U+78B5(2,3);U+78B5(2,3); # 66-83, CJK UNIFIED IDEOGRAPH-78B5 +U+78BA(2,3);U+78BA(2,3); # 19-46, CJK UNIFIED IDEOGRAPH-78BA +U+78BC(2,3);U+78BC(2,3); # 66-91, CJK UNIFIED IDEOGRAPH-78BC +U+78BE(2,3);U+78BE(2,3); # 66-90, CJK UNIFIED IDEOGRAPH-78BE +U+78C1(2,3);U+78C1(2,3); # 28-07, CJK UNIFIED IDEOGRAPH-78C1 +U+78C5(2,3);U+78C5(2,3); # 66-92, CJK UNIFIED IDEOGRAPH-78C5 +U+78C6(2,3);U+78C6(2,3); # 66-87, CJK UNIFIED IDEOGRAPH-78C6 +U+78CA(2,3);U+78CA(2,3); # 66-93, CJK UNIFIED IDEOGRAPH-78CA +U+78CB(2,3);U+78CB(2,3); # 66-88, CJK UNIFIED IDEOGRAPH-78CB +U+78D0(2,3);U+78D0(2,3); # 40-56, CJK UNIFIED IDEOGRAPH-78D0 +U+78D1(2,3);U+78D1(2,3); # 66-86, CJK UNIFIED IDEOGRAPH-78D1 +U+78D4(2,3);U+78D4(2,3); # 66-89, CJK UNIFIED IDEOGRAPH-78D4 +U+78DA(2,3);U+78DA(2,3); # 67-02, CJK UNIFIED IDEOGRAPH-78DA +U+78E7(2,3);U+78E7(2,3); # 67-01, CJK UNIFIED IDEOGRAPH-78E7 +U+78E8(2,3);U+78E8(2,3); # 43-65, CJK UNIFIED IDEOGRAPH-78E8 +U+78EC(2,3);U+78EC(2,3); # 66-94, CJK UNIFIED IDEOGRAPH-78EC +U+78EF(2,3);U+78EF(2,3); # 16-75, CJK UNIFIED IDEOGRAPH-78EF +U+78F4(2,3);U+78F4(2,3); # 67-04, CJK UNIFIED IDEOGRAPH-78F4 +U+78FD(2,3);U+78FD(2,3); # 67-03, CJK UNIFIED IDEOGRAPH-78FD +U+7901(2,3);U+7901(2,3); # 30-44, CJK UNIFIED IDEOGRAPH-7901 +U+7907(2,3);U+7907(2,3); # 67-05, CJK UNIFIED IDEOGRAPH-7907 +U+790E(2,3);U+790E(2,3); # 33-35, CJK UNIFIED IDEOGRAPH-790E +U+7911(2,3);U+7911(2,3); # 67-07, CJK UNIFIED IDEOGRAPH-7911 +U+7912(2,3);U+7912(2,3); # 67-06, CJK UNIFIED IDEOGRAPH-7912 +U+7919(2,3);U+7919(2,3); # 67-08, CJK UNIFIED IDEOGRAPH-7919 +U+7926(2,3);U+7926(2,3); # 66-72, CJK UNIFIED IDEOGRAPH-7926 +U+792A(2,3);U+792A(2,3); # 66-74, CJK UNIFIED IDEOGRAPH-792A +U+792B(2,3);U+792B(2,3); # 67-10, CJK UNIFIED IDEOGRAPH-792B +U+792C(2,3);U+792C(2,3); # 67-09, CJK UNIFIED IDEOGRAPH-792C +U+793A(2,3);U+793A(2,3); # 28-08, CJK UNIFIED IDEOGRAPH-793A +U+793C(2,3);U+793C(2,3); # 46-73, CJK UNIFIED IDEOGRAPH-793C +U+793E(2,3);U+793E(2,3); # 28-50, CJK UNIFIED IDEOGRAPH-793E +U+7940(2,3);U+7940(2,3); # 67-11, CJK UNIFIED IDEOGRAPH-7940 +U+7941(2,3);U+7941(2,3); # 23-23, CJK UNIFIED IDEOGRAPH-7941 +U+7947(2,3);U+7947(2,3); # 21-32, CJK UNIFIED IDEOGRAPH-7947 +U+7948(2,3);U+7948(2,3); # 21-07, CJK UNIFIED IDEOGRAPH-7948 +U+7949(2,3);U+7949(2,3); # 27-67, CJK UNIFIED IDEOGRAPH-7949 +U+7950(2,3);U+7950(2,3); # 45-20, CJK UNIFIED IDEOGRAPH-7950 +U+7953(2,3);U+7953(2,3); # 67-17, CJK UNIFIED IDEOGRAPH-7953 +U+7955(2,3);U+7955(2,3); # 67-16, CJK UNIFIED IDEOGRAPH-7955 +U+7956(2,3);U+7956(2,3); # 33-36, CJK UNIFIED IDEOGRAPH-7956 +U+7957(2,3);U+7957(2,3); # 67-13, CJK UNIFIED IDEOGRAPH-7957 +U+795A(2,3);U+795A(2,3); # 67-15, CJK UNIFIED IDEOGRAPH-795A +U+795D(2,3);U+795D(2,3); # 29-43, CJK UNIFIED IDEOGRAPH-795D +U+795E(2,3);U+795E(2,3); # 31-32, CJK UNIFIED IDEOGRAPH-795E +U+795F(2,3);U+795F(2,3); # 67-14, CJK UNIFIED IDEOGRAPH-795F +U+7960(2,3);U+7960(2,3); # 67-12, CJK UNIFIED IDEOGRAPH-7960 +U+7962(2,3);U+7962(2,3); # 39-10, CJK UNIFIED IDEOGRAPH-7962 +U+7965(2,3);U+7965(2,3); # 30-45, CJK UNIFIED IDEOGRAPH-7965 +U+7968(2,3);U+7968(2,3); # 41-28, CJK UNIFIED IDEOGRAPH-7968 +U+796D(2,3);U+796D(2,3); # 26-55, CJK UNIFIED IDEOGRAPH-796D +U+7977(2,3);U+7977(2,3); # 37-88, CJK UNIFIED IDEOGRAPH-7977 +U+797A(2,3);U+797A(2,3); # 67-18, CJK UNIFIED IDEOGRAPH-797A +U+797F(2,3);U+797F(2,3); # 67-19, CJK UNIFIED IDEOGRAPH-797F +U+7980(2,3);U+7980(2,3); # 67-41, CJK UNIFIED IDEOGRAPH-7980 +U+7981(2,3);U+7981(2,3); # 22-56, CJK UNIFIED IDEOGRAPH-7981 +U+7984(2,3);U+7984(2,3); # 47-29, CJK UNIFIED IDEOGRAPH-7984 +U+7985(2,3);U+7985(2,3); # 33-21, CJK UNIFIED IDEOGRAPH-7985 +U+798A(2,3);U+798A(2,3); # 67-20, CJK UNIFIED IDEOGRAPH-798A +U+798D(2,3);U+798D(2,3); # 18-50, CJK UNIFIED IDEOGRAPH-798D +U+798E(2,3);U+798E(2,3); # 36-87, CJK UNIFIED IDEOGRAPH-798E +U+798F(2,3);U+798F(2,3); # 42-01, CJK UNIFIED IDEOGRAPH-798F +U+799D(2,3);U+799D(2,3); # 67-21, CJK UNIFIED IDEOGRAPH-799D +U+79A6(2,3);U+79A6(2,3); # 21-90, CJK UNIFIED IDEOGRAPH-79A6 +U+79A7(2,3);U+79A7(2,3); # 67-22, CJK UNIFIED IDEOGRAPH-79A7 +U+79AA(2,3);U+79AA(2,3); # 67-24, CJK UNIFIED IDEOGRAPH-79AA +U+79AE(2,3);U+79AE(2,3); # 67-25, CJK UNIFIED IDEOGRAPH-79AE +U+79B0(2,3);U+79B0(2,3); # 39-09, CJK UNIFIED IDEOGRAPH-79B0 +U+79B3(2,3);U+79B3(2,3); # 67-26, CJK UNIFIED IDEOGRAPH-79B3 +U+79B9(2,3);U+79B9(2,3); # 67-27, CJK UNIFIED IDEOGRAPH-79B9 +U+79BA(2,3);U+79BA(2,3); # 67-28, CJK UNIFIED IDEOGRAPH-79BA +U+79BD(2,3);U+79BD(2,3); # 22-57, CJK UNIFIED IDEOGRAPH-79BD +U+79BE(2,3);U+79BE(2,3); # 18-51, CJK UNIFIED IDEOGRAPH-79BE +U+79BF(2,3);U+79BF(2,3); # 38-37, CJK UNIFIED IDEOGRAPH-79BF +U+79C0(2,3);U+79C0(2,3); # 29-08, CJK UNIFIED IDEOGRAPH-79C0 +U+79C1(2,3);U+79C1(2,3); # 27-68, CJK UNIFIED IDEOGRAPH-79C1 +U+79C9(2,3);U+79C9(2,3); # 67-29, CJK UNIFIED IDEOGRAPH-79C9 +U+79CB(2,3);U+79CB(2,3); # 29-09, CJK UNIFIED IDEOGRAPH-79CB +U+79D1(2,3);U+79D1(2,3); # 18-42, CJK UNIFIED IDEOGRAPH-79D1 +U+79D2(2,3);U+79D2(2,3); # 41-35, CJK UNIFIED IDEOGRAPH-79D2 +U+79D5(2,3);U+79D5(2,3); # 67-30, CJK UNIFIED IDEOGRAPH-79D5 +U+79D8(2,3);U+79D8(2,3); # 40-75, CJK UNIFIED IDEOGRAPH-79D8 +U+79DF(2,3);U+79DF(2,3); # 33-37, CJK UNIFIED IDEOGRAPH-79DF +U+79E1(2,3);U+79E1(2,3); # 67-33, CJK UNIFIED IDEOGRAPH-79E1 +U+79E3(2,3);U+79E3(2,3); # 67-34, CJK UNIFIED IDEOGRAPH-79E3 +U+79E4(2,3);U+79E4(2,3); # 39-73, CJK UNIFIED IDEOGRAPH-79E4 +U+79E6(2,3);U+79E6(2,3); # 31-33, CJK UNIFIED IDEOGRAPH-79E6 +U+79E7(2,3);U+79E7(2,3); # 67-31, CJK UNIFIED IDEOGRAPH-79E7 +U+79E9(2,3);U+79E9(2,3); # 35-65, CJK UNIFIED IDEOGRAPH-79E9 +U+79EC(2,3);U+79EC(2,3); # 67-32, CJK UNIFIED IDEOGRAPH-79EC +U+79F0(2,3);U+79F0(2,3); # 30-46, CJK UNIFIED IDEOGRAPH-79F0 +U+79FB(2,3);U+79FB(2,3); # 16-60, CJK UNIFIED IDEOGRAPH-79FB +U+7A00(2,3);U+7A00(2,3); # 21-09, CJK UNIFIED IDEOGRAPH-7A00 +U+7A08(2,3);U+7A08(2,3); # 67-35, CJK UNIFIED IDEOGRAPH-7A08 +U+7A0B(2,3);U+7A0B(2,3); # 36-88, CJK UNIFIED IDEOGRAPH-7A0B +U+7A0D(2,3);U+7A0D(2,3); # 67-36, CJK UNIFIED IDEOGRAPH-7A0D +U+7A0E(2,3);U+7A0E(2,3); # 32-39, CJK UNIFIED IDEOGRAPH-7A0E +U+7A14(2,3);U+7A14(2,3); # 44-13, CJK UNIFIED IDEOGRAPH-7A14 +U+7A17(2,3);U+7A17(2,3); # 41-03, CJK UNIFIED IDEOGRAPH-7A17 +U+7A18(2,3);U+7A18(2,3); # 67-37, CJK UNIFIED IDEOGRAPH-7A18 +U+7A19(2,3);U+7A19(2,3); # 67-38, CJK UNIFIED IDEOGRAPH-7A19 +U+7A1A(2,3);U+7A1A(2,3); # 35-53, CJK UNIFIED IDEOGRAPH-7A1A +U+7A1C(2,3);U+7A1C(2,3); # 46-39, CJK UNIFIED IDEOGRAPH-7A1C +U+7A1F(2,3);U+7A1F(2,3); # 67-40, CJK UNIFIED IDEOGRAPH-7A1F +U+7A20(2,3);U+7A20(2,3); # 67-39, CJK UNIFIED IDEOGRAPH-7A20 +U+7A2E(2,3);U+7A2E(2,3); # 28-79, CJK UNIFIED IDEOGRAPH-7A2E +U+7A31(2,3);U+7A31(2,3); # 67-42, CJK UNIFIED IDEOGRAPH-7A31 +U+7A32(2,3);U+7A32(2,3); # 16-80, CJK UNIFIED IDEOGRAPH-7A32 +U+7A37(2,3);U+7A37(2,3); # 67-45, CJK UNIFIED IDEOGRAPH-7A37 +U+7A3B(2,3);U+7A3B(2,3); # 67-43, CJK UNIFIED IDEOGRAPH-7A3B +U+7A3C(2,3);U+7A3C(2,3); # 18-52, CJK UNIFIED IDEOGRAPH-7A3C +U+7A3D(2,3);U+7A3D(2,3); # 23-46, CJK UNIFIED IDEOGRAPH-7A3D +U+7A3E(2,3);U+7A3E(2,3); # 67-44, CJK UNIFIED IDEOGRAPH-7A3E +U+7A3F(2,3);U+7A3F(2,3); # 25-38, CJK UNIFIED IDEOGRAPH-7A3F +U+7A40(2,3);U+7A40(2,3); # 25-82, CJK UNIFIED IDEOGRAPH-7A40 +U+7A42(2,3);U+7A42(2,3); # 42-70, CJK UNIFIED IDEOGRAPH-7A42 +U+7A43(2,3);U+7A43(2,3); # 67-46, CJK UNIFIED IDEOGRAPH-7A43 +U+7A46(2,3);U+7A46(2,3); # 43-52, CJK UNIFIED IDEOGRAPH-7A46 +U+7A49(2,3);U+7A49(2,3); # 67-48, CJK UNIFIED IDEOGRAPH-7A49 +U+7A4D(2,3);U+7A4D(2,3); # 32-49, CJK UNIFIED IDEOGRAPH-7A4D +U+7A4E(2,3);U+7A4E(2,3); # 17-47, CJK UNIFIED IDEOGRAPH-7A4E +U+7A4F(2,3);U+7A4F(2,3); # 18-26, CJK UNIFIED IDEOGRAPH-7A4F +U+7A50(2,3);U+7A50(2,3); # 16-12, CJK UNIFIED IDEOGRAPH-7A50 +U+7A57(2,3);U+7A57(2,3); # 67-47, CJK UNIFIED IDEOGRAPH-7A57 +U+7A61(2,3);U+7A61(2,3); # 67-49, CJK UNIFIED IDEOGRAPH-7A61 +U+7A62(2,3);U+7A62(2,3); # 67-50, CJK UNIFIED IDEOGRAPH-7A62 +U+7A63(2,3);U+7A63(2,3); # 30-87, CJK UNIFIED IDEOGRAPH-7A63 +U+7A69(2,3);U+7A69(2,3); # 67-51, CJK UNIFIED IDEOGRAPH-7A69 +U+7A6B(2,3);U+7A6B(2,3); # 19-47, CJK UNIFIED IDEOGRAPH-7A6B +U+7A70(2,3);U+7A70(2,3); # 67-53, CJK UNIFIED IDEOGRAPH-7A70 +U+7A74(2,3);U+7A74(2,3); # 23-74, CJK UNIFIED IDEOGRAPH-7A74 +U+7A76(2,3);U+7A76(2,3); # 21-70, CJK UNIFIED IDEOGRAPH-7A76 +U+7A79(2,3);U+7A79(2,3); # 67-54, CJK UNIFIED IDEOGRAPH-7A79 +U+7A7A(2,3);U+7A7A(2,3); # 22-85, CJK UNIFIED IDEOGRAPH-7A7A +U+7A7D(2,3);U+7A7D(2,3); # 67-55, CJK UNIFIED IDEOGRAPH-7A7D +U+7A7F(2,3);U+7A7F(2,3); # 32-92, CJK UNIFIED IDEOGRAPH-7A7F +U+7A81(2,3);U+7A81(2,3); # 38-45, CJK UNIFIED IDEOGRAPH-7A81 +U+7A83(2,3);U+7A83(2,3); # 32-64, CJK UNIFIED IDEOGRAPH-7A83 +U+7A84(2,3);U+7A84(2,3); # 26-85, CJK UNIFIED IDEOGRAPH-7A84 +U+7A88(2,3);U+7A88(2,3); # 67-56, CJK UNIFIED IDEOGRAPH-7A88 +U+7A92(2,3);U+7A92(2,3); # 35-66, CJK UNIFIED IDEOGRAPH-7A92 +U+7A93(2,3);U+7A93(2,3); # 33-75, CJK UNIFIED IDEOGRAPH-7A93 +U+7A95(2,3);U+7A95(2,3); # 67-58, CJK UNIFIED IDEOGRAPH-7A95 +U+7A96(2,3);U+7A96(2,3); # 67-60, CJK UNIFIED IDEOGRAPH-7A96 +U+7A97(2,3);U+7A97(2,3); # 67-57, CJK UNIFIED IDEOGRAPH-7A97 +U+7A98(2,3);U+7A98(2,3); # 67-59, CJK UNIFIED IDEOGRAPH-7A98 +U+7A9F(2,3);U+7A9F(2,3); # 23-02, CJK UNIFIED IDEOGRAPH-7A9F +U+7AA9(2,3);U+7AA9(2,3); # 67-61, CJK UNIFIED IDEOGRAPH-7AA9 +U+7AAA(2,3);U+7AAA(2,3); # 23-06, CJK UNIFIED IDEOGRAPH-7AAA +U+7AAE(2,3);U+7AAE(2,3); # 21-71, CJK UNIFIED IDEOGRAPH-7AAE +U+7AAF(2,3);U+7AAF(2,3); # 45-50, CJK UNIFIED IDEOGRAPH-7AAF +U+7AB0(2,3);U+7AB0(2,3); # 67-63, CJK UNIFIED IDEOGRAPH-7AB0 +U+7AB6(2,3);U+7AB6(2,3); # 67-64, CJK UNIFIED IDEOGRAPH-7AB6 +U+7ABA(2,3);U+7ABA(2,3); # 17-14, CJK UNIFIED IDEOGRAPH-7ABA +U+7ABF(2,3);U+7ABF(2,3); # 67-67, CJK UNIFIED IDEOGRAPH-7ABF +U+7AC3(2,3);U+7AC3(2,3); # 19-86, CJK UNIFIED IDEOGRAPH-7AC3 +U+7AC4(2,3);U+7AC4(2,3); # 67-66, CJK UNIFIED IDEOGRAPH-7AC4 +U+7AC5(2,3);U+7AC5(2,3); # 67-65, CJK UNIFIED IDEOGRAPH-7AC5 +U+7AC7(2,3);U+7AC7(2,3); # 67-69, CJK UNIFIED IDEOGRAPH-7AC7 +U+7AC8(2,3);U+7AC8(2,3); # 67-62, CJK UNIFIED IDEOGRAPH-7AC8 +U+7ACA(2,3);U+7ACA(2,3); # 67-70, CJK UNIFIED IDEOGRAPH-7ACA +U+7ACB(2,3);U+7ACB(2,3); # 46-09, CJK UNIFIED IDEOGRAPH-7ACB +U+7ACD(2,3);U+7ACD(2,3); # 67-71, CJK UNIFIED IDEOGRAPH-7ACD +U+7ACF(2,3);U+7ACF(2,3); # 67-72, CJK UNIFIED IDEOGRAPH-7ACF +U+7AD2(2,3);U+7AD2(2,3); # 52-84, CJK UNIFIED IDEOGRAPH-7AD2 +U+7AD3(2,3);U+7AD3(2,3); # 67-74, CJK UNIFIED IDEOGRAPH-7AD3 +U+7AD5(2,3);U+7AD5(2,3); # 67-73, CJK UNIFIED IDEOGRAPH-7AD5 +U+7AD9(2,3);U+7AD9(2,3); # 67-75, CJK UNIFIED IDEOGRAPH-7AD9 +U+7ADA(2,3);U+7ADA(2,3); # 67-76, CJK UNIFIED IDEOGRAPH-7ADA +U+7ADC(2,3);U+7ADC(2,3); # 46-21, CJK UNIFIED IDEOGRAPH-7ADC +U+7ADD(2,3);U+7ADD(2,3); # 67-77, CJK UNIFIED IDEOGRAPH-7ADD +U+7ADF(2,3);U+7ADF(2,3); # 80-79, CJK UNIFIED IDEOGRAPH-7ADF +U+7AE0(2,3);U+7AE0(2,3); # 30-47, CJK UNIFIED IDEOGRAPH-7AE0 +U+7AE1(2,3);U+7AE1(2,3); # 67-78, CJK UNIFIED IDEOGRAPH-7AE1 +U+7AE2(2,3);U+7AE2(2,3); # 67-79, CJK UNIFIED IDEOGRAPH-7AE2 +U+7AE3(2,3);U+7AE3(2,3); # 29-55, CJK UNIFIED IDEOGRAPH-7AE3 +U+7AE5(2,3);U+7AE5(2,3); # 38-24, CJK UNIFIED IDEOGRAPH-7AE5 +U+7AE6(2,3);U+7AE6(2,3); # 67-80, CJK UNIFIED IDEOGRAPH-7AE6 +U+7AEA(2,3);U+7AEA(2,3); # 35-08, CJK UNIFIED IDEOGRAPH-7AEA +U+7AED(2,3);U+7AED(2,3); # 67-81, CJK UNIFIED IDEOGRAPH-7AED +U+7AEF(2,3);U+7AEF(2,3); # 35-28, CJK UNIFIED IDEOGRAPH-7AEF +U+7AF0(2,3);U+7AF0(2,3); # 67-82, CJK UNIFIED IDEOGRAPH-7AF0 +U+7AF6(2,3);U+7AF6(2,3); # 22-05, CJK UNIFIED IDEOGRAPH-7AF6 +U+7AF8(2,3);U+7AF8(2,3); # 49-31, CJK UNIFIED IDEOGRAPH-7AF8 +U+7AF9(2,3);U+7AF9(2,3); # 35-61, CJK UNIFIED IDEOGRAPH-7AF9 +U+7AFA(2,3);U+7AFA(2,3); # 28-19, CJK UNIFIED IDEOGRAPH-7AFA +U+7AFF(2,3);U+7AFF(2,3); # 20-40, CJK UNIFIED IDEOGRAPH-7AFF +U+7B02(2,3);U+7B02(2,3); # 67-83, CJK UNIFIED IDEOGRAPH-7B02 +U+7B04(2,3);U+7B04(2,3); # 68-02, CJK UNIFIED IDEOGRAPH-7B04 +U+7B06(2,3);U+7B06(2,3); # 67-86, CJK UNIFIED IDEOGRAPH-7B06 +U+7B08(2,3);U+7B08(2,3); # 21-72, CJK UNIFIED IDEOGRAPH-7B08 +U+7B0A(2,3);U+7B0A(2,3); # 67-85, CJK UNIFIED IDEOGRAPH-7B0A +U+7B0B(2,3);U+7B0B(2,3); # 68-04, CJK UNIFIED IDEOGRAPH-7B0B +U+7B0F(2,3);U+7B0F(2,3); # 67-84, CJK UNIFIED IDEOGRAPH-7B0F +U+7B11(2,3);U+7B11(2,3); # 30-48, CJK UNIFIED IDEOGRAPH-7B11 +U+7B18(2,3);U+7B18(2,3); # 67-88, CJK UNIFIED IDEOGRAPH-7B18 +U+7B19(2,3);U+7B19(2,3); # 67-89, CJK UNIFIED IDEOGRAPH-7B19 +U+7B1B(2,3);U+7B1B(2,3); # 37-11, CJK UNIFIED IDEOGRAPH-7B1B +U+7B1E(2,3);U+7B1E(2,3); # 67-90, CJK UNIFIED IDEOGRAPH-7B1E +U+7B20(2,3);U+7B20(2,3); # 19-62, CJK UNIFIED IDEOGRAPH-7B20 +U+7B25(2,3);U+7B25(2,3); # 31-58, CJK UNIFIED IDEOGRAPH-7B25 +U+7B26(2,3);U+7B26(2,3); # 41-68, CJK UNIFIED IDEOGRAPH-7B26 +U+7B28(2,3);U+7B28(2,3); # 67-92, CJK UNIFIED IDEOGRAPH-7B28 +U+7B2C(2,3);U+7B2C(2,3); # 34-72, CJK UNIFIED IDEOGRAPH-7B2C +U+7B33(2,3);U+7B33(2,3); # 67-87, CJK UNIFIED IDEOGRAPH-7B33 +U+7B35(2,3);U+7B35(2,3); # 67-91, CJK UNIFIED IDEOGRAPH-7B35 +U+7B36(2,3);U+7B36(2,3); # 67-93, CJK UNIFIED IDEOGRAPH-7B36 +U+7B39(2,3);U+7B39(2,3); # 26-91, CJK UNIFIED IDEOGRAPH-7B39 +U+7B45(2,3);U+7B45(2,3); # 68-06, CJK UNIFIED IDEOGRAPH-7B45 +U+7B46(2,3);U+7B46(2,3); # 41-14, CJK UNIFIED IDEOGRAPH-7B46 +U+7B48(2,3);U+7B48(2,3); # 40-06, CJK UNIFIED IDEOGRAPH-7B48 +U+7B49(2,3);U+7B49(2,3); # 37-89, CJK UNIFIED IDEOGRAPH-7B49 +U+7B4B(2,3);U+7B4B(2,3); # 22-58, CJK UNIFIED IDEOGRAPH-7B4B +U+7B4C(2,3);U+7B4C(2,3); # 68-05, CJK UNIFIED IDEOGRAPH-7B4C +U+7B4D(2,3);U+7B4D(2,3); # 68-03, CJK UNIFIED IDEOGRAPH-7B4D +U+7B4F(2,3);U+7B4F(2,3); # 40-21, CJK UNIFIED IDEOGRAPH-7B4F +U+7B50(2,3);U+7B50(2,3); # 67-94, CJK UNIFIED IDEOGRAPH-7B50 +U+7B51(2,3);U+7B51(2,3); # 35-62, CJK UNIFIED IDEOGRAPH-7B51 +U+7B52(2,3);U+7B52(2,3); # 37-91, CJK UNIFIED IDEOGRAPH-7B52 +U+7B54(2,3);U+7B54(2,3); # 37-90, CJK UNIFIED IDEOGRAPH-7B54 +U+7B56(2,3);U+7B56(2,3); # 26-86, CJK UNIFIED IDEOGRAPH-7B56 +U+7B5D(2,3);U+7B5D(2,3); # 68-24, CJK UNIFIED IDEOGRAPH-7B5D +U+7B65(2,3);U+7B65(2,3); # 68-08, CJK UNIFIED IDEOGRAPH-7B65 +U+7B67(2,3);U+7B67(2,3); # 68-10, CJK UNIFIED IDEOGRAPH-7B67 +U+7B6C(2,3);U+7B6C(2,3); # 68-13, CJK UNIFIED IDEOGRAPH-7B6C +U+7B6E(2,3);U+7B6E(2,3); # 68-14, CJK UNIFIED IDEOGRAPH-7B6E +U+7B70(2,3);U+7B70(2,3); # 68-11, CJK UNIFIED IDEOGRAPH-7B70 +U+7B71(2,3);U+7B71(2,3); # 68-12, CJK UNIFIED IDEOGRAPH-7B71 +U+7B74(2,3);U+7B74(2,3); # 68-09, CJK UNIFIED IDEOGRAPH-7B74 +U+7B75(2,3);U+7B75(2,3); # 68-07, CJK UNIFIED IDEOGRAPH-7B75 +U+7B7A(2,3);U+7B7A(2,3); # 68-01, CJK UNIFIED IDEOGRAPH-7B7A +U+7B86(2,3);U+7B86(2,3); # 42-47, CJK UNIFIED IDEOGRAPH-7B86 +U+7B87(2,3);U+7B87(2,3); # 18-53, CJK UNIFIED IDEOGRAPH-7B87 +U+7B8B(2,3);U+7B8B(2,3); # 68-21, CJK UNIFIED IDEOGRAPH-7B8B +U+7B8D(2,3);U+7B8D(2,3); # 68-18, CJK UNIFIED IDEOGRAPH-7B8D +U+7B8F(2,3);U+7B8F(2,3); # 68-23, CJK UNIFIED IDEOGRAPH-7B8F +U+7B92(2,3);U+7B92(2,3); # 68-22, CJK UNIFIED IDEOGRAPH-7B92 +U+7B94(2,3);U+7B94(2,3); # 39-83, CJK UNIFIED IDEOGRAPH-7B94 +U+7B95(2,3);U+7B95(2,3); # 44-07, CJK UNIFIED IDEOGRAPH-7B95 +U+7B97(2,3);U+7B97(2,3); # 27-27, CJK UNIFIED IDEOGRAPH-7B97 +U+7B98(2,3);U+7B98(2,3); # 68-16, CJK UNIFIED IDEOGRAPH-7B98 +U+7B99(2,3);U+7B99(2,3); # 68-25, CJK UNIFIED IDEOGRAPH-7B99 +U+7B9A(2,3);U+7B9A(2,3); # 68-20, CJK UNIFIED IDEOGRAPH-7B9A +U+7B9C(2,3);U+7B9C(2,3); # 68-19, CJK UNIFIED IDEOGRAPH-7B9C +U+7B9D(2,3);U+7B9D(2,3); # 68-15, CJK UNIFIED IDEOGRAPH-7B9D +U+7B9F(2,3);U+7B9F(2,3); # 68-17, CJK UNIFIED IDEOGRAPH-7B9F +U+7BA1(2,3);U+7BA1(2,3); # 20-41, CJK UNIFIED IDEOGRAPH-7BA1 +U+7BAA(2,3);U+7BAA(2,3); # 35-29, CJK UNIFIED IDEOGRAPH-7BAA +U+7BAD(2,3);U+7BAD(2,3); # 32-93, CJK UNIFIED IDEOGRAPH-7BAD +U+7BB1(2,3);U+7BB1(2,3); # 40-02, CJK UNIFIED IDEOGRAPH-7BB1 +U+7BB4(2,3);U+7BB4(2,3); # 68-30, CJK UNIFIED IDEOGRAPH-7BB4 +U+7BB8(2,3);U+7BB8(2,3); # 40-04, CJK UNIFIED IDEOGRAPH-7BB8 +U+7BC0(2,3);U+7BC0(2,3); # 32-65, CJK UNIFIED IDEOGRAPH-7BC0 +U+7BC1(2,3);U+7BC1(2,3); # 68-27, CJK UNIFIED IDEOGRAPH-7BC1 +U+7BC4(2,3);U+7BC4(2,3); # 40-47, CJK UNIFIED IDEOGRAPH-7BC4 +U+7BC6(2,3);U+7BC6(2,3); # 68-31, CJK UNIFIED IDEOGRAPH-7BC6 +U+7BC7(2,3);U+7BC7(2,3); # 42-51, CJK UNIFIED IDEOGRAPH-7BC7 +U+7BC9(2,3);U+7BC9(2,3); # 35-59, CJK UNIFIED IDEOGRAPH-7BC9 +U+7BCB(2,3);U+7BCB(2,3); # 68-26, CJK UNIFIED IDEOGRAPH-7BCB +U+7BCC(2,3);U+7BCC(2,3); # 68-28, CJK UNIFIED IDEOGRAPH-7BCC +U+7BCF(2,3);U+7BCF(2,3); # 68-29, CJK UNIFIED IDEOGRAPH-7BCF +U+7BDD(2,3);U+7BDD(2,3); # 68-32, CJK UNIFIED IDEOGRAPH-7BDD +U+7BE0(2,3);U+7BE0(2,3); # 28-36, CJK UNIFIED IDEOGRAPH-7BE0 +U+7BE4(2,3);U+7BE4(2,3); # 38-38, CJK UNIFIED IDEOGRAPH-7BE4 +U+7BE5(2,3);U+7BE5(2,3); # 68-37, CJK UNIFIED IDEOGRAPH-7BE5 +U+7BE6(2,3);U+7BE6(2,3); # 68-36, CJK UNIFIED IDEOGRAPH-7BE6 +U+7BE9(2,3);U+7BE9(2,3); # 68-33, CJK UNIFIED IDEOGRAPH-7BE9 +U+7BED(2,3);U+7BED(2,3); # 47-22, CJK UNIFIED IDEOGRAPH-7BED +U+7BF3(2,3);U+7BF3(2,3); # 68-42, CJK UNIFIED IDEOGRAPH-7BF3 +U+7BF6(2,3);U+7BF6(2,3); # 68-46, CJK UNIFIED IDEOGRAPH-7BF6 +U+7BF7(2,3);U+7BF7(2,3); # 68-43, CJK UNIFIED IDEOGRAPH-7BF7 +U+7C00(2,3);U+7C00(2,3); # 68-39, CJK UNIFIED IDEOGRAPH-7C00 +U+7C07(2,3);U+7C07(2,3); # 68-40, CJK UNIFIED IDEOGRAPH-7C07 +U+7C0D(2,3);U+7C0D(2,3); # 68-45, CJK UNIFIED IDEOGRAPH-7C0D +U+7C11(2,3);U+7C11(2,3); # 68-34, CJK UNIFIED IDEOGRAPH-7C11 +U+7C12(2,3);U+7C12(2,3); # 50-53, CJK UNIFIED IDEOGRAPH-7C12 +U+7C13(2,3);U+7C13(2,3); # 68-41, CJK UNIFIED IDEOGRAPH-7C13 +U+7C14(2,3);U+7C14(2,3); # 68-35, CJK UNIFIED IDEOGRAPH-7C14 +U+7C17(2,3);U+7C17(2,3); # 68-44, CJK UNIFIED IDEOGRAPH-7C17 +U+7C1F(2,3);U+7C1F(2,3); # 68-50, CJK UNIFIED IDEOGRAPH-7C1F +U+7C21(2,3);U+7C21(2,3); # 20-42, CJK UNIFIED IDEOGRAPH-7C21 +U+7C23(2,3);U+7C23(2,3); # 68-47, CJK UNIFIED IDEOGRAPH-7C23 +U+7C27(2,3);U+7C27(2,3); # 68-48, CJK UNIFIED IDEOGRAPH-7C27 +U+7C2A(2,3);U+7C2A(2,3); # 68-49, CJK UNIFIED IDEOGRAPH-7C2A +U+7C2B(2,3);U+7C2B(2,3); # 68-52, CJK UNIFIED IDEOGRAPH-7C2B +U+7C37(2,3);U+7C37(2,3); # 68-51, CJK UNIFIED IDEOGRAPH-7C37 +U+7C38(2,3);U+7C38(2,3); # 40-86, CJK UNIFIED IDEOGRAPH-7C38 +U+7C3D(2,3);U+7C3D(2,3); # 68-53, CJK UNIFIED IDEOGRAPH-7C3D +U+7C3E(2,3);U+7C3E(2,3); # 46-92, CJK UNIFIED IDEOGRAPH-7C3E +U+7C3F(2,3);U+7C3F(2,3); # 42-77, CJK UNIFIED IDEOGRAPH-7C3F +U+7C40(2,3);U+7C40(2,3); # 68-58, CJK UNIFIED IDEOGRAPH-7C40 +U+7C43(2,3);U+7C43(2,3); # 68-55, CJK UNIFIED IDEOGRAPH-7C43 +U+7C4C(2,3);U+7C4C(2,3); # 68-54, CJK UNIFIED IDEOGRAPH-7C4C +U+7C4D(2,3);U+7C4D(2,3); # 32-50, CJK UNIFIED IDEOGRAPH-7C4D +U+7C4F(2,3);U+7C4F(2,3); # 68-57, CJK UNIFIED IDEOGRAPH-7C4F +U+7C50(2,3);U+7C50(2,3); # 68-59, CJK UNIFIED IDEOGRAPH-7C50 +U+7C54(2,3);U+7C54(2,3); # 68-56, CJK UNIFIED IDEOGRAPH-7C54 +U+7C56(2,3);U+7C56(2,3); # 68-63, CJK UNIFIED IDEOGRAPH-7C56 +U+7C58(2,3);U+7C58(2,3); # 68-60, CJK UNIFIED IDEOGRAPH-7C58 +U+7C5F(2,3);U+7C5F(2,3); # 68-61, CJK UNIFIED IDEOGRAPH-7C5F +U+7C60(2,3);U+7C60(2,3); # 68-38, CJK UNIFIED IDEOGRAPH-7C60 +U+7C64(2,3);U+7C64(2,3); # 68-62, CJK UNIFIED IDEOGRAPH-7C64 +U+7C65(2,3);U+7C65(2,3); # 68-64, CJK UNIFIED IDEOGRAPH-7C65 +U+7C6C(2,3);U+7C6C(2,3); # 68-65, CJK UNIFIED IDEOGRAPH-7C6C +U+7C73(2,3);U+7C73(2,3); # 42-38, CJK UNIFIED IDEOGRAPH-7C73 +U+7C75(2,3);U+7C75(2,3); # 68-66, CJK UNIFIED IDEOGRAPH-7C75 +U+7C7E(2,3);U+7C7E(2,3); # 44-66, CJK UNIFIED IDEOGRAPH-7C7E +U+7C81(2,3);U+7C81(2,3); # 22-46, CJK UNIFIED IDEOGRAPH-7C81 +U+7C82(2,3);U+7C82(2,3); # 23-09, CJK UNIFIED IDEOGRAPH-7C82 +U+7C83(2,3);U+7C83(2,3); # 68-67, CJK UNIFIED IDEOGRAPH-7C83 +U+7C89(2,3);U+7C89(2,3); # 42-20, CJK UNIFIED IDEOGRAPH-7C89 +U+7C8B(2,3);U+7C8B(2,3); # 31-72, CJK UNIFIED IDEOGRAPH-7C8B +U+7C8D(2,3);U+7C8D(2,3); # 44-16, CJK UNIFIED IDEOGRAPH-7C8D +U+7C90(2,3);U+7C90(2,3); # 68-68, CJK UNIFIED IDEOGRAPH-7C90 +U+7C92(2,3);U+7C92(2,3); # 46-19, CJK UNIFIED IDEOGRAPH-7C92 +U+7C95(2,3);U+7C95(2,3); # 39-84, CJK UNIFIED IDEOGRAPH-7C95 +U+7C97(2,3);U+7C97(2,3); # 33-38, CJK UNIFIED IDEOGRAPH-7C97 +U+7C98(2,3);U+7C98(2,3); # 39-20, CJK UNIFIED IDEOGRAPH-7C98 +U+7C9B(2,3);U+7C9B(2,3); # 29-45, CJK UNIFIED IDEOGRAPH-7C9B +U+7C9F(2,3);U+7C9F(2,3); # 16-32, CJK UNIFIED IDEOGRAPH-7C9F +U+7CA1(2,3);U+7CA1(2,3); # 68-73, CJK UNIFIED IDEOGRAPH-7CA1 +U+7CA2(2,3);U+7CA2(2,3); # 68-71, CJK UNIFIED IDEOGRAPH-7CA2 +U+7CA4(2,3);U+7CA4(2,3); # 68-69, CJK UNIFIED IDEOGRAPH-7CA4 +U+7CA5(2,3);U+7CA5(2,3); # 20-01, CJK UNIFIED IDEOGRAPH-7CA5 +U+7CA7(2,3);U+7CA7(2,3); # 30-49, CJK UNIFIED IDEOGRAPH-7CA7 +U+7CA8(2,3);U+7CA8(2,3); # 68-74, CJK UNIFIED IDEOGRAPH-7CA8 +U+7CAB(2,3);U+7CAB(2,3); # 68-72, CJK UNIFIED IDEOGRAPH-7CAB +U+7CAD(2,3);U+7CAD(2,3); # 68-70, CJK UNIFIED IDEOGRAPH-7CAD +U+7CAE(2,3);U+7CAE(2,3); # 68-78, CJK UNIFIED IDEOGRAPH-7CAE +U+7CB1(2,3);U+7CB1(2,3); # 68-77, CJK UNIFIED IDEOGRAPH-7CB1 +U+7CB2(2,3);U+7CB2(2,3); # 68-76, CJK UNIFIED IDEOGRAPH-7CB2 +U+7CB3(2,3);U+7CB3(2,3); # 68-75, CJK UNIFIED IDEOGRAPH-7CB3 +U+7CB9(2,3);U+7CB9(2,3); # 68-79, CJK UNIFIED IDEOGRAPH-7CB9 +U+7CBD(2,3);U+7CBD(2,3); # 68-80, CJK UNIFIED IDEOGRAPH-7CBD +U+7CBE(2,3);U+7CBE(2,3); # 32-26, CJK UNIFIED IDEOGRAPH-7CBE +U+7CC0(2,3);U+7CC0(2,3); # 68-81, CJK UNIFIED IDEOGRAPH-7CC0 +U+7CC2(2,3);U+7CC2(2,3); # 68-83, CJK UNIFIED IDEOGRAPH-7CC2 +U+7CC5(2,3);U+7CC5(2,3); # 68-82, CJK UNIFIED IDEOGRAPH-7CC5 +U+7CCA(2,3);U+7CCA(2,3); # 24-50, CJK UNIFIED IDEOGRAPH-7CCA +U+7CCE(2,3);U+7CCE(2,3); # 33-24, CJK UNIFIED IDEOGRAPH-7CCE +U+7CD2(2,3);U+7CD2(2,3); # 68-85, CJK UNIFIED IDEOGRAPH-7CD2 +U+7CD6(2,3);U+7CD6(2,3); # 37-92, CJK UNIFIED IDEOGRAPH-7CD6 +U+7CD8(2,3);U+7CD8(2,3); # 68-84, CJK UNIFIED IDEOGRAPH-7CD8 +U+7CDC(2,3);U+7CDC(2,3); # 68-86, CJK UNIFIED IDEOGRAPH-7CDC +U+7CDE(2,3);U+7CDE(2,3); # 42-21, CJK UNIFIED IDEOGRAPH-7CDE +U+7CDF(2,3);U+7CDF(2,3); # 33-76, CJK UNIFIED IDEOGRAPH-7CDF +U+7CE0(2,3);U+7CE0(2,3); # 25-39, CJK UNIFIED IDEOGRAPH-7CE0 +U+7CE2(2,3);U+7CE2(2,3); # 68-87, CJK UNIFIED IDEOGRAPH-7CE2 +U+7CE7(2,3);U+7CE7(2,3); # 46-40, CJK UNIFIED IDEOGRAPH-7CE7 +U+7CEF(2,3);U+7CEF(2,3); # 68-89, CJK UNIFIED IDEOGRAPH-7CEF +U+7CF2(2,3);U+7CF2(2,3); # 68-90, CJK UNIFIED IDEOGRAPH-7CF2 +U+7CF4(2,3);U+7CF4(2,3); # 68-91, CJK UNIFIED IDEOGRAPH-7CF4 +U+7CF6(2,3);U+7CF6(2,3); # 68-92, CJK UNIFIED IDEOGRAPH-7CF6 +U+7CF8(2,3);U+7CF8(2,3); # 27-69, CJK UNIFIED IDEOGRAPH-7CF8 +U+7CFA(2,3);U+7CFA(2,3); # 68-93, CJK UNIFIED IDEOGRAPH-7CFA +U+7CFB(2,3);U+7CFB(2,3); # 23-47, CJK UNIFIED IDEOGRAPH-7CFB +U+7CFE(2,3);U+7CFE(2,3); # 21-74, CJK UNIFIED IDEOGRAPH-7CFE +U+7D00(2,3);U+7D00(2,3); # 21-10, CJK UNIFIED IDEOGRAPH-7D00 +U+7D02(2,3);U+7D02(2,3); # 69-01, CJK UNIFIED IDEOGRAPH-7D02 +U+7D04(2,3);U+7D04(2,3); # 44-83, CJK UNIFIED IDEOGRAPH-7D04 +U+7D05(2,3);U+7D05(2,3); # 25-40, CJK UNIFIED IDEOGRAPH-7D05 +U+7D06(2,3);U+7D06(2,3); # 68-94, CJK UNIFIED IDEOGRAPH-7D06 +U+7D0A(2,3);U+7D0A(2,3); # 69-04, CJK UNIFIED IDEOGRAPH-7D0A +U+7D0B(2,3);U+7D0B(2,3); # 44-70, CJK UNIFIED IDEOGRAPH-7D0B +U+7D0D(2,3);U+7D0D(2,3); # 39-28, CJK UNIFIED IDEOGRAPH-7D0D +U+7D10(2,3);U+7D10(2,3); # 41-19, CJK UNIFIED IDEOGRAPH-7D10 +U+7D14(2,3);U+7D14(2,3); # 29-67, CJK UNIFIED IDEOGRAPH-7D14 +U+7D15(2,3);U+7D15(2,3); # 69-03, CJK UNIFIED IDEOGRAPH-7D15 +U+7D17(2,3);U+7D17(2,3); # 28-51, CJK UNIFIED IDEOGRAPH-7D17 +U+7D18(2,3);U+7D18(2,3); # 25-41, CJK UNIFIED IDEOGRAPH-7D18 +U+7D19(2,3);U+7D19(2,3); # 27-70, CJK UNIFIED IDEOGRAPH-7D19 +U+7D1A(2,3);U+7D1A(2,3); # 21-73, CJK UNIFIED IDEOGRAPH-7D1A +U+7D1B(2,3);U+7D1B(2,3); # 42-22, CJK UNIFIED IDEOGRAPH-7D1B +U+7D1C(2,3);U+7D1C(2,3); # 69-02, CJK UNIFIED IDEOGRAPH-7D1C +U+7D20(2,3);U+7D20(2,3); # 33-39, CJK UNIFIED IDEOGRAPH-7D20 +U+7D21(2,3);U+7D21(2,3); # 43-34, CJK UNIFIED IDEOGRAPH-7D21 +U+7D22(2,3);U+7D22(2,3); # 26-87, CJK UNIFIED IDEOGRAPH-7D22 +U+7D2B(2,3);U+7D2B(2,3); # 27-71, CJK UNIFIED IDEOGRAPH-7D2B +U+7D2C(2,3);U+7D2C(2,3); # 36-61, CJK UNIFIED IDEOGRAPH-7D2C +U+7D2E(2,3);U+7D2E(2,3); # 69-07, CJK UNIFIED IDEOGRAPH-7D2E +U+7D2F(2,3);U+7D2F(2,3); # 46-63, CJK UNIFIED IDEOGRAPH-7D2F +U+7D30(2,3);U+7D30(2,3); # 26-57, CJK UNIFIED IDEOGRAPH-7D30 +U+7D32(2,3);U+7D32(2,3); # 69-08, CJK UNIFIED IDEOGRAPH-7D32 +U+7D33(2,3);U+7D33(2,3); # 31-34, CJK UNIFIED IDEOGRAPH-7D33 +U+7D35(2,3);U+7D35(2,3); # 69-10, CJK UNIFIED IDEOGRAPH-7D35 +U+7D39(2,3);U+7D39(2,3); # 30-50, CJK UNIFIED IDEOGRAPH-7D39 +U+7D3A(2,3);U+7D3A(2,3); # 26-16, CJK UNIFIED IDEOGRAPH-7D3A +U+7D3F(2,3);U+7D3F(2,3); # 69-09, CJK UNIFIED IDEOGRAPH-7D3F +U+7D42(2,3);U+7D42(2,3); # 29-10, CJK UNIFIED IDEOGRAPH-7D42 +U+7D43(2,3);U+7D43(2,3); # 24-30, CJK UNIFIED IDEOGRAPH-7D43 +U+7D44(2,3);U+7D44(2,3); # 33-40, CJK UNIFIED IDEOGRAPH-7D44 +U+7D45(2,3);U+7D45(2,3); # 69-05, CJK UNIFIED IDEOGRAPH-7D45 +U+7D46(2,3);U+7D46(2,3); # 69-11, CJK UNIFIED IDEOGRAPH-7D46 +U+7D4B(2,3);U+7D4B(2,3); # 69-06, CJK UNIFIED IDEOGRAPH-7D4B +U+7D4C(2,3);U+7D4C(2,3); # 23-48, CJK UNIFIED IDEOGRAPH-7D4C +U+7D4E(2,3);U+7D4E(2,3); # 69-14, CJK UNIFIED IDEOGRAPH-7D4E +U+7D4F(2,3);U+7D4F(2,3); # 69-18, CJK UNIFIED IDEOGRAPH-7D4F +U+7D50(2,3);U+7D50(2,3); # 23-75, CJK UNIFIED IDEOGRAPH-7D50 +U+7D56(2,3);U+7D56(2,3); # 69-13, CJK UNIFIED IDEOGRAPH-7D56 +U+7D5B(2,3);U+7D5B(2,3); # 69-22, CJK UNIFIED IDEOGRAPH-7D5B +U+7D5E(2,3);U+7D5E(2,3); # 25-42, CJK UNIFIED IDEOGRAPH-7D5E +U+7D61(2,3);U+7D61(2,3); # 45-77, CJK UNIFIED IDEOGRAPH-7D61 +U+7D62(2,3);U+7D62(2,3); # 16-28, CJK UNIFIED IDEOGRAPH-7D62 +U+7D63(2,3);U+7D63(2,3); # 69-19, CJK UNIFIED IDEOGRAPH-7D63 +U+7D66(2,3);U+7D66(2,3); # 21-75, CJK UNIFIED IDEOGRAPH-7D66 +U+7D68(2,3);U+7D68(2,3); # 69-16, CJK UNIFIED IDEOGRAPH-7D68 +U+7D6E(2,3);U+7D6E(2,3); # 69-17, CJK UNIFIED IDEOGRAPH-7D6E +U+7D71(2,3);U+7D71(2,3); # 37-93, CJK UNIFIED IDEOGRAPH-7D71 +U+7D72(2,3);U+7D72(2,3); # 69-15, CJK UNIFIED IDEOGRAPH-7D72 +U+7D73(2,3);U+7D73(2,3); # 69-12, CJK UNIFIED IDEOGRAPH-7D73 +U+7D75(2,3);U+7D75(2,3); # 19-08, CJK UNIFIED IDEOGRAPH-7D75 +U+7D76(2,3);U+7D76(2,3); # 32-68, CJK UNIFIED IDEOGRAPH-7D76 +U+7D79(2,3);U+7D79(2,3); # 24-08, CJK UNIFIED IDEOGRAPH-7D79 +U+7D7D(2,3);U+7D7D(2,3); # 69-24, CJK UNIFIED IDEOGRAPH-7D7D +U+7D89(2,3);U+7D89(2,3); # 69-21, CJK UNIFIED IDEOGRAPH-7D89 +U+7D8F(2,3);U+7D8F(2,3); # 69-23, CJK UNIFIED IDEOGRAPH-7D8F +U+7D93(2,3);U+7D93(2,3); # 69-20, CJK UNIFIED IDEOGRAPH-7D93 +U+7D99(2,3);U+7D99(2,3); # 23-49, CJK UNIFIED IDEOGRAPH-7D99 +U+7D9A(2,3);U+7D9A(2,3); # 34-19, CJK UNIFIED IDEOGRAPH-7D9A +U+7D9B(2,3);U+7D9B(2,3); # 69-25, CJK UNIFIED IDEOGRAPH-7D9B +U+7D9C(2,3);U+7D9C(2,3); # 33-78, CJK UNIFIED IDEOGRAPH-7D9C +U+7D9F(2,3);U+7D9F(2,3); # 69-38, CJK UNIFIED IDEOGRAPH-7D9F +U+7DA2(2,3);U+7DA2(2,3); # 69-34, CJK UNIFIED IDEOGRAPH-7DA2 +U+7DA3(2,3);U+7DA3(2,3); # 69-28, CJK UNIFIED IDEOGRAPH-7DA3 +U+7DAB(2,3);U+7DAB(2,3); # 69-32, CJK UNIFIED IDEOGRAPH-7DAB +U+7DAC(2,3);U+7DAC(2,3); # 28-90, CJK UNIFIED IDEOGRAPH-7DAC +U+7DAD(2,3);U+7DAD(2,3); # 16-61, CJK UNIFIED IDEOGRAPH-7DAD +U+7DAE(2,3);U+7DAE(2,3); # 69-27, CJK UNIFIED IDEOGRAPH-7DAE +U+7DAF(2,3);U+7DAF(2,3); # 69-35, CJK UNIFIED IDEOGRAPH-7DAF +U+7DB0(2,3);U+7DB0(2,3); # 69-39, CJK UNIFIED IDEOGRAPH-7DB0 +U+7DB1(2,3);U+7DB1(2,3); # 25-43, CJK UNIFIED IDEOGRAPH-7DB1 +U+7DB2(2,3);U+7DB2(2,3); # 44-54, CJK UNIFIED IDEOGRAPH-7DB2 +U+7DB4(2,3);U+7DB4(2,3); # 36-54, CJK UNIFIED IDEOGRAPH-7DB4 +U+7DB5(2,3);U+7DB5(2,3); # 69-29, CJK UNIFIED IDEOGRAPH-7DB5 +U+7DB8(2,3);U+7DB8(2,3); # 69-37, CJK UNIFIED IDEOGRAPH-7DB8 +U+7DBA(2,3);U+7DBA(2,3); # 69-26, CJK UNIFIED IDEOGRAPH-7DBA +U+7DBB(2,3);U+7DBB(2,3); # 35-30, CJK UNIFIED IDEOGRAPH-7DBB +U+7DBD(2,3);U+7DBD(2,3); # 69-31, CJK UNIFIED IDEOGRAPH-7DBD +U+7DBE(2,3);U+7DBE(2,3); # 16-29, CJK UNIFIED IDEOGRAPH-7DBE +U+7DBF(2,3);U+7DBF(2,3); # 44-42, CJK UNIFIED IDEOGRAPH-7DBF +U+7DC7(2,3);U+7DC7(2,3); # 69-30, CJK UNIFIED IDEOGRAPH-7DC7 +U+7DCA(2,3);U+7DCA(2,3); # 22-59, CJK UNIFIED IDEOGRAPH-7DCA +U+7DCB(2,3);U+7DCB(2,3); # 40-76, CJK UNIFIED IDEOGRAPH-7DCB +U+7DCF(2,3);U+7DCF(2,3); # 33-77, CJK UNIFIED IDEOGRAPH-7DCF +U+7DD1(2,3);U+7DD1(2,3); # 46-48, CJK UNIFIED IDEOGRAPH-7DD1 +U+7DD2(2,3);U+7DD2(2,3); # 29-79, CJK UNIFIED IDEOGRAPH-7DD2 +U+7DD5(2,3);U+7DD5(2,3); # 69-78, CJK UNIFIED IDEOGRAPH-7DD5 +U+7DD8(2,3);U+7DD8(2,3); # 69-40, CJK UNIFIED IDEOGRAPH-7DD8 +U+7DDA(2,3);U+7DDA(2,3); # 32-94, CJK UNIFIED IDEOGRAPH-7DDA +U+7DDC(2,3);U+7DDC(2,3); # 69-36, CJK UNIFIED IDEOGRAPH-7DDC +U+7DDD(2,3);U+7DDD(2,3); # 69-41, CJK UNIFIED IDEOGRAPH-7DDD +U+7DDE(2,3);U+7DDE(2,3); # 69-43, CJK UNIFIED IDEOGRAPH-7DDE +U+7DE0(2,3);U+7DE0(2,3); # 36-89, CJK UNIFIED IDEOGRAPH-7DE0 +U+7DE1(2,3);U+7DE1(2,3); # 69-46, CJK UNIFIED IDEOGRAPH-7DE1 +U+7DE4(2,3);U+7DE4(2,3); # 69-42, CJK UNIFIED IDEOGRAPH-7DE4 +U+7DE8(2,3);U+7DE8(2,3); # 42-52, CJK UNIFIED IDEOGRAPH-7DE8 +U+7DE9(2,3);U+7DE9(2,3); # 20-43, CJK UNIFIED IDEOGRAPH-7DE9 +U+7DEC(2,3);U+7DEC(2,3); # 44-43, CJK UNIFIED IDEOGRAPH-7DEC +U+7DEF(2,3);U+7DEF(2,3); # 16-62, CJK UNIFIED IDEOGRAPH-7DEF +U+7DF2(2,3);U+7DF2(2,3); # 69-45, CJK UNIFIED IDEOGRAPH-7DF2 +U+7DF4(2,3);U+7DF4(2,3); # 46-93, CJK UNIFIED IDEOGRAPH-7DF4 +U+7DFB(2,3);U+7DFB(2,3); # 69-44, CJK UNIFIED IDEOGRAPH-7DFB +U+7E01(2,3);U+7E01(2,3); # 17-79, CJK UNIFIED IDEOGRAPH-7E01 +U+7E04(2,3);U+7E04(2,3); # 38-76, CJK UNIFIED IDEOGRAPH-7E04 +U+7E05(2,3);U+7E05(2,3); # 69-47, CJK UNIFIED IDEOGRAPH-7E05 +U+7E09(2,3);U+7E09(2,3); # 69-54, CJK UNIFIED IDEOGRAPH-7E09 +U+7E0A(2,3);U+7E0A(2,3); # 69-48, CJK UNIFIED IDEOGRAPH-7E0A +U+7E0B(2,3);U+7E0B(2,3); # 69-55, CJK UNIFIED IDEOGRAPH-7E0B +U+7E12(2,3);U+7E12(2,3); # 69-51, CJK UNIFIED IDEOGRAPH-7E12 +U+7E1B(2,3);U+7E1B(2,3); # 39-91, CJK UNIFIED IDEOGRAPH-7E1B +U+7E1E(2,3);U+7E1E(2,3); # 28-42, CJK UNIFIED IDEOGRAPH-7E1E +U+7E1F(2,3);U+7E1F(2,3); # 69-53, CJK UNIFIED IDEOGRAPH-7E1F +U+7E21(2,3);U+7E21(2,3); # 69-50, CJK UNIFIED IDEOGRAPH-7E21 +U+7E22(2,3);U+7E22(2,3); # 69-56, CJK UNIFIED IDEOGRAPH-7E22 +U+7E23(2,3);U+7E23(2,3); # 69-49, CJK UNIFIED IDEOGRAPH-7E23 +U+7E26(2,3);U+7E26(2,3); # 29-36, CJK UNIFIED IDEOGRAPH-7E26 +U+7E2B(2,3);U+7E2B(2,3); # 43-05, CJK UNIFIED IDEOGRAPH-7E2B +U+7E2E(2,3);U+7E2E(2,3); # 29-44, CJK UNIFIED IDEOGRAPH-7E2E +U+7E31(2,3);U+7E31(2,3); # 69-52, CJK UNIFIED IDEOGRAPH-7E31 +U+7E32(2,3);U+7E32(2,3); # 69-64, CJK UNIFIED IDEOGRAPH-7E32 +U+7E35(2,3);U+7E35(2,3); # 69-60, CJK UNIFIED IDEOGRAPH-7E35 +U+7E37(2,3);U+7E37(2,3); # 69-63, CJK UNIFIED IDEOGRAPH-7E37 +U+7E39(2,3);U+7E39(2,3); # 69-61, CJK UNIFIED IDEOGRAPH-7E39 +U+7E3A(2,3);U+7E3A(2,3); # 69-65, CJK UNIFIED IDEOGRAPH-7E3A +U+7E3B(2,3);U+7E3B(2,3); # 69-59, CJK UNIFIED IDEOGRAPH-7E3B +U+7E3D(2,3);U+7E3D(2,3); # 69-33, CJK UNIFIED IDEOGRAPH-7E3D +U+7E3E(2,3);U+7E3E(2,3); # 32-51, CJK UNIFIED IDEOGRAPH-7E3E +U+7E41(2,3);U+7E41(2,3); # 40-43, CJK UNIFIED IDEOGRAPH-7E41 +U+7E43(2,3);U+7E43(2,3); # 69-62, CJK UNIFIED IDEOGRAPH-7E43 +U+7E46(2,3);U+7E46(2,3); # 69-57, CJK UNIFIED IDEOGRAPH-7E46 +U+7E4A(2,3);U+7E4A(2,3); # 33-01, CJK UNIFIED IDEOGRAPH-7E4A +U+7E4B(2,3);U+7E4B(2,3); # 23-50, CJK UNIFIED IDEOGRAPH-7E4B +U+7E4D(2,3);U+7E4D(2,3); # 29-11, CJK UNIFIED IDEOGRAPH-7E4D +U+7E54(2,3);U+7E54(2,3); # 31-05, CJK UNIFIED IDEOGRAPH-7E54 +U+7E55(2,3);U+7E55(2,3); # 33-22, CJK UNIFIED IDEOGRAPH-7E55 +U+7E56(2,3);U+7E56(2,3); # 69-68, CJK UNIFIED IDEOGRAPH-7E56 +U+7E59(2,3);U+7E59(2,3); # 69-70, CJK UNIFIED IDEOGRAPH-7E59 +U+7E5A(2,3);U+7E5A(2,3); # 69-71, CJK UNIFIED IDEOGRAPH-7E5A +U+7E5D(2,3);U+7E5D(2,3); # 69-67, CJK UNIFIED IDEOGRAPH-7E5D +U+7E5E(2,3);U+7E5E(2,3); # 69-69, CJK UNIFIED IDEOGRAPH-7E5E +U+7E66(2,3);U+7E66(2,3); # 69-58, CJK UNIFIED IDEOGRAPH-7E66 +U+7E67(2,3);U+7E67(2,3); # 69-66, CJK UNIFIED IDEOGRAPH-7E67 +U+7E69(2,3);U+7E69(2,3); # 69-74, CJK UNIFIED IDEOGRAPH-7E69 +U+7E6A(2,3);U+7E6A(2,3); # 69-73, CJK UNIFIED IDEOGRAPH-7E6A +U+7E6D(2,3);U+7E6D(2,3); # 43-90, CJK UNIFIED IDEOGRAPH-7E6D +U+7E70(2,3);U+7E70(2,3); # 23-11, CJK UNIFIED IDEOGRAPH-7E70 +U+7E79(2,3);U+7E79(2,3); # 69-72, CJK UNIFIED IDEOGRAPH-7E79 +U+7E7B(2,3);U+7E7B(2,3); # 69-76, CJK UNIFIED IDEOGRAPH-7E7B +U+7E7C(2,3);U+7E7C(2,3); # 69-75, CJK UNIFIED IDEOGRAPH-7E7C +U+7E7D(2,3);U+7E7D(2,3); # 69-79, CJK UNIFIED IDEOGRAPH-7E7D +U+7E7F(2,3);U+7E7F(2,3); # 69-81, CJK UNIFIED IDEOGRAPH-7E7F +U+7E82(2,3);U+7E82(2,3); # 27-28, CJK UNIFIED IDEOGRAPH-7E82 +U+7E83(2,3);U+7E83(2,3); # 69-77, CJK UNIFIED IDEOGRAPH-7E83 +U+7E88(2,3);U+7E88(2,3); # 69-82, CJK UNIFIED IDEOGRAPH-7E88 +U+7E89(2,3);U+7E89(2,3); # 69-83, CJK UNIFIED IDEOGRAPH-7E89 +U+7E8C(2,3);U+7E8C(2,3); # 69-84, CJK UNIFIED IDEOGRAPH-7E8C +U+7E8E(2,3);U+7E8E(2,3); # 69-90, CJK UNIFIED IDEOGRAPH-7E8E +U+7E8F(2,3);U+7E8F(2,3); # 37-27, CJK UNIFIED IDEOGRAPH-7E8F +U+7E90(2,3);U+7E90(2,3); # 69-86, CJK UNIFIED IDEOGRAPH-7E90 +U+7E92(2,3);U+7E92(2,3); # 69-85, CJK UNIFIED IDEOGRAPH-7E92 +U+7E93(2,3);U+7E93(2,3); # 69-87, CJK UNIFIED IDEOGRAPH-7E93 +U+7E94(2,3);U+7E94(2,3); # 69-88, CJK UNIFIED IDEOGRAPH-7E94 +U+7E96(2,3);U+7E96(2,3); # 69-89, CJK UNIFIED IDEOGRAPH-7E96 +U+7E9B(2,3);U+7E9B(2,3); # 69-91, CJK UNIFIED IDEOGRAPH-7E9B +U+7E9C(2,3);U+7E9C(2,3); # 69-92, CJK UNIFIED IDEOGRAPH-7E9C +U+7F36(2,3);U+7F36(2,3); # 20-44, CJK UNIFIED IDEOGRAPH-7F36 +U+7F38(2,3);U+7F38(2,3); # 69-93, CJK UNIFIED IDEOGRAPH-7F38 +U+7F3A(2,3);U+7F3A(2,3); # 69-94, CJK UNIFIED IDEOGRAPH-7F3A +U+7F45(2,3);U+7F45(2,3); # 70-01, CJK UNIFIED IDEOGRAPH-7F45 +U+7F4C(2,3);U+7F4C(2,3); # 70-02, CJK UNIFIED IDEOGRAPH-7F4C +U+7F4D(2,3);U+7F4D(2,3); # 70-03, CJK UNIFIED IDEOGRAPH-7F4D +U+7F4E(2,3);U+7F4E(2,3); # 70-04, CJK UNIFIED IDEOGRAPH-7F4E +U+7F50(2,3);U+7F50(2,3); # 70-05, CJK UNIFIED IDEOGRAPH-7F50 +U+7F51(2,3);U+7F51(2,3); # 70-06, CJK UNIFIED IDEOGRAPH-7F51 +U+7F54(2,3);U+7F54(2,3); # 70-08, CJK UNIFIED IDEOGRAPH-7F54 +U+7F55(2,3);U+7F55(2,3); # 70-07, CJK UNIFIED IDEOGRAPH-7F55 +U+7F58(2,3);U+7F58(2,3); # 70-09, CJK UNIFIED IDEOGRAPH-7F58 +U+7F5F(2,3);U+7F5F(2,3); # 70-10, CJK UNIFIED IDEOGRAPH-7F5F +U+7F60(2,3);U+7F60(2,3); # 70-11, CJK UNIFIED IDEOGRAPH-7F60 +U+7F67(2,3);U+7F67(2,3); # 70-14, CJK UNIFIED IDEOGRAPH-7F67 +U+7F68(2,3);U+7F68(2,3); # 70-12, CJK UNIFIED IDEOGRAPH-7F68 +U+7F69(2,3);U+7F69(2,3); # 70-13, CJK UNIFIED IDEOGRAPH-7F69 +U+7F6A(2,3);U+7F6A(2,3); # 26-65, CJK UNIFIED IDEOGRAPH-7F6A +U+7F6B(2,3);U+7F6B(2,3); # 23-51, CJK UNIFIED IDEOGRAPH-7F6B +U+7F6E(2,3);U+7F6E(2,3); # 35-54, CJK UNIFIED IDEOGRAPH-7F6E +U+7F70(2,3);U+7F70(2,3); # 40-19, CJK UNIFIED IDEOGRAPH-7F70 +U+7F72(2,3);U+7F72(2,3); # 29-80, CJK UNIFIED IDEOGRAPH-7F72 +U+7F75(2,3);U+7F75(2,3); # 39-45, CJK UNIFIED IDEOGRAPH-7F75 +U+7F77(2,3);U+7F77(2,3); # 40-77, CJK UNIFIED IDEOGRAPH-7F77 +U+7F78(2,3);U+7F78(2,3); # 70-15, CJK UNIFIED IDEOGRAPH-7F78 +U+7F79(2,3);U+7F79(2,3); # 56-77, CJK UNIFIED IDEOGRAPH-7F79 +U+7F82(2,3);U+7F82(2,3); # 70-16, CJK UNIFIED IDEOGRAPH-7F82 +U+7F83(2,3);U+7F83(2,3); # 70-18, CJK UNIFIED IDEOGRAPH-7F83 +U+7F85(2,3);U+7F85(2,3); # 45-69, CJK UNIFIED IDEOGRAPH-7F85 +U+7F86(2,3);U+7F86(2,3); # 70-17, CJK UNIFIED IDEOGRAPH-7F86 +U+7F87(2,3);U+7F87(2,3); # 70-20, CJK UNIFIED IDEOGRAPH-7F87 +U+7F88(2,3);U+7F88(2,3); # 70-19, CJK UNIFIED IDEOGRAPH-7F88 +U+7F8A(2,3);U+7F8A(2,3); # 45-51, CJK UNIFIED IDEOGRAPH-7F8A +U+7F8C(2,3);U+7F8C(2,3); # 70-21, CJK UNIFIED IDEOGRAPH-7F8C +U+7F8E(2,3);U+7F8E(2,3); # 40-94, CJK UNIFIED IDEOGRAPH-7F8E +U+7F94(2,3);U+7F94(2,3); # 70-22, CJK UNIFIED IDEOGRAPH-7F94 +U+7F9A(2,3);U+7F9A(2,3); # 70-25, CJK UNIFIED IDEOGRAPH-7F9A +U+7F9D(2,3);U+7F9D(2,3); # 70-24, CJK UNIFIED IDEOGRAPH-7F9D +U+7F9E(2,3);U+7F9E(2,3); # 70-23, CJK UNIFIED IDEOGRAPH-7F9E +U+7FA3(2,3);U+7FA3(2,3); # 70-26, CJK UNIFIED IDEOGRAPH-7FA3 +U+7FA4(2,3);U+7FA4(2,3); # 23-18, CJK UNIFIED IDEOGRAPH-7FA4 +U+7FA8(2,3);U+7FA8(2,3); # 33-02, CJK UNIFIED IDEOGRAPH-7FA8 +U+7FA9(2,3);U+7FA9(2,3); # 21-33, CJK UNIFIED IDEOGRAPH-7FA9 +U+7FAE(2,3);U+7FAE(2,3); # 70-30, CJK UNIFIED IDEOGRAPH-7FAE +U+7FAF(2,3);U+7FAF(2,3); # 70-27, CJK UNIFIED IDEOGRAPH-7FAF +U+7FB2(2,3);U+7FB2(2,3); # 70-28, CJK UNIFIED IDEOGRAPH-7FB2 +U+7FB6(2,3);U+7FB6(2,3); # 70-31, CJK UNIFIED IDEOGRAPH-7FB6 +U+7FB8(2,3);U+7FB8(2,3); # 70-32, CJK UNIFIED IDEOGRAPH-7FB8 +U+7FB9(2,3);U+7FB9(2,3); # 70-29, CJK UNIFIED IDEOGRAPH-7FB9 +U+7FBD(2,3);U+7FBD(2,3); # 17-09, CJK UNIFIED IDEOGRAPH-7FBD +U+7FC1(2,3);U+7FC1(2,3); # 18-07, CJK UNIFIED IDEOGRAPH-7FC1 +U+7FC5(2,3);U+7FC5(2,3); # 70-34, CJK UNIFIED IDEOGRAPH-7FC5 +U+7FC6(2,3);U+7FC6(2,3); # 70-35, CJK UNIFIED IDEOGRAPH-7FC6 +U+7FCA(2,3);U+7FCA(2,3); # 70-36, CJK UNIFIED IDEOGRAPH-7FCA +U+7FCC(2,3);U+7FCC(2,3); # 45-66, CJK UNIFIED IDEOGRAPH-7FCC +U+7FD2(2,3);U+7FD2(2,3); # 29-12, CJK UNIFIED IDEOGRAPH-7FD2 +U+7FD4(2,3);U+7FD4(2,3); # 70-38, CJK UNIFIED IDEOGRAPH-7FD4 +U+7FD5(2,3);U+7FD5(2,3); # 70-37, CJK UNIFIED IDEOGRAPH-7FD5 +U+7FE0(2,3);U+7FE0(2,3); # 31-73, CJK UNIFIED IDEOGRAPH-7FE0 +U+7FE1(2,3);U+7FE1(2,3); # 70-39, CJK UNIFIED IDEOGRAPH-7FE1 +U+7FE6(2,3);U+7FE6(2,3); # 70-40, CJK UNIFIED IDEOGRAPH-7FE6 +U+7FE9(2,3);U+7FE9(2,3); # 70-41, CJK UNIFIED IDEOGRAPH-7FE9 +U+7FEB(2,3);U+7FEB(2,3); # 20-69, CJK UNIFIED IDEOGRAPH-7FEB +U+7FF0(2,3);U+7FF0(2,3); # 20-45, CJK UNIFIED IDEOGRAPH-7FF0 +U+7FF3(2,3);U+7FF3(2,3); # 70-42, CJK UNIFIED IDEOGRAPH-7FF3 +U+7FF9(2,3);U+7FF9(2,3); # 70-43, CJK UNIFIED IDEOGRAPH-7FF9 +U+7FFB(2,3);U+7FFB(2,3); # 43-61, CJK UNIFIED IDEOGRAPH-7FFB +U+7FFC(2,3);U+7FFC(2,3); # 45-67, CJK UNIFIED IDEOGRAPH-7FFC +U+8000(2,3);U+8000(2,3); # 45-52, CJK UNIFIED IDEOGRAPH-8000 +U+8001(2,3);U+8001(2,3); # 47-23, CJK UNIFIED IDEOGRAPH-8001 +U+8003(2,3);U+8003(2,3); # 25-45, CJK UNIFIED IDEOGRAPH-8003 +U+8004(2,3);U+8004(2,3); # 70-46, CJK UNIFIED IDEOGRAPH-8004 +U+8005(2,3);U+8005(2,3); # 28-52, CJK UNIFIED IDEOGRAPH-8005 +U+8006(2,3);U+8006(2,3); # 70-45, CJK UNIFIED IDEOGRAPH-8006 +U+800B(2,3);U+800B(2,3); # 70-47, CJK UNIFIED IDEOGRAPH-800B +U+800C(2,3);U+800C(2,3); # 28-09, CJK UNIFIED IDEOGRAPH-800C +U+8010(2,3);U+8010(2,3); # 34-49, CJK UNIFIED IDEOGRAPH-8010 +U+8012(2,3);U+8012(2,3); # 70-48, CJK UNIFIED IDEOGRAPH-8012 +U+8015(2,3);U+8015(2,3); # 25-44, CJK UNIFIED IDEOGRAPH-8015 +U+8017(2,3);U+8017(2,3); # 44-55, CJK UNIFIED IDEOGRAPH-8017 +U+8018(2,3);U+8018(2,3); # 70-49, CJK UNIFIED IDEOGRAPH-8018 +U+8019(2,3);U+8019(2,3); # 70-50, CJK UNIFIED IDEOGRAPH-8019 +U+801C(2,3);U+801C(2,3); # 70-51, CJK UNIFIED IDEOGRAPH-801C +U+8021(2,3);U+8021(2,3); # 70-52, CJK UNIFIED IDEOGRAPH-8021 +U+8028(2,3);U+8028(2,3); # 70-53, CJK UNIFIED IDEOGRAPH-8028 +U+8033(2,3);U+8033(2,3); # 28-10, CJK UNIFIED IDEOGRAPH-8033 +U+8036(2,3);U+8036(2,3); # 44-77, CJK UNIFIED IDEOGRAPH-8036 +U+803B(2,3);U+803B(2,3); # 70-55, CJK UNIFIED IDEOGRAPH-803B +U+803D(2,3);U+803D(2,3); # 35-31, CJK UNIFIED IDEOGRAPH-803D +U+803F(2,3);U+803F(2,3); # 70-54, CJK UNIFIED IDEOGRAPH-803F +U+8046(2,3);U+8046(2,3); # 70-57, CJK UNIFIED IDEOGRAPH-8046 +U+804A(2,3);U+804A(2,3); # 70-56, CJK UNIFIED IDEOGRAPH-804A +U+8052(2,3);U+8052(2,3); # 70-58, CJK UNIFIED IDEOGRAPH-8052 +U+8056(2,3);U+8056(2,3); # 32-27, CJK UNIFIED IDEOGRAPH-8056 +U+8058(2,3);U+8058(2,3); # 70-59, CJK UNIFIED IDEOGRAPH-8058 +U+805A(2,3);U+805A(2,3); # 70-60, CJK UNIFIED IDEOGRAPH-805A +U+805E(2,3);U+805E(2,3); # 42-25, CJK UNIFIED IDEOGRAPH-805E +U+805F(2,3);U+805F(2,3); # 70-61, CJK UNIFIED IDEOGRAPH-805F +U+8061(2,3);U+8061(2,3); # 33-79, CJK UNIFIED IDEOGRAPH-8061 +U+8062(2,3);U+8062(2,3); # 70-62, CJK UNIFIED IDEOGRAPH-8062 +U+8068(2,3);U+8068(2,3); # 70-63, CJK UNIFIED IDEOGRAPH-8068 +U+806F(2,3);U+806F(2,3); # 46-94, CJK UNIFIED IDEOGRAPH-806F +U+8070(2,3);U+8070(2,3); # 70-66, CJK UNIFIED IDEOGRAPH-8070 +U+8072(2,3);U+8072(2,3); # 70-65, CJK UNIFIED IDEOGRAPH-8072 +U+8073(2,3);U+8073(2,3); # 70-64, CJK UNIFIED IDEOGRAPH-8073 +U+8074(2,3);U+8074(2,3); # 36-16, CJK UNIFIED IDEOGRAPH-8074 +U+8076(2,3);U+8076(2,3); # 70-67, CJK UNIFIED IDEOGRAPH-8076 +U+8077(2,3);U+8077(2,3); # 31-06, CJK UNIFIED IDEOGRAPH-8077 +U+8079(2,3);U+8079(2,3); # 70-68, CJK UNIFIED IDEOGRAPH-8079 +U+807D(2,3);U+807D(2,3); # 70-69, CJK UNIFIED IDEOGRAPH-807D +U+807E(2,3);U+807E(2,3); # 47-24, CJK UNIFIED IDEOGRAPH-807E +U+807F(2,3);U+807F(2,3); # 70-70, CJK UNIFIED IDEOGRAPH-807F +U+8084(2,3);U+8084(2,3); # 70-71, CJK UNIFIED IDEOGRAPH-8084 +U+8085(2,3);U+8085(2,3); # 70-73, CJK UNIFIED IDEOGRAPH-8085 +U+8086(2,3);U+8086(2,3); # 70-72, CJK UNIFIED IDEOGRAPH-8086 +U+8087(2,3);U+8087(2,3); # 40-05, CJK UNIFIED IDEOGRAPH-8087 +U+8089(2,3);U+8089(2,3); # 38-89, CJK UNIFIED IDEOGRAPH-8089 +U+808B(2,3);U+808B(2,3); # 47-30, CJK UNIFIED IDEOGRAPH-808B +U+808C(2,3);U+808C(2,3); # 40-09, CJK UNIFIED IDEOGRAPH-808C +U+8093(2,3);U+8093(2,3); # 70-75, CJK UNIFIED IDEOGRAPH-8093 +U+8096(2,3);U+8096(2,3); # 30-51, CJK UNIFIED IDEOGRAPH-8096 +U+8098(2,3);U+8098(2,3); # 41-10, CJK UNIFIED IDEOGRAPH-8098 +U+809A(2,3);U+809A(2,3); # 70-76, CJK UNIFIED IDEOGRAPH-809A +U+809B(2,3);U+809B(2,3); # 70-74, CJK UNIFIED IDEOGRAPH-809B +U+809D(2,3);U+809D(2,3); # 20-46, CJK UNIFIED IDEOGRAPH-809D +U+80A1(2,3);U+80A1(2,3); # 24-52, CJK UNIFIED IDEOGRAPH-80A1 +U+80A2(2,3);U+80A2(2,3); # 27-72, CJK UNIFIED IDEOGRAPH-80A2 +U+80A5(2,3);U+80A5(2,3); # 40-78, CJK UNIFIED IDEOGRAPH-80A5 +U+80A9(2,3);U+80A9(2,3); # 24-10, CJK UNIFIED IDEOGRAPH-80A9 +U+80AA(2,3);U+80AA(2,3); # 43-35, CJK UNIFIED IDEOGRAPH-80AA +U+80AC(2,3);U+80AC(2,3); # 70-79, CJK UNIFIED IDEOGRAPH-80AC +U+80AD(2,3);U+80AD(2,3); # 70-77, CJK UNIFIED IDEOGRAPH-80AD +U+80AF(2,3);U+80AF(2,3); # 25-46, CJK UNIFIED IDEOGRAPH-80AF +U+80B1(2,3);U+80B1(2,3); # 25-47, CJK UNIFIED IDEOGRAPH-80B1 +U+80B2(2,3);U+80B2(2,3); # 16-73, CJK UNIFIED IDEOGRAPH-80B2 +U+80B4(2,3);U+80B4(2,3); # 26-72, CJK UNIFIED IDEOGRAPH-80B4 +U+80BA(2,3);U+80BA(2,3); # 39-57, CJK UNIFIED IDEOGRAPH-80BA +U+80C3(2,3);U+80C3(2,3); # 16-63, CJK UNIFIED IDEOGRAPH-80C3 +U+80C4(2,3);U+80C4(2,3); # 70-84, CJK UNIFIED IDEOGRAPH-80C4 +U+80C6(2,3);U+80C6(2,3); # 35-32, CJK UNIFIED IDEOGRAPH-80C6 +U+80CC(2,3);U+80CC(2,3); # 39-56, CJK UNIFIED IDEOGRAPH-80CC +U+80CE(2,3);U+80CE(2,3); # 34-59, CJK UNIFIED IDEOGRAPH-80CE +U+80D6(2,3);U+80D6(2,3); # 70-86, CJK UNIFIED IDEOGRAPH-80D6 +U+80D9(2,3);U+80D9(2,3); # 70-82, CJK UNIFIED IDEOGRAPH-80D9 +U+80DA(2,3);U+80DA(2,3); # 70-85, CJK UNIFIED IDEOGRAPH-80DA +U+80DB(2,3);U+80DB(2,3); # 70-80, CJK UNIFIED IDEOGRAPH-80DB +U+80DD(2,3);U+80DD(2,3); # 70-83, CJK UNIFIED IDEOGRAPH-80DD +U+80DE(2,3);U+80DE(2,3); # 43-06, CJK UNIFIED IDEOGRAPH-80DE +U+80E1(2,3);U+80E1(2,3); # 24-53, CJK UNIFIED IDEOGRAPH-80E1 +U+80E4(2,3);U+80E4(2,3); # 16-93, CJK UNIFIED IDEOGRAPH-80E4 +U+80E5(2,3);U+80E5(2,3); # 70-81, CJK UNIFIED IDEOGRAPH-80E5 +U+80EF(2,3);U+80EF(2,3); # 70-88, CJK UNIFIED IDEOGRAPH-80EF +U+80F1(2,3);U+80F1(2,3); # 70-89, CJK UNIFIED IDEOGRAPH-80F1 +U+80F4(2,3);U+80F4(2,3); # 38-25, CJK UNIFIED IDEOGRAPH-80F4 +U+80F8(2,3);U+80F8(2,3); # 22-27, CJK UNIFIED IDEOGRAPH-80F8 +U+80FC(2,3);U+80FC(2,3); # 71-06, CJK UNIFIED IDEOGRAPH-80FC +U+80FD(2,3);U+80FD(2,3); # 39-29, CJK UNIFIED IDEOGRAPH-80FD +U+8102(2,3);U+8102(2,3); # 27-73, CJK UNIFIED IDEOGRAPH-8102 +U+8105(2,3);U+8105(2,3); # 22-28, CJK UNIFIED IDEOGRAPH-8105 +U+8106(2,3);U+8106(2,3); # 32-40, CJK UNIFIED IDEOGRAPH-8106 +U+8107(2,3);U+8107(2,3); # 47-38, CJK UNIFIED IDEOGRAPH-8107 +U+8108(2,3);U+8108(2,3); # 44-14, CJK UNIFIED IDEOGRAPH-8108 +U+8109(2,3);U+8109(2,3); # 70-87, CJK UNIFIED IDEOGRAPH-8109 +U+810A(2,3);U+810A(2,3); # 32-52, CJK UNIFIED IDEOGRAPH-810A +U+811A(2,3);U+811A(2,3); # 21-51, CJK UNIFIED IDEOGRAPH-811A +U+811B(2,3);U+811B(2,3); # 70-90, CJK UNIFIED IDEOGRAPH-811B +U+8123(2,3);U+8123(2,3); # 70-92, CJK UNIFIED IDEOGRAPH-8123 +U+8129(2,3);U+8129(2,3); # 70-91, CJK UNIFIED IDEOGRAPH-8129 +U+812F(2,3);U+812F(2,3); # 70-93, CJK UNIFIED IDEOGRAPH-812F +U+8131(2,3);U+8131(2,3); # 35-06, CJK UNIFIED IDEOGRAPH-8131 +U+8133(2,3);U+8133(2,3); # 39-30, CJK UNIFIED IDEOGRAPH-8133 +U+8139(2,3);U+8139(2,3); # 36-17, CJK UNIFIED IDEOGRAPH-8139 +U+813E(2,3);U+813E(2,3); # 71-03, CJK UNIFIED IDEOGRAPH-813E +U+8146(2,3);U+8146(2,3); # 71-02, CJK UNIFIED IDEOGRAPH-8146 +U+814B(2,3);U+814B(2,3); # 70-94, CJK UNIFIED IDEOGRAPH-814B +U+814E(2,3);U+814E(2,3); # 31-53, CJK UNIFIED IDEOGRAPH-814E +U+8150(2,3);U+8150(2,3); # 41-69, CJK UNIFIED IDEOGRAPH-8150 +U+8151(2,3);U+8151(2,3); # 71-05, CJK UNIFIED IDEOGRAPH-8151 +U+8153(2,3);U+8153(2,3); # 71-04, CJK UNIFIED IDEOGRAPH-8153 +U+8154(2,3);U+8154(2,3); # 25-48, CJK UNIFIED IDEOGRAPH-8154 +U+8155(2,3);U+8155(2,3); # 47-51, CJK UNIFIED IDEOGRAPH-8155 +U+815F(2,3);U+815F(2,3); # 71-21, CJK UNIFIED IDEOGRAPH-815F +U+8165(2,3);U+8165(2,3); # 71-09, CJK UNIFIED IDEOGRAPH-8165 +U+8166(2,3);U+8166(2,3); # 71-10, CJK UNIFIED IDEOGRAPH-8166 +U+816B(2,3);U+816B(2,3); # 28-80, CJK UNIFIED IDEOGRAPH-816B +U+816E(2,3);U+816E(2,3); # 71-08, CJK UNIFIED IDEOGRAPH-816E +U+8170(2,3);U+8170(2,3); # 25-88, CJK UNIFIED IDEOGRAPH-8170 +U+8171(2,3);U+8171(2,3); # 71-07, CJK UNIFIED IDEOGRAPH-8171 +U+8174(2,3);U+8174(2,3); # 71-11, CJK UNIFIED IDEOGRAPH-8174 +U+8178(2,3);U+8178(2,3); # 36-18, CJK UNIFIED IDEOGRAPH-8178 +U+8179(2,3);U+8179(2,3); # 42-02, CJK UNIFIED IDEOGRAPH-8179 +U+817A(2,3);U+817A(2,3); # 33-03, CJK UNIFIED IDEOGRAPH-817A +U+817F(2,3);U+817F(2,3); # 34-60, CJK UNIFIED IDEOGRAPH-817F +U+8180(2,3);U+8180(2,3); # 71-15, CJK UNIFIED IDEOGRAPH-8180 +U+8182(2,3);U+8182(2,3); # 71-16, CJK UNIFIED IDEOGRAPH-8182 +U+8183(2,3);U+8183(2,3); # 71-12, CJK UNIFIED IDEOGRAPH-8183 +U+8188(2,3);U+8188(2,3); # 71-13, CJK UNIFIED IDEOGRAPH-8188 +U+818A(2,3);U+818A(2,3); # 71-14, CJK UNIFIED IDEOGRAPH-818A +U+818F(2,3);U+818F(2,3); # 25-49, CJK UNIFIED IDEOGRAPH-818F +U+8193(2,3);U+8193(2,3); # 71-22, CJK UNIFIED IDEOGRAPH-8193 +U+8195(2,3);U+8195(2,3); # 71-18, CJK UNIFIED IDEOGRAPH-8195 +U+819A(2,3);U+819A(2,3); # 41-70, CJK UNIFIED IDEOGRAPH-819A +U+819C(2,3);U+819C(2,3); # 43-76, CJK UNIFIED IDEOGRAPH-819C +U+819D(2,3);U+819D(2,3); # 41-08, CJK UNIFIED IDEOGRAPH-819D +U+81A0(2,3);U+81A0(2,3); # 71-17, CJK UNIFIED IDEOGRAPH-81A0 +U+81A3(2,3);U+81A3(2,3); # 71-20, CJK UNIFIED IDEOGRAPH-81A3 +U+81A4(2,3);U+81A4(2,3); # 71-19, CJK UNIFIED IDEOGRAPH-81A4 +U+81A8(2,3);U+81A8(2,3); # 43-36, CJK UNIFIED IDEOGRAPH-81A8 +U+81A9(2,3);U+81A9(2,3); # 71-23, CJK UNIFIED IDEOGRAPH-81A9 +U+81B0(2,3);U+81B0(2,3); # 71-24, CJK UNIFIED IDEOGRAPH-81B0 +U+81B3(2,3);U+81B3(2,3); # 33-23, CJK UNIFIED IDEOGRAPH-81B3 +U+81B5(2,3);U+81B5(2,3); # 71-25, CJK UNIFIED IDEOGRAPH-81B5 +U+81B8(2,3);U+81B8(2,3); # 71-27, CJK UNIFIED IDEOGRAPH-81B8 +U+81BA(2,3);U+81BA(2,3); # 71-31, CJK UNIFIED IDEOGRAPH-81BA +U+81BD(2,3);U+81BD(2,3); # 71-28, CJK UNIFIED IDEOGRAPH-81BD +U+81BE(2,3);U+81BE(2,3); # 71-26, CJK UNIFIED IDEOGRAPH-81BE +U+81BF(2,3);U+81BF(2,3); # 39-31, CJK UNIFIED IDEOGRAPH-81BF +U+81C0(2,3);U+81C0(2,3); # 71-29, CJK UNIFIED IDEOGRAPH-81C0 +U+81C2(2,3);U+81C2(2,3); # 71-30, CJK UNIFIED IDEOGRAPH-81C2 +U+81C6(2,3);U+81C6(2,3); # 18-18, CJK UNIFIED IDEOGRAPH-81C6 +U+81C8(2,3);U+81C8(2,3); # 71-37, CJK UNIFIED IDEOGRAPH-81C8 +U+81C9(2,3);U+81C9(2,3); # 71-32, CJK UNIFIED IDEOGRAPH-81C9 +U+81CD(2,3);U+81CD(2,3); # 71-33, CJK UNIFIED IDEOGRAPH-81CD +U+81D1(2,3);U+81D1(2,3); # 71-34, CJK UNIFIED IDEOGRAPH-81D1 +U+81D3(2,3);U+81D3(2,3); # 34-01, CJK UNIFIED IDEOGRAPH-81D3 +U+81D8(2,3);U+81D8(2,3); # 71-36, CJK UNIFIED IDEOGRAPH-81D8 +U+81D9(2,3);U+81D9(2,3); # 71-35, CJK UNIFIED IDEOGRAPH-81D9 +U+81DA(2,3);U+81DA(2,3); # 71-38, CJK UNIFIED IDEOGRAPH-81DA +U+81DF(2,3);U+81DF(2,3); # 71-39, CJK UNIFIED IDEOGRAPH-81DF +U+81E0(2,3);U+81E0(2,3); # 71-40, CJK UNIFIED IDEOGRAPH-81E0 +U+81E3(2,3);U+81E3(2,3); # 31-35, CJK UNIFIED IDEOGRAPH-81E3 +U+81E5(2,3);U+81E5(2,3); # 18-73, CJK UNIFIED IDEOGRAPH-81E5 +U+81E7(2,3);U+81E7(2,3); # 71-41, CJK UNIFIED IDEOGRAPH-81E7 +U+81E8(2,3);U+81E8(2,3); # 46-55, CJK UNIFIED IDEOGRAPH-81E8 +U+81EA(2,3);U+81EA(2,3); # 28-11, CJK UNIFIED IDEOGRAPH-81EA +U+81ED(2,3);U+81ED(2,3); # 29-13, CJK UNIFIED IDEOGRAPH-81ED +U+81F3(2,3);U+81F3(2,3); # 27-74, CJK UNIFIED IDEOGRAPH-81F3 +U+81F4(2,3);U+81F4(2,3); # 35-55, CJK UNIFIED IDEOGRAPH-81F4 +U+81FA(2,3);U+81FA(2,3); # 71-42, CJK UNIFIED IDEOGRAPH-81FA +U+81FB(2,3);U+81FB(2,3); # 71-43, CJK UNIFIED IDEOGRAPH-81FB +U+81FC(2,3);U+81FC(2,3); # 17-17, CJK UNIFIED IDEOGRAPH-81FC +U+81FE(2,3);U+81FE(2,3); # 71-44, CJK UNIFIED IDEOGRAPH-81FE +U+8201(2,3);U+8201(2,3); # 71-45, CJK UNIFIED IDEOGRAPH-8201 +U+8202(2,3);U+8202(2,3); # 71-46, CJK UNIFIED IDEOGRAPH-8202 +U+8205(2,3);U+8205(2,3); # 71-47, CJK UNIFIED IDEOGRAPH-8205 +U+8207(2,3);U+8207(2,3); # 71-48, CJK UNIFIED IDEOGRAPH-8207 +U+8208(2,3);U+8208(2,3); # 22-29, CJK UNIFIED IDEOGRAPH-8208 +U+8209(2,3);U+8209(2,3); # 58-10, CJK UNIFIED IDEOGRAPH-8209 +U+820A(2,3);U+820A(2,3); # 71-49, CJK UNIFIED IDEOGRAPH-820A +U+820C(2,3);U+820C(2,3); # 32-69, CJK UNIFIED IDEOGRAPH-820C +U+820D(2,3);U+820D(2,3); # 71-50, CJK UNIFIED IDEOGRAPH-820D +U+820E(2,3);U+820E(2,3); # 28-43, CJK UNIFIED IDEOGRAPH-820E +U+8210(2,3);U+8210(2,3); # 71-51, CJK UNIFIED IDEOGRAPH-8210 +U+8212(2,3);U+8212(2,3); # 48-16, CJK UNIFIED IDEOGRAPH-8212 +U+8216(2,3);U+8216(2,3); # 71-52, CJK UNIFIED IDEOGRAPH-8216 +U+8217(2,3);U+8217(2,3); # 42-62, CJK UNIFIED IDEOGRAPH-8217 +U+8218(2,3);U+8218(2,3); # 20-60, CJK UNIFIED IDEOGRAPH-8218 +U+821B(2,3);U+821B(2,3); # 33-04, CJK UNIFIED IDEOGRAPH-821B +U+821C(2,3);U+821C(2,3); # 29-56, CJK UNIFIED IDEOGRAPH-821C +U+821E(2,3);U+821E(2,3); # 41-81, CJK UNIFIED IDEOGRAPH-821E +U+821F(2,3);U+821F(2,3); # 29-14, CJK UNIFIED IDEOGRAPH-821F +U+8229(2,3);U+8229(2,3); # 71-53, CJK UNIFIED IDEOGRAPH-8229 +U+822A(2,3);U+822A(2,3); # 25-50, CJK UNIFIED IDEOGRAPH-822A +U+822B(2,3);U+822B(2,3); # 71-54, CJK UNIFIED IDEOGRAPH-822B +U+822C(2,3);U+822C(2,3); # 40-44, CJK UNIFIED IDEOGRAPH-822C +U+822E(2,3);U+822E(2,3); # 71-68, CJK UNIFIED IDEOGRAPH-822E +U+8233(2,3);U+8233(2,3); # 71-56, CJK UNIFIED IDEOGRAPH-8233 +U+8235(2,3);U+8235(2,3); # 34-41, CJK UNIFIED IDEOGRAPH-8235 +U+8236(2,3);U+8236(2,3); # 39-85, CJK UNIFIED IDEOGRAPH-8236 +U+8237(2,3);U+8237(2,3); # 24-31, CJK UNIFIED IDEOGRAPH-8237 +U+8238(2,3);U+8238(2,3); # 71-55, CJK UNIFIED IDEOGRAPH-8238 +U+8239(2,3);U+8239(2,3); # 33-05, CJK UNIFIED IDEOGRAPH-8239 +U+8240(2,3);U+8240(2,3); # 71-57, CJK UNIFIED IDEOGRAPH-8240 +U+8247(2,3);U+8247(2,3); # 36-90, CJK UNIFIED IDEOGRAPH-8247 +U+8258(2,3);U+8258(2,3); # 71-59, CJK UNIFIED IDEOGRAPH-8258 +U+8259(2,3);U+8259(2,3); # 71-58, CJK UNIFIED IDEOGRAPH-8259 +U+825A(2,3);U+825A(2,3); # 71-61, CJK UNIFIED IDEOGRAPH-825A +U+825D(2,3);U+825D(2,3); # 71-60, CJK UNIFIED IDEOGRAPH-825D +U+825F(2,3);U+825F(2,3); # 71-62, CJK UNIFIED IDEOGRAPH-825F +U+8262(2,3);U+8262(2,3); # 71-64, CJK UNIFIED IDEOGRAPH-8262 +U+8264(2,3);U+8264(2,3); # 71-63, CJK UNIFIED IDEOGRAPH-8264 +U+8266(2,3);U+8266(2,3); # 20-47, CJK UNIFIED IDEOGRAPH-8266 +U+8268(2,3);U+8268(2,3); # 71-65, CJK UNIFIED IDEOGRAPH-8268 +U+826A(2,3);U+826A(2,3); # 71-66, CJK UNIFIED IDEOGRAPH-826A +U+826B(2,3);U+826B(2,3); # 71-67, CJK UNIFIED IDEOGRAPH-826B +U+826E(2,3);U+826E(2,3); # 26-17, CJK UNIFIED IDEOGRAPH-826E +U+826F(2,3);U+826F(2,3); # 46-41, CJK UNIFIED IDEOGRAPH-826F +U+8271(2,3);U+8271(2,3); # 71-69, CJK UNIFIED IDEOGRAPH-8271 +U+8272(2,3);U+8272(2,3); # 31-07, CJK UNIFIED IDEOGRAPH-8272 +U+8276(2,3);U+8276(2,3); # 17-80, CJK UNIFIED IDEOGRAPH-8276 +U+8277(2,3);U+8277(2,3); # 71-70, CJK UNIFIED IDEOGRAPH-8277 +U+8278(2,3);U+8278(2,3); # 71-71, CJK UNIFIED IDEOGRAPH-8278 +U+827E(2,3);U+827E(2,3); # 71-72, CJK UNIFIED IDEOGRAPH-827E +U+828B(2,3);U+828B(2,3); # 16-82, CJK UNIFIED IDEOGRAPH-828B +U+828D(2,3);U+828D(2,3); # 71-73, CJK UNIFIED IDEOGRAPH-828D +U+8292(2,3);U+8292(2,3); # 71-74, CJK UNIFIED IDEOGRAPH-8292 +U+8299(2,3);U+8299(2,3); # 41-71, CJK UNIFIED IDEOGRAPH-8299 +U+829D(2,3);U+829D(2,3); # 28-39, CJK UNIFIED IDEOGRAPH-829D +U+829F(2,3);U+829F(2,3); # 71-76, CJK UNIFIED IDEOGRAPH-829F +U+82A5(2,3);U+82A5(2,3); # 19-09, CJK UNIFIED IDEOGRAPH-82A5 +U+82A6(2,3);U+82A6(2,3); # 16-18, CJK UNIFIED IDEOGRAPH-82A6 +U+82AB(2,3);U+82AB(2,3); # 71-75, CJK UNIFIED IDEOGRAPH-82AB +U+82AC(2,3);U+82AC(2,3); # 71-78, CJK UNIFIED IDEOGRAPH-82AC +U+82AD(2,3);U+82AD(2,3); # 39-46, CJK UNIFIED IDEOGRAPH-82AD +U+82AF(2,3);U+82AF(2,3); # 31-36, CJK UNIFIED IDEOGRAPH-82AF +U+82B1(2,3);U+82B1(2,3); # 18-54, CJK UNIFIED IDEOGRAPH-82B1 +U+82B3(2,3);U+82B3(2,3); # 43-07, CJK UNIFIED IDEOGRAPH-82B3 +U+82B8(2,3);U+82B8(2,3); # 23-61, CJK UNIFIED IDEOGRAPH-82B8 +U+82B9(2,3);U+82B9(2,3); # 22-60, CJK UNIFIED IDEOGRAPH-82B9 +U+82BB(2,3);U+82BB(2,3); # 71-77, CJK UNIFIED IDEOGRAPH-82BB +U+82BD(2,3);U+82BD(2,3); # 18-74, CJK UNIFIED IDEOGRAPH-82BD +U+82C5(2,3);U+82C5(2,3); # 20-03, CJK UNIFIED IDEOGRAPH-82C5 +U+82D1(2,3);U+82D1(2,3); # 17-81, CJK UNIFIED IDEOGRAPH-82D1 +U+82D2(2,3);U+82D2(2,3); # 71-82, CJK UNIFIED IDEOGRAPH-82D2 +U+82D3(2,3);U+82D3(2,3); # 46-74, CJK UNIFIED IDEOGRAPH-82D3 +U+82D4(2,3);U+82D4(2,3); # 34-61, CJK UNIFIED IDEOGRAPH-82D4 +U+82D7(2,3);U+82D7(2,3); # 41-36, CJK UNIFIED IDEOGRAPH-82D7 +U+82D9(2,3);U+82D9(2,3); # 71-94, CJK UNIFIED IDEOGRAPH-82D9 +U+82DB(2,3);U+82DB(2,3); # 18-55, CJK UNIFIED IDEOGRAPH-82DB +U+82DC(2,3);U+82DC(2,3); # 71-92, CJK UNIFIED IDEOGRAPH-82DC +U+82DE(2,3);U+82DE(2,3); # 71-90, CJK UNIFIED IDEOGRAPH-82DE +U+82DF(2,3);U+82DF(2,3); # 71-81, CJK UNIFIED IDEOGRAPH-82DF +U+82E1(2,3);U+82E1(2,3); # 71-79, CJK UNIFIED IDEOGRAPH-82E1 +U+82E3(2,3);U+82E3(2,3); # 71-80, CJK UNIFIED IDEOGRAPH-82E3 +U+82E5(2,3);U+82E5(2,3); # 28-67, CJK UNIFIED IDEOGRAPH-82E5 +U+82E6(2,3);U+82E6(2,3); # 22-76, CJK UNIFIED IDEOGRAPH-82E6 +U+82E7(2,3);U+82E7(2,3); # 35-87, CJK UNIFIED IDEOGRAPH-82E7 +U+82EB(2,3);U+82EB(2,3); # 38-49, CJK UNIFIED IDEOGRAPH-82EB +U+82F1(2,3);U+82F1(2,3); # 17-49, CJK UNIFIED IDEOGRAPH-82F1 +U+82F3(2,3);U+82F3(2,3); # 71-84, CJK UNIFIED IDEOGRAPH-82F3 +U+82F4(2,3);U+82F4(2,3); # 71-83, CJK UNIFIED IDEOGRAPH-82F4 +U+82F9(2,3);U+82F9(2,3); # 71-89, CJK UNIFIED IDEOGRAPH-82F9 +U+82FA(2,3);U+82FA(2,3); # 71-85, CJK UNIFIED IDEOGRAPH-82FA +U+82FB(2,3);U+82FB(2,3); # 71-88, CJK UNIFIED IDEOGRAPH-82FB +U+8302(2,3);U+8302(2,3); # 44-48, CJK UNIFIED IDEOGRAPH-8302 +U+8303(2,3);U+8303(2,3); # 71-87, CJK UNIFIED IDEOGRAPH-8303 +U+8304(2,3);U+8304(2,3); # 18-56, CJK UNIFIED IDEOGRAPH-8304 +U+8305(2,3);U+8305(2,3); # 19-93, CJK UNIFIED IDEOGRAPH-8305 +U+8306(2,3);U+8306(2,3); # 71-91, CJK UNIFIED IDEOGRAPH-8306 +U+8309(2,3);U+8309(2,3); # 71-93, CJK UNIFIED IDEOGRAPH-8309 +U+830E(2,3);U+830E(2,3); # 23-52, CJK UNIFIED IDEOGRAPH-830E +U+8316(2,3);U+8316(2,3); # 72-03, CJK UNIFIED IDEOGRAPH-8316 +U+8317(2,3);U+8317(2,3); # 72-12, CJK UNIFIED IDEOGRAPH-8317 +U+8318(2,3);U+8318(2,3); # 72-13, CJK UNIFIED IDEOGRAPH-8318 +U+831C(2,3);U+831C(2,3); # 16-11, CJK UNIFIED IDEOGRAPH-831C +U+8323(2,3);U+8323(2,3); # 72-20, CJK UNIFIED IDEOGRAPH-8323 +U+8328(2,3);U+8328(2,3); # 16-81, CJK UNIFIED IDEOGRAPH-8328 +U+832B(2,3);U+832B(2,3); # 72-11, CJK UNIFIED IDEOGRAPH-832B +U+832F(2,3);U+832F(2,3); # 72-10, CJK UNIFIED IDEOGRAPH-832F +U+8331(2,3);U+8331(2,3); # 72-05, CJK UNIFIED IDEOGRAPH-8331 +U+8332(2,3);U+8332(2,3); # 72-04, CJK UNIFIED IDEOGRAPH-8332 +U+8334(2,3);U+8334(2,3); # 72-02, CJK UNIFIED IDEOGRAPH-8334 +U+8335(2,3);U+8335(2,3); # 72-01, CJK UNIFIED IDEOGRAPH-8335 +U+8336(2,3);U+8336(2,3); # 35-67, CJK UNIFIED IDEOGRAPH-8336 +U+8338(2,3);U+8338(2,3); # 34-91, CJK UNIFIED IDEOGRAPH-8338 +U+8339(2,3);U+8339(2,3); # 72-07, CJK UNIFIED IDEOGRAPH-8339 +U+8340(2,3);U+8340(2,3); # 72-06, CJK UNIFIED IDEOGRAPH-8340 +U+8345(2,3);U+8345(2,3); # 72-09, CJK UNIFIED IDEOGRAPH-8345 +U+8349(2,3);U+8349(2,3); # 33-80, CJK UNIFIED IDEOGRAPH-8349 +U+834A(2,3);U+834A(2,3); # 23-53, CJK UNIFIED IDEOGRAPH-834A +U+834F(2,3);U+834F(2,3); # 17-33, CJK UNIFIED IDEOGRAPH-834F +U+8350(2,3);U+8350(2,3); # 72-08, CJK UNIFIED IDEOGRAPH-8350 +U+8352(2,3);U+8352(2,3); # 25-51, CJK UNIFIED IDEOGRAPH-8352 +U+8358(2,3);U+8358(2,3); # 33-81, CJK UNIFIED IDEOGRAPH-8358 +U+8373(2,3);U+8373(2,3); # 72-26, CJK UNIFIED IDEOGRAPH-8373 +U+8375(2,3);U+8375(2,3); # 72-27, CJK UNIFIED IDEOGRAPH-8375 +U+8377(2,3);U+8377(2,3); # 18-57, CJK UNIFIED IDEOGRAPH-8377 +U+837B(2,3);U+837B(2,3); # 18-14, CJK UNIFIED IDEOGRAPH-837B +U+837C(2,3);U+837C(2,3); # 72-24, CJK UNIFIED IDEOGRAPH-837C +U+8385(2,3);U+8385(2,3); # 72-14, CJK UNIFIED IDEOGRAPH-8385 +U+8387(2,3);U+8387(2,3); # 72-22, CJK UNIFIED IDEOGRAPH-8387 +U+8389(2,3);U+8389(2,3); # 72-29, CJK UNIFIED IDEOGRAPH-8389 +U+838A(2,3);U+838A(2,3); # 72-23, CJK UNIFIED IDEOGRAPH-838A +U+838E(2,3);U+838E(2,3); # 72-21, CJK UNIFIED IDEOGRAPH-838E +U+8393(2,3);U+8393(2,3); # 71-86, CJK UNIFIED IDEOGRAPH-8393 +U+8396(2,3);U+8396(2,3); # 72-19, CJK UNIFIED IDEOGRAPH-8396 +U+839A(2,3);U+839A(2,3); # 72-15, CJK UNIFIED IDEOGRAPH-839A +U+839E(2,3);U+839E(2,3); # 20-48, CJK UNIFIED IDEOGRAPH-839E +U+839F(2,3);U+839F(2,3); # 72-17, CJK UNIFIED IDEOGRAPH-839F +U+83A0(2,3);U+83A0(2,3); # 72-28, CJK UNIFIED IDEOGRAPH-83A0 +U+83A2(2,3);U+83A2(2,3); # 72-18, CJK UNIFIED IDEOGRAPH-83A2 +U+83A8(2,3);U+83A8(2,3); # 72-30, CJK UNIFIED IDEOGRAPH-83A8 +U+83AA(2,3);U+83AA(2,3); # 72-16, CJK UNIFIED IDEOGRAPH-83AA +U+83AB(2,3);U+83AB(2,3); # 39-92, CJK UNIFIED IDEOGRAPH-83AB +U+83B1(2,3);U+83B1(2,3); # 45-73, CJK UNIFIED IDEOGRAPH-83B1 +U+83B5(2,3);U+83B5(2,3); # 72-25, CJK UNIFIED IDEOGRAPH-83B5 +U+83BD(2,3);U+83BD(2,3); # 72-47, CJK UNIFIED IDEOGRAPH-83BD +U+83C1(2,3);U+83C1(2,3); # 72-39, CJK UNIFIED IDEOGRAPH-83C1 +U+83C5(2,3);U+83C5(2,3); # 31-91, CJK UNIFIED IDEOGRAPH-83C5 +U+83CA(2,3);U+83CA(2,3); # 21-38, CJK UNIFIED IDEOGRAPH-83CA +U+83CC(2,3);U+83CC(2,3); # 22-61, CJK UNIFIED IDEOGRAPH-83CC +U+83CE(2,3);U+83CE(2,3); # 72-34, CJK UNIFIED IDEOGRAPH-83CE +U+83D3(2,3);U+83D3(2,3); # 18-59, CJK UNIFIED IDEOGRAPH-83D3 +U+83D6(2,3);U+83D6(2,3); # 30-52, CJK UNIFIED IDEOGRAPH-83D6 +U+83D8(2,3);U+83D8(2,3); # 72-37, CJK UNIFIED IDEOGRAPH-83D8 +U+83DC(2,3);U+83DC(2,3); # 26-58, CJK UNIFIED IDEOGRAPH-83DC +U+83DF(2,3);U+83DF(2,3); # 37-49, CJK UNIFIED IDEOGRAPH-83DF +U+83E0(2,3);U+83E0(2,3); # 72-42, CJK UNIFIED IDEOGRAPH-83E0 +U+83E9(2,3);U+83E9(2,3); # 42-78, CJK UNIFIED IDEOGRAPH-83E9 +U+83EB(2,3);U+83EB(2,3); # 72-33, CJK UNIFIED IDEOGRAPH-83EB +U+83EF(2,3);U+83EF(2,3); # 18-58, CJK UNIFIED IDEOGRAPH-83EF +U+83F0(2,3);U+83F0(2,3); # 24-54, CJK UNIFIED IDEOGRAPH-83F0 +U+83F1(2,3);U+83F1(2,3); # 41-09, CJK UNIFIED IDEOGRAPH-83F1 +U+83F2(2,3);U+83F2(2,3); # 72-43, CJK UNIFIED IDEOGRAPH-83F2 +U+83F4(2,3);U+83F4(2,3); # 72-31, CJK UNIFIED IDEOGRAPH-83F4 +U+83F7(2,3);U+83F7(2,3); # 72-40, CJK UNIFIED IDEOGRAPH-83F7 +U+83FB(2,3);U+83FB(2,3); # 72-50, CJK UNIFIED IDEOGRAPH-83FB +U+83FD(2,3);U+83FD(2,3); # 72-35, CJK UNIFIED IDEOGRAPH-83FD +U+8403(2,3);U+8403(2,3); # 72-36, CJK UNIFIED IDEOGRAPH-8403 +U+8404(2,3);U+8404(2,3); # 38-26, CJK UNIFIED IDEOGRAPH-8404 +U+8407(2,3);U+8407(2,3); # 72-41, CJK UNIFIED IDEOGRAPH-8407 +U+840B(2,3);U+840B(2,3); # 72-38, CJK UNIFIED IDEOGRAPH-840B +U+840C(2,3);U+840C(2,3); # 43-08, CJK UNIFIED IDEOGRAPH-840C +U+840D(2,3);U+840D(2,3); # 72-44, CJK UNIFIED IDEOGRAPH-840D +U+840E(2,3);U+840E(2,3); # 16-64, CJK UNIFIED IDEOGRAPH-840E +U+8413(2,3);U+8413(2,3); # 72-32, CJK UNIFIED IDEOGRAPH-8413 +U+8420(2,3);U+8420(2,3); # 72-46, CJK UNIFIED IDEOGRAPH-8420 +U+8422(2,3);U+8422(2,3); # 72-45, CJK UNIFIED IDEOGRAPH-8422 +U+8429(2,3);U+8429(2,3); # 39-75, CJK UNIFIED IDEOGRAPH-8429 +U+842A(2,3);U+842A(2,3); # 72-52, CJK UNIFIED IDEOGRAPH-842A +U+842C(2,3);U+842C(2,3); # 72-63, CJK UNIFIED IDEOGRAPH-842C +U+8431(2,3);U+8431(2,3); # 19-94, CJK UNIFIED IDEOGRAPH-8431 +U+8435(2,3);U+8435(2,3); # 72-66, CJK UNIFIED IDEOGRAPH-8435 +U+8438(2,3);U+8438(2,3); # 72-48, CJK UNIFIED IDEOGRAPH-8438 +U+843C(2,3);U+843C(2,3); # 72-53, CJK UNIFIED IDEOGRAPH-843C +U+843D(2,3);U+843D(2,3); # 45-78, CJK UNIFIED IDEOGRAPH-843D +U+8446(2,3);U+8446(2,3); # 72-62, CJK UNIFIED IDEOGRAPH-8446 +U+8449(2,3);U+8449(2,3); # 45-53, CJK UNIFIED IDEOGRAPH-8449 +U+844E(2,3);U+844E(2,3); # 46-10, CJK UNIFIED IDEOGRAPH-844E +U+8457(2,3);U+8457(2,3); # 35-88, CJK UNIFIED IDEOGRAPH-8457 +U+845B(2,3);U+845B(2,3); # 19-75, CJK UNIFIED IDEOGRAPH-845B +U+8461(2,3);U+8461(2,3); # 41-82, CJK UNIFIED IDEOGRAPH-8461 +U+8462(2,3);U+8462(2,3); # 72-68, CJK UNIFIED IDEOGRAPH-8462 +U+8463(2,3);U+8463(2,3); # 38-01, CJK UNIFIED IDEOGRAPH-8463 +U+8466(2,3);U+8466(2,3); # 16-17, CJK UNIFIED IDEOGRAPH-8466 +U+8469(2,3);U+8469(2,3); # 72-61, CJK UNIFIED IDEOGRAPH-8469 +U+846B(2,3);U+846B(2,3); # 72-57, CJK UNIFIED IDEOGRAPH-846B +U+846C(2,3);U+846C(2,3); # 33-82, CJK UNIFIED IDEOGRAPH-846C +U+846D(2,3);U+846D(2,3); # 72-51, CJK UNIFIED IDEOGRAPH-846D +U+846E(2,3);U+846E(2,3); # 72-59, CJK UNIFIED IDEOGRAPH-846E +U+846F(2,3);U+846F(2,3); # 72-64, CJK UNIFIED IDEOGRAPH-846F +U+8471(2,3);U+8471(2,3); # 39-12, CJK UNIFIED IDEOGRAPH-8471 +U+8475(2,3);U+8475(2,3); # 16-10, CJK UNIFIED IDEOGRAPH-8475 +U+8477(2,3);U+8477(2,3); # 72-56, CJK UNIFIED IDEOGRAPH-8477 +U+8479(2,3);U+8479(2,3); # 72-65, CJK UNIFIED IDEOGRAPH-8479 +U+847A(2,3);U+847A(2,3); # 41-88, CJK UNIFIED IDEOGRAPH-847A +U+8482(2,3);U+8482(2,3); # 72-60, CJK UNIFIED IDEOGRAPH-8482 +U+8484(2,3);U+8484(2,3); # 72-55, CJK UNIFIED IDEOGRAPH-8484 +U+848B(2,3);U+848B(2,3); # 30-53, CJK UNIFIED IDEOGRAPH-848B +U+8490(2,3);U+8490(2,3); # 29-15, CJK UNIFIED IDEOGRAPH-8490 +U+8494(2,3);U+8494(2,3); # 28-12, CJK UNIFIED IDEOGRAPH-8494 +U+8499(2,3);U+8499(2,3); # 44-56, CJK UNIFIED IDEOGRAPH-8499 +U+849C(2,3);U+849C(2,3); # 41-39, CJK UNIFIED IDEOGRAPH-849C +U+849F(2,3);U+849F(2,3); # 72-71, CJK UNIFIED IDEOGRAPH-849F +U+84A1(2,3);U+84A1(2,3); # 72-80, CJK UNIFIED IDEOGRAPH-84A1 +U+84AD(2,3);U+84AD(2,3); # 72-58, CJK UNIFIED IDEOGRAPH-84AD +U+84B2(2,3);U+84B2(2,3); # 19-87, CJK UNIFIED IDEOGRAPH-84B2 +U+84B8(2,3);U+84B8(2,3); # 30-88, CJK UNIFIED IDEOGRAPH-84B8 +U+84B9(2,3);U+84B9(2,3); # 72-69, CJK UNIFIED IDEOGRAPH-84B9 +U+84BB(2,3);U+84BB(2,3); # 72-74, CJK UNIFIED IDEOGRAPH-84BB +U+84BC(2,3);U+84BC(2,3); # 33-83, CJK UNIFIED IDEOGRAPH-84BC +U+84BF(2,3);U+84BF(2,3); # 72-70, CJK UNIFIED IDEOGRAPH-84BF +U+84C1(2,3);U+84C1(2,3); # 72-77, CJK UNIFIED IDEOGRAPH-84C1 +U+84C4(2,3);U+84C4(2,3); # 35-63, CJK UNIFIED IDEOGRAPH-84C4 +U+84C6(2,3);U+84C6(2,3); # 72-78, CJK UNIFIED IDEOGRAPH-84C6 +U+84C9(2,3);U+84C9(2,3); # 45-54, CJK UNIFIED IDEOGRAPH-84C9 +U+84CA(2,3);U+84CA(2,3); # 72-67, CJK UNIFIED IDEOGRAPH-84CA +U+84CB(2,3);U+84CB(2,3); # 19-24, CJK UNIFIED IDEOGRAPH-84CB +U+84CD(2,3);U+84CD(2,3); # 72-73, CJK UNIFIED IDEOGRAPH-84CD +U+84D0(2,3);U+84D0(2,3); # 72-76, CJK UNIFIED IDEOGRAPH-84D0 +U+84D1(2,3);U+84D1(2,3); # 44-12, CJK UNIFIED IDEOGRAPH-84D1 +U+84D6(2,3);U+84D6(2,3); # 72-79, CJK UNIFIED IDEOGRAPH-84D6 +U+84D9(2,3);U+84D9(2,3); # 72-72, CJK UNIFIED IDEOGRAPH-84D9 +U+84DA(2,3);U+84DA(2,3); # 72-75, CJK UNIFIED IDEOGRAPH-84DA +U+84EC(2,3);U+84EC(2,3); # 43-09, CJK UNIFIED IDEOGRAPH-84EC +U+84EE(2,3);U+84EE(2,3); # 47-01, CJK UNIFIED IDEOGRAPH-84EE +U+84F4(2,3);U+84F4(2,3); # 72-83, CJK UNIFIED IDEOGRAPH-84F4 +U+84FC(2,3);U+84FC(2,3); # 72-90, CJK UNIFIED IDEOGRAPH-84FC +U+84FF(2,3);U+84FF(2,3); # 72-82, CJK UNIFIED IDEOGRAPH-84FF +U+8500(2,3);U+8500(2,3); # 28-35, CJK UNIFIED IDEOGRAPH-8500 +U+8506(2,3);U+8506(2,3); # 72-49, CJK UNIFIED IDEOGRAPH-8506 +U+8511(2,3);U+8511(2,3); # 42-46, CJK UNIFIED IDEOGRAPH-8511 +U+8513(2,3);U+8513(2,3); # 44-02, CJK UNIFIED IDEOGRAPH-8513 +U+8514(2,3);U+8514(2,3); # 72-89, CJK UNIFIED IDEOGRAPH-8514 +U+8515(2,3);U+8515(2,3); # 72-88, CJK UNIFIED IDEOGRAPH-8515 +U+8517(2,3);U+8517(2,3); # 72-84, CJK UNIFIED IDEOGRAPH-8517 +U+8518(2,3);U+8518(2,3); # 72-85, CJK UNIFIED IDEOGRAPH-8518 +U+851A(2,3);U+851A(2,3); # 17-22, CJK UNIFIED IDEOGRAPH-851A +U+851F(2,3);U+851F(2,3); # 72-87, CJK UNIFIED IDEOGRAPH-851F +U+8521(2,3);U+8521(2,3); # 72-81, CJK UNIFIED IDEOGRAPH-8521 +U+8526(2,3);U+8526(2,3); # 36-53, CJK UNIFIED IDEOGRAPH-8526 +U+852C(2,3);U+852C(2,3); # 72-86, CJK UNIFIED IDEOGRAPH-852C +U+852D(2,3);U+852D(2,3); # 16-94, CJK UNIFIED IDEOGRAPH-852D +U+8535(2,3);U+8535(2,3); # 34-02, CJK UNIFIED IDEOGRAPH-8535 +U+853D(2,3);U+853D(2,3); # 42-35, CJK UNIFIED IDEOGRAPH-853D +U+8540(2,3);U+8540(2,3); # 72-91, CJK UNIFIED IDEOGRAPH-8540 +U+8541(2,3);U+8541(2,3); # 73-01, CJK UNIFIED IDEOGRAPH-8541 +U+8543(2,3);U+8543(2,3); # 40-57, CJK UNIFIED IDEOGRAPH-8543 +U+8548(2,3);U+8548(2,3); # 72-94, CJK UNIFIED IDEOGRAPH-8548 +U+8549(2,3);U+8549(2,3); # 30-54, CJK UNIFIED IDEOGRAPH-8549 +U+854A(2,3);U+854A(2,3); # 28-41, CJK UNIFIED IDEOGRAPH-854A +U+854B(2,3);U+854B(2,3); # 73-03, CJK UNIFIED IDEOGRAPH-854B +U+854E(2,3);U+854E(2,3); # 22-30, CJK UNIFIED IDEOGRAPH-854E +U+8555(2,3);U+8555(2,3); # 73-04, CJK UNIFIED IDEOGRAPH-8555 +U+8557(2,3);U+8557(2,3); # 41-89, CJK UNIFIED IDEOGRAPH-8557 +U+8558(2,3);U+8558(2,3); # 72-93, CJK UNIFIED IDEOGRAPH-8558 +U+855A(2,3);U+855A(2,3); # 72-54, CJK UNIFIED IDEOGRAPH-855A +U+8563(2,3);U+8563(2,3); # 72-92, CJK UNIFIED IDEOGRAPH-8563 +U+8568(2,3);U+8568(2,3); # 47-47, CJK UNIFIED IDEOGRAPH-8568 +U+8569(2,3);U+8569(2,3); # 38-02, CJK UNIFIED IDEOGRAPH-8569 +U+856A(2,3);U+856A(2,3); # 41-83, CJK UNIFIED IDEOGRAPH-856A +U+856D(2,3);U+856D(2,3); # 73-11, CJK UNIFIED IDEOGRAPH-856D +U+8577(2,3);U+8577(2,3); # 73-17, CJK UNIFIED IDEOGRAPH-8577 +U+857E(2,3);U+857E(2,3); # 73-18, CJK UNIFIED IDEOGRAPH-857E +U+8580(2,3);U+8580(2,3); # 73-05, CJK UNIFIED IDEOGRAPH-8580 +U+8584(2,3);U+8584(2,3); # 39-86, CJK UNIFIED IDEOGRAPH-8584 +U+8587(2,3);U+8587(2,3); # 73-15, CJK UNIFIED IDEOGRAPH-8587 +U+8588(2,3);U+8588(2,3); # 73-07, CJK UNIFIED IDEOGRAPH-8588 +U+858A(2,3);U+858A(2,3); # 73-09, CJK UNIFIED IDEOGRAPH-858A +U+8590(2,3);U+8590(2,3); # 73-19, CJK UNIFIED IDEOGRAPH-8590 +U+8591(2,3);U+8591(2,3); # 73-08, CJK UNIFIED IDEOGRAPH-8591 +U+8594(2,3);U+8594(2,3); # 73-12, CJK UNIFIED IDEOGRAPH-8594 +U+8597(2,3);U+8597(2,3); # 17-82, CJK UNIFIED IDEOGRAPH-8597 +U+8599(2,3);U+8599(2,3); # 38-69, CJK UNIFIED IDEOGRAPH-8599 +U+859B(2,3);U+859B(2,3); # 73-13, CJK UNIFIED IDEOGRAPH-859B +U+859C(2,3);U+859C(2,3); # 73-16, CJK UNIFIED IDEOGRAPH-859C +U+85A4(2,3);U+85A4(2,3); # 73-06, CJK UNIFIED IDEOGRAPH-85A4 +U+85A6(2,3);U+85A6(2,3); # 33-06, CJK UNIFIED IDEOGRAPH-85A6 +U+85A8(2,3);U+85A8(2,3); # 73-10, CJK UNIFIED IDEOGRAPH-85A8 +U+85A9(2,3);U+85A9(2,3); # 27-07, CJK UNIFIED IDEOGRAPH-85A9 +U+85AA(2,3);U+85AA(2,3); # 31-37, CJK UNIFIED IDEOGRAPH-85AA +U+85AB(2,3);U+85AB(2,3); # 23-16, CJK UNIFIED IDEOGRAPH-85AB +U+85AC(2,3);U+85AC(2,3); # 44-84, CJK UNIFIED IDEOGRAPH-85AC +U+85AE(2,3);U+85AE(2,3); # 44-89, CJK UNIFIED IDEOGRAPH-85AE +U+85AF(2,3);U+85AF(2,3); # 29-82, CJK UNIFIED IDEOGRAPH-85AF +U+85B9(2,3);U+85B9(2,3); # 73-23, CJK UNIFIED IDEOGRAPH-85B9 +U+85BA(2,3);U+85BA(2,3); # 73-21, CJK UNIFIED IDEOGRAPH-85BA +U+85C1(2,3);U+85C1(2,3); # 47-46, CJK UNIFIED IDEOGRAPH-85C1 +U+85C9(2,3);U+85C9(2,3); # 73-20, CJK UNIFIED IDEOGRAPH-85C9 +U+85CD(2,3);U+85CD(2,3); # 45-85, CJK UNIFIED IDEOGRAPH-85CD +U+85CF(2,3);U+85CF(2,3); # 73-22, CJK UNIFIED IDEOGRAPH-85CF +U+85D0(2,3);U+85D0(2,3); # 73-24, CJK UNIFIED IDEOGRAPH-85D0 +U+85D5(2,3);U+85D5(2,3); # 73-25, CJK UNIFIED IDEOGRAPH-85D5 +U+85DC(2,3);U+85DC(2,3); # 73-28, CJK UNIFIED IDEOGRAPH-85DC +U+85DD(2,3);U+85DD(2,3); # 73-26, CJK UNIFIED IDEOGRAPH-85DD +U+85E4(2,3);U+85E4(2,3); # 38-03, CJK UNIFIED IDEOGRAPH-85E4 +U+85E5(2,3);U+85E5(2,3); # 73-27, CJK UNIFIED IDEOGRAPH-85E5 +U+85E9(2,3);U+85E9(2,3); # 40-45, CJK UNIFIED IDEOGRAPH-85E9 +U+85EA(2,3);U+85EA(2,3); # 73-14, CJK UNIFIED IDEOGRAPH-85EA +U+85F7(2,3);U+85F7(2,3); # 29-83, CJK UNIFIED IDEOGRAPH-85F7 +U+85F9(2,3);U+85F9(2,3); # 73-29, CJK UNIFIED IDEOGRAPH-85F9 +U+85FA(2,3);U+85FA(2,3); # 73-34, CJK UNIFIED IDEOGRAPH-85FA +U+85FB(2,3);U+85FB(2,3); # 33-84, CJK UNIFIED IDEOGRAPH-85FB +U+85FE(2,3);U+85FE(2,3); # 73-33, CJK UNIFIED IDEOGRAPH-85FE +U+8602(2,3);U+8602(2,3); # 73-02, CJK UNIFIED IDEOGRAPH-8602 +U+8606(2,3);U+8606(2,3); # 73-35, CJK UNIFIED IDEOGRAPH-8606 +U+8607(2,3);U+8607(2,3); # 33-41, CJK UNIFIED IDEOGRAPH-8607 +U+860A(2,3);U+860A(2,3); # 73-30, CJK UNIFIED IDEOGRAPH-860A +U+860B(2,3);U+860B(2,3); # 73-32, CJK UNIFIED IDEOGRAPH-860B +U+8613(2,3);U+8613(2,3); # 73-31, CJK UNIFIED IDEOGRAPH-8613 +U+8616(2,3);U+8616(2,3); # 61-17, CJK UNIFIED IDEOGRAPH-8616 +U+8617(2,3);U+8617(2,3); # 61-02, CJK UNIFIED IDEOGRAPH-8617 +U+861A(2,3);U+861A(2,3); # 73-37, CJK UNIFIED IDEOGRAPH-861A +U+8622(2,3);U+8622(2,3); # 73-36, CJK UNIFIED IDEOGRAPH-8622 +U+862D(2,3);U+862D(2,3); # 45-86, CJK UNIFIED IDEOGRAPH-862D +U+862F(2,3);U+862F(2,3); # 66-28, CJK UNIFIED IDEOGRAPH-862F +U+8630(2,3);U+8630(2,3); # 73-38, CJK UNIFIED IDEOGRAPH-8630 +U+863F(2,3);U+863F(2,3); # 73-39, CJK UNIFIED IDEOGRAPH-863F +U+864D(2,3);U+864D(2,3); # 73-40, CJK UNIFIED IDEOGRAPH-864D +U+864E(2,3);U+864E(2,3); # 24-55, CJK UNIFIED IDEOGRAPH-864E +U+8650(2,3);U+8650(2,3); # 21-52, CJK UNIFIED IDEOGRAPH-8650 +U+8654(2,3);U+8654(2,3); # 73-42, CJK UNIFIED IDEOGRAPH-8654 +U+8655(2,3);U+8655(2,3); # 49-61, CJK UNIFIED IDEOGRAPH-8655 +U+865A(2,3);U+865A(2,3); # 21-85, CJK UNIFIED IDEOGRAPH-865A +U+865C(2,3);U+865C(2,3); # 46-26, CJK UNIFIED IDEOGRAPH-865C +U+865E(2,3);U+865E(2,3); # 22-83, CJK UNIFIED IDEOGRAPH-865E +U+865F(2,3);U+865F(2,3); # 73-43, CJK UNIFIED IDEOGRAPH-865F +U+8667(2,3);U+8667(2,3); # 73-44, CJK UNIFIED IDEOGRAPH-8667 +U+866B(2,3);U+866B(2,3); # 35-78, CJK UNIFIED IDEOGRAPH-866B +U+8671(2,3);U+8671(2,3); # 73-45, CJK UNIFIED IDEOGRAPH-8671 +U+8679(2,3);U+8679(2,3); # 38-90, CJK UNIFIED IDEOGRAPH-8679 +U+867B(2,3);U+867B(2,3); # 16-26, CJK UNIFIED IDEOGRAPH-867B +U+868A(2,3);U+868A(2,3); # 18-67, CJK UNIFIED IDEOGRAPH-868A +U+868B(2,3);U+868B(2,3); # 73-50, CJK UNIFIED IDEOGRAPH-868B +U+868C(2,3);U+868C(2,3); # 73-51, CJK UNIFIED IDEOGRAPH-868C +U+8693(2,3);U+8693(2,3); # 73-46, CJK UNIFIED IDEOGRAPH-8693 +U+8695(2,3);U+8695(2,3); # 27-29, CJK UNIFIED IDEOGRAPH-8695 +U+86A3(2,3);U+86A3(2,3); # 73-47, CJK UNIFIED IDEOGRAPH-86A3 +U+86A4(2,3);U+86A4(2,3); # 39-34, CJK UNIFIED IDEOGRAPH-86A4 +U+86A9(2,3);U+86A9(2,3); # 73-48, CJK UNIFIED IDEOGRAPH-86A9 +U+86AA(2,3);U+86AA(2,3); # 73-49, CJK UNIFIED IDEOGRAPH-86AA +U+86AB(2,3);U+86AB(2,3); # 73-59, CJK UNIFIED IDEOGRAPH-86AB +U+86AF(2,3);U+86AF(2,3); # 73-53, CJK UNIFIED IDEOGRAPH-86AF +U+86B0(2,3);U+86B0(2,3); # 73-56, CJK UNIFIED IDEOGRAPH-86B0 +U+86B6(2,3);U+86B6(2,3); # 73-52, CJK UNIFIED IDEOGRAPH-86B6 +U+86C4(2,3);U+86C4(2,3); # 73-54, CJK UNIFIED IDEOGRAPH-86C4 +U+86C6(2,3);U+86C6(2,3); # 73-55, CJK UNIFIED IDEOGRAPH-86C6 +U+86C7(2,3);U+86C7(2,3); # 28-56, CJK UNIFIED IDEOGRAPH-86C7 +U+86C9(2,3);U+86C9(2,3); # 73-57, CJK UNIFIED IDEOGRAPH-86C9 +U+86CB(2,3);U+86CB(2,3); # 35-33, CJK UNIFIED IDEOGRAPH-86CB +U+86CD(2,3);U+86CD(2,3); # 23-54, CJK UNIFIED IDEOGRAPH-86CD +U+86CE(2,3);U+86CE(2,3); # 19-34, CJK UNIFIED IDEOGRAPH-86CE +U+86D4(2,3);U+86D4(2,3); # 73-60, CJK UNIFIED IDEOGRAPH-86D4 +U+86D9(2,3);U+86D9(2,3); # 19-31, CJK UNIFIED IDEOGRAPH-86D9 +U+86DB(2,3);U+86DB(2,3); # 73-65, CJK UNIFIED IDEOGRAPH-86DB +U+86DE(2,3);U+86DE(2,3); # 73-61, CJK UNIFIED IDEOGRAPH-86DE +U+86DF(2,3);U+86DF(2,3); # 73-64, CJK UNIFIED IDEOGRAPH-86DF +U+86E4(2,3);U+86E4(2,3); # 40-26, CJK UNIFIED IDEOGRAPH-86E4 +U+86E9(2,3);U+86E9(2,3); # 73-62, CJK UNIFIED IDEOGRAPH-86E9 +U+86EC(2,3);U+86EC(2,3); # 73-63, CJK UNIFIED IDEOGRAPH-86EC +U+86ED(2,3);U+86ED(2,3); # 41-40, CJK UNIFIED IDEOGRAPH-86ED +U+86EE(2,3);U+86EE(2,3); # 40-58, CJK UNIFIED IDEOGRAPH-86EE +U+86EF(2,3);U+86EF(2,3); # 73-66, CJK UNIFIED IDEOGRAPH-86EF +U+86F8(2,3);U+86F8(2,3); # 34-93, CJK UNIFIED IDEOGRAPH-86F8 +U+86F9(2,3);U+86F9(2,3); # 73-76, CJK UNIFIED IDEOGRAPH-86F9 +U+86FB(2,3);U+86FB(2,3); # 73-72, CJK UNIFIED IDEOGRAPH-86FB +U+86FE(2,3);U+86FE(2,3); # 18-75, CJK UNIFIED IDEOGRAPH-86FE +U+8700(2,3);U+8700(2,3); # 73-70, CJK UNIFIED IDEOGRAPH-8700 +U+8702(2,3);U+8702(2,3); # 43-10, CJK UNIFIED IDEOGRAPH-8702 +U+8703(2,3);U+8703(2,3); # 73-71, CJK UNIFIED IDEOGRAPH-8703 +U+8706(2,3);U+8706(2,3); # 73-68, CJK UNIFIED IDEOGRAPH-8706 +U+8708(2,3);U+8708(2,3); # 73-69, CJK UNIFIED IDEOGRAPH-8708 +U+8709(2,3);U+8709(2,3); # 73-74, CJK UNIFIED IDEOGRAPH-8709 +U+870A(2,3);U+870A(2,3); # 73-77, CJK UNIFIED IDEOGRAPH-870A +U+870D(2,3);U+870D(2,3); # 73-75, CJK UNIFIED IDEOGRAPH-870D +U+8711(2,3);U+8711(2,3); # 73-73, CJK UNIFIED IDEOGRAPH-8711 +U+8712(2,3);U+8712(2,3); # 73-67, CJK UNIFIED IDEOGRAPH-8712 +U+8718(2,3);U+8718(2,3); # 35-56, CJK UNIFIED IDEOGRAPH-8718 +U+871A(2,3);U+871A(2,3); # 73-84, CJK UNIFIED IDEOGRAPH-871A +U+871C(2,3);U+871C(2,3); # 44-10, CJK UNIFIED IDEOGRAPH-871C +U+8725(2,3);U+8725(2,3); # 73-82, CJK UNIFIED IDEOGRAPH-8725 +U+8729(2,3);U+8729(2,3); # 73-83, CJK UNIFIED IDEOGRAPH-8729 +U+8734(2,3);U+8734(2,3); # 73-78, CJK UNIFIED IDEOGRAPH-8734 +U+8737(2,3);U+8737(2,3); # 73-80, CJK UNIFIED IDEOGRAPH-8737 +U+873B(2,3);U+873B(2,3); # 73-81, CJK UNIFIED IDEOGRAPH-873B +U+873F(2,3);U+873F(2,3); # 73-79, CJK UNIFIED IDEOGRAPH-873F +U+8749(2,3);U+8749(2,3); # 32-70, CJK UNIFIED IDEOGRAPH-8749 +U+874B(2,3);U+874B(2,3); # 47-25, CJK UNIFIED IDEOGRAPH-874B +U+874C(2,3);U+874C(2,3); # 73-88, CJK UNIFIED IDEOGRAPH-874C +U+874E(2,3);U+874E(2,3); # 73-89, CJK UNIFIED IDEOGRAPH-874E +U+8753(2,3);U+8753(2,3); # 74-01, CJK UNIFIED IDEOGRAPH-8753 +U+8755(2,3);U+8755(2,3); # 31-10, CJK UNIFIED IDEOGRAPH-8755 +U+8757(2,3);U+8757(2,3); # 73-91, CJK UNIFIED IDEOGRAPH-8757 +U+8759(2,3);U+8759(2,3); # 73-94, CJK UNIFIED IDEOGRAPH-8759 +U+875F(2,3);U+875F(2,3); # 73-86, CJK UNIFIED IDEOGRAPH-875F +U+8760(2,3);U+8760(2,3); # 73-85, CJK UNIFIED IDEOGRAPH-8760 +U+8763(2,3);U+8763(2,3); # 74-02, CJK UNIFIED IDEOGRAPH-8763 +U+8766(2,3);U+8766(2,3); # 18-60, CJK UNIFIED IDEOGRAPH-8766 +U+8768(2,3);U+8768(2,3); # 73-92, CJK UNIFIED IDEOGRAPH-8768 +U+876A(2,3);U+876A(2,3); # 74-03, CJK UNIFIED IDEOGRAPH-876A +U+876E(2,3);U+876E(2,3); # 73-93, CJK UNIFIED IDEOGRAPH-876E +U+8774(2,3);U+8774(2,3); # 73-90, CJK UNIFIED IDEOGRAPH-8774 +U+8776(2,3);U+8776(2,3); # 36-19, CJK UNIFIED IDEOGRAPH-8776 +U+8778(2,3);U+8778(2,3); # 73-87, CJK UNIFIED IDEOGRAPH-8778 +U+877F(2,3);U+877F(2,3); # 39-72, CJK UNIFIED IDEOGRAPH-877F +U+8782(2,3);U+8782(2,3); # 74-07, CJK UNIFIED IDEOGRAPH-8782 +U+878D(2,3);U+878D(2,3); # 45-27, CJK UNIFIED IDEOGRAPH-878D +U+879F(2,3);U+879F(2,3); # 74-06, CJK UNIFIED IDEOGRAPH-879F +U+87A2(2,3);U+87A2(2,3); # 74-05, CJK UNIFIED IDEOGRAPH-87A2 +U+87AB(2,3);U+87AB(2,3); # 74-14, CJK UNIFIED IDEOGRAPH-87AB +U+87AF(2,3);U+87AF(2,3); # 74-08, CJK UNIFIED IDEOGRAPH-87AF +U+87B3(2,3);U+87B3(2,3); # 74-16, CJK UNIFIED IDEOGRAPH-87B3 +U+87BA(2,3);U+87BA(2,3); # 45-70, CJK UNIFIED IDEOGRAPH-87BA +U+87BB(2,3);U+87BB(2,3); # 74-19, CJK UNIFIED IDEOGRAPH-87BB +U+87BD(2,3);U+87BD(2,3); # 74-10, CJK UNIFIED IDEOGRAPH-87BD +U+87C0(2,3);U+87C0(2,3); # 74-11, CJK UNIFIED IDEOGRAPH-87C0 +U+87C4(2,3);U+87C4(2,3); # 74-15, CJK UNIFIED IDEOGRAPH-87C4 +U+87C6(2,3);U+87C6(2,3); # 74-18, CJK UNIFIED IDEOGRAPH-87C6 +U+87C7(2,3);U+87C7(2,3); # 74-17, CJK UNIFIED IDEOGRAPH-87C7 +U+87CB(2,3);U+87CB(2,3); # 74-09, CJK UNIFIED IDEOGRAPH-87CB +U+87D0(2,3);U+87D0(2,3); # 74-12, CJK UNIFIED IDEOGRAPH-87D0 +U+87D2(2,3);U+87D2(2,3); # 74-29, CJK UNIFIED IDEOGRAPH-87D2 +U+87E0(2,3);U+87E0(2,3); # 74-22, CJK UNIFIED IDEOGRAPH-87E0 +U+87EF(2,3);U+87EF(2,3); # 74-20, CJK UNIFIED IDEOGRAPH-87EF +U+87F2(2,3);U+87F2(2,3); # 74-21, CJK UNIFIED IDEOGRAPH-87F2 +U+87F6(2,3);U+87F6(2,3); # 74-26, CJK UNIFIED IDEOGRAPH-87F6 +U+87F7(2,3);U+87F7(2,3); # 74-27, CJK UNIFIED IDEOGRAPH-87F7 +U+87F9(2,3);U+87F9(2,3); # 19-10, CJK UNIFIED IDEOGRAPH-87F9 +U+87FB(2,3);U+87FB(2,3); # 21-34, CJK UNIFIED IDEOGRAPH-87FB +U+87FE(2,3);U+87FE(2,3); # 74-25, CJK UNIFIED IDEOGRAPH-87FE +U+8805(2,3);U+8805(2,3); # 74-04, CJK UNIFIED IDEOGRAPH-8805 +U+880D(2,3);U+880D(2,3); # 74-24, CJK UNIFIED IDEOGRAPH-880D +U+880E(2,3);U+880E(2,3); # 74-28, CJK UNIFIED IDEOGRAPH-880E +U+880F(2,3);U+880F(2,3); # 74-23, CJK UNIFIED IDEOGRAPH-880F +U+8811(2,3);U+8811(2,3); # 74-30, CJK UNIFIED IDEOGRAPH-8811 +U+8815(2,3);U+8815(2,3); # 74-32, CJK UNIFIED IDEOGRAPH-8815 +U+8816(2,3);U+8816(2,3); # 74-31, CJK UNIFIED IDEOGRAPH-8816 +U+8821(2,3);U+8821(2,3); # 74-34, CJK UNIFIED IDEOGRAPH-8821 +U+8822(2,3);U+8822(2,3); # 74-33, CJK UNIFIED IDEOGRAPH-8822 +U+8823(2,3);U+8823(2,3); # 73-58, CJK UNIFIED IDEOGRAPH-8823 +U+8827(2,3);U+8827(2,3); # 74-38, CJK UNIFIED IDEOGRAPH-8827 +U+8831(2,3);U+8831(2,3); # 74-35, CJK UNIFIED IDEOGRAPH-8831 +U+8836(2,3);U+8836(2,3); # 74-36, CJK UNIFIED IDEOGRAPH-8836 +U+8839(2,3);U+8839(2,3); # 74-37, CJK UNIFIED IDEOGRAPH-8839 +U+883B(2,3);U+883B(2,3); # 74-39, CJK UNIFIED IDEOGRAPH-883B +U+8840(2,3);U+8840(2,3); # 23-76, CJK UNIFIED IDEOGRAPH-8840 +U+8842(2,3);U+8842(2,3); # 74-41, CJK UNIFIED IDEOGRAPH-8842 +U+8844(2,3);U+8844(2,3); # 74-40, CJK UNIFIED IDEOGRAPH-8844 +U+8846(2,3);U+8846(2,3); # 29-16, CJK UNIFIED IDEOGRAPH-8846 +U+884C(2,3);U+884C(2,3); # 25-52, CJK UNIFIED IDEOGRAPH-884C +U+884D(2,3);U+884D(2,3); # 62-07, CJK UNIFIED IDEOGRAPH-884D +U+8852(2,3);U+8852(2,3); # 74-42, CJK UNIFIED IDEOGRAPH-8852 +U+8853(2,3);U+8853(2,3); # 29-49, CJK UNIFIED IDEOGRAPH-8853 +U+8857(2,3);U+8857(2,3); # 19-25, CJK UNIFIED IDEOGRAPH-8857 +U+8859(2,3);U+8859(2,3); # 74-43, CJK UNIFIED IDEOGRAPH-8859 +U+885B(2,3);U+885B(2,3); # 17-50, CJK UNIFIED IDEOGRAPH-885B +U+885D(2,3);U+885D(2,3); # 30-55, CJK UNIFIED IDEOGRAPH-885D +U+885E(2,3);U+885E(2,3); # 74-44, CJK UNIFIED IDEOGRAPH-885E +U+8861(2,3);U+8861(2,3); # 25-53, CJK UNIFIED IDEOGRAPH-8861 +U+8862(2,3);U+8862(2,3); # 74-45, CJK UNIFIED IDEOGRAPH-8862 +U+8863(2,3);U+8863(2,3); # 16-65, CJK UNIFIED IDEOGRAPH-8863 +U+8868(2,3);U+8868(2,3); # 41-29, CJK UNIFIED IDEOGRAPH-8868 +U+886B(2,3);U+886B(2,3); # 74-46, CJK UNIFIED IDEOGRAPH-886B +U+8870(2,3);U+8870(2,3); # 31-74, CJK UNIFIED IDEOGRAPH-8870 +U+8872(2,3);U+8872(2,3); # 74-53, CJK UNIFIED IDEOGRAPH-8872 +U+8875(2,3);U+8875(2,3); # 74-50, CJK UNIFIED IDEOGRAPH-8875 +U+8877(2,3);U+8877(2,3); # 35-79, CJK UNIFIED IDEOGRAPH-8877 +U+887D(2,3);U+887D(2,3); # 74-51, CJK UNIFIED IDEOGRAPH-887D +U+887E(2,3);U+887E(2,3); # 74-48, CJK UNIFIED IDEOGRAPH-887E +U+887F(2,3);U+887F(2,3); # 22-62, CJK UNIFIED IDEOGRAPH-887F +U+8881(2,3);U+8881(2,3); # 74-47, CJK UNIFIED IDEOGRAPH-8881 +U+8882(2,3);U+8882(2,3); # 74-54, CJK UNIFIED IDEOGRAPH-8882 +U+8888(2,3);U+8888(2,3); # 23-22, CJK UNIFIED IDEOGRAPH-8888 +U+888B(2,3);U+888B(2,3); # 34-62, CJK UNIFIED IDEOGRAPH-888B +U+888D(2,3);U+888D(2,3); # 74-60, CJK UNIFIED IDEOGRAPH-888D +U+8892(2,3);U+8892(2,3); # 74-56, CJK UNIFIED IDEOGRAPH-8892 +U+8896(2,3);U+8896(2,3); # 34-21, CJK UNIFIED IDEOGRAPH-8896 +U+8897(2,3);U+8897(2,3); # 74-55, CJK UNIFIED IDEOGRAPH-8897 +U+8899(2,3);U+8899(2,3); # 74-58, CJK UNIFIED IDEOGRAPH-8899 +U+889E(2,3);U+889E(2,3); # 74-49, CJK UNIFIED IDEOGRAPH-889E +U+88A2(2,3);U+88A2(2,3); # 74-59, CJK UNIFIED IDEOGRAPH-88A2 +U+88A4(2,3);U+88A4(2,3); # 74-61, CJK UNIFIED IDEOGRAPH-88A4 +U+88AB(2,3);U+88AB(2,3); # 40-79, CJK UNIFIED IDEOGRAPH-88AB +U+88AE(2,3);U+88AE(2,3); # 74-57, CJK UNIFIED IDEOGRAPH-88AE +U+88B0(2,3);U+88B0(2,3); # 74-62, CJK UNIFIED IDEOGRAPH-88B0 +U+88B1(2,3);U+88B1(2,3); # 74-64, CJK UNIFIED IDEOGRAPH-88B1 +U+88B4(2,3);U+88B4(2,3); # 24-51, CJK UNIFIED IDEOGRAPH-88B4 +U+88B5(2,3);U+88B5(2,3); # 74-52, CJK UNIFIED IDEOGRAPH-88B5 +U+88B7(2,3);U+88B7(2,3); # 16-33, CJK UNIFIED IDEOGRAPH-88B7 +U+88BF(2,3);U+88BF(2,3); # 74-63, CJK UNIFIED IDEOGRAPH-88BF +U+88C1(2,3);U+88C1(2,3); # 26-59, CJK UNIFIED IDEOGRAPH-88C1 +U+88C2(2,3);U+88C2(2,3); # 46-86, CJK UNIFIED IDEOGRAPH-88C2 +U+88C3(2,3);U+88C3(2,3); # 74-65, CJK UNIFIED IDEOGRAPH-88C3 +U+88C4(2,3);U+88C4(2,3); # 74-66, CJK UNIFIED IDEOGRAPH-88C4 +U+88C5(2,3);U+88C5(2,3); # 33-85, CJK UNIFIED IDEOGRAPH-88C5 +U+88CF(2,3);U+88CF(2,3); # 46-02, CJK UNIFIED IDEOGRAPH-88CF +U+88D4(2,3);U+88D4(2,3); # 74-67, CJK UNIFIED IDEOGRAPH-88D4 +U+88D5(2,3);U+88D5(2,3); # 45-21, CJK UNIFIED IDEOGRAPH-88D5 +U+88D8(2,3);U+88D8(2,3); # 74-68, CJK UNIFIED IDEOGRAPH-88D8 +U+88D9(2,3);U+88D9(2,3); # 74-69, CJK UNIFIED IDEOGRAPH-88D9 +U+88DC(2,3);U+88DC(2,3); # 42-68, CJK UNIFIED IDEOGRAPH-88DC +U+88DD(2,3);U+88DD(2,3); # 74-70, CJK UNIFIED IDEOGRAPH-88DD +U+88DF(2,3);U+88DF(2,3); # 26-32, CJK UNIFIED IDEOGRAPH-88DF +U+88E1(2,3);U+88E1(2,3); # 46-03, CJK UNIFIED IDEOGRAPH-88E1 +U+88E8(2,3);U+88E8(2,3); # 74-75, CJK UNIFIED IDEOGRAPH-88E8 +U+88F2(2,3);U+88F2(2,3); # 74-76, CJK UNIFIED IDEOGRAPH-88F2 +U+88F3(2,3);U+88F3(2,3); # 30-56, CJK UNIFIED IDEOGRAPH-88F3 +U+88F4(2,3);U+88F4(2,3); # 74-74, CJK UNIFIED IDEOGRAPH-88F4 +U+88F8(2,3);U+88F8(2,3); # 45-71, CJK UNIFIED IDEOGRAPH-88F8 +U+88F9(2,3);U+88F9(2,3); # 74-71, CJK UNIFIED IDEOGRAPH-88F9 +U+88FC(2,3);U+88FC(2,3); # 74-73, CJK UNIFIED IDEOGRAPH-88FC +U+88FD(2,3);U+88FD(2,3); # 32-29, CJK UNIFIED IDEOGRAPH-88FD +U+88FE(2,3);U+88FE(2,3); # 31-94, CJK UNIFIED IDEOGRAPH-88FE +U+8902(2,3);U+8902(2,3); # 74-72, CJK UNIFIED IDEOGRAPH-8902 +U+8904(2,3);U+8904(2,3); # 74-77, CJK UNIFIED IDEOGRAPH-8904 +U+8907(2,3);U+8907(2,3); # 42-03, CJK UNIFIED IDEOGRAPH-8907 +U+890A(2,3);U+890A(2,3); # 74-79, CJK UNIFIED IDEOGRAPH-890A +U+890C(2,3);U+890C(2,3); # 74-78, CJK UNIFIED IDEOGRAPH-890C +U+8910(2,3);U+8910(2,3); # 19-76, CJK UNIFIED IDEOGRAPH-8910 +U+8912(2,3);U+8912(2,3); # 43-11, CJK UNIFIED IDEOGRAPH-8912 +U+8913(2,3);U+8913(2,3); # 74-80, CJK UNIFIED IDEOGRAPH-8913 +U+891D(2,3);U+891D(2,3); # 74-92, CJK UNIFIED IDEOGRAPH-891D +U+891E(2,3);U+891E(2,3); # 74-82, CJK UNIFIED IDEOGRAPH-891E +U+8925(2,3);U+8925(2,3); # 74-83, CJK UNIFIED IDEOGRAPH-8925 +U+892A(2,3);U+892A(2,3); # 74-84, CJK UNIFIED IDEOGRAPH-892A +U+892B(2,3);U+892B(2,3); # 74-85, CJK UNIFIED IDEOGRAPH-892B +U+8936(2,3);U+8936(2,3); # 74-89, CJK UNIFIED IDEOGRAPH-8936 +U+8938(2,3);U+8938(2,3); # 74-90, CJK UNIFIED IDEOGRAPH-8938 +U+893B(2,3);U+893B(2,3); # 74-88, CJK UNIFIED IDEOGRAPH-893B +U+8941(2,3);U+8941(2,3); # 74-86, CJK UNIFIED IDEOGRAPH-8941 +U+8943(2,3);U+8943(2,3); # 74-81, CJK UNIFIED IDEOGRAPH-8943 +U+8944(2,3);U+8944(2,3); # 74-87, CJK UNIFIED IDEOGRAPH-8944 +U+894C(2,3);U+894C(2,3); # 74-91, CJK UNIFIED IDEOGRAPH-894C +U+894D(2,3);U+894D(2,3); # 80-23, CJK UNIFIED IDEOGRAPH-894D +U+8956(2,3);U+8956(2,3); # 18-08, CJK UNIFIED IDEOGRAPH-8956 +U+895E(2,3);U+895E(2,3); # 74-94, CJK UNIFIED IDEOGRAPH-895E +U+895F(2,3);U+895F(2,3); # 22-63, CJK UNIFIED IDEOGRAPH-895F +U+8960(2,3);U+8960(2,3); # 74-93, CJK UNIFIED IDEOGRAPH-8960 +U+8964(2,3);U+8964(2,3); # 75-02, CJK UNIFIED IDEOGRAPH-8964 +U+8966(2,3);U+8966(2,3); # 75-01, CJK UNIFIED IDEOGRAPH-8966 +U+896A(2,3);U+896A(2,3); # 75-04, CJK UNIFIED IDEOGRAPH-896A +U+896D(2,3);U+896D(2,3); # 75-03, CJK UNIFIED IDEOGRAPH-896D +U+896F(2,3);U+896F(2,3); # 75-05, CJK UNIFIED IDEOGRAPH-896F +U+8972(2,3);U+8972(2,3); # 29-17, CJK UNIFIED IDEOGRAPH-8972 +U+8974(2,3);U+8974(2,3); # 75-06, CJK UNIFIED IDEOGRAPH-8974 +U+8977(2,3);U+8977(2,3); # 75-07, CJK UNIFIED IDEOGRAPH-8977 +U+897E(2,3);U+897E(2,3); # 75-08, CJK UNIFIED IDEOGRAPH-897E +U+897F(2,3);U+897F(2,3); # 32-30, CJK UNIFIED IDEOGRAPH-897F +U+8981(2,3);U+8981(2,3); # 45-55, CJK UNIFIED IDEOGRAPH-8981 +U+8983(2,3);U+8983(2,3); # 75-09, CJK UNIFIED IDEOGRAPH-8983 +U+8986(2,3);U+8986(2,3); # 42-04, CJK UNIFIED IDEOGRAPH-8986 +U+8987(2,3);U+8987(2,3); # 39-38, CJK UNIFIED IDEOGRAPH-8987 +U+8988(2,3);U+8988(2,3); # 75-10, CJK UNIFIED IDEOGRAPH-8988 +U+898A(2,3);U+898A(2,3); # 75-11, CJK UNIFIED IDEOGRAPH-898A +U+898B(2,3);U+898B(2,3); # 24-11, CJK UNIFIED IDEOGRAPH-898B +U+898F(2,3);U+898F(2,3); # 21-12, CJK UNIFIED IDEOGRAPH-898F +U+8993(2,3);U+8993(2,3); # 75-12, CJK UNIFIED IDEOGRAPH-8993 +U+8996(2,3);U+8996(2,3); # 27-75, CJK UNIFIED IDEOGRAPH-8996 +U+8997(2,3);U+8997(2,3); # 39-33, CJK UNIFIED IDEOGRAPH-8997 +U+8998(2,3);U+8998(2,3); # 75-13, CJK UNIFIED IDEOGRAPH-8998 +U+899A(2,3);U+899A(2,3); # 19-48, CJK UNIFIED IDEOGRAPH-899A +U+89A1(2,3);U+89A1(2,3); # 75-14, CJK UNIFIED IDEOGRAPH-89A1 +U+89A6(2,3);U+89A6(2,3); # 75-16, CJK UNIFIED IDEOGRAPH-89A6 +U+89A7(2,3);U+89A7(2,3); # 45-87, CJK UNIFIED IDEOGRAPH-89A7 +U+89A9(2,3);U+89A9(2,3); # 75-15, CJK UNIFIED IDEOGRAPH-89A9 +U+89AA(2,3);U+89AA(2,3); # 31-38, CJK UNIFIED IDEOGRAPH-89AA +U+89AC(2,3);U+89AC(2,3); # 75-17, CJK UNIFIED IDEOGRAPH-89AC +U+89AF(2,3);U+89AF(2,3); # 75-18, CJK UNIFIED IDEOGRAPH-89AF +U+89B2(2,3);U+89B2(2,3); # 75-19, CJK UNIFIED IDEOGRAPH-89B2 +U+89B3(2,3);U+89B3(2,3); # 20-49, CJK UNIFIED IDEOGRAPH-89B3 +U+89BA(2,3);U+89BA(2,3); # 75-20, CJK UNIFIED IDEOGRAPH-89BA +U+89BD(2,3);U+89BD(2,3); # 75-21, CJK UNIFIED IDEOGRAPH-89BD +U+89BF(2,3);U+89BF(2,3); # 75-22, CJK UNIFIED IDEOGRAPH-89BF +U+89C0(2,3);U+89C0(2,3); # 75-23, CJK UNIFIED IDEOGRAPH-89C0 +U+89D2(2,3);U+89D2(2,3); # 19-49, CJK UNIFIED IDEOGRAPH-89D2 +U+89DA(2,3);U+89DA(2,3); # 75-24, CJK UNIFIED IDEOGRAPH-89DA +U+89DC(2,3);U+89DC(2,3); # 75-25, CJK UNIFIED IDEOGRAPH-89DC +U+89DD(2,3);U+89DD(2,3); # 75-26, CJK UNIFIED IDEOGRAPH-89DD +U+89E3(2,3);U+89E3(2,3); # 18-82, CJK UNIFIED IDEOGRAPH-89E3 +U+89E6(2,3);U+89E6(2,3); # 31-08, CJK UNIFIED IDEOGRAPH-89E6 +U+89E7(2,3);U+89E7(2,3); # 75-27, CJK UNIFIED IDEOGRAPH-89E7 +U+89F4(2,3);U+89F4(2,3); # 75-28, CJK UNIFIED IDEOGRAPH-89F4 +U+89F8(2,3);U+89F8(2,3); # 75-29, CJK UNIFIED IDEOGRAPH-89F8 +U+8A00(2,3);U+8A00(2,3); # 24-32, CJK UNIFIED IDEOGRAPH-8A00 +U+8A02(2,3);U+8A02(2,3); # 36-91, CJK UNIFIED IDEOGRAPH-8A02 +U+8A03(2,3);U+8A03(2,3); # 75-30, CJK UNIFIED IDEOGRAPH-8A03 +U+8A08(2,3);U+8A08(2,3); # 23-55, CJK UNIFIED IDEOGRAPH-8A08 +U+8A0A(2,3);U+8A0A(2,3); # 31-54, CJK UNIFIED IDEOGRAPH-8A0A +U+8A0C(2,3);U+8A0C(2,3); # 75-33, CJK UNIFIED IDEOGRAPH-8A0C +U+8A0E(2,3);U+8A0E(2,3); # 38-04, CJK UNIFIED IDEOGRAPH-8A0E +U+8A10(2,3);U+8A10(2,3); # 75-32, CJK UNIFIED IDEOGRAPH-8A10 +U+8A13(2,3);U+8A13(2,3); # 23-17, CJK UNIFIED IDEOGRAPH-8A13 +U+8A16(2,3);U+8A16(2,3); # 75-31, CJK UNIFIED IDEOGRAPH-8A16 +U+8A17(2,3);U+8A17(2,3); # 34-87, CJK UNIFIED IDEOGRAPH-8A17 +U+8A18(2,3);U+8A18(2,3); # 21-13, CJK UNIFIED IDEOGRAPH-8A18 +U+8A1B(2,3);U+8A1B(2,3); # 75-34, CJK UNIFIED IDEOGRAPH-8A1B +U+8A1D(2,3);U+8A1D(2,3); # 75-35, CJK UNIFIED IDEOGRAPH-8A1D +U+8A1F(2,3);U+8A1F(2,3); # 30-57, CJK UNIFIED IDEOGRAPH-8A1F +U+8A23(2,3);U+8A23(2,3); # 23-77, CJK UNIFIED IDEOGRAPH-8A23 +U+8A25(2,3);U+8A25(2,3); # 75-36, CJK UNIFIED IDEOGRAPH-8A25 +U+8A2A(2,3);U+8A2A(2,3); # 43-12, CJK UNIFIED IDEOGRAPH-8A2A +U+8A2D(2,3);U+8A2D(2,3); # 32-63, CJK UNIFIED IDEOGRAPH-8A2D +U+8A31(2,3);U+8A31(2,3); # 21-86, CJK UNIFIED IDEOGRAPH-8A31 +U+8A33(2,3);U+8A33(2,3); # 44-85, CJK UNIFIED IDEOGRAPH-8A33 +U+8A34(2,3);U+8A34(2,3); # 33-42, CJK UNIFIED IDEOGRAPH-8A34 +U+8A36(2,3);U+8A36(2,3); # 75-37, CJK UNIFIED IDEOGRAPH-8A36 +U+8A3A(2,3);U+8A3A(2,3); # 31-39, CJK UNIFIED IDEOGRAPH-8A3A +U+8A3B(2,3);U+8A3B(2,3); # 35-80, CJK UNIFIED IDEOGRAPH-8A3B +U+8A3C(2,3);U+8A3C(2,3); # 30-58, CJK UNIFIED IDEOGRAPH-8A3C +U+8A41(2,3);U+8A41(2,3); # 75-38, CJK UNIFIED IDEOGRAPH-8A41 +U+8A46(2,3);U+8A46(2,3); # 75-41, CJK UNIFIED IDEOGRAPH-8A46 +U+8A48(2,3);U+8A48(2,3); # 75-42, CJK UNIFIED IDEOGRAPH-8A48 +U+8A50(2,3);U+8A50(2,3); # 26-30, CJK UNIFIED IDEOGRAPH-8A50 +U+8A51(2,3);U+8A51(2,3); # 34-34, CJK UNIFIED IDEOGRAPH-8A51 +U+8A52(2,3);U+8A52(2,3); # 75-40, CJK UNIFIED IDEOGRAPH-8A52 +U+8A54(2,3);U+8A54(2,3); # 30-59, CJK UNIFIED IDEOGRAPH-8A54 +U+8A55(2,3);U+8A55(2,3); # 41-30, CJK UNIFIED IDEOGRAPH-8A55 +U+8A5B(2,3);U+8A5B(2,3); # 75-39, CJK UNIFIED IDEOGRAPH-8A5B +U+8A5E(2,3);U+8A5E(2,3); # 27-76, CJK UNIFIED IDEOGRAPH-8A5E +U+8A60(2,3);U+8A60(2,3); # 17-51, CJK UNIFIED IDEOGRAPH-8A60 +U+8A62(2,3);U+8A62(2,3); # 75-46, CJK UNIFIED IDEOGRAPH-8A62 +U+8A63(2,3);U+8A63(2,3); # 23-56, CJK UNIFIED IDEOGRAPH-8A63 +U+8A66(2,3);U+8A66(2,3); # 27-78, CJK UNIFIED IDEOGRAPH-8A66 +U+8A69(2,3);U+8A69(2,3); # 27-77, CJK UNIFIED IDEOGRAPH-8A69 +U+8A6B(2,3);U+8A6B(2,3); # 47-45, CJK UNIFIED IDEOGRAPH-8A6B +U+8A6C(2,3);U+8A6C(2,3); # 75-45, CJK UNIFIED IDEOGRAPH-8A6C +U+8A6D(2,3);U+8A6D(2,3); # 75-44, CJK UNIFIED IDEOGRAPH-8A6D +U+8A6E(2,3);U+8A6E(2,3); # 33-07, CJK UNIFIED IDEOGRAPH-8A6E +U+8A70(2,3);U+8A70(2,3); # 21-45, CJK UNIFIED IDEOGRAPH-8A70 +U+8A71(2,3);U+8A71(2,3); # 47-35, CJK UNIFIED IDEOGRAPH-8A71 +U+8A72(2,3);U+8A72(2,3); # 19-26, CJK UNIFIED IDEOGRAPH-8A72 +U+8A73(2,3);U+8A73(2,3); # 30-60, CJK UNIFIED IDEOGRAPH-8A73 +U+8A7C(2,3);U+8A7C(2,3); # 75-43, CJK UNIFIED IDEOGRAPH-8A7C +U+8A82(2,3);U+8A82(2,3); # 75-48, CJK UNIFIED IDEOGRAPH-8A82 +U+8A84(2,3);U+8A84(2,3); # 75-49, CJK UNIFIED IDEOGRAPH-8A84 +U+8A85(2,3);U+8A85(2,3); # 75-47, CJK UNIFIED IDEOGRAPH-8A85 +U+8A87(2,3);U+8A87(2,3); # 24-56, CJK UNIFIED IDEOGRAPH-8A87 +U+8A89(2,3);U+8A89(2,3); # 45-32, CJK UNIFIED IDEOGRAPH-8A89 +U+8A8C(2,3);U+8A8C(2,3); # 27-79, CJK UNIFIED IDEOGRAPH-8A8C +U+8A8D(2,3);U+8A8D(2,3); # 39-07, CJK UNIFIED IDEOGRAPH-8A8D +U+8A91(2,3);U+8A91(2,3); # 75-52, CJK UNIFIED IDEOGRAPH-8A91 +U+8A93(2,3);U+8A93(2,3); # 32-32, CJK UNIFIED IDEOGRAPH-8A93 +U+8A95(2,3);U+8A95(2,3); # 35-34, CJK UNIFIED IDEOGRAPH-8A95 +U+8A98(2,3);U+8A98(2,3); # 45-22, CJK UNIFIED IDEOGRAPH-8A98 +U+8A9A(2,3);U+8A9A(2,3); # 75-55, CJK UNIFIED IDEOGRAPH-8A9A +U+8A9E(2,3);U+8A9E(2,3); # 24-76, CJK UNIFIED IDEOGRAPH-8A9E +U+8AA0(2,3);U+8AA0(2,3); # 32-31, CJK UNIFIED IDEOGRAPH-8AA0 +U+8AA1(2,3);U+8AA1(2,3); # 75-51, CJK UNIFIED IDEOGRAPH-8AA1 +U+8AA3(2,3);U+8AA3(2,3); # 75-56, CJK UNIFIED IDEOGRAPH-8AA3 +U+8AA4(2,3);U+8AA4(2,3); # 24-77, CJK UNIFIED IDEOGRAPH-8AA4 +U+8AA5(2,3);U+8AA5(2,3); # 75-53, CJK UNIFIED IDEOGRAPH-8AA5 +U+8AA6(2,3);U+8AA6(2,3); # 75-54, CJK UNIFIED IDEOGRAPH-8AA6 +U+8AA8(2,3);U+8AA8(2,3); # 75-50, CJK UNIFIED IDEOGRAPH-8AA8 +U+8AAC(2,3);U+8AAC(2,3); # 32-66, CJK UNIFIED IDEOGRAPH-8AAC +U+8AAD(2,3);U+8AAD(2,3); # 38-41, CJK UNIFIED IDEOGRAPH-8AAD +U+8AB0(2,3);U+8AB0(2,3); # 35-15, CJK UNIFIED IDEOGRAPH-8AB0 +U+8AB2(2,3);U+8AB2(2,3); # 18-61, CJK UNIFIED IDEOGRAPH-8AB2 +U+8AB9(2,3);U+8AB9(2,3); # 40-80, CJK UNIFIED IDEOGRAPH-8AB9 +U+8ABC(2,3);U+8ABC(2,3); # 21-35, CJK UNIFIED IDEOGRAPH-8ABC +U+8ABF(2,3);U+8ABF(2,3); # 36-20, CJK UNIFIED IDEOGRAPH-8ABF +U+8AC2(2,3);U+8AC2(2,3); # 75-59, CJK UNIFIED IDEOGRAPH-8AC2 +U+8AC4(2,3);U+8AC4(2,3); # 75-57, CJK UNIFIED IDEOGRAPH-8AC4 +U+8AC7(2,3);U+8AC7(2,3); # 35-44, CJK UNIFIED IDEOGRAPH-8AC7 +U+8ACB(2,3);U+8ACB(2,3); # 32-33, CJK UNIFIED IDEOGRAPH-8ACB +U+8ACC(2,3);U+8ACC(2,3); # 20-50, CJK UNIFIED IDEOGRAPH-8ACC +U+8ACD(2,3);U+8ACD(2,3); # 75-58, CJK UNIFIED IDEOGRAPH-8ACD +U+8ACF(2,3);U+8ACF(2,3); # 31-59, CJK UNIFIED IDEOGRAPH-8ACF +U+8AD2(2,3);U+8AD2(2,3); # 46-42, CJK UNIFIED IDEOGRAPH-8AD2 +U+8AD6(2,3);U+8AD6(2,3); # 47-32, CJK UNIFIED IDEOGRAPH-8AD6 +U+8ADA(2,3);U+8ADA(2,3); # 75-60, CJK UNIFIED IDEOGRAPH-8ADA +U+8ADB(2,3);U+8ADB(2,3); # 75-71, CJK UNIFIED IDEOGRAPH-8ADB +U+8ADC(2,3);U+8ADC(2,3); # 36-21, CJK UNIFIED IDEOGRAPH-8ADC +U+8ADE(2,3);U+8ADE(2,3); # 75-70, CJK UNIFIED IDEOGRAPH-8ADE +U+8AE0(2,3);U+8AE0(2,3); # 75-67, CJK UNIFIED IDEOGRAPH-8AE0 +U+8AE1(2,3);U+8AE1(2,3); # 75-75, CJK UNIFIED IDEOGRAPH-8AE1 +U+8AE2(2,3);U+8AE2(2,3); # 75-68, CJK UNIFIED IDEOGRAPH-8AE2 +U+8AE4(2,3);U+8AE4(2,3); # 75-64, CJK UNIFIED IDEOGRAPH-8AE4 +U+8AE6(2,3);U+8AE6(2,3); # 36-92, CJK UNIFIED IDEOGRAPH-8AE6 +U+8AE7(2,3);U+8AE7(2,3); # 75-63, CJK UNIFIED IDEOGRAPH-8AE7 +U+8AEB(2,3);U+8AEB(2,3); # 75-61, CJK UNIFIED IDEOGRAPH-8AEB +U+8AED(2,3);U+8AED(2,3); # 45-01, CJK UNIFIED IDEOGRAPH-8AED +U+8AEE(2,3);U+8AEE(2,3); # 27-80, CJK UNIFIED IDEOGRAPH-8AEE +U+8AF1(2,3);U+8AF1(2,3); # 75-65, CJK UNIFIED IDEOGRAPH-8AF1 +U+8AF3(2,3);U+8AF3(2,3); # 75-62, CJK UNIFIED IDEOGRAPH-8AF3 +U+8AF7(2,3);U+8AF7(2,3); # 75-69, CJK UNIFIED IDEOGRAPH-8AF7 +U+8AF8(2,3);U+8AF8(2,3); # 29-84, CJK UNIFIED IDEOGRAPH-8AF8 +U+8AFA(2,3);U+8AFA(2,3); # 24-33, CJK UNIFIED IDEOGRAPH-8AFA +U+8AFE(2,3);U+8AFE(2,3); # 34-90, CJK UNIFIED IDEOGRAPH-8AFE +U+8B00(2,3);U+8B00(2,3); # 43-37, CJK UNIFIED IDEOGRAPH-8B00 +U+8B01(2,3);U+8B01(2,3); # 17-58, CJK UNIFIED IDEOGRAPH-8B01 +U+8B02(2,3);U+8B02(2,3); # 16-66, CJK UNIFIED IDEOGRAPH-8B02 +U+8B04(2,3);U+8B04(2,3); # 38-05, CJK UNIFIED IDEOGRAPH-8B04 +U+8B07(2,3);U+8B07(2,3); # 75-73, CJK UNIFIED IDEOGRAPH-8B07 +U+8B0C(2,3);U+8B0C(2,3); # 75-72, CJK UNIFIED IDEOGRAPH-8B0C +U+8B0E(2,3);U+8B0E(2,3); # 38-70, CJK UNIFIED IDEOGRAPH-8B0E +U+8B10(2,3);U+8B10(2,3); # 75-77, CJK UNIFIED IDEOGRAPH-8B10 +U+8B14(2,3);U+8B14(2,3); # 75-66, CJK UNIFIED IDEOGRAPH-8B14 +U+8B16(2,3);U+8B16(2,3); # 75-76, CJK UNIFIED IDEOGRAPH-8B16 +U+8B17(2,3);U+8B17(2,3); # 75-78, CJK UNIFIED IDEOGRAPH-8B17 +U+8B19(2,3);U+8B19(2,3); # 24-12, CJK UNIFIED IDEOGRAPH-8B19 +U+8B1A(2,3);U+8B1A(2,3); # 75-74, CJK UNIFIED IDEOGRAPH-8B1A +U+8B1B(2,3);U+8B1B(2,3); # 25-54, CJK UNIFIED IDEOGRAPH-8B1B +U+8B1D(2,3);U+8B1D(2,3); # 28-53, CJK UNIFIED IDEOGRAPH-8B1D +U+8B20(2,3);U+8B20(2,3); # 75-79, CJK UNIFIED IDEOGRAPH-8B20 +U+8B21(2,3);U+8B21(2,3); # 45-56, CJK UNIFIED IDEOGRAPH-8B21 +U+8B26(2,3);U+8B26(2,3); # 75-82, CJK UNIFIED IDEOGRAPH-8B26 +U+8B28(2,3);U+8B28(2,3); # 75-85, CJK UNIFIED IDEOGRAPH-8B28 +U+8B2B(2,3);U+8B2B(2,3); # 75-83, CJK UNIFIED IDEOGRAPH-8B2B +U+8B2C(2,3);U+8B2C(2,3); # 41-21, CJK UNIFIED IDEOGRAPH-8B2C +U+8B33(2,3);U+8B33(2,3); # 75-80, CJK UNIFIED IDEOGRAPH-8B33 +U+8B39(2,3);U+8B39(2,3); # 22-64, CJK UNIFIED IDEOGRAPH-8B39 +U+8B3E(2,3);U+8B3E(2,3); # 75-84, CJK UNIFIED IDEOGRAPH-8B3E +U+8B41(2,3);U+8B41(2,3); # 75-86, CJK UNIFIED IDEOGRAPH-8B41 +U+8B49(2,3);U+8B49(2,3); # 75-90, CJK UNIFIED IDEOGRAPH-8B49 +U+8B4C(2,3);U+8B4C(2,3); # 75-87, CJK UNIFIED IDEOGRAPH-8B4C +U+8B4E(2,3);U+8B4E(2,3); # 75-89, CJK UNIFIED IDEOGRAPH-8B4E +U+8B4F(2,3);U+8B4F(2,3); # 75-88, CJK UNIFIED IDEOGRAPH-8B4F +U+8B56(2,3);U+8B56(2,3); # 75-91, CJK UNIFIED IDEOGRAPH-8B56 +U+8B58(2,3);U+8B58(2,3); # 28-17, CJK UNIFIED IDEOGRAPH-8B58 +U+8B5A(2,3);U+8B5A(2,3); # 75-93, CJK UNIFIED IDEOGRAPH-8B5A +U+8B5B(2,3);U+8B5B(2,3); # 75-92, CJK UNIFIED IDEOGRAPH-8B5B +U+8B5C(2,3);U+8B5C(2,3); # 41-72, CJK UNIFIED IDEOGRAPH-8B5C +U+8B5F(2,3);U+8B5F(2,3); # 76-01, CJK UNIFIED IDEOGRAPH-8B5F +U+8B66(2,3);U+8B66(2,3); # 23-57, CJK UNIFIED IDEOGRAPH-8B66 +U+8B6B(2,3);U+8B6B(2,3); # 75-94, CJK UNIFIED IDEOGRAPH-8B6B +U+8B6C(2,3);U+8B6C(2,3); # 76-02, CJK UNIFIED IDEOGRAPH-8B6C +U+8B6F(2,3);U+8B6F(2,3); # 76-03, CJK UNIFIED IDEOGRAPH-8B6F +U+8B70(2,3);U+8B70(2,3); # 21-36, CJK UNIFIED IDEOGRAPH-8B70 +U+8B71(2,3);U+8B71(2,3); # 70-33, CJK UNIFIED IDEOGRAPH-8B71 +U+8B72(2,3);U+8B72(2,3); # 30-89, CJK UNIFIED IDEOGRAPH-8B72 +U+8B74(2,3);U+8B74(2,3); # 76-04, CJK UNIFIED IDEOGRAPH-8B74 +U+8B77(2,3);U+8B77(2,3); # 24-78, CJK UNIFIED IDEOGRAPH-8B77 +U+8B7D(2,3);U+8B7D(2,3); # 76-05, CJK UNIFIED IDEOGRAPH-8B7D +U+8B80(2,3);U+8B80(2,3); # 76-06, CJK UNIFIED IDEOGRAPH-8B80 +U+8B83(2,3);U+8B83(2,3); # 27-30, CJK UNIFIED IDEOGRAPH-8B83 +U+8B8A(2,3);U+8B8A(2,3); # 58-46, CJK UNIFIED IDEOGRAPH-8B8A +U+8B8C(2,3);U+8B8C(2,3); # 76-07, CJK UNIFIED IDEOGRAPH-8B8C +U+8B8E(2,3);U+8B8E(2,3); # 76-08, CJK UNIFIED IDEOGRAPH-8B8E +U+8B90(2,3);U+8B90(2,3); # 29-18, CJK UNIFIED IDEOGRAPH-8B90 +U+8B92(2,3);U+8B92(2,3); # 76-09, CJK UNIFIED IDEOGRAPH-8B92 +U+8B93(2,3);U+8B93(2,3); # 76-10, CJK UNIFIED IDEOGRAPH-8B93 +U+8B96(2,3);U+8B96(2,3); # 76-11, CJK UNIFIED IDEOGRAPH-8B96 +U+8B99(2,3);U+8B99(2,3); # 76-12, CJK UNIFIED IDEOGRAPH-8B99 +U+8B9A(2,3);U+8B9A(2,3); # 76-13, CJK UNIFIED IDEOGRAPH-8B9A +U+8C37(2,3);U+8C37(2,3); # 35-11, CJK UNIFIED IDEOGRAPH-8C37 +U+8C3A(2,3);U+8C3A(2,3); # 76-14, CJK UNIFIED IDEOGRAPH-8C3A +U+8C3F(2,3);U+8C3F(2,3); # 76-16, CJK UNIFIED IDEOGRAPH-8C3F +U+8C41(2,3);U+8C41(2,3); # 76-15, CJK UNIFIED IDEOGRAPH-8C41 +U+8C46(2,3);U+8C46(2,3); # 38-06, CJK UNIFIED IDEOGRAPH-8C46 +U+8C48(2,3);U+8C48(2,3); # 76-17, CJK UNIFIED IDEOGRAPH-8C48 +U+8C4A(2,3);U+8C4A(2,3); # 43-13, CJK UNIFIED IDEOGRAPH-8C4A +U+8C4C(2,3);U+8C4C(2,3); # 76-18, CJK UNIFIED IDEOGRAPH-8C4C +U+8C4E(2,3);U+8C4E(2,3); # 76-19, CJK UNIFIED IDEOGRAPH-8C4E +U+8C50(2,3);U+8C50(2,3); # 76-20, CJK UNIFIED IDEOGRAPH-8C50 +U+8C55(2,3);U+8C55(2,3); # 76-21, CJK UNIFIED IDEOGRAPH-8C55 +U+8C5A(2,3);U+8C5A(2,3); # 38-58, CJK UNIFIED IDEOGRAPH-8C5A +U+8C61(2,3);U+8C61(2,3); # 30-61, CJK UNIFIED IDEOGRAPH-8C61 +U+8C62(2,3);U+8C62(2,3); # 76-22, CJK UNIFIED IDEOGRAPH-8C62 +U+8C6A(2,3);U+8C6A(2,3); # 25-75, CJK UNIFIED IDEOGRAPH-8C6A +U+8C6B(2,3);U+8C6B(2,3); # 48-14, CJK UNIFIED IDEOGRAPH-8C6B +U+8C6C(2,3);U+8C6C(2,3); # 76-23, CJK UNIFIED IDEOGRAPH-8C6C +U+8C78(2,3);U+8C78(2,3); # 76-24, CJK UNIFIED IDEOGRAPH-8C78 +U+8C79(2,3);U+8C79(2,3); # 41-31, CJK UNIFIED IDEOGRAPH-8C79 +U+8C7A(2,3);U+8C7A(2,3); # 76-25, CJK UNIFIED IDEOGRAPH-8C7A +U+8C7C(2,3);U+8C7C(2,3); # 76-33, CJK UNIFIED IDEOGRAPH-8C7C +U+8C82(2,3);U+8C82(2,3); # 76-26, CJK UNIFIED IDEOGRAPH-8C82 +U+8C85(2,3);U+8C85(2,3); # 76-28, CJK UNIFIED IDEOGRAPH-8C85 +U+8C89(2,3);U+8C89(2,3); # 76-27, CJK UNIFIED IDEOGRAPH-8C89 +U+8C8A(2,3);U+8C8A(2,3); # 76-29, CJK UNIFIED IDEOGRAPH-8C8A +U+8C8C(2,3);U+8C8C(2,3); # 43-38, CJK UNIFIED IDEOGRAPH-8C8C +U+8C8D(2,3);U+8C8D(2,3); # 76-30, CJK UNIFIED IDEOGRAPH-8C8D +U+8C8E(2,3);U+8C8E(2,3); # 76-31, CJK UNIFIED IDEOGRAPH-8C8E +U+8C94(2,3);U+8C94(2,3); # 76-32, CJK UNIFIED IDEOGRAPH-8C94 +U+8C98(2,3);U+8C98(2,3); # 76-34, CJK UNIFIED IDEOGRAPH-8C98 +U+8C9D(2,3);U+8C9D(2,3); # 19-13, CJK UNIFIED IDEOGRAPH-8C9D +U+8C9E(2,3);U+8C9E(2,3); # 36-71, CJK UNIFIED IDEOGRAPH-8C9E +U+8CA0(2,3);U+8CA0(2,3); # 41-73, CJK UNIFIED IDEOGRAPH-8CA0 +U+8CA1(2,3);U+8CA1(2,3); # 26-66, CJK UNIFIED IDEOGRAPH-8CA1 +U+8CA2(2,3);U+8CA2(2,3); # 25-55, CJK UNIFIED IDEOGRAPH-8CA2 +U+8CA7(2,3);U+8CA7(2,3); # 41-47, CJK UNIFIED IDEOGRAPH-8CA7 +U+8CA8(2,3);U+8CA8(2,3); # 18-63, CJK UNIFIED IDEOGRAPH-8CA8 +U+8CA9(2,3);U+8CA9(2,3); # 40-46, CJK UNIFIED IDEOGRAPH-8CA9 +U+8CAA(2,3);U+8CAA(2,3); # 76-37, CJK UNIFIED IDEOGRAPH-8CAA +U+8CAB(2,3);U+8CAB(2,3); # 20-51, CJK UNIFIED IDEOGRAPH-8CAB +U+8CAC(2,3);U+8CAC(2,3); # 32-53, CJK UNIFIED IDEOGRAPH-8CAC +U+8CAD(2,3);U+8CAD(2,3); # 76-36, CJK UNIFIED IDEOGRAPH-8CAD +U+8CAE(2,3);U+8CAE(2,3); # 76-41, CJK UNIFIED IDEOGRAPH-8CAE +U+8CAF(2,3);U+8CAF(2,3); # 35-89, CJK UNIFIED IDEOGRAPH-8CAF +U+8CB0(2,3);U+8CB0(2,3); # 44-67, CJK UNIFIED IDEOGRAPH-8CB0 +U+8CB2(2,3);U+8CB2(2,3); # 76-39, CJK UNIFIED IDEOGRAPH-8CB2 +U+8CB3(2,3);U+8CB3(2,3); # 76-40, CJK UNIFIED IDEOGRAPH-8CB3 +U+8CB4(2,3);U+8CB4(2,3); # 21-14, CJK UNIFIED IDEOGRAPH-8CB4 +U+8CB6(2,3);U+8CB6(2,3); # 76-42, CJK UNIFIED IDEOGRAPH-8CB6 +U+8CB7(2,3);U+8CB7(2,3); # 39-67, CJK UNIFIED IDEOGRAPH-8CB7 +U+8CB8(2,3);U+8CB8(2,3); # 34-63, CJK UNIFIED IDEOGRAPH-8CB8 +U+8CBB(2,3);U+8CBB(2,3); # 40-81, CJK UNIFIED IDEOGRAPH-8CBB +U+8CBC(2,3);U+8CBC(2,3); # 37-29, CJK UNIFIED IDEOGRAPH-8CBC +U+8CBD(2,3);U+8CBD(2,3); # 76-38, CJK UNIFIED IDEOGRAPH-8CBD +U+8CBF(2,3);U+8CBF(2,3); # 43-39, CJK UNIFIED IDEOGRAPH-8CBF +U+8CC0(2,3);U+8CC0(2,3); # 18-76, CJK UNIFIED IDEOGRAPH-8CC0 +U+8CC1(2,3);U+8CC1(2,3); # 76-44, CJK UNIFIED IDEOGRAPH-8CC1 +U+8CC2(2,3);U+8CC2(2,3); # 47-08, CJK UNIFIED IDEOGRAPH-8CC2 +U+8CC3(2,3);U+8CC3(2,3); # 36-34, CJK UNIFIED IDEOGRAPH-8CC3 +U+8CC4(2,3);U+8CC4(2,3); # 47-37, CJK UNIFIED IDEOGRAPH-8CC4 +U+8CC7(2,3);U+8CC7(2,3); # 27-81, CJK UNIFIED IDEOGRAPH-8CC7 +U+8CC8(2,3);U+8CC8(2,3); # 76-43, CJK UNIFIED IDEOGRAPH-8CC8 +U+8CCA(2,3);U+8CCA(2,3); # 34-17, CJK UNIFIED IDEOGRAPH-8CCA +U+8CCD(2,3);U+8CCD(2,3); # 76-60, CJK UNIFIED IDEOGRAPH-8CCD +U+8CCE(2,3);U+8CCE(2,3); # 33-08, CJK UNIFIED IDEOGRAPH-8CCE +U+8CD1(2,3);U+8CD1(2,3); # 38-88, CJK UNIFIED IDEOGRAPH-8CD1 +U+8CD3(2,3);U+8CD3(2,3); # 41-48, CJK UNIFIED IDEOGRAPH-8CD3 +U+8CDA(2,3);U+8CDA(2,3); # 76-47, CJK UNIFIED IDEOGRAPH-8CDA +U+8CDB(2,3);U+8CDB(2,3); # 27-31, CJK UNIFIED IDEOGRAPH-8CDB +U+8CDC(2,3);U+8CDC(2,3); # 27-82, CJK UNIFIED IDEOGRAPH-8CDC +U+8CDE(2,3);U+8CDE(2,3); # 30-62, CJK UNIFIED IDEOGRAPH-8CDE +U+8CE0(2,3);U+8CE0(2,3); # 39-69, CJK UNIFIED IDEOGRAPH-8CE0 +U+8CE2(2,3);U+8CE2(2,3); # 24-13, CJK UNIFIED IDEOGRAPH-8CE2 +U+8CE3(2,3);U+8CE3(2,3); # 76-46, CJK UNIFIED IDEOGRAPH-8CE3 +U+8CE4(2,3);U+8CE4(2,3); # 76-45, CJK UNIFIED IDEOGRAPH-8CE4 +U+8CE6(2,3);U+8CE6(2,3); # 41-74, CJK UNIFIED IDEOGRAPH-8CE6 +U+8CEA(2,3);U+8CEA(2,3); # 28-33, CJK UNIFIED IDEOGRAPH-8CEA +U+8CED(2,3);U+8CED(2,3); # 37-50, CJK UNIFIED IDEOGRAPH-8CED +U+8CFA(2,3);U+8CFA(2,3); # 76-49, CJK UNIFIED IDEOGRAPH-8CFA +U+8CFB(2,3);U+8CFB(2,3); # 76-50, CJK UNIFIED IDEOGRAPH-8CFB +U+8CFC(2,3);U+8CFC(2,3); # 25-56, CJK UNIFIED IDEOGRAPH-8CFC +U+8CFD(2,3);U+8CFD(2,3); # 76-48, CJK UNIFIED IDEOGRAPH-8CFD +U+8D04(2,3);U+8D04(2,3); # 76-51, CJK UNIFIED IDEOGRAPH-8D04 +U+8D05(2,3);U+8D05(2,3); # 76-52, CJK UNIFIED IDEOGRAPH-8D05 +U+8D07(2,3);U+8D07(2,3); # 76-54, CJK UNIFIED IDEOGRAPH-8D07 +U+8D08(2,3);U+8D08(2,3); # 34-03, CJK UNIFIED IDEOGRAPH-8D08 +U+8D0A(2,3);U+8D0A(2,3); # 76-53, CJK UNIFIED IDEOGRAPH-8D0A +U+8D0B(2,3);U+8D0B(2,3); # 20-70, CJK UNIFIED IDEOGRAPH-8D0B +U+8D0D(2,3);U+8D0D(2,3); # 76-56, CJK UNIFIED IDEOGRAPH-8D0D +U+8D0F(2,3);U+8D0F(2,3); # 76-55, CJK UNIFIED IDEOGRAPH-8D0F +U+8D10(2,3);U+8D10(2,3); # 76-57, CJK UNIFIED IDEOGRAPH-8D10 +U+8D13(2,3);U+8D13(2,3); # 76-59, CJK UNIFIED IDEOGRAPH-8D13 +U+8D14(2,3);U+8D14(2,3); # 76-61, CJK UNIFIED IDEOGRAPH-8D14 +U+8D16(2,3);U+8D16(2,3); # 76-62, CJK UNIFIED IDEOGRAPH-8D16 +U+8D64(2,3);U+8D64(2,3); # 32-54, CJK UNIFIED IDEOGRAPH-8D64 +U+8D66(2,3);U+8D66(2,3); # 28-47, CJK UNIFIED IDEOGRAPH-8D66 +U+8D67(2,3);U+8D67(2,3); # 76-63, CJK UNIFIED IDEOGRAPH-8D67 +U+8D6B(2,3);U+8D6B(2,3); # 19-50, CJK UNIFIED IDEOGRAPH-8D6B +U+8D6D(2,3);U+8D6D(2,3); # 76-64, CJK UNIFIED IDEOGRAPH-8D6D +U+8D70(2,3);U+8D70(2,3); # 33-86, CJK UNIFIED IDEOGRAPH-8D70 +U+8D71(2,3);U+8D71(2,3); # 76-65, CJK UNIFIED IDEOGRAPH-8D71 +U+8D73(2,3);U+8D73(2,3); # 76-66, CJK UNIFIED IDEOGRAPH-8D73 +U+8D74(2,3);U+8D74(2,3); # 41-75, CJK UNIFIED IDEOGRAPH-8D74 +U+8D77(2,3);U+8D77(2,3); # 21-15, CJK UNIFIED IDEOGRAPH-8D77 +U+8D81(2,3);U+8D81(2,3); # 76-67, CJK UNIFIED IDEOGRAPH-8D81 +U+8D85(2,3);U+8D85(2,3); # 36-22, CJK UNIFIED IDEOGRAPH-8D85 +U+8D8A(2,3);U+8D8A(2,3); # 17-59, CJK UNIFIED IDEOGRAPH-8D8A +U+8D99(2,3);U+8D99(2,3); # 76-68, CJK UNIFIED IDEOGRAPH-8D99 +U+8DA3(2,3);U+8DA3(2,3); # 28-81, CJK UNIFIED IDEOGRAPH-8DA3 +U+8DA8(2,3);U+8DA8(2,3); # 31-86, CJK UNIFIED IDEOGRAPH-8DA8 +U+8DB3(2,3);U+8DB3(2,3); # 34-13, CJK UNIFIED IDEOGRAPH-8DB3 +U+8DBA(2,3);U+8DBA(2,3); # 76-71, CJK UNIFIED IDEOGRAPH-8DBA +U+8DBE(2,3);U+8DBE(2,3); # 76-70, CJK UNIFIED IDEOGRAPH-8DBE +U+8DC2(2,3);U+8DC2(2,3); # 76-69, CJK UNIFIED IDEOGRAPH-8DC2 +U+8DCB(2,3);U+8DCB(2,3); # 76-77, CJK UNIFIED IDEOGRAPH-8DCB +U+8DCC(2,3);U+8DCC(2,3); # 76-75, CJK UNIFIED IDEOGRAPH-8DCC +U+8DCF(2,3);U+8DCF(2,3); # 76-72, CJK UNIFIED IDEOGRAPH-8DCF +U+8DD6(2,3);U+8DD6(2,3); # 76-74, CJK UNIFIED IDEOGRAPH-8DD6 +U+8DDA(2,3);U+8DDA(2,3); # 76-73, CJK UNIFIED IDEOGRAPH-8DDA +U+8DDB(2,3);U+8DDB(2,3); # 76-76, CJK UNIFIED IDEOGRAPH-8DDB +U+8DDD(2,3);U+8DDD(2,3); # 21-87, CJK UNIFIED IDEOGRAPH-8DDD +U+8DDF(2,3);U+8DDF(2,3); # 76-80, CJK UNIFIED IDEOGRAPH-8DDF +U+8DE1(2,3);U+8DE1(2,3); # 32-55, CJK UNIFIED IDEOGRAPH-8DE1 +U+8DE3(2,3);U+8DE3(2,3); # 76-81, CJK UNIFIED IDEOGRAPH-8DE3 +U+8DE8(2,3);U+8DE8(2,3); # 24-57, CJK UNIFIED IDEOGRAPH-8DE8 +U+8DEA(2,3);U+8DEA(2,3); # 76-78, CJK UNIFIED IDEOGRAPH-8DEA +U+8DEB(2,3);U+8DEB(2,3); # 76-79, CJK UNIFIED IDEOGRAPH-8DEB +U+8DEF(2,3);U+8DEF(2,3); # 47-09, CJK UNIFIED IDEOGRAPH-8DEF +U+8DF3(2,3);U+8DF3(2,3); # 36-23, CJK UNIFIED IDEOGRAPH-8DF3 +U+8DF5(2,3);U+8DF5(2,3); # 33-09, CJK UNIFIED IDEOGRAPH-8DF5 +U+8DFC(2,3);U+8DFC(2,3); # 76-82, CJK UNIFIED IDEOGRAPH-8DFC +U+8DFF(2,3);U+8DFF(2,3); # 76-85, CJK UNIFIED IDEOGRAPH-8DFF +U+8E08(2,3);U+8E08(2,3); # 76-83, CJK UNIFIED IDEOGRAPH-8E08 +U+8E09(2,3);U+8E09(2,3); # 76-84, CJK UNIFIED IDEOGRAPH-8E09 +U+8E0A(2,3);U+8E0A(2,3); # 45-57, CJK UNIFIED IDEOGRAPH-8E0A +U+8E0F(2,3);U+8E0F(2,3); # 38-07, CJK UNIFIED IDEOGRAPH-8E0F +U+8E10(2,3);U+8E10(2,3); # 76-88, CJK UNIFIED IDEOGRAPH-8E10 +U+8E1D(2,3);U+8E1D(2,3); # 76-86, CJK UNIFIED IDEOGRAPH-8E1D +U+8E1E(2,3);U+8E1E(2,3); # 76-87, CJK UNIFIED IDEOGRAPH-8E1E +U+8E1F(2,3);U+8E1F(2,3); # 76-89, CJK UNIFIED IDEOGRAPH-8E1F +U+8E2A(2,3);U+8E2A(2,3); # 77-09, CJK UNIFIED IDEOGRAPH-8E2A +U+8E30(2,3);U+8E30(2,3); # 76-92, CJK UNIFIED IDEOGRAPH-8E30 +U+8E34(2,3);U+8E34(2,3); # 76-93, CJK UNIFIED IDEOGRAPH-8E34 +U+8E35(2,3);U+8E35(2,3); # 76-91, CJK UNIFIED IDEOGRAPH-8E35 +U+8E42(2,3);U+8E42(2,3); # 76-90, CJK UNIFIED IDEOGRAPH-8E42 +U+8E44(2,3);U+8E44(2,3); # 36-93, CJK UNIFIED IDEOGRAPH-8E44 +U+8E47(2,3);U+8E47(2,3); # 77-01, CJK UNIFIED IDEOGRAPH-8E47 +U+8E48(2,3);U+8E48(2,3); # 77-05, CJK UNIFIED IDEOGRAPH-8E48 +U+8E49(2,3);U+8E49(2,3); # 77-02, CJK UNIFIED IDEOGRAPH-8E49 +U+8E4A(2,3);U+8E4A(2,3); # 76-94, CJK UNIFIED IDEOGRAPH-8E4A +U+8E4C(2,3);U+8E4C(2,3); # 77-03, CJK UNIFIED IDEOGRAPH-8E4C +U+8E50(2,3);U+8E50(2,3); # 77-04, CJK UNIFIED IDEOGRAPH-8E50 +U+8E55(2,3);U+8E55(2,3); # 77-11, CJK UNIFIED IDEOGRAPH-8E55 +U+8E59(2,3);U+8E59(2,3); # 77-06, CJK UNIFIED IDEOGRAPH-8E59 +U+8E5F(2,3);U+8E5F(2,3); # 32-56, CJK UNIFIED IDEOGRAPH-8E5F +U+8E60(2,3);U+8E60(2,3); # 77-08, CJK UNIFIED IDEOGRAPH-8E60 +U+8E63(2,3);U+8E63(2,3); # 77-10, CJK UNIFIED IDEOGRAPH-8E63 +U+8E64(2,3);U+8E64(2,3); # 77-07, CJK UNIFIED IDEOGRAPH-8E64 +U+8E72(2,3);U+8E72(2,3); # 77-13, CJK UNIFIED IDEOGRAPH-8E72 +U+8E74(2,3);U+8E74(2,3); # 29-19, CJK UNIFIED IDEOGRAPH-8E74 +U+8E76(2,3);U+8E76(2,3); # 77-12, CJK UNIFIED IDEOGRAPH-8E76 +U+8E7C(2,3);U+8E7C(2,3); # 77-14, CJK UNIFIED IDEOGRAPH-8E7C +U+8E81(2,3);U+8E81(2,3); # 77-15, CJK UNIFIED IDEOGRAPH-8E81 +U+8E84(2,3);U+8E84(2,3); # 77-18, CJK UNIFIED IDEOGRAPH-8E84 +U+8E85(2,3);U+8E85(2,3); # 77-17, CJK UNIFIED IDEOGRAPH-8E85 +U+8E87(2,3);U+8E87(2,3); # 77-16, CJK UNIFIED IDEOGRAPH-8E87 +U+8E8A(2,3);U+8E8A(2,3); # 77-20, CJK UNIFIED IDEOGRAPH-8E8A +U+8E8B(2,3);U+8E8B(2,3); # 77-19, CJK UNIFIED IDEOGRAPH-8E8B +U+8E8D(2,3);U+8E8D(2,3); # 44-86, CJK UNIFIED IDEOGRAPH-8E8D +U+8E91(2,3);U+8E91(2,3); # 77-22, CJK UNIFIED IDEOGRAPH-8E91 +U+8E93(2,3);U+8E93(2,3); # 77-21, CJK UNIFIED IDEOGRAPH-8E93 +U+8E94(2,3);U+8E94(2,3); # 77-23, CJK UNIFIED IDEOGRAPH-8E94 +U+8E99(2,3);U+8E99(2,3); # 77-24, CJK UNIFIED IDEOGRAPH-8E99 +U+8EA1(2,3);U+8EA1(2,3); # 77-26, CJK UNIFIED IDEOGRAPH-8EA1 +U+8EAA(2,3);U+8EAA(2,3); # 77-25, CJK UNIFIED IDEOGRAPH-8EAA +U+8EAB(2,3);U+8EAB(2,3); # 31-40, CJK UNIFIED IDEOGRAPH-8EAB +U+8EAC(2,3);U+8EAC(2,3); # 77-27, CJK UNIFIED IDEOGRAPH-8EAC +U+8EAF(2,3);U+8EAF(2,3); # 22-77, CJK UNIFIED IDEOGRAPH-8EAF +U+8EB0(2,3);U+8EB0(2,3); # 77-28, CJK UNIFIED IDEOGRAPH-8EB0 +U+8EB1(2,3);U+8EB1(2,3); # 77-30, CJK UNIFIED IDEOGRAPH-8EB1 +U+8EBE(2,3);U+8EBE(2,3); # 77-31, CJK UNIFIED IDEOGRAPH-8EBE +U+8EC5(2,3);U+8EC5(2,3); # 77-32, CJK UNIFIED IDEOGRAPH-8EC5 +U+8EC6(2,3);U+8EC6(2,3); # 77-29, CJK UNIFIED IDEOGRAPH-8EC6 +U+8EC8(2,3);U+8EC8(2,3); # 77-33, CJK UNIFIED IDEOGRAPH-8EC8 +U+8ECA(2,3);U+8ECA(2,3); # 28-54, CJK UNIFIED IDEOGRAPH-8ECA +U+8ECB(2,3);U+8ECB(2,3); # 77-34, CJK UNIFIED IDEOGRAPH-8ECB +U+8ECC(2,3);U+8ECC(2,3); # 21-16, CJK UNIFIED IDEOGRAPH-8ECC +U+8ECD(2,3);U+8ECD(2,3); # 23-19, CJK UNIFIED IDEOGRAPH-8ECD +U+8ED2(2,3);U+8ED2(2,3); # 24-14, CJK UNIFIED IDEOGRAPH-8ED2 +U+8EDB(2,3);U+8EDB(2,3); # 77-35, CJK UNIFIED IDEOGRAPH-8EDB +U+8EDF(2,3);U+8EDF(2,3); # 38-80, CJK UNIFIED IDEOGRAPH-8EDF +U+8EE2(2,3);U+8EE2(2,3); # 37-30, CJK UNIFIED IDEOGRAPH-8EE2 +U+8EE3(2,3);U+8EE3(2,3); # 77-36, CJK UNIFIED IDEOGRAPH-8EE3 +U+8EEB(2,3);U+8EEB(2,3); # 77-39, CJK UNIFIED IDEOGRAPH-8EEB +U+8EF8(2,3);U+8EF8(2,3); # 28-20, CJK UNIFIED IDEOGRAPH-8EF8 +U+8EFB(2,3);U+8EFB(2,3); # 77-38, CJK UNIFIED IDEOGRAPH-8EFB +U+8EFC(2,3);U+8EFC(2,3); # 77-37, CJK UNIFIED IDEOGRAPH-8EFC +U+8EFD(2,3);U+8EFD(2,3); # 23-58, CJK UNIFIED IDEOGRAPH-8EFD +U+8EFE(2,3);U+8EFE(2,3); # 77-40, CJK UNIFIED IDEOGRAPH-8EFE +U+8F03(2,3);U+8F03(2,3); # 19-51, CJK UNIFIED IDEOGRAPH-8F03 +U+8F05(2,3);U+8F05(2,3); # 77-42, CJK UNIFIED IDEOGRAPH-8F05 +U+8F09(2,3);U+8F09(2,3); # 26-60, CJK UNIFIED IDEOGRAPH-8F09 +U+8F0A(2,3);U+8F0A(2,3); # 77-41, CJK UNIFIED IDEOGRAPH-8F0A +U+8F0C(2,3);U+8F0C(2,3); # 77-50, CJK UNIFIED IDEOGRAPH-8F0C +U+8F12(2,3);U+8F12(2,3); # 77-44, CJK UNIFIED IDEOGRAPH-8F12 +U+8F13(2,3);U+8F13(2,3); # 77-46, CJK UNIFIED IDEOGRAPH-8F13 +U+8F14(2,3);U+8F14(2,3); # 42-69, CJK UNIFIED IDEOGRAPH-8F14 +U+8F15(2,3);U+8F15(2,3); # 77-43, CJK UNIFIED IDEOGRAPH-8F15 +U+8F19(2,3);U+8F19(2,3); # 77-45, CJK UNIFIED IDEOGRAPH-8F19 +U+8F1B(2,3);U+8F1B(2,3); # 77-49, CJK UNIFIED IDEOGRAPH-8F1B +U+8F1C(2,3);U+8F1C(2,3); # 77-47, CJK UNIFIED IDEOGRAPH-8F1C +U+8F1D(2,3);U+8F1D(2,3); # 21-17, CJK UNIFIED IDEOGRAPH-8F1D +U+8F1F(2,3);U+8F1F(2,3); # 77-48, CJK UNIFIED IDEOGRAPH-8F1F +U+8F26(2,3);U+8F26(2,3); # 77-51, CJK UNIFIED IDEOGRAPH-8F26 +U+8F29(2,3);U+8F29(2,3); # 39-58, CJK UNIFIED IDEOGRAPH-8F29 +U+8F2A(2,3);U+8F2A(2,3); # 46-56, CJK UNIFIED IDEOGRAPH-8F2A +U+8F2F(2,3);U+8F2F(2,3); # 29-20, CJK UNIFIED IDEOGRAPH-8F2F +U+8F33(2,3);U+8F33(2,3); # 77-52, CJK UNIFIED IDEOGRAPH-8F33 +U+8F38(2,3);U+8F38(2,3); # 45-02, CJK UNIFIED IDEOGRAPH-8F38 +U+8F39(2,3);U+8F39(2,3); # 77-54, CJK UNIFIED IDEOGRAPH-8F39 +U+8F3B(2,3);U+8F3B(2,3); # 77-53, CJK UNIFIED IDEOGRAPH-8F3B +U+8F3E(2,3);U+8F3E(2,3); # 77-57, CJK UNIFIED IDEOGRAPH-8F3E +U+8F3F(2,3);U+8F3F(2,3); # 45-33, CJK UNIFIED IDEOGRAPH-8F3F +U+8F42(2,3);U+8F42(2,3); # 77-56, CJK UNIFIED IDEOGRAPH-8F42 +U+8F44(2,3);U+8F44(2,3); # 19-77, CJK UNIFIED IDEOGRAPH-8F44 +U+8F45(2,3);U+8F45(2,3); # 77-55, CJK UNIFIED IDEOGRAPH-8F45 +U+8F46(2,3);U+8F46(2,3); # 77-60, CJK UNIFIED IDEOGRAPH-8F46 +U+8F49(2,3);U+8F49(2,3); # 77-59, CJK UNIFIED IDEOGRAPH-8F49 +U+8F4C(2,3);U+8F4C(2,3); # 77-58, CJK UNIFIED IDEOGRAPH-8F4C +U+8F4D(2,3);U+8F4D(2,3); # 37-18, CJK UNIFIED IDEOGRAPH-8F4D +U+8F4E(2,3);U+8F4E(2,3); # 77-61, CJK UNIFIED IDEOGRAPH-8F4E +U+8F57(2,3);U+8F57(2,3); # 77-62, CJK UNIFIED IDEOGRAPH-8F57 +U+8F5C(2,3);U+8F5C(2,3); # 77-63, CJK UNIFIED IDEOGRAPH-8F5C +U+8F5F(2,3);U+8F5F(2,3); # 25-76, CJK UNIFIED IDEOGRAPH-8F5F +U+8F61(2,3);U+8F61(2,3); # 23-05, CJK UNIFIED IDEOGRAPH-8F61 +U+8F62(2,3);U+8F62(2,3); # 77-64, CJK UNIFIED IDEOGRAPH-8F62 +U+8F63(2,3);U+8F63(2,3); # 77-65, CJK UNIFIED IDEOGRAPH-8F63 +U+8F64(2,3);U+8F64(2,3); # 77-66, CJK UNIFIED IDEOGRAPH-8F64 +U+8F9B(2,3);U+8F9B(2,3); # 31-41, CJK UNIFIED IDEOGRAPH-8F9B +U+8F9C(2,3);U+8F9C(2,3); # 77-67, CJK UNIFIED IDEOGRAPH-8F9C +U+8F9E(2,3);U+8F9E(2,3); # 28-13, CJK UNIFIED IDEOGRAPH-8F9E +U+8F9F(2,3);U+8F9F(2,3); # 77-68, CJK UNIFIED IDEOGRAPH-8F9F +U+8FA3(2,3);U+8FA3(2,3); # 77-69, CJK UNIFIED IDEOGRAPH-8FA3 +U+8FA7(2,3);U+8FA7(2,3); # 50-01, CJK UNIFIED IDEOGRAPH-8FA7 +U+8FA8(2,3);U+8FA8(2,3); # 49-94, CJK UNIFIED IDEOGRAPH-8FA8 +U+8FAD(2,3);U+8FAD(2,3); # 77-70, CJK UNIFIED IDEOGRAPH-8FAD +U+8FAE(2,3);U+8FAE(2,3); # 69-80, CJK UNIFIED IDEOGRAPH-8FAE +U+8FAF(2,3);U+8FAF(2,3); # 77-71, CJK UNIFIED IDEOGRAPH-8FAF +U+8FB0(2,3);U+8FB0(2,3); # 35-04, CJK UNIFIED IDEOGRAPH-8FB0 +U+8FB1(2,3);U+8FB1(2,3); # 31-11, CJK UNIFIED IDEOGRAPH-8FB1 +U+8FB2(2,3);U+8FB2(2,3); # 39-32, CJK UNIFIED IDEOGRAPH-8FB2 +U+8FB7(2,3);U+8FB7(2,3); # 77-72, CJK UNIFIED IDEOGRAPH-8FB7 +U+8FBA(2,3);U+8FBA(2,3); # 42-53, CJK UNIFIED IDEOGRAPH-8FBA +U+8FBB(2,3);U+8FBB(2,3); # 36-52, CJK UNIFIED IDEOGRAPH-8FBB +U+8FBC(2,3);U+8FBC(2,3); # 25-94, CJK UNIFIED IDEOGRAPH-8FBC +U+8FBF(2,3);U+8FBF(2,3); # 35-09, CJK UNIFIED IDEOGRAPH-8FBF +U+8FC2(2,3);U+8FC2(2,3); # 17-10, CJK UNIFIED IDEOGRAPH-8FC2 +U+8FC4(2,3);U+8FC4(2,3); # 43-88, CJK UNIFIED IDEOGRAPH-8FC4 +U+8FC5(2,3);U+8FC5(2,3); # 31-55, CJK UNIFIED IDEOGRAPH-8FC5 +U+8FCE(2,3);U+8FCE(2,3); # 23-62, CJK UNIFIED IDEOGRAPH-8FCE +U+8FD1(2,3);U+8FD1(2,3); # 22-65, CJK UNIFIED IDEOGRAPH-8FD1 +U+8FD4(2,3);U+8FD4(2,3); # 42-54, CJK UNIFIED IDEOGRAPH-8FD4 +U+8FDA(2,3);U+8FDA(2,3); # 77-73, CJK UNIFIED IDEOGRAPH-8FDA +U+8FE2(2,3);U+8FE2(2,3); # 77-75, CJK UNIFIED IDEOGRAPH-8FE2 +U+8FE5(2,3);U+8FE5(2,3); # 77-74, CJK UNIFIED IDEOGRAPH-8FE5 +U+8FE6(2,3);U+8FE6(2,3); # 18-64, CJK UNIFIED IDEOGRAPH-8FE6 +U+8FE9(2,3);U+8FE9(2,3); # 38-86, CJK UNIFIED IDEOGRAPH-8FE9 +U+8FEA(2,3);U+8FEA(2,3); # 77-76, CJK UNIFIED IDEOGRAPH-8FEA +U+8FEB(2,3);U+8FEB(2,3); # 39-87, CJK UNIFIED IDEOGRAPH-8FEB +U+8FED(2,3);U+8FED(2,3); # 37-19, CJK UNIFIED IDEOGRAPH-8FED +U+8FEF(2,3);U+8FEF(2,3); # 77-77, CJK UNIFIED IDEOGRAPH-8FEF +U+8FF0(2,3);U+8FF0(2,3); # 29-50, CJK UNIFIED IDEOGRAPH-8FF0 +U+8FF4(2,3);U+8FF4(2,3); # 77-79, CJK UNIFIED IDEOGRAPH-8FF4 +U+8FF7(2,3);U+8FF7(2,3); # 44-34, CJK UNIFIED IDEOGRAPH-8FF7 +U+8FF8(2,3);U+8FF8(2,3); # 77-94, CJK UNIFIED IDEOGRAPH-8FF8 +U+8FF9(2,3);U+8FF9(2,3); # 77-81, CJK UNIFIED IDEOGRAPH-8FF9 +U+8FFA(2,3);U+8FFA(2,3); # 77-82, CJK UNIFIED IDEOGRAPH-8FFA +U+8FFD(2,3);U+8FFD(2,3); # 36-41, CJK UNIFIED IDEOGRAPH-8FFD +U+9000(2,3);U+9000(2,3); # 34-64, CJK UNIFIED IDEOGRAPH-9000 +U+9001(2,3);U+9001(2,3); # 33-87, CJK UNIFIED IDEOGRAPH-9001 +U+9003(2,3);U+9003(2,3); # 38-08, CJK UNIFIED IDEOGRAPH-9003 +U+9005(2,3);U+9005(2,3); # 77-80, CJK UNIFIED IDEOGRAPH-9005 +U+9006(2,3);U+9006(2,3); # 21-53, CJK UNIFIED IDEOGRAPH-9006 +U+900B(2,3);U+900B(2,3); # 77-89, CJK UNIFIED IDEOGRAPH-900B +U+900D(2,3);U+900D(2,3); # 77-86, CJK UNIFIED IDEOGRAPH-900D +U+900E(2,3);U+900E(2,3); # 78-05, CJK UNIFIED IDEOGRAPH-900E +U+900F(2,3);U+900F(2,3); # 38-09, CJK UNIFIED IDEOGRAPH-900F +U+9010(2,3);U+9010(2,3); # 35-64, CJK UNIFIED IDEOGRAPH-9010 +U+9011(2,3);U+9011(2,3); # 77-83, CJK UNIFIED IDEOGRAPH-9011 +U+9013(2,3);U+9013(2,3); # 36-94, CJK UNIFIED IDEOGRAPH-9013 +U+9014(2,3);U+9014(2,3); # 37-51, CJK UNIFIED IDEOGRAPH-9014 +U+9015(2,3);U+9015(2,3); # 77-84, CJK UNIFIED IDEOGRAPH-9015 +U+9016(2,3);U+9016(2,3); # 77-88, CJK UNIFIED IDEOGRAPH-9016 +U+9017(2,3);U+9017(2,3); # 31-64, CJK UNIFIED IDEOGRAPH-9017 +U+9019(2,3);U+9019(2,3); # 39-71, CJK UNIFIED IDEOGRAPH-9019 +U+901A(2,3);U+901A(2,3); # 36-44, CJK UNIFIED IDEOGRAPH-901A +U+901D(2,3);U+901D(2,3); # 32-34, CJK UNIFIED IDEOGRAPH-901D +U+901E(2,3);U+901E(2,3); # 77-87, CJK UNIFIED IDEOGRAPH-901E +U+901F(2,3);U+901F(2,3); # 34-14, CJK UNIFIED IDEOGRAPH-901F +U+9020(2,3);U+9020(2,3); # 34-04, CJK UNIFIED IDEOGRAPH-9020 +U+9021(2,3);U+9021(2,3); # 77-85, CJK UNIFIED IDEOGRAPH-9021 +U+9022(2,3);U+9022(2,3); # 16-09, CJK UNIFIED IDEOGRAPH-9022 +U+9023(2,3);U+9023(2,3); # 47-02, CJK UNIFIED IDEOGRAPH-9023 +U+9027(2,3);U+9027(2,3); # 77-90, CJK UNIFIED IDEOGRAPH-9027 +U+902E(2,3);U+902E(2,3); # 34-65, CJK UNIFIED IDEOGRAPH-902E +U+9031(2,3);U+9031(2,3); # 29-21, CJK UNIFIED IDEOGRAPH-9031 +U+9032(2,3);U+9032(2,3); # 31-42, CJK UNIFIED IDEOGRAPH-9032 +U+9035(2,3);U+9035(2,3); # 77-92, CJK UNIFIED IDEOGRAPH-9035 +U+9036(2,3);U+9036(2,3); # 77-91, CJK UNIFIED IDEOGRAPH-9036 +U+9038(2,3);U+9038(2,3); # 16-79, CJK UNIFIED IDEOGRAPH-9038 +U+9039(2,3);U+9039(2,3); # 77-93, CJK UNIFIED IDEOGRAPH-9039 +U+903C(2,3);U+903C(2,3); # 41-15, CJK UNIFIED IDEOGRAPH-903C +U+903E(2,3);U+903E(2,3); # 78-07, CJK UNIFIED IDEOGRAPH-903E +U+9041(2,3);U+9041(2,3); # 38-59, CJK UNIFIED IDEOGRAPH-9041 +U+9042(2,3);U+9042(2,3); # 31-75, CJK UNIFIED IDEOGRAPH-9042 +U+9045(2,3);U+9045(2,3); # 35-57, CJK UNIFIED IDEOGRAPH-9045 +U+9047(2,3);U+9047(2,3); # 22-88, CJK UNIFIED IDEOGRAPH-9047 +U+9049(2,3);U+9049(2,3); # 78-06, CJK UNIFIED IDEOGRAPH-9049 +U+904A(2,3);U+904A(2,3); # 45-23, CJK UNIFIED IDEOGRAPH-904A +U+904B(2,3);U+904B(2,3); # 17-31, CJK UNIFIED IDEOGRAPH-904B +U+904D(2,3);U+904D(2,3); # 42-55, CJK UNIFIED IDEOGRAPH-904D +U+904E(2,3);U+904E(2,3); # 18-65, CJK UNIFIED IDEOGRAPH-904E +U+904F(2,3);U+904F(2,3); # 78-01, CJK UNIFIED IDEOGRAPH-904F +U+9050(2,3);U+9050(2,3); # 78-02, CJK UNIFIED IDEOGRAPH-9050 +U+9051(2,3);U+9051(2,3); # 78-03, CJK UNIFIED IDEOGRAPH-9051 +U+9052(2,3);U+9052(2,3); # 78-04, CJK UNIFIED IDEOGRAPH-9052 +U+9053(2,3);U+9053(2,3); # 38-27, CJK UNIFIED IDEOGRAPH-9053 +U+9054(2,3);U+9054(2,3); # 35-03, CJK UNIFIED IDEOGRAPH-9054 +U+9055(2,3);U+9055(2,3); # 16-67, CJK UNIFIED IDEOGRAPH-9055 +U+9056(2,3);U+9056(2,3); # 78-08, CJK UNIFIED IDEOGRAPH-9056 +U+9058(2,3);U+9058(2,3); # 78-09, CJK UNIFIED IDEOGRAPH-9058 +U+9059(2,3);U+9059(2,3); # 84-03, CJK UNIFIED IDEOGRAPH-9059 +U+905C(2,3);U+905C(2,3); # 34-29, CJK UNIFIED IDEOGRAPH-905C +U+905E(2,3);U+905E(2,3); # 78-10, CJK UNIFIED IDEOGRAPH-905E +U+9060(2,3);U+9060(2,3); # 17-83, CJK UNIFIED IDEOGRAPH-9060 +U+9061(2,3);U+9061(2,3); # 33-44, CJK UNIFIED IDEOGRAPH-9061 +U+9063(2,3);U+9063(2,3); # 24-15, CJK UNIFIED IDEOGRAPH-9063 +U+9065(2,3);U+9065(2,3); # 45-58, CJK UNIFIED IDEOGRAPH-9065 +U+9068(2,3);U+9068(2,3); # 78-11, CJK UNIFIED IDEOGRAPH-9068 +U+9069(2,3);U+9069(2,3); # 37-12, CJK UNIFIED IDEOGRAPH-9069 +U+906D(2,3);U+906D(2,3); # 33-88, CJK UNIFIED IDEOGRAPH-906D +U+906E(2,3);U+906E(2,3); # 28-55, CJK UNIFIED IDEOGRAPH-906E +U+906F(2,3);U+906F(2,3); # 78-12, CJK UNIFIED IDEOGRAPH-906F +U+9072(2,3);U+9072(2,3); # 78-15, CJK UNIFIED IDEOGRAPH-9072 +U+9075(2,3);U+9075(2,3); # 29-69, CJK UNIFIED IDEOGRAPH-9075 +U+9076(2,3);U+9076(2,3); # 78-13, CJK UNIFIED IDEOGRAPH-9076 +U+9077(2,3);U+9077(2,3); # 33-11, CJK UNIFIED IDEOGRAPH-9077 +U+9078(2,3);U+9078(2,3); # 33-10, CJK UNIFIED IDEOGRAPH-9078 +U+907A(2,3);U+907A(2,3); # 16-68, CJK UNIFIED IDEOGRAPH-907A +U+907C(2,3);U+907C(2,3); # 46-43, CJK UNIFIED IDEOGRAPH-907C +U+907D(2,3);U+907D(2,3); # 78-17, CJK UNIFIED IDEOGRAPH-907D +U+907F(2,3);U+907F(2,3); # 40-82, CJK UNIFIED IDEOGRAPH-907F +U+9080(2,3);U+9080(2,3); # 78-19, CJK UNIFIED IDEOGRAPH-9080 +U+9081(2,3);U+9081(2,3); # 78-18, CJK UNIFIED IDEOGRAPH-9081 +U+9082(2,3);U+9082(2,3); # 78-16, CJK UNIFIED IDEOGRAPH-9082 +U+9083(2,3);U+9083(2,3); # 67-68, CJK UNIFIED IDEOGRAPH-9083 +U+9084(2,3);U+9084(2,3); # 20-52, CJK UNIFIED IDEOGRAPH-9084 +U+9087(2,3);U+9087(2,3); # 77-78, CJK UNIFIED IDEOGRAPH-9087 +U+9089(2,3);U+9089(2,3); # 78-21, CJK UNIFIED IDEOGRAPH-9089 +U+908A(2,3);U+908A(2,3); # 78-20, CJK UNIFIED IDEOGRAPH-908A +U+908F(2,3);U+908F(2,3); # 78-22, CJK UNIFIED IDEOGRAPH-908F +U+9091(2,3);U+9091(2,3); # 45-24, CJK UNIFIED IDEOGRAPH-9091 +U+90A3(2,3);U+90A3(2,3); # 38-65, CJK UNIFIED IDEOGRAPH-90A3 +U+90A6(2,3);U+90A6(2,3); # 43-14, CJK UNIFIED IDEOGRAPH-90A6 +U+90A8(2,3);U+90A8(2,3); # 78-23, CJK UNIFIED IDEOGRAPH-90A8 +U+90AA(2,3);U+90AA(2,3); # 28-57, CJK UNIFIED IDEOGRAPH-90AA +U+90AF(2,3);U+90AF(2,3); # 78-24, CJK UNIFIED IDEOGRAPH-90AF +U+90B1(2,3);U+90B1(2,3); # 78-25, CJK UNIFIED IDEOGRAPH-90B1 +U+90B5(2,3);U+90B5(2,3); # 78-26, CJK UNIFIED IDEOGRAPH-90B5 +U+90B8(2,3);U+90B8(2,3); # 37-01, CJK UNIFIED IDEOGRAPH-90B8 +U+90C1(2,3);U+90C1(2,3); # 16-74, CJK UNIFIED IDEOGRAPH-90C1 +U+90CA(2,3);U+90CA(2,3); # 25-57, CJK UNIFIED IDEOGRAPH-90CA +U+90CE(2,3);U+90CE(2,3); # 47-26, CJK UNIFIED IDEOGRAPH-90CE +U+90DB(2,3);U+90DB(2,3); # 78-30, CJK UNIFIED IDEOGRAPH-90DB +U+90E1(2,3);U+90E1(2,3); # 23-20, CJK UNIFIED IDEOGRAPH-90E1 +U+90E2(2,3);U+90E2(2,3); # 78-27, CJK UNIFIED IDEOGRAPH-90E2 +U+90E4(2,3);U+90E4(2,3); # 78-28, CJK UNIFIED IDEOGRAPH-90E4 +U+90E8(2,3);U+90E8(2,3); # 41-84, CJK UNIFIED IDEOGRAPH-90E8 +U+90ED(2,3);U+90ED(2,3); # 19-52, CJK UNIFIED IDEOGRAPH-90ED +U+90F5(2,3);U+90F5(2,3); # 45-25, CJK UNIFIED IDEOGRAPH-90F5 +U+90F7(2,3);U+90F7(2,3); # 22-31, CJK UNIFIED IDEOGRAPH-90F7 +U+90FD(2,3);U+90FD(2,3); # 37-52, CJK UNIFIED IDEOGRAPH-90FD +U+9102(2,3);U+9102(2,3); # 78-31, CJK UNIFIED IDEOGRAPH-9102 +U+9112(2,3);U+9112(2,3); # 78-32, CJK UNIFIED IDEOGRAPH-9112 +U+9119(2,3);U+9119(2,3); # 78-33, CJK UNIFIED IDEOGRAPH-9119 +U+912D(2,3);U+912D(2,3); # 37-02, CJK UNIFIED IDEOGRAPH-912D +U+9130(2,3);U+9130(2,3); # 78-35, CJK UNIFIED IDEOGRAPH-9130 +U+9132(2,3);U+9132(2,3); # 78-34, CJK UNIFIED IDEOGRAPH-9132 +U+9149(2,3);U+9149(2,3); # 38-51, CJK UNIFIED IDEOGRAPH-9149 +U+914A(2,3);U+914A(2,3); # 78-36, CJK UNIFIED IDEOGRAPH-914A +U+914B(2,3);U+914B(2,3); # 29-22, CJK UNIFIED IDEOGRAPH-914B +U+914C(2,3);U+914C(2,3); # 28-64, CJK UNIFIED IDEOGRAPH-914C +U+914D(2,3);U+914D(2,3); # 39-59, CJK UNIFIED IDEOGRAPH-914D +U+914E(2,3);U+914E(2,3); # 35-81, CJK UNIFIED IDEOGRAPH-914E +U+9152(2,3);U+9152(2,3); # 28-82, CJK UNIFIED IDEOGRAPH-9152 +U+9154(2,3);U+9154(2,3); # 31-76, CJK UNIFIED IDEOGRAPH-9154 +U+9156(2,3);U+9156(2,3); # 78-37, CJK UNIFIED IDEOGRAPH-9156 +U+9158(2,3);U+9158(2,3); # 78-38, CJK UNIFIED IDEOGRAPH-9158 +U+9162(2,3);U+9162(2,3); # 31-61, CJK UNIFIED IDEOGRAPH-9162 +U+9163(2,3);U+9163(2,3); # 78-39, CJK UNIFIED IDEOGRAPH-9163 +U+9165(2,3);U+9165(2,3); # 78-40, CJK UNIFIED IDEOGRAPH-9165 +U+9169(2,3);U+9169(2,3); # 78-41, CJK UNIFIED IDEOGRAPH-9169 +U+916A(2,3);U+916A(2,3); # 45-79, CJK UNIFIED IDEOGRAPH-916A +U+916C(2,3);U+916C(2,3); # 29-23, CJK UNIFIED IDEOGRAPH-916C +U+9172(2,3);U+9172(2,3); # 78-43, CJK UNIFIED IDEOGRAPH-9172 +U+9173(2,3);U+9173(2,3); # 78-42, CJK UNIFIED IDEOGRAPH-9173 +U+9175(2,3);U+9175(2,3); # 25-58, CJK UNIFIED IDEOGRAPH-9175 +U+9177(2,3);U+9177(2,3); # 25-83, CJK UNIFIED IDEOGRAPH-9177 +U+9178(2,3);U+9178(2,3); # 27-32, CJK UNIFIED IDEOGRAPH-9178 +U+9182(2,3);U+9182(2,3); # 78-46, CJK UNIFIED IDEOGRAPH-9182 +U+9187(2,3);U+9187(2,3); # 29-70, CJK UNIFIED IDEOGRAPH-9187 +U+9189(2,3);U+9189(2,3); # 78-45, CJK UNIFIED IDEOGRAPH-9189 +U+918B(2,3);U+918B(2,3); # 78-44, CJK UNIFIED IDEOGRAPH-918B +U+918D(2,3);U+918D(2,3); # 34-73, CJK UNIFIED IDEOGRAPH-918D +U+9190(2,3);U+9190(2,3); # 24-79, CJK UNIFIED IDEOGRAPH-9190 +U+9192(2,3);U+9192(2,3); # 32-35, CJK UNIFIED IDEOGRAPH-9192 +U+9197(2,3);U+9197(2,3); # 40-16, CJK UNIFIED IDEOGRAPH-9197 +U+919C(2,3);U+919C(2,3); # 29-25, CJK UNIFIED IDEOGRAPH-919C +U+91A2(2,3);U+91A2(2,3); # 78-47, CJK UNIFIED IDEOGRAPH-91A2 +U+91A4(2,3);U+91A4(2,3); # 30-63, CJK UNIFIED IDEOGRAPH-91A4 +U+91AA(2,3);U+91AA(2,3); # 78-50, CJK UNIFIED IDEOGRAPH-91AA +U+91AB(2,3);U+91AB(2,3); # 78-48, CJK UNIFIED IDEOGRAPH-91AB +U+91AF(2,3);U+91AF(2,3); # 78-49, CJK UNIFIED IDEOGRAPH-91AF +U+91B4(2,3);U+91B4(2,3); # 78-52, CJK UNIFIED IDEOGRAPH-91B4 +U+91B5(2,3);U+91B5(2,3); # 78-51, CJK UNIFIED IDEOGRAPH-91B5 +U+91B8(2,3);U+91B8(2,3); # 30-90, CJK UNIFIED IDEOGRAPH-91B8 +U+91BA(2,3);U+91BA(2,3); # 78-53, CJK UNIFIED IDEOGRAPH-91BA +U+91C0(2,3);U+91C0(2,3); # 78-54, CJK UNIFIED IDEOGRAPH-91C0 +U+91C1(2,3);U+91C1(2,3); # 78-55, CJK UNIFIED IDEOGRAPH-91C1 +U+91C6(2,3);U+91C6(2,3); # 40-48, CJK UNIFIED IDEOGRAPH-91C6 +U+91C7(2,3);U+91C7(2,3); # 26-51, CJK UNIFIED IDEOGRAPH-91C7 +U+91C8(2,3);U+91C8(2,3); # 28-65, CJK UNIFIED IDEOGRAPH-91C8 +U+91C9(2,3);U+91C9(2,3); # 78-56, CJK UNIFIED IDEOGRAPH-91C9 +U+91CB(2,3);U+91CB(2,3); # 78-57, CJK UNIFIED IDEOGRAPH-91CB +U+91CC(2,3);U+91CC(2,3); # 46-04, CJK UNIFIED IDEOGRAPH-91CC +U+91CD(2,3);U+91CD(2,3); # 29-37, CJK UNIFIED IDEOGRAPH-91CD +U+91CE(2,3);U+91CE(2,3); # 44-78, CJK UNIFIED IDEOGRAPH-91CE +U+91CF(2,3);U+91CF(2,3); # 46-44, CJK UNIFIED IDEOGRAPH-91CF +U+91D0(2,3);U+91D0(2,3); # 78-58, CJK UNIFIED IDEOGRAPH-91D0 +U+91D1(2,3);U+91D1(2,3); # 22-66, CJK UNIFIED IDEOGRAPH-91D1 +U+91D6(2,3);U+91D6(2,3); # 78-59, CJK UNIFIED IDEOGRAPH-91D6 +U+91D8(2,3);U+91D8(2,3); # 37-03, CJK UNIFIED IDEOGRAPH-91D8 +U+91DB(2,3);U+91DB(2,3); # 78-62, CJK UNIFIED IDEOGRAPH-91DB +U+91DC(2,3);U+91DC(2,3); # 19-88, CJK UNIFIED IDEOGRAPH-91DC +U+91DD(2,3);U+91DD(2,3); # 31-43, CJK UNIFIED IDEOGRAPH-91DD +U+91DF(2,3);U+91DF(2,3); # 78-60, CJK UNIFIED IDEOGRAPH-91DF +U+91E1(2,3);U+91E1(2,3); # 78-61, CJK UNIFIED IDEOGRAPH-91E1 +U+91E3(2,3);U+91E3(2,3); # 36-64, CJK UNIFIED IDEOGRAPH-91E3 +U+91E6(2,3);U+91E6(2,3); # 43-53, CJK UNIFIED IDEOGRAPH-91E6 +U+91E7(2,3);U+91E7(2,3); # 22-92, CJK UNIFIED IDEOGRAPH-91E7 +U+91F5(2,3);U+91F5(2,3); # 78-64, CJK UNIFIED IDEOGRAPH-91F5 +U+91F6(2,3);U+91F6(2,3); # 78-65, CJK UNIFIED IDEOGRAPH-91F6 +U+91FC(2,3);U+91FC(2,3); # 78-63, CJK UNIFIED IDEOGRAPH-91FC +U+91FF(2,3);U+91FF(2,3); # 78-67, CJK UNIFIED IDEOGRAPH-91FF +U+920D(2,3);U+920D(2,3); # 38-63, CJK UNIFIED IDEOGRAPH-920D +U+920E(2,3);U+920E(2,3); # 19-35, CJK UNIFIED IDEOGRAPH-920E +U+9211(2,3);U+9211(2,3); # 78-71, CJK UNIFIED IDEOGRAPH-9211 +U+9214(2,3);U+9214(2,3); # 78-68, CJK UNIFIED IDEOGRAPH-9214 +U+9215(2,3);U+9215(2,3); # 78-70, CJK UNIFIED IDEOGRAPH-9215 +U+921E(2,3);U+921E(2,3); # 78-66, CJK UNIFIED IDEOGRAPH-921E +U+9229(2,3);U+9229(2,3); # 79-47, CJK UNIFIED IDEOGRAPH-9229 +U+922C(2,3);U+922C(2,3); # 78-69, CJK UNIFIED IDEOGRAPH-922C +U+9234(2,3);U+9234(2,3); # 46-75, CJK UNIFIED IDEOGRAPH-9234 +U+9237(2,3);U+9237(2,3); # 24-58, CJK UNIFIED IDEOGRAPH-9237 +U+923F(2,3);U+923F(2,3); # 78-79, CJK UNIFIED IDEOGRAPH-923F +U+9244(2,3);U+9244(2,3); # 37-20, CJK UNIFIED IDEOGRAPH-9244 +U+9245(2,3);U+9245(2,3); # 78-74, CJK UNIFIED IDEOGRAPH-9245 +U+9248(2,3);U+9248(2,3); # 78-77, CJK UNIFIED IDEOGRAPH-9248 +U+9249(2,3);U+9249(2,3); # 78-75, CJK UNIFIED IDEOGRAPH-9249 +U+924B(2,3);U+924B(2,3); # 78-80, CJK UNIFIED IDEOGRAPH-924B +U+9250(2,3);U+9250(2,3); # 78-81, CJK UNIFIED IDEOGRAPH-9250 +U+9257(2,3);U+9257(2,3); # 78-73, CJK UNIFIED IDEOGRAPH-9257 +U+925A(2,3);U+925A(2,3); # 78-86, CJK UNIFIED IDEOGRAPH-925A +U+925B(2,3);U+925B(2,3); # 17-84, CJK UNIFIED IDEOGRAPH-925B +U+925E(2,3);U+925E(2,3); # 78-72, CJK UNIFIED IDEOGRAPH-925E +U+9262(2,3);U+9262(2,3); # 40-13, CJK UNIFIED IDEOGRAPH-9262 +U+9264(2,3);U+9264(2,3); # 78-76, CJK UNIFIED IDEOGRAPH-9264 +U+9266(2,3);U+9266(2,3); # 30-64, CJK UNIFIED IDEOGRAPH-9266 +U+9271(2,3);U+9271(2,3); # 25-59, CJK UNIFIED IDEOGRAPH-9271 +U+927E(2,3);U+927E(2,3); # 43-40, CJK UNIFIED IDEOGRAPH-927E +U+9280(2,3);U+9280(2,3); # 22-68, CJK UNIFIED IDEOGRAPH-9280 +U+9283(2,3);U+9283(2,3); # 29-38, CJK UNIFIED IDEOGRAPH-9283 +U+9285(2,3);U+9285(2,3); # 38-28, CJK UNIFIED IDEOGRAPH-9285 +U+9291(2,3);U+9291(2,3); # 33-13, CJK UNIFIED IDEOGRAPH-9291 +U+9293(2,3);U+9293(2,3); # 78-84, CJK UNIFIED IDEOGRAPH-9293 +U+9295(2,3);U+9295(2,3); # 78-78, CJK UNIFIED IDEOGRAPH-9295 +U+9296(2,3);U+9296(2,3); # 78-83, CJK UNIFIED IDEOGRAPH-9296 +U+9298(2,3);U+9298(2,3); # 44-35, CJK UNIFIED IDEOGRAPH-9298 +U+929A(2,3);U+929A(2,3); # 36-24, CJK UNIFIED IDEOGRAPH-929A +U+929B(2,3);U+929B(2,3); # 78-85, CJK UNIFIED IDEOGRAPH-929B +U+929C(2,3);U+929C(2,3); # 78-82, CJK UNIFIED IDEOGRAPH-929C +U+92AD(2,3);U+92AD(2,3); # 33-12, CJK UNIFIED IDEOGRAPH-92AD +U+92B7(2,3);U+92B7(2,3); # 78-89, CJK UNIFIED IDEOGRAPH-92B7 +U+92B9(2,3);U+92B9(2,3); # 78-88, CJK UNIFIED IDEOGRAPH-92B9 +U+92CF(2,3);U+92CF(2,3); # 78-87, CJK UNIFIED IDEOGRAPH-92CF +U+92D2(2,3);U+92D2(2,3); # 43-15, CJK UNIFIED IDEOGRAPH-92D2 +U+92E4(2,3);U+92E4(2,3); # 29-91, CJK UNIFIED IDEOGRAPH-92E4 +U+92E9(2,3);U+92E9(2,3); # 78-90, CJK UNIFIED IDEOGRAPH-92E9 +U+92EA(2,3);U+92EA(2,3); # 42-63, CJK UNIFIED IDEOGRAPH-92EA +U+92ED(2,3);U+92ED(2,3); # 17-52, CJK UNIFIED IDEOGRAPH-92ED +U+92F2(2,3);U+92F2(2,3); # 41-38, CJK UNIFIED IDEOGRAPH-92F2 +U+92F3(2,3);U+92F3(2,3); # 35-82, CJK UNIFIED IDEOGRAPH-92F3 +U+92F8(2,3);U+92F8(2,3); # 21-88, CJK UNIFIED IDEOGRAPH-92F8 +U+92FA(2,3);U+92FA(2,3); # 78-92, CJK UNIFIED IDEOGRAPH-92FA +U+92FC(2,3);U+92FC(2,3); # 25-61, CJK UNIFIED IDEOGRAPH-92FC +U+9306(2,3);U+9306(2,3); # 27-12, CJK UNIFIED IDEOGRAPH-9306 +U+930F(2,3);U+930F(2,3); # 78-91, CJK UNIFIED IDEOGRAPH-930F +U+9310(2,3);U+9310(2,3); # 31-77, CJK UNIFIED IDEOGRAPH-9310 +U+9318(2,3);U+9318(2,3); # 31-78, CJK UNIFIED IDEOGRAPH-9318 +U+9319(2,3);U+9319(2,3); # 79-01, CJK UNIFIED IDEOGRAPH-9319 +U+931A(2,3);U+931A(2,3); # 79-03, CJK UNIFIED IDEOGRAPH-931A +U+9320(2,3);U+9320(2,3); # 30-91, CJK UNIFIED IDEOGRAPH-9320 +U+9322(2,3);U+9322(2,3); # 79-02, CJK UNIFIED IDEOGRAPH-9322 +U+9323(2,3);U+9323(2,3); # 79-04, CJK UNIFIED IDEOGRAPH-9323 +U+9326(2,3);U+9326(2,3); # 22-51, CJK UNIFIED IDEOGRAPH-9326 +U+9328(2,3);U+9328(2,3); # 41-37, CJK UNIFIED IDEOGRAPH-9328 +U+932B(2,3);U+932B(2,3); # 28-66, CJK UNIFIED IDEOGRAPH-932B +U+932C(2,3);U+932C(2,3); # 47-03, CJK UNIFIED IDEOGRAPH-932C +U+932E(2,3);U+932E(2,3); # 78-94, CJK UNIFIED IDEOGRAPH-932E +U+932F(2,3);U+932F(2,3); # 26-88, CJK UNIFIED IDEOGRAPH-932F +U+9332(2,3);U+9332(2,3); # 47-31, CJK UNIFIED IDEOGRAPH-9332 +U+9335(2,3);U+9335(2,3); # 79-06, CJK UNIFIED IDEOGRAPH-9335 +U+933A(2,3);U+933A(2,3); # 79-05, CJK UNIFIED IDEOGRAPH-933A +U+933B(2,3);U+933B(2,3); # 79-07, CJK UNIFIED IDEOGRAPH-933B +U+9344(2,3);U+9344(2,3); # 78-93, CJK UNIFIED IDEOGRAPH-9344 +U+934B(2,3);U+934B(2,3); # 38-73, CJK UNIFIED IDEOGRAPH-934B +U+934D(2,3);U+934D(2,3); # 37-53, CJK UNIFIED IDEOGRAPH-934D +U+9354(2,3);U+9354(2,3); # 36-55, CJK UNIFIED IDEOGRAPH-9354 +U+9356(2,3);U+9356(2,3); # 79-12, CJK UNIFIED IDEOGRAPH-9356 +U+935B(2,3);U+935B(2,3); # 35-35, CJK UNIFIED IDEOGRAPH-935B +U+935C(2,3);U+935C(2,3); # 79-08, CJK UNIFIED IDEOGRAPH-935C +U+9360(2,3);U+9360(2,3); # 79-09, CJK UNIFIED IDEOGRAPH-9360 +U+936C(2,3);U+936C(2,3); # 23-13, CJK UNIFIED IDEOGRAPH-936C +U+936E(2,3);U+936E(2,3); # 79-11, CJK UNIFIED IDEOGRAPH-936E +U+9375(2,3);U+9375(2,3); # 24-16, CJK UNIFIED IDEOGRAPH-9375 +U+937C(2,3);U+937C(2,3); # 79-10, CJK UNIFIED IDEOGRAPH-937C +U+937E(2,3);U+937E(2,3); # 30-65, CJK UNIFIED IDEOGRAPH-937E +U+938C(2,3);U+938C(2,3); # 19-89, CJK UNIFIED IDEOGRAPH-938C +U+9394(2,3);U+9394(2,3); # 79-16, CJK UNIFIED IDEOGRAPH-9394 +U+9396(2,3);U+9396(2,3); # 26-31, CJK UNIFIED IDEOGRAPH-9396 +U+9397(2,3);U+9397(2,3); # 33-89, CJK UNIFIED IDEOGRAPH-9397 +U+939A(2,3);U+939A(2,3); # 36-42, CJK UNIFIED IDEOGRAPH-939A +U+93A7(2,3);U+93A7(2,3); # 19-27, CJK UNIFIED IDEOGRAPH-93A7 +U+93AC(2,3);U+93AC(2,3); # 79-14, CJK UNIFIED IDEOGRAPH-93AC +U+93AD(2,3);U+93AD(2,3); # 79-15, CJK UNIFIED IDEOGRAPH-93AD +U+93AE(2,3);U+93AE(2,3); # 36-35, CJK UNIFIED IDEOGRAPH-93AE +U+93B0(2,3);U+93B0(2,3); # 79-13, CJK UNIFIED IDEOGRAPH-93B0 +U+93B9(2,3);U+93B9(2,3); # 79-17, CJK UNIFIED IDEOGRAPH-93B9 +U+93C3(2,3);U+93C3(2,3); # 79-23, CJK UNIFIED IDEOGRAPH-93C3 +U+93C8(2,3);U+93C8(2,3); # 79-26, CJK UNIFIED IDEOGRAPH-93C8 +U+93D0(2,3);U+93D0(2,3); # 79-25, CJK UNIFIED IDEOGRAPH-93D0 +U+93D1(2,3);U+93D1(2,3); # 37-13, CJK UNIFIED IDEOGRAPH-93D1 +U+93D6(2,3);U+93D6(2,3); # 79-18, CJK UNIFIED IDEOGRAPH-93D6 +U+93D7(2,3);U+93D7(2,3); # 79-19, CJK UNIFIED IDEOGRAPH-93D7 +U+93D8(2,3);U+93D8(2,3); # 79-22, CJK UNIFIED IDEOGRAPH-93D8 +U+93DD(2,3);U+93DD(2,3); # 79-24, CJK UNIFIED IDEOGRAPH-93DD +U+93E1(2,3);U+93E1(2,3); # 22-32, CJK UNIFIED IDEOGRAPH-93E1 +U+93E4(2,3);U+93E4(2,3); # 79-27, CJK UNIFIED IDEOGRAPH-93E4 +U+93E5(2,3);U+93E5(2,3); # 79-21, CJK UNIFIED IDEOGRAPH-93E5 +U+93E8(2,3);U+93E8(2,3); # 79-20, CJK UNIFIED IDEOGRAPH-93E8 +U+9403(2,3);U+9403(2,3); # 79-31, CJK UNIFIED IDEOGRAPH-9403 +U+9407(2,3);U+9407(2,3); # 79-32, CJK UNIFIED IDEOGRAPH-9407 +U+9410(2,3);U+9410(2,3); # 79-33, CJK UNIFIED IDEOGRAPH-9410 +U+9413(2,3);U+9413(2,3); # 79-30, CJK UNIFIED IDEOGRAPH-9413 +U+9414(2,3);U+9414(2,3); # 79-29, CJK UNIFIED IDEOGRAPH-9414 +U+9418(2,3);U+9418(2,3); # 30-66, CJK UNIFIED IDEOGRAPH-9418 +U+9419(2,3);U+9419(2,3); # 38-10, CJK UNIFIED IDEOGRAPH-9419 +U+941A(2,3);U+941A(2,3); # 79-28, CJK UNIFIED IDEOGRAPH-941A +U+9421(2,3);U+9421(2,3); # 79-37, CJK UNIFIED IDEOGRAPH-9421 +U+942B(2,3);U+942B(2,3); # 79-35, CJK UNIFIED IDEOGRAPH-942B +U+9435(2,3);U+9435(2,3); # 79-36, CJK UNIFIED IDEOGRAPH-9435 +U+9436(2,3);U+9436(2,3); # 79-34, CJK UNIFIED IDEOGRAPH-9436 +U+9438(2,3);U+9438(2,3); # 34-88, CJK UNIFIED IDEOGRAPH-9438 +U+943A(2,3);U+943A(2,3); # 79-38, CJK UNIFIED IDEOGRAPH-943A +U+9441(2,3);U+9441(2,3); # 79-39, CJK UNIFIED IDEOGRAPH-9441 +U+9444(2,3);U+9444(2,3); # 79-41, CJK UNIFIED IDEOGRAPH-9444 +U+9451(2,3);U+9451(2,3); # 20-53, CJK UNIFIED IDEOGRAPH-9451 +U+9452(2,3);U+9452(2,3); # 79-40, CJK UNIFIED IDEOGRAPH-9452 +U+9453(2,3);U+9453(2,3); # 44-90, CJK UNIFIED IDEOGRAPH-9453 +U+945A(2,3);U+945A(2,3); # 79-52, CJK UNIFIED IDEOGRAPH-945A +U+945B(2,3);U+945B(2,3); # 79-42, CJK UNIFIED IDEOGRAPH-945B +U+945E(2,3);U+945E(2,3); # 79-45, CJK UNIFIED IDEOGRAPH-945E +U+9460(2,3);U+9460(2,3); # 79-43, CJK UNIFIED IDEOGRAPH-9460 +U+9462(2,3);U+9462(2,3); # 79-44, CJK UNIFIED IDEOGRAPH-9462 +U+946A(2,3);U+946A(2,3); # 79-46, CJK UNIFIED IDEOGRAPH-946A +U+9470(2,3);U+9470(2,3); # 79-48, CJK UNIFIED IDEOGRAPH-9470 +U+9475(2,3);U+9475(2,3); # 79-49, CJK UNIFIED IDEOGRAPH-9475 +U+9477(2,3);U+9477(2,3); # 79-50, CJK UNIFIED IDEOGRAPH-9477 +U+947C(2,3);U+947C(2,3); # 79-53, CJK UNIFIED IDEOGRAPH-947C +U+947D(2,3);U+947D(2,3); # 79-51, CJK UNIFIED IDEOGRAPH-947D +U+947E(2,3);U+947E(2,3); # 79-54, CJK UNIFIED IDEOGRAPH-947E +U+947F(2,3);U+947F(2,3); # 79-56, CJK UNIFIED IDEOGRAPH-947F +U+9481(2,3);U+9481(2,3); # 79-55, CJK UNIFIED IDEOGRAPH-9481 +U+9577(2,3);U+9577(2,3); # 36-25, CJK UNIFIED IDEOGRAPH-9577 +U+9580(2,3);U+9580(2,3); # 44-71, CJK UNIFIED IDEOGRAPH-9580 +U+9582(2,3);U+9582(2,3); # 79-57, CJK UNIFIED IDEOGRAPH-9582 +U+9583(2,3);U+9583(2,3); # 33-14, CJK UNIFIED IDEOGRAPH-9583 +U+9587(2,3);U+9587(2,3); # 79-58, CJK UNIFIED IDEOGRAPH-9587 +U+9589(2,3);U+9589(2,3); # 42-36, CJK UNIFIED IDEOGRAPH-9589 +U+958A(2,3);U+958A(2,3); # 79-59, CJK UNIFIED IDEOGRAPH-958A +U+958B(2,3);U+958B(2,3); # 19-11, CJK UNIFIED IDEOGRAPH-958B +U+958F(2,3);U+958F(2,3); # 17-28, CJK UNIFIED IDEOGRAPH-958F +U+9591(2,3);U+9591(2,3); # 20-55, CJK UNIFIED IDEOGRAPH-9591 +U+9593(2,3);U+9593(2,3); # 20-54, CJK UNIFIED IDEOGRAPH-9593 +U+9594(2,3);U+9594(2,3); # 79-60, CJK UNIFIED IDEOGRAPH-9594 +U+9596(2,3);U+9596(2,3); # 79-61, CJK UNIFIED IDEOGRAPH-9596 +U+9598(2,3);U+9598(2,3); # 79-62, CJK UNIFIED IDEOGRAPH-9598 +U+9599(2,3);U+9599(2,3); # 79-63, CJK UNIFIED IDEOGRAPH-9599 +U+95A0(2,3);U+95A0(2,3); # 79-64, CJK UNIFIED IDEOGRAPH-95A0 +U+95A2(2,3);U+95A2(2,3); # 20-56, CJK UNIFIED IDEOGRAPH-95A2 +U+95A3(2,3);U+95A3(2,3); # 19-53, CJK UNIFIED IDEOGRAPH-95A3 +U+95A4(2,3);U+95A4(2,3); # 25-62, CJK UNIFIED IDEOGRAPH-95A4 +U+95A5(2,3);U+95A5(2,3); # 40-22, CJK UNIFIED IDEOGRAPH-95A5 +U+95A7(2,3);U+95A7(2,3); # 79-66, CJK UNIFIED IDEOGRAPH-95A7 +U+95A8(2,3);U+95A8(2,3); # 79-65, CJK UNIFIED IDEOGRAPH-95A8 +U+95AD(2,3);U+95AD(2,3); # 79-67, CJK UNIFIED IDEOGRAPH-95AD +U+95B2(2,3);U+95B2(2,3); # 17-60, CJK UNIFIED IDEOGRAPH-95B2 +U+95B9(2,3);U+95B9(2,3); # 79-70, CJK UNIFIED IDEOGRAPH-95B9 +U+95BB(2,3);U+95BB(2,3); # 79-69, CJK UNIFIED IDEOGRAPH-95BB +U+95BC(2,3);U+95BC(2,3); # 79-68, CJK UNIFIED IDEOGRAPH-95BC +U+95BE(2,3);U+95BE(2,3); # 79-71, CJK UNIFIED IDEOGRAPH-95BE +U+95C3(2,3);U+95C3(2,3); # 79-74, CJK UNIFIED IDEOGRAPH-95C3 +U+95C7(2,3);U+95C7(2,3); # 16-39, CJK UNIFIED IDEOGRAPH-95C7 +U+95CA(2,3);U+95CA(2,3); # 79-72, CJK UNIFIED IDEOGRAPH-95CA +U+95CC(2,3);U+95CC(2,3); # 79-76, CJK UNIFIED IDEOGRAPH-95CC +U+95CD(2,3);U+95CD(2,3); # 79-75, CJK UNIFIED IDEOGRAPH-95CD +U+95D4(2,3);U+95D4(2,3); # 79-78, CJK UNIFIED IDEOGRAPH-95D4 +U+95D5(2,3);U+95D5(2,3); # 79-77, CJK UNIFIED IDEOGRAPH-95D5 +U+95D6(2,3);U+95D6(2,3); # 79-79, CJK UNIFIED IDEOGRAPH-95D6 +U+95D8(2,3);U+95D8(2,3); # 38-14, CJK UNIFIED IDEOGRAPH-95D8 +U+95DC(2,3);U+95DC(2,3); # 79-80, CJK UNIFIED IDEOGRAPH-95DC +U+95E1(2,3);U+95E1(2,3); # 79-81, CJK UNIFIED IDEOGRAPH-95E1 +U+95E2(2,3);U+95E2(2,3); # 79-83, CJK UNIFIED IDEOGRAPH-95E2 +U+95E5(2,3);U+95E5(2,3); # 79-82, CJK UNIFIED IDEOGRAPH-95E5 +U+961C(2,3);U+961C(2,3); # 41-76, CJK UNIFIED IDEOGRAPH-961C +U+9621(2,3);U+9621(2,3); # 79-84, CJK UNIFIED IDEOGRAPH-9621 +U+9628(2,3);U+9628(2,3); # 79-85, CJK UNIFIED IDEOGRAPH-9628 +U+962A(2,3);U+962A(2,3); # 26-69, CJK UNIFIED IDEOGRAPH-962A +U+962E(2,3);U+962E(2,3); # 79-86, CJK UNIFIED IDEOGRAPH-962E +U+962F(2,3);U+962F(2,3); # 79-87, CJK UNIFIED IDEOGRAPH-962F +U+9632(2,3);U+9632(2,3); # 43-41, CJK UNIFIED IDEOGRAPH-9632 +U+963B(2,3);U+963B(2,3); # 33-43, CJK UNIFIED IDEOGRAPH-963B +U+963F(2,3);U+963F(2,3); # 16-04, CJK UNIFIED IDEOGRAPH-963F +U+9640(2,3);U+9640(2,3); # 34-43, CJK UNIFIED IDEOGRAPH-9640 +U+9642(2,3);U+9642(2,3); # 79-88, CJK UNIFIED IDEOGRAPH-9642 +U+9644(2,3);U+9644(2,3); # 41-77, CJK UNIFIED IDEOGRAPH-9644 +U+964B(2,3);U+964B(2,3); # 79-91, CJK UNIFIED IDEOGRAPH-964B +U+964C(2,3);U+964C(2,3); # 79-89, CJK UNIFIED IDEOGRAPH-964C +U+964D(2,3);U+964D(2,3); # 25-63, CJK UNIFIED IDEOGRAPH-964D +U+964F(2,3);U+964F(2,3); # 79-90, CJK UNIFIED IDEOGRAPH-964F +U+9650(2,3);U+9650(2,3); # 24-34, CJK UNIFIED IDEOGRAPH-9650 +U+965B(2,3);U+965B(2,3); # 42-37, CJK UNIFIED IDEOGRAPH-965B +U+965C(2,3);U+965C(2,3); # 79-93, CJK UNIFIED IDEOGRAPH-965C +U+965D(2,3);U+965D(2,3); # 80-01, CJK UNIFIED IDEOGRAPH-965D +U+965E(2,3);U+965E(2,3); # 79-94, CJK UNIFIED IDEOGRAPH-965E +U+965F(2,3);U+965F(2,3); # 80-02, CJK UNIFIED IDEOGRAPH-965F +U+9662(2,3);U+9662(2,3); # 17-01, CJK UNIFIED IDEOGRAPH-9662 +U+9663(2,3);U+9663(2,3); # 31-56, CJK UNIFIED IDEOGRAPH-9663 +U+9664(2,3);U+9664(2,3); # 29-92, CJK UNIFIED IDEOGRAPH-9664 +U+9665(2,3);U+9665(2,3); # 20-57, CJK UNIFIED IDEOGRAPH-9665 +U+9666(2,3);U+9666(2,3); # 80-03, CJK UNIFIED IDEOGRAPH-9666 +U+966A(2,3);U+966A(2,3); # 39-70, CJK UNIFIED IDEOGRAPH-966A +U+966C(2,3);U+966C(2,3); # 80-05, CJK UNIFIED IDEOGRAPH-966C +U+9670(2,3);U+9670(2,3); # 17-02, CJK UNIFIED IDEOGRAPH-9670 +U+9672(2,3);U+9672(2,3); # 80-04, CJK UNIFIED IDEOGRAPH-9672 +U+9673(2,3);U+9673(2,3); # 36-36, CJK UNIFIED IDEOGRAPH-9673 +U+9675(2,3);U+9675(2,3); # 46-45, CJK UNIFIED IDEOGRAPH-9675 +U+9676(2,3);U+9676(2,3); # 38-11, CJK UNIFIED IDEOGRAPH-9676 +U+9677(2,3);U+9677(2,3); # 79-92, CJK UNIFIED IDEOGRAPH-9677 +U+9678(2,3);U+9678(2,3); # 46-06, CJK UNIFIED IDEOGRAPH-9678 +U+967A(2,3);U+967A(2,3); # 24-17, CJK UNIFIED IDEOGRAPH-967A +U+967D(2,3);U+967D(2,3); # 45-59, CJK UNIFIED IDEOGRAPH-967D +U+9685(2,3);U+9685(2,3); # 22-89, CJK UNIFIED IDEOGRAPH-9685 +U+9686(2,3);U+9686(2,3); # 46-20, CJK UNIFIED IDEOGRAPH-9686 +U+9688(2,3);U+9688(2,3); # 23-08, CJK UNIFIED IDEOGRAPH-9688 +U+968A(2,3);U+968A(2,3); # 34-66, CJK UNIFIED IDEOGRAPH-968A +U+968B(2,3);U+968B(2,3); # 71-01, CJK UNIFIED IDEOGRAPH-968B +U+968D(2,3);U+968D(2,3); # 80-06, CJK UNIFIED IDEOGRAPH-968D +U+968E(2,3);U+968E(2,3); # 19-12, CJK UNIFIED IDEOGRAPH-968E +U+968F(2,3);U+968F(2,3); # 31-79, CJK UNIFIED IDEOGRAPH-968F +U+9694(2,3);U+9694(2,3); # 19-54, CJK UNIFIED IDEOGRAPH-9694 +U+9695(2,3);U+9695(2,3); # 80-08, CJK UNIFIED IDEOGRAPH-9695 +U+9697(2,3);U+9697(2,3); # 80-09, CJK UNIFIED IDEOGRAPH-9697 +U+9698(2,3);U+9698(2,3); # 80-07, CJK UNIFIED IDEOGRAPH-9698 +U+9699(2,3);U+9699(2,3); # 23-68, CJK UNIFIED IDEOGRAPH-9699 +U+969B(2,3);U+969B(2,3); # 26-61, CJK UNIFIED IDEOGRAPH-969B +U+969C(2,3);U+969C(2,3); # 30-67, CJK UNIFIED IDEOGRAPH-969C +U+96A0(2,3);U+96A0(2,3); # 17-03, CJK UNIFIED IDEOGRAPH-96A0 +U+96A3(2,3);U+96A3(2,3); # 46-57, CJK UNIFIED IDEOGRAPH-96A3 +U+96A7(2,3);U+96A7(2,3); # 80-11, CJK UNIFIED IDEOGRAPH-96A7 +U+96A8(2,3);U+96A8(2,3); # 78-14, CJK UNIFIED IDEOGRAPH-96A8 +U+96AA(2,3);U+96AA(2,3); # 80-10, CJK UNIFIED IDEOGRAPH-96AA +U+96B0(2,3);U+96B0(2,3); # 80-14, CJK UNIFIED IDEOGRAPH-96B0 +U+96B1(2,3);U+96B1(2,3); # 80-12, CJK UNIFIED IDEOGRAPH-96B1 +U+96B2(2,3);U+96B2(2,3); # 80-13, CJK UNIFIED IDEOGRAPH-96B2 +U+96B4(2,3);U+96B4(2,3); # 80-15, CJK UNIFIED IDEOGRAPH-96B4 +U+96B6(2,3);U+96B6(2,3); # 80-16, CJK UNIFIED IDEOGRAPH-96B6 +U+96B7(2,3);U+96B7(2,3); # 46-76, CJK UNIFIED IDEOGRAPH-96B7 +U+96B8(2,3);U+96B8(2,3); # 80-17, CJK UNIFIED IDEOGRAPH-96B8 +U+96B9(2,3);U+96B9(2,3); # 80-18, CJK UNIFIED IDEOGRAPH-96B9 +U+96BB(2,3);U+96BB(2,3); # 32-41, CJK UNIFIED IDEOGRAPH-96BB +U+96BC(2,3);U+96BC(2,3); # 40-27, CJK UNIFIED IDEOGRAPH-96BC +U+96C0(2,3);U+96C0(2,3); # 31-93, CJK UNIFIED IDEOGRAPH-96C0 +U+96C1(2,3);U+96C1(2,3); # 20-71, CJK UNIFIED IDEOGRAPH-96C1 +U+96C4(2,3);U+96C4(2,3); # 45-26, CJK UNIFIED IDEOGRAPH-96C4 +U+96C5(2,3);U+96C5(2,3); # 18-77, CJK UNIFIED IDEOGRAPH-96C5 +U+96C6(2,3);U+96C6(2,3); # 29-24, CJK UNIFIED IDEOGRAPH-96C6 +U+96C7(2,3);U+96C7(2,3); # 24-59, CJK UNIFIED IDEOGRAPH-96C7 +U+96C9(2,3);U+96C9(2,3); # 80-21, CJK UNIFIED IDEOGRAPH-96C9 +U+96CB(2,3);U+96CB(2,3); # 80-20, CJK UNIFIED IDEOGRAPH-96CB +U+96CC(2,3);U+96CC(2,3); # 27-83, CJK UNIFIED IDEOGRAPH-96CC +U+96CD(2,3);U+96CD(2,3); # 80-22, CJK UNIFIED IDEOGRAPH-96CD +U+96CE(2,3);U+96CE(2,3); # 80-19, CJK UNIFIED IDEOGRAPH-96CE +U+96D1(2,3);U+96D1(2,3); # 27-08, CJK UNIFIED IDEOGRAPH-96D1 +U+96D5(2,3);U+96D5(2,3); # 80-26, CJK UNIFIED IDEOGRAPH-96D5 +U+96D6(2,3);U+96D6(2,3); # 74-13, CJK UNIFIED IDEOGRAPH-96D6 +U+96D9(2,3);U+96D9(2,3); # 50-54, CJK UNIFIED IDEOGRAPH-96D9 +U+96DB(2,3);U+96DB(2,3); # 31-87, CJK UNIFIED IDEOGRAPH-96DB +U+96DC(2,3);U+96DC(2,3); # 80-24, CJK UNIFIED IDEOGRAPH-96DC +U+96E2(2,3);U+96E2(2,3); # 46-05, CJK UNIFIED IDEOGRAPH-96E2 +U+96E3(2,3);U+96E3(2,3); # 38-81, CJK UNIFIED IDEOGRAPH-96E3 +U+96E8(2,3);U+96E8(2,3); # 17-11, CJK UNIFIED IDEOGRAPH-96E8 +U+96EA(2,3);U+96EA(2,3); # 32-67, CJK UNIFIED IDEOGRAPH-96EA +U+96EB(2,3);U+96EB(2,3); # 28-22, CJK UNIFIED IDEOGRAPH-96EB +U+96F0(2,3);U+96F0(2,3); # 42-23, CJK UNIFIED IDEOGRAPH-96F0 +U+96F2(2,3);U+96F2(2,3); # 17-32, CJK UNIFIED IDEOGRAPH-96F2 +U+96F6(2,3);U+96F6(2,3); # 46-77, CJK UNIFIED IDEOGRAPH-96F6 +U+96F7(2,3);U+96F7(2,3); # 45-75, CJK UNIFIED IDEOGRAPH-96F7 +U+96F9(2,3);U+96F9(2,3); # 80-27, CJK UNIFIED IDEOGRAPH-96F9 +U+96FB(2,3);U+96FB(2,3); # 37-37, CJK UNIFIED IDEOGRAPH-96FB +U+9700(2,3);U+9700(2,3); # 28-91, CJK UNIFIED IDEOGRAPH-9700 +U+9704(2,3);U+9704(2,3); # 80-28, CJK UNIFIED IDEOGRAPH-9704 +U+9706(2,3);U+9706(2,3); # 80-29, CJK UNIFIED IDEOGRAPH-9706 +U+9707(2,3);U+9707(2,3); # 31-44, CJK UNIFIED IDEOGRAPH-9707 +U+9708(2,3);U+9708(2,3); # 80-30, CJK UNIFIED IDEOGRAPH-9708 +U+970A(2,3);U+970A(2,3); # 46-78, CJK UNIFIED IDEOGRAPH-970A +U+970D(2,3);U+970D(2,3); # 80-25, CJK UNIFIED IDEOGRAPH-970D +U+970E(2,3);U+970E(2,3); # 80-32, CJK UNIFIED IDEOGRAPH-970E +U+970F(2,3);U+970F(2,3); # 80-34, CJK UNIFIED IDEOGRAPH-970F +U+9711(2,3);U+9711(2,3); # 80-33, CJK UNIFIED IDEOGRAPH-9711 +U+9713(2,3);U+9713(2,3); # 80-31, CJK UNIFIED IDEOGRAPH-9713 +U+9716(2,3);U+9716(2,3); # 80-35, CJK UNIFIED IDEOGRAPH-9716 +U+9719(2,3);U+9719(2,3); # 80-36, CJK UNIFIED IDEOGRAPH-9719 +U+971C(2,3);U+971C(2,3); # 33-90, CJK UNIFIED IDEOGRAPH-971C +U+971E(2,3);U+971E(2,3); # 18-66, CJK UNIFIED IDEOGRAPH-971E +U+9724(2,3);U+9724(2,3); # 80-37, CJK UNIFIED IDEOGRAPH-9724 +U+9727(2,3);U+9727(2,3); # 44-24, CJK UNIFIED IDEOGRAPH-9727 +U+972A(2,3);U+972A(2,3); # 80-38, CJK UNIFIED IDEOGRAPH-972A +U+9730(2,3);U+9730(2,3); # 80-39, CJK UNIFIED IDEOGRAPH-9730 +U+9732(2,3);U+9732(2,3); # 47-10, CJK UNIFIED IDEOGRAPH-9732 +U+9738(2,3);U+9738(2,3); # 59-17, CJK UNIFIED IDEOGRAPH-9738 +U+9739(2,3);U+9739(2,3); # 80-40, CJK UNIFIED IDEOGRAPH-9739 +U+973D(2,3);U+973D(2,3); # 80-41, CJK UNIFIED IDEOGRAPH-973D +U+973E(2,3);U+973E(2,3); # 80-42, CJK UNIFIED IDEOGRAPH-973E +U+9742(2,3);U+9742(2,3); # 80-46, CJK UNIFIED IDEOGRAPH-9742 +U+9744(2,3);U+9744(2,3); # 80-43, CJK UNIFIED IDEOGRAPH-9744 +U+9746(2,3);U+9746(2,3); # 80-44, CJK UNIFIED IDEOGRAPH-9746 +U+9748(2,3);U+9748(2,3); # 80-45, CJK UNIFIED IDEOGRAPH-9748 +U+9749(2,3);U+9749(2,3); # 80-47, CJK UNIFIED IDEOGRAPH-9749 +U+9752(2,3);U+9752(2,3); # 32-36, CJK UNIFIED IDEOGRAPH-9752 +U+9756(2,3);U+9756(2,3); # 44-87, CJK UNIFIED IDEOGRAPH-9756 +U+9759(2,3);U+9759(2,3); # 32-37, CJK UNIFIED IDEOGRAPH-9759 +U+975C(2,3);U+975C(2,3); # 80-48, CJK UNIFIED IDEOGRAPH-975C +U+975E(2,3);U+975E(2,3); # 40-83, CJK UNIFIED IDEOGRAPH-975E +U+9760(2,3);U+9760(2,3); # 80-49, CJK UNIFIED IDEOGRAPH-9760 +U+9761(2,3);U+9761(2,3); # 83-51, CJK UNIFIED IDEOGRAPH-9761 +U+9762(2,3);U+9762(2,3); # 44-44, CJK UNIFIED IDEOGRAPH-9762 +U+9764(2,3);U+9764(2,3); # 80-50, CJK UNIFIED IDEOGRAPH-9764 +U+9766(2,3);U+9766(2,3); # 80-51, CJK UNIFIED IDEOGRAPH-9766 +U+9768(2,3);U+9768(2,3); # 80-52, CJK UNIFIED IDEOGRAPH-9768 +U+9769(2,3);U+9769(2,3); # 19-55, CJK UNIFIED IDEOGRAPH-9769 +U+976B(2,3);U+976B(2,3); # 80-54, CJK UNIFIED IDEOGRAPH-976B +U+976D(2,3);U+976D(2,3); # 31-57, CJK UNIFIED IDEOGRAPH-976D +U+9771(2,3);U+9771(2,3); # 80-55, CJK UNIFIED IDEOGRAPH-9771 +U+9774(2,3);U+9774(2,3); # 23-04, CJK UNIFIED IDEOGRAPH-9774 +U+9779(2,3);U+9779(2,3); # 80-56, CJK UNIFIED IDEOGRAPH-9779 +U+977A(2,3);U+977A(2,3); # 80-60, CJK UNIFIED IDEOGRAPH-977A +U+977C(2,3);U+977C(2,3); # 80-58, CJK UNIFIED IDEOGRAPH-977C +U+9781(2,3);U+9781(2,3); # 80-59, CJK UNIFIED IDEOGRAPH-9781 +U+9784(2,3);U+9784(2,3); # 19-83, CJK UNIFIED IDEOGRAPH-9784 +U+9785(2,3);U+9785(2,3); # 80-57, CJK UNIFIED IDEOGRAPH-9785 +U+9786(2,3);U+9786(2,3); # 80-61, CJK UNIFIED IDEOGRAPH-9786 +U+978B(2,3);U+978B(2,3); # 80-62, CJK UNIFIED IDEOGRAPH-978B +U+978D(2,3);U+978D(2,3); # 16-40, CJK UNIFIED IDEOGRAPH-978D +U+978F(2,3);U+978F(2,3); # 80-63, CJK UNIFIED IDEOGRAPH-978F +U+9790(2,3);U+9790(2,3); # 80-64, CJK UNIFIED IDEOGRAPH-9790 +U+9798(2,3);U+9798(2,3); # 30-68, CJK UNIFIED IDEOGRAPH-9798 +U+979C(2,3);U+979C(2,3); # 80-65, CJK UNIFIED IDEOGRAPH-979C +U+97A0(2,3);U+97A0(2,3); # 21-39, CJK UNIFIED IDEOGRAPH-97A0 +U+97A3(2,3);U+97A3(2,3); # 80-68, CJK UNIFIED IDEOGRAPH-97A3 +U+97A6(2,3);U+97A6(2,3); # 80-67, CJK UNIFIED IDEOGRAPH-97A6 +U+97A8(2,3);U+97A8(2,3); # 80-66, CJK UNIFIED IDEOGRAPH-97A8 +U+97AB(2,3);U+97AB(2,3); # 75-81, CJK UNIFIED IDEOGRAPH-97AB +U+97AD(2,3);U+97AD(2,3); # 42-60, CJK UNIFIED IDEOGRAPH-97AD +U+97B3(2,3);U+97B3(2,3); # 80-69, CJK UNIFIED IDEOGRAPH-97B3 +U+97B4(2,3);U+97B4(2,3); # 80-70, CJK UNIFIED IDEOGRAPH-97B4 +U+97C3(2,3);U+97C3(2,3); # 80-71, CJK UNIFIED IDEOGRAPH-97C3 +U+97C6(2,3);U+97C6(2,3); # 80-72, CJK UNIFIED IDEOGRAPH-97C6 +U+97C8(2,3);U+97C8(2,3); # 80-73, CJK UNIFIED IDEOGRAPH-97C8 +U+97CB(2,3);U+97CB(2,3); # 80-74, CJK UNIFIED IDEOGRAPH-97CB +U+97D3(2,3);U+97D3(2,3); # 20-58, CJK UNIFIED IDEOGRAPH-97D3 +U+97DC(2,3);U+97DC(2,3); # 80-75, CJK UNIFIED IDEOGRAPH-97DC +U+97ED(2,3);U+97ED(2,3); # 80-76, CJK UNIFIED IDEOGRAPH-97ED +U+97EE(2,3);U+97EE(2,3); # 39-03, CJK UNIFIED IDEOGRAPH-97EE +U+97F2(2,3);U+97F2(2,3); # 80-78, CJK UNIFIED IDEOGRAPH-97F2 +U+97F3(2,3);U+97F3(2,3); # 18-27, CJK UNIFIED IDEOGRAPH-97F3 +U+97F5(2,3);U+97F5(2,3); # 80-81, CJK UNIFIED IDEOGRAPH-97F5 +U+97F6(2,3);U+97F6(2,3); # 80-80, CJK UNIFIED IDEOGRAPH-97F6 +U+97FB(2,3);U+97FB(2,3); # 17-04, CJK UNIFIED IDEOGRAPH-97FB +U+97FF(2,3);U+97FF(2,3); # 22-33, CJK UNIFIED IDEOGRAPH-97FF +U+9801(2,3);U+9801(2,3); # 42-39, CJK UNIFIED IDEOGRAPH-9801 +U+9802(2,3);U+9802(2,3); # 36-26, CJK UNIFIED IDEOGRAPH-9802 +U+9803(2,3);U+9803(2,3); # 26-02, CJK UNIFIED IDEOGRAPH-9803 +U+9805(2,3);U+9805(2,3); # 25-64, CJK UNIFIED IDEOGRAPH-9805 +U+9806(2,3);U+9806(2,3); # 29-71, CJK UNIFIED IDEOGRAPH-9806 +U+9808(2,3);U+9808(2,3); # 31-60, CJK UNIFIED IDEOGRAPH-9808 +U+980C(2,3);U+980C(2,3); # 80-83, CJK UNIFIED IDEOGRAPH-980C +U+980F(2,3);U+980F(2,3); # 80-82, CJK UNIFIED IDEOGRAPH-980F +U+9810(2,3);U+9810(2,3); # 45-34, CJK UNIFIED IDEOGRAPH-9810 +U+9811(2,3);U+9811(2,3); # 20-72, CJK UNIFIED IDEOGRAPH-9811 +U+9812(2,3);U+9812(2,3); # 40-50, CJK UNIFIED IDEOGRAPH-9812 +U+9813(2,3);U+9813(2,3); # 38-60, CJK UNIFIED IDEOGRAPH-9813 +U+9817(2,3);U+9817(2,3); # 31-92, CJK UNIFIED IDEOGRAPH-9817 +U+9818(2,3);U+9818(2,3); # 46-46, CJK UNIFIED IDEOGRAPH-9818 +U+981A(2,3);U+981A(2,3); # 23-59, CJK UNIFIED IDEOGRAPH-981A +U+9821(2,3);U+9821(2,3); # 80-86, CJK UNIFIED IDEOGRAPH-9821 +U+9824(2,3);U+9824(2,3); # 80-85, CJK UNIFIED IDEOGRAPH-9824 +U+982C(2,3);U+982C(2,3); # 43-43, CJK UNIFIED IDEOGRAPH-982C +U+982D(2,3);U+982D(2,3); # 38-12, CJK UNIFIED IDEOGRAPH-982D +U+9834(2,3);U+9834(2,3); # 17-48, CJK UNIFIED IDEOGRAPH-9834 +U+9837(2,3);U+9837(2,3); # 80-87, CJK UNIFIED IDEOGRAPH-9837 +U+9838(2,3);U+9838(2,3); # 80-84, CJK UNIFIED IDEOGRAPH-9838 +U+983B(2,3);U+983B(2,3); # 41-49, CJK UNIFIED IDEOGRAPH-983B +U+983C(2,3);U+983C(2,3); # 45-74, CJK UNIFIED IDEOGRAPH-983C +U+983D(2,3);U+983D(2,3); # 80-88, CJK UNIFIED IDEOGRAPH-983D +U+9846(2,3);U+9846(2,3); # 80-89, CJK UNIFIED IDEOGRAPH-9846 +U+984B(2,3);U+984B(2,3); # 80-91, CJK UNIFIED IDEOGRAPH-984B +U+984C(2,3);U+984C(2,3); # 34-74, CJK UNIFIED IDEOGRAPH-984C +U+984D(2,3);U+984D(2,3); # 19-59, CJK UNIFIED IDEOGRAPH-984D +U+984E(2,3);U+984E(2,3); # 19-60, CJK UNIFIED IDEOGRAPH-984E +U+984F(2,3);U+984F(2,3); # 80-90, CJK UNIFIED IDEOGRAPH-984F +U+9854(2,3);U+9854(2,3); # 20-73, CJK UNIFIED IDEOGRAPH-9854 +U+9855(2,3);U+9855(2,3); # 24-18, CJK UNIFIED IDEOGRAPH-9855 +U+9858(2,3);U+9858(2,3); # 20-74, CJK UNIFIED IDEOGRAPH-9858 +U+985B(2,3);U+985B(2,3); # 37-31, CJK UNIFIED IDEOGRAPH-985B +U+985E(2,3);U+985E(2,3); # 46-64, CJK UNIFIED IDEOGRAPH-985E +U+9867(2,3);U+9867(2,3); # 24-60, CJK UNIFIED IDEOGRAPH-9867 +U+986B(2,3);U+986B(2,3); # 80-92, CJK UNIFIED IDEOGRAPH-986B +U+986F(2,3);U+986F(2,3); # 80-93, CJK UNIFIED IDEOGRAPH-986F +U+9870(2,3);U+9870(2,3); # 80-94, CJK UNIFIED IDEOGRAPH-9870 +U+9871(2,3);U+9871(2,3); # 81-01, CJK UNIFIED IDEOGRAPH-9871 +U+9873(2,3);U+9873(2,3); # 81-03, CJK UNIFIED IDEOGRAPH-9873 +U+9874(2,3);U+9874(2,3); # 81-02, CJK UNIFIED IDEOGRAPH-9874 +U+98A8(2,3);U+98A8(2,3); # 41-87, CJK UNIFIED IDEOGRAPH-98A8 +U+98AA(2,3);U+98AA(2,3); # 81-04, CJK UNIFIED IDEOGRAPH-98AA +U+98AF(2,3);U+98AF(2,3); # 81-05, CJK UNIFIED IDEOGRAPH-98AF +U+98B1(2,3);U+98B1(2,3); # 81-06, CJK UNIFIED IDEOGRAPH-98B1 +U+98B6(2,3);U+98B6(2,3); # 81-07, CJK UNIFIED IDEOGRAPH-98B6 +U+98C3(2,3);U+98C3(2,3); # 81-09, CJK UNIFIED IDEOGRAPH-98C3 +U+98C4(2,3);U+98C4(2,3); # 81-08, CJK UNIFIED IDEOGRAPH-98C4 +U+98C6(2,3);U+98C6(2,3); # 81-10, CJK UNIFIED IDEOGRAPH-98C6 +U+98DB(2,3);U+98DB(2,3); # 40-84, CJK UNIFIED IDEOGRAPH-98DB +U+98DC(2,3);U+98DC(2,3); # 70-44, CJK UNIFIED IDEOGRAPH-98DC +U+98DF(2,3);U+98DF(2,3); # 31-09, CJK UNIFIED IDEOGRAPH-98DF +U+98E2(2,3);U+98E2(2,3); # 21-18, CJK UNIFIED IDEOGRAPH-98E2 +U+98E9(2,3);U+98E9(2,3); # 81-11, CJK UNIFIED IDEOGRAPH-98E9 +U+98EB(2,3);U+98EB(2,3); # 81-12, CJK UNIFIED IDEOGRAPH-98EB +U+98ED(2,3);U+98ED(2,3); # 50-12, CJK UNIFIED IDEOGRAPH-98ED +U+98EE(2,3);U+98EE(2,3); # 61-27, CJK UNIFIED IDEOGRAPH-98EE +U+98EF(2,3);U+98EF(2,3); # 40-51, CJK UNIFIED IDEOGRAPH-98EF +U+98F2(2,3);U+98F2(2,3); # 16-91, CJK UNIFIED IDEOGRAPH-98F2 +U+98F4(2,3);U+98F4(2,3); # 16-27, CJK UNIFIED IDEOGRAPH-98F4 +U+98FC(2,3);U+98FC(2,3); # 27-84, CJK UNIFIED IDEOGRAPH-98FC +U+98FD(2,3);U+98FD(2,3); # 43-16, CJK UNIFIED IDEOGRAPH-98FD +U+98FE(2,3);U+98FE(2,3); # 30-94, CJK UNIFIED IDEOGRAPH-98FE +U+9903(2,3);U+9903(2,3); # 81-13, CJK UNIFIED IDEOGRAPH-9903 +U+9905(2,3);U+9905(2,3); # 44-63, CJK UNIFIED IDEOGRAPH-9905 +U+9909(2,3);U+9909(2,3); # 81-14, CJK UNIFIED IDEOGRAPH-9909 +U+990A(2,3);U+990A(2,3); # 45-60, CJK UNIFIED IDEOGRAPH-990A +U+990C(2,3);U+990C(2,3); # 17-34, CJK UNIFIED IDEOGRAPH-990C +U+9910(2,3);U+9910(2,3); # 27-33, CJK UNIFIED IDEOGRAPH-9910 +U+9912(2,3);U+9912(2,3); # 81-15, CJK UNIFIED IDEOGRAPH-9912 +U+9913(2,3);U+9913(2,3); # 18-78, CJK UNIFIED IDEOGRAPH-9913 +U+9914(2,3);U+9914(2,3); # 81-16, CJK UNIFIED IDEOGRAPH-9914 +U+9918(2,3);U+9918(2,3); # 81-17, CJK UNIFIED IDEOGRAPH-9918 +U+991D(2,3);U+991D(2,3); # 81-19, CJK UNIFIED IDEOGRAPH-991D +U+991E(2,3);U+991E(2,3); # 81-20, CJK UNIFIED IDEOGRAPH-991E +U+9920(2,3);U+9920(2,3); # 81-22, CJK UNIFIED IDEOGRAPH-9920 +U+9921(2,3);U+9921(2,3); # 81-18, CJK UNIFIED IDEOGRAPH-9921 +U+9924(2,3);U+9924(2,3); # 81-21, CJK UNIFIED IDEOGRAPH-9924 +U+9928(2,3);U+9928(2,3); # 20-59, CJK UNIFIED IDEOGRAPH-9928 +U+992C(2,3);U+992C(2,3); # 81-23, CJK UNIFIED IDEOGRAPH-992C +U+992E(2,3);U+992E(2,3); # 81-24, CJK UNIFIED IDEOGRAPH-992E +U+993D(2,3);U+993D(2,3); # 81-25, CJK UNIFIED IDEOGRAPH-993D +U+993E(2,3);U+993E(2,3); # 81-26, CJK UNIFIED IDEOGRAPH-993E +U+9942(2,3);U+9942(2,3); # 81-27, CJK UNIFIED IDEOGRAPH-9942 +U+9945(2,3);U+9945(2,3); # 81-29, CJK UNIFIED IDEOGRAPH-9945 +U+9949(2,3);U+9949(2,3); # 81-28, CJK UNIFIED IDEOGRAPH-9949 +U+994B(2,3);U+994B(2,3); # 81-31, CJK UNIFIED IDEOGRAPH-994B +U+994C(2,3);U+994C(2,3); # 81-34, CJK UNIFIED IDEOGRAPH-994C +U+9950(2,3);U+9950(2,3); # 81-30, CJK UNIFIED IDEOGRAPH-9950 +U+9951(2,3);U+9951(2,3); # 81-32, CJK UNIFIED IDEOGRAPH-9951 +U+9952(2,3);U+9952(2,3); # 81-33, CJK UNIFIED IDEOGRAPH-9952 +U+9955(2,3);U+9955(2,3); # 81-35, CJK UNIFIED IDEOGRAPH-9955 +U+9957(2,3);U+9957(2,3); # 22-34, CJK UNIFIED IDEOGRAPH-9957 +U+9996(2,3);U+9996(2,3); # 28-83, CJK UNIFIED IDEOGRAPH-9996 +U+9997(2,3);U+9997(2,3); # 81-36, CJK UNIFIED IDEOGRAPH-9997 +U+9998(2,3);U+9998(2,3); # 81-37, CJK UNIFIED IDEOGRAPH-9998 +U+9999(2,3);U+9999(2,3); # 25-65, CJK UNIFIED IDEOGRAPH-9999 +U+99A5(2,3);U+99A5(2,3); # 81-38, CJK UNIFIED IDEOGRAPH-99A5 +U+99A8(2,3);U+99A8(2,3); # 19-30, CJK UNIFIED IDEOGRAPH-99A8 +U+99AC(2,3);U+99AC(2,3); # 39-47, CJK UNIFIED IDEOGRAPH-99AC +U+99AD(2,3);U+99AD(2,3); # 81-39, CJK UNIFIED IDEOGRAPH-99AD +U+99AE(2,3);U+99AE(2,3); # 81-40, CJK UNIFIED IDEOGRAPH-99AE +U+99B3(2,3);U+99B3(2,3); # 35-58, CJK UNIFIED IDEOGRAPH-99B3 +U+99B4(2,3);U+99B4(2,3); # 38-75, CJK UNIFIED IDEOGRAPH-99B4 +U+99BC(2,3);U+99BC(2,3); # 81-41, CJK UNIFIED IDEOGRAPH-99BC +U+99C1(2,3);U+99C1(2,3); # 39-93, CJK UNIFIED IDEOGRAPH-99C1 +U+99C4(2,3);U+99C4(2,3); # 34-44, CJK UNIFIED IDEOGRAPH-99C4 +U+99C5(2,3);U+99C5(2,3); # 17-56, CJK UNIFIED IDEOGRAPH-99C5 +U+99C6(2,3);U+99C6(2,3); # 22-78, CJK UNIFIED IDEOGRAPH-99C6 +U+99C8(2,3);U+99C8(2,3); # 22-79, CJK UNIFIED IDEOGRAPH-99C8 +U+99D0(2,3);U+99D0(2,3); # 35-83, CJK UNIFIED IDEOGRAPH-99D0 +U+99D1(2,3);U+99D1(2,3); # 81-46, CJK UNIFIED IDEOGRAPH-99D1 +U+99D2(2,3);U+99D2(2,3); # 22-80, CJK UNIFIED IDEOGRAPH-99D2 +U+99D5(2,3);U+99D5(2,3); # 18-79, CJK UNIFIED IDEOGRAPH-99D5 +U+99D8(2,3);U+99D8(2,3); # 81-45, CJK UNIFIED IDEOGRAPH-99D8 +U+99DB(2,3);U+99DB(2,3); # 81-43, CJK UNIFIED IDEOGRAPH-99DB +U+99DD(2,3);U+99DD(2,3); # 81-44, CJK UNIFIED IDEOGRAPH-99DD +U+99DF(2,3);U+99DF(2,3); # 81-42, CJK UNIFIED IDEOGRAPH-99DF +U+99E2(2,3);U+99E2(2,3); # 81-56, CJK UNIFIED IDEOGRAPH-99E2 +U+99ED(2,3);U+99ED(2,3); # 81-47, CJK UNIFIED IDEOGRAPH-99ED +U+99EE(2,3);U+99EE(2,3); # 81-48, CJK UNIFIED IDEOGRAPH-99EE +U+99F1(2,3);U+99F1(2,3); # 81-49, CJK UNIFIED IDEOGRAPH-99F1 +U+99F2(2,3);U+99F2(2,3); # 81-50, CJK UNIFIED IDEOGRAPH-99F2 +U+99F8(2,3);U+99F8(2,3); # 81-52, CJK UNIFIED IDEOGRAPH-99F8 +U+99FB(2,3);U+99FB(2,3); # 81-51, CJK UNIFIED IDEOGRAPH-99FB +U+99FF(2,3);U+99FF(2,3); # 29-57, CJK UNIFIED IDEOGRAPH-99FF +U+9A01(2,3);U+9A01(2,3); # 81-53, CJK UNIFIED IDEOGRAPH-9A01 +U+9A05(2,3);U+9A05(2,3); # 81-55, CJK UNIFIED IDEOGRAPH-9A05 +U+9A0E(2,3);U+9A0E(2,3); # 21-19, CJK UNIFIED IDEOGRAPH-9A0E +U+9A0F(2,3);U+9A0F(2,3); # 81-54, CJK UNIFIED IDEOGRAPH-9A0F +U+9A12(2,3);U+9A12(2,3); # 33-91, CJK UNIFIED IDEOGRAPH-9A12 +U+9A13(2,3);U+9A13(2,3); # 24-19, CJK UNIFIED IDEOGRAPH-9A13 +U+9A19(2,3);U+9A19(2,3); # 81-57, CJK UNIFIED IDEOGRAPH-9A19 +U+9A28(2,3);U+9A28(2,3); # 34-45, CJK UNIFIED IDEOGRAPH-9A28 +U+9A2B(2,3);U+9A2B(2,3); # 81-58, CJK UNIFIED IDEOGRAPH-9A2B +U+9A30(2,3);U+9A30(2,3); # 38-13, CJK UNIFIED IDEOGRAPH-9A30 +U+9A37(2,3);U+9A37(2,3); # 81-59, CJK UNIFIED IDEOGRAPH-9A37 +U+9A3E(2,3);U+9A3E(2,3); # 81-64, CJK UNIFIED IDEOGRAPH-9A3E +U+9A40(2,3);U+9A40(2,3); # 81-62, CJK UNIFIED IDEOGRAPH-9A40 +U+9A42(2,3);U+9A42(2,3); # 81-61, CJK UNIFIED IDEOGRAPH-9A42 +U+9A43(2,3);U+9A43(2,3); # 81-63, CJK UNIFIED IDEOGRAPH-9A43 +U+9A45(2,3);U+9A45(2,3); # 81-60, CJK UNIFIED IDEOGRAPH-9A45 +U+9A4D(2,3);U+9A4D(2,3); # 81-66, CJK UNIFIED IDEOGRAPH-9A4D +U+9A55(2,3);U+9A55(2,3); # 81-65, CJK UNIFIED IDEOGRAPH-9A55 +U+9A57(2,3);U+9A57(2,3); # 81-68, CJK UNIFIED IDEOGRAPH-9A57 +U+9A5A(2,3);U+9A5A(2,3); # 22-35, CJK UNIFIED IDEOGRAPH-9A5A +U+9A5B(2,3);U+9A5B(2,3); # 81-67, CJK UNIFIED IDEOGRAPH-9A5B +U+9A5F(2,3);U+9A5F(2,3); # 81-69, CJK UNIFIED IDEOGRAPH-9A5F +U+9A62(2,3);U+9A62(2,3); # 81-70, CJK UNIFIED IDEOGRAPH-9A62 +U+9A64(2,3);U+9A64(2,3); # 81-72, CJK UNIFIED IDEOGRAPH-9A64 +U+9A65(2,3);U+9A65(2,3); # 81-71, CJK UNIFIED IDEOGRAPH-9A65 +U+9A69(2,3);U+9A69(2,3); # 81-73, CJK UNIFIED IDEOGRAPH-9A69 +U+9A6A(2,3);U+9A6A(2,3); # 81-75, CJK UNIFIED IDEOGRAPH-9A6A +U+9A6B(2,3);U+9A6B(2,3); # 81-74, CJK UNIFIED IDEOGRAPH-9A6B +U+9AA8(2,3);U+9AA8(2,3); # 25-92, CJK UNIFIED IDEOGRAPH-9AA8 +U+9AAD(2,3);U+9AAD(2,3); # 81-76, CJK UNIFIED IDEOGRAPH-9AAD +U+9AB0(2,3);U+9AB0(2,3); # 81-77, CJK UNIFIED IDEOGRAPH-9AB0 +U+9AB8(2,3);U+9AB8(2,3); # 19-28, CJK UNIFIED IDEOGRAPH-9AB8 +U+9ABC(2,3);U+9ABC(2,3); # 81-78, CJK UNIFIED IDEOGRAPH-9ABC +U+9AC0(2,3);U+9AC0(2,3); # 81-79, CJK UNIFIED IDEOGRAPH-9AC0 +U+9AC4(2,3);U+9AC4(2,3); # 31-81, CJK UNIFIED IDEOGRAPH-9AC4 +U+9ACF(2,3);U+9ACF(2,3); # 81-80, CJK UNIFIED IDEOGRAPH-9ACF +U+9AD1(2,3);U+9AD1(2,3); # 81-81, CJK UNIFIED IDEOGRAPH-9AD1 +U+9AD3(2,3);U+9AD3(2,3); # 81-82, CJK UNIFIED IDEOGRAPH-9AD3 +U+9AD4(2,3);U+9AD4(2,3); # 81-83, CJK UNIFIED IDEOGRAPH-9AD4 +U+9AD8(2,3);U+9AD8(2,3); # 25-66, CJK UNIFIED IDEOGRAPH-9AD8 +U+9ADE(2,3);U+9ADE(2,3); # 81-84, CJK UNIFIED IDEOGRAPH-9ADE +U+9ADF(2,3);U+9ADF(2,3); # 81-85, CJK UNIFIED IDEOGRAPH-9ADF +U+9AE2(2,3);U+9AE2(2,3); # 81-86, CJK UNIFIED IDEOGRAPH-9AE2 +U+9AE3(2,3);U+9AE3(2,3); # 81-87, CJK UNIFIED IDEOGRAPH-9AE3 +U+9AE6(2,3);U+9AE6(2,3); # 81-88, CJK UNIFIED IDEOGRAPH-9AE6 +U+9AEA(2,3);U+9AEA(2,3); # 40-17, CJK UNIFIED IDEOGRAPH-9AEA +U+9AEB(2,3);U+9AEB(2,3); # 81-90, CJK UNIFIED IDEOGRAPH-9AEB +U+9AED(2,3);U+9AED(2,3); # 41-06, CJK UNIFIED IDEOGRAPH-9AED +U+9AEE(2,3);U+9AEE(2,3); # 81-91, CJK UNIFIED IDEOGRAPH-9AEE +U+9AEF(2,3);U+9AEF(2,3); # 81-89, CJK UNIFIED IDEOGRAPH-9AEF +U+9AF1(2,3);U+9AF1(2,3); # 81-93, CJK UNIFIED IDEOGRAPH-9AF1 +U+9AF4(2,3);U+9AF4(2,3); # 81-92, CJK UNIFIED IDEOGRAPH-9AF4 +U+9AF7(2,3);U+9AF7(2,3); # 81-94, CJK UNIFIED IDEOGRAPH-9AF7 +U+9AFB(2,3);U+9AFB(2,3); # 82-01, CJK UNIFIED IDEOGRAPH-9AFB +U+9B06(2,3);U+9B06(2,3); # 82-02, CJK UNIFIED IDEOGRAPH-9B06 +U+9B18(2,3);U+9B18(2,3); # 82-03, CJK UNIFIED IDEOGRAPH-9B18 +U+9B1A(2,3);U+9B1A(2,3); # 82-04, CJK UNIFIED IDEOGRAPH-9B1A +U+9B1F(2,3);U+9B1F(2,3); # 82-05, CJK UNIFIED IDEOGRAPH-9B1F +U+9B22(2,3);U+9B22(2,3); # 82-06, CJK UNIFIED IDEOGRAPH-9B22 +U+9B23(2,3);U+9B23(2,3); # 82-07, CJK UNIFIED IDEOGRAPH-9B23 +U+9B25(2,3);U+9B25(2,3); # 82-08, CJK UNIFIED IDEOGRAPH-9B25 +U+9B27(2,3);U+9B27(2,3); # 82-09, CJK UNIFIED IDEOGRAPH-9B27 +U+9B28(2,3);U+9B28(2,3); # 82-10, CJK UNIFIED IDEOGRAPH-9B28 +U+9B29(2,3);U+9B29(2,3); # 82-11, CJK UNIFIED IDEOGRAPH-9B29 +U+9B2A(2,3);U+9B2A(2,3); # 82-12, CJK UNIFIED IDEOGRAPH-9B2A +U+9B2E(2,3);U+9B2E(2,3); # 82-13, CJK UNIFIED IDEOGRAPH-9B2E +U+9B2F(2,3);U+9B2F(2,3); # 82-14, CJK UNIFIED IDEOGRAPH-9B2F +U+9B31(2,3);U+9B31(2,3); # 61-21, CJK UNIFIED IDEOGRAPH-9B31 +U+9B32(2,3);U+9B32(2,3); # 82-15, CJK UNIFIED IDEOGRAPH-9B32 +U+9B3B(2,3);U+9B3B(2,3); # 68-88, CJK UNIFIED IDEOGRAPH-9B3B +U+9B3C(2,3);U+9B3C(2,3); # 21-20, CJK UNIFIED IDEOGRAPH-9B3C +U+9B41(2,3);U+9B41(2,3); # 19-01, CJK UNIFIED IDEOGRAPH-9B41 +U+9B42(2,3);U+9B42(2,3); # 26-18, CJK UNIFIED IDEOGRAPH-9B42 +U+9B43(2,3);U+9B43(2,3); # 82-17, CJK UNIFIED IDEOGRAPH-9B43 +U+9B44(2,3);U+9B44(2,3); # 82-16, CJK UNIFIED IDEOGRAPH-9B44 +U+9B45(2,3);U+9B45(2,3); # 44-05, CJK UNIFIED IDEOGRAPH-9B45 +U+9B4D(2,3);U+9B4D(2,3); # 82-19, CJK UNIFIED IDEOGRAPH-9B4D +U+9B4E(2,3);U+9B4E(2,3); # 82-20, CJK UNIFIED IDEOGRAPH-9B4E +U+9B4F(2,3);U+9B4F(2,3); # 82-18, CJK UNIFIED IDEOGRAPH-9B4F +U+9B51(2,3);U+9B51(2,3); # 82-21, CJK UNIFIED IDEOGRAPH-9B51 +U+9B54(2,3);U+9B54(2,3); # 43-66, CJK UNIFIED IDEOGRAPH-9B54 +U+9B58(2,3);U+9B58(2,3); # 82-22, CJK UNIFIED IDEOGRAPH-9B58 +U+9B5A(2,3);U+9B5A(2,3); # 21-91, CJK UNIFIED IDEOGRAPH-9B5A +U+9B6F(2,3);U+9B6F(2,3); # 47-05, CJK UNIFIED IDEOGRAPH-9B6F +U+9B74(2,3);U+9B74(2,3); # 82-23, CJK UNIFIED IDEOGRAPH-9B74 +U+9B83(2,3);U+9B83(2,3); # 82-25, CJK UNIFIED IDEOGRAPH-9B83 +U+9B8E(2,3);U+9B8E(2,3); # 16-30, CJK UNIFIED IDEOGRAPH-9B8E +U+9B91(2,3);U+9B91(2,3); # 82-26, CJK UNIFIED IDEOGRAPH-9B91 +U+9B92(2,3);U+9B92(2,3); # 42-11, CJK UNIFIED IDEOGRAPH-9B92 +U+9B93(2,3);U+9B93(2,3); # 82-24, CJK UNIFIED IDEOGRAPH-9B93 +U+9B96(2,3);U+9B96(2,3); # 82-27, CJK UNIFIED IDEOGRAPH-9B96 +U+9B97(2,3);U+9B97(2,3); # 82-28, CJK UNIFIED IDEOGRAPH-9B97 +U+9B9F(2,3);U+9B9F(2,3); # 82-29, CJK UNIFIED IDEOGRAPH-9B9F +U+9BA0(2,3);U+9BA0(2,3); # 82-30, CJK UNIFIED IDEOGRAPH-9BA0 +U+9BA8(2,3);U+9BA8(2,3); # 82-31, CJK UNIFIED IDEOGRAPH-9BA8 +U+9BAA(2,3);U+9BAA(2,3); # 43-78, CJK UNIFIED IDEOGRAPH-9BAA +U+9BAB(2,3);U+9BAB(2,3); # 27-13, CJK UNIFIED IDEOGRAPH-9BAB +U+9BAD(2,3);U+9BAD(2,3); # 26-90, CJK UNIFIED IDEOGRAPH-9BAD +U+9BAE(2,3);U+9BAE(2,3); # 33-15, CJK UNIFIED IDEOGRAPH-9BAE +U+9BB4(2,3);U+9BB4(2,3); # 82-32, CJK UNIFIED IDEOGRAPH-9BB4 +U+9BB9(2,3);U+9BB9(2,3); # 82-35, CJK UNIFIED IDEOGRAPH-9BB9 +U+9BC0(2,3);U+9BC0(2,3); # 82-33, CJK UNIFIED IDEOGRAPH-9BC0 +U+9BC6(2,3);U+9BC6(2,3); # 82-36, CJK UNIFIED IDEOGRAPH-9BC6 +U+9BC9(2,3);U+9BC9(2,3); # 24-81, CJK UNIFIED IDEOGRAPH-9BC9 +U+9BCA(2,3);U+9BCA(2,3); # 82-34, CJK UNIFIED IDEOGRAPH-9BCA +U+9BCF(2,3);U+9BCF(2,3); # 82-37, CJK UNIFIED IDEOGRAPH-9BCF +U+9BD1(2,3);U+9BD1(2,3); # 82-38, CJK UNIFIED IDEOGRAPH-9BD1 +U+9BD2(2,3);U+9BD2(2,3); # 82-39, CJK UNIFIED IDEOGRAPH-9BD2 +U+9BD4(2,3);U+9BD4(2,3); # 82-43, CJK UNIFIED IDEOGRAPH-9BD4 +U+9BD6(2,3);U+9BD6(2,3); # 27-10, CJK UNIFIED IDEOGRAPH-9BD6 +U+9BDB(2,3);U+9BDB(2,3); # 34-68, CJK UNIFIED IDEOGRAPH-9BDB +U+9BE1(2,3);U+9BE1(2,3); # 82-44, CJK UNIFIED IDEOGRAPH-9BE1 +U+9BE2(2,3);U+9BE2(2,3); # 82-41, CJK UNIFIED IDEOGRAPH-9BE2 +U+9BE3(2,3);U+9BE3(2,3); # 82-40, CJK UNIFIED IDEOGRAPH-9BE3 +U+9BE4(2,3);U+9BE4(2,3); # 82-42, CJK UNIFIED IDEOGRAPH-9BE4 +U+9BE8(2,3);U+9BE8(2,3); # 23-63, CJK UNIFIED IDEOGRAPH-9BE8 +U+9BF0(2,3);U+9BF0(2,3); # 82-48, CJK UNIFIED IDEOGRAPH-9BF0 +U+9BF1(2,3);U+9BF1(2,3); # 82-47, CJK UNIFIED IDEOGRAPH-9BF1 +U+9BF2(2,3);U+9BF2(2,3); # 82-46, CJK UNIFIED IDEOGRAPH-9BF2 +U+9BF5(2,3);U+9BF5(2,3); # 16-19, CJK UNIFIED IDEOGRAPH-9BF5 +U+9C04(2,3);U+9C04(2,3); # 82-58, CJK UNIFIED IDEOGRAPH-9C04 +U+9C06(2,3);U+9C06(2,3); # 82-54, CJK UNIFIED IDEOGRAPH-9C06 +U+9C08(2,3);U+9C08(2,3); # 82-55, CJK UNIFIED IDEOGRAPH-9C08 +U+9C09(2,3);U+9C09(2,3); # 82-51, CJK UNIFIED IDEOGRAPH-9C09 +U+9C0A(2,3);U+9C0A(2,3); # 82-57, CJK UNIFIED IDEOGRAPH-9C0A +U+9C0C(2,3);U+9C0C(2,3); # 82-53, CJK UNIFIED IDEOGRAPH-9C0C +U+9C0D(2,3);U+9C0D(2,3); # 19-66, CJK UNIFIED IDEOGRAPH-9C0D +U+9C10(2,3);U+9C10(2,3); # 47-44, CJK UNIFIED IDEOGRAPH-9C10 +U+9C12(2,3);U+9C12(2,3); # 82-56, CJK UNIFIED IDEOGRAPH-9C12 +U+9C13(2,3);U+9C13(2,3); # 82-52, CJK UNIFIED IDEOGRAPH-9C13 +U+9C14(2,3);U+9C14(2,3); # 82-50, CJK UNIFIED IDEOGRAPH-9C14 +U+9C15(2,3);U+9C15(2,3); # 82-49, CJK UNIFIED IDEOGRAPH-9C15 +U+9C1B(2,3);U+9C1B(2,3); # 82-60, CJK UNIFIED IDEOGRAPH-9C1B +U+9C21(2,3);U+9C21(2,3); # 82-63, CJK UNIFIED IDEOGRAPH-9C21 +U+9C24(2,3);U+9C24(2,3); # 82-62, CJK UNIFIED IDEOGRAPH-9C24 +U+9C25(2,3);U+9C25(2,3); # 82-61, CJK UNIFIED IDEOGRAPH-9C25 +U+9C2D(2,3);U+9C2D(2,3); # 41-41, CJK UNIFIED IDEOGRAPH-9C2D +U+9C2E(2,3);U+9C2E(2,3); # 82-59, CJK UNIFIED IDEOGRAPH-9C2E +U+9C2F(2,3);U+9C2F(2,3); # 16-83, CJK UNIFIED IDEOGRAPH-9C2F +U+9C30(2,3);U+9C30(2,3); # 82-64, CJK UNIFIED IDEOGRAPH-9C30 +U+9C32(2,3);U+9C32(2,3); # 82-66, CJK UNIFIED IDEOGRAPH-9C32 +U+9C39(2,3);U+9C39(2,3); # 19-79, CJK UNIFIED IDEOGRAPH-9C39 +U+9C3A(2,3);U+9C3A(2,3); # 82-45, CJK UNIFIED IDEOGRAPH-9C3A +U+9C3B(2,3);U+9C3B(2,3); # 17-23, CJK UNIFIED IDEOGRAPH-9C3B +U+9C3E(2,3);U+9C3E(2,3); # 82-68, CJK UNIFIED IDEOGRAPH-9C3E +U+9C46(2,3);U+9C46(2,3); # 82-67, CJK UNIFIED IDEOGRAPH-9C46 +U+9C47(2,3);U+9C47(2,3); # 82-65, CJK UNIFIED IDEOGRAPH-9C47 +U+9C48(2,3);U+9C48(2,3); # 35-13, CJK UNIFIED IDEOGRAPH-9C48 +U+9C52(2,3);U+9C52(2,3); # 43-80, CJK UNIFIED IDEOGRAPH-9C52 +U+9C57(2,3);U+9C57(2,3); # 46-58, CJK UNIFIED IDEOGRAPH-9C57 +U+9C5A(2,3);U+9C5A(2,3); # 82-69, CJK UNIFIED IDEOGRAPH-9C5A +U+9C60(2,3);U+9C60(2,3); # 82-70, CJK UNIFIED IDEOGRAPH-9C60 +U+9C67(2,3);U+9C67(2,3); # 82-71, CJK UNIFIED IDEOGRAPH-9C67 +U+9C76(2,3);U+9C76(2,3); # 82-72, CJK UNIFIED IDEOGRAPH-9C76 +U+9C78(2,3);U+9C78(2,3); # 82-73, CJK UNIFIED IDEOGRAPH-9C78 +U+9CE5(2,3);U+9CE5(2,3); # 36-27, CJK UNIFIED IDEOGRAPH-9CE5 +U+9CE7(2,3);U+9CE7(2,3); # 82-74, CJK UNIFIED IDEOGRAPH-9CE7 +U+9CE9(2,3);U+9CE9(2,3); # 40-23, CJK UNIFIED IDEOGRAPH-9CE9 +U+9CEB(2,3);U+9CEB(2,3); # 82-79, CJK UNIFIED IDEOGRAPH-9CEB +U+9CEC(2,3);U+9CEC(2,3); # 82-75, CJK UNIFIED IDEOGRAPH-9CEC +U+9CF0(2,3);U+9CF0(2,3); # 82-76, CJK UNIFIED IDEOGRAPH-9CF0 +U+9CF3(2,3);U+9CF3(2,3); # 43-17, CJK UNIFIED IDEOGRAPH-9CF3 +U+9CF4(2,3);U+9CF4(2,3); # 44-36, CJK UNIFIED IDEOGRAPH-9CF4 +U+9CF6(2,3);U+9CF6(2,3); # 38-48, CJK UNIFIED IDEOGRAPH-9CF6 +U+9D03(2,3);U+9D03(2,3); # 82-80, CJK UNIFIED IDEOGRAPH-9D03 +U+9D06(2,3);U+9D06(2,3); # 82-81, CJK UNIFIED IDEOGRAPH-9D06 +U+9D07(2,3);U+9D07(2,3); # 38-30, CJK UNIFIED IDEOGRAPH-9D07 +U+9D08(2,3);U+9D08(2,3); # 82-78, CJK UNIFIED IDEOGRAPH-9D08 +U+9D09(2,3);U+9D09(2,3); # 82-77, CJK UNIFIED IDEOGRAPH-9D09 +U+9D0E(2,3);U+9D0E(2,3); # 18-10, CJK UNIFIED IDEOGRAPH-9D0E +U+9D12(2,3);U+9D12(2,3); # 82-89, CJK UNIFIED IDEOGRAPH-9D12 +U+9D15(2,3);U+9D15(2,3); # 82-88, CJK UNIFIED IDEOGRAPH-9D15 +U+9D1B(2,3);U+9D1B(2,3); # 17-85, CJK UNIFIED IDEOGRAPH-9D1B +U+9D1F(2,3);U+9D1F(2,3); # 82-86, CJK UNIFIED IDEOGRAPH-9D1F +U+9D23(2,3);U+9D23(2,3); # 82-85, CJK UNIFIED IDEOGRAPH-9D23 +U+9D26(2,3);U+9D26(2,3); # 82-83, CJK UNIFIED IDEOGRAPH-9D26 +U+9D28(2,3);U+9D28(2,3); # 19-91, CJK UNIFIED IDEOGRAPH-9D28 +U+9D2A(2,3);U+9D2A(2,3); # 82-82, CJK UNIFIED IDEOGRAPH-9D2A +U+9D2B(2,3);U+9D2B(2,3); # 28-18, CJK UNIFIED IDEOGRAPH-9D2B +U+9D2C(2,3);U+9D2C(2,3); # 18-09, CJK UNIFIED IDEOGRAPH-9D2C +U+9D3B(2,3);U+9D3B(2,3); # 25-67, CJK UNIFIED IDEOGRAPH-9D3B +U+9D3E(2,3);U+9D3E(2,3); # 82-92, CJK UNIFIED IDEOGRAPH-9D3E +U+9D3F(2,3);U+9D3F(2,3); # 82-91, CJK UNIFIED IDEOGRAPH-9D3F +U+9D41(2,3);U+9D41(2,3); # 82-90, CJK UNIFIED IDEOGRAPH-9D41 +U+9D44(2,3);U+9D44(2,3); # 82-87, CJK UNIFIED IDEOGRAPH-9D44 +U+9D46(2,3);U+9D46(2,3); # 82-93, CJK UNIFIED IDEOGRAPH-9D46 +U+9D48(2,3);U+9D48(2,3); # 82-94, CJK UNIFIED IDEOGRAPH-9D48 +U+9D50(2,3);U+9D50(2,3); # 83-05, CJK UNIFIED IDEOGRAPH-9D50 +U+9D51(2,3);U+9D51(2,3); # 83-04, CJK UNIFIED IDEOGRAPH-9D51 +U+9D59(2,3);U+9D59(2,3); # 83-06, CJK UNIFIED IDEOGRAPH-9D59 +U+9D5C(2,3);U+9D5C(2,3); # 17-13, CJK UNIFIED IDEOGRAPH-9D5C +U+9D5D(2,3);U+9D5D(2,3); # 83-01, CJK UNIFIED IDEOGRAPH-9D5D +U+9D5E(2,3);U+9D5E(2,3); # 83-02, CJK UNIFIED IDEOGRAPH-9D5E +U+9D60(2,3);U+9D60(2,3); # 25-84, CJK UNIFIED IDEOGRAPH-9D60 +U+9D61(2,3);U+9D61(2,3); # 44-25, CJK UNIFIED IDEOGRAPH-9D61 +U+9D64(2,3);U+9D64(2,3); # 83-03, CJK UNIFIED IDEOGRAPH-9D64 +U+9D6C(2,3);U+9D6C(2,3); # 43-18, CJK UNIFIED IDEOGRAPH-9D6C +U+9D6F(2,3);U+9D6F(2,3); # 83-11, CJK UNIFIED IDEOGRAPH-9D6F +U+9D72(2,3);U+9D72(2,3); # 83-07, CJK UNIFIED IDEOGRAPH-9D72 +U+9D7A(2,3);U+9D7A(2,3); # 83-12, CJK UNIFIED IDEOGRAPH-9D7A +U+9D87(2,3);U+9D87(2,3); # 83-09, CJK UNIFIED IDEOGRAPH-9D87 +U+9D89(2,3);U+9D89(2,3); # 83-08, CJK UNIFIED IDEOGRAPH-9D89 +U+9D8F(2,3);U+9D8F(2,3); # 23-60, CJK UNIFIED IDEOGRAPH-9D8F +U+9D9A(2,3);U+9D9A(2,3); # 83-13, CJK UNIFIED IDEOGRAPH-9D9A +U+9DA4(2,3);U+9DA4(2,3); # 83-14, CJK UNIFIED IDEOGRAPH-9DA4 +U+9DA9(2,3);U+9DA9(2,3); # 83-15, CJK UNIFIED IDEOGRAPH-9DA9 +U+9DAB(2,3);U+9DAB(2,3); # 83-10, CJK UNIFIED IDEOGRAPH-9DAB +U+9DAF(2,3);U+9DAF(2,3); # 82-84, CJK UNIFIED IDEOGRAPH-9DAF +U+9DB2(2,3);U+9DB2(2,3); # 83-16, CJK UNIFIED IDEOGRAPH-9DB2 +U+9DB4(2,3);U+9DB4(2,3); # 36-65, CJK UNIFIED IDEOGRAPH-9DB4 +U+9DB8(2,3);U+9DB8(2,3); # 83-20, CJK UNIFIED IDEOGRAPH-9DB8 +U+9DBA(2,3);U+9DBA(2,3); # 83-21, CJK UNIFIED IDEOGRAPH-9DBA +U+9DBB(2,3);U+9DBB(2,3); # 83-19, CJK UNIFIED IDEOGRAPH-9DBB +U+9DC1(2,3);U+9DC1(2,3); # 83-18, CJK UNIFIED IDEOGRAPH-9DC1 +U+9DC2(2,3);U+9DC2(2,3); # 83-24, CJK UNIFIED IDEOGRAPH-9DC2 +U+9DC4(2,3);U+9DC4(2,3); # 83-17, CJK UNIFIED IDEOGRAPH-9DC4 +U+9DC6(2,3);U+9DC6(2,3); # 83-22, CJK UNIFIED IDEOGRAPH-9DC6 +U+9DCF(2,3);U+9DCF(2,3); # 83-23, CJK UNIFIED IDEOGRAPH-9DCF +U+9DD3(2,3);U+9DD3(2,3); # 83-26, CJK UNIFIED IDEOGRAPH-9DD3 +U+9DD9(2,3);U+9DD9(2,3); # 83-25, CJK UNIFIED IDEOGRAPH-9DD9 +U+9DE6(2,3);U+9DE6(2,3); # 83-28, CJK UNIFIED IDEOGRAPH-9DE6 +U+9DED(2,3);U+9DED(2,3); # 83-29, CJK UNIFIED IDEOGRAPH-9DED +U+9DEF(2,3);U+9DEF(2,3); # 83-30, CJK UNIFIED IDEOGRAPH-9DEF +U+9DF2(2,3);U+9DF2(2,3); # 47-41, CJK UNIFIED IDEOGRAPH-9DF2 +U+9DF8(2,3);U+9DF8(2,3); # 83-27, CJK UNIFIED IDEOGRAPH-9DF8 +U+9DF9(2,3);U+9DF9(2,3); # 34-75, CJK UNIFIED IDEOGRAPH-9DF9 +U+9DFA(2,3);U+9DFA(2,3); # 26-77, CJK UNIFIED IDEOGRAPH-9DFA +U+9DFD(2,3);U+9DFD(2,3); # 83-31, CJK UNIFIED IDEOGRAPH-9DFD +U+9E1A(2,3);U+9E1A(2,3); # 83-32, CJK UNIFIED IDEOGRAPH-9E1A +U+9E1B(2,3);U+9E1B(2,3); # 83-33, CJK UNIFIED IDEOGRAPH-9E1B +U+9E1E(2,3);U+9E1E(2,3); # 83-34, CJK UNIFIED IDEOGRAPH-9E1E +U+9E75(2,3);U+9E75(2,3); # 83-35, CJK UNIFIED IDEOGRAPH-9E75 +U+9E78(2,3);U+9E78(2,3); # 24-20, CJK UNIFIED IDEOGRAPH-9E78 +U+9E79(2,3);U+9E79(2,3); # 83-36, CJK UNIFIED IDEOGRAPH-9E79 +U+9E7D(2,3);U+9E7D(2,3); # 83-37, CJK UNIFIED IDEOGRAPH-9E7D +U+9E7F(2,3);U+9E7F(2,3); # 28-15, CJK UNIFIED IDEOGRAPH-9E7F +U+9E81(2,3);U+9E81(2,3); # 83-38, CJK UNIFIED IDEOGRAPH-9E81 +U+9E88(2,3);U+9E88(2,3); # 83-39, CJK UNIFIED IDEOGRAPH-9E88 +U+9E8B(2,3);U+9E8B(2,3); # 83-40, CJK UNIFIED IDEOGRAPH-9E8B +U+9E8C(2,3);U+9E8C(2,3); # 83-41, CJK UNIFIED IDEOGRAPH-9E8C +U+9E91(2,3);U+9E91(2,3); # 83-44, CJK UNIFIED IDEOGRAPH-9E91 +U+9E92(2,3);U+9E92(2,3); # 83-42, CJK UNIFIED IDEOGRAPH-9E92 +U+9E93(2,3);U+9E93(2,3); # 47-28, CJK UNIFIED IDEOGRAPH-9E93 +U+9E95(2,3);U+9E95(2,3); # 83-43, CJK UNIFIED IDEOGRAPH-9E95 +U+9E97(2,3);U+9E97(2,3); # 46-79, CJK UNIFIED IDEOGRAPH-9E97 +U+9E9D(2,3);U+9E9D(2,3); # 83-45, CJK UNIFIED IDEOGRAPH-9E9D +U+9E9F(2,3);U+9E9F(2,3); # 46-59, CJK UNIFIED IDEOGRAPH-9E9F +U+9EA5(2,3);U+9EA5(2,3); # 83-46, CJK UNIFIED IDEOGRAPH-9EA5 +U+9EA6(2,3);U+9EA6(2,3); # 39-94, CJK UNIFIED IDEOGRAPH-9EA6 +U+9EA9(2,3);U+9EA9(2,3); # 83-47, CJK UNIFIED IDEOGRAPH-9EA9 +U+9EAA(2,3);U+9EAA(2,3); # 83-49, CJK UNIFIED IDEOGRAPH-9EAA +U+9EAD(2,3);U+9EAD(2,3); # 83-50, CJK UNIFIED IDEOGRAPH-9EAD +U+9EB8(2,3);U+9EB8(2,3); # 83-48, CJK UNIFIED IDEOGRAPH-9EB8 +U+9EB9(2,3);U+9EB9(2,3); # 25-77, CJK UNIFIED IDEOGRAPH-9EB9 +U+9EBA(2,3);U+9EBA(2,3); # 44-45, CJK UNIFIED IDEOGRAPH-9EBA +U+9EBB(2,3);U+9EBB(2,3); # 43-67, CJK UNIFIED IDEOGRAPH-9EBB +U+9EBC(2,3);U+9EBC(2,3); # 54-87, CJK UNIFIED IDEOGRAPH-9EBC +U+9EBE(2,3);U+9EBE(2,3); # 61-64, CJK UNIFIED IDEOGRAPH-9EBE +U+9EBF(2,3);U+9EBF(2,3); # 43-91, CJK UNIFIED IDEOGRAPH-9EBF +U+9EC4(2,3);U+9EC4(2,3); # 18-11, CJK UNIFIED IDEOGRAPH-9EC4 +U+9ECC(2,3);U+9ECC(2,3); # 83-52, CJK UNIFIED IDEOGRAPH-9ECC +U+9ECD(2,3);U+9ECD(2,3); # 21-48, CJK UNIFIED IDEOGRAPH-9ECD +U+9ECE(2,3);U+9ECE(2,3); # 83-53, CJK UNIFIED IDEOGRAPH-9ECE +U+9ECF(2,3);U+9ECF(2,3); # 83-54, CJK UNIFIED IDEOGRAPH-9ECF +U+9ED0(2,3);U+9ED0(2,3); # 83-55, CJK UNIFIED IDEOGRAPH-9ED0 +U+9ED2(2,3);U+9ED2(2,3); # 25-85, CJK UNIFIED IDEOGRAPH-9ED2 +U+9ED4(2,3);U+9ED4(2,3); # 83-56, CJK UNIFIED IDEOGRAPH-9ED4 +U+9ED8(2,3);U+9ED8(2,3); # 64-52, CJK UNIFIED IDEOGRAPH-9ED8 +U+9ED9(2,3);U+9ED9(2,3); # 44-59, CJK UNIFIED IDEOGRAPH-9ED9 +U+9EDB(2,3);U+9EDB(2,3); # 34-67, CJK UNIFIED IDEOGRAPH-9EDB +U+9EDC(2,3);U+9EDC(2,3); # 83-57, CJK UNIFIED IDEOGRAPH-9EDC +U+9EDD(2,3);U+9EDD(2,3); # 83-59, CJK UNIFIED IDEOGRAPH-9EDD +U+9EDE(2,3);U+9EDE(2,3); # 83-58, CJK UNIFIED IDEOGRAPH-9EDE +U+9EE0(2,3);U+9EE0(2,3); # 83-60, CJK UNIFIED IDEOGRAPH-9EE0 +U+9EE5(2,3);U+9EE5(2,3); # 83-61, CJK UNIFIED IDEOGRAPH-9EE5 +U+9EE8(2,3);U+9EE8(2,3); # 83-62, CJK UNIFIED IDEOGRAPH-9EE8 +U+9EEF(2,3);U+9EEF(2,3); # 83-63, CJK UNIFIED IDEOGRAPH-9EEF +U+9EF4(2,3);U+9EF4(2,3); # 83-64, CJK UNIFIED IDEOGRAPH-9EF4 +U+9EF6(2,3);U+9EF6(2,3); # 83-65, CJK UNIFIED IDEOGRAPH-9EF6 +U+9EF7(2,3);U+9EF7(2,3); # 83-66, CJK UNIFIED IDEOGRAPH-9EF7 +U+9EF9(2,3);U+9EF9(2,3); # 83-67, CJK UNIFIED IDEOGRAPH-9EF9 +U+9EFB(2,3);U+9EFB(2,3); # 83-68, CJK UNIFIED IDEOGRAPH-9EFB +U+9EFC(2,3);U+9EFC(2,3); # 83-69, CJK UNIFIED IDEOGRAPH-9EFC +U+9EFD(2,3);U+9EFD(2,3); # 83-70, CJK UNIFIED IDEOGRAPH-9EFD +U+9F07(2,3);U+9F07(2,3); # 83-71, CJK UNIFIED IDEOGRAPH-9F07 +U+9F08(2,3);U+9F08(2,3); # 83-72, CJK UNIFIED IDEOGRAPH-9F08 +U+9F0E(2,3);U+9F0E(2,3); # 37-04, CJK UNIFIED IDEOGRAPH-9F0E +U+9F13(2,3);U+9F13(2,3); # 24-61, CJK UNIFIED IDEOGRAPH-9F13 +U+9F15(2,3);U+9F15(2,3); # 83-74, CJK UNIFIED IDEOGRAPH-9F15 +U+9F20(2,3);U+9F20(2,3); # 33-45, CJK UNIFIED IDEOGRAPH-9F20 +U+9F21(2,3);U+9F21(2,3); # 83-75, CJK UNIFIED IDEOGRAPH-9F21 +U+9F2C(2,3);U+9F2C(2,3); # 83-76, CJK UNIFIED IDEOGRAPH-9F2C +U+9F3B(2,3);U+9F3B(2,3); # 41-01, CJK UNIFIED IDEOGRAPH-9F3B +U+9F3E(2,3);U+9F3E(2,3); # 83-77, CJK UNIFIED IDEOGRAPH-9F3E +U+9F4A(2,3);U+9F4A(2,3); # 83-78, CJK UNIFIED IDEOGRAPH-9F4A +U+9F4B(2,3);U+9F4B(2,3); # 67-23, CJK UNIFIED IDEOGRAPH-9F4B +U+9F4E(2,3);U+9F4E(2,3); # 76-58, CJK UNIFIED IDEOGRAPH-9F4E +U+9F4F(2,3);U+9F4F(2,3); # 80-77, CJK UNIFIED IDEOGRAPH-9F4F +U+9F52(2,3);U+9F52(2,3); # 83-79, CJK UNIFIED IDEOGRAPH-9F52 +U+9F54(2,3);U+9F54(2,3); # 83-80, CJK UNIFIED IDEOGRAPH-9F54 +U+9F5F(2,3);U+9F5F(2,3); # 83-82, CJK UNIFIED IDEOGRAPH-9F5F +U+9F60(2,3);U+9F60(2,3); # 83-83, CJK UNIFIED IDEOGRAPH-9F60 +U+9F61(2,3);U+9F61(2,3); # 83-84, CJK UNIFIED IDEOGRAPH-9F61 +U+9F62(2,3);U+9F62(2,3); # 46-80, CJK UNIFIED IDEOGRAPH-9F62 +U+9F63(2,3);U+9F63(2,3); # 83-81, CJK UNIFIED IDEOGRAPH-9F63 +U+9F66(2,3);U+9F66(2,3); # 83-85, CJK UNIFIED IDEOGRAPH-9F66 +U+9F67(2,3);U+9F67(2,3); # 83-86, CJK UNIFIED IDEOGRAPH-9F67 +U+9F6A(2,3);U+9F6A(2,3); # 83-88, CJK UNIFIED IDEOGRAPH-9F6A +U+9F6C(2,3);U+9F6C(2,3); # 83-87, CJK UNIFIED IDEOGRAPH-9F6C +U+9F72(2,3);U+9F72(2,3); # 83-90, CJK UNIFIED IDEOGRAPH-9F72 +U+9F76(2,3);U+9F76(2,3); # 83-91, CJK UNIFIED IDEOGRAPH-9F76 +U+9F77(2,3);U+9F77(2,3); # 83-89, CJK UNIFIED IDEOGRAPH-9F77 +U+9F8D(2,3);U+9F8D(2,3); # 46-22, CJK UNIFIED IDEOGRAPH-9F8D +U+9F95(2,3);U+9F95(2,3); # 83-92, CJK UNIFIED IDEOGRAPH-9F95 +U+9F9C(2,3);U+9F9C(2,3); # 83-93, CJK UNIFIED IDEOGRAPH-9F9C +U+9F9D(2,3);U+9F9D(2,3); # 67-52, CJK UNIFIED IDEOGRAPH-9F9D +U+9FA0(2,3);U+9FA0(2,3); # 83-94, CJK UNIFIED IDEOGRAPH-9FA0 diff --git a/java/com/google/domain/registry/idn/Kannada-IDN.txt b/java/com/google/domain/registry/idn/Kannada-IDN.txt new file mode 100644 index 000000000..3f9b538ad --- /dev/null +++ b/java/com/google/domain/registry/idn/Kannada-IDN.txt @@ -0,0 +1,108 @@ +# Registry: Charleston Road Registry Inc. +# Script: Kannada +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Kannada script. +# +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0C82 # KANNADA SIGN ANUSVARA +U+0C83 # KANNADA SIGN VISARGA +U+0C85 # KANNADA LETTER A +U+0C86 # KANNADA LETTER AA +U+0C87 # KANNADA LETTER I +U+0C88 # KANNADA LETTER II +U+0C89 # KANNADA LETTER U +U+0C8A # KANNADA LETTER UU +U+0C8B # KANNADA LETTER VOCALIC R +U+0C8C # KANNADA LETTER VOCALIC L +U+0C8E # KANNADA LETTER E +U+0C8F # KANNADA LETTER EE +U+0C90 # KANNADA LETTER AI +U+0C92 # KANNADA LETTER O +U+0C93 # KANNADA LETTER OO +U+0C94 # KANNADA LETTER AU +U+0C95 # KANNADA LETTER KA +U+0C96 # KANNADA LETTER KHA +U+0C97 # KANNADA LETTER GA +U+0C98 # KANNADA LETTER GHA +U+0C99 # KANNADA LETTER NGA +U+0C9A # KANNADA LETTER CA +U+0C9B # KANNADA LETTER CHA +U+0C9C # KANNADA LETTER JA +U+0C9D # KANNADA LETTER JHA +U+0C9E # KANNADA LETTER NYA +U+0C9F # KANNADA LETTER TTA +U+0CA0 # KANNADA LETTER TTHA +U+0CA1 # KANNADA LETTER DDA +U+0CA2 # KANNADA LETTER DDHA +U+0CA3 # KANNADA LETTER NNA +U+0CA4 # KANNADA LETTER TA +U+0CA5 # KANNADA LETTER THA +U+0CA6 # KANNADA LETTER DA +U+0CA7 # KANNADA LETTER DHA +U+0CA8 # KANNADA LETTER NA +U+0CAA # KANNADA LETTER PA +U+0CAB # KANNADA LETTER PHA +U+0CAC # KANNADA LETTER BA +U+0CAD # KANNADA LETTER BHA +U+0CAE # KANNADA LETTER MA +U+0CAF # KANNADA LETTER YA +U+0CB0 # KANNADA LETTER RA +U+0CB1 # KANNADA LETTER RRA +U+0CB2 # KANNADA LETTER LA +U+0CB3 # KANNADA LETTER LLA +U+0CB5 # KANNADA LETTER VA +U+0CB6 # KANNADA LETTER SHA +U+0CB7 # KANNADA LETTER SSA +U+0CB8 # KANNADA LETTER SA +U+0CB9 # KANNADA LETTER HA +U+0CBC # KANNADA SIGN NUKTA +U+0CBD # KANNADA SIGN AVAGRAHA +U+0CBE # KANNADA VOWEL SIGN AA +U+0CBF # KANNADA VOWEL SIGN I +U+0CC0 # KANNADA VOWEL SIGN II +U+0CC1 # KANNADA VOWEL SIGN U +U+0CC2 # KANNADA VOWEL SIGN UU +U+0CC3 # KANNADA VOWEL SIGN VOCALIC R +U+0CC4 # KANNADA VOWEL SIGN VOCALIC RR +U+0CC6 # KANNADA VOWEL SIGN E +U+0CC7 # KANNADA VOWEL SIGN EE +U+0CC8 # KANNADA VOWEL SIGN AI +U+0CCA # KANNADA VOWEL SIGN O +U+0CCB # KANNADA VOWEL SIGN OO +U+0CCC # KANNADA VOWEL SIGN AU +U+0CCD # KANNADA SIGN VIRAMA +U+0CD5 # KANNADA LENGTH MARK +U+0CD6 # KANNADA AI LENGTH MARK +U+0CDE # KANNADA LETTER FA +U+0CE0 # KANNADA LETTER VOCALIC RR +U+0CE1 # KANNADA LETTER VOCALIC LL +U+0CE2 # KANNADA VOWEL SIGN VOCALIC L +U+0CE3 # KANNADA VOWEL SIGN VOCALIC LL +U+0CE6 # KANNADA DIGIT ZERO +U+0CE7 # KANNADA DIGIT ONE +U+0CE8 # KANNADA DIGIT TWO +U+0CE9 # KANNADA DIGIT THREE +U+0CEA # KANNADA DIGIT FOUR +U+0CEB # KANNADA DIGIT FIVE +U+0CEC # KANNADA DIGIT SIX +U+0CED # KANNADA DIGIT SEVEN +U+0CEE # KANNADA DIGIT EIGHT +U+0CEF # KANNADA DIGIT NINE diff --git a/java/com/google/domain/registry/idn/Khmer-IDN.txt b/java/com/google/domain/registry/idn/Khmer-IDN.txt new file mode 100644 index 000000000..68d64271e --- /dev/null +++ b/java/com/google/domain/registry/idn/Khmer-IDN.txt @@ -0,0 +1,120 @@ +# Registry: Charleston Road Registry Inc. +# Script: Khmer +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Khmer script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+1780 # KHMER LETTER KA +U+1781 # KHMER LETTER KHA +U+1782 # KHMER LETTER KO +U+1783 # KHMER LETTER KHO +U+1784 # KHMER LETTER NGO +U+1785 # KHMER LETTER CA +U+1786 # KHMER LETTER CHA +U+1787 # KHMER LETTER CO +U+1788 # KHMER LETTER CHO +U+1789 # KHMER LETTER NYO +U+178A # KHMER LETTER DA +U+178B # KHMER LETTER TTHA +U+178C # KHMER LETTER DO +U+178D # KHMER LETTER TTHO +U+178E # KHMER LETTER NNO +U+178F # KHMER LETTER TA +U+1790 # KHMER LETTER THA +U+1791 # KHMER LETTER TO +U+1792 # KHMER LETTER THO +U+1793 # KHMER LETTER NO +U+1794 # KHMER LETTER BA +U+1795 # KHMER LETTER PHA +U+1796 # KHMER LETTER PO +U+1797 # KHMER LETTER PHO +U+1798 # KHMER LETTER MO +U+1799 # KHMER LETTER YO +U+179A # KHMER LETTER RO +U+179B # KHMER LETTER LO +U+179C # KHMER LETTER VO +U+179D # KHMER LETTER SHA +U+179E # KHMER LETTER SSO +U+179F # KHMER LETTER SA +U+17A0 # KHMER LETTER HA +U+17A1 # KHMER LETTER LA +U+17A2 # KHMER LETTER QA +U+17A3 # KHMER INDEPENDENT VOWEL QAQ +U+17A4 # KHMER INDEPENDENT VOWEL QAA +U+17A5 # KHMER INDEPENDENT VOWEL QI +U+17A6 # KHMER INDEPENDENT VOWEL QII +U+17A7 # KHMER INDEPENDENT VOWEL QU +U+17A8 # KHMER INDEPENDENT VOWEL QUK +U+17A9 # KHMER INDEPENDENT VOWEL QUU +U+17AA # KHMER INDEPENDENT VOWEL QUUV +U+17AB # KHMER INDEPENDENT VOWEL RY +U+17AC # KHMER INDEPENDENT VOWEL RYY +U+17AD # KHMER INDEPENDENT VOWEL LY +U+17AE # KHMER INDEPENDENT VOWEL LYY +U+17AF # KHMER INDEPENDENT VOWEL QE +U+17B0 # KHMER INDEPENDENT VOWEL QAI +U+17B1 # KHMER INDEPENDENT VOWEL QOO TYPE ONE +U+17B2 # KHMER INDEPENDENT VOWEL QOO TYPE TWO +U+17B3 # KHMER INDEPENDENT VOWEL QAU +U+17B6 # KHMER VOWEL SIGN AA +U+17B7 # KHMER VOWEL SIGN I +U+17B8 # KHMER VOWEL SIGN II +U+17B9 # KHMER VOWEL SIGN Y +U+17BA # KHMER VOWEL SIGN YY +U+17BB # KHMER VOWEL SIGN U +U+17BC # KHMER VOWEL SIGN UU +U+17BD # KHMER VOWEL SIGN UA +U+17BE # KHMER VOWEL SIGN OE +U+17BF # KHMER VOWEL SIGN YA +U+17C0 # KHMER VOWEL SIGN IE +U+17C1 # KHMER VOWEL SIGN E +U+17C2 # KHMER VOWEL SIGN AE +U+17C3 # KHMER VOWEL SIGN AI +U+17C4 # KHMER VOWEL SIGN OO +U+17C5 # KHMER VOWEL SIGN AU +U+17C6 # KHMER SIGN NIKAHIT +U+17C7 # KHMER SIGN REAHMUK +U+17C8 # KHMER SIGN YUUKALEAPINTU +U+17C9 # KHMER SIGN MUUSIKATOAN +U+17CA # KHMER SIGN TRIISAP +U+17CB # KHMER SIGN BANTOC +U+17CC # KHMER SIGN ROBAT +U+17CD # KHMER SIGN TOANDAKHIAT +U+17CE # KHMER SIGN KAKABAT +U+17CF # KHMER SIGN AHSDA +U+17D0 # KHMER SIGN SAMYOK SANNYA +U+17D1 # KHMER SIGN VIRIAM +U+17D2 # KHMER SIGN COENG +U+17D3 # KHMER SIGN BATHAMASAT +U+17D7 # KHMER SIGN LEK TOO +U+17DC # KHMER SIGN AVAKRAHASANYA +U+17DD # KHMER SIGN ATTHACAN +U+17E0 # KHMER DIGIT ZERO +U+17E1 # KHMER DIGIT ONE +U+17E2 # KHMER DIGIT TWO +U+17E3 # KHMER DIGIT THREE +U+17E4 # KHMER DIGIT FOUR +U+17E5 # KHMER DIGIT FIVE +U+17E6 # KHMER DIGIT SIX +U+17E7 # KHMER DIGIT SEVEN +U+17E8 # KHMER DIGIT EIGHT +U+17E9 # KHMER DIGIT NINE + diff --git a/java/com/google/domain/registry/idn/Korean-IDN.txt b/java/com/google/domain/registry/idn/Korean-IDN.txt new file mode 100644 index 000000000..1daf8829d --- /dev/null +++ b/java/com/google/domain/registry/idn/Korean-IDN.txt @@ -0,0 +1,11219 @@ +# Registry: Charleston Road Registry Inc. +# Script: Korean +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Korean script. + +U+002D(1);; # HYPHEN-MINUS +U+0030(1);; # DIGIT ZERO +U+0031(1);; # DIGIT ONE +U+0032(1);; # DIGIT TWO +U+0033(1);; # DIGIT THREE +U+0034(1);; # DIGIT FOUR +U+0035(1);; # DIGIT FIVE +U+0036(1);; # DIGIT SIX +U+0037(1);; # DIGIT SEVEN +U+0038(1);; # DIGIT EIGHT +U+0039(1);; # DIGIT NINE +U+0061(1);; # LATIN SMALL LETTER A +U+0062(1);; # LATIN SMALL LETTER B +U+0063(1);; # LATIN SMALL LETTER C +U+0064(1);; # LATIN SMALL LETTER D +U+0065(1);; # LATIN SMALL LETTER E +U+0066(1);; # LATIN SMALL LETTER F +U+0067(1);; # LATIN SMALL LETTER G +U+0068(1);; # LATIN SMALL LETTER H +U+0069(1);; # LATIN SMALL LETTER I +U+006A(1);; # LATIN SMALL LETTER J +U+006B(1);; # LATIN SMALL LETTER K +U+006C(1);; # LATIN SMALL LETTER L +U+006D(1);; # LATIN SMALL LETTER M +U+006E(1);; # LATIN SMALL LETTER N +U+006F(1);; # LATIN SMALL LETTER O +U+0070(1);; # LATIN SMALL LETTER P +U+0071(1);; # LATIN SMALL LETTER Q +U+0072(1);; # LATIN SMALL LETTER R +U+0073(1);; # LATIN SMALL LETTER S +U+0074(1);; # LATIN SMALL LETTER T +U+0075(1);; # LATIN SMALL LETTER U +U+0076(1);; # LATIN SMALL LETTER V +U+0077(1);; # LATIN SMALL LETTER W +U+0078(1);; # LATIN SMALL LETTER X +U+0079(1);; # LATIN SMALL LETTER Y +U+007A(1);; # LATIN SMALL LETTER Z +U+AC00(2);; # HANGUL SYLLABLE KIYEOK A * +U+AC01(2);; # HANGUL SYLLABLE KIYEOK A KIYEOK * +U+AC02(2);; # HANGUL SYLLABLE KIYEOK A SSANGKIYEOK +U+AC03(2);; # HANGUL SYLLABLE KIYEOK A KIYEOKSIOS +U+AC04(2);; # HANGUL SYLLABLE KIYEOK A NIEUN * +U+AC05(2);; # HANGUL SYLLABLE KIYEOK A NIEUNCIEUC +U+AC06(2);; # HANGUL SYLLABLE KIYEOK A NIEUNHIEUH +U+AC07(2);; # HANGUL SYLLABLE KIYEOK A TIKEUT * +U+AC08(2);; # HANGUL SYLLABLE KIYEOK A RIEUL * +U+AC09(2);; # HANGUL SYLLABLE KIYEOK A RIEULKIYEOK * +U+AC0A(2);; # HANGUL SYLLABLE KIYEOK A RIEULMIEUM * +U+AC0B(2);; # HANGUL SYLLABLE KIYEOK A RIEULPIEUP +U+AC0C(2);; # HANGUL SYLLABLE KIYEOK A RIEULSIOS +U+AC0D(2);; # HANGUL SYLLABLE KIYEOK A RIEULTHIEUTH +U+AC0E(2);; # HANGUL SYLLABLE KIYEOK A RIEULPHIEUPH +U+AC0F(2);; # HANGUL SYLLABLE KIYEOK A RIEULHIEUH +U+AC10(2);; # HANGUL SYLLABLE KIYEOK A MIEUM * +U+AC11(2);; # HANGUL SYLLABLE KIYEOK A PIEUP * +U+AC12(2);; # HANGUL SYLLABLE KIYEOK A PIEUPSIOS * +U+AC13(2);; # HANGUL SYLLABLE KIYEOK A SIOS * +U+AC14(2);; # HANGUL SYLLABLE KIYEOK A SSANGSIOS * +U+AC15(2);; # HANGUL SYLLABLE KIYEOK A IEUNG * +U+AC16(2);; # HANGUL SYLLABLE KIYEOK A CIEUC * +U+AC17(2);; # HANGUL SYLLABLE KIYEOK A CHIEUCH * +U+AC18(2);; # HANGUL SYLLABLE KIYEOK A KHIEUKH +U+AC19(2);; # HANGUL SYLLABLE KIYEOK A THIEUTH * +U+AC1A(2);; # HANGUL SYLLABLE KIYEOK A PHIEUPH * +U+AC1B(2);; # HANGUL SYLLABLE KIYEOK A HIEUH * +U+AC1C(2);; # HANGUL SYLLABLE KIYEOK AE * +U+AC1D(2);; # HANGUL SYLLABLE KIYEOK AE KIYEOK * +U+AC1E(2);; # HANGUL SYLLABLE KIYEOK AE SSANGKIYEOK +U+AC1F(2);; # HANGUL SYLLABLE KIYEOK AE KIYEOKSIOS +U+AC20(2);; # HANGUL SYLLABLE KIYEOK AE NIEUN * +U+AC21(2);; # HANGUL SYLLABLE KIYEOK AE NIEUNCIEUC +U+AC22(2);; # HANGUL SYLLABLE KIYEOK AE NIEUNHIEUH +U+AC23(2);; # HANGUL SYLLABLE KIYEOK AE TIKEUT +U+AC24(2);; # HANGUL SYLLABLE KIYEOK AE RIEUL * +U+AC25(2);; # HANGUL SYLLABLE KIYEOK AE RIEULKIYEOK +U+AC26(2);; # HANGUL SYLLABLE KIYEOK AE RIEULMIEUM +U+AC27(2);; # HANGUL SYLLABLE KIYEOK AE RIEULPIEUP +U+AC28(2);; # HANGUL SYLLABLE KIYEOK AE RIEULSIOS +U+AC29(2);; # HANGUL SYLLABLE KIYEOK AE RIEULTHIEUTH +U+AC2A(2);; # HANGUL SYLLABLE KIYEOK AE RIEULPHIEUPH +U+AC2B(2);; # HANGUL SYLLABLE KIYEOK AE RIEULHIEUH +U+AC2C(2);; # HANGUL SYLLABLE KIYEOK AE MIEUM * +U+AC2D(2);; # HANGUL SYLLABLE KIYEOK AE PIEUP * +U+AC2E(2);; # HANGUL SYLLABLE KIYEOK AE PIEUPSIOS +U+AC2F(2);; # HANGUL SYLLABLE KIYEOK AE SIOS * +U+AC30(2);; # HANGUL SYLLABLE KIYEOK AE SSANGSIOS * +U+AC31(2);; # HANGUL SYLLABLE KIYEOK AE IEUNG * +U+AC32(2);; # HANGUL SYLLABLE KIYEOK AE CIEUC +U+AC33(2);; # HANGUL SYLLABLE KIYEOK AE CHIEUCH +U+AC34(2);; # HANGUL SYLLABLE KIYEOK AE KHIEUKH +U+AC35(2);; # HANGUL SYLLABLE KIYEOK AE THIEUTH +U+AC36(2);; # HANGUL SYLLABLE KIYEOK AE PHIEUPH +U+AC37(2);; # HANGUL SYLLABLE KIYEOK AE HIEUH +U+AC38(2);; # HANGUL SYLLABLE KIYEOK YA * +U+AC39(2);; # HANGUL SYLLABLE KIYEOK YA KIYEOK * +U+AC3A(2);; # HANGUL SYLLABLE KIYEOK YA SSANGKIYEOK +U+AC3B(2);; # HANGUL SYLLABLE KIYEOK YA KIYEOKSIOS +U+AC3C(2);; # HANGUL SYLLABLE KIYEOK YA NIEUN * +U+AC3D(2);; # HANGUL SYLLABLE KIYEOK YA NIEUNCIEUC +U+AC3E(2);; # HANGUL SYLLABLE KIYEOK YA NIEUNHIEUH +U+AC3F(2);; # HANGUL SYLLABLE KIYEOK YA TIKEUT +U+AC40(2);; # HANGUL SYLLABLE KIYEOK YA RIEUL * +U+AC41(2);; # HANGUL SYLLABLE KIYEOK YA RIEULKIYEOK +U+AC42(2);; # HANGUL SYLLABLE KIYEOK YA RIEULMIEUM +U+AC43(2);; # HANGUL SYLLABLE KIYEOK YA RIEULPIEUP +U+AC44(2);; # HANGUL SYLLABLE KIYEOK YA RIEULSIOS +U+AC45(2);; # HANGUL SYLLABLE KIYEOK YA RIEULTHIEUTH +U+AC46(2);; # HANGUL SYLLABLE KIYEOK YA RIEULPHIEUPH +U+AC47(2);; # HANGUL SYLLABLE KIYEOK YA RIEULHIEUH +U+AC48(2);; # HANGUL SYLLABLE KIYEOK YA MIEUM +U+AC49(2);; # HANGUL SYLLABLE KIYEOK YA PIEUP +U+AC4A(2);; # HANGUL SYLLABLE KIYEOK YA PIEUPSIOS +U+AC4B(2);; # HANGUL SYLLABLE KIYEOK YA SIOS * +U+AC4C(2);; # HANGUL SYLLABLE KIYEOK YA SSANGSIOS +U+AC4D(2);; # HANGUL SYLLABLE KIYEOK YA IEUNG * +U+AC4E(2);; # HANGUL SYLLABLE KIYEOK YA CIEUC +U+AC4F(2);; # HANGUL SYLLABLE KIYEOK YA CHIEUCH +U+AC50(2);; # HANGUL SYLLABLE KIYEOK YA KHIEUKH +U+AC51(2);; # HANGUL SYLLABLE KIYEOK YA THIEUTH +U+AC52(2);; # HANGUL SYLLABLE KIYEOK YA PHIEUPH +U+AC53(2);; # HANGUL SYLLABLE KIYEOK YA HIEUH +U+AC54(2);; # HANGUL SYLLABLE KIYEOK YAE * +U+AC55(2);; # HANGUL SYLLABLE KIYEOK YAE KIYEOK +U+AC56(2);; # HANGUL SYLLABLE KIYEOK YAE SSANGKIYEOK +U+AC57(2);; # HANGUL SYLLABLE KIYEOK YAE KIYEOKSIOS +U+AC58(2);; # HANGUL SYLLABLE KIYEOK YAE NIEUN * +U+AC59(2);; # HANGUL SYLLABLE KIYEOK YAE NIEUNCIEUC +U+AC5A(2);; # HANGUL SYLLABLE KIYEOK YAE NIEUNHIEUH +U+AC5B(2);; # HANGUL SYLLABLE KIYEOK YAE TIKEUT +U+AC5C(2);; # HANGUL SYLLABLE KIYEOK YAE RIEUL * +U+AC5D(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULKIYEOK +U+AC5E(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULMIEUM +U+AC5F(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULPIEUP +U+AC60(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULSIOS +U+AC61(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULTHIEUTH +U+AC62(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULPHIEUPH +U+AC63(2);; # HANGUL SYLLABLE KIYEOK YAE RIEULHIEUH +U+AC64(2);; # HANGUL SYLLABLE KIYEOK YAE MIEUM +U+AC65(2);; # HANGUL SYLLABLE KIYEOK YAE PIEUP +U+AC66(2);; # HANGUL SYLLABLE KIYEOK YAE PIEUPSIOS +U+AC67(2);; # HANGUL SYLLABLE KIYEOK YAE SIOS +U+AC68(2);; # HANGUL SYLLABLE KIYEOK YAE SSANGSIOS +U+AC69(2);; # HANGUL SYLLABLE KIYEOK YAE IEUNG +U+AC6A(2);; # HANGUL SYLLABLE KIYEOK YAE CIEUC +U+AC6B(2);; # HANGUL SYLLABLE KIYEOK YAE CHIEUCH +U+AC6C(2);; # HANGUL SYLLABLE KIYEOK YAE KHIEUKH +U+AC6D(2);; # HANGUL SYLLABLE KIYEOK YAE THIEUTH +U+AC6E(2);; # HANGUL SYLLABLE KIYEOK YAE PHIEUPH +U+AC6F(2);; # HANGUL SYLLABLE KIYEOK YAE HIEUH +U+AC70(2);; # HANGUL SYLLABLE KIYEOK EO * +U+AC71(2);; # HANGUL SYLLABLE KIYEOK EO KIYEOK * +U+AC72(2);; # HANGUL SYLLABLE KIYEOK EO SSANGKIYEOK +U+AC73(2);; # HANGUL SYLLABLE KIYEOK EO KIYEOKSIOS +U+AC74(2);; # HANGUL SYLLABLE KIYEOK EO NIEUN * +U+AC75(2);; # HANGUL SYLLABLE KIYEOK EO NIEUNCIEUC +U+AC76(2);; # HANGUL SYLLABLE KIYEOK EO NIEUNHIEUH +U+AC77(2);; # HANGUL SYLLABLE KIYEOK EO TIKEUT * +U+AC78(2);; # HANGUL SYLLABLE KIYEOK EO RIEUL * +U+AC79(2);; # HANGUL SYLLABLE KIYEOK EO RIEULKIYEOK +U+AC7A(2);; # HANGUL SYLLABLE KIYEOK EO RIEULMIEUM * +U+AC7B(2);; # HANGUL SYLLABLE KIYEOK EO RIEULPIEUP +U+AC7C(2);; # HANGUL SYLLABLE KIYEOK EO RIEULSIOS +U+AC7D(2);; # HANGUL SYLLABLE KIYEOK EO RIEULTHIEUTH +U+AC7E(2);; # HANGUL SYLLABLE KIYEOK EO RIEULPHIEUPH +U+AC7F(2);; # HANGUL SYLLABLE KIYEOK EO RIEULHIEUH +U+AC80(2);; # HANGUL SYLLABLE KIYEOK EO MIEUM * +U+AC81(2);; # HANGUL SYLLABLE KIYEOK EO PIEUP * +U+AC82(2);; # HANGUL SYLLABLE KIYEOK EO PIEUPSIOS +U+AC83(2);; # HANGUL SYLLABLE KIYEOK EO SIOS * +U+AC84(2);; # HANGUL SYLLABLE KIYEOK EO SSANGSIOS * +U+AC85(2);; # HANGUL SYLLABLE KIYEOK EO IEUNG * +U+AC86(2);; # HANGUL SYLLABLE KIYEOK EO CIEUC * +U+AC87(2);; # HANGUL SYLLABLE KIYEOK EO CHIEUCH +U+AC88(2);; # HANGUL SYLLABLE KIYEOK EO KHIEUKH +U+AC89(2);; # HANGUL SYLLABLE KIYEOK EO THIEUTH * +U+AC8A(2);; # HANGUL SYLLABLE KIYEOK EO PHIEUPH * +U+AC8B(2);; # HANGUL SYLLABLE KIYEOK EO HIEUH * +U+AC8C(2);; # HANGUL SYLLABLE KIYEOK E * +U+AC8D(2);; # HANGUL SYLLABLE KIYEOK E KIYEOK +U+AC8E(2);; # HANGUL SYLLABLE KIYEOK E SSANGKIYEOK +U+AC8F(2);; # HANGUL SYLLABLE KIYEOK E KIYEOKSIOS +U+AC90(2);; # HANGUL SYLLABLE KIYEOK E NIEUN * +U+AC91(2);; # HANGUL SYLLABLE KIYEOK E NIEUNCIEUC +U+AC92(2);; # HANGUL SYLLABLE KIYEOK E NIEUNHIEUH +U+AC93(2);; # HANGUL SYLLABLE KIYEOK E TIKEUT +U+AC94(2);; # HANGUL SYLLABLE KIYEOK E RIEUL * +U+AC95(2);; # HANGUL SYLLABLE KIYEOK E RIEULKIYEOK +U+AC96(2);; # HANGUL SYLLABLE KIYEOK E RIEULMIEUM +U+AC97(2);; # HANGUL SYLLABLE KIYEOK E RIEULPIEUP +U+AC98(2);; # HANGUL SYLLABLE KIYEOK E RIEULSIOS +U+AC99(2);; # HANGUL SYLLABLE KIYEOK E RIEULTHIEUTH +U+AC9A(2);; # HANGUL SYLLABLE KIYEOK E RIEULPHIEUPH +U+AC9B(2);; # HANGUL SYLLABLE KIYEOK E RIEULHIEUH +U+AC9C(2);; # HANGUL SYLLABLE KIYEOK E MIEUM * +U+AC9D(2);; # HANGUL SYLLABLE KIYEOK E PIEUP * +U+AC9E(2);; # HANGUL SYLLABLE KIYEOK E PIEUPSIOS +U+AC9F(2);; # HANGUL SYLLABLE KIYEOK E SIOS * +U+ACA0(2);; # HANGUL SYLLABLE KIYEOK E SSANGSIOS * +U+ACA1(2);; # HANGUL SYLLABLE KIYEOK E IEUNG * +U+ACA2(2);; # HANGUL SYLLABLE KIYEOK E CIEUC +U+ACA3(2);; # HANGUL SYLLABLE KIYEOK E CHIEUCH +U+ACA4(2);; # HANGUL SYLLABLE KIYEOK E KHIEUKH +U+ACA5(2);; # HANGUL SYLLABLE KIYEOK E THIEUTH +U+ACA6(2);; # HANGUL SYLLABLE KIYEOK E PHIEUPH +U+ACA7(2);; # HANGUL SYLLABLE KIYEOK E HIEUH +U+ACA8(2);; # HANGUL SYLLABLE KIYEOK YEO * +U+ACA9(2);; # HANGUL SYLLABLE KIYEOK YEO KIYEOK * +U+ACAA(2);; # HANGUL SYLLABLE KIYEOK YEO SSANGKIYEOK * +U+ACAB(2);; # HANGUL SYLLABLE KIYEOK YEO KIYEOKSIOS +U+ACAC(2);; # HANGUL SYLLABLE KIYEOK YEO NIEUN * +U+ACAD(2);; # HANGUL SYLLABLE KIYEOK YEO NIEUNCIEUC +U+ACAE(2);; # HANGUL SYLLABLE KIYEOK YEO NIEUNHIEUH +U+ACAF(2);; # HANGUL SYLLABLE KIYEOK YEO TIKEUT * +U+ACB0(2);; # HANGUL SYLLABLE KIYEOK YEO RIEUL * +U+ACB1(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULKIYEOK +U+ACB2(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULMIEUM +U+ACB3(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULPIEUP +U+ACB4(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULSIOS +U+ACB5(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULTHIEUTH +U+ACB6(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULPHIEUPH +U+ACB7(2);; # HANGUL SYLLABLE KIYEOK YEO RIEULHIEUH +U+ACB8(2);; # HANGUL SYLLABLE KIYEOK YEO MIEUM * +U+ACB9(2);; # HANGUL SYLLABLE KIYEOK YEO PIEUP * +U+ACBA(2);; # HANGUL SYLLABLE KIYEOK YEO PIEUPSIOS +U+ACBB(2);; # HANGUL SYLLABLE KIYEOK YEO SIOS * +U+ACBC(2);; # HANGUL SYLLABLE KIYEOK YEO SSANGSIOS * +U+ACBD(2);; # HANGUL SYLLABLE KIYEOK YEO IEUNG * +U+ACBE(2);; # HANGUL SYLLABLE KIYEOK YEO CIEUC +U+ACBF(2);; # HANGUL SYLLABLE KIYEOK YEO CHIEUCH +U+ACC0(2);; # HANGUL SYLLABLE KIYEOK YEO KHIEUKH +U+ACC1(2);; # HANGUL SYLLABLE KIYEOK YEO THIEUTH * +U+ACC2(2);; # HANGUL SYLLABLE KIYEOK YEO PHIEUPH +U+ACC3(2);; # HANGUL SYLLABLE KIYEOK YEO HIEUH +U+ACC4(2);; # HANGUL SYLLABLE KIYEOK YE * +U+ACC5(2);; # HANGUL SYLLABLE KIYEOK YE KIYEOK +U+ACC6(2);; # HANGUL SYLLABLE KIYEOK YE SSANGKIYEOK +U+ACC7(2);; # HANGUL SYLLABLE KIYEOK YE KIYEOKSIOS +U+ACC8(2);; # HANGUL SYLLABLE KIYEOK YE NIEUN * +U+ACC9(2);; # HANGUL SYLLABLE KIYEOK YE NIEUNCIEUC +U+ACCA(2);; # HANGUL SYLLABLE KIYEOK YE NIEUNHIEUH +U+ACCB(2);; # HANGUL SYLLABLE KIYEOK YE TIKEUT +U+ACCC(2);; # HANGUL SYLLABLE KIYEOK YE RIEUL * +U+ACCD(2);; # HANGUL SYLLABLE KIYEOK YE RIEULKIYEOK +U+ACCE(2);; # HANGUL SYLLABLE KIYEOK YE RIEULMIEUM +U+ACCF(2);; # HANGUL SYLLABLE KIYEOK YE RIEULPIEUP +U+ACD0(2);; # HANGUL SYLLABLE KIYEOK YE RIEULSIOS +U+ACD1(2);; # HANGUL SYLLABLE KIYEOK YE RIEULTHIEUTH +U+ACD2(2);; # HANGUL SYLLABLE KIYEOK YE RIEULPHIEUPH +U+ACD3(2);; # HANGUL SYLLABLE KIYEOK YE RIEULHIEUH +U+ACD4(2);; # HANGUL SYLLABLE KIYEOK YE MIEUM +U+ACD5(2);; # HANGUL SYLLABLE KIYEOK YE PIEUP * +U+ACD6(2);; # HANGUL SYLLABLE KIYEOK YE PIEUPSIOS +U+ACD7(2);; # HANGUL SYLLABLE KIYEOK YE SIOS * +U+ACD8(2);; # HANGUL SYLLABLE KIYEOK YE SSANGSIOS +U+ACD9(2);; # HANGUL SYLLABLE KIYEOK YE IEUNG +U+ACDA(2);; # HANGUL SYLLABLE KIYEOK YE CIEUC +U+ACDB(2);; # HANGUL SYLLABLE KIYEOK YE CHIEUCH +U+ACDC(2);; # HANGUL SYLLABLE KIYEOK YE KHIEUKH +U+ACDD(2);; # HANGUL SYLLABLE KIYEOK YE THIEUTH +U+ACDE(2);; # HANGUL SYLLABLE KIYEOK YE PHIEUPH +U+ACDF(2);; # HANGUL SYLLABLE KIYEOK YE HIEUH +U+ACE0(2);; # HANGUL SYLLABLE KIYEOK O * +U+ACE1(2);; # HANGUL SYLLABLE KIYEOK O KIYEOK * +U+ACE2(2);; # HANGUL SYLLABLE KIYEOK O SSANGKIYEOK +U+ACE3(2);; # HANGUL SYLLABLE KIYEOK O KIYEOKSIOS +U+ACE4(2);; # HANGUL SYLLABLE KIYEOK O NIEUN * +U+ACE5(2);; # HANGUL SYLLABLE KIYEOK O NIEUNCIEUC +U+ACE6(2);; # HANGUL SYLLABLE KIYEOK O NIEUNHIEUH +U+ACE7(2);; # HANGUL SYLLABLE KIYEOK O TIKEUT * +U+ACE8(2);; # HANGUL SYLLABLE KIYEOK O RIEUL * +U+ACE9(2);; # HANGUL SYLLABLE KIYEOK O RIEULKIYEOK +U+ACEA(2);; # HANGUL SYLLABLE KIYEOK O RIEULMIEUM * +U+ACEB(2);; # HANGUL SYLLABLE KIYEOK O RIEULPIEUP +U+ACEC(2);; # HANGUL SYLLABLE KIYEOK O RIEULSIOS * +U+ACED(2);; # HANGUL SYLLABLE KIYEOK O RIEULTHIEUTH +U+ACEE(2);; # HANGUL SYLLABLE KIYEOK O RIEULPHIEUPH +U+ACEF(2);; # HANGUL SYLLABLE KIYEOK O RIEULHIEUH * +U+ACF0(2);; # HANGUL SYLLABLE KIYEOK O MIEUM * +U+ACF1(2);; # HANGUL SYLLABLE KIYEOK O PIEUP * +U+ACF2(2);; # HANGUL SYLLABLE KIYEOK O PIEUPSIOS +U+ACF3(2);; # HANGUL SYLLABLE KIYEOK O SIOS * +U+ACF4(2);; # HANGUL SYLLABLE KIYEOK O SSANGSIOS +U+ACF5(2);; # HANGUL SYLLABLE KIYEOK O IEUNG * +U+ACF6(2);; # HANGUL SYLLABLE KIYEOK O CIEUC * +U+ACF7(2);; # HANGUL SYLLABLE KIYEOK O CHIEUCH +U+ACF8(2);; # HANGUL SYLLABLE KIYEOK O KHIEUKH +U+ACF9(2);; # HANGUL SYLLABLE KIYEOK O THIEUTH +U+ACFA(2);; # HANGUL SYLLABLE KIYEOK O PHIEUPH +U+ACFB(2);; # HANGUL SYLLABLE KIYEOK O HIEUH +U+ACFC(2);; # HANGUL SYLLABLE KIYEOK WA * +U+ACFD(2);; # HANGUL SYLLABLE KIYEOK WA KIYEOK * +U+ACFE(2);; # HANGUL SYLLABLE KIYEOK WA SSANGKIYEOK +U+ACFF(2);; # HANGUL SYLLABLE KIYEOK WA KIYEOKSIOS +U+AD00(2);; # HANGUL SYLLABLE KIYEOK WA NIEUN * +U+AD01(2);; # HANGUL SYLLABLE KIYEOK WA NIEUNCIEUC +U+AD02(2);; # HANGUL SYLLABLE KIYEOK WA NIEUNHIEUH +U+AD03(2);; # HANGUL SYLLABLE KIYEOK WA TIKEUT +U+AD04(2);; # HANGUL SYLLABLE KIYEOK WA RIEUL * +U+AD05(2);; # HANGUL SYLLABLE KIYEOK WA RIEULKIYEOK +U+AD06(2);; # HANGUL SYLLABLE KIYEOK WA RIEULMIEUM * +U+AD07(2);; # HANGUL SYLLABLE KIYEOK WA RIEULPIEUP +U+AD08(2);; # HANGUL SYLLABLE KIYEOK WA RIEULSIOS +U+AD09(2);; # HANGUL SYLLABLE KIYEOK WA RIEULTHIEUTH +U+AD0A(2);; # HANGUL SYLLABLE KIYEOK WA RIEULPHIEUPH +U+AD0B(2);; # HANGUL SYLLABLE KIYEOK WA RIEULHIEUH +U+AD0C(2);; # HANGUL SYLLABLE KIYEOK WA MIEUM * +U+AD0D(2);; # HANGUL SYLLABLE KIYEOK WA PIEUP * +U+AD0E(2);; # HANGUL SYLLABLE KIYEOK WA PIEUPSIOS +U+AD0F(2);; # HANGUL SYLLABLE KIYEOK WA SIOS * +U+AD10(2);; # HANGUL SYLLABLE KIYEOK WA SSANGSIOS +U+AD11(2);; # HANGUL SYLLABLE KIYEOK WA IEUNG * +U+AD12(2);; # HANGUL SYLLABLE KIYEOK WA CIEUC +U+AD13(2);; # HANGUL SYLLABLE KIYEOK WA CHIEUCH +U+AD14(2);; # HANGUL SYLLABLE KIYEOK WA KHIEUKH +U+AD15(2);; # HANGUL SYLLABLE KIYEOK WA THIEUTH +U+AD16(2);; # HANGUL SYLLABLE KIYEOK WA PHIEUPH +U+AD17(2);; # HANGUL SYLLABLE KIYEOK WA HIEUH +U+AD18(2);; # HANGUL SYLLABLE KIYEOK WAE * +U+AD19(2);; # HANGUL SYLLABLE KIYEOK WAE KIYEOK +U+AD1A(2);; # HANGUL SYLLABLE KIYEOK WAE SSANGKIYEOK +U+AD1B(2);; # HANGUL SYLLABLE KIYEOK WAE KIYEOKSIOS +U+AD1C(2);; # HANGUL SYLLABLE KIYEOK WAE NIEUN * +U+AD1D(2);; # HANGUL SYLLABLE KIYEOK WAE NIEUNCIEUC +U+AD1E(2);; # HANGUL SYLLABLE KIYEOK WAE NIEUNHIEUH +U+AD1F(2);; # HANGUL SYLLABLE KIYEOK WAE TIKEUT +U+AD20(2);; # HANGUL SYLLABLE KIYEOK WAE RIEUL * +U+AD21(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULKIYEOK +U+AD22(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULMIEUM +U+AD23(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULPIEUP +U+AD24(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULSIOS +U+AD25(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULTHIEUTH +U+AD26(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULPHIEUPH +U+AD27(2);; # HANGUL SYLLABLE KIYEOK WAE RIEULHIEUH +U+AD28(2);; # HANGUL SYLLABLE KIYEOK WAE MIEUM +U+AD29(2);; # HANGUL SYLLABLE KIYEOK WAE PIEUP * +U+AD2A(2);; # HANGUL SYLLABLE KIYEOK WAE PIEUPSIOS +U+AD2B(2);; # HANGUL SYLLABLE KIYEOK WAE SIOS +U+AD2C(2);; # HANGUL SYLLABLE KIYEOK WAE SSANGSIOS * +U+AD2D(2);; # HANGUL SYLLABLE KIYEOK WAE IEUNG * +U+AD2E(2);; # HANGUL SYLLABLE KIYEOK WAE CIEUC +U+AD2F(2);; # HANGUL SYLLABLE KIYEOK WAE CHIEUCH +U+AD30(2);; # HANGUL SYLLABLE KIYEOK WAE KHIEUKH +U+AD31(2);; # HANGUL SYLLABLE KIYEOK WAE THIEUTH +U+AD32(2);; # HANGUL SYLLABLE KIYEOK WAE PHIEUPH +U+AD33(2);; # HANGUL SYLLABLE KIYEOK WAE HIEUH +U+AD34(2);; # HANGUL SYLLABLE KIYEOK OE * +U+AD35(2);; # HANGUL SYLLABLE KIYEOK OE KIYEOK * +U+AD36(2);; # HANGUL SYLLABLE KIYEOK OE SSANGKIYEOK +U+AD37(2);; # HANGUL SYLLABLE KIYEOK OE KIYEOKSIOS +U+AD38(2);; # HANGUL SYLLABLE KIYEOK OE NIEUN * +U+AD39(2);; # HANGUL SYLLABLE KIYEOK OE NIEUNCIEUC +U+AD3A(2);; # HANGUL SYLLABLE KIYEOK OE NIEUNHIEUH +U+AD3B(2);; # HANGUL SYLLABLE KIYEOK OE TIKEUT +U+AD3C(2);; # HANGUL SYLLABLE KIYEOK OE RIEUL * +U+AD3D(2);; # HANGUL SYLLABLE KIYEOK OE RIEULKIYEOK +U+AD3E(2);; # HANGUL SYLLABLE KIYEOK OE RIEULMIEUM +U+AD3F(2);; # HANGUL SYLLABLE KIYEOK OE RIEULPIEUP +U+AD40(2);; # HANGUL SYLLABLE KIYEOK OE RIEULSIOS +U+AD41(2);; # HANGUL SYLLABLE KIYEOK OE RIEULTHIEUTH +U+AD42(2);; # HANGUL SYLLABLE KIYEOK OE RIEULPHIEUPH +U+AD43(2);; # HANGUL SYLLABLE KIYEOK OE RIEULHIEUH +U+AD44(2);; # HANGUL SYLLABLE KIYEOK OE MIEUM * +U+AD45(2);; # HANGUL SYLLABLE KIYEOK OE PIEUP * +U+AD46(2);; # HANGUL SYLLABLE KIYEOK OE PIEUPSIOS +U+AD47(2);; # HANGUL SYLLABLE KIYEOK OE SIOS * +U+AD48(2);; # HANGUL SYLLABLE KIYEOK OE SSANGSIOS +U+AD49(2);; # HANGUL SYLLABLE KIYEOK OE IEUNG * +U+AD4A(2);; # HANGUL SYLLABLE KIYEOK OE CIEUC +U+AD4B(2);; # HANGUL SYLLABLE KIYEOK OE CHIEUCH +U+AD4C(2);; # HANGUL SYLLABLE KIYEOK OE KHIEUKH +U+AD4D(2);; # HANGUL SYLLABLE KIYEOK OE THIEUTH +U+AD4E(2);; # HANGUL SYLLABLE KIYEOK OE PHIEUPH +U+AD4F(2);; # HANGUL SYLLABLE KIYEOK OE HIEUH +U+AD50(2);; # HANGUL SYLLABLE KIYEOK YO * +U+AD51(2);; # HANGUL SYLLABLE KIYEOK YO KIYEOK +U+AD52(2);; # HANGUL SYLLABLE KIYEOK YO SSANGKIYEOK +U+AD53(2);; # HANGUL SYLLABLE KIYEOK YO KIYEOKSIOS +U+AD54(2);; # HANGUL SYLLABLE KIYEOK YO NIEUN * +U+AD55(2);; # HANGUL SYLLABLE KIYEOK YO NIEUNCIEUC +U+AD56(2);; # HANGUL SYLLABLE KIYEOK YO NIEUNHIEUH +U+AD57(2);; # HANGUL SYLLABLE KIYEOK YO TIKEUT +U+AD58(2);; # HANGUL SYLLABLE KIYEOK YO RIEUL * +U+AD59(2);; # HANGUL SYLLABLE KIYEOK YO RIEULKIYEOK +U+AD5A(2);; # HANGUL SYLLABLE KIYEOK YO RIEULMIEUM +U+AD5B(2);; # HANGUL SYLLABLE KIYEOK YO RIEULPIEUP +U+AD5C(2);; # HANGUL SYLLABLE KIYEOK YO RIEULSIOS +U+AD5D(2);; # HANGUL SYLLABLE KIYEOK YO RIEULTHIEUTH +U+AD5E(2);; # HANGUL SYLLABLE KIYEOK YO RIEULPHIEUPH +U+AD5F(2);; # HANGUL SYLLABLE KIYEOK YO RIEULHIEUH +U+AD60(2);; # HANGUL SYLLABLE KIYEOK YO MIEUM +U+AD61(2);; # HANGUL SYLLABLE KIYEOK YO PIEUP * +U+AD62(2);; # HANGUL SYLLABLE KIYEOK YO PIEUPSIOS +U+AD63(2);; # HANGUL SYLLABLE KIYEOK YO SIOS * +U+AD64(2);; # HANGUL SYLLABLE KIYEOK YO SSANGSIOS +U+AD65(2);; # HANGUL SYLLABLE KIYEOK YO IEUNG +U+AD66(2);; # HANGUL SYLLABLE KIYEOK YO CIEUC +U+AD67(2);; # HANGUL SYLLABLE KIYEOK YO CHIEUCH +U+AD68(2);; # HANGUL SYLLABLE KIYEOK YO KHIEUKH +U+AD69(2);; # HANGUL SYLLABLE KIYEOK YO THIEUTH +U+AD6A(2);; # HANGUL SYLLABLE KIYEOK YO PHIEUPH +U+AD6B(2);; # HANGUL SYLLABLE KIYEOK YO HIEUH +U+AD6C(2);; # HANGUL SYLLABLE KIYEOK U * +U+AD6D(2);; # HANGUL SYLLABLE KIYEOK U KIYEOK * +U+AD6E(2);; # HANGUL SYLLABLE KIYEOK U SSANGKIYEOK +U+AD6F(2);; # HANGUL SYLLABLE KIYEOK U KIYEOKSIOS +U+AD70(2);; # HANGUL SYLLABLE KIYEOK U NIEUN * +U+AD71(2);; # HANGUL SYLLABLE KIYEOK U NIEUNCIEUC +U+AD72(2);; # HANGUL SYLLABLE KIYEOK U NIEUNHIEUH +U+AD73(2);; # HANGUL SYLLABLE KIYEOK U TIKEUT * +U+AD74(2);; # HANGUL SYLLABLE KIYEOK U RIEUL * +U+AD75(2);; # HANGUL SYLLABLE KIYEOK U RIEULKIYEOK * +U+AD76(2);; # HANGUL SYLLABLE KIYEOK U RIEULMIEUM * +U+AD77(2);; # HANGUL SYLLABLE KIYEOK U RIEULPIEUP +U+AD78(2);; # HANGUL SYLLABLE KIYEOK U RIEULSIOS +U+AD79(2);; # HANGUL SYLLABLE KIYEOK U RIEULTHIEUTH +U+AD7A(2);; # HANGUL SYLLABLE KIYEOK U RIEULPHIEUPH +U+AD7B(2);; # HANGUL SYLLABLE KIYEOK U RIEULHIEUH * +U+AD7C(2);; # HANGUL SYLLABLE KIYEOK U MIEUM * +U+AD7D(2);; # HANGUL SYLLABLE KIYEOK U PIEUP * +U+AD7E(2);; # HANGUL SYLLABLE KIYEOK U PIEUPSIOS +U+AD7F(2);; # HANGUL SYLLABLE KIYEOK U SIOS * +U+AD80(2);; # HANGUL SYLLABLE KIYEOK U SSANGSIOS +U+AD81(2);; # HANGUL SYLLABLE KIYEOK U IEUNG * +U+AD82(2);; # HANGUL SYLLABLE KIYEOK U CIEUC * +U+AD83(2);; # HANGUL SYLLABLE KIYEOK U CHIEUCH +U+AD84(2);; # HANGUL SYLLABLE KIYEOK U KHIEUKH +U+AD85(2);; # HANGUL SYLLABLE KIYEOK U THIEUTH +U+AD86(2);; # HANGUL SYLLABLE KIYEOK U PHIEUPH +U+AD87(2);; # HANGUL SYLLABLE KIYEOK U HIEUH +U+AD88(2);; # HANGUL SYLLABLE KIYEOK WEO * +U+AD89(2);; # HANGUL SYLLABLE KIYEOK WEO KIYEOK * +U+AD8A(2);; # HANGUL SYLLABLE KIYEOK WEO SSANGKIYEOK +U+AD8B(2);; # HANGUL SYLLABLE KIYEOK WEO KIYEOKSIOS +U+AD8C(2);; # HANGUL SYLLABLE KIYEOK WEO NIEUN * +U+AD8D(2);; # HANGUL SYLLABLE KIYEOK WEO NIEUNCIEUC +U+AD8E(2);; # HANGUL SYLLABLE KIYEOK WEO NIEUNHIEUH +U+AD8F(2);; # HANGUL SYLLABLE KIYEOK WEO TIKEUT +U+AD90(2);; # HANGUL SYLLABLE KIYEOK WEO RIEUL * +U+AD91(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULKIYEOK +U+AD92(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULMIEUM +U+AD93(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULPIEUP +U+AD94(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULSIOS +U+AD95(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULTHIEUTH +U+AD96(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULPHIEUPH +U+AD97(2);; # HANGUL SYLLABLE KIYEOK WEO RIEULHIEUH +U+AD98(2);; # HANGUL SYLLABLE KIYEOK WEO MIEUM +U+AD99(2);; # HANGUL SYLLABLE KIYEOK WEO PIEUP +U+AD9A(2);; # HANGUL SYLLABLE KIYEOK WEO PIEUPSIOS +U+AD9B(2);; # HANGUL SYLLABLE KIYEOK WEO SIOS +U+AD9C(2);; # HANGUL SYLLABLE KIYEOK WEO SSANGSIOS * +U+AD9D(2);; # HANGUL SYLLABLE KIYEOK WEO IEUNG * +U+AD9E(2);; # HANGUL SYLLABLE KIYEOK WEO CIEUC +U+AD9F(2);; # HANGUL SYLLABLE KIYEOK WEO CHIEUCH +U+ADA0(2);; # HANGUL SYLLABLE KIYEOK WEO KHIEUKH +U+ADA1(2);; # HANGUL SYLLABLE KIYEOK WEO THIEUTH +U+ADA2(2);; # HANGUL SYLLABLE KIYEOK WEO PHIEUPH +U+ADA3(2);; # HANGUL SYLLABLE KIYEOK WEO HIEUH +U+ADA4(2);; # HANGUL SYLLABLE KIYEOK WE * +U+ADA5(2);; # HANGUL SYLLABLE KIYEOK WE KIYEOK +U+ADA6(2);; # HANGUL SYLLABLE KIYEOK WE SSANGKIYEOK +U+ADA7(2);; # HANGUL SYLLABLE KIYEOK WE KIYEOKSIOS +U+ADA8(2);; # HANGUL SYLLABLE KIYEOK WE NIEUN +U+ADA9(2);; # HANGUL SYLLABLE KIYEOK WE NIEUNCIEUC +U+ADAA(2);; # HANGUL SYLLABLE KIYEOK WE NIEUNHIEUH +U+ADAB(2);; # HANGUL SYLLABLE KIYEOK WE TIKEUT +U+ADAC(2);; # HANGUL SYLLABLE KIYEOK WE RIEUL +U+ADAD(2);; # HANGUL SYLLABLE KIYEOK WE RIEULKIYEOK +U+ADAE(2);; # HANGUL SYLLABLE KIYEOK WE RIEULMIEUM +U+ADAF(2);; # HANGUL SYLLABLE KIYEOK WE RIEULPIEUP +U+ADB0(2);; # HANGUL SYLLABLE KIYEOK WE RIEULSIOS +U+ADB1(2);; # HANGUL SYLLABLE KIYEOK WE RIEULTHIEUTH +U+ADB2(2);; # HANGUL SYLLABLE KIYEOK WE RIEULPHIEUPH +U+ADB3(2);; # HANGUL SYLLABLE KIYEOK WE RIEULHIEUH +U+ADB4(2);; # HANGUL SYLLABLE KIYEOK WE MIEUM +U+ADB5(2);; # HANGUL SYLLABLE KIYEOK WE PIEUP +U+ADB6(2);; # HANGUL SYLLABLE KIYEOK WE PIEUPSIOS +U+ADB7(2);; # HANGUL SYLLABLE KIYEOK WE SIOS * +U+ADB8(2);; # HANGUL SYLLABLE KIYEOK WE SSANGSIOS +U+ADB9(2);; # HANGUL SYLLABLE KIYEOK WE IEUNG +U+ADBA(2);; # HANGUL SYLLABLE KIYEOK WE CIEUC +U+ADBB(2);; # HANGUL SYLLABLE KIYEOK WE CHIEUCH +U+ADBC(2);; # HANGUL SYLLABLE KIYEOK WE KHIEUKH +U+ADBD(2);; # HANGUL SYLLABLE KIYEOK WE THIEUTH +U+ADBE(2);; # HANGUL SYLLABLE KIYEOK WE PHIEUPH +U+ADBF(2);; # HANGUL SYLLABLE KIYEOK WE HIEUH +U+ADC0(2);; # HANGUL SYLLABLE KIYEOK WI * +U+ADC1(2);; # HANGUL SYLLABLE KIYEOK WI KIYEOK * +U+ADC2(2);; # HANGUL SYLLABLE KIYEOK WI SSANGKIYEOK +U+ADC3(2);; # HANGUL SYLLABLE KIYEOK WI KIYEOKSIOS +U+ADC4(2);; # HANGUL SYLLABLE KIYEOK WI NIEUN * +U+ADC5(2);; # HANGUL SYLLABLE KIYEOK WI NIEUNCIEUC +U+ADC6(2);; # HANGUL SYLLABLE KIYEOK WI NIEUNHIEUH +U+ADC7(2);; # HANGUL SYLLABLE KIYEOK WI TIKEUT +U+ADC8(2);; # HANGUL SYLLABLE KIYEOK WI RIEUL * +U+ADC9(2);; # HANGUL SYLLABLE KIYEOK WI RIEULKIYEOK +U+ADCA(2);; # HANGUL SYLLABLE KIYEOK WI RIEULMIEUM +U+ADCB(2);; # HANGUL SYLLABLE KIYEOK WI RIEULPIEUP +U+ADCC(2);; # HANGUL SYLLABLE KIYEOK WI RIEULSIOS +U+ADCD(2);; # HANGUL SYLLABLE KIYEOK WI RIEULTHIEUTH +U+ADCE(2);; # HANGUL SYLLABLE KIYEOK WI RIEULPHIEUPH +U+ADCF(2);; # HANGUL SYLLABLE KIYEOK WI RIEULHIEUH +U+ADD0(2);; # HANGUL SYLLABLE KIYEOK WI MIEUM * +U+ADD1(2);; # HANGUL SYLLABLE KIYEOK WI PIEUP * +U+ADD2(2);; # HANGUL SYLLABLE KIYEOK WI PIEUPSIOS +U+ADD3(2);; # HANGUL SYLLABLE KIYEOK WI SIOS * +U+ADD4(2);; # HANGUL SYLLABLE KIYEOK WI SSANGSIOS +U+ADD5(2);; # HANGUL SYLLABLE KIYEOK WI IEUNG +U+ADD6(2);; # HANGUL SYLLABLE KIYEOK WI CIEUC +U+ADD7(2);; # HANGUL SYLLABLE KIYEOK WI CHIEUCH +U+ADD8(2);; # HANGUL SYLLABLE KIYEOK WI KHIEUKH +U+ADD9(2);; # HANGUL SYLLABLE KIYEOK WI THIEUTH +U+ADDA(2);; # HANGUL SYLLABLE KIYEOK WI PHIEUPH +U+ADDB(2);; # HANGUL SYLLABLE KIYEOK WI HIEUH +U+ADDC(2);; # HANGUL SYLLABLE KIYEOK YU * +U+ADDD(2);; # HANGUL SYLLABLE KIYEOK YU KIYEOK +U+ADDE(2);; # HANGUL SYLLABLE KIYEOK YU SSANGKIYEOK +U+ADDF(2);; # HANGUL SYLLABLE KIYEOK YU KIYEOKSIOS +U+ADE0(2);; # HANGUL SYLLABLE KIYEOK YU NIEUN * +U+ADE1(2);; # HANGUL SYLLABLE KIYEOK YU NIEUNCIEUC +U+ADE2(2);; # HANGUL SYLLABLE KIYEOK YU NIEUNHIEUH +U+ADE3(2);; # HANGUL SYLLABLE KIYEOK YU TIKEUT +U+ADE4(2);; # HANGUL SYLLABLE KIYEOK YU RIEUL * +U+ADE5(2);; # HANGUL SYLLABLE KIYEOK YU RIEULKIYEOK +U+ADE6(2);; # HANGUL SYLLABLE KIYEOK YU RIEULMIEUM +U+ADE7(2);; # HANGUL SYLLABLE KIYEOK YU RIEULPIEUP +U+ADE8(2);; # HANGUL SYLLABLE KIYEOK YU RIEULSIOS +U+ADE9(2);; # HANGUL SYLLABLE KIYEOK YU RIEULTHIEUTH +U+ADEA(2);; # HANGUL SYLLABLE KIYEOK YU RIEULPHIEUPH +U+ADEB(2);; # HANGUL SYLLABLE KIYEOK YU RIEULHIEUH +U+ADEC(2);; # HANGUL SYLLABLE KIYEOK YU MIEUM +U+ADED(2);; # HANGUL SYLLABLE KIYEOK YU PIEUP +U+ADEE(2);; # HANGUL SYLLABLE KIYEOK YU PIEUPSIOS +U+ADEF(2);; # HANGUL SYLLABLE KIYEOK YU SIOS +U+ADF0(2);; # HANGUL SYLLABLE KIYEOK YU SSANGSIOS +U+ADF1(2);; # HANGUL SYLLABLE KIYEOK YU IEUNG +U+ADF2(2);; # HANGUL SYLLABLE KIYEOK YU CIEUC +U+ADF3(2);; # HANGUL SYLLABLE KIYEOK YU CHIEUCH +U+ADF4(2);; # HANGUL SYLLABLE KIYEOK YU KHIEUKH +U+ADF5(2);; # HANGUL SYLLABLE KIYEOK YU THIEUTH +U+ADF6(2);; # HANGUL SYLLABLE KIYEOK YU PHIEUPH +U+ADF7(2);; # HANGUL SYLLABLE KIYEOK YU HIEUH +U+ADF8(2);; # HANGUL SYLLABLE KIYEOK EU * +U+ADF9(2);; # HANGUL SYLLABLE KIYEOK EU KIYEOK * +U+ADFA(2);; # HANGUL SYLLABLE KIYEOK EU SSANGKIYEOK +U+ADFB(2);; # HANGUL SYLLABLE KIYEOK EU KIYEOKSIOS +U+ADFC(2);; # HANGUL SYLLABLE KIYEOK EU NIEUN * +U+ADFD(2);; # HANGUL SYLLABLE KIYEOK EU NIEUNCIEUC +U+ADFE(2);; # HANGUL SYLLABLE KIYEOK EU NIEUNHIEUH +U+ADFF(2);; # HANGUL SYLLABLE KIYEOK EU TIKEUT * +U+AE00(2);; # HANGUL SYLLABLE KIYEOK EU RIEUL * +U+AE01(2);; # HANGUL SYLLABLE KIYEOK EU RIEULKIYEOK * +U+AE02(2);; # HANGUL SYLLABLE KIYEOK EU RIEULMIEUM +U+AE03(2);; # HANGUL SYLLABLE KIYEOK EU RIEULPIEUP +U+AE04(2);; # HANGUL SYLLABLE KIYEOK EU RIEULSIOS +U+AE05(2);; # HANGUL SYLLABLE KIYEOK EU RIEULTHIEUTH +U+AE06(2);; # HANGUL SYLLABLE KIYEOK EU RIEULPHIEUPH +U+AE07(2);; # HANGUL SYLLABLE KIYEOK EU RIEULHIEUH +U+AE08(2);; # HANGUL SYLLABLE KIYEOK EU MIEUM * +U+AE09(2);; # HANGUL SYLLABLE KIYEOK EU PIEUP * +U+AE0A(2);; # HANGUL SYLLABLE KIYEOK EU PIEUPSIOS +U+AE0B(2);; # HANGUL SYLLABLE KIYEOK EU SIOS * +U+AE0C(2);; # HANGUL SYLLABLE KIYEOK EU SSANGSIOS +U+AE0D(2);; # HANGUL SYLLABLE KIYEOK EU IEUNG * +U+AE0E(2);; # HANGUL SYLLABLE KIYEOK EU CIEUC +U+AE0F(2);; # HANGUL SYLLABLE KIYEOK EU CHIEUCH +U+AE10(2);; # HANGUL SYLLABLE KIYEOK EU KHIEUKH +U+AE11(2);; # HANGUL SYLLABLE KIYEOK EU THIEUTH +U+AE12(2);; # HANGUL SYLLABLE KIYEOK EU PHIEUPH +U+AE13(2);; # HANGUL SYLLABLE KIYEOK EU HIEUH +U+AE14(2);; # HANGUL SYLLABLE KIYEOK YI * +U+AE15(2);; # HANGUL SYLLABLE KIYEOK YI KIYEOK +U+AE16(2);; # HANGUL SYLLABLE KIYEOK YI SSANGKIYEOK +U+AE17(2);; # HANGUL SYLLABLE KIYEOK YI KIYEOKSIOS +U+AE18(2);; # HANGUL SYLLABLE KIYEOK YI NIEUN +U+AE19(2);; # HANGUL SYLLABLE KIYEOK YI NIEUNCIEUC +U+AE1A(2);; # HANGUL SYLLABLE KIYEOK YI NIEUNHIEUH +U+AE1B(2);; # HANGUL SYLLABLE KIYEOK YI TIKEUT +U+AE1C(2);; # HANGUL SYLLABLE KIYEOK YI RIEUL +U+AE1D(2);; # HANGUL SYLLABLE KIYEOK YI RIEULKIYEOK +U+AE1E(2);; # HANGUL SYLLABLE KIYEOK YI RIEULMIEUM +U+AE1F(2);; # HANGUL SYLLABLE KIYEOK YI RIEULPIEUP +U+AE20(2);; # HANGUL SYLLABLE KIYEOK YI RIEULSIOS +U+AE21(2);; # HANGUL SYLLABLE KIYEOK YI RIEULTHIEUTH +U+AE22(2);; # HANGUL SYLLABLE KIYEOK YI RIEULPHIEUPH +U+AE23(2);; # HANGUL SYLLABLE KIYEOK YI RIEULHIEUH +U+AE24(2);; # HANGUL SYLLABLE KIYEOK YI MIEUM +U+AE25(2);; # HANGUL SYLLABLE KIYEOK YI PIEUP +U+AE26(2);; # HANGUL SYLLABLE KIYEOK YI PIEUPSIOS +U+AE27(2);; # HANGUL SYLLABLE KIYEOK YI SIOS +U+AE28(2);; # HANGUL SYLLABLE KIYEOK YI SSANGSIOS +U+AE29(2);; # HANGUL SYLLABLE KIYEOK YI IEUNG +U+AE2A(2);; # HANGUL SYLLABLE KIYEOK YI CIEUC +U+AE2B(2);; # HANGUL SYLLABLE KIYEOK YI CHIEUCH +U+AE2C(2);; # HANGUL SYLLABLE KIYEOK YI KHIEUKH +U+AE2D(2);; # HANGUL SYLLABLE KIYEOK YI THIEUTH +U+AE2E(2);; # HANGUL SYLLABLE KIYEOK YI PHIEUPH +U+AE2F(2);; # HANGUL SYLLABLE KIYEOK YI HIEUH +U+AE30(2);; # HANGUL SYLLABLE KIYEOK I * +U+AE31(2);; # HANGUL SYLLABLE KIYEOK I KIYEOK * +U+AE32(2);; # HANGUL SYLLABLE KIYEOK I SSANGKIYEOK +U+AE33(2);; # HANGUL SYLLABLE KIYEOK I KIYEOKSIOS +U+AE34(2);; # HANGUL SYLLABLE KIYEOK I NIEUN * +U+AE35(2);; # HANGUL SYLLABLE KIYEOK I NIEUNCIEUC +U+AE36(2);; # HANGUL SYLLABLE KIYEOK I NIEUNHIEUH +U+AE37(2);; # HANGUL SYLLABLE KIYEOK I TIKEUT * +U+AE38(2);; # HANGUL SYLLABLE KIYEOK I RIEUL * +U+AE39(2);; # HANGUL SYLLABLE KIYEOK I RIEULKIYEOK +U+AE3A(2);; # HANGUL SYLLABLE KIYEOK I RIEULMIEUM * +U+AE3B(2);; # HANGUL SYLLABLE KIYEOK I RIEULPIEUP +U+AE3C(2);; # HANGUL SYLLABLE KIYEOK I RIEULSIOS +U+AE3D(2);; # HANGUL SYLLABLE KIYEOK I RIEULTHIEUTH +U+AE3E(2);; # HANGUL SYLLABLE KIYEOK I RIEULPHIEUPH +U+AE3F(2);; # HANGUL SYLLABLE KIYEOK I RIEULHIEUH +U+AE40(2);; # HANGUL SYLLABLE KIYEOK I MIEUM * +U+AE41(2);; # HANGUL SYLLABLE KIYEOK I PIEUP * +U+AE42(2);; # HANGUL SYLLABLE KIYEOK I PIEUPSIOS +U+AE43(2);; # HANGUL SYLLABLE KIYEOK I SIOS * +U+AE44(2);; # HANGUL SYLLABLE KIYEOK I SSANGSIOS +U+AE45(2);; # HANGUL SYLLABLE KIYEOK I IEUNG * +U+AE46(2);; # HANGUL SYLLABLE KIYEOK I CIEUC * +U+AE47(2);; # HANGUL SYLLABLE KIYEOK I CHIEUCH +U+AE48(2);; # HANGUL SYLLABLE KIYEOK I KHIEUKH +U+AE49(2);; # HANGUL SYLLABLE KIYEOK I THIEUTH +U+AE4A(2);; # HANGUL SYLLABLE KIYEOK I PHIEUPH * +U+AE4B(2);; # HANGUL SYLLABLE KIYEOK I HIEUH +U+AE4C(2);; # HANGUL SYLLABLE SSANGKIYEOK A * +U+AE4D(2);; # HANGUL SYLLABLE SSANGKIYEOK A KIYEOK * +U+AE4E(2);; # HANGUL SYLLABLE SSANGKIYEOK A SSANGKIYEOK * +U+AE4F(2);; # HANGUL SYLLABLE SSANGKIYEOK A KIYEOKSIOS +U+AE50(2);; # HANGUL SYLLABLE SSANGKIYEOK A NIEUN * +U+AE51(2);; # HANGUL SYLLABLE SSANGKIYEOK A NIEUNCIEUC +U+AE52(2);; # HANGUL SYLLABLE SSANGKIYEOK A NIEUNHIEUH +U+AE53(2);; # HANGUL SYLLABLE SSANGKIYEOK A TIKEUT +U+AE54(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEUL * +U+AE55(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULKIYEOK +U+AE56(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULMIEUM * +U+AE57(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULPIEUP +U+AE58(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULSIOS +U+AE59(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULTHIEUTH +U+AE5A(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULPHIEUPH +U+AE5B(2);; # HANGUL SYLLABLE SSANGKIYEOK A RIEULHIEUH +U+AE5C(2);; # HANGUL SYLLABLE SSANGKIYEOK A MIEUM * +U+AE5D(2);; # HANGUL SYLLABLE SSANGKIYEOK A PIEUP * +U+AE5E(2);; # HANGUL SYLLABLE SSANGKIYEOK A PIEUPSIOS +U+AE5F(2);; # HANGUL SYLLABLE SSANGKIYEOK A SIOS * +U+AE60(2);; # HANGUL SYLLABLE SSANGKIYEOK A SSANGSIOS * +U+AE61(2);; # HANGUL SYLLABLE SSANGKIYEOK A IEUNG * +U+AE62(2);; # HANGUL SYLLABLE SSANGKIYEOK A CIEUC +U+AE63(2);; # HANGUL SYLLABLE SSANGKIYEOK A CHIEUCH +U+AE64(2);; # HANGUL SYLLABLE SSANGKIYEOK A KHIEUKH +U+AE65(2);; # HANGUL SYLLABLE SSANGKIYEOK A THIEUTH * +U+AE66(2);; # HANGUL SYLLABLE SSANGKIYEOK A PHIEUPH +U+AE67(2);; # HANGUL SYLLABLE SSANGKIYEOK A HIEUH +U+AE68(2);; # HANGUL SYLLABLE SSANGKIYEOK AE * +U+AE69(2);; # HANGUL SYLLABLE SSANGKIYEOK AE KIYEOK * +U+AE6A(2);; # HANGUL SYLLABLE SSANGKIYEOK AE SSANGKIYEOK +U+AE6B(2);; # HANGUL SYLLABLE SSANGKIYEOK AE KIYEOKSIOS +U+AE6C(2);; # HANGUL SYLLABLE SSANGKIYEOK AE NIEUN * +U+AE6D(2);; # HANGUL SYLLABLE SSANGKIYEOK AE NIEUNCIEUC +U+AE6E(2);; # HANGUL SYLLABLE SSANGKIYEOK AE NIEUNHIEUH +U+AE6F(2);; # HANGUL SYLLABLE SSANGKIYEOK AE TIKEUT +U+AE70(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEUL * +U+AE71(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULKIYEOK +U+AE72(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULMIEUM +U+AE73(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULPIEUP +U+AE74(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULSIOS +U+AE75(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULTHIEUTH +U+AE76(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULPHIEUPH +U+AE77(2);; # HANGUL SYLLABLE SSANGKIYEOK AE RIEULHIEUH +U+AE78(2);; # HANGUL SYLLABLE SSANGKIYEOK AE MIEUM * +U+AE79(2);; # HANGUL SYLLABLE SSANGKIYEOK AE PIEUP * +U+AE7A(2);; # HANGUL SYLLABLE SSANGKIYEOK AE PIEUPSIOS +U+AE7B(2);; # HANGUL SYLLABLE SSANGKIYEOK AE SIOS * +U+AE7C(2);; # HANGUL SYLLABLE SSANGKIYEOK AE SSANGSIOS * +U+AE7D(2);; # HANGUL SYLLABLE SSANGKIYEOK AE IEUNG * +U+AE7E(2);; # HANGUL SYLLABLE SSANGKIYEOK AE CIEUC +U+AE7F(2);; # HANGUL SYLLABLE SSANGKIYEOK AE CHIEUCH +U+AE80(2);; # HANGUL SYLLABLE SSANGKIYEOK AE KHIEUKH +U+AE81(2);; # HANGUL SYLLABLE SSANGKIYEOK AE THIEUTH +U+AE82(2);; # HANGUL SYLLABLE SSANGKIYEOK AE PHIEUPH +U+AE83(2);; # HANGUL SYLLABLE SSANGKIYEOK AE HIEUH +U+AE84(2);; # HANGUL SYLLABLE SSANGKIYEOK YA * +U+AE85(2);; # HANGUL SYLLABLE SSANGKIYEOK YA KIYEOK * +U+AE86(2);; # HANGUL SYLLABLE SSANGKIYEOK YA SSANGKIYEOK +U+AE87(2);; # HANGUL SYLLABLE SSANGKIYEOK YA KIYEOKSIOS +U+AE88(2);; # HANGUL SYLLABLE SSANGKIYEOK YA NIEUN +U+AE89(2);; # HANGUL SYLLABLE SSANGKIYEOK YA NIEUNCIEUC +U+AE8A(2);; # HANGUL SYLLABLE SSANGKIYEOK YA NIEUNHIEUH +U+AE8B(2);; # HANGUL SYLLABLE SSANGKIYEOK YA TIKEUT +U+AE8C(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEUL * +U+AE8D(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULKIYEOK +U+AE8E(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULMIEUM +U+AE8F(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULPIEUP +U+AE90(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULSIOS +U+AE91(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULTHIEUTH +U+AE92(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULPHIEUPH +U+AE93(2);; # HANGUL SYLLABLE SSANGKIYEOK YA RIEULHIEUH +U+AE94(2);; # HANGUL SYLLABLE SSANGKIYEOK YA MIEUM +U+AE95(2);; # HANGUL SYLLABLE SSANGKIYEOK YA PIEUP +U+AE96(2);; # HANGUL SYLLABLE SSANGKIYEOK YA PIEUPSIOS +U+AE97(2);; # HANGUL SYLLABLE SSANGKIYEOK YA SIOS +U+AE98(2);; # HANGUL SYLLABLE SSANGKIYEOK YA SSANGSIOS +U+AE99(2);; # HANGUL SYLLABLE SSANGKIYEOK YA IEUNG +U+AE9A(2);; # HANGUL SYLLABLE SSANGKIYEOK YA CIEUC +U+AE9B(2);; # HANGUL SYLLABLE SSANGKIYEOK YA CHIEUCH +U+AE9C(2);; # HANGUL SYLLABLE SSANGKIYEOK YA KHIEUKH +U+AE9D(2);; # HANGUL SYLLABLE SSANGKIYEOK YA THIEUTH +U+AE9E(2);; # HANGUL SYLLABLE SSANGKIYEOK YA PHIEUPH +U+AE9F(2);; # HANGUL SYLLABLE SSANGKIYEOK YA HIEUH +U+AEA0(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE +U+AEA1(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE KIYEOK +U+AEA2(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE SSANGKIYEOK +U+AEA3(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE KIYEOKSIOS +U+AEA4(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE NIEUN +U+AEA5(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE NIEUNCIEUC +U+AEA6(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE NIEUNHIEUH +U+AEA7(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE TIKEUT +U+AEA8(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEUL +U+AEA9(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULKIYEOK +U+AEAA(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULMIEUM +U+AEAB(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULPIEUP +U+AEAC(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULSIOS +U+AEAD(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULTHIEUTH +U+AEAE(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULPHIEUPH +U+AEAF(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE RIEULHIEUH +U+AEB0(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE MIEUM +U+AEB1(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE PIEUP +U+AEB2(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE PIEUPSIOS +U+AEB3(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE SIOS +U+AEB4(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE SSANGSIOS +U+AEB5(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE IEUNG +U+AEB6(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE CIEUC +U+AEB7(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE CHIEUCH +U+AEB8(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE KHIEUKH +U+AEB9(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE THIEUTH +U+AEBA(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE PHIEUPH +U+AEBB(2);; # HANGUL SYLLABLE SSANGKIYEOK YAE HIEUH +U+AEBC(2);; # HANGUL SYLLABLE SSANGKIYEOK EO * +U+AEBD(2);; # HANGUL SYLLABLE SSANGKIYEOK EO KIYEOK * +U+AEBE(2);; # HANGUL SYLLABLE SSANGKIYEOK EO SSANGKIYEOK * +U+AEBF(2);; # HANGUL SYLLABLE SSANGKIYEOK EO KIYEOKSIOS +U+AEC0(2);; # HANGUL SYLLABLE SSANGKIYEOK EO NIEUN * +U+AEC1(2);; # HANGUL SYLLABLE SSANGKIYEOK EO NIEUNCIEUC +U+AEC2(2);; # HANGUL SYLLABLE SSANGKIYEOK EO NIEUNHIEUH +U+AEC3(2);; # HANGUL SYLLABLE SSANGKIYEOK EO TIKEUT +U+AEC4(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEUL * +U+AEC5(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULKIYEOK +U+AEC6(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULMIEUM +U+AEC7(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULPIEUP +U+AEC8(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULSIOS +U+AEC9(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULTHIEUTH +U+AECA(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULPHIEUPH +U+AECB(2);; # HANGUL SYLLABLE SSANGKIYEOK EO RIEULHIEUH +U+AECC(2);; # HANGUL SYLLABLE SSANGKIYEOK EO MIEUM * +U+AECD(2);; # HANGUL SYLLABLE SSANGKIYEOK EO PIEUP * +U+AECE(2);; # HANGUL SYLLABLE SSANGKIYEOK EO PIEUPSIOS +U+AECF(2);; # HANGUL SYLLABLE SSANGKIYEOK EO SIOS * +U+AED0(2);; # HANGUL SYLLABLE SSANGKIYEOK EO SSANGSIOS * +U+AED1(2);; # HANGUL SYLLABLE SSANGKIYEOK EO IEUNG * +U+AED2(2);; # HANGUL SYLLABLE SSANGKIYEOK EO CIEUC +U+AED3(2);; # HANGUL SYLLABLE SSANGKIYEOK EO CHIEUCH +U+AED4(2);; # HANGUL SYLLABLE SSANGKIYEOK EO KHIEUKH +U+AED5(2);; # HANGUL SYLLABLE SSANGKIYEOK EO THIEUTH +U+AED6(2);; # HANGUL SYLLABLE SSANGKIYEOK EO PHIEUPH +U+AED7(2);; # HANGUL SYLLABLE SSANGKIYEOK EO HIEUH +U+AED8(2);; # HANGUL SYLLABLE SSANGKIYEOK E * +U+AED9(2);; # HANGUL SYLLABLE SSANGKIYEOK E KIYEOK * +U+AEDA(2);; # HANGUL SYLLABLE SSANGKIYEOK E SSANGKIYEOK +U+AEDB(2);; # HANGUL SYLLABLE SSANGKIYEOK E KIYEOKSIOS +U+AEDC(2);; # HANGUL SYLLABLE SSANGKIYEOK E NIEUN * +U+AEDD(2);; # HANGUL SYLLABLE SSANGKIYEOK E NIEUNCIEUC +U+AEDE(2);; # HANGUL SYLLABLE SSANGKIYEOK E NIEUNHIEUH +U+AEDF(2);; # HANGUL SYLLABLE SSANGKIYEOK E TIKEUT +U+AEE0(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEUL +U+AEE1(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULKIYEOK +U+AEE2(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULMIEUM +U+AEE3(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULPIEUP +U+AEE4(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULSIOS +U+AEE5(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULTHIEUTH +U+AEE6(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULPHIEUPH +U+AEE7(2);; # HANGUL SYLLABLE SSANGKIYEOK E RIEULHIEUH +U+AEE8(2);; # HANGUL SYLLABLE SSANGKIYEOK E MIEUM * +U+AEE9(2);; # HANGUL SYLLABLE SSANGKIYEOK E PIEUP +U+AEEA(2);; # HANGUL SYLLABLE SSANGKIYEOK E PIEUPSIOS +U+AEEB(2);; # HANGUL SYLLABLE SSANGKIYEOK E SIOS * +U+AEEC(2);; # HANGUL SYLLABLE SSANGKIYEOK E SSANGSIOS +U+AEED(2);; # HANGUL SYLLABLE SSANGKIYEOK E IEUNG * +U+AEEE(2);; # HANGUL SYLLABLE SSANGKIYEOK E CIEUC +U+AEEF(2);; # HANGUL SYLLABLE SSANGKIYEOK E CHIEUCH +U+AEF0(2);; # HANGUL SYLLABLE SSANGKIYEOK E KHIEUKH +U+AEF1(2);; # HANGUL SYLLABLE SSANGKIYEOK E THIEUTH +U+AEF2(2);; # HANGUL SYLLABLE SSANGKIYEOK E PHIEUPH +U+AEF3(2);; # HANGUL SYLLABLE SSANGKIYEOK E HIEUH +U+AEF4(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO * +U+AEF5(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO KIYEOK +U+AEF6(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO SSANGKIYEOK +U+AEF7(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO KIYEOKSIOS +U+AEF8(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO NIEUN * +U+AEF9(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO NIEUNCIEUC +U+AEFA(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO NIEUNHIEUH +U+AEFB(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO TIKEUT +U+AEFC(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEUL * +U+AEFD(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULKIYEOK +U+AEFE(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULMIEUM +U+AEFF(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULPIEUP +U+AF00(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULSIOS +U+AF01(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULTHIEUTH +U+AF02(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULPHIEUPH +U+AF03(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO RIEULHIEUH +U+AF04(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO MIEUM +U+AF05(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO PIEUP +U+AF06(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO PIEUPSIOS +U+AF07(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO SIOS * +U+AF08(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO SSANGSIOS * +U+AF09(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO IEUNG +U+AF0A(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO CIEUC +U+AF0B(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO CHIEUCH +U+AF0C(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO KHIEUKH +U+AF0D(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO THIEUTH * +U+AF0E(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO PHIEUPH +U+AF0F(2);; # HANGUL SYLLABLE SSANGKIYEOK YEO HIEUH +U+AF10(2);; # HANGUL SYLLABLE SSANGKIYEOK YE * +U+AF11(2);; # HANGUL SYLLABLE SSANGKIYEOK YE KIYEOK +U+AF12(2);; # HANGUL SYLLABLE SSANGKIYEOK YE SSANGKIYEOK +U+AF13(2);; # HANGUL SYLLABLE SSANGKIYEOK YE KIYEOKSIOS +U+AF14(2);; # HANGUL SYLLABLE SSANGKIYEOK YE NIEUN +U+AF15(2);; # HANGUL SYLLABLE SSANGKIYEOK YE NIEUNCIEUC +U+AF16(2);; # HANGUL SYLLABLE SSANGKIYEOK YE NIEUNHIEUH +U+AF17(2);; # HANGUL SYLLABLE SSANGKIYEOK YE TIKEUT +U+AF18(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEUL +U+AF19(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULKIYEOK +U+AF1A(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULMIEUM +U+AF1B(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULPIEUP +U+AF1C(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULSIOS +U+AF1D(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULTHIEUTH +U+AF1E(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULPHIEUPH +U+AF1F(2);; # HANGUL SYLLABLE SSANGKIYEOK YE RIEULHIEUH +U+AF20(2);; # HANGUL SYLLABLE SSANGKIYEOK YE MIEUM +U+AF21(2);; # HANGUL SYLLABLE SSANGKIYEOK YE PIEUP +U+AF22(2);; # HANGUL SYLLABLE SSANGKIYEOK YE PIEUPSIOS +U+AF23(2);; # HANGUL SYLLABLE SSANGKIYEOK YE SIOS +U+AF24(2);; # HANGUL SYLLABLE SSANGKIYEOK YE SSANGSIOS +U+AF25(2);; # HANGUL SYLLABLE SSANGKIYEOK YE IEUNG +U+AF26(2);; # HANGUL SYLLABLE SSANGKIYEOK YE CIEUC +U+AF27(2);; # HANGUL SYLLABLE SSANGKIYEOK YE CHIEUCH +U+AF28(2);; # HANGUL SYLLABLE SSANGKIYEOK YE KHIEUKH +U+AF29(2);; # HANGUL SYLLABLE SSANGKIYEOK YE THIEUTH +U+AF2A(2);; # HANGUL SYLLABLE SSANGKIYEOK YE PHIEUPH +U+AF2B(2);; # HANGUL SYLLABLE SSANGKIYEOK YE HIEUH +U+AF2C(2);; # HANGUL SYLLABLE SSANGKIYEOK O * +U+AF2D(2);; # HANGUL SYLLABLE SSANGKIYEOK O KIYEOK * +U+AF2E(2);; # HANGUL SYLLABLE SSANGKIYEOK O SSANGKIYEOK +U+AF2F(2);; # HANGUL SYLLABLE SSANGKIYEOK O KIYEOKSIOS +U+AF30(2);; # HANGUL SYLLABLE SSANGKIYEOK O NIEUN * +U+AF31(2);; # HANGUL SYLLABLE SSANGKIYEOK O NIEUNCIEUC +U+AF32(2);; # HANGUL SYLLABLE SSANGKIYEOK O NIEUNHIEUH * +U+AF33(2);; # HANGUL SYLLABLE SSANGKIYEOK O TIKEUT +U+AF34(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEUL * +U+AF35(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULKIYEOK +U+AF36(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULMIEUM +U+AF37(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULPIEUP +U+AF38(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULSIOS +U+AF39(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULTHIEUTH +U+AF3A(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULPHIEUPH +U+AF3B(2);; # HANGUL SYLLABLE SSANGKIYEOK O RIEULHIEUH +U+AF3C(2);; # HANGUL SYLLABLE SSANGKIYEOK O MIEUM * +U+AF3D(2);; # HANGUL SYLLABLE SSANGKIYEOK O PIEUP * +U+AF3E(2);; # HANGUL SYLLABLE SSANGKIYEOK O PIEUPSIOS +U+AF3F(2);; # HANGUL SYLLABLE SSANGKIYEOK O SIOS * +U+AF40(2);; # HANGUL SYLLABLE SSANGKIYEOK O SSANGSIOS +U+AF41(2);; # HANGUL SYLLABLE SSANGKIYEOK O IEUNG * +U+AF42(2);; # HANGUL SYLLABLE SSANGKIYEOK O CIEUC * +U+AF43(2);; # HANGUL SYLLABLE SSANGKIYEOK O CHIEUCH * +U+AF44(2);; # HANGUL SYLLABLE SSANGKIYEOK O KHIEUKH +U+AF45(2);; # HANGUL SYLLABLE SSANGKIYEOK O THIEUTH +U+AF46(2);; # HANGUL SYLLABLE SSANGKIYEOK O PHIEUPH +U+AF47(2);; # HANGUL SYLLABLE SSANGKIYEOK O HIEUH +U+AF48(2);; # HANGUL SYLLABLE SSANGKIYEOK WA * +U+AF49(2);; # HANGUL SYLLABLE SSANGKIYEOK WA KIYEOK * +U+AF4A(2);; # HANGUL SYLLABLE SSANGKIYEOK WA SSANGKIYEOK +U+AF4B(2);; # HANGUL SYLLABLE SSANGKIYEOK WA KIYEOKSIOS +U+AF4C(2);; # HANGUL SYLLABLE SSANGKIYEOK WA NIEUN +U+AF4D(2);; # HANGUL SYLLABLE SSANGKIYEOK WA NIEUNCIEUC +U+AF4E(2);; # HANGUL SYLLABLE SSANGKIYEOK WA NIEUNHIEUH +U+AF4F(2);; # HANGUL SYLLABLE SSANGKIYEOK WA TIKEUT +U+AF50(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEUL * +U+AF51(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULKIYEOK +U+AF52(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULMIEUM +U+AF53(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULPIEUP +U+AF54(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULSIOS +U+AF55(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULTHIEUTH +U+AF56(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULPHIEUPH +U+AF57(2);; # HANGUL SYLLABLE SSANGKIYEOK WA RIEULHIEUH +U+AF58(2);; # HANGUL SYLLABLE SSANGKIYEOK WA MIEUM +U+AF59(2);; # HANGUL SYLLABLE SSANGKIYEOK WA PIEUP +U+AF5A(2);; # HANGUL SYLLABLE SSANGKIYEOK WA PIEUPSIOS +U+AF5B(2);; # HANGUL SYLLABLE SSANGKIYEOK WA SIOS +U+AF5C(2);; # HANGUL SYLLABLE SSANGKIYEOK WA SSANGSIOS * +U+AF5D(2);; # HANGUL SYLLABLE SSANGKIYEOK WA IEUNG * +U+AF5E(2);; # HANGUL SYLLABLE SSANGKIYEOK WA CIEUC +U+AF5F(2);; # HANGUL SYLLABLE SSANGKIYEOK WA CHIEUCH +U+AF60(2);; # HANGUL SYLLABLE SSANGKIYEOK WA KHIEUKH +U+AF61(2);; # HANGUL SYLLABLE SSANGKIYEOK WA THIEUTH +U+AF62(2);; # HANGUL SYLLABLE SSANGKIYEOK WA PHIEUPH +U+AF63(2);; # HANGUL SYLLABLE SSANGKIYEOK WA HIEUH +U+AF64(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE * +U+AF65(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE KIYEOK * +U+AF66(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE SSANGKIYEOK +U+AF67(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE KIYEOKSIOS +U+AF68(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE NIEUN +U+AF69(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE NIEUNCIEUC +U+AF6A(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE NIEUNHIEUH +U+AF6B(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE TIKEUT +U+AF6C(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEUL +U+AF6D(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULKIYEOK +U+AF6E(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULMIEUM +U+AF6F(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULPIEUP +U+AF70(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULSIOS +U+AF71(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULTHIEUTH +U+AF72(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULPHIEUPH +U+AF73(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE RIEULHIEUH +U+AF74(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE MIEUM +U+AF75(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE PIEUP +U+AF76(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE PIEUPSIOS +U+AF77(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE SIOS +U+AF78(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE SSANGSIOS +U+AF79(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE IEUNG * +U+AF7A(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE CIEUC +U+AF7B(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE CHIEUCH +U+AF7C(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE KHIEUKH +U+AF7D(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE THIEUTH +U+AF7E(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE PHIEUPH +U+AF7F(2);; # HANGUL SYLLABLE SSANGKIYEOK WAE HIEUH +U+AF80(2);; # HANGUL SYLLABLE SSANGKIYEOK OE * +U+AF81(2);; # HANGUL SYLLABLE SSANGKIYEOK OE KIYEOK +U+AF82(2);; # HANGUL SYLLABLE SSANGKIYEOK OE SSANGKIYEOK +U+AF83(2);; # HANGUL SYLLABLE SSANGKIYEOK OE KIYEOKSIOS +U+AF84(2);; # HANGUL SYLLABLE SSANGKIYEOK OE NIEUN * +U+AF85(2);; # HANGUL SYLLABLE SSANGKIYEOK OE NIEUNCIEUC +U+AF86(2);; # HANGUL SYLLABLE SSANGKIYEOK OE NIEUNHIEUH +U+AF87(2);; # HANGUL SYLLABLE SSANGKIYEOK OE TIKEUT +U+AF88(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEUL * +U+AF89(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULKIYEOK +U+AF8A(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULMIEUM +U+AF8B(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULPIEUP +U+AF8C(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULSIOS +U+AF8D(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULTHIEUTH +U+AF8E(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULPHIEUPH +U+AF8F(2);; # HANGUL SYLLABLE SSANGKIYEOK OE RIEULHIEUH +U+AF90(2);; # HANGUL SYLLABLE SSANGKIYEOK OE MIEUM * +U+AF91(2);; # HANGUL SYLLABLE SSANGKIYEOK OE PIEUP * +U+AF92(2);; # HANGUL SYLLABLE SSANGKIYEOK OE PIEUPSIOS +U+AF93(2);; # HANGUL SYLLABLE SSANGKIYEOK OE SIOS +U+AF94(2);; # HANGUL SYLLABLE SSANGKIYEOK OE SSANGSIOS +U+AF95(2);; # HANGUL SYLLABLE SSANGKIYEOK OE IEUNG * +U+AF96(2);; # HANGUL SYLLABLE SSANGKIYEOK OE CIEUC +U+AF97(2);; # HANGUL SYLLABLE SSANGKIYEOK OE CHIEUCH +U+AF98(2);; # HANGUL SYLLABLE SSANGKIYEOK OE KHIEUKH +U+AF99(2);; # HANGUL SYLLABLE SSANGKIYEOK OE THIEUTH +U+AF9A(2);; # HANGUL SYLLABLE SSANGKIYEOK OE PHIEUPH +U+AF9B(2);; # HANGUL SYLLABLE SSANGKIYEOK OE HIEUH +U+AF9C(2);; # HANGUL SYLLABLE SSANGKIYEOK YO * +U+AF9D(2);; # HANGUL SYLLABLE SSANGKIYEOK YO KIYEOK +U+AF9E(2);; # HANGUL SYLLABLE SSANGKIYEOK YO SSANGKIYEOK +U+AF9F(2);; # HANGUL SYLLABLE SSANGKIYEOK YO KIYEOKSIOS +U+AFA0(2);; # HANGUL SYLLABLE SSANGKIYEOK YO NIEUN +U+AFA1(2);; # HANGUL SYLLABLE SSANGKIYEOK YO NIEUNCIEUC +U+AFA2(2);; # HANGUL SYLLABLE SSANGKIYEOK YO NIEUNHIEUH +U+AFA3(2);; # HANGUL SYLLABLE SSANGKIYEOK YO TIKEUT +U+AFA4(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEUL +U+AFA5(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULKIYEOK +U+AFA6(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULMIEUM +U+AFA7(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULPIEUP +U+AFA8(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULSIOS +U+AFA9(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULTHIEUTH +U+AFAA(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULPHIEUPH +U+AFAB(2);; # HANGUL SYLLABLE SSANGKIYEOK YO RIEULHIEUH +U+AFAC(2);; # HANGUL SYLLABLE SSANGKIYEOK YO MIEUM +U+AFAD(2);; # HANGUL SYLLABLE SSANGKIYEOK YO PIEUP +U+AFAE(2);; # HANGUL SYLLABLE SSANGKIYEOK YO PIEUPSIOS +U+AFAF(2);; # HANGUL SYLLABLE SSANGKIYEOK YO SIOS +U+AFB0(2);; # HANGUL SYLLABLE SSANGKIYEOK YO SSANGSIOS +U+AFB1(2);; # HANGUL SYLLABLE SSANGKIYEOK YO IEUNG +U+AFB2(2);; # HANGUL SYLLABLE SSANGKIYEOK YO CIEUC +U+AFB3(2);; # HANGUL SYLLABLE SSANGKIYEOK YO CHIEUCH +U+AFB4(2);; # HANGUL SYLLABLE SSANGKIYEOK YO KHIEUKH +U+AFB5(2);; # HANGUL SYLLABLE SSANGKIYEOK YO THIEUTH +U+AFB6(2);; # HANGUL SYLLABLE SSANGKIYEOK YO PHIEUPH +U+AFB7(2);; # HANGUL SYLLABLE SSANGKIYEOK YO HIEUH +U+AFB8(2);; # HANGUL SYLLABLE SSANGKIYEOK U * +U+AFB9(2);; # HANGUL SYLLABLE SSANGKIYEOK U KIYEOK * +U+AFBA(2);; # HANGUL SYLLABLE SSANGKIYEOK U SSANGKIYEOK +U+AFBB(2);; # HANGUL SYLLABLE SSANGKIYEOK U KIYEOKSIOS +U+AFBC(2);; # HANGUL SYLLABLE SSANGKIYEOK U NIEUN * +U+AFBD(2);; # HANGUL SYLLABLE SSANGKIYEOK U NIEUNCIEUC +U+AFBE(2);; # HANGUL SYLLABLE SSANGKIYEOK U NIEUNHIEUH +U+AFBF(2);; # HANGUL SYLLABLE SSANGKIYEOK U TIKEUT +U+AFC0(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEUL * +U+AFC1(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULKIYEOK +U+AFC2(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULMIEUM +U+AFC3(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULPIEUP +U+AFC4(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULSIOS +U+AFC5(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULTHIEUTH +U+AFC6(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULPHIEUPH +U+AFC7(2);; # HANGUL SYLLABLE SSANGKIYEOK U RIEULHIEUH * +U+AFC8(2);; # HANGUL SYLLABLE SSANGKIYEOK U MIEUM * +U+AFC9(2);; # HANGUL SYLLABLE SSANGKIYEOK U PIEUP * +U+AFCA(2);; # HANGUL SYLLABLE SSANGKIYEOK U PIEUPSIOS +U+AFCB(2);; # HANGUL SYLLABLE SSANGKIYEOK U SIOS * +U+AFCC(2);; # HANGUL SYLLABLE SSANGKIYEOK U SSANGSIOS +U+AFCD(2);; # HANGUL SYLLABLE SSANGKIYEOK U IEUNG * +U+AFCE(2);; # HANGUL SYLLABLE SSANGKIYEOK U CIEUC * +U+AFCF(2);; # HANGUL SYLLABLE SSANGKIYEOK U CHIEUCH +U+AFD0(2);; # HANGUL SYLLABLE SSANGKIYEOK U KHIEUKH +U+AFD1(2);; # HANGUL SYLLABLE SSANGKIYEOK U THIEUTH +U+AFD2(2);; # HANGUL SYLLABLE SSANGKIYEOK U PHIEUPH +U+AFD3(2);; # HANGUL SYLLABLE SSANGKIYEOK U HIEUH +U+AFD4(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO * +U+AFD5(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO KIYEOK +U+AFD6(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO SSANGKIYEOK +U+AFD7(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO KIYEOKSIOS +U+AFD8(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO NIEUN +U+AFD9(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO NIEUNCIEUC +U+AFDA(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO NIEUNHIEUH +U+AFDB(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO TIKEUT +U+AFDC(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEUL * +U+AFDD(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULKIYEOK +U+AFDE(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULMIEUM +U+AFDF(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULPIEUP +U+AFE0(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULSIOS +U+AFE1(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULTHIEUTH +U+AFE2(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULPHIEUPH +U+AFE3(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO RIEULHIEUH +U+AFE4(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO MIEUM +U+AFE5(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO PIEUP +U+AFE6(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO PIEUPSIOS +U+AFE7(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO SIOS +U+AFE8(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO SSANGSIOS * +U+AFE9(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO IEUNG * +U+AFEA(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO CIEUC +U+AFEB(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO CHIEUCH +U+AFEC(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO KHIEUKH +U+AFED(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO THIEUTH +U+AFEE(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO PHIEUPH +U+AFEF(2);; # HANGUL SYLLABLE SSANGKIYEOK WEO HIEUH +U+AFF0(2);; # HANGUL SYLLABLE SSANGKIYEOK WE * +U+AFF1(2);; # HANGUL SYLLABLE SSANGKIYEOK WE KIYEOK * +U+AFF2(2);; # HANGUL SYLLABLE SSANGKIYEOK WE SSANGKIYEOK +U+AFF3(2);; # HANGUL SYLLABLE SSANGKIYEOK WE KIYEOKSIOS +U+AFF4(2);; # HANGUL SYLLABLE SSANGKIYEOK WE NIEUN * +U+AFF5(2);; # HANGUL SYLLABLE SSANGKIYEOK WE NIEUNCIEUC +U+AFF6(2);; # HANGUL SYLLABLE SSANGKIYEOK WE NIEUNHIEUH +U+AFF7(2);; # HANGUL SYLLABLE SSANGKIYEOK WE TIKEUT +U+AFF8(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEUL * +U+AFF9(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULKIYEOK +U+AFFA(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULMIEUM +U+AFFB(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULPIEUP +U+AFFC(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULSIOS +U+AFFD(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULTHIEUTH +U+AFFE(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULPHIEUPH +U+AFFF(2);; # HANGUL SYLLABLE SSANGKIYEOK WE RIEULHIEUH +U+B000(2);; # HANGUL SYLLABLE SSANGKIYEOK WE MIEUM * +U+B001(2);; # HANGUL SYLLABLE SSANGKIYEOK WE PIEUP * +U+B002(2);; # HANGUL SYLLABLE SSANGKIYEOK WE PIEUPSIOS +U+B003(2);; # HANGUL SYLLABLE SSANGKIYEOK WE SIOS +U+B004(2);; # HANGUL SYLLABLE SSANGKIYEOK WE SSANGSIOS * +U+B005(2);; # HANGUL SYLLABLE SSANGKIYEOK WE IEUNG +U+B006(2);; # HANGUL SYLLABLE SSANGKIYEOK WE CIEUC +U+B007(2);; # HANGUL SYLLABLE SSANGKIYEOK WE CHIEUCH +U+B008(2);; # HANGUL SYLLABLE SSANGKIYEOK WE KHIEUKH +U+B009(2);; # HANGUL SYLLABLE SSANGKIYEOK WE THIEUTH +U+B00A(2);; # HANGUL SYLLABLE SSANGKIYEOK WE PHIEUPH +U+B00B(2);; # HANGUL SYLLABLE SSANGKIYEOK WE HIEUH +U+B00C(2);; # HANGUL SYLLABLE SSANGKIYEOK WI * +U+B00D(2);; # HANGUL SYLLABLE SSANGKIYEOK WI KIYEOK +U+B00E(2);; # HANGUL SYLLABLE SSANGKIYEOK WI SSANGKIYEOK +U+B00F(2);; # HANGUL SYLLABLE SSANGKIYEOK WI KIYEOKSIOS +U+B010(2);; # HANGUL SYLLABLE SSANGKIYEOK WI NIEUN * +U+B011(2);; # HANGUL SYLLABLE SSANGKIYEOK WI NIEUNCIEUC +U+B012(2);; # HANGUL SYLLABLE SSANGKIYEOK WI NIEUNHIEUH +U+B013(2);; # HANGUL SYLLABLE SSANGKIYEOK WI TIKEUT +U+B014(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEUL * +U+B015(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULKIYEOK +U+B016(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULMIEUM +U+B017(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULPIEUP +U+B018(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULSIOS +U+B019(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULTHIEUTH +U+B01A(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULPHIEUPH +U+B01B(2);; # HANGUL SYLLABLE SSANGKIYEOK WI RIEULHIEUH +U+B01C(2);; # HANGUL SYLLABLE SSANGKIYEOK WI MIEUM * +U+B01D(2);; # HANGUL SYLLABLE SSANGKIYEOK WI PIEUP * +U+B01E(2);; # HANGUL SYLLABLE SSANGKIYEOK WI PIEUPSIOS +U+B01F(2);; # HANGUL SYLLABLE SSANGKIYEOK WI SIOS +U+B020(2);; # HANGUL SYLLABLE SSANGKIYEOK WI SSANGSIOS +U+B021(2);; # HANGUL SYLLABLE SSANGKIYEOK WI IEUNG +U+B022(2);; # HANGUL SYLLABLE SSANGKIYEOK WI CIEUC +U+B023(2);; # HANGUL SYLLABLE SSANGKIYEOK WI CHIEUCH +U+B024(2);; # HANGUL SYLLABLE SSANGKIYEOK WI KHIEUKH +U+B025(2);; # HANGUL SYLLABLE SSANGKIYEOK WI THIEUTH +U+B026(2);; # HANGUL SYLLABLE SSANGKIYEOK WI PHIEUPH +U+B027(2);; # HANGUL SYLLABLE SSANGKIYEOK WI HIEUH +U+B028(2);; # HANGUL SYLLABLE SSANGKIYEOK YU * +U+B029(2);; # HANGUL SYLLABLE SSANGKIYEOK YU KIYEOK +U+B02A(2);; # HANGUL SYLLABLE SSANGKIYEOK YU SSANGKIYEOK +U+B02B(2);; # HANGUL SYLLABLE SSANGKIYEOK YU KIYEOKSIOS +U+B02C(2);; # HANGUL SYLLABLE SSANGKIYEOK YU NIEUN +U+B02D(2);; # HANGUL SYLLABLE SSANGKIYEOK YU NIEUNCIEUC +U+B02E(2);; # HANGUL SYLLABLE SSANGKIYEOK YU NIEUNHIEUH +U+B02F(2);; # HANGUL SYLLABLE SSANGKIYEOK YU TIKEUT +U+B030(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEUL +U+B031(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULKIYEOK +U+B032(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULMIEUM +U+B033(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULPIEUP +U+B034(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULSIOS +U+B035(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULTHIEUTH +U+B036(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULPHIEUPH +U+B037(2);; # HANGUL SYLLABLE SSANGKIYEOK YU RIEULHIEUH +U+B038(2);; # HANGUL SYLLABLE SSANGKIYEOK YU MIEUM +U+B039(2);; # HANGUL SYLLABLE SSANGKIYEOK YU PIEUP +U+B03A(2);; # HANGUL SYLLABLE SSANGKIYEOK YU PIEUPSIOS +U+B03B(2);; # HANGUL SYLLABLE SSANGKIYEOK YU SIOS +U+B03C(2);; # HANGUL SYLLABLE SSANGKIYEOK YU SSANGSIOS +U+B03D(2);; # HANGUL SYLLABLE SSANGKIYEOK YU IEUNG +U+B03E(2);; # HANGUL SYLLABLE SSANGKIYEOK YU CIEUC +U+B03F(2);; # HANGUL SYLLABLE SSANGKIYEOK YU CHIEUCH +U+B040(2);; # HANGUL SYLLABLE SSANGKIYEOK YU KHIEUKH +U+B041(2);; # HANGUL SYLLABLE SSANGKIYEOK YU THIEUTH +U+B042(2);; # HANGUL SYLLABLE SSANGKIYEOK YU PHIEUPH +U+B043(2);; # HANGUL SYLLABLE SSANGKIYEOK YU HIEUH +U+B044(2);; # HANGUL SYLLABLE SSANGKIYEOK EU * +U+B045(2);; # HANGUL SYLLABLE SSANGKIYEOK EU KIYEOK * +U+B046(2);; # HANGUL SYLLABLE SSANGKIYEOK EU SSANGKIYEOK +U+B047(2);; # HANGUL SYLLABLE SSANGKIYEOK EU KIYEOKSIOS +U+B048(2);; # HANGUL SYLLABLE SSANGKIYEOK EU NIEUN * +U+B049(2);; # HANGUL SYLLABLE SSANGKIYEOK EU NIEUNCIEUC +U+B04A(2);; # HANGUL SYLLABLE SSANGKIYEOK EU NIEUNHIEUH * +U+B04B(2);; # HANGUL SYLLABLE SSANGKIYEOK EU TIKEUT +U+B04C(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEUL * +U+B04D(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULKIYEOK +U+B04E(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULMIEUM * +U+B04F(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULPIEUP +U+B050(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULSIOS +U+B051(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULTHIEUTH +U+B052(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULPHIEUPH +U+B053(2);; # HANGUL SYLLABLE SSANGKIYEOK EU RIEULHIEUH * +U+B054(2);; # HANGUL SYLLABLE SSANGKIYEOK EU MIEUM * +U+B055(2);; # HANGUL SYLLABLE SSANGKIYEOK EU PIEUP * +U+B056(2);; # HANGUL SYLLABLE SSANGKIYEOK EU PIEUPSIOS +U+B057(2);; # HANGUL SYLLABLE SSANGKIYEOK EU SIOS * +U+B058(2);; # HANGUL SYLLABLE SSANGKIYEOK EU SSANGSIOS +U+B059(2);; # HANGUL SYLLABLE SSANGKIYEOK EU IEUNG * +U+B05A(2);; # HANGUL SYLLABLE SSANGKIYEOK EU CIEUC +U+B05B(2);; # HANGUL SYLLABLE SSANGKIYEOK EU CHIEUCH +U+B05C(2);; # HANGUL SYLLABLE SSANGKIYEOK EU KHIEUKH +U+B05D(2);; # HANGUL SYLLABLE SSANGKIYEOK EU THIEUTH * +U+B05E(2);; # HANGUL SYLLABLE SSANGKIYEOK EU PHIEUPH +U+B05F(2);; # HANGUL SYLLABLE SSANGKIYEOK EU HIEUH +U+B060(2);; # HANGUL SYLLABLE SSANGKIYEOK YI +U+B061(2);; # HANGUL SYLLABLE SSANGKIYEOK YI KIYEOK +U+B062(2);; # HANGUL SYLLABLE SSANGKIYEOK YI SSANGKIYEOK +U+B063(2);; # HANGUL SYLLABLE SSANGKIYEOK YI KIYEOKSIOS +U+B064(2);; # HANGUL SYLLABLE SSANGKIYEOK YI NIEUN +U+B065(2);; # HANGUL SYLLABLE SSANGKIYEOK YI NIEUNCIEUC +U+B066(2);; # HANGUL SYLLABLE SSANGKIYEOK YI NIEUNHIEUH +U+B067(2);; # HANGUL SYLLABLE SSANGKIYEOK YI TIKEUT +U+B068(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEUL +U+B069(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULKIYEOK +U+B06A(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULMIEUM +U+B06B(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULPIEUP +U+B06C(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULSIOS +U+B06D(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULTHIEUTH +U+B06E(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULPHIEUPH +U+B06F(2);; # HANGUL SYLLABLE SSANGKIYEOK YI RIEULHIEUH +U+B070(2);; # HANGUL SYLLABLE SSANGKIYEOK YI MIEUM +U+B071(2);; # HANGUL SYLLABLE SSANGKIYEOK YI PIEUP +U+B072(2);; # HANGUL SYLLABLE SSANGKIYEOK YI PIEUPSIOS +U+B073(2);; # HANGUL SYLLABLE SSANGKIYEOK YI SIOS +U+B074(2);; # HANGUL SYLLABLE SSANGKIYEOK YI SSANGSIOS +U+B075(2);; # HANGUL SYLLABLE SSANGKIYEOK YI IEUNG +U+B076(2);; # HANGUL SYLLABLE SSANGKIYEOK YI CIEUC +U+B077(2);; # HANGUL SYLLABLE SSANGKIYEOK YI CHIEUCH +U+B078(2);; # HANGUL SYLLABLE SSANGKIYEOK YI KHIEUKH +U+B079(2);; # HANGUL SYLLABLE SSANGKIYEOK YI THIEUTH +U+B07A(2);; # HANGUL SYLLABLE SSANGKIYEOK YI PHIEUPH +U+B07B(2);; # HANGUL SYLLABLE SSANGKIYEOK YI HIEUH +U+B07C(2);; # HANGUL SYLLABLE SSANGKIYEOK I * +U+B07D(2);; # HANGUL SYLLABLE SSANGKIYEOK I KIYEOK * +U+B07E(2);; # HANGUL SYLLABLE SSANGKIYEOK I SSANGKIYEOK +U+B07F(2);; # HANGUL SYLLABLE SSANGKIYEOK I KIYEOKSIOS +U+B080(2);; # HANGUL SYLLABLE SSANGKIYEOK I NIEUN * +U+B081(2);; # HANGUL SYLLABLE SSANGKIYEOK I NIEUNCIEUC +U+B082(2);; # HANGUL SYLLABLE SSANGKIYEOK I NIEUNHIEUH +U+B083(2);; # HANGUL SYLLABLE SSANGKIYEOK I TIKEUT +U+B084(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEUL * +U+B085(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULKIYEOK +U+B086(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULMIEUM +U+B087(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULPIEUP +U+B088(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULSIOS +U+B089(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULTHIEUTH +U+B08A(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULPHIEUPH +U+B08B(2);; # HANGUL SYLLABLE SSANGKIYEOK I RIEULHIEUH +U+B08C(2);; # HANGUL SYLLABLE SSANGKIYEOK I MIEUM * +U+B08D(2);; # HANGUL SYLLABLE SSANGKIYEOK I PIEUP * +U+B08E(2);; # HANGUL SYLLABLE SSANGKIYEOK I PIEUPSIOS +U+B08F(2);; # HANGUL SYLLABLE SSANGKIYEOK I SIOS * +U+B090(2);; # HANGUL SYLLABLE SSANGKIYEOK I SSANGSIOS +U+B091(2);; # HANGUL SYLLABLE SSANGKIYEOK I IEUNG * +U+B092(2);; # HANGUL SYLLABLE SSANGKIYEOK I CIEUC +U+B093(2);; # HANGUL SYLLABLE SSANGKIYEOK I CHIEUCH +U+B094(2);; # HANGUL SYLLABLE SSANGKIYEOK I KHIEUKH +U+B095(2);; # HANGUL SYLLABLE SSANGKIYEOK I THIEUTH +U+B096(2);; # HANGUL SYLLABLE SSANGKIYEOK I PHIEUPH +U+B097(2);; # HANGUL SYLLABLE SSANGKIYEOK I HIEUH +U+B098(2);; # HANGUL SYLLABLE NIEUN A * +U+B099(2);; # HANGUL SYLLABLE NIEUN A KIYEOK * +U+B09A(2);; # HANGUL SYLLABLE NIEUN A SSANGKIYEOK * +U+B09B(2);; # HANGUL SYLLABLE NIEUN A KIYEOKSIOS +U+B09C(2);; # HANGUL SYLLABLE NIEUN A NIEUN * +U+B09D(2);; # HANGUL SYLLABLE NIEUN A NIEUNCIEUC +U+B09E(2);; # HANGUL SYLLABLE NIEUN A NIEUNHIEUH +U+B09F(2);; # HANGUL SYLLABLE NIEUN A TIKEUT * +U+B0A0(2);; # HANGUL SYLLABLE NIEUN A RIEUL * +U+B0A1(2);; # HANGUL SYLLABLE NIEUN A RIEULKIYEOK * +U+B0A2(2);; # HANGUL SYLLABLE NIEUN A RIEULMIEUM * +U+B0A3(2);; # HANGUL SYLLABLE NIEUN A RIEULPIEUP +U+B0A4(2);; # HANGUL SYLLABLE NIEUN A RIEULSIOS +U+B0A5(2);; # HANGUL SYLLABLE NIEUN A RIEULTHIEUTH +U+B0A6(2);; # HANGUL SYLLABLE NIEUN A RIEULPHIEUPH +U+B0A7(2);; # HANGUL SYLLABLE NIEUN A RIEULHIEUH +U+B0A8(2);; # HANGUL SYLLABLE NIEUN A MIEUM * +U+B0A9(2);; # HANGUL SYLLABLE NIEUN A PIEUP * +U+B0AA(2);; # HANGUL SYLLABLE NIEUN A PIEUPSIOS +U+B0AB(2);; # HANGUL SYLLABLE NIEUN A SIOS * +U+B0AC(2);; # HANGUL SYLLABLE NIEUN A SSANGSIOS * +U+B0AD(2);; # HANGUL SYLLABLE NIEUN A IEUNG * +U+B0AE(2);; # HANGUL SYLLABLE NIEUN A CIEUC * +U+B0AF(2);; # HANGUL SYLLABLE NIEUN A CHIEUCH * +U+B0B0(2);; # HANGUL SYLLABLE NIEUN A KHIEUKH +U+B0B1(2);; # HANGUL SYLLABLE NIEUN A THIEUTH * +U+B0B2(2);; # HANGUL SYLLABLE NIEUN A PHIEUPH +U+B0B3(2);; # HANGUL SYLLABLE NIEUN A HIEUH * +U+B0B4(2);; # HANGUL SYLLABLE NIEUN AE * +U+B0B5(2);; # HANGUL SYLLABLE NIEUN AE KIYEOK * +U+B0B6(2);; # HANGUL SYLLABLE NIEUN AE SSANGKIYEOK +U+B0B7(2);; # HANGUL SYLLABLE NIEUN AE KIYEOKSIOS +U+B0B8(2);; # HANGUL SYLLABLE NIEUN AE NIEUN * +U+B0B9(2);; # HANGUL SYLLABLE NIEUN AE NIEUNCIEUC +U+B0BA(2);; # HANGUL SYLLABLE NIEUN AE NIEUNHIEUH +U+B0BB(2);; # HANGUL SYLLABLE NIEUN AE TIKEUT +U+B0BC(2);; # HANGUL SYLLABLE NIEUN AE RIEUL * +U+B0BD(2);; # HANGUL SYLLABLE NIEUN AE RIEULKIYEOK +U+B0BE(2);; # HANGUL SYLLABLE NIEUN AE RIEULMIEUM +U+B0BF(2);; # HANGUL SYLLABLE NIEUN AE RIEULPIEUP +U+B0C0(2);; # HANGUL SYLLABLE NIEUN AE RIEULSIOS +U+B0C1(2);; # HANGUL SYLLABLE NIEUN AE RIEULTHIEUTH +U+B0C2(2);; # HANGUL SYLLABLE NIEUN AE RIEULPHIEUPH +U+B0C3(2);; # HANGUL SYLLABLE NIEUN AE RIEULHIEUH +U+B0C4(2);; # HANGUL SYLLABLE NIEUN AE MIEUM * +U+B0C5(2);; # HANGUL SYLLABLE NIEUN AE PIEUP * +U+B0C6(2);; # HANGUL SYLLABLE NIEUN AE PIEUPSIOS +U+B0C7(2);; # HANGUL SYLLABLE NIEUN AE SIOS * +U+B0C8(2);; # HANGUL SYLLABLE NIEUN AE SSANGSIOS * +U+B0C9(2);; # HANGUL SYLLABLE NIEUN AE IEUNG * +U+B0CA(2);; # HANGUL SYLLABLE NIEUN AE CIEUC +U+B0CB(2);; # HANGUL SYLLABLE NIEUN AE CHIEUCH +U+B0CC(2);; # HANGUL SYLLABLE NIEUN AE KHIEUKH +U+B0CD(2);; # HANGUL SYLLABLE NIEUN AE THIEUTH +U+B0CE(2);; # HANGUL SYLLABLE NIEUN AE PHIEUPH +U+B0CF(2);; # HANGUL SYLLABLE NIEUN AE HIEUH +U+B0D0(2);; # HANGUL SYLLABLE NIEUN YA * +U+B0D1(2);; # HANGUL SYLLABLE NIEUN YA KIYEOK * +U+B0D2(2);; # HANGUL SYLLABLE NIEUN YA SSANGKIYEOK +U+B0D3(2);; # HANGUL SYLLABLE NIEUN YA KIYEOKSIOS +U+B0D4(2);; # HANGUL SYLLABLE NIEUN YA NIEUN * +U+B0D5(2);; # HANGUL SYLLABLE NIEUN YA NIEUNCIEUC +U+B0D6(2);; # HANGUL SYLLABLE NIEUN YA NIEUNHIEUH +U+B0D7(2);; # HANGUL SYLLABLE NIEUN YA TIKEUT +U+B0D8(2);; # HANGUL SYLLABLE NIEUN YA RIEUL * +U+B0D9(2);; # HANGUL SYLLABLE NIEUN YA RIEULKIYEOK +U+B0DA(2);; # HANGUL SYLLABLE NIEUN YA RIEULMIEUM +U+B0DB(2);; # HANGUL SYLLABLE NIEUN YA RIEULPIEUP +U+B0DC(2);; # HANGUL SYLLABLE NIEUN YA RIEULSIOS +U+B0DD(2);; # HANGUL SYLLABLE NIEUN YA RIEULTHIEUTH +U+B0DE(2);; # HANGUL SYLLABLE NIEUN YA RIEULPHIEUPH +U+B0DF(2);; # HANGUL SYLLABLE NIEUN YA RIEULHIEUH +U+B0E0(2);; # HANGUL SYLLABLE NIEUN YA MIEUM * +U+B0E1(2);; # HANGUL SYLLABLE NIEUN YA PIEUP +U+B0E2(2);; # HANGUL SYLLABLE NIEUN YA PIEUPSIOS +U+B0E3(2);; # HANGUL SYLLABLE NIEUN YA SIOS +U+B0E4(2);; # HANGUL SYLLABLE NIEUN YA SSANGSIOS +U+B0E5(2);; # HANGUL SYLLABLE NIEUN YA IEUNG * +U+B0E6(2);; # HANGUL SYLLABLE NIEUN YA CIEUC +U+B0E7(2);; # HANGUL SYLLABLE NIEUN YA CHIEUCH +U+B0E8(2);; # HANGUL SYLLABLE NIEUN YA KHIEUKH +U+B0E9(2);; # HANGUL SYLLABLE NIEUN YA THIEUTH +U+B0EA(2);; # HANGUL SYLLABLE NIEUN YA PHIEUPH +U+B0EB(2);; # HANGUL SYLLABLE NIEUN YA HIEUH +U+B0EC(2);; # HANGUL SYLLABLE NIEUN YAE +U+B0ED(2);; # HANGUL SYLLABLE NIEUN YAE KIYEOK +U+B0EE(2);; # HANGUL SYLLABLE NIEUN YAE SSANGKIYEOK +U+B0EF(2);; # HANGUL SYLLABLE NIEUN YAE KIYEOKSIOS +U+B0F0(2);; # HANGUL SYLLABLE NIEUN YAE NIEUN +U+B0F1(2);; # HANGUL SYLLABLE NIEUN YAE NIEUNCIEUC +U+B0F2(2);; # HANGUL SYLLABLE NIEUN YAE NIEUNHIEUH +U+B0F3(2);; # HANGUL SYLLABLE NIEUN YAE TIKEUT +U+B0F4(2);; # HANGUL SYLLABLE NIEUN YAE RIEUL +U+B0F5(2);; # HANGUL SYLLABLE NIEUN YAE RIEULKIYEOK +U+B0F6(2);; # HANGUL SYLLABLE NIEUN YAE RIEULMIEUM +U+B0F7(2);; # HANGUL SYLLABLE NIEUN YAE RIEULPIEUP +U+B0F8(2);; # HANGUL SYLLABLE NIEUN YAE RIEULSIOS +U+B0F9(2);; # HANGUL SYLLABLE NIEUN YAE RIEULTHIEUTH +U+B0FA(2);; # HANGUL SYLLABLE NIEUN YAE RIEULPHIEUPH +U+B0FB(2);; # HANGUL SYLLABLE NIEUN YAE RIEULHIEUH +U+B0FC(2);; # HANGUL SYLLABLE NIEUN YAE MIEUM +U+B0FD(2);; # HANGUL SYLLABLE NIEUN YAE PIEUP +U+B0FE(2);; # HANGUL SYLLABLE NIEUN YAE PIEUPSIOS +U+B0FF(2);; # HANGUL SYLLABLE NIEUN YAE SIOS +U+B100(2);; # HANGUL SYLLABLE NIEUN YAE SSANGSIOS +U+B101(2);; # HANGUL SYLLABLE NIEUN YAE IEUNG +U+B102(2);; # HANGUL SYLLABLE NIEUN YAE CIEUC +U+B103(2);; # HANGUL SYLLABLE NIEUN YAE CHIEUCH +U+B104(2);; # HANGUL SYLLABLE NIEUN YAE KHIEUKH +U+B105(2);; # HANGUL SYLLABLE NIEUN YAE THIEUTH +U+B106(2);; # HANGUL SYLLABLE NIEUN YAE PHIEUPH +U+B107(2);; # HANGUL SYLLABLE NIEUN YAE HIEUH +U+B108(2);; # HANGUL SYLLABLE NIEUN EO * +U+B109(2);; # HANGUL SYLLABLE NIEUN EO KIYEOK * +U+B10A(2);; # HANGUL SYLLABLE NIEUN EO SSANGKIYEOK +U+B10B(2);; # HANGUL SYLLABLE NIEUN EO KIYEOKSIOS * +U+B10C(2);; # HANGUL SYLLABLE NIEUN EO NIEUN * +U+B10D(2);; # HANGUL SYLLABLE NIEUN EO NIEUNCIEUC +U+B10E(2);; # HANGUL SYLLABLE NIEUN EO NIEUNHIEUH +U+B10F(2);; # HANGUL SYLLABLE NIEUN EO TIKEUT +U+B110(2);; # HANGUL SYLLABLE NIEUN EO RIEUL * +U+B111(2);; # HANGUL SYLLABLE NIEUN EO RIEULKIYEOK +U+B112(2);; # HANGUL SYLLABLE NIEUN EO RIEULMIEUM * +U+B113(2);; # HANGUL SYLLABLE NIEUN EO RIEULPIEUP * +U+B114(2);; # HANGUL SYLLABLE NIEUN EO RIEULSIOS +U+B115(2);; # HANGUL SYLLABLE NIEUN EO RIEULTHIEUTH +U+B116(2);; # HANGUL SYLLABLE NIEUN EO RIEULPHIEUPH +U+B117(2);; # HANGUL SYLLABLE NIEUN EO RIEULHIEUH +U+B118(2);; # HANGUL SYLLABLE NIEUN EO MIEUM * +U+B119(2);; # HANGUL SYLLABLE NIEUN EO PIEUP * +U+B11A(2);; # HANGUL SYLLABLE NIEUN EO PIEUPSIOS +U+B11B(2);; # HANGUL SYLLABLE NIEUN EO SIOS * +U+B11C(2);; # HANGUL SYLLABLE NIEUN EO SSANGSIOS * +U+B11D(2);; # HANGUL SYLLABLE NIEUN EO IEUNG * +U+B11E(2);; # HANGUL SYLLABLE NIEUN EO CIEUC +U+B11F(2);; # HANGUL SYLLABLE NIEUN EO CHIEUCH +U+B120(2);; # HANGUL SYLLABLE NIEUN EO KHIEUKH +U+B121(2);; # HANGUL SYLLABLE NIEUN EO THIEUTH +U+B122(2);; # HANGUL SYLLABLE NIEUN EO PHIEUPH +U+B123(2);; # HANGUL SYLLABLE NIEUN EO HIEUH * +U+B124(2);; # HANGUL SYLLABLE NIEUN E * +U+B125(2);; # HANGUL SYLLABLE NIEUN E KIYEOK * +U+B126(2);; # HANGUL SYLLABLE NIEUN E SSANGKIYEOK +U+B127(2);; # HANGUL SYLLABLE NIEUN E KIYEOKSIOS +U+B128(2);; # HANGUL SYLLABLE NIEUN E NIEUN * +U+B129(2);; # HANGUL SYLLABLE NIEUN E NIEUNCIEUC +U+B12A(2);; # HANGUL SYLLABLE NIEUN E NIEUNHIEUH +U+B12B(2);; # HANGUL SYLLABLE NIEUN E TIKEUT +U+B12C(2);; # HANGUL SYLLABLE NIEUN E RIEUL * +U+B12D(2);; # HANGUL SYLLABLE NIEUN E RIEULKIYEOK +U+B12E(2);; # HANGUL SYLLABLE NIEUN E RIEULMIEUM +U+B12F(2);; # HANGUL SYLLABLE NIEUN E RIEULPIEUP +U+B130(2);; # HANGUL SYLLABLE NIEUN E RIEULSIOS +U+B131(2);; # HANGUL SYLLABLE NIEUN E RIEULTHIEUTH +U+B132(2);; # HANGUL SYLLABLE NIEUN E RIEULPHIEUPH +U+B133(2);; # HANGUL SYLLABLE NIEUN E RIEULHIEUH +U+B134(2);; # HANGUL SYLLABLE NIEUN E MIEUM * +U+B135(2);; # HANGUL SYLLABLE NIEUN E PIEUP * +U+B136(2);; # HANGUL SYLLABLE NIEUN E PIEUPSIOS +U+B137(2);; # HANGUL SYLLABLE NIEUN E SIOS * +U+B138(2);; # HANGUL SYLLABLE NIEUN E SSANGSIOS * +U+B139(2);; # HANGUL SYLLABLE NIEUN E IEUNG * +U+B13A(2);; # HANGUL SYLLABLE NIEUN E CIEUC +U+B13B(2);; # HANGUL SYLLABLE NIEUN E CHIEUCH +U+B13C(2);; # HANGUL SYLLABLE NIEUN E KHIEUKH +U+B13D(2);; # HANGUL SYLLABLE NIEUN E THIEUTH +U+B13E(2);; # HANGUL SYLLABLE NIEUN E PHIEUPH +U+B13F(2);; # HANGUL SYLLABLE NIEUN E HIEUH +U+B140(2);; # HANGUL SYLLABLE NIEUN YEO * +U+B141(2);; # HANGUL SYLLABLE NIEUN YEO KIYEOK * +U+B142(2);; # HANGUL SYLLABLE NIEUN YEO SSANGKIYEOK +U+B143(2);; # HANGUL SYLLABLE NIEUN YEO KIYEOKSIOS +U+B144(2);; # HANGUL SYLLABLE NIEUN YEO NIEUN * +U+B145(2);; # HANGUL SYLLABLE NIEUN YEO NIEUNCIEUC +U+B146(2);; # HANGUL SYLLABLE NIEUN YEO NIEUNHIEUH +U+B147(2);; # HANGUL SYLLABLE NIEUN YEO TIKEUT +U+B148(2);; # HANGUL SYLLABLE NIEUN YEO RIEUL * +U+B149(2);; # HANGUL SYLLABLE NIEUN YEO RIEULKIYEOK +U+B14A(2);; # HANGUL SYLLABLE NIEUN YEO RIEULMIEUM +U+B14B(2);; # HANGUL SYLLABLE NIEUN YEO RIEULPIEUP +U+B14C(2);; # HANGUL SYLLABLE NIEUN YEO RIEULSIOS +U+B14D(2);; # HANGUL SYLLABLE NIEUN YEO RIEULTHIEUTH +U+B14E(2);; # HANGUL SYLLABLE NIEUN YEO RIEULPHIEUPH +U+B14F(2);; # HANGUL SYLLABLE NIEUN YEO RIEULHIEUH +U+B150(2);; # HANGUL SYLLABLE NIEUN YEO MIEUM * +U+B151(2);; # HANGUL SYLLABLE NIEUN YEO PIEUP * +U+B152(2);; # HANGUL SYLLABLE NIEUN YEO PIEUPSIOS +U+B153(2);; # HANGUL SYLLABLE NIEUN YEO SIOS +U+B154(2);; # HANGUL SYLLABLE NIEUN YEO SSANGSIOS * +U+B155(2);; # HANGUL SYLLABLE NIEUN YEO IEUNG * +U+B156(2);; # HANGUL SYLLABLE NIEUN YEO CIEUC +U+B157(2);; # HANGUL SYLLABLE NIEUN YEO CHIEUCH +U+B158(2);; # HANGUL SYLLABLE NIEUN YEO KHIEUKH * +U+B159(2);; # HANGUL SYLLABLE NIEUN YEO THIEUTH +U+B15A(2);; # HANGUL SYLLABLE NIEUN YEO PHIEUPH +U+B15B(2);; # HANGUL SYLLABLE NIEUN YEO HIEUH +U+B15C(2);; # HANGUL SYLLABLE NIEUN YE * +U+B15D(2);; # HANGUL SYLLABLE NIEUN YE KIYEOK +U+B15E(2);; # HANGUL SYLLABLE NIEUN YE SSANGKIYEOK +U+B15F(2);; # HANGUL SYLLABLE NIEUN YE KIYEOKSIOS +U+B160(2);; # HANGUL SYLLABLE NIEUN YE NIEUN * +U+B161(2);; # HANGUL SYLLABLE NIEUN YE NIEUNCIEUC +U+B162(2);; # HANGUL SYLLABLE NIEUN YE NIEUNHIEUH +U+B163(2);; # HANGUL SYLLABLE NIEUN YE TIKEUT +U+B164(2);; # HANGUL SYLLABLE NIEUN YE RIEUL +U+B165(2);; # HANGUL SYLLABLE NIEUN YE RIEULKIYEOK +U+B166(2);; # HANGUL SYLLABLE NIEUN YE RIEULMIEUM +U+B167(2);; # HANGUL SYLLABLE NIEUN YE RIEULPIEUP +U+B168(2);; # HANGUL SYLLABLE NIEUN YE RIEULSIOS +U+B169(2);; # HANGUL SYLLABLE NIEUN YE RIEULTHIEUTH +U+B16A(2);; # HANGUL SYLLABLE NIEUN YE RIEULPHIEUPH +U+B16B(2);; # HANGUL SYLLABLE NIEUN YE RIEULHIEUH +U+B16C(2);; # HANGUL SYLLABLE NIEUN YE MIEUM +U+B16D(2);; # HANGUL SYLLABLE NIEUN YE PIEUP +U+B16E(2);; # HANGUL SYLLABLE NIEUN YE PIEUPSIOS +U+B16F(2);; # HANGUL SYLLABLE NIEUN YE SIOS +U+B170(2);; # HANGUL SYLLABLE NIEUN YE SSANGSIOS +U+B171(2);; # HANGUL SYLLABLE NIEUN YE IEUNG +U+B172(2);; # HANGUL SYLLABLE NIEUN YE CIEUC +U+B173(2);; # HANGUL SYLLABLE NIEUN YE CHIEUCH +U+B174(2);; # HANGUL SYLLABLE NIEUN YE KHIEUKH +U+B175(2);; # HANGUL SYLLABLE NIEUN YE THIEUTH +U+B176(2);; # HANGUL SYLLABLE NIEUN YE PHIEUPH +U+B177(2);; # HANGUL SYLLABLE NIEUN YE HIEUH +U+B178(2);; # HANGUL SYLLABLE NIEUN O * +U+B179(2);; # HANGUL SYLLABLE NIEUN O KIYEOK * +U+B17A(2);; # HANGUL SYLLABLE NIEUN O SSANGKIYEOK +U+B17B(2);; # HANGUL SYLLABLE NIEUN O KIYEOKSIOS +U+B17C(2);; # HANGUL SYLLABLE NIEUN O NIEUN * +U+B17D(2);; # HANGUL SYLLABLE NIEUN O NIEUNCIEUC +U+B17E(2);; # HANGUL SYLLABLE NIEUN O NIEUNHIEUH +U+B17F(2);; # HANGUL SYLLABLE NIEUN O TIKEUT +U+B180(2);; # HANGUL SYLLABLE NIEUN O RIEUL * +U+B181(2);; # HANGUL SYLLABLE NIEUN O RIEULKIYEOK +U+B182(2);; # HANGUL SYLLABLE NIEUN O RIEULMIEUM * +U+B183(2);; # HANGUL SYLLABLE NIEUN O RIEULPIEUP +U+B184(2);; # HANGUL SYLLABLE NIEUN O RIEULSIOS +U+B185(2);; # HANGUL SYLLABLE NIEUN O RIEULTHIEUTH +U+B186(2);; # HANGUL SYLLABLE NIEUN O RIEULPHIEUPH +U+B187(2);; # HANGUL SYLLABLE NIEUN O RIEULHIEUH +U+B188(2);; # HANGUL SYLLABLE NIEUN O MIEUM * +U+B189(2);; # HANGUL SYLLABLE NIEUN O PIEUP * +U+B18A(2);; # HANGUL SYLLABLE NIEUN O PIEUPSIOS +U+B18B(2);; # HANGUL SYLLABLE NIEUN O SIOS * +U+B18C(2);; # HANGUL SYLLABLE NIEUN O SSANGSIOS +U+B18D(2);; # HANGUL SYLLABLE NIEUN O IEUNG * +U+B18E(2);; # HANGUL SYLLABLE NIEUN O CIEUC +U+B18F(2);; # HANGUL SYLLABLE NIEUN O CHIEUCH +U+B190(2);; # HANGUL SYLLABLE NIEUN O KHIEUKH +U+B191(2);; # HANGUL SYLLABLE NIEUN O THIEUTH +U+B192(2);; # HANGUL SYLLABLE NIEUN O PHIEUPH * +U+B193(2);; # HANGUL SYLLABLE NIEUN O HIEUH * +U+B194(2);; # HANGUL SYLLABLE NIEUN WA * +U+B195(2);; # HANGUL SYLLABLE NIEUN WA KIYEOK +U+B196(2);; # HANGUL SYLLABLE NIEUN WA SSANGKIYEOK +U+B197(2);; # HANGUL SYLLABLE NIEUN WA KIYEOKSIOS +U+B198(2);; # HANGUL SYLLABLE NIEUN WA NIEUN * +U+B199(2);; # HANGUL SYLLABLE NIEUN WA NIEUNCIEUC +U+B19A(2);; # HANGUL SYLLABLE NIEUN WA NIEUNHIEUH +U+B19B(2);; # HANGUL SYLLABLE NIEUN WA TIKEUT +U+B19C(2);; # HANGUL SYLLABLE NIEUN WA RIEUL * +U+B19D(2);; # HANGUL SYLLABLE NIEUN WA RIEULKIYEOK +U+B19E(2);; # HANGUL SYLLABLE NIEUN WA RIEULMIEUM +U+B19F(2);; # HANGUL SYLLABLE NIEUN WA RIEULPIEUP +U+B1A0(2);; # HANGUL SYLLABLE NIEUN WA RIEULSIOS +U+B1A1(2);; # HANGUL SYLLABLE NIEUN WA RIEULTHIEUTH +U+B1A2(2);; # HANGUL SYLLABLE NIEUN WA RIEULPHIEUPH +U+B1A3(2);; # HANGUL SYLLABLE NIEUN WA RIEULHIEUH +U+B1A4(2);; # HANGUL SYLLABLE NIEUN WA MIEUM +U+B1A5(2);; # HANGUL SYLLABLE NIEUN WA PIEUP +U+B1A6(2);; # HANGUL SYLLABLE NIEUN WA PIEUPSIOS +U+B1A7(2);; # HANGUL SYLLABLE NIEUN WA SIOS +U+B1A8(2);; # HANGUL SYLLABLE NIEUN WA SSANGSIOS * +U+B1A9(2);; # HANGUL SYLLABLE NIEUN WA IEUNG +U+B1AA(2);; # HANGUL SYLLABLE NIEUN WA CIEUC +U+B1AB(2);; # HANGUL SYLLABLE NIEUN WA CHIEUCH +U+B1AC(2);; # HANGUL SYLLABLE NIEUN WA KHIEUKH +U+B1AD(2);; # HANGUL SYLLABLE NIEUN WA THIEUTH +U+B1AE(2);; # HANGUL SYLLABLE NIEUN WA PHIEUPH +U+B1AF(2);; # HANGUL SYLLABLE NIEUN WA HIEUH +U+B1B0(2);; # HANGUL SYLLABLE NIEUN WAE +U+B1B1(2);; # HANGUL SYLLABLE NIEUN WAE KIYEOK +U+B1B2(2);; # HANGUL SYLLABLE NIEUN WAE SSANGKIYEOK +U+B1B3(2);; # HANGUL SYLLABLE NIEUN WAE KIYEOKSIOS +U+B1B4(2);; # HANGUL SYLLABLE NIEUN WAE NIEUN +U+B1B5(2);; # HANGUL SYLLABLE NIEUN WAE NIEUNCIEUC +U+B1B6(2);; # HANGUL SYLLABLE NIEUN WAE NIEUNHIEUH +U+B1B7(2);; # HANGUL SYLLABLE NIEUN WAE TIKEUT +U+B1B8(2);; # HANGUL SYLLABLE NIEUN WAE RIEUL +U+B1B9(2);; # HANGUL SYLLABLE NIEUN WAE RIEULKIYEOK +U+B1BA(2);; # HANGUL SYLLABLE NIEUN WAE RIEULMIEUM +U+B1BB(2);; # HANGUL SYLLABLE NIEUN WAE RIEULPIEUP +U+B1BC(2);; # HANGUL SYLLABLE NIEUN WAE RIEULSIOS +U+B1BD(2);; # HANGUL SYLLABLE NIEUN WAE RIEULTHIEUTH +U+B1BE(2);; # HANGUL SYLLABLE NIEUN WAE RIEULPHIEUPH +U+B1BF(2);; # HANGUL SYLLABLE NIEUN WAE RIEULHIEUH +U+B1C0(2);; # HANGUL SYLLABLE NIEUN WAE MIEUM +U+B1C1(2);; # HANGUL SYLLABLE NIEUN WAE PIEUP +U+B1C2(2);; # HANGUL SYLLABLE NIEUN WAE PIEUPSIOS +U+B1C3(2);; # HANGUL SYLLABLE NIEUN WAE SIOS +U+B1C4(2);; # HANGUL SYLLABLE NIEUN WAE SSANGSIOS +U+B1C5(2);; # HANGUL SYLLABLE NIEUN WAE IEUNG +U+B1C6(2);; # HANGUL SYLLABLE NIEUN WAE CIEUC +U+B1C7(2);; # HANGUL SYLLABLE NIEUN WAE CHIEUCH +U+B1C8(2);; # HANGUL SYLLABLE NIEUN WAE KHIEUKH +U+B1C9(2);; # HANGUL SYLLABLE NIEUN WAE THIEUTH +U+B1CA(2);; # HANGUL SYLLABLE NIEUN WAE PHIEUPH +U+B1CB(2);; # HANGUL SYLLABLE NIEUN WAE HIEUH +U+B1CC(2);; # HANGUL SYLLABLE NIEUN OE * +U+B1CD(2);; # HANGUL SYLLABLE NIEUN OE KIYEOK +U+B1CE(2);; # HANGUL SYLLABLE NIEUN OE SSANGKIYEOK +U+B1CF(2);; # HANGUL SYLLABLE NIEUN OE KIYEOKSIOS +U+B1D0(2);; # HANGUL SYLLABLE NIEUN OE NIEUN * +U+B1D1(2);; # HANGUL SYLLABLE NIEUN OE NIEUNCIEUC +U+B1D2(2);; # HANGUL SYLLABLE NIEUN OE NIEUNHIEUH +U+B1D3(2);; # HANGUL SYLLABLE NIEUN OE TIKEUT +U+B1D4(2);; # HANGUL SYLLABLE NIEUN OE RIEUL * +U+B1D5(2);; # HANGUL SYLLABLE NIEUN OE RIEULKIYEOK +U+B1D6(2);; # HANGUL SYLLABLE NIEUN OE RIEULMIEUM +U+B1D7(2);; # HANGUL SYLLABLE NIEUN OE RIEULPIEUP +U+B1D8(2);; # HANGUL SYLLABLE NIEUN OE RIEULSIOS +U+B1D9(2);; # HANGUL SYLLABLE NIEUN OE RIEULTHIEUTH +U+B1DA(2);; # HANGUL SYLLABLE NIEUN OE RIEULPHIEUPH +U+B1DB(2);; # HANGUL SYLLABLE NIEUN OE RIEULHIEUH +U+B1DC(2);; # HANGUL SYLLABLE NIEUN OE MIEUM * +U+B1DD(2);; # HANGUL SYLLABLE NIEUN OE PIEUP * +U+B1DE(2);; # HANGUL SYLLABLE NIEUN OE PIEUPSIOS +U+B1DF(2);; # HANGUL SYLLABLE NIEUN OE SIOS * +U+B1E0(2);; # HANGUL SYLLABLE NIEUN OE SSANGSIOS +U+B1E1(2);; # HANGUL SYLLABLE NIEUN OE IEUNG +U+B1E2(2);; # HANGUL SYLLABLE NIEUN OE CIEUC +U+B1E3(2);; # HANGUL SYLLABLE NIEUN OE CHIEUCH +U+B1E4(2);; # HANGUL SYLLABLE NIEUN OE KHIEUKH +U+B1E5(2);; # HANGUL SYLLABLE NIEUN OE THIEUTH +U+B1E6(2);; # HANGUL SYLLABLE NIEUN OE PHIEUPH +U+B1E7(2);; # HANGUL SYLLABLE NIEUN OE HIEUH +U+B1E8(2);; # HANGUL SYLLABLE NIEUN YO * +U+B1E9(2);; # HANGUL SYLLABLE NIEUN YO KIYEOK * +U+B1EA(2);; # HANGUL SYLLABLE NIEUN YO SSANGKIYEOK +U+B1EB(2);; # HANGUL SYLLABLE NIEUN YO KIYEOKSIOS +U+B1EC(2);; # HANGUL SYLLABLE NIEUN YO NIEUN * +U+B1ED(2);; # HANGUL SYLLABLE NIEUN YO NIEUNCIEUC +U+B1EE(2);; # HANGUL SYLLABLE NIEUN YO NIEUNHIEUH +U+B1EF(2);; # HANGUL SYLLABLE NIEUN YO TIKEUT +U+B1F0(2);; # HANGUL SYLLABLE NIEUN YO RIEUL * +U+B1F1(2);; # HANGUL SYLLABLE NIEUN YO RIEULKIYEOK +U+B1F2(2);; # HANGUL SYLLABLE NIEUN YO RIEULMIEUM +U+B1F3(2);; # HANGUL SYLLABLE NIEUN YO RIEULPIEUP +U+B1F4(2);; # HANGUL SYLLABLE NIEUN YO RIEULSIOS +U+B1F5(2);; # HANGUL SYLLABLE NIEUN YO RIEULTHIEUTH +U+B1F6(2);; # HANGUL SYLLABLE NIEUN YO RIEULPHIEUPH +U+B1F7(2);; # HANGUL SYLLABLE NIEUN YO RIEULHIEUH +U+B1F8(2);; # HANGUL SYLLABLE NIEUN YO MIEUM +U+B1F9(2);; # HANGUL SYLLABLE NIEUN YO PIEUP * +U+B1FA(2);; # HANGUL SYLLABLE NIEUN YO PIEUPSIOS +U+B1FB(2);; # HANGUL SYLLABLE NIEUN YO SIOS * +U+B1FC(2);; # HANGUL SYLLABLE NIEUN YO SSANGSIOS +U+B1FD(2);; # HANGUL SYLLABLE NIEUN YO IEUNG * +U+B1FE(2);; # HANGUL SYLLABLE NIEUN YO CIEUC +U+B1FF(2);; # HANGUL SYLLABLE NIEUN YO CHIEUCH +U+B200(2);; # HANGUL SYLLABLE NIEUN YO KHIEUKH +U+B201(2);; # HANGUL SYLLABLE NIEUN YO THIEUTH +U+B202(2);; # HANGUL SYLLABLE NIEUN YO PHIEUPH +U+B203(2);; # HANGUL SYLLABLE NIEUN YO HIEUH +U+B204(2);; # HANGUL SYLLABLE NIEUN U * +U+B205(2);; # HANGUL SYLLABLE NIEUN U KIYEOK * +U+B206(2);; # HANGUL SYLLABLE NIEUN U SSANGKIYEOK +U+B207(2);; # HANGUL SYLLABLE NIEUN U KIYEOKSIOS +U+B208(2);; # HANGUL SYLLABLE NIEUN U NIEUN * +U+B209(2);; # HANGUL SYLLABLE NIEUN U NIEUNCIEUC +U+B20A(2);; # HANGUL SYLLABLE NIEUN U NIEUNHIEUH +U+B20B(2);; # HANGUL SYLLABLE NIEUN U TIKEUT * +U+B20C(2);; # HANGUL SYLLABLE NIEUN U RIEUL * +U+B20D(2);; # HANGUL SYLLABLE NIEUN U RIEULKIYEOK +U+B20E(2);; # HANGUL SYLLABLE NIEUN U RIEULMIEUM +U+B20F(2);; # HANGUL SYLLABLE NIEUN U RIEULPIEUP +U+B210(2);; # HANGUL SYLLABLE NIEUN U RIEULSIOS +U+B211(2);; # HANGUL SYLLABLE NIEUN U RIEULTHIEUTH +U+B212(2);; # HANGUL SYLLABLE NIEUN U RIEULPHIEUPH +U+B213(2);; # HANGUL SYLLABLE NIEUN U RIEULHIEUH +U+B214(2);; # HANGUL SYLLABLE NIEUN U MIEUM * +U+B215(2);; # HANGUL SYLLABLE NIEUN U PIEUP * +U+B216(2);; # HANGUL SYLLABLE NIEUN U PIEUPSIOS +U+B217(2);; # HANGUL SYLLABLE NIEUN U SIOS * +U+B218(2);; # HANGUL SYLLABLE NIEUN U SSANGSIOS +U+B219(2);; # HANGUL SYLLABLE NIEUN U IEUNG * +U+B21A(2);; # HANGUL SYLLABLE NIEUN U CIEUC +U+B21B(2);; # HANGUL SYLLABLE NIEUN U CHIEUCH +U+B21C(2);; # HANGUL SYLLABLE NIEUN U KHIEUKH +U+B21D(2);; # HANGUL SYLLABLE NIEUN U THIEUTH +U+B21E(2);; # HANGUL SYLLABLE NIEUN U PHIEUPH +U+B21F(2);; # HANGUL SYLLABLE NIEUN U HIEUH +U+B220(2);; # HANGUL SYLLABLE NIEUN WEO * +U+B221(2);; # HANGUL SYLLABLE NIEUN WEO KIYEOK +U+B222(2);; # HANGUL SYLLABLE NIEUN WEO SSANGKIYEOK +U+B223(2);; # HANGUL SYLLABLE NIEUN WEO KIYEOKSIOS +U+B224(2);; # HANGUL SYLLABLE NIEUN WEO NIEUN +U+B225(2);; # HANGUL SYLLABLE NIEUN WEO NIEUNCIEUC +U+B226(2);; # HANGUL SYLLABLE NIEUN WEO NIEUNHIEUH +U+B227(2);; # HANGUL SYLLABLE NIEUN WEO TIKEUT +U+B228(2);; # HANGUL SYLLABLE NIEUN WEO RIEUL +U+B229(2);; # HANGUL SYLLABLE NIEUN WEO RIEULKIYEOK +U+B22A(2);; # HANGUL SYLLABLE NIEUN WEO RIEULMIEUM +U+B22B(2);; # HANGUL SYLLABLE NIEUN WEO RIEULPIEUP +U+B22C(2);; # HANGUL SYLLABLE NIEUN WEO RIEULSIOS +U+B22D(2);; # HANGUL SYLLABLE NIEUN WEO RIEULTHIEUTH +U+B22E(2);; # HANGUL SYLLABLE NIEUN WEO RIEULPHIEUPH +U+B22F(2);; # HANGUL SYLLABLE NIEUN WEO RIEULHIEUH +U+B230(2);; # HANGUL SYLLABLE NIEUN WEO MIEUM +U+B231(2);; # HANGUL SYLLABLE NIEUN WEO PIEUP +U+B232(2);; # HANGUL SYLLABLE NIEUN WEO PIEUPSIOS +U+B233(2);; # HANGUL SYLLABLE NIEUN WEO SIOS +U+B234(2);; # HANGUL SYLLABLE NIEUN WEO SSANGSIOS * +U+B235(2);; # HANGUL SYLLABLE NIEUN WEO IEUNG +U+B236(2);; # HANGUL SYLLABLE NIEUN WEO CIEUC +U+B237(2);; # HANGUL SYLLABLE NIEUN WEO CHIEUCH +U+B238(2);; # HANGUL SYLLABLE NIEUN WEO KHIEUKH +U+B239(2);; # HANGUL SYLLABLE NIEUN WEO THIEUTH +U+B23A(2);; # HANGUL SYLLABLE NIEUN WEO PHIEUPH +U+B23B(2);; # HANGUL SYLLABLE NIEUN WEO HIEUH +U+B23C(2);; # HANGUL SYLLABLE NIEUN WE * +U+B23D(2);; # HANGUL SYLLABLE NIEUN WE KIYEOK +U+B23E(2);; # HANGUL SYLLABLE NIEUN WE SSANGKIYEOK +U+B23F(2);; # HANGUL SYLLABLE NIEUN WE KIYEOKSIOS +U+B240(2);; # HANGUL SYLLABLE NIEUN WE NIEUN +U+B241(2);; # HANGUL SYLLABLE NIEUN WE NIEUNCIEUC +U+B242(2);; # HANGUL SYLLABLE NIEUN WE NIEUNHIEUH +U+B243(2);; # HANGUL SYLLABLE NIEUN WE TIKEUT +U+B244(2);; # HANGUL SYLLABLE NIEUN WE RIEUL +U+B245(2);; # HANGUL SYLLABLE NIEUN WE RIEULKIYEOK +U+B246(2);; # HANGUL SYLLABLE NIEUN WE RIEULMIEUM +U+B247(2);; # HANGUL SYLLABLE NIEUN WE RIEULPIEUP +U+B248(2);; # HANGUL SYLLABLE NIEUN WE RIEULSIOS +U+B249(2);; # HANGUL SYLLABLE NIEUN WE RIEULTHIEUTH +U+B24A(2);; # HANGUL SYLLABLE NIEUN WE RIEULPHIEUPH +U+B24B(2);; # HANGUL SYLLABLE NIEUN WE RIEULHIEUH +U+B24C(2);; # HANGUL SYLLABLE NIEUN WE MIEUM +U+B24D(2);; # HANGUL SYLLABLE NIEUN WE PIEUP +U+B24E(2);; # HANGUL SYLLABLE NIEUN WE PIEUPSIOS +U+B24F(2);; # HANGUL SYLLABLE NIEUN WE SIOS +U+B250(2);; # HANGUL SYLLABLE NIEUN WE SSANGSIOS +U+B251(2);; # HANGUL SYLLABLE NIEUN WE IEUNG +U+B252(2);; # HANGUL SYLLABLE NIEUN WE CIEUC +U+B253(2);; # HANGUL SYLLABLE NIEUN WE CHIEUCH +U+B254(2);; # HANGUL SYLLABLE NIEUN WE KHIEUKH +U+B255(2);; # HANGUL SYLLABLE NIEUN WE THIEUTH +U+B256(2);; # HANGUL SYLLABLE NIEUN WE PHIEUPH +U+B257(2);; # HANGUL SYLLABLE NIEUN WE HIEUH +U+B258(2);; # HANGUL SYLLABLE NIEUN WI * +U+B259(2);; # HANGUL SYLLABLE NIEUN WI KIYEOK +U+B25A(2);; # HANGUL SYLLABLE NIEUN WI SSANGKIYEOK +U+B25B(2);; # HANGUL SYLLABLE NIEUN WI KIYEOKSIOS +U+B25C(2);; # HANGUL SYLLABLE NIEUN WI NIEUN * +U+B25D(2);; # HANGUL SYLLABLE NIEUN WI NIEUNCIEUC +U+B25E(2);; # HANGUL SYLLABLE NIEUN WI NIEUNHIEUH +U+B25F(2);; # HANGUL SYLLABLE NIEUN WI TIKEUT +U+B260(2);; # HANGUL SYLLABLE NIEUN WI RIEUL * +U+B261(2);; # HANGUL SYLLABLE NIEUN WI RIEULKIYEOK +U+B262(2);; # HANGUL SYLLABLE NIEUN WI RIEULMIEUM +U+B263(2);; # HANGUL SYLLABLE NIEUN WI RIEULPIEUP +U+B264(2);; # HANGUL SYLLABLE NIEUN WI RIEULSIOS +U+B265(2);; # HANGUL SYLLABLE NIEUN WI RIEULTHIEUTH +U+B266(2);; # HANGUL SYLLABLE NIEUN WI RIEULPHIEUPH +U+B267(2);; # HANGUL SYLLABLE NIEUN WI RIEULHIEUH +U+B268(2);; # HANGUL SYLLABLE NIEUN WI MIEUM * +U+B269(2);; # HANGUL SYLLABLE NIEUN WI PIEUP * +U+B26A(2);; # HANGUL SYLLABLE NIEUN WI PIEUPSIOS +U+B26B(2);; # HANGUL SYLLABLE NIEUN WI SIOS +U+B26C(2);; # HANGUL SYLLABLE NIEUN WI SSANGSIOS +U+B26D(2);; # HANGUL SYLLABLE NIEUN WI IEUNG +U+B26E(2);; # HANGUL SYLLABLE NIEUN WI CIEUC +U+B26F(2);; # HANGUL SYLLABLE NIEUN WI CHIEUCH +U+B270(2);; # HANGUL SYLLABLE NIEUN WI KHIEUKH +U+B271(2);; # HANGUL SYLLABLE NIEUN WI THIEUTH +U+B272(2);; # HANGUL SYLLABLE NIEUN WI PHIEUPH +U+B273(2);; # HANGUL SYLLABLE NIEUN WI HIEUH +U+B274(2);; # HANGUL SYLLABLE NIEUN YU * +U+B275(2);; # HANGUL SYLLABLE NIEUN YU KIYEOK * +U+B276(2);; # HANGUL SYLLABLE NIEUN YU SSANGKIYEOK +U+B277(2);; # HANGUL SYLLABLE NIEUN YU KIYEOKSIOS +U+B278(2);; # HANGUL SYLLABLE NIEUN YU NIEUN +U+B279(2);; # HANGUL SYLLABLE NIEUN YU NIEUNCIEUC +U+B27A(2);; # HANGUL SYLLABLE NIEUN YU NIEUNHIEUH +U+B27B(2);; # HANGUL SYLLABLE NIEUN YU TIKEUT +U+B27C(2);; # HANGUL SYLLABLE NIEUN YU RIEUL * +U+B27D(2);; # HANGUL SYLLABLE NIEUN YU RIEULKIYEOK +U+B27E(2);; # HANGUL SYLLABLE NIEUN YU RIEULMIEUM +U+B27F(2);; # HANGUL SYLLABLE NIEUN YU RIEULPIEUP +U+B280(2);; # HANGUL SYLLABLE NIEUN YU RIEULSIOS +U+B281(2);; # HANGUL SYLLABLE NIEUN YU RIEULTHIEUTH +U+B282(2);; # HANGUL SYLLABLE NIEUN YU RIEULPHIEUPH +U+B283(2);; # HANGUL SYLLABLE NIEUN YU RIEULHIEUH +U+B284(2);; # HANGUL SYLLABLE NIEUN YU MIEUM * +U+B285(2);; # HANGUL SYLLABLE NIEUN YU PIEUP * +U+B286(2);; # HANGUL SYLLABLE NIEUN YU PIEUPSIOS +U+B287(2);; # HANGUL SYLLABLE NIEUN YU SIOS +U+B288(2);; # HANGUL SYLLABLE NIEUN YU SSANGSIOS +U+B289(2);; # HANGUL SYLLABLE NIEUN YU IEUNG * +U+B28A(2);; # HANGUL SYLLABLE NIEUN YU CIEUC +U+B28B(2);; # HANGUL SYLLABLE NIEUN YU CHIEUCH +U+B28C(2);; # HANGUL SYLLABLE NIEUN YU KHIEUKH +U+B28D(2);; # HANGUL SYLLABLE NIEUN YU THIEUTH +U+B28E(2);; # HANGUL SYLLABLE NIEUN YU PHIEUPH +U+B28F(2);; # HANGUL SYLLABLE NIEUN YU HIEUH +U+B290(2);; # HANGUL SYLLABLE NIEUN EU * +U+B291(2);; # HANGUL SYLLABLE NIEUN EU KIYEOK * +U+B292(2);; # HANGUL SYLLABLE NIEUN EU SSANGKIYEOK +U+B293(2);; # HANGUL SYLLABLE NIEUN EU KIYEOKSIOS +U+B294(2);; # HANGUL SYLLABLE NIEUN EU NIEUN * +U+B295(2);; # HANGUL SYLLABLE NIEUN EU NIEUNCIEUC +U+B296(2);; # HANGUL SYLLABLE NIEUN EU NIEUNHIEUH +U+B297(2);; # HANGUL SYLLABLE NIEUN EU TIKEUT +U+B298(2);; # HANGUL SYLLABLE NIEUN EU RIEUL * +U+B299(2);; # HANGUL SYLLABLE NIEUN EU RIEULKIYEOK * +U+B29A(2);; # HANGUL SYLLABLE NIEUN EU RIEULMIEUM * +U+B29B(2);; # HANGUL SYLLABLE NIEUN EU RIEULPIEUP +U+B29C(2);; # HANGUL SYLLABLE NIEUN EU RIEULSIOS +U+B29D(2);; # HANGUL SYLLABLE NIEUN EU RIEULTHIEUTH +U+B29E(2);; # HANGUL SYLLABLE NIEUN EU RIEULPHIEUPH +U+B29F(2);; # HANGUL SYLLABLE NIEUN EU RIEULHIEUH +U+B2A0(2);; # HANGUL SYLLABLE NIEUN EU MIEUM * +U+B2A1(2);; # HANGUL SYLLABLE NIEUN EU PIEUP * +U+B2A2(2);; # HANGUL SYLLABLE NIEUN EU PIEUPSIOS +U+B2A3(2);; # HANGUL SYLLABLE NIEUN EU SIOS * +U+B2A4(2);; # HANGUL SYLLABLE NIEUN EU SSANGSIOS +U+B2A5(2);; # HANGUL SYLLABLE NIEUN EU IEUNG * +U+B2A6(2);; # HANGUL SYLLABLE NIEUN EU CIEUC * +U+B2A7(2);; # HANGUL SYLLABLE NIEUN EU CHIEUCH +U+B2A8(2);; # HANGUL SYLLABLE NIEUN EU KHIEUKH +U+B2A9(2);; # HANGUL SYLLABLE NIEUN EU THIEUTH +U+B2AA(2);; # HANGUL SYLLABLE NIEUN EU PHIEUPH * +U+B2AB(2);; # HANGUL SYLLABLE NIEUN EU HIEUH +U+B2AC(2);; # HANGUL SYLLABLE NIEUN YI * +U+B2AD(2);; # HANGUL SYLLABLE NIEUN YI KIYEOK +U+B2AE(2);; # HANGUL SYLLABLE NIEUN YI SSANGKIYEOK +U+B2AF(2);; # HANGUL SYLLABLE NIEUN YI KIYEOKSIOS +U+B2B0(2);; # HANGUL SYLLABLE NIEUN YI NIEUN * +U+B2B1(2);; # HANGUL SYLLABLE NIEUN YI NIEUNCIEUC +U+B2B2(2);; # HANGUL SYLLABLE NIEUN YI NIEUNHIEUH +U+B2B3(2);; # HANGUL SYLLABLE NIEUN YI TIKEUT +U+B2B4(2);; # HANGUL SYLLABLE NIEUN YI RIEUL * +U+B2B5(2);; # HANGUL SYLLABLE NIEUN YI RIEULKIYEOK +U+B2B6(2);; # HANGUL SYLLABLE NIEUN YI RIEULMIEUM +U+B2B7(2);; # HANGUL SYLLABLE NIEUN YI RIEULPIEUP +U+B2B8(2);; # HANGUL SYLLABLE NIEUN YI RIEULSIOS +U+B2B9(2);; # HANGUL SYLLABLE NIEUN YI RIEULTHIEUTH +U+B2BA(2);; # HANGUL SYLLABLE NIEUN YI RIEULPHIEUPH +U+B2BB(2);; # HANGUL SYLLABLE NIEUN YI RIEULHIEUH +U+B2BC(2);; # HANGUL SYLLABLE NIEUN YI MIEUM +U+B2BD(2);; # HANGUL SYLLABLE NIEUN YI PIEUP +U+B2BE(2);; # HANGUL SYLLABLE NIEUN YI PIEUPSIOS +U+B2BF(2);; # HANGUL SYLLABLE NIEUN YI SIOS +U+B2C0(2);; # HANGUL SYLLABLE NIEUN YI SSANGSIOS +U+B2C1(2);; # HANGUL SYLLABLE NIEUN YI IEUNG +U+B2C2(2);; # HANGUL SYLLABLE NIEUN YI CIEUC +U+B2C3(2);; # HANGUL SYLLABLE NIEUN YI CHIEUCH +U+B2C4(2);; # HANGUL SYLLABLE NIEUN YI KHIEUKH +U+B2C5(2);; # HANGUL SYLLABLE NIEUN YI THIEUTH +U+B2C6(2);; # HANGUL SYLLABLE NIEUN YI PHIEUPH +U+B2C7(2);; # HANGUL SYLLABLE NIEUN YI HIEUH +U+B2C8(2);; # HANGUL SYLLABLE NIEUN I * +U+B2C9(2);; # HANGUL SYLLABLE NIEUN I KIYEOK * +U+B2CA(2);; # HANGUL SYLLABLE NIEUN I SSANGKIYEOK +U+B2CB(2);; # HANGUL SYLLABLE NIEUN I KIYEOKSIOS +U+B2CC(2);; # HANGUL SYLLABLE NIEUN I NIEUN * +U+B2CD(2);; # HANGUL SYLLABLE NIEUN I NIEUNCIEUC +U+B2CE(2);; # HANGUL SYLLABLE NIEUN I NIEUNHIEUH +U+B2CF(2);; # HANGUL SYLLABLE NIEUN I TIKEUT +U+B2D0(2);; # HANGUL SYLLABLE NIEUN I RIEUL * +U+B2D1(2);; # HANGUL SYLLABLE NIEUN I RIEULKIYEOK +U+B2D2(2);; # HANGUL SYLLABLE NIEUN I RIEULMIEUM * +U+B2D3(2);; # HANGUL SYLLABLE NIEUN I RIEULPIEUP +U+B2D4(2);; # HANGUL SYLLABLE NIEUN I RIEULSIOS +U+B2D5(2);; # HANGUL SYLLABLE NIEUN I RIEULTHIEUTH +U+B2D6(2);; # HANGUL SYLLABLE NIEUN I RIEULPHIEUPH +U+B2D7(2);; # HANGUL SYLLABLE NIEUN I RIEULHIEUH +U+B2D8(2);; # HANGUL SYLLABLE NIEUN I MIEUM * +U+B2D9(2);; # HANGUL SYLLABLE NIEUN I PIEUP * +U+B2DA(2);; # HANGUL SYLLABLE NIEUN I PIEUPSIOS +U+B2DB(2);; # HANGUL SYLLABLE NIEUN I SIOS * +U+B2DC(2);; # HANGUL SYLLABLE NIEUN I SSANGSIOS +U+B2DD(2);; # HANGUL SYLLABLE NIEUN I IEUNG * +U+B2DE(2);; # HANGUL SYLLABLE NIEUN I CIEUC +U+B2DF(2);; # HANGUL SYLLABLE NIEUN I CHIEUCH +U+B2E0(2);; # HANGUL SYLLABLE NIEUN I KHIEUKH +U+B2E1(2);; # HANGUL SYLLABLE NIEUN I THIEUTH +U+B2E2(2);; # HANGUL SYLLABLE NIEUN I PHIEUPH * +U+B2E3(2);; # HANGUL SYLLABLE NIEUN I HIEUH +U+B2E4(2);; # HANGUL SYLLABLE TIKEUT A * +U+B2E5(2);; # HANGUL SYLLABLE TIKEUT A KIYEOK * +U+B2E6(2);; # HANGUL SYLLABLE TIKEUT A SSANGKIYEOK * +U+B2E7(2);; # HANGUL SYLLABLE TIKEUT A KIYEOKSIOS +U+B2E8(2);; # HANGUL SYLLABLE TIKEUT A NIEUN * +U+B2E9(2);; # HANGUL SYLLABLE TIKEUT A NIEUNCIEUC +U+B2EA(2);; # HANGUL SYLLABLE TIKEUT A NIEUNHIEUH +U+B2EB(2);; # HANGUL SYLLABLE TIKEUT A TIKEUT * +U+B2EC(2);; # HANGUL SYLLABLE TIKEUT A RIEUL * +U+B2ED(2);; # HANGUL SYLLABLE TIKEUT A RIEULKIYEOK * +U+B2EE(2);; # HANGUL SYLLABLE TIKEUT A RIEULMIEUM * +U+B2EF(2);; # HANGUL SYLLABLE TIKEUT A RIEULPIEUP * +U+B2F0(2);; # HANGUL SYLLABLE TIKEUT A RIEULSIOS +U+B2F1(2);; # HANGUL SYLLABLE TIKEUT A RIEULTHIEUTH +U+B2F2(2);; # HANGUL SYLLABLE TIKEUT A RIEULPHIEUPH +U+B2F3(2);; # HANGUL SYLLABLE TIKEUT A RIEULHIEUH * +U+B2F4(2);; # HANGUL SYLLABLE TIKEUT A MIEUM * +U+B2F5(2);; # HANGUL SYLLABLE TIKEUT A PIEUP * +U+B2F6(2);; # HANGUL SYLLABLE TIKEUT A PIEUPSIOS +U+B2F7(2);; # HANGUL SYLLABLE TIKEUT A SIOS * +U+B2F8(2);; # HANGUL SYLLABLE TIKEUT A SSANGSIOS * +U+B2F9(2);; # HANGUL SYLLABLE TIKEUT A IEUNG * +U+B2FA(2);; # HANGUL SYLLABLE TIKEUT A CIEUC * +U+B2FB(2);; # HANGUL SYLLABLE TIKEUT A CHIEUCH * +U+B2FC(2);; # HANGUL SYLLABLE TIKEUT A KHIEUKH +U+B2FD(2);; # HANGUL SYLLABLE TIKEUT A THIEUTH +U+B2FE(2);; # HANGUL SYLLABLE TIKEUT A PHIEUPH +U+B2FF(2);; # HANGUL SYLLABLE TIKEUT A HIEUH * +U+B300(2);; # HANGUL SYLLABLE TIKEUT AE * +U+B301(2);; # HANGUL SYLLABLE TIKEUT AE KIYEOK * +U+B302(2);; # HANGUL SYLLABLE TIKEUT AE SSANGKIYEOK +U+B303(2);; # HANGUL SYLLABLE TIKEUT AE KIYEOKSIOS +U+B304(2);; # HANGUL SYLLABLE TIKEUT AE NIEUN * +U+B305(2);; # HANGUL SYLLABLE TIKEUT AE NIEUNCIEUC +U+B306(2);; # HANGUL SYLLABLE TIKEUT AE NIEUNHIEUH +U+B307(2);; # HANGUL SYLLABLE TIKEUT AE TIKEUT +U+B308(2);; # HANGUL SYLLABLE TIKEUT AE RIEUL * +U+B309(2);; # HANGUL SYLLABLE TIKEUT AE RIEULKIYEOK +U+B30A(2);; # HANGUL SYLLABLE TIKEUT AE RIEULMIEUM +U+B30B(2);; # HANGUL SYLLABLE TIKEUT AE RIEULPIEUP +U+B30C(2);; # HANGUL SYLLABLE TIKEUT AE RIEULSIOS +U+B30D(2);; # HANGUL SYLLABLE TIKEUT AE RIEULTHIEUTH +U+B30E(2);; # HANGUL SYLLABLE TIKEUT AE RIEULPHIEUPH +U+B30F(2);; # HANGUL SYLLABLE TIKEUT AE RIEULHIEUH +U+B310(2);; # HANGUL SYLLABLE TIKEUT AE MIEUM * +U+B311(2);; # HANGUL SYLLABLE TIKEUT AE PIEUP * +U+B312(2);; # HANGUL SYLLABLE TIKEUT AE PIEUPSIOS +U+B313(2);; # HANGUL SYLLABLE TIKEUT AE SIOS * +U+B314(2);; # HANGUL SYLLABLE TIKEUT AE SSANGSIOS * +U+B315(2);; # HANGUL SYLLABLE TIKEUT AE IEUNG * +U+B316(2);; # HANGUL SYLLABLE TIKEUT AE CIEUC +U+B317(2);; # HANGUL SYLLABLE TIKEUT AE CHIEUCH +U+B318(2);; # HANGUL SYLLABLE TIKEUT AE KHIEUKH +U+B319(2);; # HANGUL SYLLABLE TIKEUT AE THIEUTH +U+B31A(2);; # HANGUL SYLLABLE TIKEUT AE PHIEUPH +U+B31B(2);; # HANGUL SYLLABLE TIKEUT AE HIEUH +U+B31C(2);; # HANGUL SYLLABLE TIKEUT YA * +U+B31D(2);; # HANGUL SYLLABLE TIKEUT YA KIYEOK +U+B31E(2);; # HANGUL SYLLABLE TIKEUT YA SSANGKIYEOK +U+B31F(2);; # HANGUL SYLLABLE TIKEUT YA KIYEOKSIOS +U+B320(2);; # HANGUL SYLLABLE TIKEUT YA NIEUN +U+B321(2);; # HANGUL SYLLABLE TIKEUT YA NIEUNCIEUC +U+B322(2);; # HANGUL SYLLABLE TIKEUT YA NIEUNHIEUH +U+B323(2);; # HANGUL SYLLABLE TIKEUT YA TIKEUT +U+B324(2);; # HANGUL SYLLABLE TIKEUT YA RIEUL +U+B325(2);; # HANGUL SYLLABLE TIKEUT YA RIEULKIYEOK +U+B326(2);; # HANGUL SYLLABLE TIKEUT YA RIEULMIEUM +U+B327(2);; # HANGUL SYLLABLE TIKEUT YA RIEULPIEUP +U+B328(2);; # HANGUL SYLLABLE TIKEUT YA RIEULSIOS +U+B329(2);; # HANGUL SYLLABLE TIKEUT YA RIEULTHIEUTH +U+B32A(2);; # HANGUL SYLLABLE TIKEUT YA RIEULPHIEUPH +U+B32B(2);; # HANGUL SYLLABLE TIKEUT YA RIEULHIEUH +U+B32C(2);; # HANGUL SYLLABLE TIKEUT YA MIEUM +U+B32D(2);; # HANGUL SYLLABLE TIKEUT YA PIEUP +U+B32E(2);; # HANGUL SYLLABLE TIKEUT YA PIEUPSIOS +U+B32F(2);; # HANGUL SYLLABLE TIKEUT YA SIOS +U+B330(2);; # HANGUL SYLLABLE TIKEUT YA SSANGSIOS +U+B331(2);; # HANGUL SYLLABLE TIKEUT YA IEUNG +U+B332(2);; # HANGUL SYLLABLE TIKEUT YA CIEUC +U+B333(2);; # HANGUL SYLLABLE TIKEUT YA CHIEUCH +U+B334(2);; # HANGUL SYLLABLE TIKEUT YA KHIEUKH +U+B335(2);; # HANGUL SYLLABLE TIKEUT YA THIEUTH +U+B336(2);; # HANGUL SYLLABLE TIKEUT YA PHIEUPH +U+B337(2);; # HANGUL SYLLABLE TIKEUT YA HIEUH +U+B338(2);; # HANGUL SYLLABLE TIKEUT YAE +U+B339(2);; # HANGUL SYLLABLE TIKEUT YAE KIYEOK +U+B33A(2);; # HANGUL SYLLABLE TIKEUT YAE SSANGKIYEOK +U+B33B(2);; # HANGUL SYLLABLE TIKEUT YAE KIYEOKSIOS +U+B33C(2);; # HANGUL SYLLABLE TIKEUT YAE NIEUN +U+B33D(2);; # HANGUL SYLLABLE TIKEUT YAE NIEUNCIEUC +U+B33E(2);; # HANGUL SYLLABLE TIKEUT YAE NIEUNHIEUH +U+B33F(2);; # HANGUL SYLLABLE TIKEUT YAE TIKEUT +U+B340(2);; # HANGUL SYLLABLE TIKEUT YAE RIEUL +U+B341(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULKIYEOK +U+B342(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULMIEUM +U+B343(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULPIEUP +U+B344(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULSIOS +U+B345(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULTHIEUTH +U+B346(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULPHIEUPH +U+B347(2);; # HANGUL SYLLABLE TIKEUT YAE RIEULHIEUH +U+B348(2);; # HANGUL SYLLABLE TIKEUT YAE MIEUM +U+B349(2);; # HANGUL SYLLABLE TIKEUT YAE PIEUP +U+B34A(2);; # HANGUL SYLLABLE TIKEUT YAE PIEUPSIOS +U+B34B(2);; # HANGUL SYLLABLE TIKEUT YAE SIOS +U+B34C(2);; # HANGUL SYLLABLE TIKEUT YAE SSANGSIOS +U+B34D(2);; # HANGUL SYLLABLE TIKEUT YAE IEUNG +U+B34E(2);; # HANGUL SYLLABLE TIKEUT YAE CIEUC +U+B34F(2);; # HANGUL SYLLABLE TIKEUT YAE CHIEUCH +U+B350(2);; # HANGUL SYLLABLE TIKEUT YAE KHIEUKH +U+B351(2);; # HANGUL SYLLABLE TIKEUT YAE THIEUTH +U+B352(2);; # HANGUL SYLLABLE TIKEUT YAE PHIEUPH +U+B353(2);; # HANGUL SYLLABLE TIKEUT YAE HIEUH +U+B354(2);; # HANGUL SYLLABLE TIKEUT EO * +U+B355(2);; # HANGUL SYLLABLE TIKEUT EO KIYEOK * +U+B356(2);; # HANGUL SYLLABLE TIKEUT EO SSANGKIYEOK * +U+B357(2);; # HANGUL SYLLABLE TIKEUT EO KIYEOKSIOS +U+B358(2);; # HANGUL SYLLABLE TIKEUT EO NIEUN * +U+B359(2);; # HANGUL SYLLABLE TIKEUT EO NIEUNCIEUC +U+B35A(2);; # HANGUL SYLLABLE TIKEUT EO NIEUNHIEUH +U+B35B(2);; # HANGUL SYLLABLE TIKEUT EO TIKEUT * +U+B35C(2);; # HANGUL SYLLABLE TIKEUT EO RIEUL * +U+B35D(2);; # HANGUL SYLLABLE TIKEUT EO RIEULKIYEOK +U+B35E(2);; # HANGUL SYLLABLE TIKEUT EO RIEULMIEUM * +U+B35F(2);; # HANGUL SYLLABLE TIKEUT EO RIEULPIEUP * +U+B360(2);; # HANGUL SYLLABLE TIKEUT EO RIEULSIOS +U+B361(2);; # HANGUL SYLLABLE TIKEUT EO RIEULTHIEUTH +U+B362(2);; # HANGUL SYLLABLE TIKEUT EO RIEULPHIEUPH +U+B363(2);; # HANGUL SYLLABLE TIKEUT EO RIEULHIEUH +U+B364(2);; # HANGUL SYLLABLE TIKEUT EO MIEUM * +U+B365(2);; # HANGUL SYLLABLE TIKEUT EO PIEUP * +U+B366(2);; # HANGUL SYLLABLE TIKEUT EO PIEUPSIOS +U+B367(2);; # HANGUL SYLLABLE TIKEUT EO SIOS * +U+B368(2);; # HANGUL SYLLABLE TIKEUT EO SSANGSIOS +U+B369(2);; # HANGUL SYLLABLE TIKEUT EO IEUNG * +U+B36A(2);; # HANGUL SYLLABLE TIKEUT EO CIEUC +U+B36B(2);; # HANGUL SYLLABLE TIKEUT EO CHIEUCH * +U+B36C(2);; # HANGUL SYLLABLE TIKEUT EO KHIEUKH +U+B36D(2);; # HANGUL SYLLABLE TIKEUT EO THIEUTH +U+B36E(2);; # HANGUL SYLLABLE TIKEUT EO PHIEUPH * +U+B36F(2);; # HANGUL SYLLABLE TIKEUT EO HIEUH +U+B370(2);; # HANGUL SYLLABLE TIKEUT E * +U+B371(2);; # HANGUL SYLLABLE TIKEUT E KIYEOK * +U+B372(2);; # HANGUL SYLLABLE TIKEUT E SSANGKIYEOK +U+B373(2);; # HANGUL SYLLABLE TIKEUT E KIYEOKSIOS +U+B374(2);; # HANGUL SYLLABLE TIKEUT E NIEUN * +U+B375(2);; # HANGUL SYLLABLE TIKEUT E NIEUNCIEUC +U+B376(2);; # HANGUL SYLLABLE TIKEUT E NIEUNHIEUH +U+B377(2);; # HANGUL SYLLABLE TIKEUT E TIKEUT +U+B378(2);; # HANGUL SYLLABLE TIKEUT E RIEUL * +U+B379(2);; # HANGUL SYLLABLE TIKEUT E RIEULKIYEOK +U+B37A(2);; # HANGUL SYLLABLE TIKEUT E RIEULMIEUM +U+B37B(2);; # HANGUL SYLLABLE TIKEUT E RIEULPIEUP +U+B37C(2);; # HANGUL SYLLABLE TIKEUT E RIEULSIOS +U+B37D(2);; # HANGUL SYLLABLE TIKEUT E RIEULTHIEUTH +U+B37E(2);; # HANGUL SYLLABLE TIKEUT E RIEULPHIEUPH +U+B37F(2);; # HANGUL SYLLABLE TIKEUT E RIEULHIEUH +U+B380(2);; # HANGUL SYLLABLE TIKEUT E MIEUM * +U+B381(2);; # HANGUL SYLLABLE TIKEUT E PIEUP * +U+B382(2);; # HANGUL SYLLABLE TIKEUT E PIEUPSIOS +U+B383(2);; # HANGUL SYLLABLE TIKEUT E SIOS * +U+B384(2);; # HANGUL SYLLABLE TIKEUT E SSANGSIOS * +U+B385(2);; # HANGUL SYLLABLE TIKEUT E IEUNG * +U+B386(2);; # HANGUL SYLLABLE TIKEUT E CIEUC +U+B387(2);; # HANGUL SYLLABLE TIKEUT E CHIEUCH +U+B388(2);; # HANGUL SYLLABLE TIKEUT E KHIEUKH +U+B389(2);; # HANGUL SYLLABLE TIKEUT E THIEUTH +U+B38A(2);; # HANGUL SYLLABLE TIKEUT E PHIEUPH +U+B38B(2);; # HANGUL SYLLABLE TIKEUT E HIEUH +U+B38C(2);; # HANGUL SYLLABLE TIKEUT YEO * +U+B38D(2);; # HANGUL SYLLABLE TIKEUT YEO KIYEOK +U+B38E(2);; # HANGUL SYLLABLE TIKEUT YEO SSANGKIYEOK +U+B38F(2);; # HANGUL SYLLABLE TIKEUT YEO KIYEOKSIOS +U+B390(2);; # HANGUL SYLLABLE TIKEUT YEO NIEUN * +U+B391(2);; # HANGUL SYLLABLE TIKEUT YEO NIEUNCIEUC +U+B392(2);; # HANGUL SYLLABLE TIKEUT YEO NIEUNHIEUH +U+B393(2);; # HANGUL SYLLABLE TIKEUT YEO TIKEUT +U+B394(2);; # HANGUL SYLLABLE TIKEUT YEO RIEUL * +U+B395(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULKIYEOK +U+B396(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULMIEUM +U+B397(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULPIEUP +U+B398(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULSIOS +U+B399(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULTHIEUTH +U+B39A(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULPHIEUPH +U+B39B(2);; # HANGUL SYLLABLE TIKEUT YEO RIEULHIEUH +U+B39C(2);; # HANGUL SYLLABLE TIKEUT YEO MIEUM +U+B39D(2);; # HANGUL SYLLABLE TIKEUT YEO PIEUP +U+B39E(2);; # HANGUL SYLLABLE TIKEUT YEO PIEUPSIOS +U+B39F(2);; # HANGUL SYLLABLE TIKEUT YEO SIOS +U+B3A0(2);; # HANGUL SYLLABLE TIKEUT YEO SSANGSIOS * +U+B3A1(2);; # HANGUL SYLLABLE TIKEUT YEO IEUNG * +U+B3A2(2);; # HANGUL SYLLABLE TIKEUT YEO CIEUC +U+B3A3(2);; # HANGUL SYLLABLE TIKEUT YEO CHIEUCH +U+B3A4(2);; # HANGUL SYLLABLE TIKEUT YEO KHIEUKH +U+B3A5(2);; # HANGUL SYLLABLE TIKEUT YEO THIEUTH +U+B3A6(2);; # HANGUL SYLLABLE TIKEUT YEO PHIEUPH +U+B3A7(2);; # HANGUL SYLLABLE TIKEUT YEO HIEUH +U+B3A8(2);; # HANGUL SYLLABLE TIKEUT YE * +U+B3A9(2);; # HANGUL SYLLABLE TIKEUT YE KIYEOK +U+B3AA(2);; # HANGUL SYLLABLE TIKEUT YE SSANGKIYEOK +U+B3AB(2);; # HANGUL SYLLABLE TIKEUT YE KIYEOKSIOS +U+B3AC(2);; # HANGUL SYLLABLE TIKEUT YE NIEUN * +U+B3AD(2);; # HANGUL SYLLABLE TIKEUT YE NIEUNCIEUC +U+B3AE(2);; # HANGUL SYLLABLE TIKEUT YE NIEUNHIEUH +U+B3AF(2);; # HANGUL SYLLABLE TIKEUT YE TIKEUT +U+B3B0(2);; # HANGUL SYLLABLE TIKEUT YE RIEUL +U+B3B1(2);; # HANGUL SYLLABLE TIKEUT YE RIEULKIYEOK +U+B3B2(2);; # HANGUL SYLLABLE TIKEUT YE RIEULMIEUM +U+B3B3(2);; # HANGUL SYLLABLE TIKEUT YE RIEULPIEUP +U+B3B4(2);; # HANGUL SYLLABLE TIKEUT YE RIEULSIOS +U+B3B5(2);; # HANGUL SYLLABLE TIKEUT YE RIEULTHIEUTH +U+B3B6(2);; # HANGUL SYLLABLE TIKEUT YE RIEULPHIEUPH +U+B3B7(2);; # HANGUL SYLLABLE TIKEUT YE RIEULHIEUH +U+B3B8(2);; # HANGUL SYLLABLE TIKEUT YE MIEUM +U+B3B9(2);; # HANGUL SYLLABLE TIKEUT YE PIEUP +U+B3BA(2);; # HANGUL SYLLABLE TIKEUT YE PIEUPSIOS +U+B3BB(2);; # HANGUL SYLLABLE TIKEUT YE SIOS +U+B3BC(2);; # HANGUL SYLLABLE TIKEUT YE SSANGSIOS +U+B3BD(2);; # HANGUL SYLLABLE TIKEUT YE IEUNG +U+B3BE(2);; # HANGUL SYLLABLE TIKEUT YE CIEUC +U+B3BF(2);; # HANGUL SYLLABLE TIKEUT YE CHIEUCH +U+B3C0(2);; # HANGUL SYLLABLE TIKEUT YE KHIEUKH +U+B3C1(2);; # HANGUL SYLLABLE TIKEUT YE THIEUTH +U+B3C2(2);; # HANGUL SYLLABLE TIKEUT YE PHIEUPH +U+B3C3(2);; # HANGUL SYLLABLE TIKEUT YE HIEUH +U+B3C4(2);; # HANGUL SYLLABLE TIKEUT O * +U+B3C5(2);; # HANGUL SYLLABLE TIKEUT O KIYEOK * +U+B3C6(2);; # HANGUL SYLLABLE TIKEUT O SSANGKIYEOK +U+B3C7(2);; # HANGUL SYLLABLE TIKEUT O KIYEOKSIOS +U+B3C8(2);; # HANGUL SYLLABLE TIKEUT O NIEUN * +U+B3C9(2);; # HANGUL SYLLABLE TIKEUT O NIEUNCIEUC +U+B3CA(2);; # HANGUL SYLLABLE TIKEUT O NIEUNHIEUH +U+B3CB(2);; # HANGUL SYLLABLE TIKEUT O TIKEUT * +U+B3CC(2);; # HANGUL SYLLABLE TIKEUT O RIEUL * +U+B3CD(2);; # HANGUL SYLLABLE TIKEUT O RIEULKIYEOK +U+B3CE(2);; # HANGUL SYLLABLE TIKEUT O RIEULMIEUM * +U+B3CF(2);; # HANGUL SYLLABLE TIKEUT O RIEULPIEUP +U+B3D0(2);; # HANGUL SYLLABLE TIKEUT O RIEULSIOS * +U+B3D1(2);; # HANGUL SYLLABLE TIKEUT O RIEULTHIEUTH +U+B3D2(2);; # HANGUL SYLLABLE TIKEUT O RIEULPHIEUPH +U+B3D3(2);; # HANGUL SYLLABLE TIKEUT O RIEULHIEUH +U+B3D4(2);; # HANGUL SYLLABLE TIKEUT O MIEUM * +U+B3D5(2);; # HANGUL SYLLABLE TIKEUT O PIEUP * +U+B3D6(2);; # HANGUL SYLLABLE TIKEUT O PIEUPSIOS +U+B3D7(2);; # HANGUL SYLLABLE TIKEUT O SIOS * +U+B3D8(2);; # HANGUL SYLLABLE TIKEUT O SSANGSIOS +U+B3D9(2);; # HANGUL SYLLABLE TIKEUT O IEUNG * +U+B3DA(2);; # HANGUL SYLLABLE TIKEUT O CIEUC +U+B3DB(2);; # HANGUL SYLLABLE TIKEUT O CHIEUCH * +U+B3DC(2);; # HANGUL SYLLABLE TIKEUT O KHIEUKH +U+B3DD(2);; # HANGUL SYLLABLE TIKEUT O THIEUTH * +U+B3DE(2);; # HANGUL SYLLABLE TIKEUT O PHIEUPH +U+B3DF(2);; # HANGUL SYLLABLE TIKEUT O HIEUH +U+B3E0(2);; # HANGUL SYLLABLE TIKEUT WA * +U+B3E1(2);; # HANGUL SYLLABLE TIKEUT WA KIYEOK +U+B3E2(2);; # HANGUL SYLLABLE TIKEUT WA SSANGKIYEOK +U+B3E3(2);; # HANGUL SYLLABLE TIKEUT WA KIYEOKSIOS +U+B3E4(2);; # HANGUL SYLLABLE TIKEUT WA NIEUN * +U+B3E5(2);; # HANGUL SYLLABLE TIKEUT WA NIEUNCIEUC +U+B3E6(2);; # HANGUL SYLLABLE TIKEUT WA NIEUNHIEUH +U+B3E7(2);; # HANGUL SYLLABLE TIKEUT WA TIKEUT +U+B3E8(2);; # HANGUL SYLLABLE TIKEUT WA RIEUL * +U+B3E9(2);; # HANGUL SYLLABLE TIKEUT WA RIEULKIYEOK +U+B3EA(2);; # HANGUL SYLLABLE TIKEUT WA RIEULMIEUM +U+B3EB(2);; # HANGUL SYLLABLE TIKEUT WA RIEULPIEUP +U+B3EC(2);; # HANGUL SYLLABLE TIKEUT WA RIEULSIOS +U+B3ED(2);; # HANGUL SYLLABLE TIKEUT WA RIEULTHIEUTH +U+B3EE(2);; # HANGUL SYLLABLE TIKEUT WA RIEULPHIEUPH +U+B3EF(2);; # HANGUL SYLLABLE TIKEUT WA RIEULHIEUH +U+B3F0(2);; # HANGUL SYLLABLE TIKEUT WA MIEUM +U+B3F1(2);; # HANGUL SYLLABLE TIKEUT WA PIEUP +U+B3F2(2);; # HANGUL SYLLABLE TIKEUT WA PIEUPSIOS +U+B3F3(2);; # HANGUL SYLLABLE TIKEUT WA SIOS +U+B3F4(2);; # HANGUL SYLLABLE TIKEUT WA SSANGSIOS +U+B3F5(2);; # HANGUL SYLLABLE TIKEUT WA IEUNG +U+B3F6(2);; # HANGUL SYLLABLE TIKEUT WA CIEUC +U+B3F7(2);; # HANGUL SYLLABLE TIKEUT WA CHIEUCH +U+B3F8(2);; # HANGUL SYLLABLE TIKEUT WA KHIEUKH +U+B3F9(2);; # HANGUL SYLLABLE TIKEUT WA THIEUTH +U+B3FA(2);; # HANGUL SYLLABLE TIKEUT WA PHIEUPH +U+B3FB(2);; # HANGUL SYLLABLE TIKEUT WA HIEUH +U+B3FC(2);; # HANGUL SYLLABLE TIKEUT WAE * +U+B3FD(2);; # HANGUL SYLLABLE TIKEUT WAE KIYEOK +U+B3FE(2);; # HANGUL SYLLABLE TIKEUT WAE SSANGKIYEOK +U+B3FF(2);; # HANGUL SYLLABLE TIKEUT WAE KIYEOKSIOS +U+B400(2);; # HANGUL SYLLABLE TIKEUT WAE NIEUN +U+B401(2);; # HANGUL SYLLABLE TIKEUT WAE NIEUNCIEUC +U+B402(2);; # HANGUL SYLLABLE TIKEUT WAE NIEUNHIEUH +U+B403(2);; # HANGUL SYLLABLE TIKEUT WAE TIKEUT +U+B404(2);; # HANGUL SYLLABLE TIKEUT WAE RIEUL +U+B405(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULKIYEOK +U+B406(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULMIEUM +U+B407(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULPIEUP +U+B408(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULSIOS +U+B409(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULTHIEUTH +U+B40A(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULPHIEUPH +U+B40B(2);; # HANGUL SYLLABLE TIKEUT WAE RIEULHIEUH +U+B40C(2);; # HANGUL SYLLABLE TIKEUT WAE MIEUM +U+B40D(2);; # HANGUL SYLLABLE TIKEUT WAE PIEUP +U+B40E(2);; # HANGUL SYLLABLE TIKEUT WAE PIEUPSIOS +U+B40F(2);; # HANGUL SYLLABLE TIKEUT WAE SIOS +U+B410(2);; # HANGUL SYLLABLE TIKEUT WAE SSANGSIOS * +U+B411(2);; # HANGUL SYLLABLE TIKEUT WAE IEUNG +U+B412(2);; # HANGUL SYLLABLE TIKEUT WAE CIEUC +U+B413(2);; # HANGUL SYLLABLE TIKEUT WAE CHIEUCH +U+B414(2);; # HANGUL SYLLABLE TIKEUT WAE KHIEUKH +U+B415(2);; # HANGUL SYLLABLE TIKEUT WAE THIEUTH +U+B416(2);; # HANGUL SYLLABLE TIKEUT WAE PHIEUPH +U+B417(2);; # HANGUL SYLLABLE TIKEUT WAE HIEUH +U+B418(2);; # HANGUL SYLLABLE TIKEUT OE * +U+B419(2);; # HANGUL SYLLABLE TIKEUT OE KIYEOK +U+B41A(2);; # HANGUL SYLLABLE TIKEUT OE SSANGKIYEOK +U+B41B(2);; # HANGUL SYLLABLE TIKEUT OE KIYEOKSIOS +U+B41C(2);; # HANGUL SYLLABLE TIKEUT OE NIEUN * +U+B41D(2);; # HANGUL SYLLABLE TIKEUT OE NIEUNCIEUC +U+B41E(2);; # HANGUL SYLLABLE TIKEUT OE NIEUNHIEUH +U+B41F(2);; # HANGUL SYLLABLE TIKEUT OE TIKEUT +U+B420(2);; # HANGUL SYLLABLE TIKEUT OE RIEUL * +U+B421(2);; # HANGUL SYLLABLE TIKEUT OE RIEULKIYEOK +U+B422(2);; # HANGUL SYLLABLE TIKEUT OE RIEULMIEUM +U+B423(2);; # HANGUL SYLLABLE TIKEUT OE RIEULPIEUP +U+B424(2);; # HANGUL SYLLABLE TIKEUT OE RIEULSIOS +U+B425(2);; # HANGUL SYLLABLE TIKEUT OE RIEULTHIEUTH +U+B426(2);; # HANGUL SYLLABLE TIKEUT OE RIEULPHIEUPH +U+B427(2);; # HANGUL SYLLABLE TIKEUT OE RIEULHIEUH +U+B428(2);; # HANGUL SYLLABLE TIKEUT OE MIEUM * +U+B429(2);; # HANGUL SYLLABLE TIKEUT OE PIEUP * +U+B42A(2);; # HANGUL SYLLABLE TIKEUT OE PIEUPSIOS +U+B42B(2);; # HANGUL SYLLABLE TIKEUT OE SIOS * +U+B42C(2);; # HANGUL SYLLABLE TIKEUT OE SSANGSIOS +U+B42D(2);; # HANGUL SYLLABLE TIKEUT OE IEUNG +U+B42E(2);; # HANGUL SYLLABLE TIKEUT OE CIEUC +U+B42F(2);; # HANGUL SYLLABLE TIKEUT OE CHIEUCH +U+B430(2);; # HANGUL SYLLABLE TIKEUT OE KHIEUKH +U+B431(2);; # HANGUL SYLLABLE TIKEUT OE THIEUTH +U+B432(2);; # HANGUL SYLLABLE TIKEUT OE PHIEUPH +U+B433(2);; # HANGUL SYLLABLE TIKEUT OE HIEUH +U+B434(2);; # HANGUL SYLLABLE TIKEUT YO * +U+B435(2);; # HANGUL SYLLABLE TIKEUT YO KIYEOK +U+B436(2);; # HANGUL SYLLABLE TIKEUT YO SSANGKIYEOK +U+B437(2);; # HANGUL SYLLABLE TIKEUT YO KIYEOKSIOS +U+B438(2);; # HANGUL SYLLABLE TIKEUT YO NIEUN +U+B439(2);; # HANGUL SYLLABLE TIKEUT YO NIEUNCIEUC +U+B43A(2);; # HANGUL SYLLABLE TIKEUT YO NIEUNHIEUH +U+B43B(2);; # HANGUL SYLLABLE TIKEUT YO TIKEUT +U+B43C(2);; # HANGUL SYLLABLE TIKEUT YO RIEUL +U+B43D(2);; # HANGUL SYLLABLE TIKEUT YO RIEULKIYEOK +U+B43E(2);; # HANGUL SYLLABLE TIKEUT YO RIEULMIEUM +U+B43F(2);; # HANGUL SYLLABLE TIKEUT YO RIEULPIEUP +U+B440(2);; # HANGUL SYLLABLE TIKEUT YO RIEULSIOS +U+B441(2);; # HANGUL SYLLABLE TIKEUT YO RIEULTHIEUTH +U+B442(2);; # HANGUL SYLLABLE TIKEUT YO RIEULPHIEUPH +U+B443(2);; # HANGUL SYLLABLE TIKEUT YO RIEULHIEUH +U+B444(2);; # HANGUL SYLLABLE TIKEUT YO MIEUM +U+B445(2);; # HANGUL SYLLABLE TIKEUT YO PIEUP +U+B446(2);; # HANGUL SYLLABLE TIKEUT YO PIEUPSIOS +U+B447(2);; # HANGUL SYLLABLE TIKEUT YO SIOS +U+B448(2);; # HANGUL SYLLABLE TIKEUT YO SSANGSIOS +U+B449(2);; # HANGUL SYLLABLE TIKEUT YO IEUNG +U+B44A(2);; # HANGUL SYLLABLE TIKEUT YO CIEUC +U+B44B(2);; # HANGUL SYLLABLE TIKEUT YO CHIEUCH +U+B44C(2);; # HANGUL SYLLABLE TIKEUT YO KHIEUKH +U+B44D(2);; # HANGUL SYLLABLE TIKEUT YO THIEUTH +U+B44E(2);; # HANGUL SYLLABLE TIKEUT YO PHIEUPH +U+B44F(2);; # HANGUL SYLLABLE TIKEUT YO HIEUH +U+B450(2);; # HANGUL SYLLABLE TIKEUT U * +U+B451(2);; # HANGUL SYLLABLE TIKEUT U KIYEOK * +U+B452(2);; # HANGUL SYLLABLE TIKEUT U SSANGKIYEOK +U+B453(2);; # HANGUL SYLLABLE TIKEUT U KIYEOKSIOS +U+B454(2);; # HANGUL SYLLABLE TIKEUT U NIEUN * +U+B455(2);; # HANGUL SYLLABLE TIKEUT U NIEUNCIEUC +U+B456(2);; # HANGUL SYLLABLE TIKEUT U NIEUNHIEUH +U+B457(2);; # HANGUL SYLLABLE TIKEUT U TIKEUT +U+B458(2);; # HANGUL SYLLABLE TIKEUT U RIEUL * +U+B459(2);; # HANGUL SYLLABLE TIKEUT U RIEULKIYEOK +U+B45A(2);; # HANGUL SYLLABLE TIKEUT U RIEULMIEUM +U+B45B(2);; # HANGUL SYLLABLE TIKEUT U RIEULPIEUP +U+B45C(2);; # HANGUL SYLLABLE TIKEUT U RIEULSIOS +U+B45D(2);; # HANGUL SYLLABLE TIKEUT U RIEULTHIEUTH +U+B45E(2);; # HANGUL SYLLABLE TIKEUT U RIEULPHIEUPH +U+B45F(2);; # HANGUL SYLLABLE TIKEUT U RIEULHIEUH +U+B460(2);; # HANGUL SYLLABLE TIKEUT U MIEUM * +U+B461(2);; # HANGUL SYLLABLE TIKEUT U PIEUP * +U+B462(2);; # HANGUL SYLLABLE TIKEUT U PIEUPSIOS +U+B463(2);; # HANGUL SYLLABLE TIKEUT U SIOS * +U+B464(2);; # HANGUL SYLLABLE TIKEUT U SSANGSIOS +U+B465(2);; # HANGUL SYLLABLE TIKEUT U IEUNG * +U+B466(2);; # HANGUL SYLLABLE TIKEUT U CIEUC +U+B467(2);; # HANGUL SYLLABLE TIKEUT U CHIEUCH +U+B468(2);; # HANGUL SYLLABLE TIKEUT U KHIEUKH +U+B469(2);; # HANGUL SYLLABLE TIKEUT U THIEUTH +U+B46A(2);; # HANGUL SYLLABLE TIKEUT U PHIEUPH +U+B46B(2);; # HANGUL SYLLABLE TIKEUT U HIEUH +U+B46C(2);; # HANGUL SYLLABLE TIKEUT WEO * +U+B46D(2);; # HANGUL SYLLABLE TIKEUT WEO KIYEOK +U+B46E(2);; # HANGUL SYLLABLE TIKEUT WEO SSANGKIYEOK +U+B46F(2);; # HANGUL SYLLABLE TIKEUT WEO KIYEOKSIOS +U+B470(2);; # HANGUL SYLLABLE TIKEUT WEO NIEUN +U+B471(2);; # HANGUL SYLLABLE TIKEUT WEO NIEUNCIEUC +U+B472(2);; # HANGUL SYLLABLE TIKEUT WEO NIEUNHIEUH +U+B473(2);; # HANGUL SYLLABLE TIKEUT WEO TIKEUT +U+B474(2);; # HANGUL SYLLABLE TIKEUT WEO RIEUL +U+B475(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULKIYEOK +U+B476(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULMIEUM +U+B477(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULPIEUP +U+B478(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULSIOS +U+B479(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULTHIEUTH +U+B47A(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULPHIEUPH +U+B47B(2);; # HANGUL SYLLABLE TIKEUT WEO RIEULHIEUH +U+B47C(2);; # HANGUL SYLLABLE TIKEUT WEO MIEUM +U+B47D(2);; # HANGUL SYLLABLE TIKEUT WEO PIEUP +U+B47E(2);; # HANGUL SYLLABLE TIKEUT WEO PIEUPSIOS +U+B47F(2);; # HANGUL SYLLABLE TIKEUT WEO SIOS +U+B480(2);; # HANGUL SYLLABLE TIKEUT WEO SSANGSIOS * +U+B481(2);; # HANGUL SYLLABLE TIKEUT WEO IEUNG +U+B482(2);; # HANGUL SYLLABLE TIKEUT WEO CIEUC +U+B483(2);; # HANGUL SYLLABLE TIKEUT WEO CHIEUCH +U+B484(2);; # HANGUL SYLLABLE TIKEUT WEO KHIEUKH +U+B485(2);; # HANGUL SYLLABLE TIKEUT WEO THIEUTH +U+B486(2);; # HANGUL SYLLABLE TIKEUT WEO PHIEUPH +U+B487(2);; # HANGUL SYLLABLE TIKEUT WEO HIEUH +U+B488(2);; # HANGUL SYLLABLE TIKEUT WE * +U+B489(2);; # HANGUL SYLLABLE TIKEUT WE KIYEOK +U+B48A(2);; # HANGUL SYLLABLE TIKEUT WE SSANGKIYEOK +U+B48B(2);; # HANGUL SYLLABLE TIKEUT WE KIYEOKSIOS +U+B48C(2);; # HANGUL SYLLABLE TIKEUT WE NIEUN +U+B48D(2);; # HANGUL SYLLABLE TIKEUT WE NIEUNCIEUC +U+B48E(2);; # HANGUL SYLLABLE TIKEUT WE NIEUNHIEUH +U+B48F(2);; # HANGUL SYLLABLE TIKEUT WE TIKEUT +U+B490(2);; # HANGUL SYLLABLE TIKEUT WE RIEUL +U+B491(2);; # HANGUL SYLLABLE TIKEUT WE RIEULKIYEOK +U+B492(2);; # HANGUL SYLLABLE TIKEUT WE RIEULMIEUM +U+B493(2);; # HANGUL SYLLABLE TIKEUT WE RIEULPIEUP +U+B494(2);; # HANGUL SYLLABLE TIKEUT WE RIEULSIOS +U+B495(2);; # HANGUL SYLLABLE TIKEUT WE RIEULTHIEUTH +U+B496(2);; # HANGUL SYLLABLE TIKEUT WE RIEULPHIEUPH +U+B497(2);; # HANGUL SYLLABLE TIKEUT WE RIEULHIEUH +U+B498(2);; # HANGUL SYLLABLE TIKEUT WE MIEUM +U+B499(2);; # HANGUL SYLLABLE TIKEUT WE PIEUP +U+B49A(2);; # HANGUL SYLLABLE TIKEUT WE PIEUPSIOS +U+B49B(2);; # HANGUL SYLLABLE TIKEUT WE SIOS +U+B49C(2);; # HANGUL SYLLABLE TIKEUT WE SSANGSIOS +U+B49D(2);; # HANGUL SYLLABLE TIKEUT WE IEUNG * +U+B49E(2);; # HANGUL SYLLABLE TIKEUT WE CIEUC +U+B49F(2);; # HANGUL SYLLABLE TIKEUT WE CHIEUCH +U+B4A0(2);; # HANGUL SYLLABLE TIKEUT WE KHIEUKH +U+B4A1(2);; # HANGUL SYLLABLE TIKEUT WE THIEUTH +U+B4A2(2);; # HANGUL SYLLABLE TIKEUT WE PHIEUPH +U+B4A3(2);; # HANGUL SYLLABLE TIKEUT WE HIEUH +U+B4A4(2);; # HANGUL SYLLABLE TIKEUT WI * +U+B4A5(2);; # HANGUL SYLLABLE TIKEUT WI KIYEOK +U+B4A6(2);; # HANGUL SYLLABLE TIKEUT WI SSANGKIYEOK +U+B4A7(2);; # HANGUL SYLLABLE TIKEUT WI KIYEOKSIOS +U+B4A8(2);; # HANGUL SYLLABLE TIKEUT WI NIEUN * +U+B4A9(2);; # HANGUL SYLLABLE TIKEUT WI NIEUNCIEUC +U+B4AA(2);; # HANGUL SYLLABLE TIKEUT WI NIEUNHIEUH +U+B4AB(2);; # HANGUL SYLLABLE TIKEUT WI TIKEUT +U+B4AC(2);; # HANGUL SYLLABLE TIKEUT WI RIEUL * +U+B4AD(2);; # HANGUL SYLLABLE TIKEUT WI RIEULKIYEOK +U+B4AE(2);; # HANGUL SYLLABLE TIKEUT WI RIEULMIEUM +U+B4AF(2);; # HANGUL SYLLABLE TIKEUT WI RIEULPIEUP +U+B4B0(2);; # HANGUL SYLLABLE TIKEUT WI RIEULSIOS +U+B4B1(2);; # HANGUL SYLLABLE TIKEUT WI RIEULTHIEUTH +U+B4B2(2);; # HANGUL SYLLABLE TIKEUT WI RIEULPHIEUPH +U+B4B3(2);; # HANGUL SYLLABLE TIKEUT WI RIEULHIEUH +U+B4B4(2);; # HANGUL SYLLABLE TIKEUT WI MIEUM +U+B4B5(2);; # HANGUL SYLLABLE TIKEUT WI PIEUP * +U+B4B6(2);; # HANGUL SYLLABLE TIKEUT WI PIEUPSIOS +U+B4B7(2);; # HANGUL SYLLABLE TIKEUT WI SIOS * +U+B4B8(2);; # HANGUL SYLLABLE TIKEUT WI SSANGSIOS +U+B4B9(2);; # HANGUL SYLLABLE TIKEUT WI IEUNG * +U+B4BA(2);; # HANGUL SYLLABLE TIKEUT WI CIEUC +U+B4BB(2);; # HANGUL SYLLABLE TIKEUT WI CHIEUCH +U+B4BC(2);; # HANGUL SYLLABLE TIKEUT WI KHIEUKH +U+B4BD(2);; # HANGUL SYLLABLE TIKEUT WI THIEUTH +U+B4BE(2);; # HANGUL SYLLABLE TIKEUT WI PHIEUPH +U+B4BF(2);; # HANGUL SYLLABLE TIKEUT WI HIEUH +U+B4C0(2);; # HANGUL SYLLABLE TIKEUT YU * +U+B4C1(2);; # HANGUL SYLLABLE TIKEUT YU KIYEOK +U+B4C2(2);; # HANGUL SYLLABLE TIKEUT YU SSANGKIYEOK +U+B4C3(2);; # HANGUL SYLLABLE TIKEUT YU KIYEOKSIOS +U+B4C4(2);; # HANGUL SYLLABLE TIKEUT YU NIEUN * +U+B4C5(2);; # HANGUL SYLLABLE TIKEUT YU NIEUNCIEUC +U+B4C6(2);; # HANGUL SYLLABLE TIKEUT YU NIEUNHIEUH +U+B4C7(2);; # HANGUL SYLLABLE TIKEUT YU TIKEUT +U+B4C8(2);; # HANGUL SYLLABLE TIKEUT YU RIEUL * +U+B4C9(2);; # HANGUL SYLLABLE TIKEUT YU RIEULKIYEOK +U+B4CA(2);; # HANGUL SYLLABLE TIKEUT YU RIEULMIEUM +U+B4CB(2);; # HANGUL SYLLABLE TIKEUT YU RIEULPIEUP +U+B4CC(2);; # HANGUL SYLLABLE TIKEUT YU RIEULSIOS +U+B4CD(2);; # HANGUL SYLLABLE TIKEUT YU RIEULTHIEUTH +U+B4CE(2);; # HANGUL SYLLABLE TIKEUT YU RIEULPHIEUPH +U+B4CF(2);; # HANGUL SYLLABLE TIKEUT YU RIEULHIEUH +U+B4D0(2);; # HANGUL SYLLABLE TIKEUT YU MIEUM * +U+B4D1(2);; # HANGUL SYLLABLE TIKEUT YU PIEUP +U+B4D2(2);; # HANGUL SYLLABLE TIKEUT YU PIEUPSIOS +U+B4D3(2);; # HANGUL SYLLABLE TIKEUT YU SIOS +U+B4D4(2);; # HANGUL SYLLABLE TIKEUT YU SSANGSIOS +U+B4D5(2);; # HANGUL SYLLABLE TIKEUT YU IEUNG * +U+B4D6(2);; # HANGUL SYLLABLE TIKEUT YU CIEUC +U+B4D7(2);; # HANGUL SYLLABLE TIKEUT YU CHIEUCH +U+B4D8(2);; # HANGUL SYLLABLE TIKEUT YU KHIEUKH +U+B4D9(2);; # HANGUL SYLLABLE TIKEUT YU THIEUTH +U+B4DA(2);; # HANGUL SYLLABLE TIKEUT YU PHIEUPH +U+B4DB(2);; # HANGUL SYLLABLE TIKEUT YU HIEUH +U+B4DC(2);; # HANGUL SYLLABLE TIKEUT EU * +U+B4DD(2);; # HANGUL SYLLABLE TIKEUT EU KIYEOK * +U+B4DE(2);; # HANGUL SYLLABLE TIKEUT EU SSANGKIYEOK +U+B4DF(2);; # HANGUL SYLLABLE TIKEUT EU KIYEOKSIOS +U+B4E0(2);; # HANGUL SYLLABLE TIKEUT EU NIEUN * +U+B4E1(2);; # HANGUL SYLLABLE TIKEUT EU NIEUNCIEUC +U+B4E2(2);; # HANGUL SYLLABLE TIKEUT EU NIEUNHIEUH +U+B4E3(2);; # HANGUL SYLLABLE TIKEUT EU TIKEUT * +U+B4E4(2);; # HANGUL SYLLABLE TIKEUT EU RIEUL * +U+B4E5(2);; # HANGUL SYLLABLE TIKEUT EU RIEULKIYEOK +U+B4E6(2);; # HANGUL SYLLABLE TIKEUT EU RIEULMIEUM * +U+B4E7(2);; # HANGUL SYLLABLE TIKEUT EU RIEULPIEUP +U+B4E8(2);; # HANGUL SYLLABLE TIKEUT EU RIEULSIOS +U+B4E9(2);; # HANGUL SYLLABLE TIKEUT EU RIEULTHIEUTH +U+B4EA(2);; # HANGUL SYLLABLE TIKEUT EU RIEULPHIEUPH +U+B4EB(2);; # HANGUL SYLLABLE TIKEUT EU RIEULHIEUH +U+B4EC(2);; # HANGUL SYLLABLE TIKEUT EU MIEUM * +U+B4ED(2);; # HANGUL SYLLABLE TIKEUT EU PIEUP * +U+B4EE(2);; # HANGUL SYLLABLE TIKEUT EU PIEUPSIOS +U+B4EF(2);; # HANGUL SYLLABLE TIKEUT EU SIOS * +U+B4F0(2);; # HANGUL SYLLABLE TIKEUT EU SSANGSIOS +U+B4F1(2);; # HANGUL SYLLABLE TIKEUT EU IEUNG * +U+B4F2(2);; # HANGUL SYLLABLE TIKEUT EU CIEUC +U+B4F3(2);; # HANGUL SYLLABLE TIKEUT EU CHIEUCH +U+B4F4(2);; # HANGUL SYLLABLE TIKEUT EU KHIEUKH +U+B4F5(2);; # HANGUL SYLLABLE TIKEUT EU THIEUTH +U+B4F6(2);; # HANGUL SYLLABLE TIKEUT EU PHIEUPH +U+B4F7(2);; # HANGUL SYLLABLE TIKEUT EU HIEUH +U+B4F8(2);; # HANGUL SYLLABLE TIKEUT YI * +U+B4F9(2);; # HANGUL SYLLABLE TIKEUT YI KIYEOK +U+B4FA(2);; # HANGUL SYLLABLE TIKEUT YI SSANGKIYEOK +U+B4FB(2);; # HANGUL SYLLABLE TIKEUT YI KIYEOKSIOS +U+B4FC(2);; # HANGUL SYLLABLE TIKEUT YI NIEUN +U+B4FD(2);; # HANGUL SYLLABLE TIKEUT YI NIEUNCIEUC +U+B4FE(2);; # HANGUL SYLLABLE TIKEUT YI NIEUNHIEUH +U+B4FF(2);; # HANGUL SYLLABLE TIKEUT YI TIKEUT +U+B500(2);; # HANGUL SYLLABLE TIKEUT YI RIEUL +U+B501(2);; # HANGUL SYLLABLE TIKEUT YI RIEULKIYEOK +U+B502(2);; # HANGUL SYLLABLE TIKEUT YI RIEULMIEUM +U+B503(2);; # HANGUL SYLLABLE TIKEUT YI RIEULPIEUP +U+B504(2);; # HANGUL SYLLABLE TIKEUT YI RIEULSIOS +U+B505(2);; # HANGUL SYLLABLE TIKEUT YI RIEULTHIEUTH +U+B506(2);; # HANGUL SYLLABLE TIKEUT YI RIEULPHIEUPH +U+B507(2);; # HANGUL SYLLABLE TIKEUT YI RIEULHIEUH +U+B508(2);; # HANGUL SYLLABLE TIKEUT YI MIEUM +U+B509(2);; # HANGUL SYLLABLE TIKEUT YI PIEUP +U+B50A(2);; # HANGUL SYLLABLE TIKEUT YI PIEUPSIOS +U+B50B(2);; # HANGUL SYLLABLE TIKEUT YI SIOS +U+B50C(2);; # HANGUL SYLLABLE TIKEUT YI SSANGSIOS +U+B50D(2);; # HANGUL SYLLABLE TIKEUT YI IEUNG +U+B50E(2);; # HANGUL SYLLABLE TIKEUT YI CIEUC +U+B50F(2);; # HANGUL SYLLABLE TIKEUT YI CHIEUCH +U+B510(2);; # HANGUL SYLLABLE TIKEUT YI KHIEUKH +U+B511(2);; # HANGUL SYLLABLE TIKEUT YI THIEUTH +U+B512(2);; # HANGUL SYLLABLE TIKEUT YI PHIEUPH +U+B513(2);; # HANGUL SYLLABLE TIKEUT YI HIEUH +U+B514(2);; # HANGUL SYLLABLE TIKEUT I * +U+B515(2);; # HANGUL SYLLABLE TIKEUT I KIYEOK * +U+B516(2);; # HANGUL SYLLABLE TIKEUT I SSANGKIYEOK +U+B517(2);; # HANGUL SYLLABLE TIKEUT I KIYEOKSIOS +U+B518(2);; # HANGUL SYLLABLE TIKEUT I NIEUN * +U+B519(2);; # HANGUL SYLLABLE TIKEUT I NIEUNCIEUC +U+B51A(2);; # HANGUL SYLLABLE TIKEUT I NIEUNHIEUH +U+B51B(2);; # HANGUL SYLLABLE TIKEUT I TIKEUT * +U+B51C(2);; # HANGUL SYLLABLE TIKEUT I RIEUL * +U+B51D(2);; # HANGUL SYLLABLE TIKEUT I RIEULKIYEOK +U+B51E(2);; # HANGUL SYLLABLE TIKEUT I RIEULMIEUM +U+B51F(2);; # HANGUL SYLLABLE TIKEUT I RIEULPIEUP +U+B520(2);; # HANGUL SYLLABLE TIKEUT I RIEULSIOS +U+B521(2);; # HANGUL SYLLABLE TIKEUT I RIEULTHIEUTH +U+B522(2);; # HANGUL SYLLABLE TIKEUT I RIEULPHIEUPH +U+B523(2);; # HANGUL SYLLABLE TIKEUT I RIEULHIEUH +U+B524(2);; # HANGUL SYLLABLE TIKEUT I MIEUM * +U+B525(2);; # HANGUL SYLLABLE TIKEUT I PIEUP * +U+B526(2);; # HANGUL SYLLABLE TIKEUT I PIEUPSIOS +U+B527(2);; # HANGUL SYLLABLE TIKEUT I SIOS * +U+B528(2);; # HANGUL SYLLABLE TIKEUT I SSANGSIOS * +U+B529(2);; # HANGUL SYLLABLE TIKEUT I IEUNG * +U+B52A(2);; # HANGUL SYLLABLE TIKEUT I CIEUC * +U+B52B(2);; # HANGUL SYLLABLE TIKEUT I CHIEUCH +U+B52C(2);; # HANGUL SYLLABLE TIKEUT I KHIEUKH +U+B52D(2);; # HANGUL SYLLABLE TIKEUT I THIEUTH +U+B52E(2);; # HANGUL SYLLABLE TIKEUT I PHIEUPH +U+B52F(2);; # HANGUL SYLLABLE TIKEUT I HIEUH +U+B530(2);; # HANGUL SYLLABLE SSANGTIKEUT A * +U+B531(2);; # HANGUL SYLLABLE SSANGTIKEUT A KIYEOK * +U+B532(2);; # HANGUL SYLLABLE SSANGTIKEUT A SSANGKIYEOK +U+B533(2);; # HANGUL SYLLABLE SSANGTIKEUT A KIYEOKSIOS +U+B534(2);; # HANGUL SYLLABLE SSANGTIKEUT A NIEUN * +U+B535(2);; # HANGUL SYLLABLE SSANGTIKEUT A NIEUNCIEUC +U+B536(2);; # HANGUL SYLLABLE SSANGTIKEUT A NIEUNHIEUH +U+B537(2);; # HANGUL SYLLABLE SSANGTIKEUT A TIKEUT +U+B538(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEUL * +U+B539(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULKIYEOK +U+B53A(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULMIEUM +U+B53B(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULPIEUP +U+B53C(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULSIOS +U+B53D(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULTHIEUTH +U+B53E(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULPHIEUPH +U+B53F(2);; # HANGUL SYLLABLE SSANGTIKEUT A RIEULHIEUH +U+B540(2);; # HANGUL SYLLABLE SSANGTIKEUT A MIEUM * +U+B541(2);; # HANGUL SYLLABLE SSANGTIKEUT A PIEUP * +U+B542(2);; # HANGUL SYLLABLE SSANGTIKEUT A PIEUPSIOS +U+B543(2);; # HANGUL SYLLABLE SSANGTIKEUT A SIOS * +U+B544(2);; # HANGUL SYLLABLE SSANGTIKEUT A SSANGSIOS * +U+B545(2);; # HANGUL SYLLABLE SSANGTIKEUT A IEUNG * +U+B546(2);; # HANGUL SYLLABLE SSANGTIKEUT A CIEUC +U+B547(2);; # HANGUL SYLLABLE SSANGTIKEUT A CHIEUCH +U+B548(2);; # HANGUL SYLLABLE SSANGTIKEUT A KHIEUKH +U+B549(2);; # HANGUL SYLLABLE SSANGTIKEUT A THIEUTH +U+B54A(2);; # HANGUL SYLLABLE SSANGTIKEUT A PHIEUPH +U+B54B(2);; # HANGUL SYLLABLE SSANGTIKEUT A HIEUH * +U+B54C(2);; # HANGUL SYLLABLE SSANGTIKEUT AE * +U+B54D(2);; # HANGUL SYLLABLE SSANGTIKEUT AE KIYEOK * +U+B54E(2);; # HANGUL SYLLABLE SSANGTIKEUT AE SSANGKIYEOK +U+B54F(2);; # HANGUL SYLLABLE SSANGTIKEUT AE KIYEOKSIOS +U+B550(2);; # HANGUL SYLLABLE SSANGTIKEUT AE NIEUN * +U+B551(2);; # HANGUL SYLLABLE SSANGTIKEUT AE NIEUNCIEUC +U+B552(2);; # HANGUL SYLLABLE SSANGTIKEUT AE NIEUNHIEUH +U+B553(2);; # HANGUL SYLLABLE SSANGTIKEUT AE TIKEUT +U+B554(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEUL * +U+B555(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULKIYEOK +U+B556(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULMIEUM +U+B557(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULPIEUP +U+B558(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULSIOS +U+B559(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULTHIEUTH +U+B55A(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULPHIEUPH +U+B55B(2);; # HANGUL SYLLABLE SSANGTIKEUT AE RIEULHIEUH +U+B55C(2);; # HANGUL SYLLABLE SSANGTIKEUT AE MIEUM * +U+B55D(2);; # HANGUL SYLLABLE SSANGTIKEUT AE PIEUP * +U+B55E(2);; # HANGUL SYLLABLE SSANGTIKEUT AE PIEUPSIOS +U+B55F(2);; # HANGUL SYLLABLE SSANGTIKEUT AE SIOS * +U+B560(2);; # HANGUL SYLLABLE SSANGTIKEUT AE SSANGSIOS * +U+B561(2);; # HANGUL SYLLABLE SSANGTIKEUT AE IEUNG * +U+B562(2);; # HANGUL SYLLABLE SSANGTIKEUT AE CIEUC +U+B563(2);; # HANGUL SYLLABLE SSANGTIKEUT AE CHIEUCH +U+B564(2);; # HANGUL SYLLABLE SSANGTIKEUT AE KHIEUKH +U+B565(2);; # HANGUL SYLLABLE SSANGTIKEUT AE THIEUTH +U+B566(2);; # HANGUL SYLLABLE SSANGTIKEUT AE PHIEUPH +U+B567(2);; # HANGUL SYLLABLE SSANGTIKEUT AE HIEUH +U+B568(2);; # HANGUL SYLLABLE SSANGTIKEUT YA +U+B569(2);; # HANGUL SYLLABLE SSANGTIKEUT YA KIYEOK +U+B56A(2);; # HANGUL SYLLABLE SSANGTIKEUT YA SSANGKIYEOK +U+B56B(2);; # HANGUL SYLLABLE SSANGTIKEUT YA KIYEOKSIOS +U+B56C(2);; # HANGUL SYLLABLE SSANGTIKEUT YA NIEUN +U+B56D(2);; # HANGUL SYLLABLE SSANGTIKEUT YA NIEUNCIEUC +U+B56E(2);; # HANGUL SYLLABLE SSANGTIKEUT YA NIEUNHIEUH +U+B56F(2);; # HANGUL SYLLABLE SSANGTIKEUT YA TIKEUT +U+B570(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEUL +U+B571(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULKIYEOK +U+B572(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULMIEUM +U+B573(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULPIEUP +U+B574(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULSIOS +U+B575(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULTHIEUTH +U+B576(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULPHIEUPH +U+B577(2);; # HANGUL SYLLABLE SSANGTIKEUT YA RIEULHIEUH +U+B578(2);; # HANGUL SYLLABLE SSANGTIKEUT YA MIEUM +U+B579(2);; # HANGUL SYLLABLE SSANGTIKEUT YA PIEUP +U+B57A(2);; # HANGUL SYLLABLE SSANGTIKEUT YA PIEUPSIOS +U+B57B(2);; # HANGUL SYLLABLE SSANGTIKEUT YA SIOS +U+B57C(2);; # HANGUL SYLLABLE SSANGTIKEUT YA SSANGSIOS +U+B57D(2);; # HANGUL SYLLABLE SSANGTIKEUT YA IEUNG +U+B57E(2);; # HANGUL SYLLABLE SSANGTIKEUT YA CIEUC +U+B57F(2);; # HANGUL SYLLABLE SSANGTIKEUT YA CHIEUCH +U+B580(2);; # HANGUL SYLLABLE SSANGTIKEUT YA KHIEUKH +U+B581(2);; # HANGUL SYLLABLE SSANGTIKEUT YA THIEUTH +U+B582(2);; # HANGUL SYLLABLE SSANGTIKEUT YA PHIEUPH +U+B583(2);; # HANGUL SYLLABLE SSANGTIKEUT YA HIEUH +U+B584(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE +U+B585(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE KIYEOK +U+B586(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE SSANGKIYEOK +U+B587(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE KIYEOKSIOS +U+B588(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE NIEUN +U+B589(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE NIEUNCIEUC +U+B58A(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE NIEUNHIEUH +U+B58B(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE TIKEUT +U+B58C(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEUL +U+B58D(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULKIYEOK +U+B58E(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULMIEUM +U+B58F(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULPIEUP +U+B590(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULSIOS +U+B591(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULTHIEUTH +U+B592(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULPHIEUPH +U+B593(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE RIEULHIEUH +U+B594(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE MIEUM +U+B595(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE PIEUP +U+B596(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE PIEUPSIOS +U+B597(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE SIOS +U+B598(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE SSANGSIOS +U+B599(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE IEUNG +U+B59A(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE CIEUC +U+B59B(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE CHIEUCH +U+B59C(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE KHIEUKH +U+B59D(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE THIEUTH +U+B59E(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE PHIEUPH +U+B59F(2);; # HANGUL SYLLABLE SSANGTIKEUT YAE HIEUH +U+B5A0(2);; # HANGUL SYLLABLE SSANGTIKEUT EO * +U+B5A1(2);; # HANGUL SYLLABLE SSANGTIKEUT EO KIYEOK * +U+B5A2(2);; # HANGUL SYLLABLE SSANGTIKEUT EO SSANGKIYEOK +U+B5A3(2);; # HANGUL SYLLABLE SSANGTIKEUT EO KIYEOKSIOS +U+B5A4(2);; # HANGUL SYLLABLE SSANGTIKEUT EO NIEUN * +U+B5A5(2);; # HANGUL SYLLABLE SSANGTIKEUT EO NIEUNCIEUC +U+B5A6(2);; # HANGUL SYLLABLE SSANGTIKEUT EO NIEUNHIEUH +U+B5A7(2);; # HANGUL SYLLABLE SSANGTIKEUT EO TIKEUT +U+B5A8(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEUL * +U+B5A9(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULKIYEOK +U+B5AA(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULMIEUM * +U+B5AB(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULPIEUP * +U+B5AC(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULSIOS +U+B5AD(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULTHIEUTH +U+B5AE(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULPHIEUPH +U+B5AF(2);; # HANGUL SYLLABLE SSANGTIKEUT EO RIEULHIEUH +U+B5B0(2);; # HANGUL SYLLABLE SSANGTIKEUT EO MIEUM * +U+B5B1(2);; # HANGUL SYLLABLE SSANGTIKEUT EO PIEUP * +U+B5B2(2);; # HANGUL SYLLABLE SSANGTIKEUT EO PIEUPSIOS +U+B5B3(2);; # HANGUL SYLLABLE SSANGTIKEUT EO SIOS * +U+B5B4(2);; # HANGUL SYLLABLE SSANGTIKEUT EO SSANGSIOS * +U+B5B5(2);; # HANGUL SYLLABLE SSANGTIKEUT EO IEUNG * +U+B5B6(2);; # HANGUL SYLLABLE SSANGTIKEUT EO CIEUC +U+B5B7(2);; # HANGUL SYLLABLE SSANGTIKEUT EO CHIEUCH +U+B5B8(2);; # HANGUL SYLLABLE SSANGTIKEUT EO KHIEUKH +U+B5B9(2);; # HANGUL SYLLABLE SSANGTIKEUT EO THIEUTH +U+B5BA(2);; # HANGUL SYLLABLE SSANGTIKEUT EO PHIEUPH +U+B5BB(2);; # HANGUL SYLLABLE SSANGTIKEUT EO HIEUH * +U+B5BC(2);; # HANGUL SYLLABLE SSANGTIKEUT E * +U+B5BD(2);; # HANGUL SYLLABLE SSANGTIKEUT E KIYEOK * +U+B5BE(2);; # HANGUL SYLLABLE SSANGTIKEUT E SSANGKIYEOK +U+B5BF(2);; # HANGUL SYLLABLE SSANGTIKEUT E KIYEOKSIOS +U+B5C0(2);; # HANGUL SYLLABLE SSANGTIKEUT E NIEUN * +U+B5C1(2);; # HANGUL SYLLABLE SSANGTIKEUT E NIEUNCIEUC +U+B5C2(2);; # HANGUL SYLLABLE SSANGTIKEUT E NIEUNHIEUH +U+B5C3(2);; # HANGUL SYLLABLE SSANGTIKEUT E TIKEUT +U+B5C4(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEUL * +U+B5C5(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULKIYEOK +U+B5C6(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULMIEUM +U+B5C7(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULPIEUP +U+B5C8(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULSIOS +U+B5C9(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULTHIEUTH +U+B5CA(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULPHIEUPH +U+B5CB(2);; # HANGUL SYLLABLE SSANGTIKEUT E RIEULHIEUH +U+B5CC(2);; # HANGUL SYLLABLE SSANGTIKEUT E MIEUM * +U+B5CD(2);; # HANGUL SYLLABLE SSANGTIKEUT E PIEUP * +U+B5CE(2);; # HANGUL SYLLABLE SSANGTIKEUT E PIEUPSIOS +U+B5CF(2);; # HANGUL SYLLABLE SSANGTIKEUT E SIOS * +U+B5D0(2);; # HANGUL SYLLABLE SSANGTIKEUT E SSANGSIOS * +U+B5D1(2);; # HANGUL SYLLABLE SSANGTIKEUT E IEUNG * +U+B5D2(2);; # HANGUL SYLLABLE SSANGTIKEUT E CIEUC +U+B5D3(2);; # HANGUL SYLLABLE SSANGTIKEUT E CHIEUCH +U+B5D4(2);; # HANGUL SYLLABLE SSANGTIKEUT E KHIEUKH +U+B5D5(2);; # HANGUL SYLLABLE SSANGTIKEUT E THIEUTH +U+B5D6(2);; # HANGUL SYLLABLE SSANGTIKEUT E PHIEUPH +U+B5D7(2);; # HANGUL SYLLABLE SSANGTIKEUT E HIEUH +U+B5D8(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO * +U+B5D9(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO KIYEOK +U+B5DA(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO SSANGKIYEOK +U+B5DB(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO KIYEOKSIOS +U+B5DC(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO NIEUN +U+B5DD(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO NIEUNCIEUC +U+B5DE(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO NIEUNHIEUH +U+B5DF(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO TIKEUT +U+B5E0(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEUL +U+B5E1(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULKIYEOK +U+B5E2(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULMIEUM +U+B5E3(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULPIEUP +U+B5E4(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULSIOS +U+B5E5(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULTHIEUTH +U+B5E6(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULPHIEUPH +U+B5E7(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO RIEULHIEUH +U+B5E8(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO MIEUM +U+B5E9(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO PIEUP +U+B5EA(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO PIEUPSIOS +U+B5EB(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO SIOS +U+B5EC(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO SSANGSIOS * +U+B5ED(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO IEUNG +U+B5EE(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO CIEUC +U+B5EF(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO CHIEUCH +U+B5F0(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO KHIEUKH +U+B5F1(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO THIEUTH +U+B5F2(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO PHIEUPH +U+B5F3(2);; # HANGUL SYLLABLE SSANGTIKEUT YEO HIEUH +U+B5F4(2);; # HANGUL SYLLABLE SSANGTIKEUT YE +U+B5F5(2);; # HANGUL SYLLABLE SSANGTIKEUT YE KIYEOK +U+B5F6(2);; # HANGUL SYLLABLE SSANGTIKEUT YE SSANGKIYEOK +U+B5F7(2);; # HANGUL SYLLABLE SSANGTIKEUT YE KIYEOKSIOS +U+B5F8(2);; # HANGUL SYLLABLE SSANGTIKEUT YE NIEUN +U+B5F9(2);; # HANGUL SYLLABLE SSANGTIKEUT YE NIEUNCIEUC +U+B5FA(2);; # HANGUL SYLLABLE SSANGTIKEUT YE NIEUNHIEUH +U+B5FB(2);; # HANGUL SYLLABLE SSANGTIKEUT YE TIKEUT +U+B5FC(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEUL +U+B5FD(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULKIYEOK +U+B5FE(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULMIEUM +U+B5FF(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULPIEUP +U+B600(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULSIOS +U+B601(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULTHIEUTH +U+B602(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULPHIEUPH +U+B603(2);; # HANGUL SYLLABLE SSANGTIKEUT YE RIEULHIEUH +U+B604(2);; # HANGUL SYLLABLE SSANGTIKEUT YE MIEUM +U+B605(2);; # HANGUL SYLLABLE SSANGTIKEUT YE PIEUP +U+B606(2);; # HANGUL SYLLABLE SSANGTIKEUT YE PIEUPSIOS +U+B607(2);; # HANGUL SYLLABLE SSANGTIKEUT YE SIOS +U+B608(2);; # HANGUL SYLLABLE SSANGTIKEUT YE SSANGSIOS +U+B609(2);; # HANGUL SYLLABLE SSANGTIKEUT YE IEUNG +U+B60A(2);; # HANGUL SYLLABLE SSANGTIKEUT YE CIEUC +U+B60B(2);; # HANGUL SYLLABLE SSANGTIKEUT YE CHIEUCH +U+B60C(2);; # HANGUL SYLLABLE SSANGTIKEUT YE KHIEUKH +U+B60D(2);; # HANGUL SYLLABLE SSANGTIKEUT YE THIEUTH +U+B60E(2);; # HANGUL SYLLABLE SSANGTIKEUT YE PHIEUPH +U+B60F(2);; # HANGUL SYLLABLE SSANGTIKEUT YE HIEUH +U+B610(2);; # HANGUL SYLLABLE SSANGTIKEUT O * +U+B611(2);; # HANGUL SYLLABLE SSANGTIKEUT O KIYEOK * +U+B612(2);; # HANGUL SYLLABLE SSANGTIKEUT O SSANGKIYEOK +U+B613(2);; # HANGUL SYLLABLE SSANGTIKEUT O KIYEOKSIOS +U+B614(2);; # HANGUL SYLLABLE SSANGTIKEUT O NIEUN * +U+B615(2);; # HANGUL SYLLABLE SSANGTIKEUT O NIEUNCIEUC +U+B616(2);; # HANGUL SYLLABLE SSANGTIKEUT O NIEUNHIEUH +U+B617(2);; # HANGUL SYLLABLE SSANGTIKEUT O TIKEUT +U+B618(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEUL * +U+B619(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULKIYEOK +U+B61A(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULMIEUM +U+B61B(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULPIEUP +U+B61C(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULSIOS +U+B61D(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULTHIEUTH +U+B61E(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULPHIEUPH +U+B61F(2);; # HANGUL SYLLABLE SSANGTIKEUT O RIEULHIEUH +U+B620(2);; # HANGUL SYLLABLE SSANGTIKEUT O MIEUM +U+B621(2);; # HANGUL SYLLABLE SSANGTIKEUT O PIEUP +U+B622(2);; # HANGUL SYLLABLE SSANGTIKEUT O PIEUPSIOS +U+B623(2);; # HANGUL SYLLABLE SSANGTIKEUT O SIOS +U+B624(2);; # HANGUL SYLLABLE SSANGTIKEUT O SSANGSIOS +U+B625(2);; # HANGUL SYLLABLE SSANGTIKEUT O IEUNG * +U+B626(2);; # HANGUL SYLLABLE SSANGTIKEUT O CIEUC +U+B627(2);; # HANGUL SYLLABLE SSANGTIKEUT O CHIEUCH +U+B628(2);; # HANGUL SYLLABLE SSANGTIKEUT O KHIEUKH +U+B629(2);; # HANGUL SYLLABLE SSANGTIKEUT O THIEUTH +U+B62A(2);; # HANGUL SYLLABLE SSANGTIKEUT O PHIEUPH +U+B62B(2);; # HANGUL SYLLABLE SSANGTIKEUT O HIEUH +U+B62C(2);; # HANGUL SYLLABLE SSANGTIKEUT WA * +U+B62D(2);; # HANGUL SYLLABLE SSANGTIKEUT WA KIYEOK +U+B62E(2);; # HANGUL SYLLABLE SSANGTIKEUT WA SSANGKIYEOK +U+B62F(2);; # HANGUL SYLLABLE SSANGTIKEUT WA KIYEOKSIOS +U+B630(2);; # HANGUL SYLLABLE SSANGTIKEUT WA NIEUN +U+B631(2);; # HANGUL SYLLABLE SSANGTIKEUT WA NIEUNCIEUC +U+B632(2);; # HANGUL SYLLABLE SSANGTIKEUT WA NIEUNHIEUH +U+B633(2);; # HANGUL SYLLABLE SSANGTIKEUT WA TIKEUT +U+B634(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEUL * +U+B635(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULKIYEOK +U+B636(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULMIEUM +U+B637(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULPIEUP +U+B638(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULSIOS +U+B639(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULTHIEUTH +U+B63A(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULPHIEUPH +U+B63B(2);; # HANGUL SYLLABLE SSANGTIKEUT WA RIEULHIEUH +U+B63C(2);; # HANGUL SYLLABLE SSANGTIKEUT WA MIEUM +U+B63D(2);; # HANGUL SYLLABLE SSANGTIKEUT WA PIEUP +U+B63E(2);; # HANGUL SYLLABLE SSANGTIKEUT WA PIEUPSIOS +U+B63F(2);; # HANGUL SYLLABLE SSANGTIKEUT WA SIOS +U+B640(2);; # HANGUL SYLLABLE SSANGTIKEUT WA SSANGSIOS +U+B641(2);; # HANGUL SYLLABLE SSANGTIKEUT WA IEUNG +U+B642(2);; # HANGUL SYLLABLE SSANGTIKEUT WA CIEUC +U+B643(2);; # HANGUL SYLLABLE SSANGTIKEUT WA CHIEUCH +U+B644(2);; # HANGUL SYLLABLE SSANGTIKEUT WA KHIEUKH +U+B645(2);; # HANGUL SYLLABLE SSANGTIKEUT WA THIEUTH +U+B646(2);; # HANGUL SYLLABLE SSANGTIKEUT WA PHIEUPH +U+B647(2);; # HANGUL SYLLABLE SSANGTIKEUT WA HIEUH +U+B648(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE * +U+B649(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE KIYEOK +U+B64A(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE SSANGKIYEOK +U+B64B(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE KIYEOKSIOS +U+B64C(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE NIEUN +U+B64D(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE NIEUNCIEUC +U+B64E(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE NIEUNHIEUH +U+B64F(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE TIKEUT +U+B650(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEUL +U+B651(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULKIYEOK +U+B652(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULMIEUM +U+B653(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULPIEUP +U+B654(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULSIOS +U+B655(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULTHIEUTH +U+B656(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULPHIEUPH +U+B657(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE RIEULHIEUH +U+B658(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE MIEUM +U+B659(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE PIEUP +U+B65A(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE PIEUPSIOS +U+B65B(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE SIOS +U+B65C(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE SSANGSIOS +U+B65D(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE IEUNG +U+B65E(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE CIEUC +U+B65F(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE CHIEUCH +U+B660(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE KHIEUKH +U+B661(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE THIEUTH +U+B662(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE PHIEUPH +U+B663(2);; # HANGUL SYLLABLE SSANGTIKEUT WAE HIEUH +U+B664(2);; # HANGUL SYLLABLE SSANGTIKEUT OE * +U+B665(2);; # HANGUL SYLLABLE SSANGTIKEUT OE KIYEOK +U+B666(2);; # HANGUL SYLLABLE SSANGTIKEUT OE SSANGKIYEOK +U+B667(2);; # HANGUL SYLLABLE SSANGTIKEUT OE KIYEOKSIOS +U+B668(2);; # HANGUL SYLLABLE SSANGTIKEUT OE NIEUN * +U+B669(2);; # HANGUL SYLLABLE SSANGTIKEUT OE NIEUNCIEUC +U+B66A(2);; # HANGUL SYLLABLE SSANGTIKEUT OE NIEUNHIEUH +U+B66B(2);; # HANGUL SYLLABLE SSANGTIKEUT OE TIKEUT +U+B66C(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEUL +U+B66D(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULKIYEOK +U+B66E(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULMIEUM +U+B66F(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULPIEUP +U+B670(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULSIOS +U+B671(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULTHIEUTH +U+B672(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULPHIEUPH +U+B673(2);; # HANGUL SYLLABLE SSANGTIKEUT OE RIEULHIEUH +U+B674(2);; # HANGUL SYLLABLE SSANGTIKEUT OE MIEUM +U+B675(2);; # HANGUL SYLLABLE SSANGTIKEUT OE PIEUP +U+B676(2);; # HANGUL SYLLABLE SSANGTIKEUT OE PIEUPSIOS +U+B677(2);; # HANGUL SYLLABLE SSANGTIKEUT OE SIOS +U+B678(2);; # HANGUL SYLLABLE SSANGTIKEUT OE SSANGSIOS +U+B679(2);; # HANGUL SYLLABLE SSANGTIKEUT OE IEUNG +U+B67A(2);; # HANGUL SYLLABLE SSANGTIKEUT OE CIEUC +U+B67B(2);; # HANGUL SYLLABLE SSANGTIKEUT OE CHIEUCH +U+B67C(2);; # HANGUL SYLLABLE SSANGTIKEUT OE KHIEUKH +U+B67D(2);; # HANGUL SYLLABLE SSANGTIKEUT OE THIEUTH +U+B67E(2);; # HANGUL SYLLABLE SSANGTIKEUT OE PHIEUPH +U+B67F(2);; # HANGUL SYLLABLE SSANGTIKEUT OE HIEUH +U+B680(2);; # HANGUL SYLLABLE SSANGTIKEUT YO +U+B681(2);; # HANGUL SYLLABLE SSANGTIKEUT YO KIYEOK +U+B682(2);; # HANGUL SYLLABLE SSANGTIKEUT YO SSANGKIYEOK +U+B683(2);; # HANGUL SYLLABLE SSANGTIKEUT YO KIYEOKSIOS +U+B684(2);; # HANGUL SYLLABLE SSANGTIKEUT YO NIEUN +U+B685(2);; # HANGUL SYLLABLE SSANGTIKEUT YO NIEUNCIEUC +U+B686(2);; # HANGUL SYLLABLE SSANGTIKEUT YO NIEUNHIEUH +U+B687(2);; # HANGUL SYLLABLE SSANGTIKEUT YO TIKEUT +U+B688(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEUL +U+B689(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULKIYEOK +U+B68A(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULMIEUM +U+B68B(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULPIEUP +U+B68C(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULSIOS +U+B68D(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULTHIEUTH +U+B68E(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULPHIEUPH +U+B68F(2);; # HANGUL SYLLABLE SSANGTIKEUT YO RIEULHIEUH +U+B690(2);; # HANGUL SYLLABLE SSANGTIKEUT YO MIEUM +U+B691(2);; # HANGUL SYLLABLE SSANGTIKEUT YO PIEUP +U+B692(2);; # HANGUL SYLLABLE SSANGTIKEUT YO PIEUPSIOS +U+B693(2);; # HANGUL SYLLABLE SSANGTIKEUT YO SIOS +U+B694(2);; # HANGUL SYLLABLE SSANGTIKEUT YO SSANGSIOS +U+B695(2);; # HANGUL SYLLABLE SSANGTIKEUT YO IEUNG +U+B696(2);; # HANGUL SYLLABLE SSANGTIKEUT YO CIEUC +U+B697(2);; # HANGUL SYLLABLE SSANGTIKEUT YO CHIEUCH +U+B698(2);; # HANGUL SYLLABLE SSANGTIKEUT YO KHIEUKH +U+B699(2);; # HANGUL SYLLABLE SSANGTIKEUT YO THIEUTH +U+B69A(2);; # HANGUL SYLLABLE SSANGTIKEUT YO PHIEUPH +U+B69B(2);; # HANGUL SYLLABLE SSANGTIKEUT YO HIEUH +U+B69C(2);; # HANGUL SYLLABLE SSANGTIKEUT U * +U+B69D(2);; # HANGUL SYLLABLE SSANGTIKEUT U KIYEOK * +U+B69E(2);; # HANGUL SYLLABLE SSANGTIKEUT U SSANGKIYEOK +U+B69F(2);; # HANGUL SYLLABLE SSANGTIKEUT U KIYEOKSIOS +U+B6A0(2);; # HANGUL SYLLABLE SSANGTIKEUT U NIEUN * +U+B6A1(2);; # HANGUL SYLLABLE SSANGTIKEUT U NIEUNCIEUC +U+B6A2(2);; # HANGUL SYLLABLE SSANGTIKEUT U NIEUNHIEUH +U+B6A3(2);; # HANGUL SYLLABLE SSANGTIKEUT U TIKEUT +U+B6A4(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEUL * +U+B6A5(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULKIYEOK +U+B6A6(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULMIEUM +U+B6A7(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULPIEUP +U+B6A8(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULSIOS +U+B6A9(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULTHIEUTH +U+B6AA(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULPHIEUPH +U+B6AB(2);; # HANGUL SYLLABLE SSANGTIKEUT U RIEULHIEUH * +U+B6AC(2);; # HANGUL SYLLABLE SSANGTIKEUT U MIEUM * +U+B6AD(2);; # HANGUL SYLLABLE SSANGTIKEUT U PIEUP +U+B6AE(2);; # HANGUL SYLLABLE SSANGTIKEUT U PIEUPSIOS +U+B6AF(2);; # HANGUL SYLLABLE SSANGTIKEUT U SIOS +U+B6B0(2);; # HANGUL SYLLABLE SSANGTIKEUT U SSANGSIOS +U+B6B1(2);; # HANGUL SYLLABLE SSANGTIKEUT U IEUNG * +U+B6B2(2);; # HANGUL SYLLABLE SSANGTIKEUT U CIEUC +U+B6B3(2);; # HANGUL SYLLABLE SSANGTIKEUT U CHIEUCH +U+B6B4(2);; # HANGUL SYLLABLE SSANGTIKEUT U KHIEUKH +U+B6B5(2);; # HANGUL SYLLABLE SSANGTIKEUT U THIEUTH +U+B6B6(2);; # HANGUL SYLLABLE SSANGTIKEUT U PHIEUPH +U+B6B7(2);; # HANGUL SYLLABLE SSANGTIKEUT U HIEUH +U+B6B8(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO +U+B6B9(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO KIYEOK +U+B6BA(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO SSANGKIYEOK +U+B6BB(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO KIYEOKSIOS +U+B6BC(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO NIEUN +U+B6BD(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO NIEUNCIEUC +U+B6BE(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO NIEUNHIEUH +U+B6BF(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO TIKEUT +U+B6C0(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEUL +U+B6C1(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULKIYEOK +U+B6C2(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULMIEUM +U+B6C3(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULPIEUP +U+B6C4(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULSIOS +U+B6C5(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULTHIEUTH +U+B6C6(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULPHIEUPH +U+B6C7(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO RIEULHIEUH +U+B6C8(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO MIEUM +U+B6C9(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO PIEUP +U+B6CA(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO PIEUPSIOS +U+B6CB(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO SIOS +U+B6CC(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO SSANGSIOS +U+B6CD(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO IEUNG +U+B6CE(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO CIEUC +U+B6CF(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO CHIEUCH +U+B6D0(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO KHIEUKH +U+B6D1(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO THIEUTH +U+B6D2(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO PHIEUPH +U+B6D3(2);; # HANGUL SYLLABLE SSANGTIKEUT WEO HIEUH +U+B6D4(2);; # HANGUL SYLLABLE SSANGTIKEUT WE * +U+B6D5(2);; # HANGUL SYLLABLE SSANGTIKEUT WE KIYEOK +U+B6D6(2);; # HANGUL SYLLABLE SSANGTIKEUT WE SSANGKIYEOK +U+B6D7(2);; # HANGUL SYLLABLE SSANGTIKEUT WE KIYEOKSIOS +U+B6D8(2);; # HANGUL SYLLABLE SSANGTIKEUT WE NIEUN +U+B6D9(2);; # HANGUL SYLLABLE SSANGTIKEUT WE NIEUNCIEUC +U+B6DA(2);; # HANGUL SYLLABLE SSANGTIKEUT WE NIEUNHIEUH +U+B6DB(2);; # HANGUL SYLLABLE SSANGTIKEUT WE TIKEUT +U+B6DC(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEUL +U+B6DD(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULKIYEOK +U+B6DE(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULMIEUM +U+B6DF(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULPIEUP +U+B6E0(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULSIOS +U+B6E1(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULTHIEUTH +U+B6E2(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULPHIEUPH +U+B6E3(2);; # HANGUL SYLLABLE SSANGTIKEUT WE RIEULHIEUH +U+B6E4(2);; # HANGUL SYLLABLE SSANGTIKEUT WE MIEUM +U+B6E5(2);; # HANGUL SYLLABLE SSANGTIKEUT WE PIEUP +U+B6E6(2);; # HANGUL SYLLABLE SSANGTIKEUT WE PIEUPSIOS +U+B6E7(2);; # HANGUL SYLLABLE SSANGTIKEUT WE SIOS +U+B6E8(2);; # HANGUL SYLLABLE SSANGTIKEUT WE SSANGSIOS +U+B6E9(2);; # HANGUL SYLLABLE SSANGTIKEUT WE IEUNG +U+B6EA(2);; # HANGUL SYLLABLE SSANGTIKEUT WE CIEUC +U+B6EB(2);; # HANGUL SYLLABLE SSANGTIKEUT WE CHIEUCH +U+B6EC(2);; # HANGUL SYLLABLE SSANGTIKEUT WE KHIEUKH +U+B6ED(2);; # HANGUL SYLLABLE SSANGTIKEUT WE THIEUTH +U+B6EE(2);; # HANGUL SYLLABLE SSANGTIKEUT WE PHIEUPH +U+B6EF(2);; # HANGUL SYLLABLE SSANGTIKEUT WE HIEUH +U+B6F0(2);; # HANGUL SYLLABLE SSANGTIKEUT WI * +U+B6F1(2);; # HANGUL SYLLABLE SSANGTIKEUT WI KIYEOK +U+B6F2(2);; # HANGUL SYLLABLE SSANGTIKEUT WI SSANGKIYEOK +U+B6F3(2);; # HANGUL SYLLABLE SSANGTIKEUT WI KIYEOKSIOS +U+B6F4(2);; # HANGUL SYLLABLE SSANGTIKEUT WI NIEUN * +U+B6F5(2);; # HANGUL SYLLABLE SSANGTIKEUT WI NIEUNCIEUC +U+B6F6(2);; # HANGUL SYLLABLE SSANGTIKEUT WI NIEUNHIEUH +U+B6F7(2);; # HANGUL SYLLABLE SSANGTIKEUT WI TIKEUT +U+B6F8(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEUL * +U+B6F9(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULKIYEOK +U+B6FA(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULMIEUM +U+B6FB(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULPIEUP +U+B6FC(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULSIOS +U+B6FD(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULTHIEUTH +U+B6FE(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULPHIEUPH +U+B6FF(2);; # HANGUL SYLLABLE SSANGTIKEUT WI RIEULHIEUH +U+B700(2);; # HANGUL SYLLABLE SSANGTIKEUT WI MIEUM * +U+B701(2);; # HANGUL SYLLABLE SSANGTIKEUT WI PIEUP * +U+B702(2);; # HANGUL SYLLABLE SSANGTIKEUT WI PIEUPSIOS +U+B703(2);; # HANGUL SYLLABLE SSANGTIKEUT WI SIOS +U+B704(2);; # HANGUL SYLLABLE SSANGTIKEUT WI SSANGSIOS +U+B705(2);; # HANGUL SYLLABLE SSANGTIKEUT WI IEUNG * +U+B706(2);; # HANGUL SYLLABLE SSANGTIKEUT WI CIEUC +U+B707(2);; # HANGUL SYLLABLE SSANGTIKEUT WI CHIEUCH +U+B708(2);; # HANGUL SYLLABLE SSANGTIKEUT WI KHIEUKH +U+B709(2);; # HANGUL SYLLABLE SSANGTIKEUT WI THIEUTH +U+B70A(2);; # HANGUL SYLLABLE SSANGTIKEUT WI PHIEUPH +U+B70B(2);; # HANGUL SYLLABLE SSANGTIKEUT WI HIEUH +U+B70C(2);; # HANGUL SYLLABLE SSANGTIKEUT YU +U+B70D(2);; # HANGUL SYLLABLE SSANGTIKEUT YU KIYEOK +U+B70E(2);; # HANGUL SYLLABLE SSANGTIKEUT YU SSANGKIYEOK +U+B70F(2);; # HANGUL SYLLABLE SSANGTIKEUT YU KIYEOKSIOS +U+B710(2);; # HANGUL SYLLABLE SSANGTIKEUT YU NIEUN +U+B711(2);; # HANGUL SYLLABLE SSANGTIKEUT YU NIEUNCIEUC +U+B712(2);; # HANGUL SYLLABLE SSANGTIKEUT YU NIEUNHIEUH +U+B713(2);; # HANGUL SYLLABLE SSANGTIKEUT YU TIKEUT +U+B714(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEUL +U+B715(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULKIYEOK +U+B716(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULMIEUM +U+B717(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULPIEUP +U+B718(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULSIOS +U+B719(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULTHIEUTH +U+B71A(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULPHIEUPH +U+B71B(2);; # HANGUL SYLLABLE SSANGTIKEUT YU RIEULHIEUH +U+B71C(2);; # HANGUL SYLLABLE SSANGTIKEUT YU MIEUM +U+B71D(2);; # HANGUL SYLLABLE SSANGTIKEUT YU PIEUP +U+B71E(2);; # HANGUL SYLLABLE SSANGTIKEUT YU PIEUPSIOS +U+B71F(2);; # HANGUL SYLLABLE SSANGTIKEUT YU SIOS +U+B720(2);; # HANGUL SYLLABLE SSANGTIKEUT YU SSANGSIOS +U+B721(2);; # HANGUL SYLLABLE SSANGTIKEUT YU IEUNG +U+B722(2);; # HANGUL SYLLABLE SSANGTIKEUT YU CIEUC +U+B723(2);; # HANGUL SYLLABLE SSANGTIKEUT YU CHIEUCH +U+B724(2);; # HANGUL SYLLABLE SSANGTIKEUT YU KHIEUKH +U+B725(2);; # HANGUL SYLLABLE SSANGTIKEUT YU THIEUTH +U+B726(2);; # HANGUL SYLLABLE SSANGTIKEUT YU PHIEUPH +U+B727(2);; # HANGUL SYLLABLE SSANGTIKEUT YU HIEUH +U+B728(2);; # HANGUL SYLLABLE SSANGTIKEUT EU * +U+B729(2);; # HANGUL SYLLABLE SSANGTIKEUT EU KIYEOK * +U+B72A(2);; # HANGUL SYLLABLE SSANGTIKEUT EU SSANGKIYEOK +U+B72B(2);; # HANGUL SYLLABLE SSANGTIKEUT EU KIYEOKSIOS +U+B72C(2);; # HANGUL SYLLABLE SSANGTIKEUT EU NIEUN * +U+B72D(2);; # HANGUL SYLLABLE SSANGTIKEUT EU NIEUNCIEUC +U+B72E(2);; # HANGUL SYLLABLE SSANGTIKEUT EU NIEUNHIEUH +U+B72F(2);; # HANGUL SYLLABLE SSANGTIKEUT EU TIKEUT * +U+B730(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEUL * +U+B731(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULKIYEOK +U+B732(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULMIEUM +U+B733(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULPIEUP +U+B734(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULSIOS +U+B735(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULTHIEUTH +U+B736(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULPHIEUPH +U+B737(2);; # HANGUL SYLLABLE SSANGTIKEUT EU RIEULHIEUH +U+B738(2);; # HANGUL SYLLABLE SSANGTIKEUT EU MIEUM * +U+B739(2);; # HANGUL SYLLABLE SSANGTIKEUT EU PIEUP * +U+B73A(2);; # HANGUL SYLLABLE SSANGTIKEUT EU PIEUPSIOS +U+B73B(2);; # HANGUL SYLLABLE SSANGTIKEUT EU SIOS * +U+B73C(2);; # HANGUL SYLLABLE SSANGTIKEUT EU SSANGSIOS +U+B73D(2);; # HANGUL SYLLABLE SSANGTIKEUT EU IEUNG +U+B73E(2);; # HANGUL SYLLABLE SSANGTIKEUT EU CIEUC +U+B73F(2);; # HANGUL SYLLABLE SSANGTIKEUT EU CHIEUCH +U+B740(2);; # HANGUL SYLLABLE SSANGTIKEUT EU KHIEUKH +U+B741(2);; # HANGUL SYLLABLE SSANGTIKEUT EU THIEUTH +U+B742(2);; # HANGUL SYLLABLE SSANGTIKEUT EU PHIEUPH +U+B743(2);; # HANGUL SYLLABLE SSANGTIKEUT EU HIEUH +U+B744(2);; # HANGUL SYLLABLE SSANGTIKEUT YI * +U+B745(2);; # HANGUL SYLLABLE SSANGTIKEUT YI KIYEOK +U+B746(2);; # HANGUL SYLLABLE SSANGTIKEUT YI SSANGKIYEOK +U+B747(2);; # HANGUL SYLLABLE SSANGTIKEUT YI KIYEOKSIOS +U+B748(2);; # HANGUL SYLLABLE SSANGTIKEUT YI NIEUN * +U+B749(2);; # HANGUL SYLLABLE SSANGTIKEUT YI NIEUNCIEUC +U+B74A(2);; # HANGUL SYLLABLE SSANGTIKEUT YI NIEUNHIEUH +U+B74B(2);; # HANGUL SYLLABLE SSANGTIKEUT YI TIKEUT +U+B74C(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEUL * +U+B74D(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULKIYEOK +U+B74E(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULMIEUM +U+B74F(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULPIEUP +U+B750(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULSIOS +U+B751(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULTHIEUTH +U+B752(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULPHIEUPH +U+B753(2);; # HANGUL SYLLABLE SSANGTIKEUT YI RIEULHIEUH +U+B754(2);; # HANGUL SYLLABLE SSANGTIKEUT YI MIEUM * +U+B755(2);; # HANGUL SYLLABLE SSANGTIKEUT YI PIEUP * +U+B756(2);; # HANGUL SYLLABLE SSANGTIKEUT YI PIEUPSIOS +U+B757(2);; # HANGUL SYLLABLE SSANGTIKEUT YI SIOS +U+B758(2);; # HANGUL SYLLABLE SSANGTIKEUT YI SSANGSIOS +U+B759(2);; # HANGUL SYLLABLE SSANGTIKEUT YI IEUNG +U+B75A(2);; # HANGUL SYLLABLE SSANGTIKEUT YI CIEUC +U+B75B(2);; # HANGUL SYLLABLE SSANGTIKEUT YI CHIEUCH +U+B75C(2);; # HANGUL SYLLABLE SSANGTIKEUT YI KHIEUKH +U+B75D(2);; # HANGUL SYLLABLE SSANGTIKEUT YI THIEUTH +U+B75E(2);; # HANGUL SYLLABLE SSANGTIKEUT YI PHIEUPH +U+B75F(2);; # HANGUL SYLLABLE SSANGTIKEUT YI HIEUH +U+B760(2);; # HANGUL SYLLABLE SSANGTIKEUT I * +U+B761(2);; # HANGUL SYLLABLE SSANGTIKEUT I KIYEOK +U+B762(2);; # HANGUL SYLLABLE SSANGTIKEUT I SSANGKIYEOK +U+B763(2);; # HANGUL SYLLABLE SSANGTIKEUT I KIYEOKSIOS +U+B764(2);; # HANGUL SYLLABLE SSANGTIKEUT I NIEUN * +U+B765(2);; # HANGUL SYLLABLE SSANGTIKEUT I NIEUNCIEUC +U+B766(2);; # HANGUL SYLLABLE SSANGTIKEUT I NIEUNHIEUH +U+B767(2);; # HANGUL SYLLABLE SSANGTIKEUT I TIKEUT +U+B768(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEUL * +U+B769(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULKIYEOK +U+B76A(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULMIEUM +U+B76B(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULPIEUP +U+B76C(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULSIOS +U+B76D(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULTHIEUTH +U+B76E(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULPHIEUPH +U+B76F(2);; # HANGUL SYLLABLE SSANGTIKEUT I RIEULHIEUH +U+B770(2);; # HANGUL SYLLABLE SSANGTIKEUT I MIEUM * +U+B771(2);; # HANGUL SYLLABLE SSANGTIKEUT I PIEUP * +U+B772(2);; # HANGUL SYLLABLE SSANGTIKEUT I PIEUPSIOS +U+B773(2);; # HANGUL SYLLABLE SSANGTIKEUT I SIOS * +U+B774(2);; # HANGUL SYLLABLE SSANGTIKEUT I SSANGSIOS +U+B775(2);; # HANGUL SYLLABLE SSANGTIKEUT I IEUNG * +U+B776(2);; # HANGUL SYLLABLE SSANGTIKEUT I CIEUC +U+B777(2);; # HANGUL SYLLABLE SSANGTIKEUT I CHIEUCH +U+B778(2);; # HANGUL SYLLABLE SSANGTIKEUT I KHIEUKH +U+B779(2);; # HANGUL SYLLABLE SSANGTIKEUT I THIEUTH +U+B77A(2);; # HANGUL SYLLABLE SSANGTIKEUT I PHIEUPH +U+B77B(2);; # HANGUL SYLLABLE SSANGTIKEUT I HIEUH +U+B77C(2);; # HANGUL SYLLABLE RIEUL A * +U+B77D(2);; # HANGUL SYLLABLE RIEUL A KIYEOK * +U+B77E(2);; # HANGUL SYLLABLE RIEUL A SSANGKIYEOK +U+B77F(2);; # HANGUL SYLLABLE RIEUL A KIYEOKSIOS +U+B780(2);; # HANGUL SYLLABLE RIEUL A NIEUN * +U+B781(2);; # HANGUL SYLLABLE RIEUL A NIEUNCIEUC +U+B782(2);; # HANGUL SYLLABLE RIEUL A NIEUNHIEUH +U+B783(2);; # HANGUL SYLLABLE RIEUL A TIKEUT +U+B784(2);; # HANGUL SYLLABLE RIEUL A RIEUL * +U+B785(2);; # HANGUL SYLLABLE RIEUL A RIEULKIYEOK +U+B786(2);; # HANGUL SYLLABLE RIEUL A RIEULMIEUM +U+B787(2);; # HANGUL SYLLABLE RIEUL A RIEULPIEUP +U+B788(2);; # HANGUL SYLLABLE RIEUL A RIEULSIOS +U+B789(2);; # HANGUL SYLLABLE RIEUL A RIEULTHIEUTH +U+B78A(2);; # HANGUL SYLLABLE RIEUL A RIEULPHIEUPH +U+B78B(2);; # HANGUL SYLLABLE RIEUL A RIEULHIEUH +U+B78C(2);; # HANGUL SYLLABLE RIEUL A MIEUM * +U+B78D(2);; # HANGUL SYLLABLE RIEUL A PIEUP * +U+B78E(2);; # HANGUL SYLLABLE RIEUL A PIEUPSIOS +U+B78F(2);; # HANGUL SYLLABLE RIEUL A SIOS * +U+B790(2);; # HANGUL SYLLABLE RIEUL A SSANGSIOS * +U+B791(2);; # HANGUL SYLLABLE RIEUL A IEUNG * +U+B792(2);; # HANGUL SYLLABLE RIEUL A CIEUC * +U+B793(2);; # HANGUL SYLLABLE RIEUL A CHIEUCH +U+B794(2);; # HANGUL SYLLABLE RIEUL A KHIEUKH +U+B795(2);; # HANGUL SYLLABLE RIEUL A THIEUTH +U+B796(2);; # HANGUL SYLLABLE RIEUL A PHIEUPH * +U+B797(2);; # HANGUL SYLLABLE RIEUL A HIEUH * +U+B798(2);; # HANGUL SYLLABLE RIEUL AE * +U+B799(2);; # HANGUL SYLLABLE RIEUL AE KIYEOK * +U+B79A(2);; # HANGUL SYLLABLE RIEUL AE SSANGKIYEOK +U+B79B(2);; # HANGUL SYLLABLE RIEUL AE KIYEOKSIOS +U+B79C(2);; # HANGUL SYLLABLE RIEUL AE NIEUN * +U+B79D(2);; # HANGUL SYLLABLE RIEUL AE NIEUNCIEUC +U+B79E(2);; # HANGUL SYLLABLE RIEUL AE NIEUNHIEUH +U+B79F(2);; # HANGUL SYLLABLE RIEUL AE TIKEUT +U+B7A0(2);; # HANGUL SYLLABLE RIEUL AE RIEUL * +U+B7A1(2);; # HANGUL SYLLABLE RIEUL AE RIEULKIYEOK +U+B7A2(2);; # HANGUL SYLLABLE RIEUL AE RIEULMIEUM +U+B7A3(2);; # HANGUL SYLLABLE RIEUL AE RIEULPIEUP +U+B7A4(2);; # HANGUL SYLLABLE RIEUL AE RIEULSIOS +U+B7A5(2);; # HANGUL SYLLABLE RIEUL AE RIEULTHIEUTH +U+B7A6(2);; # HANGUL SYLLABLE RIEUL AE RIEULPHIEUPH +U+B7A7(2);; # HANGUL SYLLABLE RIEUL AE RIEULHIEUH +U+B7A8(2);; # HANGUL SYLLABLE RIEUL AE MIEUM * +U+B7A9(2);; # HANGUL SYLLABLE RIEUL AE PIEUP * +U+B7AA(2);; # HANGUL SYLLABLE RIEUL AE PIEUPSIOS +U+B7AB(2);; # HANGUL SYLLABLE RIEUL AE SIOS * +U+B7AC(2);; # HANGUL SYLLABLE RIEUL AE SSANGSIOS * +U+B7AD(2);; # HANGUL SYLLABLE RIEUL AE IEUNG * +U+B7AE(2);; # HANGUL SYLLABLE RIEUL AE CIEUC +U+B7AF(2);; # HANGUL SYLLABLE RIEUL AE CHIEUCH +U+B7B0(2);; # HANGUL SYLLABLE RIEUL AE KHIEUKH +U+B7B1(2);; # HANGUL SYLLABLE RIEUL AE THIEUTH +U+B7B2(2);; # HANGUL SYLLABLE RIEUL AE PHIEUPH +U+B7B3(2);; # HANGUL SYLLABLE RIEUL AE HIEUH +U+B7B4(2);; # HANGUL SYLLABLE RIEUL YA * +U+B7B5(2);; # HANGUL SYLLABLE RIEUL YA KIYEOK * +U+B7B6(2);; # HANGUL SYLLABLE RIEUL YA SSANGKIYEOK +U+B7B7(2);; # HANGUL SYLLABLE RIEUL YA KIYEOKSIOS +U+B7B8(2);; # HANGUL SYLLABLE RIEUL YA NIEUN * +U+B7B9(2);; # HANGUL SYLLABLE RIEUL YA NIEUNCIEUC +U+B7BA(2);; # HANGUL SYLLABLE RIEUL YA NIEUNHIEUH +U+B7BB(2);; # HANGUL SYLLABLE RIEUL YA TIKEUT +U+B7BC(2);; # HANGUL SYLLABLE RIEUL YA RIEUL +U+B7BD(2);; # HANGUL SYLLABLE RIEUL YA RIEULKIYEOK +U+B7BE(2);; # HANGUL SYLLABLE RIEUL YA RIEULMIEUM +U+B7BF(2);; # HANGUL SYLLABLE RIEUL YA RIEULPIEUP +U+B7C0(2);; # HANGUL SYLLABLE RIEUL YA RIEULSIOS +U+B7C1(2);; # HANGUL SYLLABLE RIEUL YA RIEULTHIEUTH +U+B7C2(2);; # HANGUL SYLLABLE RIEUL YA RIEULPHIEUPH +U+B7C3(2);; # HANGUL SYLLABLE RIEUL YA RIEULHIEUH +U+B7C4(2);; # HANGUL SYLLABLE RIEUL YA MIEUM +U+B7C5(2);; # HANGUL SYLLABLE RIEUL YA PIEUP +U+B7C6(2);; # HANGUL SYLLABLE RIEUL YA PIEUPSIOS +U+B7C7(2);; # HANGUL SYLLABLE RIEUL YA SIOS * +U+B7C8(2);; # HANGUL SYLLABLE RIEUL YA SSANGSIOS +U+B7C9(2);; # HANGUL SYLLABLE RIEUL YA IEUNG * +U+B7CA(2);; # HANGUL SYLLABLE RIEUL YA CIEUC +U+B7CB(2);; # HANGUL SYLLABLE RIEUL YA CHIEUCH +U+B7CC(2);; # HANGUL SYLLABLE RIEUL YA KHIEUKH +U+B7CD(2);; # HANGUL SYLLABLE RIEUL YA THIEUTH +U+B7CE(2);; # HANGUL SYLLABLE RIEUL YA PHIEUPH +U+B7CF(2);; # HANGUL SYLLABLE RIEUL YA HIEUH +U+B7D0(2);; # HANGUL SYLLABLE RIEUL YAE +U+B7D1(2);; # HANGUL SYLLABLE RIEUL YAE KIYEOK +U+B7D2(2);; # HANGUL SYLLABLE RIEUL YAE SSANGKIYEOK +U+B7D3(2);; # HANGUL SYLLABLE RIEUL YAE KIYEOKSIOS +U+B7D4(2);; # HANGUL SYLLABLE RIEUL YAE NIEUN +U+B7D5(2);; # HANGUL SYLLABLE RIEUL YAE NIEUNCIEUC +U+B7D6(2);; # HANGUL SYLLABLE RIEUL YAE NIEUNHIEUH +U+B7D7(2);; # HANGUL SYLLABLE RIEUL YAE TIKEUT +U+B7D8(2);; # HANGUL SYLLABLE RIEUL YAE RIEUL +U+B7D9(2);; # HANGUL SYLLABLE RIEUL YAE RIEULKIYEOK +U+B7DA(2);; # HANGUL SYLLABLE RIEUL YAE RIEULMIEUM +U+B7DB(2);; # HANGUL SYLLABLE RIEUL YAE RIEULPIEUP +U+B7DC(2);; # HANGUL SYLLABLE RIEUL YAE RIEULSIOS +U+B7DD(2);; # HANGUL SYLLABLE RIEUL YAE RIEULTHIEUTH +U+B7DE(2);; # HANGUL SYLLABLE RIEUL YAE RIEULPHIEUPH +U+B7DF(2);; # HANGUL SYLLABLE RIEUL YAE RIEULHIEUH +U+B7E0(2);; # HANGUL SYLLABLE RIEUL YAE MIEUM +U+B7E1(2);; # HANGUL SYLLABLE RIEUL YAE PIEUP +U+B7E2(2);; # HANGUL SYLLABLE RIEUL YAE PIEUPSIOS +U+B7E3(2);; # HANGUL SYLLABLE RIEUL YAE SIOS +U+B7E4(2);; # HANGUL SYLLABLE RIEUL YAE SSANGSIOS +U+B7E5(2);; # HANGUL SYLLABLE RIEUL YAE IEUNG +U+B7E6(2);; # HANGUL SYLLABLE RIEUL YAE CIEUC +U+B7E7(2);; # HANGUL SYLLABLE RIEUL YAE CHIEUCH +U+B7E8(2);; # HANGUL SYLLABLE RIEUL YAE KHIEUKH +U+B7E9(2);; # HANGUL SYLLABLE RIEUL YAE THIEUTH +U+B7EA(2);; # HANGUL SYLLABLE RIEUL YAE PHIEUPH +U+B7EB(2);; # HANGUL SYLLABLE RIEUL YAE HIEUH +U+B7EC(2);; # HANGUL SYLLABLE RIEUL EO * +U+B7ED(2);; # HANGUL SYLLABLE RIEUL EO KIYEOK * +U+B7EE(2);; # HANGUL SYLLABLE RIEUL EO SSANGKIYEOK +U+B7EF(2);; # HANGUL SYLLABLE RIEUL EO KIYEOKSIOS +U+B7F0(2);; # HANGUL SYLLABLE RIEUL EO NIEUN * +U+B7F1(2);; # HANGUL SYLLABLE RIEUL EO NIEUNCIEUC +U+B7F2(2);; # HANGUL SYLLABLE RIEUL EO NIEUNHIEUH +U+B7F3(2);; # HANGUL SYLLABLE RIEUL EO TIKEUT +U+B7F4(2);; # HANGUL SYLLABLE RIEUL EO RIEUL * +U+B7F5(2);; # HANGUL SYLLABLE RIEUL EO RIEULKIYEOK +U+B7F6(2);; # HANGUL SYLLABLE RIEUL EO RIEULMIEUM +U+B7F7(2);; # HANGUL SYLLABLE RIEUL EO RIEULPIEUP +U+B7F8(2);; # HANGUL SYLLABLE RIEUL EO RIEULSIOS +U+B7F9(2);; # HANGUL SYLLABLE RIEUL EO RIEULTHIEUTH +U+B7FA(2);; # HANGUL SYLLABLE RIEUL EO RIEULPHIEUPH +U+B7FB(2);; # HANGUL SYLLABLE RIEUL EO RIEULHIEUH +U+B7FC(2);; # HANGUL SYLLABLE RIEUL EO MIEUM * +U+B7FD(2);; # HANGUL SYLLABLE RIEUL EO PIEUP * +U+B7FE(2);; # HANGUL SYLLABLE RIEUL EO PIEUPSIOS +U+B7FF(2);; # HANGUL SYLLABLE RIEUL EO SIOS * +U+B800(2);; # HANGUL SYLLABLE RIEUL EO SSANGSIOS * +U+B801(2);; # HANGUL SYLLABLE RIEUL EO IEUNG * +U+B802(2);; # HANGUL SYLLABLE RIEUL EO CIEUC +U+B803(2);; # HANGUL SYLLABLE RIEUL EO CHIEUCH +U+B804(2);; # HANGUL SYLLABLE RIEUL EO KHIEUKH +U+B805(2);; # HANGUL SYLLABLE RIEUL EO THIEUTH +U+B806(2);; # HANGUL SYLLABLE RIEUL EO PHIEUPH +U+B807(2);; # HANGUL SYLLABLE RIEUL EO HIEUH * +U+B808(2);; # HANGUL SYLLABLE RIEUL E * +U+B809(2);; # HANGUL SYLLABLE RIEUL E KIYEOK * +U+B80A(2);; # HANGUL SYLLABLE RIEUL E SSANGKIYEOK +U+B80B(2);; # HANGUL SYLLABLE RIEUL E KIYEOKSIOS +U+B80C(2);; # HANGUL SYLLABLE RIEUL E NIEUN * +U+B80D(2);; # HANGUL SYLLABLE RIEUL E NIEUNCIEUC +U+B80E(2);; # HANGUL SYLLABLE RIEUL E NIEUNHIEUH +U+B80F(2);; # HANGUL SYLLABLE RIEUL E TIKEUT +U+B810(2);; # HANGUL SYLLABLE RIEUL E RIEUL * +U+B811(2);; # HANGUL SYLLABLE RIEUL E RIEULKIYEOK +U+B812(2);; # HANGUL SYLLABLE RIEUL E RIEULMIEUM +U+B813(2);; # HANGUL SYLLABLE RIEUL E RIEULPIEUP +U+B814(2);; # HANGUL SYLLABLE RIEUL E RIEULSIOS +U+B815(2);; # HANGUL SYLLABLE RIEUL E RIEULTHIEUTH +U+B816(2);; # HANGUL SYLLABLE RIEUL E RIEULPHIEUPH +U+B817(2);; # HANGUL SYLLABLE RIEUL E RIEULHIEUH +U+B818(2);; # HANGUL SYLLABLE RIEUL E MIEUM * +U+B819(2);; # HANGUL SYLLABLE RIEUL E PIEUP * +U+B81A(2);; # HANGUL SYLLABLE RIEUL E PIEUPSIOS +U+B81B(2);; # HANGUL SYLLABLE RIEUL E SIOS * +U+B81C(2);; # HANGUL SYLLABLE RIEUL E SSANGSIOS +U+B81D(2);; # HANGUL SYLLABLE RIEUL E IEUNG * +U+B81E(2);; # HANGUL SYLLABLE RIEUL E CIEUC +U+B81F(2);; # HANGUL SYLLABLE RIEUL E CHIEUCH +U+B820(2);; # HANGUL SYLLABLE RIEUL E KHIEUKH +U+B821(2);; # HANGUL SYLLABLE RIEUL E THIEUTH +U+B822(2);; # HANGUL SYLLABLE RIEUL E PHIEUPH +U+B823(2);; # HANGUL SYLLABLE RIEUL E HIEUH +U+B824(2);; # HANGUL SYLLABLE RIEUL YEO * +U+B825(2);; # HANGUL SYLLABLE RIEUL YEO KIYEOK * +U+B826(2);; # HANGUL SYLLABLE RIEUL YEO SSANGKIYEOK +U+B827(2);; # HANGUL SYLLABLE RIEUL YEO KIYEOKSIOS +U+B828(2);; # HANGUL SYLLABLE RIEUL YEO NIEUN * +U+B829(2);; # HANGUL SYLLABLE RIEUL YEO NIEUNCIEUC +U+B82A(2);; # HANGUL SYLLABLE RIEUL YEO NIEUNHIEUH +U+B82B(2);; # HANGUL SYLLABLE RIEUL YEO TIKEUT +U+B82C(2);; # HANGUL SYLLABLE RIEUL YEO RIEUL * +U+B82D(2);; # HANGUL SYLLABLE RIEUL YEO RIEULKIYEOK +U+B82E(2);; # HANGUL SYLLABLE RIEUL YEO RIEULMIEUM +U+B82F(2);; # HANGUL SYLLABLE RIEUL YEO RIEULPIEUP +U+B830(2);; # HANGUL SYLLABLE RIEUL YEO RIEULSIOS +U+B831(2);; # HANGUL SYLLABLE RIEUL YEO RIEULTHIEUTH +U+B832(2);; # HANGUL SYLLABLE RIEUL YEO RIEULPHIEUPH +U+B833(2);; # HANGUL SYLLABLE RIEUL YEO RIEULHIEUH +U+B834(2);; # HANGUL SYLLABLE RIEUL YEO MIEUM * +U+B835(2);; # HANGUL SYLLABLE RIEUL YEO PIEUP * +U+B836(2);; # HANGUL SYLLABLE RIEUL YEO PIEUPSIOS +U+B837(2);; # HANGUL SYLLABLE RIEUL YEO SIOS * +U+B838(2);; # HANGUL SYLLABLE RIEUL YEO SSANGSIOS * +U+B839(2);; # HANGUL SYLLABLE RIEUL YEO IEUNG * +U+B83A(2);; # HANGUL SYLLABLE RIEUL YEO CIEUC +U+B83B(2);; # HANGUL SYLLABLE RIEUL YEO CHIEUCH +U+B83C(2);; # HANGUL SYLLABLE RIEUL YEO KHIEUKH +U+B83D(2);; # HANGUL SYLLABLE RIEUL YEO THIEUTH +U+B83E(2);; # HANGUL SYLLABLE RIEUL YEO PHIEUPH +U+B83F(2);; # HANGUL SYLLABLE RIEUL YEO HIEUH +U+B840(2);; # HANGUL SYLLABLE RIEUL YE * +U+B841(2);; # HANGUL SYLLABLE RIEUL YE KIYEOK +U+B842(2);; # HANGUL SYLLABLE RIEUL YE SSANGKIYEOK +U+B843(2);; # HANGUL SYLLABLE RIEUL YE KIYEOKSIOS +U+B844(2);; # HANGUL SYLLABLE RIEUL YE NIEUN * +U+B845(2);; # HANGUL SYLLABLE RIEUL YE NIEUNCIEUC +U+B846(2);; # HANGUL SYLLABLE RIEUL YE NIEUNHIEUH +U+B847(2);; # HANGUL SYLLABLE RIEUL YE TIKEUT +U+B848(2);; # HANGUL SYLLABLE RIEUL YE RIEUL +U+B849(2);; # HANGUL SYLLABLE RIEUL YE RIEULKIYEOK +U+B84A(2);; # HANGUL SYLLABLE RIEUL YE RIEULMIEUM +U+B84B(2);; # HANGUL SYLLABLE RIEUL YE RIEULPIEUP +U+B84C(2);; # HANGUL SYLLABLE RIEUL YE RIEULSIOS +U+B84D(2);; # HANGUL SYLLABLE RIEUL YE RIEULTHIEUTH +U+B84E(2);; # HANGUL SYLLABLE RIEUL YE RIEULPHIEUPH +U+B84F(2);; # HANGUL SYLLABLE RIEUL YE RIEULHIEUH +U+B850(2);; # HANGUL SYLLABLE RIEUL YE MIEUM +U+B851(2);; # HANGUL SYLLABLE RIEUL YE PIEUP * +U+B852(2);; # HANGUL SYLLABLE RIEUL YE PIEUPSIOS +U+B853(2);; # HANGUL SYLLABLE RIEUL YE SIOS * +U+B854(2);; # HANGUL SYLLABLE RIEUL YE SSANGSIOS +U+B855(2);; # HANGUL SYLLABLE RIEUL YE IEUNG +U+B856(2);; # HANGUL SYLLABLE RIEUL YE CIEUC +U+B857(2);; # HANGUL SYLLABLE RIEUL YE CHIEUCH +U+B858(2);; # HANGUL SYLLABLE RIEUL YE KHIEUKH +U+B859(2);; # HANGUL SYLLABLE RIEUL YE THIEUTH +U+B85A(2);; # HANGUL SYLLABLE RIEUL YE PHIEUPH +U+B85B(2);; # HANGUL SYLLABLE RIEUL YE HIEUH +U+B85C(2);; # HANGUL SYLLABLE RIEUL O * +U+B85D(2);; # HANGUL SYLLABLE RIEUL O KIYEOK * +U+B85E(2);; # HANGUL SYLLABLE RIEUL O SSANGKIYEOK +U+B85F(2);; # HANGUL SYLLABLE RIEUL O KIYEOKSIOS +U+B860(2);; # HANGUL SYLLABLE RIEUL O NIEUN * +U+B861(2);; # HANGUL SYLLABLE RIEUL O NIEUNCIEUC +U+B862(2);; # HANGUL SYLLABLE RIEUL O NIEUNHIEUH +U+B863(2);; # HANGUL SYLLABLE RIEUL O TIKEUT +U+B864(2);; # HANGUL SYLLABLE RIEUL O RIEUL * +U+B865(2);; # HANGUL SYLLABLE RIEUL O RIEULKIYEOK +U+B866(2);; # HANGUL SYLLABLE RIEUL O RIEULMIEUM +U+B867(2);; # HANGUL SYLLABLE RIEUL O RIEULPIEUP +U+B868(2);; # HANGUL SYLLABLE RIEUL O RIEULSIOS +U+B869(2);; # HANGUL SYLLABLE RIEUL O RIEULTHIEUTH +U+B86A(2);; # HANGUL SYLLABLE RIEUL O RIEULPHIEUPH +U+B86B(2);; # HANGUL SYLLABLE RIEUL O RIEULHIEUH +U+B86C(2);; # HANGUL SYLLABLE RIEUL O MIEUM * +U+B86D(2);; # HANGUL SYLLABLE RIEUL O PIEUP * +U+B86E(2);; # HANGUL SYLLABLE RIEUL O PIEUPSIOS +U+B86F(2);; # HANGUL SYLLABLE RIEUL O SIOS * +U+B870(2);; # HANGUL SYLLABLE RIEUL O SSANGSIOS +U+B871(2);; # HANGUL SYLLABLE RIEUL O IEUNG * +U+B872(2);; # HANGUL SYLLABLE RIEUL O CIEUC +U+B873(2);; # HANGUL SYLLABLE RIEUL O CHIEUCH +U+B874(2);; # HANGUL SYLLABLE RIEUL O KHIEUKH +U+B875(2);; # HANGUL SYLLABLE RIEUL O THIEUTH +U+B876(2);; # HANGUL SYLLABLE RIEUL O PHIEUPH +U+B877(2);; # HANGUL SYLLABLE RIEUL O HIEUH +U+B878(2);; # HANGUL SYLLABLE RIEUL WA * +U+B879(2);; # HANGUL SYLLABLE RIEUL WA KIYEOK +U+B87A(2);; # HANGUL SYLLABLE RIEUL WA SSANGKIYEOK +U+B87B(2);; # HANGUL SYLLABLE RIEUL WA KIYEOKSIOS +U+B87C(2);; # HANGUL SYLLABLE RIEUL WA NIEUN * +U+B87D(2);; # HANGUL SYLLABLE RIEUL WA NIEUNCIEUC +U+B87E(2);; # HANGUL SYLLABLE RIEUL WA NIEUNHIEUH +U+B87F(2);; # HANGUL SYLLABLE RIEUL WA TIKEUT +U+B880(2);; # HANGUL SYLLABLE RIEUL WA RIEUL +U+B881(2);; # HANGUL SYLLABLE RIEUL WA RIEULKIYEOK +U+B882(2);; # HANGUL SYLLABLE RIEUL WA RIEULMIEUM +U+B883(2);; # HANGUL SYLLABLE RIEUL WA RIEULPIEUP +U+B884(2);; # HANGUL SYLLABLE RIEUL WA RIEULSIOS +U+B885(2);; # HANGUL SYLLABLE RIEUL WA RIEULTHIEUTH +U+B886(2);; # HANGUL SYLLABLE RIEUL WA RIEULPHIEUPH +U+B887(2);; # HANGUL SYLLABLE RIEUL WA RIEULHIEUH +U+B888(2);; # HANGUL SYLLABLE RIEUL WA MIEUM +U+B889(2);; # HANGUL SYLLABLE RIEUL WA PIEUP +U+B88A(2);; # HANGUL SYLLABLE RIEUL WA PIEUPSIOS +U+B88B(2);; # HANGUL SYLLABLE RIEUL WA SIOS +U+B88C(2);; # HANGUL SYLLABLE RIEUL WA SSANGSIOS +U+B88D(2);; # HANGUL SYLLABLE RIEUL WA IEUNG * +U+B88E(2);; # HANGUL SYLLABLE RIEUL WA CIEUC +U+B88F(2);; # HANGUL SYLLABLE RIEUL WA CHIEUCH +U+B890(2);; # HANGUL SYLLABLE RIEUL WA KHIEUKH +U+B891(2);; # HANGUL SYLLABLE RIEUL WA THIEUTH +U+B892(2);; # HANGUL SYLLABLE RIEUL WA PHIEUPH +U+B893(2);; # HANGUL SYLLABLE RIEUL WA HIEUH +U+B894(2);; # HANGUL SYLLABLE RIEUL WAE +U+B895(2);; # HANGUL SYLLABLE RIEUL WAE KIYEOK +U+B896(2);; # HANGUL SYLLABLE RIEUL WAE SSANGKIYEOK +U+B897(2);; # HANGUL SYLLABLE RIEUL WAE KIYEOKSIOS +U+B898(2);; # HANGUL SYLLABLE RIEUL WAE NIEUN +U+B899(2);; # HANGUL SYLLABLE RIEUL WAE NIEUNCIEUC +U+B89A(2);; # HANGUL SYLLABLE RIEUL WAE NIEUNHIEUH +U+B89B(2);; # HANGUL SYLLABLE RIEUL WAE TIKEUT +U+B89C(2);; # HANGUL SYLLABLE RIEUL WAE RIEUL +U+B89D(2);; # HANGUL SYLLABLE RIEUL WAE RIEULKIYEOK +U+B89E(2);; # HANGUL SYLLABLE RIEUL WAE RIEULMIEUM +U+B89F(2);; # HANGUL SYLLABLE RIEUL WAE RIEULPIEUP +U+B8A0(2);; # HANGUL SYLLABLE RIEUL WAE RIEULSIOS +U+B8A1(2);; # HANGUL SYLLABLE RIEUL WAE RIEULTHIEUTH +U+B8A2(2);; # HANGUL SYLLABLE RIEUL WAE RIEULPHIEUPH +U+B8A3(2);; # HANGUL SYLLABLE RIEUL WAE RIEULHIEUH +U+B8A4(2);; # HANGUL SYLLABLE RIEUL WAE MIEUM +U+B8A5(2);; # HANGUL SYLLABLE RIEUL WAE PIEUP +U+B8A6(2);; # HANGUL SYLLABLE RIEUL WAE PIEUPSIOS +U+B8A7(2);; # HANGUL SYLLABLE RIEUL WAE SIOS +U+B8A8(2);; # HANGUL SYLLABLE RIEUL WAE SSANGSIOS * +U+B8A9(2);; # HANGUL SYLLABLE RIEUL WAE IEUNG +U+B8AA(2);; # HANGUL SYLLABLE RIEUL WAE CIEUC +U+B8AB(2);; # HANGUL SYLLABLE RIEUL WAE CHIEUCH +U+B8AC(2);; # HANGUL SYLLABLE RIEUL WAE KHIEUKH +U+B8AD(2);; # HANGUL SYLLABLE RIEUL WAE THIEUTH +U+B8AE(2);; # HANGUL SYLLABLE RIEUL WAE PHIEUPH +U+B8AF(2);; # HANGUL SYLLABLE RIEUL WAE HIEUH +U+B8B0(2);; # HANGUL SYLLABLE RIEUL OE * +U+B8B1(2);; # HANGUL SYLLABLE RIEUL OE KIYEOK +U+B8B2(2);; # HANGUL SYLLABLE RIEUL OE SSANGKIYEOK +U+B8B3(2);; # HANGUL SYLLABLE RIEUL OE KIYEOKSIOS +U+B8B4(2);; # HANGUL SYLLABLE RIEUL OE NIEUN * +U+B8B5(2);; # HANGUL SYLLABLE RIEUL OE NIEUNCIEUC +U+B8B6(2);; # HANGUL SYLLABLE RIEUL OE NIEUNHIEUH +U+B8B7(2);; # HANGUL SYLLABLE RIEUL OE TIKEUT +U+B8B8(2);; # HANGUL SYLLABLE RIEUL OE RIEUL * +U+B8B9(2);; # HANGUL SYLLABLE RIEUL OE RIEULKIYEOK +U+B8BA(2);; # HANGUL SYLLABLE RIEUL OE RIEULMIEUM +U+B8BB(2);; # HANGUL SYLLABLE RIEUL OE RIEULPIEUP +U+B8BC(2);; # HANGUL SYLLABLE RIEUL OE RIEULSIOS +U+B8BD(2);; # HANGUL SYLLABLE RIEUL OE RIEULTHIEUTH +U+B8BE(2);; # HANGUL SYLLABLE RIEUL OE RIEULPHIEUPH +U+B8BF(2);; # HANGUL SYLLABLE RIEUL OE RIEULHIEUH +U+B8C0(2);; # HANGUL SYLLABLE RIEUL OE MIEUM * +U+B8C1(2);; # HANGUL SYLLABLE RIEUL OE PIEUP * +U+B8C2(2);; # HANGUL SYLLABLE RIEUL OE PIEUPSIOS +U+B8C3(2);; # HANGUL SYLLABLE RIEUL OE SIOS * +U+B8C4(2);; # HANGUL SYLLABLE RIEUL OE SSANGSIOS +U+B8C5(2);; # HANGUL SYLLABLE RIEUL OE IEUNG * +U+B8C6(2);; # HANGUL SYLLABLE RIEUL OE CIEUC +U+B8C7(2);; # HANGUL SYLLABLE RIEUL OE CHIEUCH +U+B8C8(2);; # HANGUL SYLLABLE RIEUL OE KHIEUKH +U+B8C9(2);; # HANGUL SYLLABLE RIEUL OE THIEUTH +U+B8CA(2);; # HANGUL SYLLABLE RIEUL OE PHIEUPH +U+B8CB(2);; # HANGUL SYLLABLE RIEUL OE HIEUH +U+B8CC(2);; # HANGUL SYLLABLE RIEUL YO * +U+B8CD(2);; # HANGUL SYLLABLE RIEUL YO KIYEOK +U+B8CE(2);; # HANGUL SYLLABLE RIEUL YO SSANGKIYEOK +U+B8CF(2);; # HANGUL SYLLABLE RIEUL YO KIYEOKSIOS +U+B8D0(2);; # HANGUL SYLLABLE RIEUL YO NIEUN * +U+B8D1(2);; # HANGUL SYLLABLE RIEUL YO NIEUNCIEUC +U+B8D2(2);; # HANGUL SYLLABLE RIEUL YO NIEUNHIEUH +U+B8D3(2);; # HANGUL SYLLABLE RIEUL YO TIKEUT +U+B8D4(2);; # HANGUL SYLLABLE RIEUL YO RIEUL * +U+B8D5(2);; # HANGUL SYLLABLE RIEUL YO RIEULKIYEOK +U+B8D6(2);; # HANGUL SYLLABLE RIEUL YO RIEULMIEUM +U+B8D7(2);; # HANGUL SYLLABLE RIEUL YO RIEULPIEUP +U+B8D8(2);; # HANGUL SYLLABLE RIEUL YO RIEULSIOS +U+B8D9(2);; # HANGUL SYLLABLE RIEUL YO RIEULTHIEUTH +U+B8DA(2);; # HANGUL SYLLABLE RIEUL YO RIEULPHIEUPH +U+B8DB(2);; # HANGUL SYLLABLE RIEUL YO RIEULHIEUH +U+B8DC(2);; # HANGUL SYLLABLE RIEUL YO MIEUM +U+B8DD(2);; # HANGUL SYLLABLE RIEUL YO PIEUP * +U+B8DE(2);; # HANGUL SYLLABLE RIEUL YO PIEUPSIOS +U+B8DF(2);; # HANGUL SYLLABLE RIEUL YO SIOS * +U+B8E0(2);; # HANGUL SYLLABLE RIEUL YO SSANGSIOS +U+B8E1(2);; # HANGUL SYLLABLE RIEUL YO IEUNG * +U+B8E2(2);; # HANGUL SYLLABLE RIEUL YO CIEUC +U+B8E3(2);; # HANGUL SYLLABLE RIEUL YO CHIEUCH +U+B8E4(2);; # HANGUL SYLLABLE RIEUL YO KHIEUKH +U+B8E5(2);; # HANGUL SYLLABLE RIEUL YO THIEUTH +U+B8E6(2);; # HANGUL SYLLABLE RIEUL YO PHIEUPH +U+B8E7(2);; # HANGUL SYLLABLE RIEUL YO HIEUH +U+B8E8(2);; # HANGUL SYLLABLE RIEUL U * +U+B8E9(2);; # HANGUL SYLLABLE RIEUL U KIYEOK * +U+B8EA(2);; # HANGUL SYLLABLE RIEUL U SSANGKIYEOK +U+B8EB(2);; # HANGUL SYLLABLE RIEUL U KIYEOKSIOS +U+B8EC(2);; # HANGUL SYLLABLE RIEUL U NIEUN * +U+B8ED(2);; # HANGUL SYLLABLE RIEUL U NIEUNCIEUC +U+B8EE(2);; # HANGUL SYLLABLE RIEUL U NIEUNHIEUH +U+B8EF(2);; # HANGUL SYLLABLE RIEUL U TIKEUT +U+B8F0(2);; # HANGUL SYLLABLE RIEUL U RIEUL * +U+B8F1(2);; # HANGUL SYLLABLE RIEUL U RIEULKIYEOK +U+B8F2(2);; # HANGUL SYLLABLE RIEUL U RIEULMIEUM +U+B8F3(2);; # HANGUL SYLLABLE RIEUL U RIEULPIEUP +U+B8F4(2);; # HANGUL SYLLABLE RIEUL U RIEULSIOS +U+B8F5(2);; # HANGUL SYLLABLE RIEUL U RIEULTHIEUTH +U+B8F6(2);; # HANGUL SYLLABLE RIEUL U RIEULPHIEUPH +U+B8F7(2);; # HANGUL SYLLABLE RIEUL U RIEULHIEUH +U+B8F8(2);; # HANGUL SYLLABLE RIEUL U MIEUM * +U+B8F9(2);; # HANGUL SYLLABLE RIEUL U PIEUP * +U+B8FA(2);; # HANGUL SYLLABLE RIEUL U PIEUPSIOS +U+B8FB(2);; # HANGUL SYLLABLE RIEUL U SIOS * +U+B8FC(2);; # HANGUL SYLLABLE RIEUL U SSANGSIOS +U+B8FD(2);; # HANGUL SYLLABLE RIEUL U IEUNG * +U+B8FE(2);; # HANGUL SYLLABLE RIEUL U CIEUC +U+B8FF(2);; # HANGUL SYLLABLE RIEUL U CHIEUCH +U+B900(2);; # HANGUL SYLLABLE RIEUL U KHIEUKH +U+B901(2);; # HANGUL SYLLABLE RIEUL U THIEUTH +U+B902(2);; # HANGUL SYLLABLE RIEUL U PHIEUPH +U+B903(2);; # HANGUL SYLLABLE RIEUL U HIEUH +U+B904(2);; # HANGUL SYLLABLE RIEUL WEO * +U+B905(2);; # HANGUL SYLLABLE RIEUL WEO KIYEOK +U+B906(2);; # HANGUL SYLLABLE RIEUL WEO SSANGKIYEOK +U+B907(2);; # HANGUL SYLLABLE RIEUL WEO KIYEOKSIOS +U+B908(2);; # HANGUL SYLLABLE RIEUL WEO NIEUN +U+B909(2);; # HANGUL SYLLABLE RIEUL WEO NIEUNCIEUC +U+B90A(2);; # HANGUL SYLLABLE RIEUL WEO NIEUNHIEUH +U+B90B(2);; # HANGUL SYLLABLE RIEUL WEO TIKEUT +U+B90C(2);; # HANGUL SYLLABLE RIEUL WEO RIEUL +U+B90D(2);; # HANGUL SYLLABLE RIEUL WEO RIEULKIYEOK +U+B90E(2);; # HANGUL SYLLABLE RIEUL WEO RIEULMIEUM +U+B90F(2);; # HANGUL SYLLABLE RIEUL WEO RIEULPIEUP +U+B910(2);; # HANGUL SYLLABLE RIEUL WEO RIEULSIOS +U+B911(2);; # HANGUL SYLLABLE RIEUL WEO RIEULTHIEUTH +U+B912(2);; # HANGUL SYLLABLE RIEUL WEO RIEULPHIEUPH +U+B913(2);; # HANGUL SYLLABLE RIEUL WEO RIEULHIEUH +U+B914(2);; # HANGUL SYLLABLE RIEUL WEO MIEUM +U+B915(2);; # HANGUL SYLLABLE RIEUL WEO PIEUP +U+B916(2);; # HANGUL SYLLABLE RIEUL WEO PIEUPSIOS +U+B917(2);; # HANGUL SYLLABLE RIEUL WEO SIOS +U+B918(2);; # HANGUL SYLLABLE RIEUL WEO SSANGSIOS * +U+B919(2);; # HANGUL SYLLABLE RIEUL WEO IEUNG +U+B91A(2);; # HANGUL SYLLABLE RIEUL WEO CIEUC +U+B91B(2);; # HANGUL SYLLABLE RIEUL WEO CHIEUCH +U+B91C(2);; # HANGUL SYLLABLE RIEUL WEO KHIEUKH +U+B91D(2);; # HANGUL SYLLABLE RIEUL WEO THIEUTH +U+B91E(2);; # HANGUL SYLLABLE RIEUL WEO PHIEUPH +U+B91F(2);; # HANGUL SYLLABLE RIEUL WEO HIEUH +U+B920(2);; # HANGUL SYLLABLE RIEUL WE * +U+B921(2);; # HANGUL SYLLABLE RIEUL WE KIYEOK +U+B922(2);; # HANGUL SYLLABLE RIEUL WE SSANGKIYEOK +U+B923(2);; # HANGUL SYLLABLE RIEUL WE KIYEOKSIOS +U+B924(2);; # HANGUL SYLLABLE RIEUL WE NIEUN +U+B925(2);; # HANGUL SYLLABLE RIEUL WE NIEUNCIEUC +U+B926(2);; # HANGUL SYLLABLE RIEUL WE NIEUNHIEUH +U+B927(2);; # HANGUL SYLLABLE RIEUL WE TIKEUT +U+B928(2);; # HANGUL SYLLABLE RIEUL WE RIEUL +U+B929(2);; # HANGUL SYLLABLE RIEUL WE RIEULKIYEOK +U+B92A(2);; # HANGUL SYLLABLE RIEUL WE RIEULMIEUM +U+B92B(2);; # HANGUL SYLLABLE RIEUL WE RIEULPIEUP +U+B92C(2);; # HANGUL SYLLABLE RIEUL WE RIEULSIOS +U+B92D(2);; # HANGUL SYLLABLE RIEUL WE RIEULTHIEUTH +U+B92E(2);; # HANGUL SYLLABLE RIEUL WE RIEULPHIEUPH +U+B92F(2);; # HANGUL SYLLABLE RIEUL WE RIEULHIEUH +U+B930(2);; # HANGUL SYLLABLE RIEUL WE MIEUM +U+B931(2);; # HANGUL SYLLABLE RIEUL WE PIEUP +U+B932(2);; # HANGUL SYLLABLE RIEUL WE PIEUPSIOS +U+B933(2);; # HANGUL SYLLABLE RIEUL WE SIOS +U+B934(2);; # HANGUL SYLLABLE RIEUL WE SSANGSIOS +U+B935(2);; # HANGUL SYLLABLE RIEUL WE IEUNG +U+B936(2);; # HANGUL SYLLABLE RIEUL WE CIEUC +U+B937(2);; # HANGUL SYLLABLE RIEUL WE CHIEUCH +U+B938(2);; # HANGUL SYLLABLE RIEUL WE KHIEUKH +U+B939(2);; # HANGUL SYLLABLE RIEUL WE THIEUTH +U+B93A(2);; # HANGUL SYLLABLE RIEUL WE PHIEUPH +U+B93B(2);; # HANGUL SYLLABLE RIEUL WE HIEUH +U+B93C(2);; # HANGUL SYLLABLE RIEUL WI * +U+B93D(2);; # HANGUL SYLLABLE RIEUL WI KIYEOK * +U+B93E(2);; # HANGUL SYLLABLE RIEUL WI SSANGKIYEOK +U+B93F(2);; # HANGUL SYLLABLE RIEUL WI KIYEOKSIOS +U+B940(2);; # HANGUL SYLLABLE RIEUL WI NIEUN * +U+B941(2);; # HANGUL SYLLABLE RIEUL WI NIEUNCIEUC +U+B942(2);; # HANGUL SYLLABLE RIEUL WI NIEUNHIEUH +U+B943(2);; # HANGUL SYLLABLE RIEUL WI TIKEUT +U+B944(2);; # HANGUL SYLLABLE RIEUL WI RIEUL * +U+B945(2);; # HANGUL SYLLABLE RIEUL WI RIEULKIYEOK +U+B946(2);; # HANGUL SYLLABLE RIEUL WI RIEULMIEUM +U+B947(2);; # HANGUL SYLLABLE RIEUL WI RIEULPIEUP +U+B948(2);; # HANGUL SYLLABLE RIEUL WI RIEULSIOS +U+B949(2);; # HANGUL SYLLABLE RIEUL WI RIEULTHIEUTH +U+B94A(2);; # HANGUL SYLLABLE RIEUL WI RIEULPHIEUPH +U+B94B(2);; # HANGUL SYLLABLE RIEUL WI RIEULHIEUH +U+B94C(2);; # HANGUL SYLLABLE RIEUL WI MIEUM * +U+B94D(2);; # HANGUL SYLLABLE RIEUL WI PIEUP +U+B94E(2);; # HANGUL SYLLABLE RIEUL WI PIEUPSIOS +U+B94F(2);; # HANGUL SYLLABLE RIEUL WI SIOS * +U+B950(2);; # HANGUL SYLLABLE RIEUL WI SSANGSIOS +U+B951(2);; # HANGUL SYLLABLE RIEUL WI IEUNG * +U+B952(2);; # HANGUL SYLLABLE RIEUL WI CIEUC +U+B953(2);; # HANGUL SYLLABLE RIEUL WI CHIEUCH +U+B954(2);; # HANGUL SYLLABLE RIEUL WI KHIEUKH +U+B955(2);; # HANGUL SYLLABLE RIEUL WI THIEUTH +U+B956(2);; # HANGUL SYLLABLE RIEUL WI PHIEUPH +U+B957(2);; # HANGUL SYLLABLE RIEUL WI HIEUH +U+B958(2);; # HANGUL SYLLABLE RIEUL YU * +U+B959(2);; # HANGUL SYLLABLE RIEUL YU KIYEOK * +U+B95A(2);; # HANGUL SYLLABLE RIEUL YU SSANGKIYEOK +U+B95B(2);; # HANGUL SYLLABLE RIEUL YU KIYEOKSIOS +U+B95C(2);; # HANGUL SYLLABLE RIEUL YU NIEUN * +U+B95D(2);; # HANGUL SYLLABLE RIEUL YU NIEUNCIEUC +U+B95E(2);; # HANGUL SYLLABLE RIEUL YU NIEUNHIEUH +U+B95F(2);; # HANGUL SYLLABLE RIEUL YU TIKEUT +U+B960(2);; # HANGUL SYLLABLE RIEUL YU RIEUL * +U+B961(2);; # HANGUL SYLLABLE RIEUL YU RIEULKIYEOK +U+B962(2);; # HANGUL SYLLABLE RIEUL YU RIEULMIEUM +U+B963(2);; # HANGUL SYLLABLE RIEUL YU RIEULPIEUP +U+B964(2);; # HANGUL SYLLABLE RIEUL YU RIEULSIOS +U+B965(2);; # HANGUL SYLLABLE RIEUL YU RIEULTHIEUTH +U+B966(2);; # HANGUL SYLLABLE RIEUL YU RIEULPHIEUPH +U+B967(2);; # HANGUL SYLLABLE RIEUL YU RIEULHIEUH +U+B968(2);; # HANGUL SYLLABLE RIEUL YU MIEUM * +U+B969(2);; # HANGUL SYLLABLE RIEUL YU PIEUP * +U+B96A(2);; # HANGUL SYLLABLE RIEUL YU PIEUPSIOS +U+B96B(2);; # HANGUL SYLLABLE RIEUL YU SIOS * +U+B96C(2);; # HANGUL SYLLABLE RIEUL YU SSANGSIOS +U+B96D(2);; # HANGUL SYLLABLE RIEUL YU IEUNG * +U+B96E(2);; # HANGUL SYLLABLE RIEUL YU CIEUC +U+B96F(2);; # HANGUL SYLLABLE RIEUL YU CHIEUCH +U+B970(2);; # HANGUL SYLLABLE RIEUL YU KHIEUKH +U+B971(2);; # HANGUL SYLLABLE RIEUL YU THIEUTH +U+B972(2);; # HANGUL SYLLABLE RIEUL YU PHIEUPH +U+B973(2);; # HANGUL SYLLABLE RIEUL YU HIEUH +U+B974(2);; # HANGUL SYLLABLE RIEUL EU * +U+B975(2);; # HANGUL SYLLABLE RIEUL EU KIYEOK * +U+B976(2);; # HANGUL SYLLABLE RIEUL EU SSANGKIYEOK +U+B977(2);; # HANGUL SYLLABLE RIEUL EU KIYEOKSIOS +U+B978(2);; # HANGUL SYLLABLE RIEUL EU NIEUN * +U+B979(2);; # HANGUL SYLLABLE RIEUL EU NIEUNCIEUC +U+B97A(2);; # HANGUL SYLLABLE RIEUL EU NIEUNHIEUH +U+B97B(2);; # HANGUL SYLLABLE RIEUL EU TIKEUT +U+B97C(2);; # HANGUL SYLLABLE RIEUL EU RIEUL * +U+B97D(2);; # HANGUL SYLLABLE RIEUL EU RIEULKIYEOK +U+B97E(2);; # HANGUL SYLLABLE RIEUL EU RIEULMIEUM +U+B97F(2);; # HANGUL SYLLABLE RIEUL EU RIEULPIEUP +U+B980(2);; # HANGUL SYLLABLE RIEUL EU RIEULSIOS +U+B981(2);; # HANGUL SYLLABLE RIEUL EU RIEULTHIEUTH +U+B982(2);; # HANGUL SYLLABLE RIEUL EU RIEULPHIEUPH +U+B983(2);; # HANGUL SYLLABLE RIEUL EU RIEULHIEUH +U+B984(2);; # HANGUL SYLLABLE RIEUL EU MIEUM * +U+B985(2);; # HANGUL SYLLABLE RIEUL EU PIEUP * +U+B986(2);; # HANGUL SYLLABLE RIEUL EU PIEUPSIOS +U+B987(2);; # HANGUL SYLLABLE RIEUL EU SIOS * +U+B988(2);; # HANGUL SYLLABLE RIEUL EU SSANGSIOS +U+B989(2);; # HANGUL SYLLABLE RIEUL EU IEUNG * +U+B98A(2);; # HANGUL SYLLABLE RIEUL EU CIEUC * +U+B98B(2);; # HANGUL SYLLABLE RIEUL EU CHIEUCH +U+B98C(2);; # HANGUL SYLLABLE RIEUL EU KHIEUKH +U+B98D(2);; # HANGUL SYLLABLE RIEUL EU THIEUTH * +U+B98E(2);; # HANGUL SYLLABLE RIEUL EU PHIEUPH * +U+B98F(2);; # HANGUL SYLLABLE RIEUL EU HIEUH +U+B990(2);; # HANGUL SYLLABLE RIEUL YI +U+B991(2);; # HANGUL SYLLABLE RIEUL YI KIYEOK +U+B992(2);; # HANGUL SYLLABLE RIEUL YI SSANGKIYEOK +U+B993(2);; # HANGUL SYLLABLE RIEUL YI KIYEOKSIOS +U+B994(2);; # HANGUL SYLLABLE RIEUL YI NIEUN +U+B995(2);; # HANGUL SYLLABLE RIEUL YI NIEUNCIEUC +U+B996(2);; # HANGUL SYLLABLE RIEUL YI NIEUNHIEUH +U+B997(2);; # HANGUL SYLLABLE RIEUL YI TIKEUT +U+B998(2);; # HANGUL SYLLABLE RIEUL YI RIEUL +U+B999(2);; # HANGUL SYLLABLE RIEUL YI RIEULKIYEOK +U+B99A(2);; # HANGUL SYLLABLE RIEUL YI RIEULMIEUM +U+B99B(2);; # HANGUL SYLLABLE RIEUL YI RIEULPIEUP +U+B99C(2);; # HANGUL SYLLABLE RIEUL YI RIEULSIOS +U+B99D(2);; # HANGUL SYLLABLE RIEUL YI RIEULTHIEUTH +U+B99E(2);; # HANGUL SYLLABLE RIEUL YI RIEULPHIEUPH +U+B99F(2);; # HANGUL SYLLABLE RIEUL YI RIEULHIEUH +U+B9A0(2);; # HANGUL SYLLABLE RIEUL YI MIEUM +U+B9A1(2);; # HANGUL SYLLABLE RIEUL YI PIEUP +U+B9A2(2);; # HANGUL SYLLABLE RIEUL YI PIEUPSIOS +U+B9A3(2);; # HANGUL SYLLABLE RIEUL YI SIOS +U+B9A4(2);; # HANGUL SYLLABLE RIEUL YI SSANGSIOS +U+B9A5(2);; # HANGUL SYLLABLE RIEUL YI IEUNG +U+B9A6(2);; # HANGUL SYLLABLE RIEUL YI CIEUC +U+B9A7(2);; # HANGUL SYLLABLE RIEUL YI CHIEUCH +U+B9A8(2);; # HANGUL SYLLABLE RIEUL YI KHIEUKH +U+B9A9(2);; # HANGUL SYLLABLE RIEUL YI THIEUTH +U+B9AA(2);; # HANGUL SYLLABLE RIEUL YI PHIEUPH +U+B9AB(2);; # HANGUL SYLLABLE RIEUL YI HIEUH +U+B9AC(2);; # HANGUL SYLLABLE RIEUL I * +U+B9AD(2);; # HANGUL SYLLABLE RIEUL I KIYEOK * +U+B9AE(2);; # HANGUL SYLLABLE RIEUL I SSANGKIYEOK +U+B9AF(2);; # HANGUL SYLLABLE RIEUL I KIYEOKSIOS +U+B9B0(2);; # HANGUL SYLLABLE RIEUL I NIEUN * +U+B9B1(2);; # HANGUL SYLLABLE RIEUL I NIEUNCIEUC +U+B9B2(2);; # HANGUL SYLLABLE RIEUL I NIEUNHIEUH +U+B9B3(2);; # HANGUL SYLLABLE RIEUL I TIKEUT +U+B9B4(2);; # HANGUL SYLLABLE RIEUL I RIEUL * +U+B9B5(2);; # HANGUL SYLLABLE RIEUL I RIEULKIYEOK +U+B9B6(2);; # HANGUL SYLLABLE RIEUL I RIEULMIEUM +U+B9B7(2);; # HANGUL SYLLABLE RIEUL I RIEULPIEUP +U+B9B8(2);; # HANGUL SYLLABLE RIEUL I RIEULSIOS +U+B9B9(2);; # HANGUL SYLLABLE RIEUL I RIEULTHIEUTH +U+B9BA(2);; # HANGUL SYLLABLE RIEUL I RIEULPHIEUPH +U+B9BB(2);; # HANGUL SYLLABLE RIEUL I RIEULHIEUH +U+B9BC(2);; # HANGUL SYLLABLE RIEUL I MIEUM * +U+B9BD(2);; # HANGUL SYLLABLE RIEUL I PIEUP * +U+B9BE(2);; # HANGUL SYLLABLE RIEUL I PIEUPSIOS +U+B9BF(2);; # HANGUL SYLLABLE RIEUL I SIOS * +U+B9C0(2);; # HANGUL SYLLABLE RIEUL I SSANGSIOS +U+B9C1(2);; # HANGUL SYLLABLE RIEUL I IEUNG * +U+B9C2(2);; # HANGUL SYLLABLE RIEUL I CIEUC +U+B9C3(2);; # HANGUL SYLLABLE RIEUL I CHIEUCH +U+B9C4(2);; # HANGUL SYLLABLE RIEUL I KHIEUKH +U+B9C5(2);; # HANGUL SYLLABLE RIEUL I THIEUTH +U+B9C6(2);; # HANGUL SYLLABLE RIEUL I PHIEUPH +U+B9C7(2);; # HANGUL SYLLABLE RIEUL I HIEUH +U+B9C8(2);; # HANGUL SYLLABLE MIEUM A * +U+B9C9(2);; # HANGUL SYLLABLE MIEUM A KIYEOK * +U+B9CA(2);; # HANGUL SYLLABLE MIEUM A SSANGKIYEOK +U+B9CB(2);; # HANGUL SYLLABLE MIEUM A KIYEOKSIOS +U+B9CC(2);; # HANGUL SYLLABLE MIEUM A NIEUN * +U+B9CD(2);; # HANGUL SYLLABLE MIEUM A NIEUNCIEUC +U+B9CE(2);; # HANGUL SYLLABLE MIEUM A NIEUNHIEUH * +U+B9CF(2);; # HANGUL SYLLABLE MIEUM A TIKEUT * +U+B9D0(2);; # HANGUL SYLLABLE MIEUM A RIEUL * +U+B9D1(2);; # HANGUL SYLLABLE MIEUM A RIEULKIYEOK * +U+B9D2(2);; # HANGUL SYLLABLE MIEUM A RIEULMIEUM * +U+B9D3(2);; # HANGUL SYLLABLE MIEUM A RIEULPIEUP +U+B9D4(2);; # HANGUL SYLLABLE MIEUM A RIEULSIOS +U+B9D5(2);; # HANGUL SYLLABLE MIEUM A RIEULTHIEUTH +U+B9D6(2);; # HANGUL SYLLABLE MIEUM A RIEULPHIEUPH +U+B9D7(2);; # HANGUL SYLLABLE MIEUM A RIEULHIEUH +U+B9D8(2);; # HANGUL SYLLABLE MIEUM A MIEUM * +U+B9D9(2);; # HANGUL SYLLABLE MIEUM A PIEUP * +U+B9DA(2);; # HANGUL SYLLABLE MIEUM A PIEUPSIOS +U+B9DB(2);; # HANGUL SYLLABLE MIEUM A SIOS * +U+B9DC(2);; # HANGUL SYLLABLE MIEUM A SSANGSIOS +U+B9DD(2);; # HANGUL SYLLABLE MIEUM A IEUNG * +U+B9DE(2);; # HANGUL SYLLABLE MIEUM A CIEUC * +U+B9DF(2);; # HANGUL SYLLABLE MIEUM A CHIEUCH +U+B9E0(2);; # HANGUL SYLLABLE MIEUM A KHIEUKH +U+B9E1(2);; # HANGUL SYLLABLE MIEUM A THIEUTH * +U+B9E2(2);; # HANGUL SYLLABLE MIEUM A PHIEUPH +U+B9E3(2);; # HANGUL SYLLABLE MIEUM A HIEUH * +U+B9E4(2);; # HANGUL SYLLABLE MIEUM AE * +U+B9E5(2);; # HANGUL SYLLABLE MIEUM AE KIYEOK * +U+B9E6(2);; # HANGUL SYLLABLE MIEUM AE SSANGKIYEOK +U+B9E7(2);; # HANGUL SYLLABLE MIEUM AE KIYEOKSIOS +U+B9E8(2);; # HANGUL SYLLABLE MIEUM AE NIEUN * +U+B9E9(2);; # HANGUL SYLLABLE MIEUM AE NIEUNCIEUC +U+B9EA(2);; # HANGUL SYLLABLE MIEUM AE NIEUNHIEUH +U+B9EB(2);; # HANGUL SYLLABLE MIEUM AE TIKEUT +U+B9EC(2);; # HANGUL SYLLABLE MIEUM AE RIEUL * +U+B9ED(2);; # HANGUL SYLLABLE MIEUM AE RIEULKIYEOK +U+B9EE(2);; # HANGUL SYLLABLE MIEUM AE RIEULMIEUM +U+B9EF(2);; # HANGUL SYLLABLE MIEUM AE RIEULPIEUP +U+B9F0(2);; # HANGUL SYLLABLE MIEUM AE RIEULSIOS +U+B9F1(2);; # HANGUL SYLLABLE MIEUM AE RIEULTHIEUTH +U+B9F2(2);; # HANGUL SYLLABLE MIEUM AE RIEULPHIEUPH +U+B9F3(2);; # HANGUL SYLLABLE MIEUM AE RIEULHIEUH +U+B9F4(2);; # HANGUL SYLLABLE MIEUM AE MIEUM * +U+B9F5(2);; # HANGUL SYLLABLE MIEUM AE PIEUP * +U+B9F6(2);; # HANGUL SYLLABLE MIEUM AE PIEUPSIOS +U+B9F7(2);; # HANGUL SYLLABLE MIEUM AE SIOS * +U+B9F8(2);; # HANGUL SYLLABLE MIEUM AE SSANGSIOS * +U+B9F9(2);; # HANGUL SYLLABLE MIEUM AE IEUNG * +U+B9FA(2);; # HANGUL SYLLABLE MIEUM AE CIEUC * +U+B9FB(2);; # HANGUL SYLLABLE MIEUM AE CHIEUCH +U+B9FC(2);; # HANGUL SYLLABLE MIEUM AE KHIEUKH +U+B9FD(2);; # HANGUL SYLLABLE MIEUM AE THIEUTH +U+B9FE(2);; # HANGUL SYLLABLE MIEUM AE PHIEUPH +U+B9FF(2);; # HANGUL SYLLABLE MIEUM AE HIEUH +U+BA00(2);; # HANGUL SYLLABLE MIEUM YA * +U+BA01(2);; # HANGUL SYLLABLE MIEUM YA KIYEOK * +U+BA02(2);; # HANGUL SYLLABLE MIEUM YA SSANGKIYEOK +U+BA03(2);; # HANGUL SYLLABLE MIEUM YA KIYEOKSIOS +U+BA04(2);; # HANGUL SYLLABLE MIEUM YA NIEUN +U+BA05(2);; # HANGUL SYLLABLE MIEUM YA NIEUNCIEUC +U+BA06(2);; # HANGUL SYLLABLE MIEUM YA NIEUNHIEUH +U+BA07(2);; # HANGUL SYLLABLE MIEUM YA TIKEUT +U+BA08(2);; # HANGUL SYLLABLE MIEUM YA RIEUL * +U+BA09(2);; # HANGUL SYLLABLE MIEUM YA RIEULKIYEOK +U+BA0A(2);; # HANGUL SYLLABLE MIEUM YA RIEULMIEUM +U+BA0B(2);; # HANGUL SYLLABLE MIEUM YA RIEULPIEUP +U+BA0C(2);; # HANGUL SYLLABLE MIEUM YA RIEULSIOS +U+BA0D(2);; # HANGUL SYLLABLE MIEUM YA RIEULTHIEUTH +U+BA0E(2);; # HANGUL SYLLABLE MIEUM YA RIEULPHIEUPH +U+BA0F(2);; # HANGUL SYLLABLE MIEUM YA RIEULHIEUH +U+BA10(2);; # HANGUL SYLLABLE MIEUM YA MIEUM +U+BA11(2);; # HANGUL SYLLABLE MIEUM YA PIEUP +U+BA12(2);; # HANGUL SYLLABLE MIEUM YA PIEUPSIOS +U+BA13(2);; # HANGUL SYLLABLE MIEUM YA SIOS +U+BA14(2);; # HANGUL SYLLABLE MIEUM YA SSANGSIOS +U+BA15(2);; # HANGUL SYLLABLE MIEUM YA IEUNG * +U+BA16(2);; # HANGUL SYLLABLE MIEUM YA CIEUC +U+BA17(2);; # HANGUL SYLLABLE MIEUM YA CHIEUCH +U+BA18(2);; # HANGUL SYLLABLE MIEUM YA KHIEUKH +U+BA19(2);; # HANGUL SYLLABLE MIEUM YA THIEUTH +U+BA1A(2);; # HANGUL SYLLABLE MIEUM YA PHIEUPH +U+BA1B(2);; # HANGUL SYLLABLE MIEUM YA HIEUH +U+BA1C(2);; # HANGUL SYLLABLE MIEUM YAE +U+BA1D(2);; # HANGUL SYLLABLE MIEUM YAE KIYEOK +U+BA1E(2);; # HANGUL SYLLABLE MIEUM YAE SSANGKIYEOK +U+BA1F(2);; # HANGUL SYLLABLE MIEUM YAE KIYEOKSIOS +U+BA20(2);; # HANGUL SYLLABLE MIEUM YAE NIEUN +U+BA21(2);; # HANGUL SYLLABLE MIEUM YAE NIEUNCIEUC +U+BA22(2);; # HANGUL SYLLABLE MIEUM YAE NIEUNHIEUH +U+BA23(2);; # HANGUL SYLLABLE MIEUM YAE TIKEUT +U+BA24(2);; # HANGUL SYLLABLE MIEUM YAE RIEUL +U+BA25(2);; # HANGUL SYLLABLE MIEUM YAE RIEULKIYEOK +U+BA26(2);; # HANGUL SYLLABLE MIEUM YAE RIEULMIEUM +U+BA27(2);; # HANGUL SYLLABLE MIEUM YAE RIEULPIEUP +U+BA28(2);; # HANGUL SYLLABLE MIEUM YAE RIEULSIOS +U+BA29(2);; # HANGUL SYLLABLE MIEUM YAE RIEULTHIEUTH +U+BA2A(2);; # HANGUL SYLLABLE MIEUM YAE RIEULPHIEUPH +U+BA2B(2);; # HANGUL SYLLABLE MIEUM YAE RIEULHIEUH +U+BA2C(2);; # HANGUL SYLLABLE MIEUM YAE MIEUM +U+BA2D(2);; # HANGUL SYLLABLE MIEUM YAE PIEUP +U+BA2E(2);; # HANGUL SYLLABLE MIEUM YAE PIEUPSIOS +U+BA2F(2);; # HANGUL SYLLABLE MIEUM YAE SIOS +U+BA30(2);; # HANGUL SYLLABLE MIEUM YAE SSANGSIOS +U+BA31(2);; # HANGUL SYLLABLE MIEUM YAE IEUNG +U+BA32(2);; # HANGUL SYLLABLE MIEUM YAE CIEUC +U+BA33(2);; # HANGUL SYLLABLE MIEUM YAE CHIEUCH +U+BA34(2);; # HANGUL SYLLABLE MIEUM YAE KHIEUKH +U+BA35(2);; # HANGUL SYLLABLE MIEUM YAE THIEUTH +U+BA36(2);; # HANGUL SYLLABLE MIEUM YAE PHIEUPH +U+BA37(2);; # HANGUL SYLLABLE MIEUM YAE HIEUH +U+BA38(2);; # HANGUL SYLLABLE MIEUM EO * +U+BA39(2);; # HANGUL SYLLABLE MIEUM EO KIYEOK * +U+BA3A(2);; # HANGUL SYLLABLE MIEUM EO SSANGKIYEOK +U+BA3B(2);; # HANGUL SYLLABLE MIEUM EO KIYEOKSIOS +U+BA3C(2);; # HANGUL SYLLABLE MIEUM EO NIEUN * +U+BA3D(2);; # HANGUL SYLLABLE MIEUM EO NIEUNCIEUC +U+BA3E(2);; # HANGUL SYLLABLE MIEUM EO NIEUNHIEUH +U+BA3F(2);; # HANGUL SYLLABLE MIEUM EO TIKEUT +U+BA40(2);; # HANGUL SYLLABLE MIEUM EO RIEUL * +U+BA41(2);; # HANGUL SYLLABLE MIEUM EO RIEULKIYEOK +U+BA42(2);; # HANGUL SYLLABLE MIEUM EO RIEULMIEUM * +U+BA43(2);; # HANGUL SYLLABLE MIEUM EO RIEULPIEUP +U+BA44(2);; # HANGUL SYLLABLE MIEUM EO RIEULSIOS +U+BA45(2);; # HANGUL SYLLABLE MIEUM EO RIEULTHIEUTH +U+BA46(2);; # HANGUL SYLLABLE MIEUM EO RIEULPHIEUPH +U+BA47(2);; # HANGUL SYLLABLE MIEUM EO RIEULHIEUH +U+BA48(2);; # HANGUL SYLLABLE MIEUM EO MIEUM * +U+BA49(2);; # HANGUL SYLLABLE MIEUM EO PIEUP * +U+BA4A(2);; # HANGUL SYLLABLE MIEUM EO PIEUPSIOS +U+BA4B(2);; # HANGUL SYLLABLE MIEUM EO SIOS * +U+BA4C(2);; # HANGUL SYLLABLE MIEUM EO SSANGSIOS +U+BA4D(2);; # HANGUL SYLLABLE MIEUM EO IEUNG * +U+BA4E(2);; # HANGUL SYLLABLE MIEUM EO CIEUC * +U+BA4F(2);; # HANGUL SYLLABLE MIEUM EO CHIEUCH +U+BA50(2);; # HANGUL SYLLABLE MIEUM EO KHIEUKH +U+BA51(2);; # HANGUL SYLLABLE MIEUM EO THIEUTH +U+BA52(2);; # HANGUL SYLLABLE MIEUM EO PHIEUPH +U+BA53(2);; # HANGUL SYLLABLE MIEUM EO HIEUH * +U+BA54(2);; # HANGUL SYLLABLE MIEUM E * +U+BA55(2);; # HANGUL SYLLABLE MIEUM E KIYEOK * +U+BA56(2);; # HANGUL SYLLABLE MIEUM E SSANGKIYEOK +U+BA57(2);; # HANGUL SYLLABLE MIEUM E KIYEOKSIOS +U+BA58(2);; # HANGUL SYLLABLE MIEUM E NIEUN * +U+BA59(2);; # HANGUL SYLLABLE MIEUM E NIEUNCIEUC +U+BA5A(2);; # HANGUL SYLLABLE MIEUM E NIEUNHIEUH +U+BA5B(2);; # HANGUL SYLLABLE MIEUM E TIKEUT +U+BA5C(2);; # HANGUL SYLLABLE MIEUM E RIEUL * +U+BA5D(2);; # HANGUL SYLLABLE MIEUM E RIEULKIYEOK +U+BA5E(2);; # HANGUL SYLLABLE MIEUM E RIEULMIEUM +U+BA5F(2);; # HANGUL SYLLABLE MIEUM E RIEULPIEUP +U+BA60(2);; # HANGUL SYLLABLE MIEUM E RIEULSIOS +U+BA61(2);; # HANGUL SYLLABLE MIEUM E RIEULTHIEUTH +U+BA62(2);; # HANGUL SYLLABLE MIEUM E RIEULPHIEUPH +U+BA63(2);; # HANGUL SYLLABLE MIEUM E RIEULHIEUH +U+BA64(2);; # HANGUL SYLLABLE MIEUM E MIEUM * +U+BA65(2);; # HANGUL SYLLABLE MIEUM E PIEUP * +U+BA66(2);; # HANGUL SYLLABLE MIEUM E PIEUPSIOS +U+BA67(2);; # HANGUL SYLLABLE MIEUM E SIOS * +U+BA68(2);; # HANGUL SYLLABLE MIEUM E SSANGSIOS * +U+BA69(2);; # HANGUL SYLLABLE MIEUM E IEUNG * +U+BA6A(2);; # HANGUL SYLLABLE MIEUM E CIEUC +U+BA6B(2);; # HANGUL SYLLABLE MIEUM E CHIEUCH +U+BA6C(2);; # HANGUL SYLLABLE MIEUM E KHIEUKH +U+BA6D(2);; # HANGUL SYLLABLE MIEUM E THIEUTH +U+BA6E(2);; # HANGUL SYLLABLE MIEUM E PHIEUPH +U+BA6F(2);; # HANGUL SYLLABLE MIEUM E HIEUH +U+BA70(2);; # HANGUL SYLLABLE MIEUM YEO * +U+BA71(2);; # HANGUL SYLLABLE MIEUM YEO KIYEOK * +U+BA72(2);; # HANGUL SYLLABLE MIEUM YEO SSANGKIYEOK +U+BA73(2);; # HANGUL SYLLABLE MIEUM YEO KIYEOKSIOS +U+BA74(2);; # HANGUL SYLLABLE MIEUM YEO NIEUN * +U+BA75(2);; # HANGUL SYLLABLE MIEUM YEO NIEUNCIEUC +U+BA76(2);; # HANGUL SYLLABLE MIEUM YEO NIEUNHIEUH +U+BA77(2);; # HANGUL SYLLABLE MIEUM YEO TIKEUT +U+BA78(2);; # HANGUL SYLLABLE MIEUM YEO RIEUL * +U+BA79(2);; # HANGUL SYLLABLE MIEUM YEO RIEULKIYEOK +U+BA7A(2);; # HANGUL SYLLABLE MIEUM YEO RIEULMIEUM +U+BA7B(2);; # HANGUL SYLLABLE MIEUM YEO RIEULPIEUP +U+BA7C(2);; # HANGUL SYLLABLE MIEUM YEO RIEULSIOS +U+BA7D(2);; # HANGUL SYLLABLE MIEUM YEO RIEULTHIEUTH +U+BA7E(2);; # HANGUL SYLLABLE MIEUM YEO RIEULPHIEUPH +U+BA7F(2);; # HANGUL SYLLABLE MIEUM YEO RIEULHIEUH +U+BA80(2);; # HANGUL SYLLABLE MIEUM YEO MIEUM +U+BA81(2);; # HANGUL SYLLABLE MIEUM YEO PIEUP +U+BA82(2);; # HANGUL SYLLABLE MIEUM YEO PIEUPSIOS +U+BA83(2);; # HANGUL SYLLABLE MIEUM YEO SIOS * +U+BA84(2);; # HANGUL SYLLABLE MIEUM YEO SSANGSIOS * +U+BA85(2);; # HANGUL SYLLABLE MIEUM YEO IEUNG * +U+BA86(2);; # HANGUL SYLLABLE MIEUM YEO CIEUC +U+BA87(2);; # HANGUL SYLLABLE MIEUM YEO CHIEUCH * +U+BA88(2);; # HANGUL SYLLABLE MIEUM YEO KHIEUKH +U+BA89(2);; # HANGUL SYLLABLE MIEUM YEO THIEUTH +U+BA8A(2);; # HANGUL SYLLABLE MIEUM YEO PHIEUPH +U+BA8B(2);; # HANGUL SYLLABLE MIEUM YEO HIEUH +U+BA8C(2);; # HANGUL SYLLABLE MIEUM YE * +U+BA8D(2);; # HANGUL SYLLABLE MIEUM YE KIYEOK +U+BA8E(2);; # HANGUL SYLLABLE MIEUM YE SSANGKIYEOK +U+BA8F(2);; # HANGUL SYLLABLE MIEUM YE KIYEOKSIOS +U+BA90(2);; # HANGUL SYLLABLE MIEUM YE NIEUN +U+BA91(2);; # HANGUL SYLLABLE MIEUM YE NIEUNCIEUC +U+BA92(2);; # HANGUL SYLLABLE MIEUM YE NIEUNHIEUH +U+BA93(2);; # HANGUL SYLLABLE MIEUM YE TIKEUT +U+BA94(2);; # HANGUL SYLLABLE MIEUM YE RIEUL +U+BA95(2);; # HANGUL SYLLABLE MIEUM YE RIEULKIYEOK +U+BA96(2);; # HANGUL SYLLABLE MIEUM YE RIEULMIEUM +U+BA97(2);; # HANGUL SYLLABLE MIEUM YE RIEULPIEUP +U+BA98(2);; # HANGUL SYLLABLE MIEUM YE RIEULSIOS +U+BA99(2);; # HANGUL SYLLABLE MIEUM YE RIEULTHIEUTH +U+BA9A(2);; # HANGUL SYLLABLE MIEUM YE RIEULPHIEUPH +U+BA9B(2);; # HANGUL SYLLABLE MIEUM YE RIEULHIEUH +U+BA9C(2);; # HANGUL SYLLABLE MIEUM YE MIEUM +U+BA9D(2);; # HANGUL SYLLABLE MIEUM YE PIEUP +U+BA9E(2);; # HANGUL SYLLABLE MIEUM YE PIEUPSIOS +U+BA9F(2);; # HANGUL SYLLABLE MIEUM YE SIOS +U+BAA0(2);; # HANGUL SYLLABLE MIEUM YE SSANGSIOS +U+BAA1(2);; # HANGUL SYLLABLE MIEUM YE IEUNG +U+BAA2(2);; # HANGUL SYLLABLE MIEUM YE CIEUC +U+BAA3(2);; # HANGUL SYLLABLE MIEUM YE CHIEUCH +U+BAA4(2);; # HANGUL SYLLABLE MIEUM YE KHIEUKH +U+BAA5(2);; # HANGUL SYLLABLE MIEUM YE THIEUTH +U+BAA6(2);; # HANGUL SYLLABLE MIEUM YE PHIEUPH +U+BAA7(2);; # HANGUL SYLLABLE MIEUM YE HIEUH +U+BAA8(2);; # HANGUL SYLLABLE MIEUM O * +U+BAA9(2);; # HANGUL SYLLABLE MIEUM O KIYEOK * +U+BAAA(2);; # HANGUL SYLLABLE MIEUM O SSANGKIYEOK +U+BAAB(2);; # HANGUL SYLLABLE MIEUM O KIYEOKSIOS * +U+BAAC(2);; # HANGUL SYLLABLE MIEUM O NIEUN * +U+BAAD(2);; # HANGUL SYLLABLE MIEUM O NIEUNCIEUC +U+BAAE(2);; # HANGUL SYLLABLE MIEUM O NIEUNHIEUH +U+BAAF(2);; # HANGUL SYLLABLE MIEUM O TIKEUT +U+BAB0(2);; # HANGUL SYLLABLE MIEUM O RIEUL * +U+BAB1(2);; # HANGUL SYLLABLE MIEUM O RIEULKIYEOK +U+BAB2(2);; # HANGUL SYLLABLE MIEUM O RIEULMIEUM * +U+BAB3(2);; # HANGUL SYLLABLE MIEUM O RIEULPIEUP +U+BAB4(2);; # HANGUL SYLLABLE MIEUM O RIEULSIOS +U+BAB5(2);; # HANGUL SYLLABLE MIEUM O RIEULTHIEUTH +U+BAB6(2);; # HANGUL SYLLABLE MIEUM O RIEULPHIEUPH +U+BAB7(2);; # HANGUL SYLLABLE MIEUM O RIEULHIEUH +U+BAB8(2);; # HANGUL SYLLABLE MIEUM O MIEUM * +U+BAB9(2);; # HANGUL SYLLABLE MIEUM O PIEUP * +U+BABA(2);; # HANGUL SYLLABLE MIEUM O PIEUPSIOS +U+BABB(2);; # HANGUL SYLLABLE MIEUM O SIOS * +U+BABC(2);; # HANGUL SYLLABLE MIEUM O SSANGSIOS +U+BABD(2);; # HANGUL SYLLABLE MIEUM O IEUNG * +U+BABE(2);; # HANGUL SYLLABLE MIEUM O CIEUC +U+BABF(2);; # HANGUL SYLLABLE MIEUM O CHIEUCH +U+BAC0(2);; # HANGUL SYLLABLE MIEUM O KHIEUKH +U+BAC1(2);; # HANGUL SYLLABLE MIEUM O THIEUTH +U+BAC2(2);; # HANGUL SYLLABLE MIEUM O PHIEUPH +U+BAC3(2);; # HANGUL SYLLABLE MIEUM O HIEUH +U+BAC4(2);; # HANGUL SYLLABLE MIEUM WA * +U+BAC5(2);; # HANGUL SYLLABLE MIEUM WA KIYEOK +U+BAC6(2);; # HANGUL SYLLABLE MIEUM WA SSANGKIYEOK +U+BAC7(2);; # HANGUL SYLLABLE MIEUM WA KIYEOKSIOS +U+BAC8(2);; # HANGUL SYLLABLE MIEUM WA NIEUN * +U+BAC9(2);; # HANGUL SYLLABLE MIEUM WA NIEUNCIEUC +U+BACA(2);; # HANGUL SYLLABLE MIEUM WA NIEUNHIEUH +U+BACB(2);; # HANGUL SYLLABLE MIEUM WA TIKEUT +U+BACC(2);; # HANGUL SYLLABLE MIEUM WA RIEUL +U+BACD(2);; # HANGUL SYLLABLE MIEUM WA RIEULKIYEOK +U+BACE(2);; # HANGUL SYLLABLE MIEUM WA RIEULMIEUM +U+BACF(2);; # HANGUL SYLLABLE MIEUM WA RIEULPIEUP +U+BAD0(2);; # HANGUL SYLLABLE MIEUM WA RIEULSIOS +U+BAD1(2);; # HANGUL SYLLABLE MIEUM WA RIEULTHIEUTH +U+BAD2(2);; # HANGUL SYLLABLE MIEUM WA RIEULPHIEUPH +U+BAD3(2);; # HANGUL SYLLABLE MIEUM WA RIEULHIEUH +U+BAD4(2);; # HANGUL SYLLABLE MIEUM WA MIEUM +U+BAD5(2);; # HANGUL SYLLABLE MIEUM WA PIEUP +U+BAD6(2);; # HANGUL SYLLABLE MIEUM WA PIEUPSIOS +U+BAD7(2);; # HANGUL SYLLABLE MIEUM WA SIOS +U+BAD8(2);; # HANGUL SYLLABLE MIEUM WA SSANGSIOS * +U+BAD9(2);; # HANGUL SYLLABLE MIEUM WA IEUNG * +U+BADA(2);; # HANGUL SYLLABLE MIEUM WA CIEUC +U+BADB(2);; # HANGUL SYLLABLE MIEUM WA CHIEUCH +U+BADC(2);; # HANGUL SYLLABLE MIEUM WA KHIEUKH +U+BADD(2);; # HANGUL SYLLABLE MIEUM WA THIEUTH +U+BADE(2);; # HANGUL SYLLABLE MIEUM WA PHIEUPH +U+BADF(2);; # HANGUL SYLLABLE MIEUM WA HIEUH +U+BAE0(2);; # HANGUL SYLLABLE MIEUM WAE +U+BAE1(2);; # HANGUL SYLLABLE MIEUM WAE KIYEOK +U+BAE2(2);; # HANGUL SYLLABLE MIEUM WAE SSANGKIYEOK +U+BAE3(2);; # HANGUL SYLLABLE MIEUM WAE KIYEOKSIOS +U+BAE4(2);; # HANGUL SYLLABLE MIEUM WAE NIEUN +U+BAE5(2);; # HANGUL SYLLABLE MIEUM WAE NIEUNCIEUC +U+BAE6(2);; # HANGUL SYLLABLE MIEUM WAE NIEUNHIEUH +U+BAE7(2);; # HANGUL SYLLABLE MIEUM WAE TIKEUT +U+BAE8(2);; # HANGUL SYLLABLE MIEUM WAE RIEUL +U+BAE9(2);; # HANGUL SYLLABLE MIEUM WAE RIEULKIYEOK +U+BAEA(2);; # HANGUL SYLLABLE MIEUM WAE RIEULMIEUM +U+BAEB(2);; # HANGUL SYLLABLE MIEUM WAE RIEULPIEUP +U+BAEC(2);; # HANGUL SYLLABLE MIEUM WAE RIEULSIOS +U+BAED(2);; # HANGUL SYLLABLE MIEUM WAE RIEULTHIEUTH +U+BAEE(2);; # HANGUL SYLLABLE MIEUM WAE RIEULPHIEUPH +U+BAEF(2);; # HANGUL SYLLABLE MIEUM WAE RIEULHIEUH +U+BAF0(2);; # HANGUL SYLLABLE MIEUM WAE MIEUM +U+BAF1(2);; # HANGUL SYLLABLE MIEUM WAE PIEUP +U+BAF2(2);; # HANGUL SYLLABLE MIEUM WAE PIEUPSIOS +U+BAF3(2);; # HANGUL SYLLABLE MIEUM WAE SIOS +U+BAF4(2);; # HANGUL SYLLABLE MIEUM WAE SSANGSIOS +U+BAF5(2);; # HANGUL SYLLABLE MIEUM WAE IEUNG +U+BAF6(2);; # HANGUL SYLLABLE MIEUM WAE CIEUC +U+BAF7(2);; # HANGUL SYLLABLE MIEUM WAE CHIEUCH +U+BAF8(2);; # HANGUL SYLLABLE MIEUM WAE KHIEUKH +U+BAF9(2);; # HANGUL SYLLABLE MIEUM WAE THIEUTH +U+BAFA(2);; # HANGUL SYLLABLE MIEUM WAE PHIEUPH +U+BAFB(2);; # HANGUL SYLLABLE MIEUM WAE HIEUH +U+BAFC(2);; # HANGUL SYLLABLE MIEUM OE * +U+BAFD(2);; # HANGUL SYLLABLE MIEUM OE KIYEOK +U+BAFE(2);; # HANGUL SYLLABLE MIEUM OE SSANGKIYEOK +U+BAFF(2);; # HANGUL SYLLABLE MIEUM OE KIYEOKSIOS +U+BB00(2);; # HANGUL SYLLABLE MIEUM OE NIEUN * +U+BB01(2);; # HANGUL SYLLABLE MIEUM OE NIEUNCIEUC +U+BB02(2);; # HANGUL SYLLABLE MIEUM OE NIEUNHIEUH +U+BB03(2);; # HANGUL SYLLABLE MIEUM OE TIKEUT +U+BB04(2);; # HANGUL SYLLABLE MIEUM OE RIEUL * +U+BB05(2);; # HANGUL SYLLABLE MIEUM OE RIEULKIYEOK +U+BB06(2);; # HANGUL SYLLABLE MIEUM OE RIEULMIEUM +U+BB07(2);; # HANGUL SYLLABLE MIEUM OE RIEULPIEUP +U+BB08(2);; # HANGUL SYLLABLE MIEUM OE RIEULSIOS +U+BB09(2);; # HANGUL SYLLABLE MIEUM OE RIEULTHIEUTH +U+BB0A(2);; # HANGUL SYLLABLE MIEUM OE RIEULPHIEUPH +U+BB0B(2);; # HANGUL SYLLABLE MIEUM OE RIEULHIEUH +U+BB0C(2);; # HANGUL SYLLABLE MIEUM OE MIEUM +U+BB0D(2);; # HANGUL SYLLABLE MIEUM OE PIEUP * +U+BB0E(2);; # HANGUL SYLLABLE MIEUM OE PIEUPSIOS +U+BB0F(2);; # HANGUL SYLLABLE MIEUM OE SIOS * +U+BB10(2);; # HANGUL SYLLABLE MIEUM OE SSANGSIOS +U+BB11(2);; # HANGUL SYLLABLE MIEUM OE IEUNG * +U+BB12(2);; # HANGUL SYLLABLE MIEUM OE CIEUC +U+BB13(2);; # HANGUL SYLLABLE MIEUM OE CHIEUCH +U+BB14(2);; # HANGUL SYLLABLE MIEUM OE KHIEUKH +U+BB15(2);; # HANGUL SYLLABLE MIEUM OE THIEUTH +U+BB16(2);; # HANGUL SYLLABLE MIEUM OE PHIEUPH +U+BB17(2);; # HANGUL SYLLABLE MIEUM OE HIEUH +U+BB18(2);; # HANGUL SYLLABLE MIEUM YO * +U+BB19(2);; # HANGUL SYLLABLE MIEUM YO KIYEOK +U+BB1A(2);; # HANGUL SYLLABLE MIEUM YO SSANGKIYEOK +U+BB1B(2);; # HANGUL SYLLABLE MIEUM YO KIYEOKSIOS +U+BB1C(2);; # HANGUL SYLLABLE MIEUM YO NIEUN * +U+BB1D(2);; # HANGUL SYLLABLE MIEUM YO NIEUNCIEUC +U+BB1E(2);; # HANGUL SYLLABLE MIEUM YO NIEUNHIEUH +U+BB1F(2);; # HANGUL SYLLABLE MIEUM YO TIKEUT +U+BB20(2);; # HANGUL SYLLABLE MIEUM YO RIEUL * +U+BB21(2);; # HANGUL SYLLABLE MIEUM YO RIEULKIYEOK +U+BB22(2);; # HANGUL SYLLABLE MIEUM YO RIEULMIEUM +U+BB23(2);; # HANGUL SYLLABLE MIEUM YO RIEULPIEUP +U+BB24(2);; # HANGUL SYLLABLE MIEUM YO RIEULSIOS +U+BB25(2);; # HANGUL SYLLABLE MIEUM YO RIEULTHIEUTH +U+BB26(2);; # HANGUL SYLLABLE MIEUM YO RIEULPHIEUPH +U+BB27(2);; # HANGUL SYLLABLE MIEUM YO RIEULHIEUH +U+BB28(2);; # HANGUL SYLLABLE MIEUM YO MIEUM +U+BB29(2);; # HANGUL SYLLABLE MIEUM YO PIEUP * +U+BB2A(2);; # HANGUL SYLLABLE MIEUM YO PIEUPSIOS +U+BB2B(2);; # HANGUL SYLLABLE MIEUM YO SIOS * +U+BB2C(2);; # HANGUL SYLLABLE MIEUM YO SSANGSIOS +U+BB2D(2);; # HANGUL SYLLABLE MIEUM YO IEUNG +U+BB2E(2);; # HANGUL SYLLABLE MIEUM YO CIEUC +U+BB2F(2);; # HANGUL SYLLABLE MIEUM YO CHIEUCH +U+BB30(2);; # HANGUL SYLLABLE MIEUM YO KHIEUKH +U+BB31(2);; # HANGUL SYLLABLE MIEUM YO THIEUTH +U+BB32(2);; # HANGUL SYLLABLE MIEUM YO PHIEUPH +U+BB33(2);; # HANGUL SYLLABLE MIEUM YO HIEUH +U+BB34(2);; # HANGUL SYLLABLE MIEUM U * +U+BB35(2);; # HANGUL SYLLABLE MIEUM U KIYEOK * +U+BB36(2);; # HANGUL SYLLABLE MIEUM U SSANGKIYEOK * +U+BB37(2);; # HANGUL SYLLABLE MIEUM U KIYEOKSIOS +U+BB38(2);; # HANGUL SYLLABLE MIEUM U NIEUN * +U+BB39(2);; # HANGUL SYLLABLE MIEUM U NIEUNCIEUC +U+BB3A(2);; # HANGUL SYLLABLE MIEUM U NIEUNHIEUH +U+BB3B(2);; # HANGUL SYLLABLE MIEUM U TIKEUT * +U+BB3C(2);; # HANGUL SYLLABLE MIEUM U RIEUL * +U+BB3D(2);; # HANGUL SYLLABLE MIEUM U RIEULKIYEOK * +U+BB3E(2);; # HANGUL SYLLABLE MIEUM U RIEULMIEUM * +U+BB3F(2);; # HANGUL SYLLABLE MIEUM U RIEULPIEUP +U+BB40(2);; # HANGUL SYLLABLE MIEUM U RIEULSIOS +U+BB41(2);; # HANGUL SYLLABLE MIEUM U RIEULTHIEUTH +U+BB42(2);; # HANGUL SYLLABLE MIEUM U RIEULPHIEUPH +U+BB43(2);; # HANGUL SYLLABLE MIEUM U RIEULHIEUH +U+BB44(2);; # HANGUL SYLLABLE MIEUM U MIEUM * +U+BB45(2);; # HANGUL SYLLABLE MIEUM U PIEUP * +U+BB46(2);; # HANGUL SYLLABLE MIEUM U PIEUPSIOS +U+BB47(2);; # HANGUL SYLLABLE MIEUM U SIOS * +U+BB48(2);; # HANGUL SYLLABLE MIEUM U SSANGSIOS +U+BB49(2);; # HANGUL SYLLABLE MIEUM U IEUNG * +U+BB4A(2);; # HANGUL SYLLABLE MIEUM U CIEUC +U+BB4B(2);; # HANGUL SYLLABLE MIEUM U CHIEUCH +U+BB4C(2);; # HANGUL SYLLABLE MIEUM U KHIEUKH +U+BB4D(2);; # HANGUL SYLLABLE MIEUM U THIEUTH * +U+BB4E(2);; # HANGUL SYLLABLE MIEUM U PHIEUPH +U+BB4F(2);; # HANGUL SYLLABLE MIEUM U HIEUH * +U+BB50(2);; # HANGUL SYLLABLE MIEUM WEO * +U+BB51(2);; # HANGUL SYLLABLE MIEUM WEO KIYEOK +U+BB52(2);; # HANGUL SYLLABLE MIEUM WEO SSANGKIYEOK +U+BB53(2);; # HANGUL SYLLABLE MIEUM WEO KIYEOKSIOS +U+BB54(2);; # HANGUL SYLLABLE MIEUM WEO NIEUN * +U+BB55(2);; # HANGUL SYLLABLE MIEUM WEO NIEUNCIEUC +U+BB56(2);; # HANGUL SYLLABLE MIEUM WEO NIEUNHIEUH +U+BB57(2);; # HANGUL SYLLABLE MIEUM WEO TIKEUT +U+BB58(2);; # HANGUL SYLLABLE MIEUM WEO RIEUL * +U+BB59(2);; # HANGUL SYLLABLE MIEUM WEO RIEULKIYEOK +U+BB5A(2);; # HANGUL SYLLABLE MIEUM WEO RIEULMIEUM +U+BB5B(2);; # HANGUL SYLLABLE MIEUM WEO RIEULPIEUP +U+BB5C(2);; # HANGUL SYLLABLE MIEUM WEO RIEULSIOS +U+BB5D(2);; # HANGUL SYLLABLE MIEUM WEO RIEULTHIEUTH +U+BB5E(2);; # HANGUL SYLLABLE MIEUM WEO RIEULPHIEUPH +U+BB5F(2);; # HANGUL SYLLABLE MIEUM WEO RIEULHIEUH +U+BB60(2);; # HANGUL SYLLABLE MIEUM WEO MIEUM +U+BB61(2);; # HANGUL SYLLABLE MIEUM WEO PIEUP * +U+BB62(2);; # HANGUL SYLLABLE MIEUM WEO PIEUPSIOS +U+BB63(2);; # HANGUL SYLLABLE MIEUM WEO SIOS * +U+BB64(2);; # HANGUL SYLLABLE MIEUM WEO SSANGSIOS +U+BB65(2);; # HANGUL SYLLABLE MIEUM WEO IEUNG +U+BB66(2);; # HANGUL SYLLABLE MIEUM WEO CIEUC +U+BB67(2);; # HANGUL SYLLABLE MIEUM WEO CHIEUCH +U+BB68(2);; # HANGUL SYLLABLE MIEUM WEO KHIEUKH +U+BB69(2);; # HANGUL SYLLABLE MIEUM WEO THIEUTH +U+BB6A(2);; # HANGUL SYLLABLE MIEUM WEO PHIEUPH +U+BB6B(2);; # HANGUL SYLLABLE MIEUM WEO HIEUH +U+BB6C(2);; # HANGUL SYLLABLE MIEUM WE * +U+BB6D(2);; # HANGUL SYLLABLE MIEUM WE KIYEOK +U+BB6E(2);; # HANGUL SYLLABLE MIEUM WE SSANGKIYEOK +U+BB6F(2);; # HANGUL SYLLABLE MIEUM WE KIYEOKSIOS +U+BB70(2);; # HANGUL SYLLABLE MIEUM WE NIEUN +U+BB71(2);; # HANGUL SYLLABLE MIEUM WE NIEUNCIEUC +U+BB72(2);; # HANGUL SYLLABLE MIEUM WE NIEUNHIEUH +U+BB73(2);; # HANGUL SYLLABLE MIEUM WE TIKEUT +U+BB74(2);; # HANGUL SYLLABLE MIEUM WE RIEUL +U+BB75(2);; # HANGUL SYLLABLE MIEUM WE RIEULKIYEOK +U+BB76(2);; # HANGUL SYLLABLE MIEUM WE RIEULMIEUM +U+BB77(2);; # HANGUL SYLLABLE MIEUM WE RIEULPIEUP +U+BB78(2);; # HANGUL SYLLABLE MIEUM WE RIEULSIOS +U+BB79(2);; # HANGUL SYLLABLE MIEUM WE RIEULTHIEUTH +U+BB7A(2);; # HANGUL SYLLABLE MIEUM WE RIEULPHIEUPH +U+BB7B(2);; # HANGUL SYLLABLE MIEUM WE RIEULHIEUH +U+BB7C(2);; # HANGUL SYLLABLE MIEUM WE MIEUM +U+BB7D(2);; # HANGUL SYLLABLE MIEUM WE PIEUP +U+BB7E(2);; # HANGUL SYLLABLE MIEUM WE PIEUPSIOS +U+BB7F(2);; # HANGUL SYLLABLE MIEUM WE SIOS +U+BB80(2);; # HANGUL SYLLABLE MIEUM WE SSANGSIOS +U+BB81(2);; # HANGUL SYLLABLE MIEUM WE IEUNG +U+BB82(2);; # HANGUL SYLLABLE MIEUM WE CIEUC +U+BB83(2);; # HANGUL SYLLABLE MIEUM WE CHIEUCH +U+BB84(2);; # HANGUL SYLLABLE MIEUM WE KHIEUKH +U+BB85(2);; # HANGUL SYLLABLE MIEUM WE THIEUTH +U+BB86(2);; # HANGUL SYLLABLE MIEUM WE PHIEUPH +U+BB87(2);; # HANGUL SYLLABLE MIEUM WE HIEUH +U+BB88(2);; # HANGUL SYLLABLE MIEUM WI * +U+BB89(2);; # HANGUL SYLLABLE MIEUM WI KIYEOK +U+BB8A(2);; # HANGUL SYLLABLE MIEUM WI SSANGKIYEOK +U+BB8B(2);; # HANGUL SYLLABLE MIEUM WI KIYEOKSIOS +U+BB8C(2);; # HANGUL SYLLABLE MIEUM WI NIEUN * +U+BB8D(2);; # HANGUL SYLLABLE MIEUM WI NIEUNCIEUC +U+BB8E(2);; # HANGUL SYLLABLE MIEUM WI NIEUNHIEUH +U+BB8F(2);; # HANGUL SYLLABLE MIEUM WI TIKEUT +U+BB90(2);; # HANGUL SYLLABLE MIEUM WI RIEUL * +U+BB91(2);; # HANGUL SYLLABLE MIEUM WI RIEULKIYEOK +U+BB92(2);; # HANGUL SYLLABLE MIEUM WI RIEULMIEUM +U+BB93(2);; # HANGUL SYLLABLE MIEUM WI RIEULPIEUP +U+BB94(2);; # HANGUL SYLLABLE MIEUM WI RIEULSIOS +U+BB95(2);; # HANGUL SYLLABLE MIEUM WI RIEULTHIEUTH +U+BB96(2);; # HANGUL SYLLABLE MIEUM WI RIEULPHIEUPH +U+BB97(2);; # HANGUL SYLLABLE MIEUM WI RIEULHIEUH +U+BB98(2);; # HANGUL SYLLABLE MIEUM WI MIEUM +U+BB99(2);; # HANGUL SYLLABLE MIEUM WI PIEUP +U+BB9A(2);; # HANGUL SYLLABLE MIEUM WI PIEUPSIOS +U+BB9B(2);; # HANGUL SYLLABLE MIEUM WI SIOS +U+BB9C(2);; # HANGUL SYLLABLE MIEUM WI SSANGSIOS +U+BB9D(2);; # HANGUL SYLLABLE MIEUM WI IEUNG +U+BB9E(2);; # HANGUL SYLLABLE MIEUM WI CIEUC +U+BB9F(2);; # HANGUL SYLLABLE MIEUM WI CHIEUCH +U+BBA0(2);; # HANGUL SYLLABLE MIEUM WI KHIEUKH +U+BBA1(2);; # HANGUL SYLLABLE MIEUM WI THIEUTH +U+BBA2(2);; # HANGUL SYLLABLE MIEUM WI PHIEUPH +U+BBA3(2);; # HANGUL SYLLABLE MIEUM WI HIEUH +U+BBA4(2);; # HANGUL SYLLABLE MIEUM YU * +U+BBA5(2);; # HANGUL SYLLABLE MIEUM YU KIYEOK +U+BBA6(2);; # HANGUL SYLLABLE MIEUM YU SSANGKIYEOK +U+BBA7(2);; # HANGUL SYLLABLE MIEUM YU KIYEOKSIOS +U+BBA8(2);; # HANGUL SYLLABLE MIEUM YU NIEUN * +U+BBA9(2);; # HANGUL SYLLABLE MIEUM YU NIEUNCIEUC +U+BBAA(2);; # HANGUL SYLLABLE MIEUM YU NIEUNHIEUH +U+BBAB(2);; # HANGUL SYLLABLE MIEUM YU TIKEUT +U+BBAC(2);; # HANGUL SYLLABLE MIEUM YU RIEUL * +U+BBAD(2);; # HANGUL SYLLABLE MIEUM YU RIEULKIYEOK +U+BBAE(2);; # HANGUL SYLLABLE MIEUM YU RIEULMIEUM +U+BBAF(2);; # HANGUL SYLLABLE MIEUM YU RIEULPIEUP +U+BBB0(2);; # HANGUL SYLLABLE MIEUM YU RIEULSIOS +U+BBB1(2);; # HANGUL SYLLABLE MIEUM YU RIEULTHIEUTH +U+BBB2(2);; # HANGUL SYLLABLE MIEUM YU RIEULPHIEUPH +U+BBB3(2);; # HANGUL SYLLABLE MIEUM YU RIEULHIEUH +U+BBB4(2);; # HANGUL SYLLABLE MIEUM YU MIEUM * +U+BBB5(2);; # HANGUL SYLLABLE MIEUM YU PIEUP +U+BBB6(2);; # HANGUL SYLLABLE MIEUM YU PIEUPSIOS +U+BBB7(2);; # HANGUL SYLLABLE MIEUM YU SIOS * +U+BBB8(2);; # HANGUL SYLLABLE MIEUM YU SSANGSIOS +U+BBB9(2);; # HANGUL SYLLABLE MIEUM YU IEUNG +U+BBBA(2);; # HANGUL SYLLABLE MIEUM YU CIEUC +U+BBBB(2);; # HANGUL SYLLABLE MIEUM YU CHIEUCH +U+BBBC(2);; # HANGUL SYLLABLE MIEUM YU KHIEUKH +U+BBBD(2);; # HANGUL SYLLABLE MIEUM YU THIEUTH +U+BBBE(2);; # HANGUL SYLLABLE MIEUM YU PHIEUPH +U+BBBF(2);; # HANGUL SYLLABLE MIEUM YU HIEUH +U+BBC0(2);; # HANGUL SYLLABLE MIEUM EU * +U+BBC1(2);; # HANGUL SYLLABLE MIEUM EU KIYEOK +U+BBC2(2);; # HANGUL SYLLABLE MIEUM EU SSANGKIYEOK +U+BBC3(2);; # HANGUL SYLLABLE MIEUM EU KIYEOKSIOS +U+BBC4(2);; # HANGUL SYLLABLE MIEUM EU NIEUN * +U+BBC5(2);; # HANGUL SYLLABLE MIEUM EU NIEUNCIEUC +U+BBC6(2);; # HANGUL SYLLABLE MIEUM EU NIEUNHIEUH +U+BBC7(2);; # HANGUL SYLLABLE MIEUM EU TIKEUT +U+BBC8(2);; # HANGUL SYLLABLE MIEUM EU RIEUL * +U+BBC9(2);; # HANGUL SYLLABLE MIEUM EU RIEULKIYEOK +U+BBCA(2);; # HANGUL SYLLABLE MIEUM EU RIEULMIEUM +U+BBCB(2);; # HANGUL SYLLABLE MIEUM EU RIEULPIEUP +U+BBCC(2);; # HANGUL SYLLABLE MIEUM EU RIEULSIOS +U+BBCD(2);; # HANGUL SYLLABLE MIEUM EU RIEULTHIEUTH +U+BBCE(2);; # HANGUL SYLLABLE MIEUM EU RIEULPHIEUPH +U+BBCF(2);; # HANGUL SYLLABLE MIEUM EU RIEULHIEUH +U+BBD0(2);; # HANGUL SYLLABLE MIEUM EU MIEUM * +U+BBD1(2);; # HANGUL SYLLABLE MIEUM EU PIEUP +U+BBD2(2);; # HANGUL SYLLABLE MIEUM EU PIEUPSIOS +U+BBD3(2);; # HANGUL SYLLABLE MIEUM EU SIOS * +U+BBD4(2);; # HANGUL SYLLABLE MIEUM EU SSANGSIOS +U+BBD5(2);; # HANGUL SYLLABLE MIEUM EU IEUNG +U+BBD6(2);; # HANGUL SYLLABLE MIEUM EU CIEUC +U+BBD7(2);; # HANGUL SYLLABLE MIEUM EU CHIEUCH +U+BBD8(2);; # HANGUL SYLLABLE MIEUM EU KHIEUKH +U+BBD9(2);; # HANGUL SYLLABLE MIEUM EU THIEUTH +U+BBDA(2);; # HANGUL SYLLABLE MIEUM EU PHIEUPH +U+BBDB(2);; # HANGUL SYLLABLE MIEUM EU HIEUH +U+BBDC(2);; # HANGUL SYLLABLE MIEUM YI +U+BBDD(2);; # HANGUL SYLLABLE MIEUM YI KIYEOK +U+BBDE(2);; # HANGUL SYLLABLE MIEUM YI SSANGKIYEOK +U+BBDF(2);; # HANGUL SYLLABLE MIEUM YI KIYEOKSIOS +U+BBE0(2);; # HANGUL SYLLABLE MIEUM YI NIEUN +U+BBE1(2);; # HANGUL SYLLABLE MIEUM YI NIEUNCIEUC +U+BBE2(2);; # HANGUL SYLLABLE MIEUM YI NIEUNHIEUH +U+BBE3(2);; # HANGUL SYLLABLE MIEUM YI TIKEUT +U+BBE4(2);; # HANGUL SYLLABLE MIEUM YI RIEUL +U+BBE5(2);; # HANGUL SYLLABLE MIEUM YI RIEULKIYEOK +U+BBE6(2);; # HANGUL SYLLABLE MIEUM YI RIEULMIEUM +U+BBE7(2);; # HANGUL SYLLABLE MIEUM YI RIEULPIEUP +U+BBE8(2);; # HANGUL SYLLABLE MIEUM YI RIEULSIOS +U+BBE9(2);; # HANGUL SYLLABLE MIEUM YI RIEULTHIEUTH +U+BBEA(2);; # HANGUL SYLLABLE MIEUM YI RIEULPHIEUPH +U+BBEB(2);; # HANGUL SYLLABLE MIEUM YI RIEULHIEUH +U+BBEC(2);; # HANGUL SYLLABLE MIEUM YI MIEUM +U+BBED(2);; # HANGUL SYLLABLE MIEUM YI PIEUP +U+BBEE(2);; # HANGUL SYLLABLE MIEUM YI PIEUPSIOS +U+BBEF(2);; # HANGUL SYLLABLE MIEUM YI SIOS +U+BBF0(2);; # HANGUL SYLLABLE MIEUM YI SSANGSIOS +U+BBF1(2);; # HANGUL SYLLABLE MIEUM YI IEUNG +U+BBF2(2);; # HANGUL SYLLABLE MIEUM YI CIEUC +U+BBF3(2);; # HANGUL SYLLABLE MIEUM YI CHIEUCH +U+BBF4(2);; # HANGUL SYLLABLE MIEUM YI KHIEUKH +U+BBF5(2);; # HANGUL SYLLABLE MIEUM YI THIEUTH +U+BBF6(2);; # HANGUL SYLLABLE MIEUM YI PHIEUPH +U+BBF7(2);; # HANGUL SYLLABLE MIEUM YI HIEUH +U+BBF8(2);; # HANGUL SYLLABLE MIEUM I * +U+BBF9(2);; # HANGUL SYLLABLE MIEUM I KIYEOK * +U+BBFA(2);; # HANGUL SYLLABLE MIEUM I SSANGKIYEOK +U+BBFB(2);; # HANGUL SYLLABLE MIEUM I KIYEOKSIOS +U+BBFC(2);; # HANGUL SYLLABLE MIEUM I NIEUN * +U+BBFD(2);; # HANGUL SYLLABLE MIEUM I NIEUNCIEUC +U+BBFE(2);; # HANGUL SYLLABLE MIEUM I NIEUNHIEUH +U+BBFF(2);; # HANGUL SYLLABLE MIEUM I TIKEUT * +U+BC00(2);; # HANGUL SYLLABLE MIEUM I RIEUL * +U+BC01(2);; # HANGUL SYLLABLE MIEUM I RIEULKIYEOK +U+BC02(2);; # HANGUL SYLLABLE MIEUM I RIEULMIEUM * +U+BC03(2);; # HANGUL SYLLABLE MIEUM I RIEULPIEUP +U+BC04(2);; # HANGUL SYLLABLE MIEUM I RIEULSIOS +U+BC05(2);; # HANGUL SYLLABLE MIEUM I RIEULTHIEUTH +U+BC06(2);; # HANGUL SYLLABLE MIEUM I RIEULPHIEUPH +U+BC07(2);; # HANGUL SYLLABLE MIEUM I RIEULHIEUH +U+BC08(2);; # HANGUL SYLLABLE MIEUM I MIEUM * +U+BC09(2);; # HANGUL SYLLABLE MIEUM I PIEUP * +U+BC0A(2);; # HANGUL SYLLABLE MIEUM I PIEUPSIOS +U+BC0B(2);; # HANGUL SYLLABLE MIEUM I SIOS * +U+BC0C(2);; # HANGUL SYLLABLE MIEUM I SSANGSIOS * +U+BC0D(2);; # HANGUL SYLLABLE MIEUM I IEUNG * +U+BC0E(2);; # HANGUL SYLLABLE MIEUM I CIEUC +U+BC0F(2);; # HANGUL SYLLABLE MIEUM I CHIEUCH * +U+BC10(2);; # HANGUL SYLLABLE MIEUM I KHIEUKH +U+BC11(2);; # HANGUL SYLLABLE MIEUM I THIEUTH * +U+BC12(2);; # HANGUL SYLLABLE MIEUM I PHIEUPH +U+BC13(2);; # HANGUL SYLLABLE MIEUM I HIEUH +U+BC14(2);; # HANGUL SYLLABLE PIEUP A * +U+BC15(2);; # HANGUL SYLLABLE PIEUP A KIYEOK * +U+BC16(2);; # HANGUL SYLLABLE PIEUP A SSANGKIYEOK * +U+BC17(2);; # HANGUL SYLLABLE PIEUP A KIYEOKSIOS * +U+BC18(2);; # HANGUL SYLLABLE PIEUP A NIEUN * +U+BC19(2);; # HANGUL SYLLABLE PIEUP A NIEUNCIEUC +U+BC1A(2);; # HANGUL SYLLABLE PIEUP A NIEUNHIEUH +U+BC1B(2);; # HANGUL SYLLABLE PIEUP A TIKEUT * +U+BC1C(2);; # HANGUL SYLLABLE PIEUP A RIEUL * +U+BC1D(2);; # HANGUL SYLLABLE PIEUP A RIEULKIYEOK * +U+BC1E(2);; # HANGUL SYLLABLE PIEUP A RIEULMIEUM * +U+BC1F(2);; # HANGUL SYLLABLE PIEUP A RIEULPIEUP * +U+BC20(2);; # HANGUL SYLLABLE PIEUP A RIEULSIOS +U+BC21(2);; # HANGUL SYLLABLE PIEUP A RIEULTHIEUTH +U+BC22(2);; # HANGUL SYLLABLE PIEUP A RIEULPHIEUPH +U+BC23(2);; # HANGUL SYLLABLE PIEUP A RIEULHIEUH +U+BC24(2);; # HANGUL SYLLABLE PIEUP A MIEUM * +U+BC25(2);; # HANGUL SYLLABLE PIEUP A PIEUP * +U+BC26(2);; # HANGUL SYLLABLE PIEUP A PIEUPSIOS +U+BC27(2);; # HANGUL SYLLABLE PIEUP A SIOS * +U+BC28(2);; # HANGUL SYLLABLE PIEUP A SSANGSIOS +U+BC29(2);; # HANGUL SYLLABLE PIEUP A IEUNG * +U+BC2A(2);; # HANGUL SYLLABLE PIEUP A CIEUC +U+BC2B(2);; # HANGUL SYLLABLE PIEUP A CHIEUCH +U+BC2C(2);; # HANGUL SYLLABLE PIEUP A KHIEUKH +U+BC2D(2);; # HANGUL SYLLABLE PIEUP A THIEUTH * +U+BC2E(2);; # HANGUL SYLLABLE PIEUP A PHIEUPH +U+BC2F(2);; # HANGUL SYLLABLE PIEUP A HIEUH +U+BC30(2);; # HANGUL SYLLABLE PIEUP AE * +U+BC31(2);; # HANGUL SYLLABLE PIEUP AE KIYEOK * +U+BC32(2);; # HANGUL SYLLABLE PIEUP AE SSANGKIYEOK +U+BC33(2);; # HANGUL SYLLABLE PIEUP AE KIYEOKSIOS +U+BC34(2);; # HANGUL SYLLABLE PIEUP AE NIEUN * +U+BC35(2);; # HANGUL SYLLABLE PIEUP AE NIEUNCIEUC +U+BC36(2);; # HANGUL SYLLABLE PIEUP AE NIEUNHIEUH +U+BC37(2);; # HANGUL SYLLABLE PIEUP AE TIKEUT +U+BC38(2);; # HANGUL SYLLABLE PIEUP AE RIEUL * +U+BC39(2);; # HANGUL SYLLABLE PIEUP AE RIEULKIYEOK +U+BC3A(2);; # HANGUL SYLLABLE PIEUP AE RIEULMIEUM +U+BC3B(2);; # HANGUL SYLLABLE PIEUP AE RIEULPIEUP +U+BC3C(2);; # HANGUL SYLLABLE PIEUP AE RIEULSIOS +U+BC3D(2);; # HANGUL SYLLABLE PIEUP AE RIEULTHIEUTH +U+BC3E(2);; # HANGUL SYLLABLE PIEUP AE RIEULPHIEUPH +U+BC3F(2);; # HANGUL SYLLABLE PIEUP AE RIEULHIEUH +U+BC40(2);; # HANGUL SYLLABLE PIEUP AE MIEUM * +U+BC41(2);; # HANGUL SYLLABLE PIEUP AE PIEUP * +U+BC42(2);; # HANGUL SYLLABLE PIEUP AE PIEUPSIOS +U+BC43(2);; # HANGUL SYLLABLE PIEUP AE SIOS * +U+BC44(2);; # HANGUL SYLLABLE PIEUP AE SSANGSIOS * +U+BC45(2);; # HANGUL SYLLABLE PIEUP AE IEUNG * +U+BC46(2);; # HANGUL SYLLABLE PIEUP AE CIEUC +U+BC47(2);; # HANGUL SYLLABLE PIEUP AE CHIEUCH +U+BC48(2);; # HANGUL SYLLABLE PIEUP AE KHIEUKH +U+BC49(2);; # HANGUL SYLLABLE PIEUP AE THIEUTH * +U+BC4A(2);; # HANGUL SYLLABLE PIEUP AE PHIEUPH +U+BC4B(2);; # HANGUL SYLLABLE PIEUP AE HIEUH +U+BC4C(2);; # HANGUL SYLLABLE PIEUP YA * +U+BC4D(2);; # HANGUL SYLLABLE PIEUP YA KIYEOK * +U+BC4E(2);; # HANGUL SYLLABLE PIEUP YA SSANGKIYEOK +U+BC4F(2);; # HANGUL SYLLABLE PIEUP YA KIYEOKSIOS +U+BC50(2);; # HANGUL SYLLABLE PIEUP YA NIEUN * +U+BC51(2);; # HANGUL SYLLABLE PIEUP YA NIEUNCIEUC +U+BC52(2);; # HANGUL SYLLABLE PIEUP YA NIEUNHIEUH +U+BC53(2);; # HANGUL SYLLABLE PIEUP YA TIKEUT +U+BC54(2);; # HANGUL SYLLABLE PIEUP YA RIEUL +U+BC55(2);; # HANGUL SYLLABLE PIEUP YA RIEULKIYEOK +U+BC56(2);; # HANGUL SYLLABLE PIEUP YA RIEULMIEUM +U+BC57(2);; # HANGUL SYLLABLE PIEUP YA RIEULPIEUP +U+BC58(2);; # HANGUL SYLLABLE PIEUP YA RIEULSIOS +U+BC59(2);; # HANGUL SYLLABLE PIEUP YA RIEULTHIEUTH +U+BC5A(2);; # HANGUL SYLLABLE PIEUP YA RIEULPHIEUPH +U+BC5B(2);; # HANGUL SYLLABLE PIEUP YA RIEULHIEUH +U+BC5C(2);; # HANGUL SYLLABLE PIEUP YA MIEUM +U+BC5D(2);; # HANGUL SYLLABLE PIEUP YA PIEUP * +U+BC5E(2);; # HANGUL SYLLABLE PIEUP YA PIEUPSIOS +U+BC5F(2);; # HANGUL SYLLABLE PIEUP YA SIOS +U+BC60(2);; # HANGUL SYLLABLE PIEUP YA SSANGSIOS +U+BC61(2);; # HANGUL SYLLABLE PIEUP YA IEUNG +U+BC62(2);; # HANGUL SYLLABLE PIEUP YA CIEUC +U+BC63(2);; # HANGUL SYLLABLE PIEUP YA CHIEUCH +U+BC64(2);; # HANGUL SYLLABLE PIEUP YA KHIEUKH +U+BC65(2);; # HANGUL SYLLABLE PIEUP YA THIEUTH +U+BC66(2);; # HANGUL SYLLABLE PIEUP YA PHIEUPH +U+BC67(2);; # HANGUL SYLLABLE PIEUP YA HIEUH +U+BC68(2);; # HANGUL SYLLABLE PIEUP YAE +U+BC69(2);; # HANGUL SYLLABLE PIEUP YAE KIYEOK +U+BC6A(2);; # HANGUL SYLLABLE PIEUP YAE SSANGKIYEOK +U+BC6B(2);; # HANGUL SYLLABLE PIEUP YAE KIYEOKSIOS +U+BC6C(2);; # HANGUL SYLLABLE PIEUP YAE NIEUN +U+BC6D(2);; # HANGUL SYLLABLE PIEUP YAE NIEUNCIEUC +U+BC6E(2);; # HANGUL SYLLABLE PIEUP YAE NIEUNHIEUH +U+BC6F(2);; # HANGUL SYLLABLE PIEUP YAE TIKEUT +U+BC70(2);; # HANGUL SYLLABLE PIEUP YAE RIEUL +U+BC71(2);; # HANGUL SYLLABLE PIEUP YAE RIEULKIYEOK +U+BC72(2);; # HANGUL SYLLABLE PIEUP YAE RIEULMIEUM +U+BC73(2);; # HANGUL SYLLABLE PIEUP YAE RIEULPIEUP +U+BC74(2);; # HANGUL SYLLABLE PIEUP YAE RIEULSIOS +U+BC75(2);; # HANGUL SYLLABLE PIEUP YAE RIEULTHIEUTH +U+BC76(2);; # HANGUL SYLLABLE PIEUP YAE RIEULPHIEUPH +U+BC77(2);; # HANGUL SYLLABLE PIEUP YAE RIEULHIEUH +U+BC78(2);; # HANGUL SYLLABLE PIEUP YAE MIEUM +U+BC79(2);; # HANGUL SYLLABLE PIEUP YAE PIEUP +U+BC7A(2);; # HANGUL SYLLABLE PIEUP YAE PIEUPSIOS +U+BC7B(2);; # HANGUL SYLLABLE PIEUP YAE SIOS +U+BC7C(2);; # HANGUL SYLLABLE PIEUP YAE SSANGSIOS +U+BC7D(2);; # HANGUL SYLLABLE PIEUP YAE IEUNG +U+BC7E(2);; # HANGUL SYLLABLE PIEUP YAE CIEUC +U+BC7F(2);; # HANGUL SYLLABLE PIEUP YAE CHIEUCH +U+BC80(2);; # HANGUL SYLLABLE PIEUP YAE KHIEUKH +U+BC81(2);; # HANGUL SYLLABLE PIEUP YAE THIEUTH +U+BC82(2);; # HANGUL SYLLABLE PIEUP YAE PHIEUPH +U+BC83(2);; # HANGUL SYLLABLE PIEUP YAE HIEUH +U+BC84(2);; # HANGUL SYLLABLE PIEUP EO * +U+BC85(2);; # HANGUL SYLLABLE PIEUP EO KIYEOK * +U+BC86(2);; # HANGUL SYLLABLE PIEUP EO SSANGKIYEOK +U+BC87(2);; # HANGUL SYLLABLE PIEUP EO KIYEOKSIOS +U+BC88(2);; # HANGUL SYLLABLE PIEUP EO NIEUN * +U+BC89(2);; # HANGUL SYLLABLE PIEUP EO NIEUNCIEUC +U+BC8A(2);; # HANGUL SYLLABLE PIEUP EO NIEUNHIEUH +U+BC8B(2);; # HANGUL SYLLABLE PIEUP EO TIKEUT * +U+BC8C(2);; # HANGUL SYLLABLE PIEUP EO RIEUL * +U+BC8D(2);; # HANGUL SYLLABLE PIEUP EO RIEULKIYEOK +U+BC8E(2);; # HANGUL SYLLABLE PIEUP EO RIEULMIEUM * +U+BC8F(2);; # HANGUL SYLLABLE PIEUP EO RIEULPIEUP +U+BC90(2);; # HANGUL SYLLABLE PIEUP EO RIEULSIOS +U+BC91(2);; # HANGUL SYLLABLE PIEUP EO RIEULTHIEUTH +U+BC92(2);; # HANGUL SYLLABLE PIEUP EO RIEULPHIEUPH +U+BC93(2);; # HANGUL SYLLABLE PIEUP EO RIEULHIEUH +U+BC94(2);; # HANGUL SYLLABLE PIEUP EO MIEUM * +U+BC95(2);; # HANGUL SYLLABLE PIEUP EO PIEUP * +U+BC96(2);; # HANGUL SYLLABLE PIEUP EO PIEUPSIOS +U+BC97(2);; # HANGUL SYLLABLE PIEUP EO SIOS * +U+BC98(2);; # HANGUL SYLLABLE PIEUP EO SSANGSIOS +U+BC99(2);; # HANGUL SYLLABLE PIEUP EO IEUNG * +U+BC9A(2);; # HANGUL SYLLABLE PIEUP EO CIEUC * +U+BC9B(2);; # HANGUL SYLLABLE PIEUP EO CHIEUCH +U+BC9C(2);; # HANGUL SYLLABLE PIEUP EO KHIEUKH +U+BC9D(2);; # HANGUL SYLLABLE PIEUP EO THIEUTH +U+BC9E(2);; # HANGUL SYLLABLE PIEUP EO PHIEUPH +U+BC9F(2);; # HANGUL SYLLABLE PIEUP EO HIEUH +U+BCA0(2);; # HANGUL SYLLABLE PIEUP E * +U+BCA1(2);; # HANGUL SYLLABLE PIEUP E KIYEOK * +U+BCA2(2);; # HANGUL SYLLABLE PIEUP E SSANGKIYEOK +U+BCA3(2);; # HANGUL SYLLABLE PIEUP E KIYEOKSIOS +U+BCA4(2);; # HANGUL SYLLABLE PIEUP E NIEUN * +U+BCA5(2);; # HANGUL SYLLABLE PIEUP E NIEUNCIEUC +U+BCA6(2);; # HANGUL SYLLABLE PIEUP E NIEUNHIEUH +U+BCA7(2);; # HANGUL SYLLABLE PIEUP E TIKEUT * +U+BCA8(2);; # HANGUL SYLLABLE PIEUP E RIEUL * +U+BCA9(2);; # HANGUL SYLLABLE PIEUP E RIEULKIYEOK +U+BCAA(2);; # HANGUL SYLLABLE PIEUP E RIEULMIEUM +U+BCAB(2);; # HANGUL SYLLABLE PIEUP E RIEULPIEUP +U+BCAC(2);; # HANGUL SYLLABLE PIEUP E RIEULSIOS +U+BCAD(2);; # HANGUL SYLLABLE PIEUP E RIEULTHIEUTH +U+BCAE(2);; # HANGUL SYLLABLE PIEUP E RIEULPHIEUPH +U+BCAF(2);; # HANGUL SYLLABLE PIEUP E RIEULHIEUH +U+BCB0(2);; # HANGUL SYLLABLE PIEUP E MIEUM * +U+BCB1(2);; # HANGUL SYLLABLE PIEUP E PIEUP * +U+BCB2(2);; # HANGUL SYLLABLE PIEUP E PIEUPSIOS +U+BCB3(2);; # HANGUL SYLLABLE PIEUP E SIOS * +U+BCB4(2);; # HANGUL SYLLABLE PIEUP E SSANGSIOS * +U+BCB5(2);; # HANGUL SYLLABLE PIEUP E IEUNG * +U+BCB6(2);; # HANGUL SYLLABLE PIEUP E CIEUC +U+BCB7(2);; # HANGUL SYLLABLE PIEUP E CHIEUCH +U+BCB8(2);; # HANGUL SYLLABLE PIEUP E KHIEUKH +U+BCB9(2);; # HANGUL SYLLABLE PIEUP E THIEUTH +U+BCBA(2);; # HANGUL SYLLABLE PIEUP E PHIEUPH +U+BCBB(2);; # HANGUL SYLLABLE PIEUP E HIEUH +U+BCBC(2);; # HANGUL SYLLABLE PIEUP YEO * +U+BCBD(2);; # HANGUL SYLLABLE PIEUP YEO KIYEOK * +U+BCBE(2);; # HANGUL SYLLABLE PIEUP YEO SSANGKIYEOK +U+BCBF(2);; # HANGUL SYLLABLE PIEUP YEO KIYEOKSIOS +U+BCC0(2);; # HANGUL SYLLABLE PIEUP YEO NIEUN * +U+BCC1(2);; # HANGUL SYLLABLE PIEUP YEO NIEUNCIEUC +U+BCC2(2);; # HANGUL SYLLABLE PIEUP YEO NIEUNHIEUH +U+BCC3(2);; # HANGUL SYLLABLE PIEUP YEO TIKEUT +U+BCC4(2);; # HANGUL SYLLABLE PIEUP YEO RIEUL * +U+BCC5(2);; # HANGUL SYLLABLE PIEUP YEO RIEULKIYEOK +U+BCC6(2);; # HANGUL SYLLABLE PIEUP YEO RIEULMIEUM +U+BCC7(2);; # HANGUL SYLLABLE PIEUP YEO RIEULPIEUP +U+BCC8(2);; # HANGUL SYLLABLE PIEUP YEO RIEULSIOS +U+BCC9(2);; # HANGUL SYLLABLE PIEUP YEO RIEULTHIEUTH +U+BCCA(2);; # HANGUL SYLLABLE PIEUP YEO RIEULPHIEUPH +U+BCCB(2);; # HANGUL SYLLABLE PIEUP YEO RIEULHIEUH +U+BCCC(2);; # HANGUL SYLLABLE PIEUP YEO MIEUM +U+BCCD(2);; # HANGUL SYLLABLE PIEUP YEO PIEUP * +U+BCCE(2);; # HANGUL SYLLABLE PIEUP YEO PIEUPSIOS +U+BCCF(2);; # HANGUL SYLLABLE PIEUP YEO SIOS * +U+BCD0(2);; # HANGUL SYLLABLE PIEUP YEO SSANGSIOS * +U+BCD1(2);; # HANGUL SYLLABLE PIEUP YEO IEUNG * +U+BCD2(2);; # HANGUL SYLLABLE PIEUP YEO CIEUC +U+BCD3(2);; # HANGUL SYLLABLE PIEUP YEO CHIEUCH +U+BCD4(2);; # HANGUL SYLLABLE PIEUP YEO KHIEUKH +U+BCD5(2);; # HANGUL SYLLABLE PIEUP YEO THIEUTH * +U+BCD6(2);; # HANGUL SYLLABLE PIEUP YEO PHIEUPH +U+BCD7(2);; # HANGUL SYLLABLE PIEUP YEO HIEUH +U+BCD8(2);; # HANGUL SYLLABLE PIEUP YE * +U+BCD9(2);; # HANGUL SYLLABLE PIEUP YE KIYEOK +U+BCDA(2);; # HANGUL SYLLABLE PIEUP YE SSANGKIYEOK +U+BCDB(2);; # HANGUL SYLLABLE PIEUP YE KIYEOKSIOS +U+BCDC(2);; # HANGUL SYLLABLE PIEUP YE NIEUN * +U+BCDD(2);; # HANGUL SYLLABLE PIEUP YE NIEUNCIEUC +U+BCDE(2);; # HANGUL SYLLABLE PIEUP YE NIEUNHIEUH +U+BCDF(2);; # HANGUL SYLLABLE PIEUP YE TIKEUT +U+BCE0(2);; # HANGUL SYLLABLE PIEUP YE RIEUL +U+BCE1(2);; # HANGUL SYLLABLE PIEUP YE RIEULKIYEOK +U+BCE2(2);; # HANGUL SYLLABLE PIEUP YE RIEULMIEUM +U+BCE3(2);; # HANGUL SYLLABLE PIEUP YE RIEULPIEUP +U+BCE4(2);; # HANGUL SYLLABLE PIEUP YE RIEULSIOS +U+BCE5(2);; # HANGUL SYLLABLE PIEUP YE RIEULTHIEUTH +U+BCE6(2);; # HANGUL SYLLABLE PIEUP YE RIEULPHIEUPH +U+BCE7(2);; # HANGUL SYLLABLE PIEUP YE RIEULHIEUH +U+BCE8(2);; # HANGUL SYLLABLE PIEUP YE MIEUM +U+BCE9(2);; # HANGUL SYLLABLE PIEUP YE PIEUP +U+BCEA(2);; # HANGUL SYLLABLE PIEUP YE PIEUPSIOS +U+BCEB(2);; # HANGUL SYLLABLE PIEUP YE SIOS +U+BCEC(2);; # HANGUL SYLLABLE PIEUP YE SSANGSIOS +U+BCED(2);; # HANGUL SYLLABLE PIEUP YE IEUNG +U+BCEE(2);; # HANGUL SYLLABLE PIEUP YE CIEUC +U+BCEF(2);; # HANGUL SYLLABLE PIEUP YE CHIEUCH +U+BCF0(2);; # HANGUL SYLLABLE PIEUP YE KHIEUKH +U+BCF1(2);; # HANGUL SYLLABLE PIEUP YE THIEUTH +U+BCF2(2);; # HANGUL SYLLABLE PIEUP YE PHIEUPH +U+BCF3(2);; # HANGUL SYLLABLE PIEUP YE HIEUH +U+BCF4(2);; # HANGUL SYLLABLE PIEUP O * +U+BCF5(2);; # HANGUL SYLLABLE PIEUP O KIYEOK * +U+BCF6(2);; # HANGUL SYLLABLE PIEUP O SSANGKIYEOK * +U+BCF7(2);; # HANGUL SYLLABLE PIEUP O KIYEOKSIOS +U+BCF8(2);; # HANGUL SYLLABLE PIEUP O NIEUN * +U+BCF9(2);; # HANGUL SYLLABLE PIEUP O NIEUNCIEUC +U+BCFA(2);; # HANGUL SYLLABLE PIEUP O NIEUNHIEUH +U+BCFB(2);; # HANGUL SYLLABLE PIEUP O TIKEUT +U+BCFC(2);; # HANGUL SYLLABLE PIEUP O RIEUL * +U+BCFD(2);; # HANGUL SYLLABLE PIEUP O RIEULKIYEOK +U+BCFE(2);; # HANGUL SYLLABLE PIEUP O RIEULMIEUM +U+BCFF(2);; # HANGUL SYLLABLE PIEUP O RIEULPIEUP +U+BD00(2);; # HANGUL SYLLABLE PIEUP O RIEULSIOS +U+BD01(2);; # HANGUL SYLLABLE PIEUP O RIEULTHIEUTH +U+BD02(2);; # HANGUL SYLLABLE PIEUP O RIEULPHIEUPH +U+BD03(2);; # HANGUL SYLLABLE PIEUP O RIEULHIEUH +U+BD04(2);; # HANGUL SYLLABLE PIEUP O MIEUM * +U+BD05(2);; # HANGUL SYLLABLE PIEUP O PIEUP * +U+BD06(2);; # HANGUL SYLLABLE PIEUP O PIEUPSIOS +U+BD07(2);; # HANGUL SYLLABLE PIEUP O SIOS * +U+BD08(2);; # HANGUL SYLLABLE PIEUP O SSANGSIOS +U+BD09(2);; # HANGUL SYLLABLE PIEUP O IEUNG * +U+BD0A(2);; # HANGUL SYLLABLE PIEUP O CIEUC +U+BD0B(2);; # HANGUL SYLLABLE PIEUP O CHIEUCH +U+BD0C(2);; # HANGUL SYLLABLE PIEUP O KHIEUKH +U+BD0D(2);; # HANGUL SYLLABLE PIEUP O THIEUTH +U+BD0E(2);; # HANGUL SYLLABLE PIEUP O PHIEUPH +U+BD0F(2);; # HANGUL SYLLABLE PIEUP O HIEUH +U+BD10(2);; # HANGUL SYLLABLE PIEUP WA * +U+BD11(2);; # HANGUL SYLLABLE PIEUP WA KIYEOK +U+BD12(2);; # HANGUL SYLLABLE PIEUP WA SSANGKIYEOK +U+BD13(2);; # HANGUL SYLLABLE PIEUP WA KIYEOKSIOS +U+BD14(2);; # HANGUL SYLLABLE PIEUP WA NIEUN * +U+BD15(2);; # HANGUL SYLLABLE PIEUP WA NIEUNCIEUC +U+BD16(2);; # HANGUL SYLLABLE PIEUP WA NIEUNHIEUH +U+BD17(2);; # HANGUL SYLLABLE PIEUP WA TIKEUT +U+BD18(2);; # HANGUL SYLLABLE PIEUP WA RIEUL +U+BD19(2);; # HANGUL SYLLABLE PIEUP WA RIEULKIYEOK +U+BD1A(2);; # HANGUL SYLLABLE PIEUP WA RIEULMIEUM +U+BD1B(2);; # HANGUL SYLLABLE PIEUP WA RIEULPIEUP +U+BD1C(2);; # HANGUL SYLLABLE PIEUP WA RIEULSIOS +U+BD1D(2);; # HANGUL SYLLABLE PIEUP WA RIEULTHIEUTH +U+BD1E(2);; # HANGUL SYLLABLE PIEUP WA RIEULPHIEUPH +U+BD1F(2);; # HANGUL SYLLABLE PIEUP WA RIEULHIEUH +U+BD20(2);; # HANGUL SYLLABLE PIEUP WA MIEUM +U+BD21(2);; # HANGUL SYLLABLE PIEUP WA PIEUP +U+BD22(2);; # HANGUL SYLLABLE PIEUP WA PIEUPSIOS +U+BD23(2);; # HANGUL SYLLABLE PIEUP WA SIOS +U+BD24(2);; # HANGUL SYLLABLE PIEUP WA SSANGSIOS * +U+BD25(2);; # HANGUL SYLLABLE PIEUP WA IEUNG +U+BD26(2);; # HANGUL SYLLABLE PIEUP WA CIEUC +U+BD27(2);; # HANGUL SYLLABLE PIEUP WA CHIEUCH +U+BD28(2);; # HANGUL SYLLABLE PIEUP WA KHIEUKH +U+BD29(2);; # HANGUL SYLLABLE PIEUP WA THIEUTH +U+BD2A(2);; # HANGUL SYLLABLE PIEUP WA PHIEUPH +U+BD2B(2);; # HANGUL SYLLABLE PIEUP WA HIEUH +U+BD2C(2);; # HANGUL SYLLABLE PIEUP WAE * +U+BD2D(2);; # HANGUL SYLLABLE PIEUP WAE KIYEOK +U+BD2E(2);; # HANGUL SYLLABLE PIEUP WAE SSANGKIYEOK +U+BD2F(2);; # HANGUL SYLLABLE PIEUP WAE KIYEOKSIOS +U+BD30(2);; # HANGUL SYLLABLE PIEUP WAE NIEUN +U+BD31(2);; # HANGUL SYLLABLE PIEUP WAE NIEUNCIEUC +U+BD32(2);; # HANGUL SYLLABLE PIEUP WAE NIEUNHIEUH +U+BD33(2);; # HANGUL SYLLABLE PIEUP WAE TIKEUT +U+BD34(2);; # HANGUL SYLLABLE PIEUP WAE RIEUL +U+BD35(2);; # HANGUL SYLLABLE PIEUP WAE RIEULKIYEOK +U+BD36(2);; # HANGUL SYLLABLE PIEUP WAE RIEULMIEUM +U+BD37(2);; # HANGUL SYLLABLE PIEUP WAE RIEULPIEUP +U+BD38(2);; # HANGUL SYLLABLE PIEUP WAE RIEULSIOS +U+BD39(2);; # HANGUL SYLLABLE PIEUP WAE RIEULTHIEUTH +U+BD3A(2);; # HANGUL SYLLABLE PIEUP WAE RIEULPHIEUPH +U+BD3B(2);; # HANGUL SYLLABLE PIEUP WAE RIEULHIEUH +U+BD3C(2);; # HANGUL SYLLABLE PIEUP WAE MIEUM +U+BD3D(2);; # HANGUL SYLLABLE PIEUP WAE PIEUP +U+BD3E(2);; # HANGUL SYLLABLE PIEUP WAE PIEUPSIOS +U+BD3F(2);; # HANGUL SYLLABLE PIEUP WAE SIOS +U+BD40(2);; # HANGUL SYLLABLE PIEUP WAE SSANGSIOS * +U+BD41(2);; # HANGUL SYLLABLE PIEUP WAE IEUNG +U+BD42(2);; # HANGUL SYLLABLE PIEUP WAE CIEUC +U+BD43(2);; # HANGUL SYLLABLE PIEUP WAE CHIEUCH +U+BD44(2);; # HANGUL SYLLABLE PIEUP WAE KHIEUKH +U+BD45(2);; # HANGUL SYLLABLE PIEUP WAE THIEUTH +U+BD46(2);; # HANGUL SYLLABLE PIEUP WAE PHIEUPH +U+BD47(2);; # HANGUL SYLLABLE PIEUP WAE HIEUH +U+BD48(2);; # HANGUL SYLLABLE PIEUP OE * +U+BD49(2);; # HANGUL SYLLABLE PIEUP OE KIYEOK * +U+BD4A(2);; # HANGUL SYLLABLE PIEUP OE SSANGKIYEOK +U+BD4B(2);; # HANGUL SYLLABLE PIEUP OE KIYEOKSIOS +U+BD4C(2);; # HANGUL SYLLABLE PIEUP OE NIEUN * +U+BD4D(2);; # HANGUL SYLLABLE PIEUP OE NIEUNCIEUC +U+BD4E(2);; # HANGUL SYLLABLE PIEUP OE NIEUNHIEUH +U+BD4F(2);; # HANGUL SYLLABLE PIEUP OE TIKEUT +U+BD50(2);; # HANGUL SYLLABLE PIEUP OE RIEUL * +U+BD51(2);; # HANGUL SYLLABLE PIEUP OE RIEULKIYEOK +U+BD52(2);; # HANGUL SYLLABLE PIEUP OE RIEULMIEUM +U+BD53(2);; # HANGUL SYLLABLE PIEUP OE RIEULPIEUP +U+BD54(2);; # HANGUL SYLLABLE PIEUP OE RIEULSIOS +U+BD55(2);; # HANGUL SYLLABLE PIEUP OE RIEULTHIEUTH +U+BD56(2);; # HANGUL SYLLABLE PIEUP OE RIEULPHIEUPH +U+BD57(2);; # HANGUL SYLLABLE PIEUP OE RIEULHIEUH +U+BD58(2);; # HANGUL SYLLABLE PIEUP OE MIEUM * +U+BD59(2);; # HANGUL SYLLABLE PIEUP OE PIEUP * +U+BD5A(2);; # HANGUL SYLLABLE PIEUP OE PIEUPSIOS +U+BD5B(2);; # HANGUL SYLLABLE PIEUP OE SIOS +U+BD5C(2);; # HANGUL SYLLABLE PIEUP OE SSANGSIOS +U+BD5D(2);; # HANGUL SYLLABLE PIEUP OE IEUNG +U+BD5E(2);; # HANGUL SYLLABLE PIEUP OE CIEUC +U+BD5F(2);; # HANGUL SYLLABLE PIEUP OE CHIEUCH +U+BD60(2);; # HANGUL SYLLABLE PIEUP OE KHIEUKH +U+BD61(2);; # HANGUL SYLLABLE PIEUP OE THIEUTH +U+BD62(2);; # HANGUL SYLLABLE PIEUP OE PHIEUPH +U+BD63(2);; # HANGUL SYLLABLE PIEUP OE HIEUH +U+BD64(2);; # HANGUL SYLLABLE PIEUP YO * +U+BD65(2);; # HANGUL SYLLABLE PIEUP YO KIYEOK +U+BD66(2);; # HANGUL SYLLABLE PIEUP YO SSANGKIYEOK +U+BD67(2);; # HANGUL SYLLABLE PIEUP YO KIYEOKSIOS +U+BD68(2);; # HANGUL SYLLABLE PIEUP YO NIEUN * +U+BD69(2);; # HANGUL SYLLABLE PIEUP YO NIEUNCIEUC +U+BD6A(2);; # HANGUL SYLLABLE PIEUP YO NIEUNHIEUH +U+BD6B(2);; # HANGUL SYLLABLE PIEUP YO TIKEUT +U+BD6C(2);; # HANGUL SYLLABLE PIEUP YO RIEUL +U+BD6D(2);; # HANGUL SYLLABLE PIEUP YO RIEULKIYEOK +U+BD6E(2);; # HANGUL SYLLABLE PIEUP YO RIEULMIEUM +U+BD6F(2);; # HANGUL SYLLABLE PIEUP YO RIEULPIEUP +U+BD70(2);; # HANGUL SYLLABLE PIEUP YO RIEULSIOS +U+BD71(2);; # HANGUL SYLLABLE PIEUP YO RIEULTHIEUTH +U+BD72(2);; # HANGUL SYLLABLE PIEUP YO RIEULPHIEUPH +U+BD73(2);; # HANGUL SYLLABLE PIEUP YO RIEULHIEUH +U+BD74(2);; # HANGUL SYLLABLE PIEUP YO MIEUM +U+BD75(2);; # HANGUL SYLLABLE PIEUP YO PIEUP +U+BD76(2);; # HANGUL SYLLABLE PIEUP YO PIEUPSIOS +U+BD77(2);; # HANGUL SYLLABLE PIEUP YO SIOS +U+BD78(2);; # HANGUL SYLLABLE PIEUP YO SSANGSIOS +U+BD79(2);; # HANGUL SYLLABLE PIEUP YO IEUNG +U+BD7A(2);; # HANGUL SYLLABLE PIEUP YO CIEUC +U+BD7B(2);; # HANGUL SYLLABLE PIEUP YO CHIEUCH +U+BD7C(2);; # HANGUL SYLLABLE PIEUP YO KHIEUKH +U+BD7D(2);; # HANGUL SYLLABLE PIEUP YO THIEUTH +U+BD7E(2);; # HANGUL SYLLABLE PIEUP YO PHIEUPH +U+BD7F(2);; # HANGUL SYLLABLE PIEUP YO HIEUH +U+BD80(2);; # HANGUL SYLLABLE PIEUP U * +U+BD81(2);; # HANGUL SYLLABLE PIEUP U KIYEOK * +U+BD82(2);; # HANGUL SYLLABLE PIEUP U SSANGKIYEOK +U+BD83(2);; # HANGUL SYLLABLE PIEUP U KIYEOKSIOS +U+BD84(2);; # HANGUL SYLLABLE PIEUP U NIEUN * +U+BD85(2);; # HANGUL SYLLABLE PIEUP U NIEUNCIEUC +U+BD86(2);; # HANGUL SYLLABLE PIEUP U NIEUNHIEUH +U+BD87(2);; # HANGUL SYLLABLE PIEUP U TIKEUT * +U+BD88(2);; # HANGUL SYLLABLE PIEUP U RIEUL * +U+BD89(2);; # HANGUL SYLLABLE PIEUP U RIEULKIYEOK * +U+BD8A(2);; # HANGUL SYLLABLE PIEUP U RIEULMIEUM * +U+BD8B(2);; # HANGUL SYLLABLE PIEUP U RIEULPIEUP +U+BD8C(2);; # HANGUL SYLLABLE PIEUP U RIEULSIOS +U+BD8D(2);; # HANGUL SYLLABLE PIEUP U RIEULTHIEUTH +U+BD8E(2);; # HANGUL SYLLABLE PIEUP U RIEULPHIEUPH +U+BD8F(2);; # HANGUL SYLLABLE PIEUP U RIEULHIEUH +U+BD90(2);; # HANGUL SYLLABLE PIEUP U MIEUM * +U+BD91(2);; # HANGUL SYLLABLE PIEUP U PIEUP * +U+BD92(2);; # HANGUL SYLLABLE PIEUP U PIEUPSIOS +U+BD93(2);; # HANGUL SYLLABLE PIEUP U SIOS * +U+BD94(2);; # HANGUL SYLLABLE PIEUP U SSANGSIOS +U+BD95(2);; # HANGUL SYLLABLE PIEUP U IEUNG * +U+BD96(2);; # HANGUL SYLLABLE PIEUP U CIEUC +U+BD97(2);; # HANGUL SYLLABLE PIEUP U CHIEUCH +U+BD98(2);; # HANGUL SYLLABLE PIEUP U KHIEUKH +U+BD99(2);; # HANGUL SYLLABLE PIEUP U THIEUTH * +U+BD9A(2);; # HANGUL SYLLABLE PIEUP U PHIEUPH * +U+BD9B(2);; # HANGUL SYLLABLE PIEUP U HIEUH +U+BD9C(2);; # HANGUL SYLLABLE PIEUP WEO * +U+BD9D(2);; # HANGUL SYLLABLE PIEUP WEO KIYEOK +U+BD9E(2);; # HANGUL SYLLABLE PIEUP WEO SSANGKIYEOK +U+BD9F(2);; # HANGUL SYLLABLE PIEUP WEO KIYEOKSIOS +U+BDA0(2);; # HANGUL SYLLABLE PIEUP WEO NIEUN +U+BDA1(2);; # HANGUL SYLLABLE PIEUP WEO NIEUNCIEUC +U+BDA2(2);; # HANGUL SYLLABLE PIEUP WEO NIEUNHIEUH +U+BDA3(2);; # HANGUL SYLLABLE PIEUP WEO TIKEUT +U+BDA4(2);; # HANGUL SYLLABLE PIEUP WEO RIEUL * +U+BDA5(2);; # HANGUL SYLLABLE PIEUP WEO RIEULKIYEOK +U+BDA6(2);; # HANGUL SYLLABLE PIEUP WEO RIEULMIEUM +U+BDA7(2);; # HANGUL SYLLABLE PIEUP WEO RIEULPIEUP +U+BDA8(2);; # HANGUL SYLLABLE PIEUP WEO RIEULSIOS +U+BDA9(2);; # HANGUL SYLLABLE PIEUP WEO RIEULTHIEUTH +U+BDAA(2);; # HANGUL SYLLABLE PIEUP WEO RIEULPHIEUPH +U+BDAB(2);; # HANGUL SYLLABLE PIEUP WEO RIEULHIEUH +U+BDAC(2);; # HANGUL SYLLABLE PIEUP WEO MIEUM +U+BDAD(2);; # HANGUL SYLLABLE PIEUP WEO PIEUP +U+BDAE(2);; # HANGUL SYLLABLE PIEUP WEO PIEUPSIOS +U+BDAF(2);; # HANGUL SYLLABLE PIEUP WEO SIOS +U+BDB0(2);; # HANGUL SYLLABLE PIEUP WEO SSANGSIOS * +U+BDB1(2);; # HANGUL SYLLABLE PIEUP WEO IEUNG +U+BDB2(2);; # HANGUL SYLLABLE PIEUP WEO CIEUC +U+BDB3(2);; # HANGUL SYLLABLE PIEUP WEO CHIEUCH +U+BDB4(2);; # HANGUL SYLLABLE PIEUP WEO KHIEUKH +U+BDB5(2);; # HANGUL SYLLABLE PIEUP WEO THIEUTH +U+BDB6(2);; # HANGUL SYLLABLE PIEUP WEO PHIEUPH +U+BDB7(2);; # HANGUL SYLLABLE PIEUP WEO HIEUH +U+BDB8(2);; # HANGUL SYLLABLE PIEUP WE * +U+BDB9(2);; # HANGUL SYLLABLE PIEUP WE KIYEOK +U+BDBA(2);; # HANGUL SYLLABLE PIEUP WE SSANGKIYEOK +U+BDBB(2);; # HANGUL SYLLABLE PIEUP WE KIYEOKSIOS +U+BDBC(2);; # HANGUL SYLLABLE PIEUP WE NIEUN +U+BDBD(2);; # HANGUL SYLLABLE PIEUP WE NIEUNCIEUC +U+BDBE(2);; # HANGUL SYLLABLE PIEUP WE NIEUNHIEUH +U+BDBF(2);; # HANGUL SYLLABLE PIEUP WE TIKEUT +U+BDC0(2);; # HANGUL SYLLABLE PIEUP WE RIEUL +U+BDC1(2);; # HANGUL SYLLABLE PIEUP WE RIEULKIYEOK +U+BDC2(2);; # HANGUL SYLLABLE PIEUP WE RIEULMIEUM +U+BDC3(2);; # HANGUL SYLLABLE PIEUP WE RIEULPIEUP +U+BDC4(2);; # HANGUL SYLLABLE PIEUP WE RIEULSIOS +U+BDC5(2);; # HANGUL SYLLABLE PIEUP WE RIEULTHIEUTH +U+BDC6(2);; # HANGUL SYLLABLE PIEUP WE RIEULPHIEUPH +U+BDC7(2);; # HANGUL SYLLABLE PIEUP WE RIEULHIEUH +U+BDC8(2);; # HANGUL SYLLABLE PIEUP WE MIEUM +U+BDC9(2);; # HANGUL SYLLABLE PIEUP WE PIEUP +U+BDCA(2);; # HANGUL SYLLABLE PIEUP WE PIEUPSIOS +U+BDCB(2);; # HANGUL SYLLABLE PIEUP WE SIOS +U+BDCC(2);; # HANGUL SYLLABLE PIEUP WE SSANGSIOS +U+BDCD(2);; # HANGUL SYLLABLE PIEUP WE IEUNG +U+BDCE(2);; # HANGUL SYLLABLE PIEUP WE CIEUC +U+BDCF(2);; # HANGUL SYLLABLE PIEUP WE CHIEUCH +U+BDD0(2);; # HANGUL SYLLABLE PIEUP WE KHIEUKH +U+BDD1(2);; # HANGUL SYLLABLE PIEUP WE THIEUTH +U+BDD2(2);; # HANGUL SYLLABLE PIEUP WE PHIEUPH +U+BDD3(2);; # HANGUL SYLLABLE PIEUP WE HIEUH +U+BDD4(2);; # HANGUL SYLLABLE PIEUP WI * +U+BDD5(2);; # HANGUL SYLLABLE PIEUP WI KIYEOK * +U+BDD6(2);; # HANGUL SYLLABLE PIEUP WI SSANGKIYEOK +U+BDD7(2);; # HANGUL SYLLABLE PIEUP WI KIYEOKSIOS +U+BDD8(2);; # HANGUL SYLLABLE PIEUP WI NIEUN * +U+BDD9(2);; # HANGUL SYLLABLE PIEUP WI NIEUNCIEUC +U+BDDA(2);; # HANGUL SYLLABLE PIEUP WI NIEUNHIEUH +U+BDDB(2);; # HANGUL SYLLABLE PIEUP WI TIKEUT +U+BDDC(2);; # HANGUL SYLLABLE PIEUP WI RIEUL * +U+BDDD(2);; # HANGUL SYLLABLE PIEUP WI RIEULKIYEOK +U+BDDE(2);; # HANGUL SYLLABLE PIEUP WI RIEULMIEUM +U+BDDF(2);; # HANGUL SYLLABLE PIEUP WI RIEULPIEUP +U+BDE0(2);; # HANGUL SYLLABLE PIEUP WI RIEULSIOS +U+BDE1(2);; # HANGUL SYLLABLE PIEUP WI RIEULTHIEUTH +U+BDE2(2);; # HANGUL SYLLABLE PIEUP WI RIEULPHIEUPH +U+BDE3(2);; # HANGUL SYLLABLE PIEUP WI RIEULHIEUH +U+BDE4(2);; # HANGUL SYLLABLE PIEUP WI MIEUM +U+BDE5(2);; # HANGUL SYLLABLE PIEUP WI PIEUP +U+BDE6(2);; # HANGUL SYLLABLE PIEUP WI PIEUPSIOS +U+BDE7(2);; # HANGUL SYLLABLE PIEUP WI SIOS +U+BDE8(2);; # HANGUL SYLLABLE PIEUP WI SSANGSIOS +U+BDE9(2);; # HANGUL SYLLABLE PIEUP WI IEUNG * +U+BDEA(2);; # HANGUL SYLLABLE PIEUP WI CIEUC +U+BDEB(2);; # HANGUL SYLLABLE PIEUP WI CHIEUCH +U+BDEC(2);; # HANGUL SYLLABLE PIEUP WI KHIEUKH +U+BDED(2);; # HANGUL SYLLABLE PIEUP WI THIEUTH +U+BDEE(2);; # HANGUL SYLLABLE PIEUP WI PHIEUPH +U+BDEF(2);; # HANGUL SYLLABLE PIEUP WI HIEUH +U+BDF0(2);; # HANGUL SYLLABLE PIEUP YU * +U+BDF1(2);; # HANGUL SYLLABLE PIEUP YU KIYEOK +U+BDF2(2);; # HANGUL SYLLABLE PIEUP YU SSANGKIYEOK +U+BDF3(2);; # HANGUL SYLLABLE PIEUP YU KIYEOKSIOS +U+BDF4(2);; # HANGUL SYLLABLE PIEUP YU NIEUN * +U+BDF5(2);; # HANGUL SYLLABLE PIEUP YU NIEUNCIEUC +U+BDF6(2);; # HANGUL SYLLABLE PIEUP YU NIEUNHIEUH +U+BDF7(2);; # HANGUL SYLLABLE PIEUP YU TIKEUT +U+BDF8(2);; # HANGUL SYLLABLE PIEUP YU RIEUL * +U+BDF9(2);; # HANGUL SYLLABLE PIEUP YU RIEULKIYEOK +U+BDFA(2);; # HANGUL SYLLABLE PIEUP YU RIEULMIEUM +U+BDFB(2);; # HANGUL SYLLABLE PIEUP YU RIEULPIEUP +U+BDFC(2);; # HANGUL SYLLABLE PIEUP YU RIEULSIOS +U+BDFD(2);; # HANGUL SYLLABLE PIEUP YU RIEULTHIEUTH +U+BDFE(2);; # HANGUL SYLLABLE PIEUP YU RIEULPHIEUPH +U+BDFF(2);; # HANGUL SYLLABLE PIEUP YU RIEULHIEUH +U+BE00(2);; # HANGUL SYLLABLE PIEUP YU MIEUM * +U+BE01(2);; # HANGUL SYLLABLE PIEUP YU PIEUP +U+BE02(2);; # HANGUL SYLLABLE PIEUP YU PIEUPSIOS +U+BE03(2);; # HANGUL SYLLABLE PIEUP YU SIOS * +U+BE04(2);; # HANGUL SYLLABLE PIEUP YU SSANGSIOS +U+BE05(2);; # HANGUL SYLLABLE PIEUP YU IEUNG * +U+BE06(2);; # HANGUL SYLLABLE PIEUP YU CIEUC +U+BE07(2);; # HANGUL SYLLABLE PIEUP YU CHIEUCH +U+BE08(2);; # HANGUL SYLLABLE PIEUP YU KHIEUKH +U+BE09(2);; # HANGUL SYLLABLE PIEUP YU THIEUTH +U+BE0A(2);; # HANGUL SYLLABLE PIEUP YU PHIEUPH +U+BE0B(2);; # HANGUL SYLLABLE PIEUP YU HIEUH +U+BE0C(2);; # HANGUL SYLLABLE PIEUP EU * +U+BE0D(2);; # HANGUL SYLLABLE PIEUP EU KIYEOK * +U+BE0E(2);; # HANGUL SYLLABLE PIEUP EU SSANGKIYEOK +U+BE0F(2);; # HANGUL SYLLABLE PIEUP EU KIYEOKSIOS +U+BE10(2);; # HANGUL SYLLABLE PIEUP EU NIEUN * +U+BE11(2);; # HANGUL SYLLABLE PIEUP EU NIEUNCIEUC +U+BE12(2);; # HANGUL SYLLABLE PIEUP EU NIEUNHIEUH +U+BE13(2);; # HANGUL SYLLABLE PIEUP EU TIKEUT +U+BE14(2);; # HANGUL SYLLABLE PIEUP EU RIEUL * +U+BE15(2);; # HANGUL SYLLABLE PIEUP EU RIEULKIYEOK +U+BE16(2);; # HANGUL SYLLABLE PIEUP EU RIEULMIEUM +U+BE17(2);; # HANGUL SYLLABLE PIEUP EU RIEULPIEUP +U+BE18(2);; # HANGUL SYLLABLE PIEUP EU RIEULSIOS +U+BE19(2);; # HANGUL SYLLABLE PIEUP EU RIEULTHIEUTH +U+BE1A(2);; # HANGUL SYLLABLE PIEUP EU RIEULPHIEUPH +U+BE1B(2);; # HANGUL SYLLABLE PIEUP EU RIEULHIEUH +U+BE1C(2);; # HANGUL SYLLABLE PIEUP EU MIEUM * +U+BE1D(2);; # HANGUL SYLLABLE PIEUP EU PIEUP * +U+BE1E(2);; # HANGUL SYLLABLE PIEUP EU PIEUPSIOS +U+BE1F(2);; # HANGUL SYLLABLE PIEUP EU SIOS * +U+BE20(2);; # HANGUL SYLLABLE PIEUP EU SSANGSIOS +U+BE21(2);; # HANGUL SYLLABLE PIEUP EU IEUNG +U+BE22(2);; # HANGUL SYLLABLE PIEUP EU CIEUC +U+BE23(2);; # HANGUL SYLLABLE PIEUP EU CHIEUCH +U+BE24(2);; # HANGUL SYLLABLE PIEUP EU KHIEUKH +U+BE25(2);; # HANGUL SYLLABLE PIEUP EU THIEUTH +U+BE26(2);; # HANGUL SYLLABLE PIEUP EU PHIEUPH +U+BE27(2);; # HANGUL SYLLABLE PIEUP EU HIEUH +U+BE28(2);; # HANGUL SYLLABLE PIEUP YI +U+BE29(2);; # HANGUL SYLLABLE PIEUP YI KIYEOK +U+BE2A(2);; # HANGUL SYLLABLE PIEUP YI SSANGKIYEOK +U+BE2B(2);; # HANGUL SYLLABLE PIEUP YI KIYEOKSIOS +U+BE2C(2);; # HANGUL SYLLABLE PIEUP YI NIEUN +U+BE2D(2);; # HANGUL SYLLABLE PIEUP YI NIEUNCIEUC +U+BE2E(2);; # HANGUL SYLLABLE PIEUP YI NIEUNHIEUH +U+BE2F(2);; # HANGUL SYLLABLE PIEUP YI TIKEUT +U+BE30(2);; # HANGUL SYLLABLE PIEUP YI RIEUL +U+BE31(2);; # HANGUL SYLLABLE PIEUP YI RIEULKIYEOK +U+BE32(2);; # HANGUL SYLLABLE PIEUP YI RIEULMIEUM +U+BE33(2);; # HANGUL SYLLABLE PIEUP YI RIEULPIEUP +U+BE34(2);; # HANGUL SYLLABLE PIEUP YI RIEULSIOS +U+BE35(2);; # HANGUL SYLLABLE PIEUP YI RIEULTHIEUTH +U+BE36(2);; # HANGUL SYLLABLE PIEUP YI RIEULPHIEUPH +U+BE37(2);; # HANGUL SYLLABLE PIEUP YI RIEULHIEUH +U+BE38(2);; # HANGUL SYLLABLE PIEUP YI MIEUM +U+BE39(2);; # HANGUL SYLLABLE PIEUP YI PIEUP +U+BE3A(2);; # HANGUL SYLLABLE PIEUP YI PIEUPSIOS +U+BE3B(2);; # HANGUL SYLLABLE PIEUP YI SIOS +U+BE3C(2);; # HANGUL SYLLABLE PIEUP YI SSANGSIOS +U+BE3D(2);; # HANGUL SYLLABLE PIEUP YI IEUNG +U+BE3E(2);; # HANGUL SYLLABLE PIEUP YI CIEUC +U+BE3F(2);; # HANGUL SYLLABLE PIEUP YI CHIEUCH +U+BE40(2);; # HANGUL SYLLABLE PIEUP YI KHIEUKH +U+BE41(2);; # HANGUL SYLLABLE PIEUP YI THIEUTH +U+BE42(2);; # HANGUL SYLLABLE PIEUP YI PHIEUPH +U+BE43(2);; # HANGUL SYLLABLE PIEUP YI HIEUH +U+BE44(2);; # HANGUL SYLLABLE PIEUP I * +U+BE45(2);; # HANGUL SYLLABLE PIEUP I KIYEOK * +U+BE46(2);; # HANGUL SYLLABLE PIEUP I SSANGKIYEOK +U+BE47(2);; # HANGUL SYLLABLE PIEUP I KIYEOKSIOS +U+BE48(2);; # HANGUL SYLLABLE PIEUP I NIEUN * +U+BE49(2);; # HANGUL SYLLABLE PIEUP I NIEUNCIEUC +U+BE4A(2);; # HANGUL SYLLABLE PIEUP I NIEUNHIEUH +U+BE4B(2);; # HANGUL SYLLABLE PIEUP I TIKEUT +U+BE4C(2);; # HANGUL SYLLABLE PIEUP I RIEUL * +U+BE4D(2);; # HANGUL SYLLABLE PIEUP I RIEULKIYEOK +U+BE4E(2);; # HANGUL SYLLABLE PIEUP I RIEULMIEUM * +U+BE4F(2);; # HANGUL SYLLABLE PIEUP I RIEULPIEUP +U+BE50(2);; # HANGUL SYLLABLE PIEUP I RIEULSIOS +U+BE51(2);; # HANGUL SYLLABLE PIEUP I RIEULTHIEUTH +U+BE52(2);; # HANGUL SYLLABLE PIEUP I RIEULPHIEUPH +U+BE53(2);; # HANGUL SYLLABLE PIEUP I RIEULHIEUH +U+BE54(2);; # HANGUL SYLLABLE PIEUP I MIEUM * +U+BE55(2);; # HANGUL SYLLABLE PIEUP I PIEUP * +U+BE56(2);; # HANGUL SYLLABLE PIEUP I PIEUPSIOS +U+BE57(2);; # HANGUL SYLLABLE PIEUP I SIOS * +U+BE58(2);; # HANGUL SYLLABLE PIEUP I SSANGSIOS +U+BE59(2);; # HANGUL SYLLABLE PIEUP I IEUNG * +U+BE5A(2);; # HANGUL SYLLABLE PIEUP I CIEUC * +U+BE5B(2);; # HANGUL SYLLABLE PIEUP I CHIEUCH * +U+BE5C(2);; # HANGUL SYLLABLE PIEUP I KHIEUKH +U+BE5D(2);; # HANGUL SYLLABLE PIEUP I THIEUTH +U+BE5E(2);; # HANGUL SYLLABLE PIEUP I PHIEUPH +U+BE5F(2);; # HANGUL SYLLABLE PIEUP I HIEUH +U+BE60(2);; # HANGUL SYLLABLE SSANGPIEUP A * +U+BE61(2);; # HANGUL SYLLABLE SSANGPIEUP A KIYEOK * +U+BE62(2);; # HANGUL SYLLABLE SSANGPIEUP A SSANGKIYEOK +U+BE63(2);; # HANGUL SYLLABLE SSANGPIEUP A KIYEOKSIOS +U+BE64(2);; # HANGUL SYLLABLE SSANGPIEUP A NIEUN * +U+BE65(2);; # HANGUL SYLLABLE SSANGPIEUP A NIEUNCIEUC +U+BE66(2);; # HANGUL SYLLABLE SSANGPIEUP A NIEUNHIEUH +U+BE67(2);; # HANGUL SYLLABLE SSANGPIEUP A TIKEUT +U+BE68(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEUL * +U+BE69(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULKIYEOK +U+BE6A(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULMIEUM * +U+BE6B(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULPIEUP +U+BE6C(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULSIOS +U+BE6D(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULTHIEUTH +U+BE6E(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULPHIEUPH +U+BE6F(2);; # HANGUL SYLLABLE SSANGPIEUP A RIEULHIEUH +U+BE70(2);; # HANGUL SYLLABLE SSANGPIEUP A MIEUM * +U+BE71(2);; # HANGUL SYLLABLE SSANGPIEUP A PIEUP * +U+BE72(2);; # HANGUL SYLLABLE SSANGPIEUP A PIEUPSIOS +U+BE73(2);; # HANGUL SYLLABLE SSANGPIEUP A SIOS * +U+BE74(2);; # HANGUL SYLLABLE SSANGPIEUP A SSANGSIOS * +U+BE75(2);; # HANGUL SYLLABLE SSANGPIEUP A IEUNG * +U+BE76(2);; # HANGUL SYLLABLE SSANGPIEUP A CIEUC +U+BE77(2);; # HANGUL SYLLABLE SSANGPIEUP A CHIEUCH +U+BE78(2);; # HANGUL SYLLABLE SSANGPIEUP A KHIEUKH +U+BE79(2);; # HANGUL SYLLABLE SSANGPIEUP A THIEUTH +U+BE7A(2);; # HANGUL SYLLABLE SSANGPIEUP A PHIEUPH +U+BE7B(2);; # HANGUL SYLLABLE SSANGPIEUP A HIEUH * +U+BE7C(2);; # HANGUL SYLLABLE SSANGPIEUP AE * +U+BE7D(2);; # HANGUL SYLLABLE SSANGPIEUP AE KIYEOK * +U+BE7E(2);; # HANGUL SYLLABLE SSANGPIEUP AE SSANGKIYEOK +U+BE7F(2);; # HANGUL SYLLABLE SSANGPIEUP AE KIYEOKSIOS +U+BE80(2);; # HANGUL SYLLABLE SSANGPIEUP AE NIEUN * +U+BE81(2);; # HANGUL SYLLABLE SSANGPIEUP AE NIEUNCIEUC +U+BE82(2);; # HANGUL SYLLABLE SSANGPIEUP AE NIEUNHIEUH +U+BE83(2);; # HANGUL SYLLABLE SSANGPIEUP AE TIKEUT +U+BE84(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEUL * +U+BE85(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULKIYEOK +U+BE86(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULMIEUM +U+BE87(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULPIEUP +U+BE88(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULSIOS +U+BE89(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULTHIEUTH +U+BE8A(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULPHIEUPH +U+BE8B(2);; # HANGUL SYLLABLE SSANGPIEUP AE RIEULHIEUH +U+BE8C(2);; # HANGUL SYLLABLE SSANGPIEUP AE MIEUM * +U+BE8D(2);; # HANGUL SYLLABLE SSANGPIEUP AE PIEUP * +U+BE8E(2);; # HANGUL SYLLABLE SSANGPIEUP AE PIEUPSIOS +U+BE8F(2);; # HANGUL SYLLABLE SSANGPIEUP AE SIOS * +U+BE90(2);; # HANGUL SYLLABLE SSANGPIEUP AE SSANGSIOS * +U+BE91(2);; # HANGUL SYLLABLE SSANGPIEUP AE IEUNG * +U+BE92(2);; # HANGUL SYLLABLE SSANGPIEUP AE CIEUC +U+BE93(2);; # HANGUL SYLLABLE SSANGPIEUP AE CHIEUCH +U+BE94(2);; # HANGUL SYLLABLE SSANGPIEUP AE KHIEUKH +U+BE95(2);; # HANGUL SYLLABLE SSANGPIEUP AE THIEUTH +U+BE96(2);; # HANGUL SYLLABLE SSANGPIEUP AE PHIEUPH +U+BE97(2);; # HANGUL SYLLABLE SSANGPIEUP AE HIEUH +U+BE98(2);; # HANGUL SYLLABLE SSANGPIEUP YA * +U+BE99(2);; # HANGUL SYLLABLE SSANGPIEUP YA KIYEOK * +U+BE9A(2);; # HANGUL SYLLABLE SSANGPIEUP YA SSANGKIYEOK +U+BE9B(2);; # HANGUL SYLLABLE SSANGPIEUP YA KIYEOKSIOS +U+BE9C(2);; # HANGUL SYLLABLE SSANGPIEUP YA NIEUN +U+BE9D(2);; # HANGUL SYLLABLE SSANGPIEUP YA NIEUNCIEUC +U+BE9E(2);; # HANGUL SYLLABLE SSANGPIEUP YA NIEUNHIEUH +U+BE9F(2);; # HANGUL SYLLABLE SSANGPIEUP YA TIKEUT +U+BEA0(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEUL +U+BEA1(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULKIYEOK +U+BEA2(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULMIEUM +U+BEA3(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULPIEUP +U+BEA4(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULSIOS +U+BEA5(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULTHIEUTH +U+BEA6(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULPHIEUPH +U+BEA7(2);; # HANGUL SYLLABLE SSANGPIEUP YA RIEULHIEUH +U+BEA8(2);; # HANGUL SYLLABLE SSANGPIEUP YA MIEUM * +U+BEA9(2);; # HANGUL SYLLABLE SSANGPIEUP YA PIEUP +U+BEAA(2);; # HANGUL SYLLABLE SSANGPIEUP YA PIEUPSIOS +U+BEAB(2);; # HANGUL SYLLABLE SSANGPIEUP YA SIOS +U+BEAC(2);; # HANGUL SYLLABLE SSANGPIEUP YA SSANGSIOS +U+BEAD(2);; # HANGUL SYLLABLE SSANGPIEUP YA IEUNG +U+BEAE(2);; # HANGUL SYLLABLE SSANGPIEUP YA CIEUC +U+BEAF(2);; # HANGUL SYLLABLE SSANGPIEUP YA CHIEUCH +U+BEB0(2);; # HANGUL SYLLABLE SSANGPIEUP YA KHIEUKH +U+BEB1(2);; # HANGUL SYLLABLE SSANGPIEUP YA THIEUTH +U+BEB2(2);; # HANGUL SYLLABLE SSANGPIEUP YA PHIEUPH +U+BEB3(2);; # HANGUL SYLLABLE SSANGPIEUP YA HIEUH +U+BEB4(2);; # HANGUL SYLLABLE SSANGPIEUP YAE +U+BEB5(2);; # HANGUL SYLLABLE SSANGPIEUP YAE KIYEOK +U+BEB6(2);; # HANGUL SYLLABLE SSANGPIEUP YAE SSANGKIYEOK +U+BEB7(2);; # HANGUL SYLLABLE SSANGPIEUP YAE KIYEOKSIOS +U+BEB8(2);; # HANGUL SYLLABLE SSANGPIEUP YAE NIEUN +U+BEB9(2);; # HANGUL SYLLABLE SSANGPIEUP YAE NIEUNCIEUC +U+BEBA(2);; # HANGUL SYLLABLE SSANGPIEUP YAE NIEUNHIEUH +U+BEBB(2);; # HANGUL SYLLABLE SSANGPIEUP YAE TIKEUT +U+BEBC(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEUL +U+BEBD(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULKIYEOK +U+BEBE(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULMIEUM +U+BEBF(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULPIEUP +U+BEC0(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULSIOS +U+BEC1(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULTHIEUTH +U+BEC2(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULPHIEUPH +U+BEC3(2);; # HANGUL SYLLABLE SSANGPIEUP YAE RIEULHIEUH +U+BEC4(2);; # HANGUL SYLLABLE SSANGPIEUP YAE MIEUM +U+BEC5(2);; # HANGUL SYLLABLE SSANGPIEUP YAE PIEUP +U+BEC6(2);; # HANGUL SYLLABLE SSANGPIEUP YAE PIEUPSIOS +U+BEC7(2);; # HANGUL SYLLABLE SSANGPIEUP YAE SIOS +U+BEC8(2);; # HANGUL SYLLABLE SSANGPIEUP YAE SSANGSIOS +U+BEC9(2);; # HANGUL SYLLABLE SSANGPIEUP YAE IEUNG +U+BECA(2);; # HANGUL SYLLABLE SSANGPIEUP YAE CIEUC +U+BECB(2);; # HANGUL SYLLABLE SSANGPIEUP YAE CHIEUCH +U+BECC(2);; # HANGUL SYLLABLE SSANGPIEUP YAE KHIEUKH +U+BECD(2);; # HANGUL SYLLABLE SSANGPIEUP YAE THIEUTH +U+BECE(2);; # HANGUL SYLLABLE SSANGPIEUP YAE PHIEUPH +U+BECF(2);; # HANGUL SYLLABLE SSANGPIEUP YAE HIEUH +U+BED0(2);; # HANGUL SYLLABLE SSANGPIEUP EO * +U+BED1(2);; # HANGUL SYLLABLE SSANGPIEUP EO KIYEOK * +U+BED2(2);; # HANGUL SYLLABLE SSANGPIEUP EO SSANGKIYEOK +U+BED3(2);; # HANGUL SYLLABLE SSANGPIEUP EO KIYEOKSIOS +U+BED4(2);; # HANGUL SYLLABLE SSANGPIEUP EO NIEUN * +U+BED5(2);; # HANGUL SYLLABLE SSANGPIEUP EO NIEUNCIEUC +U+BED6(2);; # HANGUL SYLLABLE SSANGPIEUP EO NIEUNHIEUH +U+BED7(2);; # HANGUL SYLLABLE SSANGPIEUP EO TIKEUT * +U+BED8(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEUL * +U+BED9(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULKIYEOK +U+BEDA(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULMIEUM +U+BEDB(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULPIEUP +U+BEDC(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULSIOS +U+BEDD(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULTHIEUTH +U+BEDE(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULPHIEUPH +U+BEDF(2);; # HANGUL SYLLABLE SSANGPIEUP EO RIEULHIEUH +U+BEE0(2);; # HANGUL SYLLABLE SSANGPIEUP EO MIEUM * +U+BEE1(2);; # HANGUL SYLLABLE SSANGPIEUP EO PIEUP +U+BEE2(2);; # HANGUL SYLLABLE SSANGPIEUP EO PIEUPSIOS +U+BEE3(2);; # HANGUL SYLLABLE SSANGPIEUP EO SIOS * +U+BEE4(2);; # HANGUL SYLLABLE SSANGPIEUP EO SSANGSIOS * +U+BEE5(2);; # HANGUL SYLLABLE SSANGPIEUP EO IEUNG * +U+BEE6(2);; # HANGUL SYLLABLE SSANGPIEUP EO CIEUC +U+BEE7(2);; # HANGUL SYLLABLE SSANGPIEUP EO CHIEUCH +U+BEE8(2);; # HANGUL SYLLABLE SSANGPIEUP EO KHIEUKH +U+BEE9(2);; # HANGUL SYLLABLE SSANGPIEUP EO THIEUTH +U+BEEA(2);; # HANGUL SYLLABLE SSANGPIEUP EO PHIEUPH +U+BEEB(2);; # HANGUL SYLLABLE SSANGPIEUP EO HIEUH +U+BEEC(2);; # HANGUL SYLLABLE SSANGPIEUP E * +U+BEED(2);; # HANGUL SYLLABLE SSANGPIEUP E KIYEOK +U+BEEE(2);; # HANGUL SYLLABLE SSANGPIEUP E SSANGKIYEOK +U+BEEF(2);; # HANGUL SYLLABLE SSANGPIEUP E KIYEOKSIOS +U+BEF0(2);; # HANGUL SYLLABLE SSANGPIEUP E NIEUN +U+BEF1(2);; # HANGUL SYLLABLE SSANGPIEUP E NIEUNCIEUC +U+BEF2(2);; # HANGUL SYLLABLE SSANGPIEUP E NIEUNHIEUH +U+BEF3(2);; # HANGUL SYLLABLE SSANGPIEUP E TIKEUT +U+BEF4(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEUL +U+BEF5(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULKIYEOK +U+BEF6(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULMIEUM +U+BEF7(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULPIEUP +U+BEF8(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULSIOS +U+BEF9(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULTHIEUTH +U+BEFA(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULPHIEUPH +U+BEFB(2);; # HANGUL SYLLABLE SSANGPIEUP E RIEULHIEUH +U+BEFC(2);; # HANGUL SYLLABLE SSANGPIEUP E MIEUM +U+BEFD(2);; # HANGUL SYLLABLE SSANGPIEUP E PIEUP +U+BEFE(2);; # HANGUL SYLLABLE SSANGPIEUP E PIEUPSIOS +U+BEFF(2);; # HANGUL SYLLABLE SSANGPIEUP E SIOS +U+BF00(2);; # HANGUL SYLLABLE SSANGPIEUP E SSANGSIOS +U+BF01(2);; # HANGUL SYLLABLE SSANGPIEUP E IEUNG * +U+BF02(2);; # HANGUL SYLLABLE SSANGPIEUP E CIEUC +U+BF03(2);; # HANGUL SYLLABLE SSANGPIEUP E CHIEUCH +U+BF04(2);; # HANGUL SYLLABLE SSANGPIEUP E KHIEUKH +U+BF05(2);; # HANGUL SYLLABLE SSANGPIEUP E THIEUTH +U+BF06(2);; # HANGUL SYLLABLE SSANGPIEUP E PHIEUPH +U+BF07(2);; # HANGUL SYLLABLE SSANGPIEUP E HIEUH +U+BF08(2);; # HANGUL SYLLABLE SSANGPIEUP YEO * +U+BF09(2);; # HANGUL SYLLABLE SSANGPIEUP YEO KIYEOK * +U+BF0A(2);; # HANGUL SYLLABLE SSANGPIEUP YEO SSANGKIYEOK +U+BF0B(2);; # HANGUL SYLLABLE SSANGPIEUP YEO KIYEOKSIOS +U+BF0C(2);; # HANGUL SYLLABLE SSANGPIEUP YEO NIEUN +U+BF0D(2);; # HANGUL SYLLABLE SSANGPIEUP YEO NIEUNCIEUC +U+BF0E(2);; # HANGUL SYLLABLE SSANGPIEUP YEO NIEUNHIEUH +U+BF0F(2);; # HANGUL SYLLABLE SSANGPIEUP YEO TIKEUT +U+BF10(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEUL +U+BF11(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULKIYEOK +U+BF12(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULMIEUM +U+BF13(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULPIEUP +U+BF14(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULSIOS +U+BF15(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULTHIEUTH +U+BF16(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULPHIEUPH +U+BF17(2);; # HANGUL SYLLABLE SSANGPIEUP YEO RIEULHIEUH +U+BF18(2);; # HANGUL SYLLABLE SSANGPIEUP YEO MIEUM * +U+BF19(2);; # HANGUL SYLLABLE SSANGPIEUP YEO PIEUP * +U+BF1A(2);; # HANGUL SYLLABLE SSANGPIEUP YEO PIEUPSIOS +U+BF1B(2);; # HANGUL SYLLABLE SSANGPIEUP YEO SIOS * +U+BF1C(2);; # HANGUL SYLLABLE SSANGPIEUP YEO SSANGSIOS * +U+BF1D(2);; # HANGUL SYLLABLE SSANGPIEUP YEO IEUNG * +U+BF1E(2);; # HANGUL SYLLABLE SSANGPIEUP YEO CIEUC +U+BF1F(2);; # HANGUL SYLLABLE SSANGPIEUP YEO CHIEUCH +U+BF20(2);; # HANGUL SYLLABLE SSANGPIEUP YEO KHIEUKH +U+BF21(2);; # HANGUL SYLLABLE SSANGPIEUP YEO THIEUTH +U+BF22(2);; # HANGUL SYLLABLE SSANGPIEUP YEO PHIEUPH +U+BF23(2);; # HANGUL SYLLABLE SSANGPIEUP YEO HIEUH +U+BF24(2);; # HANGUL SYLLABLE SSANGPIEUP YE +U+BF25(2);; # HANGUL SYLLABLE SSANGPIEUP YE KIYEOK +U+BF26(2);; # HANGUL SYLLABLE SSANGPIEUP YE SSANGKIYEOK +U+BF27(2);; # HANGUL SYLLABLE SSANGPIEUP YE KIYEOKSIOS +U+BF28(2);; # HANGUL SYLLABLE SSANGPIEUP YE NIEUN +U+BF29(2);; # HANGUL SYLLABLE SSANGPIEUP YE NIEUNCIEUC +U+BF2A(2);; # HANGUL SYLLABLE SSANGPIEUP YE NIEUNHIEUH +U+BF2B(2);; # HANGUL SYLLABLE SSANGPIEUP YE TIKEUT +U+BF2C(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEUL +U+BF2D(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULKIYEOK +U+BF2E(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULMIEUM +U+BF2F(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULPIEUP +U+BF30(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULSIOS +U+BF31(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULTHIEUTH +U+BF32(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULPHIEUPH +U+BF33(2);; # HANGUL SYLLABLE SSANGPIEUP YE RIEULHIEUH +U+BF34(2);; # HANGUL SYLLABLE SSANGPIEUP YE MIEUM +U+BF35(2);; # HANGUL SYLLABLE SSANGPIEUP YE PIEUP +U+BF36(2);; # HANGUL SYLLABLE SSANGPIEUP YE PIEUPSIOS +U+BF37(2);; # HANGUL SYLLABLE SSANGPIEUP YE SIOS +U+BF38(2);; # HANGUL SYLLABLE SSANGPIEUP YE SSANGSIOS +U+BF39(2);; # HANGUL SYLLABLE SSANGPIEUP YE IEUNG +U+BF3A(2);; # HANGUL SYLLABLE SSANGPIEUP YE CIEUC +U+BF3B(2);; # HANGUL SYLLABLE SSANGPIEUP YE CHIEUCH +U+BF3C(2);; # HANGUL SYLLABLE SSANGPIEUP YE KHIEUKH +U+BF3D(2);; # HANGUL SYLLABLE SSANGPIEUP YE THIEUTH +U+BF3E(2);; # HANGUL SYLLABLE SSANGPIEUP YE PHIEUPH +U+BF3F(2);; # HANGUL SYLLABLE SSANGPIEUP YE HIEUH +U+BF40(2);; # HANGUL SYLLABLE SSANGPIEUP O * +U+BF41(2);; # HANGUL SYLLABLE SSANGPIEUP O KIYEOK * +U+BF42(2);; # HANGUL SYLLABLE SSANGPIEUP O SSANGKIYEOK +U+BF43(2);; # HANGUL SYLLABLE SSANGPIEUP O KIYEOKSIOS +U+BF44(2);; # HANGUL SYLLABLE SSANGPIEUP O NIEUN * +U+BF45(2);; # HANGUL SYLLABLE SSANGPIEUP O NIEUNCIEUC +U+BF46(2);; # HANGUL SYLLABLE SSANGPIEUP O NIEUNHIEUH +U+BF47(2);; # HANGUL SYLLABLE SSANGPIEUP O TIKEUT +U+BF48(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEUL * +U+BF49(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULKIYEOK +U+BF4A(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULMIEUM +U+BF4B(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULPIEUP +U+BF4C(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULSIOS +U+BF4D(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULTHIEUTH +U+BF4E(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULPHIEUPH +U+BF4F(2);; # HANGUL SYLLABLE SSANGPIEUP O RIEULHIEUH +U+BF50(2);; # HANGUL SYLLABLE SSANGPIEUP O MIEUM * +U+BF51(2);; # HANGUL SYLLABLE SSANGPIEUP O PIEUP * +U+BF52(2);; # HANGUL SYLLABLE SSANGPIEUP O PIEUPSIOS +U+BF53(2);; # HANGUL SYLLABLE SSANGPIEUP O SIOS +U+BF54(2);; # HANGUL SYLLABLE SSANGPIEUP O SSANGSIOS +U+BF55(2);; # HANGUL SYLLABLE SSANGPIEUP O IEUNG * +U+BF56(2);; # HANGUL SYLLABLE SSANGPIEUP O CIEUC +U+BF57(2);; # HANGUL SYLLABLE SSANGPIEUP O CHIEUCH +U+BF58(2);; # HANGUL SYLLABLE SSANGPIEUP O KHIEUKH +U+BF59(2);; # HANGUL SYLLABLE SSANGPIEUP O THIEUTH +U+BF5A(2);; # HANGUL SYLLABLE SSANGPIEUP O PHIEUPH +U+BF5B(2);; # HANGUL SYLLABLE SSANGPIEUP O HIEUH +U+BF5C(2);; # HANGUL SYLLABLE SSANGPIEUP WA +U+BF5D(2);; # HANGUL SYLLABLE SSANGPIEUP WA KIYEOK +U+BF5E(2);; # HANGUL SYLLABLE SSANGPIEUP WA SSANGKIYEOK +U+BF5F(2);; # HANGUL SYLLABLE SSANGPIEUP WA KIYEOKSIOS +U+BF60(2);; # HANGUL SYLLABLE SSANGPIEUP WA NIEUN +U+BF61(2);; # HANGUL SYLLABLE SSANGPIEUP WA NIEUNCIEUC +U+BF62(2);; # HANGUL SYLLABLE SSANGPIEUP WA NIEUNHIEUH +U+BF63(2);; # HANGUL SYLLABLE SSANGPIEUP WA TIKEUT +U+BF64(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEUL +U+BF65(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULKIYEOK +U+BF66(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULMIEUM +U+BF67(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULPIEUP +U+BF68(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULSIOS +U+BF69(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULTHIEUTH +U+BF6A(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULPHIEUPH +U+BF6B(2);; # HANGUL SYLLABLE SSANGPIEUP WA RIEULHIEUH +U+BF6C(2);; # HANGUL SYLLABLE SSANGPIEUP WA MIEUM +U+BF6D(2);; # HANGUL SYLLABLE SSANGPIEUP WA PIEUP +U+BF6E(2);; # HANGUL SYLLABLE SSANGPIEUP WA PIEUPSIOS +U+BF6F(2);; # HANGUL SYLLABLE SSANGPIEUP WA SIOS +U+BF70(2);; # HANGUL SYLLABLE SSANGPIEUP WA SSANGSIOS +U+BF71(2);; # HANGUL SYLLABLE SSANGPIEUP WA IEUNG +U+BF72(2);; # HANGUL SYLLABLE SSANGPIEUP WA CIEUC +U+BF73(2);; # HANGUL SYLLABLE SSANGPIEUP WA CHIEUCH +U+BF74(2);; # HANGUL SYLLABLE SSANGPIEUP WA KHIEUKH +U+BF75(2);; # HANGUL SYLLABLE SSANGPIEUP WA THIEUTH +U+BF76(2);; # HANGUL SYLLABLE SSANGPIEUP WA PHIEUPH +U+BF77(2);; # HANGUL SYLLABLE SSANGPIEUP WA HIEUH +U+BF78(2);; # HANGUL SYLLABLE SSANGPIEUP WAE +U+BF79(2);; # HANGUL SYLLABLE SSANGPIEUP WAE KIYEOK +U+BF7A(2);; # HANGUL SYLLABLE SSANGPIEUP WAE SSANGKIYEOK +U+BF7B(2);; # HANGUL SYLLABLE SSANGPIEUP WAE KIYEOKSIOS +U+BF7C(2);; # HANGUL SYLLABLE SSANGPIEUP WAE NIEUN +U+BF7D(2);; # HANGUL SYLLABLE SSANGPIEUP WAE NIEUNCIEUC +U+BF7E(2);; # HANGUL SYLLABLE SSANGPIEUP WAE NIEUNHIEUH +U+BF7F(2);; # HANGUL SYLLABLE SSANGPIEUP WAE TIKEUT +U+BF80(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEUL +U+BF81(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULKIYEOK +U+BF82(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULMIEUM +U+BF83(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULPIEUP +U+BF84(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULSIOS +U+BF85(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULTHIEUTH +U+BF86(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULPHIEUPH +U+BF87(2);; # HANGUL SYLLABLE SSANGPIEUP WAE RIEULHIEUH +U+BF88(2);; # HANGUL SYLLABLE SSANGPIEUP WAE MIEUM +U+BF89(2);; # HANGUL SYLLABLE SSANGPIEUP WAE PIEUP +U+BF8A(2);; # HANGUL SYLLABLE SSANGPIEUP WAE PIEUPSIOS +U+BF8B(2);; # HANGUL SYLLABLE SSANGPIEUP WAE SIOS +U+BF8C(2);; # HANGUL SYLLABLE SSANGPIEUP WAE SSANGSIOS +U+BF8D(2);; # HANGUL SYLLABLE SSANGPIEUP WAE IEUNG +U+BF8E(2);; # HANGUL SYLLABLE SSANGPIEUP WAE CIEUC +U+BF8F(2);; # HANGUL SYLLABLE SSANGPIEUP WAE CHIEUCH +U+BF90(2);; # HANGUL SYLLABLE SSANGPIEUP WAE KHIEUKH +U+BF91(2);; # HANGUL SYLLABLE SSANGPIEUP WAE THIEUTH +U+BF92(2);; # HANGUL SYLLABLE SSANGPIEUP WAE PHIEUPH +U+BF93(2);; # HANGUL SYLLABLE SSANGPIEUP WAE HIEUH +U+BF94(2);; # HANGUL SYLLABLE SSANGPIEUP OE * +U+BF95(2);; # HANGUL SYLLABLE SSANGPIEUP OE KIYEOK +U+BF96(2);; # HANGUL SYLLABLE SSANGPIEUP OE SSANGKIYEOK +U+BF97(2);; # HANGUL SYLLABLE SSANGPIEUP OE KIYEOKSIOS +U+BF98(2);; # HANGUL SYLLABLE SSANGPIEUP OE NIEUN +U+BF99(2);; # HANGUL SYLLABLE SSANGPIEUP OE NIEUNCIEUC +U+BF9A(2);; # HANGUL SYLLABLE SSANGPIEUP OE NIEUNHIEUH +U+BF9B(2);; # HANGUL SYLLABLE SSANGPIEUP OE TIKEUT +U+BF9C(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEUL +U+BF9D(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULKIYEOK +U+BF9E(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULMIEUM +U+BF9F(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULPIEUP +U+BFA0(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULSIOS +U+BFA1(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULTHIEUTH +U+BFA2(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULPHIEUPH +U+BFA3(2);; # HANGUL SYLLABLE SSANGPIEUP OE RIEULHIEUH +U+BFA4(2);; # HANGUL SYLLABLE SSANGPIEUP OE MIEUM +U+BFA5(2);; # HANGUL SYLLABLE SSANGPIEUP OE PIEUP +U+BFA6(2);; # HANGUL SYLLABLE SSANGPIEUP OE PIEUPSIOS +U+BFA7(2);; # HANGUL SYLLABLE SSANGPIEUP OE SIOS +U+BFA8(2);; # HANGUL SYLLABLE SSANGPIEUP OE SSANGSIOS +U+BFA9(2);; # HANGUL SYLLABLE SSANGPIEUP OE IEUNG +U+BFAA(2);; # HANGUL SYLLABLE SSANGPIEUP OE CIEUC +U+BFAB(2);; # HANGUL SYLLABLE SSANGPIEUP OE CHIEUCH +U+BFAC(2);; # HANGUL SYLLABLE SSANGPIEUP OE KHIEUKH +U+BFAD(2);; # HANGUL SYLLABLE SSANGPIEUP OE THIEUTH +U+BFAE(2);; # HANGUL SYLLABLE SSANGPIEUP OE PHIEUPH +U+BFAF(2);; # HANGUL SYLLABLE SSANGPIEUP OE HIEUH +U+BFB0(2);; # HANGUL SYLLABLE SSANGPIEUP YO * +U+BFB1(2);; # HANGUL SYLLABLE SSANGPIEUP YO KIYEOK +U+BFB2(2);; # HANGUL SYLLABLE SSANGPIEUP YO SSANGKIYEOK +U+BFB3(2);; # HANGUL SYLLABLE SSANGPIEUP YO KIYEOKSIOS +U+BFB4(2);; # HANGUL SYLLABLE SSANGPIEUP YO NIEUN +U+BFB5(2);; # HANGUL SYLLABLE SSANGPIEUP YO NIEUNCIEUC +U+BFB6(2);; # HANGUL SYLLABLE SSANGPIEUP YO NIEUNHIEUH +U+BFB7(2);; # HANGUL SYLLABLE SSANGPIEUP YO TIKEUT +U+BFB8(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEUL +U+BFB9(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULKIYEOK +U+BFBA(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULMIEUM +U+BFBB(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULPIEUP +U+BFBC(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULSIOS +U+BFBD(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULTHIEUTH +U+BFBE(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULPHIEUPH +U+BFBF(2);; # HANGUL SYLLABLE SSANGPIEUP YO RIEULHIEUH +U+BFC0(2);; # HANGUL SYLLABLE SSANGPIEUP YO MIEUM +U+BFC1(2);; # HANGUL SYLLABLE SSANGPIEUP YO PIEUP +U+BFC2(2);; # HANGUL SYLLABLE SSANGPIEUP YO PIEUPSIOS +U+BFC3(2);; # HANGUL SYLLABLE SSANGPIEUP YO SIOS +U+BFC4(2);; # HANGUL SYLLABLE SSANGPIEUP YO SSANGSIOS +U+BFC5(2);; # HANGUL SYLLABLE SSANGPIEUP YO IEUNG * +U+BFC6(2);; # HANGUL SYLLABLE SSANGPIEUP YO CIEUC +U+BFC7(2);; # HANGUL SYLLABLE SSANGPIEUP YO CHIEUCH +U+BFC8(2);; # HANGUL SYLLABLE SSANGPIEUP YO KHIEUKH +U+BFC9(2);; # HANGUL SYLLABLE SSANGPIEUP YO THIEUTH +U+BFCA(2);; # HANGUL SYLLABLE SSANGPIEUP YO PHIEUPH +U+BFCB(2);; # HANGUL SYLLABLE SSANGPIEUP YO HIEUH +U+BFCC(2);; # HANGUL SYLLABLE SSANGPIEUP U * +U+BFCD(2);; # HANGUL SYLLABLE SSANGPIEUP U KIYEOK * +U+BFCE(2);; # HANGUL SYLLABLE SSANGPIEUP U SSANGKIYEOK +U+BFCF(2);; # HANGUL SYLLABLE SSANGPIEUP U KIYEOKSIOS +U+BFD0(2);; # HANGUL SYLLABLE SSANGPIEUP U NIEUN * +U+BFD1(2);; # HANGUL SYLLABLE SSANGPIEUP U NIEUNCIEUC +U+BFD2(2);; # HANGUL SYLLABLE SSANGPIEUP U NIEUNHIEUH +U+BFD3(2);; # HANGUL SYLLABLE SSANGPIEUP U TIKEUT +U+BFD4(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEUL * +U+BFD5(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULKIYEOK +U+BFD6(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULMIEUM +U+BFD7(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULPIEUP +U+BFD8(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULSIOS +U+BFD9(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULTHIEUTH +U+BFDA(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULPHIEUPH +U+BFDB(2);; # HANGUL SYLLABLE SSANGPIEUP U RIEULHIEUH +U+BFDC(2);; # HANGUL SYLLABLE SSANGPIEUP U MIEUM * +U+BFDD(2);; # HANGUL SYLLABLE SSANGPIEUP U PIEUP +U+BFDE(2);; # HANGUL SYLLABLE SSANGPIEUP U PIEUPSIOS +U+BFDF(2);; # HANGUL SYLLABLE SSANGPIEUP U SIOS * +U+BFE0(2);; # HANGUL SYLLABLE SSANGPIEUP U SSANGSIOS +U+BFE1(2);; # HANGUL SYLLABLE SSANGPIEUP U IEUNG * +U+BFE2(2);; # HANGUL SYLLABLE SSANGPIEUP U CIEUC +U+BFE3(2);; # HANGUL SYLLABLE SSANGPIEUP U CHIEUCH +U+BFE4(2);; # HANGUL SYLLABLE SSANGPIEUP U KHIEUKH +U+BFE5(2);; # HANGUL SYLLABLE SSANGPIEUP U THIEUTH +U+BFE6(2);; # HANGUL SYLLABLE SSANGPIEUP U PHIEUPH +U+BFE7(2);; # HANGUL SYLLABLE SSANGPIEUP U HIEUH +U+BFE8(2);; # HANGUL SYLLABLE SSANGPIEUP WEO +U+BFE9(2);; # HANGUL SYLLABLE SSANGPIEUP WEO KIYEOK +U+BFEA(2);; # HANGUL SYLLABLE SSANGPIEUP WEO SSANGKIYEOK +U+BFEB(2);; # HANGUL SYLLABLE SSANGPIEUP WEO KIYEOKSIOS +U+BFEC(2);; # HANGUL SYLLABLE SSANGPIEUP WEO NIEUN +U+BFED(2);; # HANGUL SYLLABLE SSANGPIEUP WEO NIEUNCIEUC +U+BFEE(2);; # HANGUL SYLLABLE SSANGPIEUP WEO NIEUNHIEUH +U+BFEF(2);; # HANGUL SYLLABLE SSANGPIEUP WEO TIKEUT +U+BFF0(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEUL +U+BFF1(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULKIYEOK +U+BFF2(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULMIEUM +U+BFF3(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULPIEUP +U+BFF4(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULSIOS +U+BFF5(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULTHIEUTH +U+BFF6(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULPHIEUPH +U+BFF7(2);; # HANGUL SYLLABLE SSANGPIEUP WEO RIEULHIEUH +U+BFF8(2);; # HANGUL SYLLABLE SSANGPIEUP WEO MIEUM +U+BFF9(2);; # HANGUL SYLLABLE SSANGPIEUP WEO PIEUP +U+BFFA(2);; # HANGUL SYLLABLE SSANGPIEUP WEO PIEUPSIOS +U+BFFB(2);; # HANGUL SYLLABLE SSANGPIEUP WEO SIOS +U+BFFC(2);; # HANGUL SYLLABLE SSANGPIEUP WEO SSANGSIOS +U+BFFD(2);; # HANGUL SYLLABLE SSANGPIEUP WEO IEUNG +U+BFFE(2);; # HANGUL SYLLABLE SSANGPIEUP WEO CIEUC +U+BFFF(2);; # HANGUL SYLLABLE SSANGPIEUP WEO CHIEUCH +U+C000(2);; # HANGUL SYLLABLE SSANGPIEUP WEO KHIEUKH +U+C001(2);; # HANGUL SYLLABLE SSANGPIEUP WEO THIEUTH +U+C002(2);; # HANGUL SYLLABLE SSANGPIEUP WEO PHIEUPH +U+C003(2);; # HANGUL SYLLABLE SSANGPIEUP WEO HIEUH +U+C004(2);; # HANGUL SYLLABLE SSANGPIEUP WE +U+C005(2);; # HANGUL SYLLABLE SSANGPIEUP WE KIYEOK +U+C006(2);; # HANGUL SYLLABLE SSANGPIEUP WE SSANGKIYEOK +U+C007(2);; # HANGUL SYLLABLE SSANGPIEUP WE KIYEOKSIOS +U+C008(2);; # HANGUL SYLLABLE SSANGPIEUP WE NIEUN +U+C009(2);; # HANGUL SYLLABLE SSANGPIEUP WE NIEUNCIEUC +U+C00A(2);; # HANGUL SYLLABLE SSANGPIEUP WE NIEUNHIEUH +U+C00B(2);; # HANGUL SYLLABLE SSANGPIEUP WE TIKEUT +U+C00C(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEUL +U+C00D(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULKIYEOK +U+C00E(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULMIEUM +U+C00F(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULPIEUP +U+C010(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULSIOS +U+C011(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULTHIEUTH +U+C012(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULPHIEUPH +U+C013(2);; # HANGUL SYLLABLE SSANGPIEUP WE RIEULHIEUH +U+C014(2);; # HANGUL SYLLABLE SSANGPIEUP WE MIEUM +U+C015(2);; # HANGUL SYLLABLE SSANGPIEUP WE PIEUP +U+C016(2);; # HANGUL SYLLABLE SSANGPIEUP WE PIEUPSIOS +U+C017(2);; # HANGUL SYLLABLE SSANGPIEUP WE SIOS +U+C018(2);; # HANGUL SYLLABLE SSANGPIEUP WE SSANGSIOS +U+C019(2);; # HANGUL SYLLABLE SSANGPIEUP WE IEUNG +U+C01A(2);; # HANGUL SYLLABLE SSANGPIEUP WE CIEUC +U+C01B(2);; # HANGUL SYLLABLE SSANGPIEUP WE CHIEUCH +U+C01C(2);; # HANGUL SYLLABLE SSANGPIEUP WE KHIEUKH +U+C01D(2);; # HANGUL SYLLABLE SSANGPIEUP WE THIEUTH +U+C01E(2);; # HANGUL SYLLABLE SSANGPIEUP WE PHIEUPH +U+C01F(2);; # HANGUL SYLLABLE SSANGPIEUP WE HIEUH +U+C020(2);; # HANGUL SYLLABLE SSANGPIEUP WI +U+C021(2);; # HANGUL SYLLABLE SSANGPIEUP WI KIYEOK +U+C022(2);; # HANGUL SYLLABLE SSANGPIEUP WI SSANGKIYEOK +U+C023(2);; # HANGUL SYLLABLE SSANGPIEUP WI KIYEOKSIOS +U+C024(2);; # HANGUL SYLLABLE SSANGPIEUP WI NIEUN +U+C025(2);; # HANGUL SYLLABLE SSANGPIEUP WI NIEUNCIEUC +U+C026(2);; # HANGUL SYLLABLE SSANGPIEUP WI NIEUNHIEUH +U+C027(2);; # HANGUL SYLLABLE SSANGPIEUP WI TIKEUT +U+C028(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEUL +U+C029(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULKIYEOK +U+C02A(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULMIEUM +U+C02B(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULPIEUP +U+C02C(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULSIOS +U+C02D(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULTHIEUTH +U+C02E(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULPHIEUPH +U+C02F(2);; # HANGUL SYLLABLE SSANGPIEUP WI RIEULHIEUH +U+C030(2);; # HANGUL SYLLABLE SSANGPIEUP WI MIEUM +U+C031(2);; # HANGUL SYLLABLE SSANGPIEUP WI PIEUP +U+C032(2);; # HANGUL SYLLABLE SSANGPIEUP WI PIEUPSIOS +U+C033(2);; # HANGUL SYLLABLE SSANGPIEUP WI SIOS +U+C034(2);; # HANGUL SYLLABLE SSANGPIEUP WI SSANGSIOS +U+C035(2);; # HANGUL SYLLABLE SSANGPIEUP WI IEUNG +U+C036(2);; # HANGUL SYLLABLE SSANGPIEUP WI CIEUC +U+C037(2);; # HANGUL SYLLABLE SSANGPIEUP WI CHIEUCH +U+C038(2);; # HANGUL SYLLABLE SSANGPIEUP WI KHIEUKH +U+C039(2);; # HANGUL SYLLABLE SSANGPIEUP WI THIEUTH +U+C03A(2);; # HANGUL SYLLABLE SSANGPIEUP WI PHIEUPH +U+C03B(2);; # HANGUL SYLLABLE SSANGPIEUP WI HIEUH +U+C03C(2);; # HANGUL SYLLABLE SSANGPIEUP YU * +U+C03D(2);; # HANGUL SYLLABLE SSANGPIEUP YU KIYEOK +U+C03E(2);; # HANGUL SYLLABLE SSANGPIEUP YU SSANGKIYEOK +U+C03F(2);; # HANGUL SYLLABLE SSANGPIEUP YU KIYEOKSIOS +U+C040(2);; # HANGUL SYLLABLE SSANGPIEUP YU NIEUN +U+C041(2);; # HANGUL SYLLABLE SSANGPIEUP YU NIEUNCIEUC +U+C042(2);; # HANGUL SYLLABLE SSANGPIEUP YU NIEUNHIEUH +U+C043(2);; # HANGUL SYLLABLE SSANGPIEUP YU TIKEUT +U+C044(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEUL +U+C045(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULKIYEOK +U+C046(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULMIEUM +U+C047(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULPIEUP +U+C048(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULSIOS +U+C049(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULTHIEUTH +U+C04A(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULPHIEUPH +U+C04B(2);; # HANGUL SYLLABLE SSANGPIEUP YU RIEULHIEUH +U+C04C(2);; # HANGUL SYLLABLE SSANGPIEUP YU MIEUM +U+C04D(2);; # HANGUL SYLLABLE SSANGPIEUP YU PIEUP +U+C04E(2);; # HANGUL SYLLABLE SSANGPIEUP YU PIEUPSIOS +U+C04F(2);; # HANGUL SYLLABLE SSANGPIEUP YU SIOS +U+C050(2);; # HANGUL SYLLABLE SSANGPIEUP YU SSANGSIOS +U+C051(2);; # HANGUL SYLLABLE SSANGPIEUP YU IEUNG * +U+C052(2);; # HANGUL SYLLABLE SSANGPIEUP YU CIEUC +U+C053(2);; # HANGUL SYLLABLE SSANGPIEUP YU CHIEUCH +U+C054(2);; # HANGUL SYLLABLE SSANGPIEUP YU KHIEUKH +U+C055(2);; # HANGUL SYLLABLE SSANGPIEUP YU THIEUTH +U+C056(2);; # HANGUL SYLLABLE SSANGPIEUP YU PHIEUPH +U+C057(2);; # HANGUL SYLLABLE SSANGPIEUP YU HIEUH +U+C058(2);; # HANGUL SYLLABLE SSANGPIEUP EU * +U+C059(2);; # HANGUL SYLLABLE SSANGPIEUP EU KIYEOK +U+C05A(2);; # HANGUL SYLLABLE SSANGPIEUP EU SSANGKIYEOK +U+C05B(2);; # HANGUL SYLLABLE SSANGPIEUP EU KIYEOKSIOS +U+C05C(2);; # HANGUL SYLLABLE SSANGPIEUP EU NIEUN * +U+C05D(2);; # HANGUL SYLLABLE SSANGPIEUP EU NIEUNCIEUC +U+C05E(2);; # HANGUL SYLLABLE SSANGPIEUP EU NIEUNHIEUH +U+C05F(2);; # HANGUL SYLLABLE SSANGPIEUP EU TIKEUT +U+C060(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEUL * +U+C061(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULKIYEOK +U+C062(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULMIEUM +U+C063(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULPIEUP +U+C064(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULSIOS +U+C065(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULTHIEUTH +U+C066(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULPHIEUPH +U+C067(2);; # HANGUL SYLLABLE SSANGPIEUP EU RIEULHIEUH +U+C068(2);; # HANGUL SYLLABLE SSANGPIEUP EU MIEUM * +U+C069(2);; # HANGUL SYLLABLE SSANGPIEUP EU PIEUP * +U+C06A(2);; # HANGUL SYLLABLE SSANGPIEUP EU PIEUPSIOS +U+C06B(2);; # HANGUL SYLLABLE SSANGPIEUP EU SIOS +U+C06C(2);; # HANGUL SYLLABLE SSANGPIEUP EU SSANGSIOS +U+C06D(2);; # HANGUL SYLLABLE SSANGPIEUP EU IEUNG +U+C06E(2);; # HANGUL SYLLABLE SSANGPIEUP EU CIEUC +U+C06F(2);; # HANGUL SYLLABLE SSANGPIEUP EU CHIEUCH +U+C070(2);; # HANGUL SYLLABLE SSANGPIEUP EU KHIEUKH +U+C071(2);; # HANGUL SYLLABLE SSANGPIEUP EU THIEUTH +U+C072(2);; # HANGUL SYLLABLE SSANGPIEUP EU PHIEUPH +U+C073(2);; # HANGUL SYLLABLE SSANGPIEUP EU HIEUH +U+C074(2);; # HANGUL SYLLABLE SSANGPIEUP YI +U+C075(2);; # HANGUL SYLLABLE SSANGPIEUP YI KIYEOK +U+C076(2);; # HANGUL SYLLABLE SSANGPIEUP YI SSANGKIYEOK +U+C077(2);; # HANGUL SYLLABLE SSANGPIEUP YI KIYEOKSIOS +U+C078(2);; # HANGUL SYLLABLE SSANGPIEUP YI NIEUN +U+C079(2);; # HANGUL SYLLABLE SSANGPIEUP YI NIEUNCIEUC +U+C07A(2);; # HANGUL SYLLABLE SSANGPIEUP YI NIEUNHIEUH +U+C07B(2);; # HANGUL SYLLABLE SSANGPIEUP YI TIKEUT +U+C07C(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEUL +U+C07D(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULKIYEOK +U+C07E(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULMIEUM +U+C07F(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULPIEUP +U+C080(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULSIOS +U+C081(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULTHIEUTH +U+C082(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULPHIEUPH +U+C083(2);; # HANGUL SYLLABLE SSANGPIEUP YI RIEULHIEUH +U+C084(2);; # HANGUL SYLLABLE SSANGPIEUP YI MIEUM +U+C085(2);; # HANGUL SYLLABLE SSANGPIEUP YI PIEUP +U+C086(2);; # HANGUL SYLLABLE SSANGPIEUP YI PIEUPSIOS +U+C087(2);; # HANGUL SYLLABLE SSANGPIEUP YI SIOS +U+C088(2);; # HANGUL SYLLABLE SSANGPIEUP YI SSANGSIOS +U+C089(2);; # HANGUL SYLLABLE SSANGPIEUP YI IEUNG +U+C08A(2);; # HANGUL SYLLABLE SSANGPIEUP YI CIEUC +U+C08B(2);; # HANGUL SYLLABLE SSANGPIEUP YI CHIEUCH +U+C08C(2);; # HANGUL SYLLABLE SSANGPIEUP YI KHIEUKH +U+C08D(2);; # HANGUL SYLLABLE SSANGPIEUP YI THIEUTH +U+C08E(2);; # HANGUL SYLLABLE SSANGPIEUP YI PHIEUPH +U+C08F(2);; # HANGUL SYLLABLE SSANGPIEUP YI HIEUH +U+C090(2);; # HANGUL SYLLABLE SSANGPIEUP I * +U+C091(2);; # HANGUL SYLLABLE SSANGPIEUP I KIYEOK * +U+C092(2);; # HANGUL SYLLABLE SSANGPIEUP I SSANGKIYEOK +U+C093(2);; # HANGUL SYLLABLE SSANGPIEUP I KIYEOKSIOS +U+C094(2);; # HANGUL SYLLABLE SSANGPIEUP I NIEUN * +U+C095(2);; # HANGUL SYLLABLE SSANGPIEUP I NIEUNCIEUC +U+C096(2);; # HANGUL SYLLABLE SSANGPIEUP I NIEUNHIEUH +U+C097(2);; # HANGUL SYLLABLE SSANGPIEUP I TIKEUT +U+C098(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEUL * +U+C099(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULKIYEOK +U+C09A(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULMIEUM +U+C09B(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULPIEUP +U+C09C(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULSIOS +U+C09D(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULTHIEUTH +U+C09E(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULPHIEUPH +U+C09F(2);; # HANGUL SYLLABLE SSANGPIEUP I RIEULHIEUH +U+C0A0(2);; # HANGUL SYLLABLE SSANGPIEUP I MIEUM * +U+C0A1(2);; # HANGUL SYLLABLE SSANGPIEUP I PIEUP * +U+C0A2(2);; # HANGUL SYLLABLE SSANGPIEUP I PIEUPSIOS +U+C0A3(2);; # HANGUL SYLLABLE SSANGPIEUP I SIOS * +U+C0A4(2);; # HANGUL SYLLABLE SSANGPIEUP I SSANGSIOS +U+C0A5(2);; # HANGUL SYLLABLE SSANGPIEUP I IEUNG * +U+C0A6(2);; # HANGUL SYLLABLE SSANGPIEUP I CIEUC +U+C0A7(2);; # HANGUL SYLLABLE SSANGPIEUP I CHIEUCH +U+C0A8(2);; # HANGUL SYLLABLE SSANGPIEUP I KHIEUKH +U+C0A9(2);; # HANGUL SYLLABLE SSANGPIEUP I THIEUTH +U+C0AA(2);; # HANGUL SYLLABLE SSANGPIEUP I PHIEUPH +U+C0AB(2);; # HANGUL SYLLABLE SSANGPIEUP I HIEUH +U+C0AC(2);; # HANGUL SYLLABLE SIOS A * +U+C0AD(2);; # HANGUL SYLLABLE SIOS A KIYEOK * +U+C0AE(2);; # HANGUL SYLLABLE SIOS A SSANGKIYEOK +U+C0AF(2);; # HANGUL SYLLABLE SIOS A KIYEOKSIOS * +U+C0B0(2);; # HANGUL SYLLABLE SIOS A NIEUN * +U+C0B1(2);; # HANGUL SYLLABLE SIOS A NIEUNCIEUC +U+C0B2(2);; # HANGUL SYLLABLE SIOS A NIEUNHIEUH +U+C0B3(2);; # HANGUL SYLLABLE SIOS A TIKEUT * +U+C0B4(2);; # HANGUL SYLLABLE SIOS A RIEUL * +U+C0B5(2);; # HANGUL SYLLABLE SIOS A RIEULKIYEOK * +U+C0B6(2);; # HANGUL SYLLABLE SIOS A RIEULMIEUM * +U+C0B7(2);; # HANGUL SYLLABLE SIOS A RIEULPIEUP +U+C0B8(2);; # HANGUL SYLLABLE SIOS A RIEULSIOS +U+C0B9(2);; # HANGUL SYLLABLE SIOS A RIEULTHIEUTH +U+C0BA(2);; # HANGUL SYLLABLE SIOS A RIEULPHIEUPH +U+C0BB(2);; # HANGUL SYLLABLE SIOS A RIEULHIEUH +U+C0BC(2);; # HANGUL SYLLABLE SIOS A MIEUM * +U+C0BD(2);; # HANGUL SYLLABLE SIOS A PIEUP * +U+C0BE(2);; # HANGUL SYLLABLE SIOS A PIEUPSIOS +U+C0BF(2);; # HANGUL SYLLABLE SIOS A SIOS * +U+C0C0(2);; # HANGUL SYLLABLE SIOS A SSANGSIOS * +U+C0C1(2);; # HANGUL SYLLABLE SIOS A IEUNG * +U+C0C2(2);; # HANGUL SYLLABLE SIOS A CIEUC +U+C0C3(2);; # HANGUL SYLLABLE SIOS A CHIEUCH +U+C0C4(2);; # HANGUL SYLLABLE SIOS A KHIEUKH +U+C0C5(2);; # HANGUL SYLLABLE SIOS A THIEUTH * +U+C0C6(2);; # HANGUL SYLLABLE SIOS A PHIEUPH +U+C0C7(2);; # HANGUL SYLLABLE SIOS A HIEUH +U+C0C8(2);; # HANGUL SYLLABLE SIOS AE * +U+C0C9(2);; # HANGUL SYLLABLE SIOS AE KIYEOK * +U+C0CA(2);; # HANGUL SYLLABLE SIOS AE SSANGKIYEOK +U+C0CB(2);; # HANGUL SYLLABLE SIOS AE KIYEOKSIOS +U+C0CC(2);; # HANGUL SYLLABLE SIOS AE NIEUN * +U+C0CD(2);; # HANGUL SYLLABLE SIOS AE NIEUNCIEUC +U+C0CE(2);; # HANGUL SYLLABLE SIOS AE NIEUNHIEUH +U+C0CF(2);; # HANGUL SYLLABLE SIOS AE TIKEUT +U+C0D0(2);; # HANGUL SYLLABLE SIOS AE RIEUL * +U+C0D1(2);; # HANGUL SYLLABLE SIOS AE RIEULKIYEOK +U+C0D2(2);; # HANGUL SYLLABLE SIOS AE RIEULMIEUM +U+C0D3(2);; # HANGUL SYLLABLE SIOS AE RIEULPIEUP +U+C0D4(2);; # HANGUL SYLLABLE SIOS AE RIEULSIOS +U+C0D5(2);; # HANGUL SYLLABLE SIOS AE RIEULTHIEUTH +U+C0D6(2);; # HANGUL SYLLABLE SIOS AE RIEULPHIEUPH +U+C0D7(2);; # HANGUL SYLLABLE SIOS AE RIEULHIEUH +U+C0D8(2);; # HANGUL SYLLABLE SIOS AE MIEUM * +U+C0D9(2);; # HANGUL SYLLABLE SIOS AE PIEUP * +U+C0DA(2);; # HANGUL SYLLABLE SIOS AE PIEUPSIOS +U+C0DB(2);; # HANGUL SYLLABLE SIOS AE SIOS * +U+C0DC(2);; # HANGUL SYLLABLE SIOS AE SSANGSIOS * +U+C0DD(2);; # HANGUL SYLLABLE SIOS AE IEUNG * +U+C0DE(2);; # HANGUL SYLLABLE SIOS AE CIEUC +U+C0DF(2);; # HANGUL SYLLABLE SIOS AE CHIEUCH +U+C0E0(2);; # HANGUL SYLLABLE SIOS AE KHIEUKH +U+C0E1(2);; # HANGUL SYLLABLE SIOS AE THIEUTH +U+C0E2(2);; # HANGUL SYLLABLE SIOS AE PHIEUPH +U+C0E3(2);; # HANGUL SYLLABLE SIOS AE HIEUH +U+C0E4(2);; # HANGUL SYLLABLE SIOS YA * +U+C0E5(2);; # HANGUL SYLLABLE SIOS YA KIYEOK * +U+C0E6(2);; # HANGUL SYLLABLE SIOS YA SSANGKIYEOK +U+C0E7(2);; # HANGUL SYLLABLE SIOS YA KIYEOKSIOS +U+C0E8(2);; # HANGUL SYLLABLE SIOS YA NIEUN * +U+C0E9(2);; # HANGUL SYLLABLE SIOS YA NIEUNCIEUC +U+C0EA(2);; # HANGUL SYLLABLE SIOS YA NIEUNHIEUH +U+C0EB(2);; # HANGUL SYLLABLE SIOS YA TIKEUT +U+C0EC(2);; # HANGUL SYLLABLE SIOS YA RIEUL * +U+C0ED(2);; # HANGUL SYLLABLE SIOS YA RIEULKIYEOK +U+C0EE(2);; # HANGUL SYLLABLE SIOS YA RIEULMIEUM +U+C0EF(2);; # HANGUL SYLLABLE SIOS YA RIEULPIEUP +U+C0F0(2);; # HANGUL SYLLABLE SIOS YA RIEULSIOS +U+C0F1(2);; # HANGUL SYLLABLE SIOS YA RIEULTHIEUTH +U+C0F2(2);; # HANGUL SYLLABLE SIOS YA RIEULPHIEUPH +U+C0F3(2);; # HANGUL SYLLABLE SIOS YA RIEULHIEUH +U+C0F4(2);; # HANGUL SYLLABLE SIOS YA MIEUM * +U+C0F5(2);; # HANGUL SYLLABLE SIOS YA PIEUP * +U+C0F6(2);; # HANGUL SYLLABLE SIOS YA PIEUPSIOS +U+C0F7(2);; # HANGUL SYLLABLE SIOS YA SIOS * +U+C0F8(2);; # HANGUL SYLLABLE SIOS YA SSANGSIOS +U+C0F9(2);; # HANGUL SYLLABLE SIOS YA IEUNG * +U+C0FA(2);; # HANGUL SYLLABLE SIOS YA CIEUC +U+C0FB(2);; # HANGUL SYLLABLE SIOS YA CHIEUCH +U+C0FC(2);; # HANGUL SYLLABLE SIOS YA KHIEUKH +U+C0FD(2);; # HANGUL SYLLABLE SIOS YA THIEUTH +U+C0FE(2);; # HANGUL SYLLABLE SIOS YA PHIEUPH +U+C0FF(2);; # HANGUL SYLLABLE SIOS YA HIEUH +U+C100(2);; # HANGUL SYLLABLE SIOS YAE * +U+C101(2);; # HANGUL SYLLABLE SIOS YAE KIYEOK +U+C102(2);; # HANGUL SYLLABLE SIOS YAE SSANGKIYEOK +U+C103(2);; # HANGUL SYLLABLE SIOS YAE KIYEOKSIOS +U+C104(2);; # HANGUL SYLLABLE SIOS YAE NIEUN * +U+C105(2);; # HANGUL SYLLABLE SIOS YAE NIEUNCIEUC +U+C106(2);; # HANGUL SYLLABLE SIOS YAE NIEUNHIEUH +U+C107(2);; # HANGUL SYLLABLE SIOS YAE TIKEUT +U+C108(2);; # HANGUL SYLLABLE SIOS YAE RIEUL * +U+C109(2);; # HANGUL SYLLABLE SIOS YAE RIEULKIYEOK +U+C10A(2);; # HANGUL SYLLABLE SIOS YAE RIEULMIEUM +U+C10B(2);; # HANGUL SYLLABLE SIOS YAE RIEULPIEUP +U+C10C(2);; # HANGUL SYLLABLE SIOS YAE RIEULSIOS +U+C10D(2);; # HANGUL SYLLABLE SIOS YAE RIEULTHIEUTH +U+C10E(2);; # HANGUL SYLLABLE SIOS YAE RIEULPHIEUPH +U+C10F(2);; # HANGUL SYLLABLE SIOS YAE RIEULHIEUH +U+C110(2);; # HANGUL SYLLABLE SIOS YAE MIEUM * +U+C111(2);; # HANGUL SYLLABLE SIOS YAE PIEUP +U+C112(2);; # HANGUL SYLLABLE SIOS YAE PIEUPSIOS +U+C113(2);; # HANGUL SYLLABLE SIOS YAE SIOS +U+C114(2);; # HANGUL SYLLABLE SIOS YAE SSANGSIOS +U+C115(2);; # HANGUL SYLLABLE SIOS YAE IEUNG * +U+C116(2);; # HANGUL SYLLABLE SIOS YAE CIEUC +U+C117(2);; # HANGUL SYLLABLE SIOS YAE CHIEUCH +U+C118(2);; # HANGUL SYLLABLE SIOS YAE KHIEUKH +U+C119(2);; # HANGUL SYLLABLE SIOS YAE THIEUTH +U+C11A(2);; # HANGUL SYLLABLE SIOS YAE PHIEUPH +U+C11B(2);; # HANGUL SYLLABLE SIOS YAE HIEUH +U+C11C(2);; # HANGUL SYLLABLE SIOS EO * +U+C11D(2);; # HANGUL SYLLABLE SIOS EO KIYEOK * +U+C11E(2);; # HANGUL SYLLABLE SIOS EO SSANGKIYEOK * +U+C11F(2);; # HANGUL SYLLABLE SIOS EO KIYEOKSIOS * +U+C120(2);; # HANGUL SYLLABLE SIOS EO NIEUN * +U+C121(2);; # HANGUL SYLLABLE SIOS EO NIEUNCIEUC +U+C122(2);; # HANGUL SYLLABLE SIOS EO NIEUNHIEUH +U+C123(2);; # HANGUL SYLLABLE SIOS EO TIKEUT * +U+C124(2);; # HANGUL SYLLABLE SIOS EO RIEUL * +U+C125(2);; # HANGUL SYLLABLE SIOS EO RIEULKIYEOK +U+C126(2);; # HANGUL SYLLABLE SIOS EO RIEULMIEUM * +U+C127(2);; # HANGUL SYLLABLE SIOS EO RIEULPIEUP * +U+C128(2);; # HANGUL SYLLABLE SIOS EO RIEULSIOS +U+C129(2);; # HANGUL SYLLABLE SIOS EO RIEULTHIEUTH +U+C12A(2);; # HANGUL SYLLABLE SIOS EO RIEULPHIEUPH +U+C12B(2);; # HANGUL SYLLABLE SIOS EO RIEULHIEUH +U+C12C(2);; # HANGUL SYLLABLE SIOS EO MIEUM * +U+C12D(2);; # HANGUL SYLLABLE SIOS EO PIEUP * +U+C12E(2);; # HANGUL SYLLABLE SIOS EO PIEUPSIOS +U+C12F(2);; # HANGUL SYLLABLE SIOS EO SIOS * +U+C130(2);; # HANGUL SYLLABLE SIOS EO SSANGSIOS * +U+C131(2);; # HANGUL SYLLABLE SIOS EO IEUNG * +U+C132(2);; # HANGUL SYLLABLE SIOS EO CIEUC +U+C133(2);; # HANGUL SYLLABLE SIOS EO CHIEUCH +U+C134(2);; # HANGUL SYLLABLE SIOS EO KHIEUKH +U+C135(2);; # HANGUL SYLLABLE SIOS EO THIEUTH +U+C136(2);; # HANGUL SYLLABLE SIOS EO PHIEUPH * +U+C137(2);; # HANGUL SYLLABLE SIOS EO HIEUH +U+C138(2);; # HANGUL SYLLABLE SIOS E * +U+C139(2);; # HANGUL SYLLABLE SIOS E KIYEOK * +U+C13A(2);; # HANGUL SYLLABLE SIOS E SSANGKIYEOK +U+C13B(2);; # HANGUL SYLLABLE SIOS E KIYEOKSIOS +U+C13C(2);; # HANGUL SYLLABLE SIOS E NIEUN * +U+C13D(2);; # HANGUL SYLLABLE SIOS E NIEUNCIEUC +U+C13E(2);; # HANGUL SYLLABLE SIOS E NIEUNHIEUH +U+C13F(2);; # HANGUL SYLLABLE SIOS E TIKEUT +U+C140(2);; # HANGUL SYLLABLE SIOS E RIEUL * +U+C141(2);; # HANGUL SYLLABLE SIOS E RIEULKIYEOK +U+C142(2);; # HANGUL SYLLABLE SIOS E RIEULMIEUM +U+C143(2);; # HANGUL SYLLABLE SIOS E RIEULPIEUP +U+C144(2);; # HANGUL SYLLABLE SIOS E RIEULSIOS +U+C145(2);; # HANGUL SYLLABLE SIOS E RIEULTHIEUTH +U+C146(2);; # HANGUL SYLLABLE SIOS E RIEULPHIEUPH +U+C147(2);; # HANGUL SYLLABLE SIOS E RIEULHIEUH +U+C148(2);; # HANGUL SYLLABLE SIOS E MIEUM * +U+C149(2);; # HANGUL SYLLABLE SIOS E PIEUP * +U+C14A(2);; # HANGUL SYLLABLE SIOS E PIEUPSIOS +U+C14B(2);; # HANGUL SYLLABLE SIOS E SIOS * +U+C14C(2);; # HANGUL SYLLABLE SIOS E SSANGSIOS * +U+C14D(2);; # HANGUL SYLLABLE SIOS E IEUNG * +U+C14E(2);; # HANGUL SYLLABLE SIOS E CIEUC +U+C14F(2);; # HANGUL SYLLABLE SIOS E CHIEUCH +U+C150(2);; # HANGUL SYLLABLE SIOS E KHIEUKH +U+C151(2);; # HANGUL SYLLABLE SIOS E THIEUTH +U+C152(2);; # HANGUL SYLLABLE SIOS E PHIEUPH +U+C153(2);; # HANGUL SYLLABLE SIOS E HIEUH +U+C154(2);; # HANGUL SYLLABLE SIOS YEO * +U+C155(2);; # HANGUL SYLLABLE SIOS YEO KIYEOK * +U+C156(2);; # HANGUL SYLLABLE SIOS YEO SSANGKIYEOK +U+C157(2);; # HANGUL SYLLABLE SIOS YEO KIYEOKSIOS +U+C158(2);; # HANGUL SYLLABLE SIOS YEO NIEUN * +U+C159(2);; # HANGUL SYLLABLE SIOS YEO NIEUNCIEUC +U+C15A(2);; # HANGUL SYLLABLE SIOS YEO NIEUNHIEUH +U+C15B(2);; # HANGUL SYLLABLE SIOS YEO TIKEUT +U+C15C(2);; # HANGUL SYLLABLE SIOS YEO RIEUL * +U+C15D(2);; # HANGUL SYLLABLE SIOS YEO RIEULKIYEOK +U+C15E(2);; # HANGUL SYLLABLE SIOS YEO RIEULMIEUM +U+C15F(2);; # HANGUL SYLLABLE SIOS YEO RIEULPIEUP +U+C160(2);; # HANGUL SYLLABLE SIOS YEO RIEULSIOS +U+C161(2);; # HANGUL SYLLABLE SIOS YEO RIEULTHIEUTH +U+C162(2);; # HANGUL SYLLABLE SIOS YEO RIEULPHIEUPH +U+C163(2);; # HANGUL SYLLABLE SIOS YEO RIEULHIEUH +U+C164(2);; # HANGUL SYLLABLE SIOS YEO MIEUM * +U+C165(2);; # HANGUL SYLLABLE SIOS YEO PIEUP * +U+C166(2);; # HANGUL SYLLABLE SIOS YEO PIEUPSIOS +U+C167(2);; # HANGUL SYLLABLE SIOS YEO SIOS * +U+C168(2);; # HANGUL SYLLABLE SIOS YEO SSANGSIOS * +U+C169(2);; # HANGUL SYLLABLE SIOS YEO IEUNG * +U+C16A(2);; # HANGUL SYLLABLE SIOS YEO CIEUC +U+C16B(2);; # HANGUL SYLLABLE SIOS YEO CHIEUCH +U+C16C(2);; # HANGUL SYLLABLE SIOS YEO KHIEUKH +U+C16D(2);; # HANGUL SYLLABLE SIOS YEO THIEUTH +U+C16E(2);; # HANGUL SYLLABLE SIOS YEO PHIEUPH +U+C16F(2);; # HANGUL SYLLABLE SIOS YEO HIEUH +U+C170(2);; # HANGUL SYLLABLE SIOS YE * +U+C171(2);; # HANGUL SYLLABLE SIOS YE KIYEOK +U+C172(2);; # HANGUL SYLLABLE SIOS YE SSANGKIYEOK +U+C173(2);; # HANGUL SYLLABLE SIOS YE KIYEOKSIOS +U+C174(2);; # HANGUL SYLLABLE SIOS YE NIEUN * +U+C175(2);; # HANGUL SYLLABLE SIOS YE NIEUNCIEUC +U+C176(2);; # HANGUL SYLLABLE SIOS YE NIEUNHIEUH +U+C177(2);; # HANGUL SYLLABLE SIOS YE TIKEUT +U+C178(2);; # HANGUL SYLLABLE SIOS YE RIEUL * +U+C179(2);; # HANGUL SYLLABLE SIOS YE RIEULKIYEOK +U+C17A(2);; # HANGUL SYLLABLE SIOS YE RIEULMIEUM +U+C17B(2);; # HANGUL SYLLABLE SIOS YE RIEULPIEUP +U+C17C(2);; # HANGUL SYLLABLE SIOS YE RIEULSIOS +U+C17D(2);; # HANGUL SYLLABLE SIOS YE RIEULTHIEUTH +U+C17E(2);; # HANGUL SYLLABLE SIOS YE RIEULPHIEUPH +U+C17F(2);; # HANGUL SYLLABLE SIOS YE RIEULHIEUH +U+C180(2);; # HANGUL SYLLABLE SIOS YE MIEUM +U+C181(2);; # HANGUL SYLLABLE SIOS YE PIEUP +U+C182(2);; # HANGUL SYLLABLE SIOS YE PIEUPSIOS +U+C183(2);; # HANGUL SYLLABLE SIOS YE SIOS +U+C184(2);; # HANGUL SYLLABLE SIOS YE SSANGSIOS +U+C185(2);; # HANGUL SYLLABLE SIOS YE IEUNG * +U+C186(2);; # HANGUL SYLLABLE SIOS YE CIEUC +U+C187(2);; # HANGUL SYLLABLE SIOS YE CHIEUCH +U+C188(2);; # HANGUL SYLLABLE SIOS YE KHIEUKH +U+C189(2);; # HANGUL SYLLABLE SIOS YE THIEUTH +U+C18A(2);; # HANGUL SYLLABLE SIOS YE PHIEUPH +U+C18B(2);; # HANGUL SYLLABLE SIOS YE HIEUH +U+C18C(2);; # HANGUL SYLLABLE SIOS O * +U+C18D(2);; # HANGUL SYLLABLE SIOS O KIYEOK * +U+C18E(2);; # HANGUL SYLLABLE SIOS O SSANGKIYEOK * +U+C18F(2);; # HANGUL SYLLABLE SIOS O KIYEOKSIOS +U+C190(2);; # HANGUL SYLLABLE SIOS O NIEUN * +U+C191(2);; # HANGUL SYLLABLE SIOS O NIEUNCIEUC +U+C192(2);; # HANGUL SYLLABLE SIOS O NIEUNHIEUH +U+C193(2);; # HANGUL SYLLABLE SIOS O TIKEUT +U+C194(2);; # HANGUL SYLLABLE SIOS O RIEUL * +U+C195(2);; # HANGUL SYLLABLE SIOS O RIEULKIYEOK +U+C196(2);; # HANGUL SYLLABLE SIOS O RIEULMIEUM * +U+C197(2);; # HANGUL SYLLABLE SIOS O RIEULPIEUP +U+C198(2);; # HANGUL SYLLABLE SIOS O RIEULSIOS +U+C199(2);; # HANGUL SYLLABLE SIOS O RIEULTHIEUTH +U+C19A(2);; # HANGUL SYLLABLE SIOS O RIEULPHIEUPH +U+C19B(2);; # HANGUL SYLLABLE SIOS O RIEULHIEUH +U+C19C(2);; # HANGUL SYLLABLE SIOS O MIEUM * +U+C19D(2);; # HANGUL SYLLABLE SIOS O PIEUP * +U+C19E(2);; # HANGUL SYLLABLE SIOS O PIEUPSIOS +U+C19F(2);; # HANGUL SYLLABLE SIOS O SIOS * +U+C1A0(2);; # HANGUL SYLLABLE SIOS O SSANGSIOS +U+C1A1(2);; # HANGUL SYLLABLE SIOS O IEUNG * +U+C1A2(2);; # HANGUL SYLLABLE SIOS O CIEUC +U+C1A3(2);; # HANGUL SYLLABLE SIOS O CHIEUCH +U+C1A4(2);; # HANGUL SYLLABLE SIOS O KHIEUKH +U+C1A5(2);; # HANGUL SYLLABLE SIOS O THIEUTH * +U+C1A6(2);; # HANGUL SYLLABLE SIOS O PHIEUPH +U+C1A7(2);; # HANGUL SYLLABLE SIOS O HIEUH +U+C1A8(2);; # HANGUL SYLLABLE SIOS WA * +U+C1A9(2);; # HANGUL SYLLABLE SIOS WA KIYEOK * +U+C1AA(2);; # HANGUL SYLLABLE SIOS WA SSANGKIYEOK +U+C1AB(2);; # HANGUL SYLLABLE SIOS WA KIYEOKSIOS +U+C1AC(2);; # HANGUL SYLLABLE SIOS WA NIEUN * +U+C1AD(2);; # HANGUL SYLLABLE SIOS WA NIEUNCIEUC +U+C1AE(2);; # HANGUL SYLLABLE SIOS WA NIEUNHIEUH +U+C1AF(2);; # HANGUL SYLLABLE SIOS WA TIKEUT +U+C1B0(2);; # HANGUL SYLLABLE SIOS WA RIEUL * +U+C1B1(2);; # HANGUL SYLLABLE SIOS WA RIEULKIYEOK +U+C1B2(2);; # HANGUL SYLLABLE SIOS WA RIEULMIEUM +U+C1B3(2);; # HANGUL SYLLABLE SIOS WA RIEULPIEUP +U+C1B4(2);; # HANGUL SYLLABLE SIOS WA RIEULSIOS +U+C1B5(2);; # HANGUL SYLLABLE SIOS WA RIEULTHIEUTH +U+C1B6(2);; # HANGUL SYLLABLE SIOS WA RIEULPHIEUPH +U+C1B7(2);; # HANGUL SYLLABLE SIOS WA RIEULHIEUH +U+C1B8(2);; # HANGUL SYLLABLE SIOS WA MIEUM +U+C1B9(2);; # HANGUL SYLLABLE SIOS WA PIEUP +U+C1BA(2);; # HANGUL SYLLABLE SIOS WA PIEUPSIOS +U+C1BB(2);; # HANGUL SYLLABLE SIOS WA SIOS +U+C1BC(2);; # HANGUL SYLLABLE SIOS WA SSANGSIOS +U+C1BD(2);; # HANGUL SYLLABLE SIOS WA IEUNG * +U+C1BE(2);; # HANGUL SYLLABLE SIOS WA CIEUC +U+C1BF(2);; # HANGUL SYLLABLE SIOS WA CHIEUCH +U+C1C0(2);; # HANGUL SYLLABLE SIOS WA KHIEUKH +U+C1C1(2);; # HANGUL SYLLABLE SIOS WA THIEUTH +U+C1C2(2);; # HANGUL SYLLABLE SIOS WA PHIEUPH +U+C1C3(2);; # HANGUL SYLLABLE SIOS WA HIEUH +U+C1C4(2);; # HANGUL SYLLABLE SIOS WAE * +U+C1C5(2);; # HANGUL SYLLABLE SIOS WAE KIYEOK +U+C1C6(2);; # HANGUL SYLLABLE SIOS WAE SSANGKIYEOK +U+C1C7(2);; # HANGUL SYLLABLE SIOS WAE KIYEOKSIOS +U+C1C8(2);; # HANGUL SYLLABLE SIOS WAE NIEUN * +U+C1C9(2);; # HANGUL SYLLABLE SIOS WAE NIEUNCIEUC +U+C1CA(2);; # HANGUL SYLLABLE SIOS WAE NIEUNHIEUH +U+C1CB(2);; # HANGUL SYLLABLE SIOS WAE TIKEUT +U+C1CC(2);; # HANGUL SYLLABLE SIOS WAE RIEUL * +U+C1CD(2);; # HANGUL SYLLABLE SIOS WAE RIEULKIYEOK +U+C1CE(2);; # HANGUL SYLLABLE SIOS WAE RIEULMIEUM +U+C1CF(2);; # HANGUL SYLLABLE SIOS WAE RIEULPIEUP +U+C1D0(2);; # HANGUL SYLLABLE SIOS WAE RIEULSIOS +U+C1D1(2);; # HANGUL SYLLABLE SIOS WAE RIEULTHIEUTH +U+C1D2(2);; # HANGUL SYLLABLE SIOS WAE RIEULPHIEUPH +U+C1D3(2);; # HANGUL SYLLABLE SIOS WAE RIEULHIEUH +U+C1D4(2);; # HANGUL SYLLABLE SIOS WAE MIEUM * +U+C1D5(2);; # HANGUL SYLLABLE SIOS WAE PIEUP +U+C1D6(2);; # HANGUL SYLLABLE SIOS WAE PIEUPSIOS +U+C1D7(2);; # HANGUL SYLLABLE SIOS WAE SIOS * +U+C1D8(2);; # HANGUL SYLLABLE SIOS WAE SSANGSIOS * +U+C1D9(2);; # HANGUL SYLLABLE SIOS WAE IEUNG +U+C1DA(2);; # HANGUL SYLLABLE SIOS WAE CIEUC +U+C1DB(2);; # HANGUL SYLLABLE SIOS WAE CHIEUCH +U+C1DC(2);; # HANGUL SYLLABLE SIOS WAE KHIEUKH +U+C1DD(2);; # HANGUL SYLLABLE SIOS WAE THIEUTH +U+C1DE(2);; # HANGUL SYLLABLE SIOS WAE PHIEUPH +U+C1DF(2);; # HANGUL SYLLABLE SIOS WAE HIEUH +U+C1E0(2);; # HANGUL SYLLABLE SIOS OE * +U+C1E1(2);; # HANGUL SYLLABLE SIOS OE KIYEOK +U+C1E2(2);; # HANGUL SYLLABLE SIOS OE SSANGKIYEOK +U+C1E3(2);; # HANGUL SYLLABLE SIOS OE KIYEOKSIOS +U+C1E4(2);; # HANGUL SYLLABLE SIOS OE NIEUN * +U+C1E5(2);; # HANGUL SYLLABLE SIOS OE NIEUNCIEUC +U+C1E6(2);; # HANGUL SYLLABLE SIOS OE NIEUNHIEUH +U+C1E7(2);; # HANGUL SYLLABLE SIOS OE TIKEUT +U+C1E8(2);; # HANGUL SYLLABLE SIOS OE RIEUL * +U+C1E9(2);; # HANGUL SYLLABLE SIOS OE RIEULKIYEOK +U+C1EA(2);; # HANGUL SYLLABLE SIOS OE RIEULMIEUM +U+C1EB(2);; # HANGUL SYLLABLE SIOS OE RIEULPIEUP +U+C1EC(2);; # HANGUL SYLLABLE SIOS OE RIEULSIOS +U+C1ED(2);; # HANGUL SYLLABLE SIOS OE RIEULTHIEUTH +U+C1EE(2);; # HANGUL SYLLABLE SIOS OE RIEULPHIEUPH +U+C1EF(2);; # HANGUL SYLLABLE SIOS OE RIEULHIEUH +U+C1F0(2);; # HANGUL SYLLABLE SIOS OE MIEUM * +U+C1F1(2);; # HANGUL SYLLABLE SIOS OE PIEUP * +U+C1F2(2);; # HANGUL SYLLABLE SIOS OE PIEUPSIOS +U+C1F3(2);; # HANGUL SYLLABLE SIOS OE SIOS * +U+C1F4(2);; # HANGUL SYLLABLE SIOS OE SSANGSIOS +U+C1F5(2);; # HANGUL SYLLABLE SIOS OE IEUNG +U+C1F6(2);; # HANGUL SYLLABLE SIOS OE CIEUC +U+C1F7(2);; # HANGUL SYLLABLE SIOS OE CHIEUCH +U+C1F8(2);; # HANGUL SYLLABLE SIOS OE KHIEUKH +U+C1F9(2);; # HANGUL SYLLABLE SIOS OE THIEUTH +U+C1FA(2);; # HANGUL SYLLABLE SIOS OE PHIEUPH +U+C1FB(2);; # HANGUL SYLLABLE SIOS OE HIEUH +U+C1FC(2);; # HANGUL SYLLABLE SIOS YO * +U+C1FD(2);; # HANGUL SYLLABLE SIOS YO KIYEOK * +U+C1FE(2);; # HANGUL SYLLABLE SIOS YO SSANGKIYEOK +U+C1FF(2);; # HANGUL SYLLABLE SIOS YO KIYEOKSIOS +U+C200(2);; # HANGUL SYLLABLE SIOS YO NIEUN * +U+C201(2);; # HANGUL SYLLABLE SIOS YO NIEUNCIEUC +U+C202(2);; # HANGUL SYLLABLE SIOS YO NIEUNHIEUH +U+C203(2);; # HANGUL SYLLABLE SIOS YO TIKEUT +U+C204(2);; # HANGUL SYLLABLE SIOS YO RIEUL * +U+C205(2);; # HANGUL SYLLABLE SIOS YO RIEULKIYEOK +U+C206(2);; # HANGUL SYLLABLE SIOS YO RIEULMIEUM +U+C207(2);; # HANGUL SYLLABLE SIOS YO RIEULPIEUP +U+C208(2);; # HANGUL SYLLABLE SIOS YO RIEULSIOS +U+C209(2);; # HANGUL SYLLABLE SIOS YO RIEULTHIEUTH +U+C20A(2);; # HANGUL SYLLABLE SIOS YO RIEULPHIEUPH +U+C20B(2);; # HANGUL SYLLABLE SIOS YO RIEULHIEUH +U+C20C(2);; # HANGUL SYLLABLE SIOS YO MIEUM * +U+C20D(2);; # HANGUL SYLLABLE SIOS YO PIEUP * +U+C20E(2);; # HANGUL SYLLABLE SIOS YO PIEUPSIOS +U+C20F(2);; # HANGUL SYLLABLE SIOS YO SIOS * +U+C210(2);; # HANGUL SYLLABLE SIOS YO SSANGSIOS +U+C211(2);; # HANGUL SYLLABLE SIOS YO IEUNG * +U+C212(2);; # HANGUL SYLLABLE SIOS YO CIEUC +U+C213(2);; # HANGUL SYLLABLE SIOS YO CHIEUCH +U+C214(2);; # HANGUL SYLLABLE SIOS YO KHIEUKH +U+C215(2);; # HANGUL SYLLABLE SIOS YO THIEUTH +U+C216(2);; # HANGUL SYLLABLE SIOS YO PHIEUPH +U+C217(2);; # HANGUL SYLLABLE SIOS YO HIEUH +U+C218(2);; # HANGUL SYLLABLE SIOS U * +U+C219(2);; # HANGUL SYLLABLE SIOS U KIYEOK * +U+C21A(2);; # HANGUL SYLLABLE SIOS U SSANGKIYEOK +U+C21B(2);; # HANGUL SYLLABLE SIOS U KIYEOKSIOS +U+C21C(2);; # HANGUL SYLLABLE SIOS U NIEUN * +U+C21D(2);; # HANGUL SYLLABLE SIOS U NIEUNCIEUC +U+C21E(2);; # HANGUL SYLLABLE SIOS U NIEUNHIEUH +U+C21F(2);; # HANGUL SYLLABLE SIOS U TIKEUT * +U+C220(2);; # HANGUL SYLLABLE SIOS U RIEUL * +U+C221(2);; # HANGUL SYLLABLE SIOS U RIEULKIYEOK +U+C222(2);; # HANGUL SYLLABLE SIOS U RIEULMIEUM +U+C223(2);; # HANGUL SYLLABLE SIOS U RIEULPIEUP +U+C224(2);; # HANGUL SYLLABLE SIOS U RIEULSIOS +U+C225(2);; # HANGUL SYLLABLE SIOS U RIEULTHIEUTH +U+C226(2);; # HANGUL SYLLABLE SIOS U RIEULPHIEUPH +U+C227(2);; # HANGUL SYLLABLE SIOS U RIEULHIEUH +U+C228(2);; # HANGUL SYLLABLE SIOS U MIEUM * +U+C229(2);; # HANGUL SYLLABLE SIOS U PIEUP * +U+C22A(2);; # HANGUL SYLLABLE SIOS U PIEUPSIOS +U+C22B(2);; # HANGUL SYLLABLE SIOS U SIOS * +U+C22C(2);; # HANGUL SYLLABLE SIOS U SSANGSIOS +U+C22D(2);; # HANGUL SYLLABLE SIOS U IEUNG * +U+C22E(2);; # HANGUL SYLLABLE SIOS U CIEUC +U+C22F(2);; # HANGUL SYLLABLE SIOS U CHIEUCH * +U+C230(2);; # HANGUL SYLLABLE SIOS U KHIEUKH +U+C231(2);; # HANGUL SYLLABLE SIOS U THIEUTH * +U+C232(2);; # HANGUL SYLLABLE SIOS U PHIEUPH * +U+C233(2);; # HANGUL SYLLABLE SIOS U HIEUH +U+C234(2);; # HANGUL SYLLABLE SIOS WEO * +U+C235(2);; # HANGUL SYLLABLE SIOS WEO KIYEOK +U+C236(2);; # HANGUL SYLLABLE SIOS WEO SSANGKIYEOK +U+C237(2);; # HANGUL SYLLABLE SIOS WEO KIYEOKSIOS +U+C238(2);; # HANGUL SYLLABLE SIOS WEO NIEUN +U+C239(2);; # HANGUL SYLLABLE SIOS WEO NIEUNCIEUC +U+C23A(2);; # HANGUL SYLLABLE SIOS WEO NIEUNHIEUH +U+C23B(2);; # HANGUL SYLLABLE SIOS WEO TIKEUT +U+C23C(2);; # HANGUL SYLLABLE SIOS WEO RIEUL +U+C23D(2);; # HANGUL SYLLABLE SIOS WEO RIEULKIYEOK +U+C23E(2);; # HANGUL SYLLABLE SIOS WEO RIEULMIEUM +U+C23F(2);; # HANGUL SYLLABLE SIOS WEO RIEULPIEUP +U+C240(2);; # HANGUL SYLLABLE SIOS WEO RIEULSIOS +U+C241(2);; # HANGUL SYLLABLE SIOS WEO RIEULTHIEUTH +U+C242(2);; # HANGUL SYLLABLE SIOS WEO RIEULPHIEUPH +U+C243(2);; # HANGUL SYLLABLE SIOS WEO RIEULHIEUH +U+C244(2);; # HANGUL SYLLABLE SIOS WEO MIEUM +U+C245(2);; # HANGUL SYLLABLE SIOS WEO PIEUP +U+C246(2);; # HANGUL SYLLABLE SIOS WEO PIEUPSIOS +U+C247(2);; # HANGUL SYLLABLE SIOS WEO SIOS +U+C248(2);; # HANGUL SYLLABLE SIOS WEO SSANGSIOS * +U+C249(2);; # HANGUL SYLLABLE SIOS WEO IEUNG +U+C24A(2);; # HANGUL SYLLABLE SIOS WEO CIEUC +U+C24B(2);; # HANGUL SYLLABLE SIOS WEO CHIEUCH +U+C24C(2);; # HANGUL SYLLABLE SIOS WEO KHIEUKH +U+C24D(2);; # HANGUL SYLLABLE SIOS WEO THIEUTH +U+C24E(2);; # HANGUL SYLLABLE SIOS WEO PHIEUPH +U+C24F(2);; # HANGUL SYLLABLE SIOS WEO HIEUH +U+C250(2);; # HANGUL SYLLABLE SIOS WE * +U+C251(2);; # HANGUL SYLLABLE SIOS WE KIYEOK * +U+C252(2);; # HANGUL SYLLABLE SIOS WE SSANGKIYEOK +U+C253(2);; # HANGUL SYLLABLE SIOS WE KIYEOKSIOS +U+C254(2);; # HANGUL SYLLABLE SIOS WE NIEUN * +U+C255(2);; # HANGUL SYLLABLE SIOS WE NIEUNCIEUC +U+C256(2);; # HANGUL SYLLABLE SIOS WE NIEUNHIEUH +U+C257(2);; # HANGUL SYLLABLE SIOS WE TIKEUT +U+C258(2);; # HANGUL SYLLABLE SIOS WE RIEUL * +U+C259(2);; # HANGUL SYLLABLE SIOS WE RIEULKIYEOK +U+C25A(2);; # HANGUL SYLLABLE SIOS WE RIEULMIEUM +U+C25B(2);; # HANGUL SYLLABLE SIOS WE RIEULPIEUP +U+C25C(2);; # HANGUL SYLLABLE SIOS WE RIEULSIOS +U+C25D(2);; # HANGUL SYLLABLE SIOS WE RIEULTHIEUTH +U+C25E(2);; # HANGUL SYLLABLE SIOS WE RIEULPHIEUPH +U+C25F(2);; # HANGUL SYLLABLE SIOS WE RIEULHIEUH +U+C260(2);; # HANGUL SYLLABLE SIOS WE MIEUM * +U+C261(2);; # HANGUL SYLLABLE SIOS WE PIEUP +U+C262(2);; # HANGUL SYLLABLE SIOS WE PIEUPSIOS +U+C263(2);; # HANGUL SYLLABLE SIOS WE SIOS +U+C264(2);; # HANGUL SYLLABLE SIOS WE SSANGSIOS +U+C265(2);; # HANGUL SYLLABLE SIOS WE IEUNG * +U+C266(2);; # HANGUL SYLLABLE SIOS WE CIEUC +U+C267(2);; # HANGUL SYLLABLE SIOS WE CHIEUCH +U+C268(2);; # HANGUL SYLLABLE SIOS WE KHIEUKH +U+C269(2);; # HANGUL SYLLABLE SIOS WE THIEUTH +U+C26A(2);; # HANGUL SYLLABLE SIOS WE PHIEUPH +U+C26B(2);; # HANGUL SYLLABLE SIOS WE HIEUH +U+C26C(2);; # HANGUL SYLLABLE SIOS WI * +U+C26D(2);; # HANGUL SYLLABLE SIOS WI KIYEOK * +U+C26E(2);; # HANGUL SYLLABLE SIOS WI SSANGKIYEOK +U+C26F(2);; # HANGUL SYLLABLE SIOS WI KIYEOKSIOS +U+C270(2);; # HANGUL SYLLABLE SIOS WI NIEUN * +U+C271(2);; # HANGUL SYLLABLE SIOS WI NIEUNCIEUC +U+C272(2);; # HANGUL SYLLABLE SIOS WI NIEUNHIEUH +U+C273(2);; # HANGUL SYLLABLE SIOS WI TIKEUT +U+C274(2);; # HANGUL SYLLABLE SIOS WI RIEUL * +U+C275(2);; # HANGUL SYLLABLE SIOS WI RIEULKIYEOK +U+C276(2);; # HANGUL SYLLABLE SIOS WI RIEULMIEUM +U+C277(2);; # HANGUL SYLLABLE SIOS WI RIEULPIEUP +U+C278(2);; # HANGUL SYLLABLE SIOS WI RIEULSIOS +U+C279(2);; # HANGUL SYLLABLE SIOS WI RIEULTHIEUTH +U+C27A(2);; # HANGUL SYLLABLE SIOS WI RIEULPHIEUPH +U+C27B(2);; # HANGUL SYLLABLE SIOS WI RIEULHIEUH +U+C27C(2);; # HANGUL SYLLABLE SIOS WI MIEUM * +U+C27D(2);; # HANGUL SYLLABLE SIOS WI PIEUP * +U+C27E(2);; # HANGUL SYLLABLE SIOS WI PIEUPSIOS +U+C27F(2);; # HANGUL SYLLABLE SIOS WI SIOS * +U+C280(2);; # HANGUL SYLLABLE SIOS WI SSANGSIOS +U+C281(2);; # HANGUL SYLLABLE SIOS WI IEUNG * +U+C282(2);; # HANGUL SYLLABLE SIOS WI CIEUC +U+C283(2);; # HANGUL SYLLABLE SIOS WI CHIEUCH +U+C284(2);; # HANGUL SYLLABLE SIOS WI KHIEUKH +U+C285(2);; # HANGUL SYLLABLE SIOS WI THIEUTH +U+C286(2);; # HANGUL SYLLABLE SIOS WI PHIEUPH +U+C287(2);; # HANGUL SYLLABLE SIOS WI HIEUH +U+C288(2);; # HANGUL SYLLABLE SIOS YU * +U+C289(2);; # HANGUL SYLLABLE SIOS YU KIYEOK * +U+C28A(2);; # HANGUL SYLLABLE SIOS YU SSANGKIYEOK +U+C28B(2);; # HANGUL SYLLABLE SIOS YU KIYEOKSIOS +U+C28C(2);; # HANGUL SYLLABLE SIOS YU NIEUN +U+C28D(2);; # HANGUL SYLLABLE SIOS YU NIEUNCIEUC +U+C28E(2);; # HANGUL SYLLABLE SIOS YU NIEUNHIEUH +U+C28F(2);; # HANGUL SYLLABLE SIOS YU TIKEUT +U+C290(2);; # HANGUL SYLLABLE SIOS YU RIEUL * +U+C291(2);; # HANGUL SYLLABLE SIOS YU RIEULKIYEOK +U+C292(2);; # HANGUL SYLLABLE SIOS YU RIEULMIEUM +U+C293(2);; # HANGUL SYLLABLE SIOS YU RIEULPIEUP +U+C294(2);; # HANGUL SYLLABLE SIOS YU RIEULSIOS +U+C295(2);; # HANGUL SYLLABLE SIOS YU RIEULTHIEUTH +U+C296(2);; # HANGUL SYLLABLE SIOS YU RIEULPHIEUPH +U+C297(2);; # HANGUL SYLLABLE SIOS YU RIEULHIEUH +U+C298(2);; # HANGUL SYLLABLE SIOS YU MIEUM * +U+C299(2);; # HANGUL SYLLABLE SIOS YU PIEUP +U+C29A(2);; # HANGUL SYLLABLE SIOS YU PIEUPSIOS +U+C29B(2);; # HANGUL SYLLABLE SIOS YU SIOS * +U+C29C(2);; # HANGUL SYLLABLE SIOS YU SSANGSIOS +U+C29D(2);; # HANGUL SYLLABLE SIOS YU IEUNG * +U+C29E(2);; # HANGUL SYLLABLE SIOS YU CIEUC +U+C29F(2);; # HANGUL SYLLABLE SIOS YU CHIEUCH +U+C2A0(2);; # HANGUL SYLLABLE SIOS YU KHIEUKH +U+C2A1(2);; # HANGUL SYLLABLE SIOS YU THIEUTH +U+C2A2(2);; # HANGUL SYLLABLE SIOS YU PHIEUPH +U+C2A3(2);; # HANGUL SYLLABLE SIOS YU HIEUH +U+C2A4(2);; # HANGUL SYLLABLE SIOS EU * +U+C2A5(2);; # HANGUL SYLLABLE SIOS EU KIYEOK * +U+C2A6(2);; # HANGUL SYLLABLE SIOS EU SSANGKIYEOK +U+C2A7(2);; # HANGUL SYLLABLE SIOS EU KIYEOKSIOS +U+C2A8(2);; # HANGUL SYLLABLE SIOS EU NIEUN * +U+C2A9(2);; # HANGUL SYLLABLE SIOS EU NIEUNCIEUC +U+C2AA(2);; # HANGUL SYLLABLE SIOS EU NIEUNHIEUH +U+C2AB(2);; # HANGUL SYLLABLE SIOS EU TIKEUT +U+C2AC(2);; # HANGUL SYLLABLE SIOS EU RIEUL * +U+C2AD(2);; # HANGUL SYLLABLE SIOS EU RIEULKIYEOK * +U+C2AE(2);; # HANGUL SYLLABLE SIOS EU RIEULMIEUM +U+C2AF(2);; # HANGUL SYLLABLE SIOS EU RIEULPIEUP +U+C2B0(2);; # HANGUL SYLLABLE SIOS EU RIEULSIOS +U+C2B1(2);; # HANGUL SYLLABLE SIOS EU RIEULTHIEUTH +U+C2B2(2);; # HANGUL SYLLABLE SIOS EU RIEULPHIEUPH +U+C2B3(2);; # HANGUL SYLLABLE SIOS EU RIEULHIEUH +U+C2B4(2);; # HANGUL SYLLABLE SIOS EU MIEUM * +U+C2B5(2);; # HANGUL SYLLABLE SIOS EU PIEUP * +U+C2B6(2);; # HANGUL SYLLABLE SIOS EU PIEUPSIOS +U+C2B7(2);; # HANGUL SYLLABLE SIOS EU SIOS * +U+C2B8(2);; # HANGUL SYLLABLE SIOS EU SSANGSIOS +U+C2B9(2);; # HANGUL SYLLABLE SIOS EU IEUNG * +U+C2BA(2);; # HANGUL SYLLABLE SIOS EU CIEUC +U+C2BB(2);; # HANGUL SYLLABLE SIOS EU CHIEUCH +U+C2BC(2);; # HANGUL SYLLABLE SIOS EU KHIEUKH +U+C2BD(2);; # HANGUL SYLLABLE SIOS EU THIEUTH +U+C2BE(2);; # HANGUL SYLLABLE SIOS EU PHIEUPH +U+C2BF(2);; # HANGUL SYLLABLE SIOS EU HIEUH +U+C2C0(2);; # HANGUL SYLLABLE SIOS YI +U+C2C1(2);; # HANGUL SYLLABLE SIOS YI KIYEOK +U+C2C2(2);; # HANGUL SYLLABLE SIOS YI SSANGKIYEOK +U+C2C3(2);; # HANGUL SYLLABLE SIOS YI KIYEOKSIOS +U+C2C4(2);; # HANGUL SYLLABLE SIOS YI NIEUN +U+C2C5(2);; # HANGUL SYLLABLE SIOS YI NIEUNCIEUC +U+C2C6(2);; # HANGUL SYLLABLE SIOS YI NIEUNHIEUH +U+C2C7(2);; # HANGUL SYLLABLE SIOS YI TIKEUT +U+C2C8(2);; # HANGUL SYLLABLE SIOS YI RIEUL +U+C2C9(2);; # HANGUL SYLLABLE SIOS YI RIEULKIYEOK +U+C2CA(2);; # HANGUL SYLLABLE SIOS YI RIEULMIEUM +U+C2CB(2);; # HANGUL SYLLABLE SIOS YI RIEULPIEUP +U+C2CC(2);; # HANGUL SYLLABLE SIOS YI RIEULSIOS +U+C2CD(2);; # HANGUL SYLLABLE SIOS YI RIEULTHIEUTH +U+C2CE(2);; # HANGUL SYLLABLE SIOS YI RIEULPHIEUPH +U+C2CF(2);; # HANGUL SYLLABLE SIOS YI RIEULHIEUH +U+C2D0(2);; # HANGUL SYLLABLE SIOS YI MIEUM +U+C2D1(2);; # HANGUL SYLLABLE SIOS YI PIEUP +U+C2D2(2);; # HANGUL SYLLABLE SIOS YI PIEUPSIOS +U+C2D3(2);; # HANGUL SYLLABLE SIOS YI SIOS +U+C2D4(2);; # HANGUL SYLLABLE SIOS YI SSANGSIOS +U+C2D5(2);; # HANGUL SYLLABLE SIOS YI IEUNG +U+C2D6(2);; # HANGUL SYLLABLE SIOS YI CIEUC +U+C2D7(2);; # HANGUL SYLLABLE SIOS YI CHIEUCH +U+C2D8(2);; # HANGUL SYLLABLE SIOS YI KHIEUKH +U+C2D9(2);; # HANGUL SYLLABLE SIOS YI THIEUTH +U+C2DA(2);; # HANGUL SYLLABLE SIOS YI PHIEUPH +U+C2DB(2);; # HANGUL SYLLABLE SIOS YI HIEUH +U+C2DC(2);; # HANGUL SYLLABLE SIOS I * +U+C2DD(2);; # HANGUL SYLLABLE SIOS I KIYEOK * +U+C2DE(2);; # HANGUL SYLLABLE SIOS I SSANGKIYEOK +U+C2DF(2);; # HANGUL SYLLABLE SIOS I KIYEOKSIOS +U+C2E0(2);; # HANGUL SYLLABLE SIOS I NIEUN * +U+C2E1(2);; # HANGUL SYLLABLE SIOS I NIEUNCIEUC +U+C2E2(2);; # HANGUL SYLLABLE SIOS I NIEUNHIEUH +U+C2E3(2);; # HANGUL SYLLABLE SIOS I TIKEUT * +U+C2E4(2);; # HANGUL SYLLABLE SIOS I RIEUL * +U+C2E5(2);; # HANGUL SYLLABLE SIOS I RIEULKIYEOK +U+C2E6(2);; # HANGUL SYLLABLE SIOS I RIEULMIEUM +U+C2E7(2);; # HANGUL SYLLABLE SIOS I RIEULPIEUP +U+C2E8(2);; # HANGUL SYLLABLE SIOS I RIEULSIOS +U+C2E9(2);; # HANGUL SYLLABLE SIOS I RIEULTHIEUTH +U+C2EA(2);; # HANGUL SYLLABLE SIOS I RIEULPHIEUPH +U+C2EB(2);; # HANGUL SYLLABLE SIOS I RIEULHIEUH * +U+C2EC(2);; # HANGUL SYLLABLE SIOS I MIEUM * +U+C2ED(2);; # HANGUL SYLLABLE SIOS I PIEUP * +U+C2EE(2);; # HANGUL SYLLABLE SIOS I PIEUPSIOS +U+C2EF(2);; # HANGUL SYLLABLE SIOS I SIOS * +U+C2F0(2);; # HANGUL SYLLABLE SIOS I SSANGSIOS +U+C2F1(2);; # HANGUL SYLLABLE SIOS I IEUNG * +U+C2F2(2);; # HANGUL SYLLABLE SIOS I CIEUC +U+C2F3(2);; # HANGUL SYLLABLE SIOS I CHIEUCH +U+C2F4(2);; # HANGUL SYLLABLE SIOS I KHIEUKH +U+C2F5(2);; # HANGUL SYLLABLE SIOS I THIEUTH +U+C2F6(2);; # HANGUL SYLLABLE SIOS I PHIEUPH * +U+C2F7(2);; # HANGUL SYLLABLE SIOS I HIEUH +U+C2F8(2);; # HANGUL SYLLABLE SSANGSIOS A * +U+C2F9(2);; # HANGUL SYLLABLE SSANGSIOS A KIYEOK * +U+C2FA(2);; # HANGUL SYLLABLE SSANGSIOS A SSANGKIYEOK +U+C2FB(2);; # HANGUL SYLLABLE SSANGSIOS A KIYEOKSIOS * +U+C2FC(2);; # HANGUL SYLLABLE SSANGSIOS A NIEUN * +U+C2FD(2);; # HANGUL SYLLABLE SSANGSIOS A NIEUNCIEUC +U+C2FE(2);; # HANGUL SYLLABLE SSANGSIOS A NIEUNHIEUH +U+C2FF(2);; # HANGUL SYLLABLE SSANGSIOS A TIKEUT +U+C300(2);; # HANGUL SYLLABLE SSANGSIOS A RIEUL * +U+C301(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULKIYEOK +U+C302(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULMIEUM +U+C303(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULPIEUP +U+C304(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULSIOS +U+C305(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULTHIEUTH +U+C306(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULPHIEUPH +U+C307(2);; # HANGUL SYLLABLE SSANGSIOS A RIEULHIEUH +U+C308(2);; # HANGUL SYLLABLE SSANGSIOS A MIEUM * +U+C309(2);; # HANGUL SYLLABLE SSANGSIOS A PIEUP * +U+C30A(2);; # HANGUL SYLLABLE SSANGSIOS A PIEUPSIOS +U+C30B(2);; # HANGUL SYLLABLE SSANGSIOS A SIOS +U+C30C(2);; # HANGUL SYLLABLE SSANGSIOS A SSANGSIOS * +U+C30D(2);; # HANGUL SYLLABLE SSANGSIOS A IEUNG * +U+C30E(2);; # HANGUL SYLLABLE SSANGSIOS A CIEUC +U+C30F(2);; # HANGUL SYLLABLE SSANGSIOS A CHIEUCH +U+C310(2);; # HANGUL SYLLABLE SSANGSIOS A KHIEUKH +U+C311(2);; # HANGUL SYLLABLE SSANGSIOS A THIEUTH +U+C312(2);; # HANGUL SYLLABLE SSANGSIOS A PHIEUPH +U+C313(2);; # HANGUL SYLLABLE SSANGSIOS A HIEUH * +U+C314(2);; # HANGUL SYLLABLE SSANGSIOS AE * +U+C315(2);; # HANGUL SYLLABLE SSANGSIOS AE KIYEOK * +U+C316(2);; # HANGUL SYLLABLE SSANGSIOS AE SSANGKIYEOK +U+C317(2);; # HANGUL SYLLABLE SSANGSIOS AE KIYEOKSIOS +U+C318(2);; # HANGUL SYLLABLE SSANGSIOS AE NIEUN * +U+C319(2);; # HANGUL SYLLABLE SSANGSIOS AE NIEUNCIEUC +U+C31A(2);; # HANGUL SYLLABLE SSANGSIOS AE NIEUNHIEUH +U+C31B(2);; # HANGUL SYLLABLE SSANGSIOS AE TIKEUT +U+C31C(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEUL * +U+C31D(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULKIYEOK +U+C31E(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULMIEUM +U+C31F(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULPIEUP +U+C320(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULSIOS +U+C321(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULTHIEUTH +U+C322(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULPHIEUPH +U+C323(2);; # HANGUL SYLLABLE SSANGSIOS AE RIEULHIEUH +U+C324(2);; # HANGUL SYLLABLE SSANGSIOS AE MIEUM * +U+C325(2);; # HANGUL SYLLABLE SSANGSIOS AE PIEUP * +U+C326(2);; # HANGUL SYLLABLE SSANGSIOS AE PIEUPSIOS +U+C327(2);; # HANGUL SYLLABLE SSANGSIOS AE SIOS +U+C328(2);; # HANGUL SYLLABLE SSANGSIOS AE SSANGSIOS * +U+C329(2);; # HANGUL SYLLABLE SSANGSIOS AE IEUNG * +U+C32A(2);; # HANGUL SYLLABLE SSANGSIOS AE CIEUC +U+C32B(2);; # HANGUL SYLLABLE SSANGSIOS AE CHIEUCH +U+C32C(2);; # HANGUL SYLLABLE SSANGSIOS AE KHIEUKH +U+C32D(2);; # HANGUL SYLLABLE SSANGSIOS AE THIEUTH +U+C32E(2);; # HANGUL SYLLABLE SSANGSIOS AE PHIEUPH +U+C32F(2);; # HANGUL SYLLABLE SSANGSIOS AE HIEUH +U+C330(2);; # HANGUL SYLLABLE SSANGSIOS YA +U+C331(2);; # HANGUL SYLLABLE SSANGSIOS YA KIYEOK +U+C332(2);; # HANGUL SYLLABLE SSANGSIOS YA SSANGKIYEOK +U+C333(2);; # HANGUL SYLLABLE SSANGSIOS YA KIYEOKSIOS +U+C334(2);; # HANGUL SYLLABLE SSANGSIOS YA NIEUN +U+C335(2);; # HANGUL SYLLABLE SSANGSIOS YA NIEUNCIEUC +U+C336(2);; # HANGUL SYLLABLE SSANGSIOS YA NIEUNHIEUH +U+C337(2);; # HANGUL SYLLABLE SSANGSIOS YA TIKEUT +U+C338(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEUL +U+C339(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULKIYEOK +U+C33A(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULMIEUM +U+C33B(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULPIEUP +U+C33C(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULSIOS +U+C33D(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULTHIEUTH +U+C33E(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULPHIEUPH +U+C33F(2);; # HANGUL SYLLABLE SSANGSIOS YA RIEULHIEUH +U+C340(2);; # HANGUL SYLLABLE SSANGSIOS YA MIEUM +U+C341(2);; # HANGUL SYLLABLE SSANGSIOS YA PIEUP +U+C342(2);; # HANGUL SYLLABLE SSANGSIOS YA PIEUPSIOS +U+C343(2);; # HANGUL SYLLABLE SSANGSIOS YA SIOS +U+C344(2);; # HANGUL SYLLABLE SSANGSIOS YA SSANGSIOS +U+C345(2);; # HANGUL SYLLABLE SSANGSIOS YA IEUNG * +U+C346(2);; # HANGUL SYLLABLE SSANGSIOS YA CIEUC +U+C347(2);; # HANGUL SYLLABLE SSANGSIOS YA CHIEUCH +U+C348(2);; # HANGUL SYLLABLE SSANGSIOS YA KHIEUKH +U+C349(2);; # HANGUL SYLLABLE SSANGSIOS YA THIEUTH +U+C34A(2);; # HANGUL SYLLABLE SSANGSIOS YA PHIEUPH +U+C34B(2);; # HANGUL SYLLABLE SSANGSIOS YA HIEUH +U+C34C(2);; # HANGUL SYLLABLE SSANGSIOS YAE +U+C34D(2);; # HANGUL SYLLABLE SSANGSIOS YAE KIYEOK +U+C34E(2);; # HANGUL SYLLABLE SSANGSIOS YAE SSANGKIYEOK +U+C34F(2);; # HANGUL SYLLABLE SSANGSIOS YAE KIYEOKSIOS +U+C350(2);; # HANGUL SYLLABLE SSANGSIOS YAE NIEUN +U+C351(2);; # HANGUL SYLLABLE SSANGSIOS YAE NIEUNCIEUC +U+C352(2);; # HANGUL SYLLABLE SSANGSIOS YAE NIEUNHIEUH +U+C353(2);; # HANGUL SYLLABLE SSANGSIOS YAE TIKEUT +U+C354(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEUL +U+C355(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULKIYEOK +U+C356(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULMIEUM +U+C357(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULPIEUP +U+C358(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULSIOS +U+C359(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULTHIEUTH +U+C35A(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULPHIEUPH +U+C35B(2);; # HANGUL SYLLABLE SSANGSIOS YAE RIEULHIEUH +U+C35C(2);; # HANGUL SYLLABLE SSANGSIOS YAE MIEUM +U+C35D(2);; # HANGUL SYLLABLE SSANGSIOS YAE PIEUP +U+C35E(2);; # HANGUL SYLLABLE SSANGSIOS YAE PIEUPSIOS +U+C35F(2);; # HANGUL SYLLABLE SSANGSIOS YAE SIOS +U+C360(2);; # HANGUL SYLLABLE SSANGSIOS YAE SSANGSIOS +U+C361(2);; # HANGUL SYLLABLE SSANGSIOS YAE IEUNG +U+C362(2);; # HANGUL SYLLABLE SSANGSIOS YAE CIEUC +U+C363(2);; # HANGUL SYLLABLE SSANGSIOS YAE CHIEUCH +U+C364(2);; # HANGUL SYLLABLE SSANGSIOS YAE KHIEUKH +U+C365(2);; # HANGUL SYLLABLE SSANGSIOS YAE THIEUTH +U+C366(2);; # HANGUL SYLLABLE SSANGSIOS YAE PHIEUPH +U+C367(2);; # HANGUL SYLLABLE SSANGSIOS YAE HIEUH +U+C368(2);; # HANGUL SYLLABLE SSANGSIOS EO * +U+C369(2);; # HANGUL SYLLABLE SSANGSIOS EO KIYEOK * +U+C36A(2);; # HANGUL SYLLABLE SSANGSIOS EO SSANGKIYEOK +U+C36B(2);; # HANGUL SYLLABLE SSANGSIOS EO KIYEOKSIOS +U+C36C(2);; # HANGUL SYLLABLE SSANGSIOS EO NIEUN * +U+C36D(2);; # HANGUL SYLLABLE SSANGSIOS EO NIEUNCIEUC +U+C36E(2);; # HANGUL SYLLABLE SSANGSIOS EO NIEUNHIEUH +U+C36F(2);; # HANGUL SYLLABLE SSANGSIOS EO TIKEUT +U+C370(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEUL * +U+C371(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULKIYEOK +U+C372(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULMIEUM * +U+C373(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULPIEUP +U+C374(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULSIOS +U+C375(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULTHIEUTH +U+C376(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULPHIEUPH +U+C377(2);; # HANGUL SYLLABLE SSANGSIOS EO RIEULHIEUH +U+C378(2);; # HANGUL SYLLABLE SSANGSIOS EO MIEUM * +U+C379(2);; # HANGUL SYLLABLE SSANGSIOS EO PIEUP * +U+C37A(2);; # HANGUL SYLLABLE SSANGSIOS EO PIEUPSIOS +U+C37B(2);; # HANGUL SYLLABLE SSANGSIOS EO SIOS +U+C37C(2);; # HANGUL SYLLABLE SSANGSIOS EO SSANGSIOS * +U+C37D(2);; # HANGUL SYLLABLE SSANGSIOS EO IEUNG * +U+C37E(2);; # HANGUL SYLLABLE SSANGSIOS EO CIEUC +U+C37F(2);; # HANGUL SYLLABLE SSANGSIOS EO CHIEUCH +U+C380(2);; # HANGUL SYLLABLE SSANGSIOS EO KHIEUKH +U+C381(2);; # HANGUL SYLLABLE SSANGSIOS EO THIEUTH +U+C382(2);; # HANGUL SYLLABLE SSANGSIOS EO PHIEUPH +U+C383(2);; # HANGUL SYLLABLE SSANGSIOS EO HIEUH +U+C384(2);; # HANGUL SYLLABLE SSANGSIOS E * +U+C385(2);; # HANGUL SYLLABLE SSANGSIOS E KIYEOK +U+C386(2);; # HANGUL SYLLABLE SSANGSIOS E SSANGKIYEOK +U+C387(2);; # HANGUL SYLLABLE SSANGSIOS E KIYEOKSIOS +U+C388(2);; # HANGUL SYLLABLE SSANGSIOS E NIEUN * +U+C389(2);; # HANGUL SYLLABLE SSANGSIOS E NIEUNCIEUC +U+C38A(2);; # HANGUL SYLLABLE SSANGSIOS E NIEUNHIEUH +U+C38B(2);; # HANGUL SYLLABLE SSANGSIOS E TIKEUT +U+C38C(2);; # HANGUL SYLLABLE SSANGSIOS E RIEUL * +U+C38D(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULKIYEOK +U+C38E(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULMIEUM +U+C38F(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULPIEUP +U+C390(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULSIOS +U+C391(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULTHIEUTH +U+C392(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULPHIEUPH +U+C393(2);; # HANGUL SYLLABLE SSANGSIOS E RIEULHIEUH +U+C394(2);; # HANGUL SYLLABLE SSANGSIOS E MIEUM +U+C395(2);; # HANGUL SYLLABLE SSANGSIOS E PIEUP +U+C396(2);; # HANGUL SYLLABLE SSANGSIOS E PIEUPSIOS +U+C397(2);; # HANGUL SYLLABLE SSANGSIOS E SIOS +U+C398(2);; # HANGUL SYLLABLE SSANGSIOS E SSANGSIOS +U+C399(2);; # HANGUL SYLLABLE SSANGSIOS E IEUNG +U+C39A(2);; # HANGUL SYLLABLE SSANGSIOS E CIEUC +U+C39B(2);; # HANGUL SYLLABLE SSANGSIOS E CHIEUCH +U+C39C(2);; # HANGUL SYLLABLE SSANGSIOS E KHIEUKH +U+C39D(2);; # HANGUL SYLLABLE SSANGSIOS E THIEUTH +U+C39E(2);; # HANGUL SYLLABLE SSANGSIOS E PHIEUPH +U+C39F(2);; # HANGUL SYLLABLE SSANGSIOS E HIEUH +U+C3A0(2);; # HANGUL SYLLABLE SSANGSIOS YEO +U+C3A1(2);; # HANGUL SYLLABLE SSANGSIOS YEO KIYEOK +U+C3A2(2);; # HANGUL SYLLABLE SSANGSIOS YEO SSANGKIYEOK +U+C3A3(2);; # HANGUL SYLLABLE SSANGSIOS YEO KIYEOKSIOS +U+C3A4(2);; # HANGUL SYLLABLE SSANGSIOS YEO NIEUN +U+C3A5(2);; # HANGUL SYLLABLE SSANGSIOS YEO NIEUNCIEUC +U+C3A6(2);; # HANGUL SYLLABLE SSANGSIOS YEO NIEUNHIEUH +U+C3A7(2);; # HANGUL SYLLABLE SSANGSIOS YEO TIKEUT +U+C3A8(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEUL +U+C3A9(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULKIYEOK +U+C3AA(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULMIEUM +U+C3AB(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULPIEUP +U+C3AC(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULSIOS +U+C3AD(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULTHIEUTH +U+C3AE(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULPHIEUPH +U+C3AF(2);; # HANGUL SYLLABLE SSANGSIOS YEO RIEULHIEUH +U+C3B0(2);; # HANGUL SYLLABLE SSANGSIOS YEO MIEUM +U+C3B1(2);; # HANGUL SYLLABLE SSANGSIOS YEO PIEUP +U+C3B2(2);; # HANGUL SYLLABLE SSANGSIOS YEO PIEUPSIOS +U+C3B3(2);; # HANGUL SYLLABLE SSANGSIOS YEO SIOS +U+C3B4(2);; # HANGUL SYLLABLE SSANGSIOS YEO SSANGSIOS +U+C3B5(2);; # HANGUL SYLLABLE SSANGSIOS YEO IEUNG +U+C3B6(2);; # HANGUL SYLLABLE SSANGSIOS YEO CIEUC +U+C3B7(2);; # HANGUL SYLLABLE SSANGSIOS YEO CHIEUCH +U+C3B8(2);; # HANGUL SYLLABLE SSANGSIOS YEO KHIEUKH +U+C3B9(2);; # HANGUL SYLLABLE SSANGSIOS YEO THIEUTH +U+C3BA(2);; # HANGUL SYLLABLE SSANGSIOS YEO PHIEUPH +U+C3BB(2);; # HANGUL SYLLABLE SSANGSIOS YEO HIEUH +U+C3BC(2);; # HANGUL SYLLABLE SSANGSIOS YE +U+C3BD(2);; # HANGUL SYLLABLE SSANGSIOS YE KIYEOK +U+C3BE(2);; # HANGUL SYLLABLE SSANGSIOS YE SSANGKIYEOK +U+C3BF(2);; # HANGUL SYLLABLE SSANGSIOS YE KIYEOKSIOS +U+C3C0(2);; # HANGUL SYLLABLE SSANGSIOS YE NIEUN * +U+C3C1(2);; # HANGUL SYLLABLE SSANGSIOS YE NIEUNCIEUC +U+C3C2(2);; # HANGUL SYLLABLE SSANGSIOS YE NIEUNHIEUH +U+C3C3(2);; # HANGUL SYLLABLE SSANGSIOS YE TIKEUT +U+C3C4(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEUL +U+C3C5(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULKIYEOK +U+C3C6(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULMIEUM +U+C3C7(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULPIEUP +U+C3C8(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULSIOS +U+C3C9(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULTHIEUTH +U+C3CA(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULPHIEUPH +U+C3CB(2);; # HANGUL SYLLABLE SSANGSIOS YE RIEULHIEUH +U+C3CC(2);; # HANGUL SYLLABLE SSANGSIOS YE MIEUM +U+C3CD(2);; # HANGUL SYLLABLE SSANGSIOS YE PIEUP +U+C3CE(2);; # HANGUL SYLLABLE SSANGSIOS YE PIEUPSIOS +U+C3CF(2);; # HANGUL SYLLABLE SSANGSIOS YE SIOS +U+C3D0(2);; # HANGUL SYLLABLE SSANGSIOS YE SSANGSIOS +U+C3D1(2);; # HANGUL SYLLABLE SSANGSIOS YE IEUNG +U+C3D2(2);; # HANGUL SYLLABLE SSANGSIOS YE CIEUC +U+C3D3(2);; # HANGUL SYLLABLE SSANGSIOS YE CHIEUCH +U+C3D4(2);; # HANGUL SYLLABLE SSANGSIOS YE KHIEUKH +U+C3D5(2);; # HANGUL SYLLABLE SSANGSIOS YE THIEUTH +U+C3D6(2);; # HANGUL SYLLABLE SSANGSIOS YE PHIEUPH +U+C3D7(2);; # HANGUL SYLLABLE SSANGSIOS YE HIEUH +U+C3D8(2);; # HANGUL SYLLABLE SSANGSIOS O * +U+C3D9(2);; # HANGUL SYLLABLE SSANGSIOS O KIYEOK * +U+C3DA(2);; # HANGUL SYLLABLE SSANGSIOS O SSANGKIYEOK +U+C3DB(2);; # HANGUL SYLLABLE SSANGSIOS O KIYEOKSIOS +U+C3DC(2);; # HANGUL SYLLABLE SSANGSIOS O NIEUN * +U+C3DD(2);; # HANGUL SYLLABLE SSANGSIOS O NIEUNCIEUC +U+C3DE(2);; # HANGUL SYLLABLE SSANGSIOS O NIEUNHIEUH +U+C3DF(2);; # HANGUL SYLLABLE SSANGSIOS O TIKEUT * +U+C3E0(2);; # HANGUL SYLLABLE SSANGSIOS O RIEUL * +U+C3E1(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULKIYEOK +U+C3E2(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULMIEUM * +U+C3E3(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULPIEUP +U+C3E4(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULSIOS +U+C3E5(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULTHIEUTH +U+C3E6(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULPHIEUPH +U+C3E7(2);; # HANGUL SYLLABLE SSANGSIOS O RIEULHIEUH +U+C3E8(2);; # HANGUL SYLLABLE SSANGSIOS O MIEUM * +U+C3E9(2);; # HANGUL SYLLABLE SSANGSIOS O PIEUP * +U+C3EA(2);; # HANGUL SYLLABLE SSANGSIOS O PIEUPSIOS +U+C3EB(2);; # HANGUL SYLLABLE SSANGSIOS O SIOS +U+C3EC(2);; # HANGUL SYLLABLE SSANGSIOS O SSANGSIOS +U+C3ED(2);; # HANGUL SYLLABLE SSANGSIOS O IEUNG * +U+C3EE(2);; # HANGUL SYLLABLE SSANGSIOS O CIEUC +U+C3EF(2);; # HANGUL SYLLABLE SSANGSIOS O CHIEUCH +U+C3F0(2);; # HANGUL SYLLABLE SSANGSIOS O KHIEUKH +U+C3F1(2);; # HANGUL SYLLABLE SSANGSIOS O THIEUTH +U+C3F2(2);; # HANGUL SYLLABLE SSANGSIOS O PHIEUPH +U+C3F3(2);; # HANGUL SYLLABLE SSANGSIOS O HIEUH +U+C3F4(2);; # HANGUL SYLLABLE SSANGSIOS WA * +U+C3F5(2);; # HANGUL SYLLABLE SSANGSIOS WA KIYEOK * +U+C3F6(2);; # HANGUL SYLLABLE SSANGSIOS WA SSANGKIYEOK +U+C3F7(2);; # HANGUL SYLLABLE SSANGSIOS WA KIYEOKSIOS +U+C3F8(2);; # HANGUL SYLLABLE SSANGSIOS WA NIEUN * +U+C3F9(2);; # HANGUL SYLLABLE SSANGSIOS WA NIEUNCIEUC +U+C3FA(2);; # HANGUL SYLLABLE SSANGSIOS WA NIEUNHIEUH +U+C3FB(2);; # HANGUL SYLLABLE SSANGSIOS WA TIKEUT +U+C3FC(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEUL +U+C3FD(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULKIYEOK +U+C3FE(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULMIEUM +U+C3FF(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULPIEUP +U+C400(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULSIOS +U+C401(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULTHIEUTH +U+C402(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULPHIEUPH +U+C403(2);; # HANGUL SYLLABLE SSANGSIOS WA RIEULHIEUH +U+C404(2);; # HANGUL SYLLABLE SSANGSIOS WA MIEUM +U+C405(2);; # HANGUL SYLLABLE SSANGSIOS WA PIEUP +U+C406(2);; # HANGUL SYLLABLE SSANGSIOS WA PIEUPSIOS +U+C407(2);; # HANGUL SYLLABLE SSANGSIOS WA SIOS +U+C408(2);; # HANGUL SYLLABLE SSANGSIOS WA SSANGSIOS * +U+C409(2);; # HANGUL SYLLABLE SSANGSIOS WA IEUNG +U+C40A(2);; # HANGUL SYLLABLE SSANGSIOS WA CIEUC +U+C40B(2);; # HANGUL SYLLABLE SSANGSIOS WA CHIEUCH +U+C40C(2);; # HANGUL SYLLABLE SSANGSIOS WA KHIEUKH +U+C40D(2);; # HANGUL SYLLABLE SSANGSIOS WA THIEUTH +U+C40E(2);; # HANGUL SYLLABLE SSANGSIOS WA PHIEUPH +U+C40F(2);; # HANGUL SYLLABLE SSANGSIOS WA HIEUH +U+C410(2);; # HANGUL SYLLABLE SSANGSIOS WAE * +U+C411(2);; # HANGUL SYLLABLE SSANGSIOS WAE KIYEOK +U+C412(2);; # HANGUL SYLLABLE SSANGSIOS WAE SSANGKIYEOK +U+C413(2);; # HANGUL SYLLABLE SSANGSIOS WAE KIYEOKSIOS +U+C414(2);; # HANGUL SYLLABLE SSANGSIOS WAE NIEUN +U+C415(2);; # HANGUL SYLLABLE SSANGSIOS WAE NIEUNCIEUC +U+C416(2);; # HANGUL SYLLABLE SSANGSIOS WAE NIEUNHIEUH +U+C417(2);; # HANGUL SYLLABLE SSANGSIOS WAE TIKEUT +U+C418(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEUL +U+C419(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULKIYEOK +U+C41A(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULMIEUM +U+C41B(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULPIEUP +U+C41C(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULSIOS +U+C41D(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULTHIEUTH +U+C41E(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULPHIEUPH +U+C41F(2);; # HANGUL SYLLABLE SSANGSIOS WAE RIEULHIEUH +U+C420(2);; # HANGUL SYLLABLE SSANGSIOS WAE MIEUM +U+C421(2);; # HANGUL SYLLABLE SSANGSIOS WAE PIEUP +U+C422(2);; # HANGUL SYLLABLE SSANGSIOS WAE PIEUPSIOS +U+C423(2);; # HANGUL SYLLABLE SSANGSIOS WAE SIOS +U+C424(2);; # HANGUL SYLLABLE SSANGSIOS WAE SSANGSIOS * +U+C425(2);; # HANGUL SYLLABLE SSANGSIOS WAE IEUNG +U+C426(2);; # HANGUL SYLLABLE SSANGSIOS WAE CIEUC +U+C427(2);; # HANGUL SYLLABLE SSANGSIOS WAE CHIEUCH +U+C428(2);; # HANGUL SYLLABLE SSANGSIOS WAE KHIEUKH +U+C429(2);; # HANGUL SYLLABLE SSANGSIOS WAE THIEUTH +U+C42A(2);; # HANGUL SYLLABLE SSANGSIOS WAE PHIEUPH +U+C42B(2);; # HANGUL SYLLABLE SSANGSIOS WAE HIEUH +U+C42C(2);; # HANGUL SYLLABLE SSANGSIOS OE * +U+C42D(2);; # HANGUL SYLLABLE SSANGSIOS OE KIYEOK +U+C42E(2);; # HANGUL SYLLABLE SSANGSIOS OE SSANGKIYEOK +U+C42F(2);; # HANGUL SYLLABLE SSANGSIOS OE KIYEOKSIOS +U+C430(2);; # HANGUL SYLLABLE SSANGSIOS OE NIEUN * +U+C431(2);; # HANGUL SYLLABLE SSANGSIOS OE NIEUNCIEUC +U+C432(2);; # HANGUL SYLLABLE SSANGSIOS OE NIEUNHIEUH +U+C433(2);; # HANGUL SYLLABLE SSANGSIOS OE TIKEUT +U+C434(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEUL * +U+C435(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULKIYEOK +U+C436(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULMIEUM +U+C437(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULPIEUP +U+C438(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULSIOS +U+C439(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULTHIEUTH +U+C43A(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULPHIEUPH +U+C43B(2);; # HANGUL SYLLABLE SSANGSIOS OE RIEULHIEUH +U+C43C(2);; # HANGUL SYLLABLE SSANGSIOS OE MIEUM * +U+C43D(2);; # HANGUL SYLLABLE SSANGSIOS OE PIEUP * +U+C43E(2);; # HANGUL SYLLABLE SSANGSIOS OE PIEUPSIOS +U+C43F(2);; # HANGUL SYLLABLE SSANGSIOS OE SIOS +U+C440(2);; # HANGUL SYLLABLE SSANGSIOS OE SSANGSIOS +U+C441(2);; # HANGUL SYLLABLE SSANGSIOS OE IEUNG +U+C442(2);; # HANGUL SYLLABLE SSANGSIOS OE CIEUC +U+C443(2);; # HANGUL SYLLABLE SSANGSIOS OE CHIEUCH +U+C444(2);; # HANGUL SYLLABLE SSANGSIOS OE KHIEUKH +U+C445(2);; # HANGUL SYLLABLE SSANGSIOS OE THIEUTH +U+C446(2);; # HANGUL SYLLABLE SSANGSIOS OE PHIEUPH +U+C447(2);; # HANGUL SYLLABLE SSANGSIOS OE HIEUH +U+C448(2);; # HANGUL SYLLABLE SSANGSIOS YO * +U+C449(2);; # HANGUL SYLLABLE SSANGSIOS YO KIYEOK +U+C44A(2);; # HANGUL SYLLABLE SSANGSIOS YO SSANGKIYEOK +U+C44B(2);; # HANGUL SYLLABLE SSANGSIOS YO KIYEOKSIOS +U+C44C(2);; # HANGUL SYLLABLE SSANGSIOS YO NIEUN +U+C44D(2);; # HANGUL SYLLABLE SSANGSIOS YO NIEUNCIEUC +U+C44E(2);; # HANGUL SYLLABLE SSANGSIOS YO NIEUNHIEUH +U+C44F(2);; # HANGUL SYLLABLE SSANGSIOS YO TIKEUT +U+C450(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEUL +U+C451(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULKIYEOK +U+C452(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULMIEUM +U+C453(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULPIEUP +U+C454(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULSIOS +U+C455(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULTHIEUTH +U+C456(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULPHIEUPH +U+C457(2);; # HANGUL SYLLABLE SSANGSIOS YO RIEULHIEUH +U+C458(2);; # HANGUL SYLLABLE SSANGSIOS YO MIEUM +U+C459(2);; # HANGUL SYLLABLE SSANGSIOS YO PIEUP +U+C45A(2);; # HANGUL SYLLABLE SSANGSIOS YO PIEUPSIOS +U+C45B(2);; # HANGUL SYLLABLE SSANGSIOS YO SIOS +U+C45C(2);; # HANGUL SYLLABLE SSANGSIOS YO SSANGSIOS +U+C45D(2);; # HANGUL SYLLABLE SSANGSIOS YO IEUNG +U+C45E(2);; # HANGUL SYLLABLE SSANGSIOS YO CIEUC +U+C45F(2);; # HANGUL SYLLABLE SSANGSIOS YO CHIEUCH +U+C460(2);; # HANGUL SYLLABLE SSANGSIOS YO KHIEUKH +U+C461(2);; # HANGUL SYLLABLE SSANGSIOS YO THIEUTH +U+C462(2);; # HANGUL SYLLABLE SSANGSIOS YO PHIEUPH +U+C463(2);; # HANGUL SYLLABLE SSANGSIOS YO HIEUH +U+C464(2);; # HANGUL SYLLABLE SSANGSIOS U * +U+C465(2);; # HANGUL SYLLABLE SSANGSIOS U KIYEOK * +U+C466(2);; # HANGUL SYLLABLE SSANGSIOS U SSANGKIYEOK +U+C467(2);; # HANGUL SYLLABLE SSANGSIOS U KIYEOKSIOS +U+C468(2);; # HANGUL SYLLABLE SSANGSIOS U NIEUN * +U+C469(2);; # HANGUL SYLLABLE SSANGSIOS U NIEUNCIEUC +U+C46A(2);; # HANGUL SYLLABLE SSANGSIOS U NIEUNHIEUH +U+C46B(2);; # HANGUL SYLLABLE SSANGSIOS U TIKEUT +U+C46C(2);; # HANGUL SYLLABLE SSANGSIOS U RIEUL * +U+C46D(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULKIYEOK +U+C46E(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULMIEUM +U+C46F(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULPIEUP +U+C470(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULSIOS +U+C471(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULTHIEUTH +U+C472(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULPHIEUPH +U+C473(2);; # HANGUL SYLLABLE SSANGSIOS U RIEULHIEUH +U+C474(2);; # HANGUL SYLLABLE SSANGSIOS U MIEUM * +U+C475(2);; # HANGUL SYLLABLE SSANGSIOS U PIEUP * +U+C476(2);; # HANGUL SYLLABLE SSANGSIOS U PIEUPSIOS +U+C477(2);; # HANGUL SYLLABLE SSANGSIOS U SIOS +U+C478(2);; # HANGUL SYLLABLE SSANGSIOS U SSANGSIOS +U+C479(2);; # HANGUL SYLLABLE SSANGSIOS U IEUNG * +U+C47A(2);; # HANGUL SYLLABLE SSANGSIOS U CIEUC +U+C47B(2);; # HANGUL SYLLABLE SSANGSIOS U CHIEUCH +U+C47C(2);; # HANGUL SYLLABLE SSANGSIOS U KHIEUKH +U+C47D(2);; # HANGUL SYLLABLE SSANGSIOS U THIEUTH +U+C47E(2);; # HANGUL SYLLABLE SSANGSIOS U PHIEUPH +U+C47F(2);; # HANGUL SYLLABLE SSANGSIOS U HIEUH +U+C480(2);; # HANGUL SYLLABLE SSANGSIOS WEO * +U+C481(2);; # HANGUL SYLLABLE SSANGSIOS WEO KIYEOK +U+C482(2);; # HANGUL SYLLABLE SSANGSIOS WEO SSANGKIYEOK +U+C483(2);; # HANGUL SYLLABLE SSANGSIOS WEO KIYEOKSIOS +U+C484(2);; # HANGUL SYLLABLE SSANGSIOS WEO NIEUN +U+C485(2);; # HANGUL SYLLABLE SSANGSIOS WEO NIEUNCIEUC +U+C486(2);; # HANGUL SYLLABLE SSANGSIOS WEO NIEUNHIEUH +U+C487(2);; # HANGUL SYLLABLE SSANGSIOS WEO TIKEUT +U+C488(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEUL +U+C489(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULKIYEOK +U+C48A(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULMIEUM +U+C48B(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULPIEUP +U+C48C(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULSIOS +U+C48D(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULTHIEUTH +U+C48E(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULPHIEUPH +U+C48F(2);; # HANGUL SYLLABLE SSANGSIOS WEO RIEULHIEUH +U+C490(2);; # HANGUL SYLLABLE SSANGSIOS WEO MIEUM +U+C491(2);; # HANGUL SYLLABLE SSANGSIOS WEO PIEUP +U+C492(2);; # HANGUL SYLLABLE SSANGSIOS WEO PIEUPSIOS +U+C493(2);; # HANGUL SYLLABLE SSANGSIOS WEO SIOS +U+C494(2);; # HANGUL SYLLABLE SSANGSIOS WEO SSANGSIOS * +U+C495(2);; # HANGUL SYLLABLE SSANGSIOS WEO IEUNG +U+C496(2);; # HANGUL SYLLABLE SSANGSIOS WEO CIEUC +U+C497(2);; # HANGUL SYLLABLE SSANGSIOS WEO CHIEUCH +U+C498(2);; # HANGUL SYLLABLE SSANGSIOS WEO KHIEUKH +U+C499(2);; # HANGUL SYLLABLE SSANGSIOS WEO THIEUTH +U+C49A(2);; # HANGUL SYLLABLE SSANGSIOS WEO PHIEUPH +U+C49B(2);; # HANGUL SYLLABLE SSANGSIOS WEO HIEUH +U+C49C(2);; # HANGUL SYLLABLE SSANGSIOS WE * +U+C49D(2);; # HANGUL SYLLABLE SSANGSIOS WE KIYEOK +U+C49E(2);; # HANGUL SYLLABLE SSANGSIOS WE SSANGKIYEOK +U+C49F(2);; # HANGUL SYLLABLE SSANGSIOS WE KIYEOKSIOS +U+C4A0(2);; # HANGUL SYLLABLE SSANGSIOS WE NIEUN +U+C4A1(2);; # HANGUL SYLLABLE SSANGSIOS WE NIEUNCIEUC +U+C4A2(2);; # HANGUL SYLLABLE SSANGSIOS WE NIEUNHIEUH +U+C4A3(2);; # HANGUL SYLLABLE SSANGSIOS WE TIKEUT +U+C4A4(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEUL +U+C4A5(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULKIYEOK +U+C4A6(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULMIEUM +U+C4A7(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULPIEUP +U+C4A8(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULSIOS +U+C4A9(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULTHIEUTH +U+C4AA(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULPHIEUPH +U+C4AB(2);; # HANGUL SYLLABLE SSANGSIOS WE RIEULHIEUH +U+C4AC(2);; # HANGUL SYLLABLE SSANGSIOS WE MIEUM +U+C4AD(2);; # HANGUL SYLLABLE SSANGSIOS WE PIEUP +U+C4AE(2);; # HANGUL SYLLABLE SSANGSIOS WE PIEUPSIOS +U+C4AF(2);; # HANGUL SYLLABLE SSANGSIOS WE SIOS +U+C4B0(2);; # HANGUL SYLLABLE SSANGSIOS WE SSANGSIOS +U+C4B1(2);; # HANGUL SYLLABLE SSANGSIOS WE IEUNG +U+C4B2(2);; # HANGUL SYLLABLE SSANGSIOS WE CIEUC +U+C4B3(2);; # HANGUL SYLLABLE SSANGSIOS WE CHIEUCH +U+C4B4(2);; # HANGUL SYLLABLE SSANGSIOS WE KHIEUKH +U+C4B5(2);; # HANGUL SYLLABLE SSANGSIOS WE THIEUTH +U+C4B6(2);; # HANGUL SYLLABLE SSANGSIOS WE PHIEUPH +U+C4B7(2);; # HANGUL SYLLABLE SSANGSIOS WE HIEUH +U+C4B8(2);; # HANGUL SYLLABLE SSANGSIOS WI * +U+C4B9(2);; # HANGUL SYLLABLE SSANGSIOS WI KIYEOK +U+C4BA(2);; # HANGUL SYLLABLE SSANGSIOS WI SSANGKIYEOK +U+C4BB(2);; # HANGUL SYLLABLE SSANGSIOS WI KIYEOKSIOS +U+C4BC(2);; # HANGUL SYLLABLE SSANGSIOS WI NIEUN * +U+C4BD(2);; # HANGUL SYLLABLE SSANGSIOS WI NIEUNCIEUC +U+C4BE(2);; # HANGUL SYLLABLE SSANGSIOS WI NIEUNHIEUH +U+C4BF(2);; # HANGUL SYLLABLE SSANGSIOS WI TIKEUT +U+C4C0(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEUL +U+C4C1(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULKIYEOK +U+C4C2(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULMIEUM +U+C4C3(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULPIEUP +U+C4C4(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULSIOS +U+C4C5(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULTHIEUTH +U+C4C6(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULPHIEUPH +U+C4C7(2);; # HANGUL SYLLABLE SSANGSIOS WI RIEULHIEUH +U+C4C8(2);; # HANGUL SYLLABLE SSANGSIOS WI MIEUM +U+C4C9(2);; # HANGUL SYLLABLE SSANGSIOS WI PIEUP +U+C4CA(2);; # HANGUL SYLLABLE SSANGSIOS WI PIEUPSIOS +U+C4CB(2);; # HANGUL SYLLABLE SSANGSIOS WI SIOS +U+C4CC(2);; # HANGUL SYLLABLE SSANGSIOS WI SSANGSIOS +U+C4CD(2);; # HANGUL SYLLABLE SSANGSIOS WI IEUNG +U+C4CE(2);; # HANGUL SYLLABLE SSANGSIOS WI CIEUC +U+C4CF(2);; # HANGUL SYLLABLE SSANGSIOS WI CHIEUCH +U+C4D0(2);; # HANGUL SYLLABLE SSANGSIOS WI KHIEUKH +U+C4D1(2);; # HANGUL SYLLABLE SSANGSIOS WI THIEUTH +U+C4D2(2);; # HANGUL SYLLABLE SSANGSIOS WI PHIEUPH +U+C4D3(2);; # HANGUL SYLLABLE SSANGSIOS WI HIEUH +U+C4D4(2);; # HANGUL SYLLABLE SSANGSIOS YU +U+C4D5(2);; # HANGUL SYLLABLE SSANGSIOS YU KIYEOK +U+C4D6(2);; # HANGUL SYLLABLE SSANGSIOS YU SSANGKIYEOK +U+C4D7(2);; # HANGUL SYLLABLE SSANGSIOS YU KIYEOKSIOS +U+C4D8(2);; # HANGUL SYLLABLE SSANGSIOS YU NIEUN +U+C4D9(2);; # HANGUL SYLLABLE SSANGSIOS YU NIEUNCIEUC +U+C4DA(2);; # HANGUL SYLLABLE SSANGSIOS YU NIEUNHIEUH +U+C4DB(2);; # HANGUL SYLLABLE SSANGSIOS YU TIKEUT +U+C4DC(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEUL +U+C4DD(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULKIYEOK +U+C4DE(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULMIEUM +U+C4DF(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULPIEUP +U+C4E0(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULSIOS +U+C4E1(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULTHIEUTH +U+C4E2(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULPHIEUPH +U+C4E3(2);; # HANGUL SYLLABLE SSANGSIOS YU RIEULHIEUH +U+C4E4(2);; # HANGUL SYLLABLE SSANGSIOS YU MIEUM +U+C4E5(2);; # HANGUL SYLLABLE SSANGSIOS YU PIEUP +U+C4E6(2);; # HANGUL SYLLABLE SSANGSIOS YU PIEUPSIOS +U+C4E7(2);; # HANGUL SYLLABLE SSANGSIOS YU SIOS +U+C4E8(2);; # HANGUL SYLLABLE SSANGSIOS YU SSANGSIOS +U+C4E9(2);; # HANGUL SYLLABLE SSANGSIOS YU IEUNG * +U+C4EA(2);; # HANGUL SYLLABLE SSANGSIOS YU CIEUC +U+C4EB(2);; # HANGUL SYLLABLE SSANGSIOS YU CHIEUCH +U+C4EC(2);; # HANGUL SYLLABLE SSANGSIOS YU KHIEUKH +U+C4ED(2);; # HANGUL SYLLABLE SSANGSIOS YU THIEUTH +U+C4EE(2);; # HANGUL SYLLABLE SSANGSIOS YU PHIEUPH +U+C4EF(2);; # HANGUL SYLLABLE SSANGSIOS YU HIEUH +U+C4F0(2);; # HANGUL SYLLABLE SSANGSIOS EU * +U+C4F1(2);; # HANGUL SYLLABLE SSANGSIOS EU KIYEOK * +U+C4F2(2);; # HANGUL SYLLABLE SSANGSIOS EU SSANGKIYEOK +U+C4F3(2);; # HANGUL SYLLABLE SSANGSIOS EU KIYEOKSIOS +U+C4F4(2);; # HANGUL SYLLABLE SSANGSIOS EU NIEUN * +U+C4F5(2);; # HANGUL SYLLABLE SSANGSIOS EU NIEUNCIEUC +U+C4F6(2);; # HANGUL SYLLABLE SSANGSIOS EU NIEUNHIEUH +U+C4F7(2);; # HANGUL SYLLABLE SSANGSIOS EU TIKEUT +U+C4F8(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEUL * +U+C4F9(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULKIYEOK +U+C4FA(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULMIEUM * +U+C4FB(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULPIEUP +U+C4FC(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULSIOS +U+C4FD(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULTHIEUTH +U+C4FE(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULPHIEUPH +U+C4FF(2);; # HANGUL SYLLABLE SSANGSIOS EU RIEULHIEUH * +U+C500(2);; # HANGUL SYLLABLE SSANGSIOS EU MIEUM * +U+C501(2);; # HANGUL SYLLABLE SSANGSIOS EU PIEUP * +U+C502(2);; # HANGUL SYLLABLE SSANGSIOS EU PIEUPSIOS +U+C503(2);; # HANGUL SYLLABLE SSANGSIOS EU SIOS +U+C504(2);; # HANGUL SYLLABLE SSANGSIOS EU SSANGSIOS +U+C505(2);; # HANGUL SYLLABLE SSANGSIOS EU IEUNG +U+C506(2);; # HANGUL SYLLABLE SSANGSIOS EU CIEUC +U+C507(2);; # HANGUL SYLLABLE SSANGSIOS EU CHIEUCH +U+C508(2);; # HANGUL SYLLABLE SSANGSIOS EU KHIEUKH +U+C509(2);; # HANGUL SYLLABLE SSANGSIOS EU THIEUTH +U+C50A(2);; # HANGUL SYLLABLE SSANGSIOS EU PHIEUPH +U+C50B(2);; # HANGUL SYLLABLE SSANGSIOS EU HIEUH +U+C50C(2);; # HANGUL SYLLABLE SSANGSIOS YI * +U+C50D(2);; # HANGUL SYLLABLE SSANGSIOS YI KIYEOK +U+C50E(2);; # HANGUL SYLLABLE SSANGSIOS YI SSANGKIYEOK +U+C50F(2);; # HANGUL SYLLABLE SSANGSIOS YI KIYEOKSIOS +U+C510(2);; # HANGUL SYLLABLE SSANGSIOS YI NIEUN * +U+C511(2);; # HANGUL SYLLABLE SSANGSIOS YI NIEUNCIEUC +U+C512(2);; # HANGUL SYLLABLE SSANGSIOS YI NIEUNHIEUH +U+C513(2);; # HANGUL SYLLABLE SSANGSIOS YI TIKEUT +U+C514(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEUL * +U+C515(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULKIYEOK +U+C516(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULMIEUM +U+C517(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULPIEUP +U+C518(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULSIOS +U+C519(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULTHIEUTH +U+C51A(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULPHIEUPH +U+C51B(2);; # HANGUL SYLLABLE SSANGSIOS YI RIEULHIEUH +U+C51C(2);; # HANGUL SYLLABLE SSANGSIOS YI MIEUM * +U+C51D(2);; # HANGUL SYLLABLE SSANGSIOS YI PIEUP +U+C51E(2);; # HANGUL SYLLABLE SSANGSIOS YI PIEUPSIOS +U+C51F(2);; # HANGUL SYLLABLE SSANGSIOS YI SIOS +U+C520(2);; # HANGUL SYLLABLE SSANGSIOS YI SSANGSIOS +U+C521(2);; # HANGUL SYLLABLE SSANGSIOS YI IEUNG +U+C522(2);; # HANGUL SYLLABLE SSANGSIOS YI CIEUC +U+C523(2);; # HANGUL SYLLABLE SSANGSIOS YI CHIEUCH +U+C524(2);; # HANGUL SYLLABLE SSANGSIOS YI KHIEUKH +U+C525(2);; # HANGUL SYLLABLE SSANGSIOS YI THIEUTH +U+C526(2);; # HANGUL SYLLABLE SSANGSIOS YI PHIEUPH +U+C527(2);; # HANGUL SYLLABLE SSANGSIOS YI HIEUH +U+C528(2);; # HANGUL SYLLABLE SSANGSIOS I * +U+C529(2);; # HANGUL SYLLABLE SSANGSIOS I KIYEOK * +U+C52A(2);; # HANGUL SYLLABLE SSANGSIOS I SSANGKIYEOK +U+C52B(2);; # HANGUL SYLLABLE SSANGSIOS I KIYEOKSIOS +U+C52C(2);; # HANGUL SYLLABLE SSANGSIOS I NIEUN * +U+C52D(2);; # HANGUL SYLLABLE SSANGSIOS I NIEUNCIEUC +U+C52E(2);; # HANGUL SYLLABLE SSANGSIOS I NIEUNHIEUH +U+C52F(2);; # HANGUL SYLLABLE SSANGSIOS I TIKEUT +U+C530(2);; # HANGUL SYLLABLE SSANGSIOS I RIEUL * +U+C531(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULKIYEOK +U+C532(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULMIEUM +U+C533(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULPIEUP +U+C534(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULSIOS +U+C535(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULTHIEUTH +U+C536(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULPHIEUPH +U+C537(2);; # HANGUL SYLLABLE SSANGSIOS I RIEULHIEUH +U+C538(2);; # HANGUL SYLLABLE SSANGSIOS I MIEUM * +U+C539(2);; # HANGUL SYLLABLE SSANGSIOS I PIEUP * +U+C53A(2);; # HANGUL SYLLABLE SSANGSIOS I PIEUPSIOS +U+C53B(2);; # HANGUL SYLLABLE SSANGSIOS I SIOS * +U+C53C(2);; # HANGUL SYLLABLE SSANGSIOS I SSANGSIOS +U+C53D(2);; # HANGUL SYLLABLE SSANGSIOS I IEUNG * +U+C53E(2);; # HANGUL SYLLABLE SSANGSIOS I CIEUC +U+C53F(2);; # HANGUL SYLLABLE SSANGSIOS I CHIEUCH +U+C540(2);; # HANGUL SYLLABLE SSANGSIOS I KHIEUKH +U+C541(2);; # HANGUL SYLLABLE SSANGSIOS I THIEUTH +U+C542(2);; # HANGUL SYLLABLE SSANGSIOS I PHIEUPH +U+C543(2);; # HANGUL SYLLABLE SSANGSIOS I HIEUH +U+C544(2);; # HANGUL SYLLABLE IEUNG A * +U+C545(2);; # HANGUL SYLLABLE IEUNG A KIYEOK * +U+C546(2);; # HANGUL SYLLABLE IEUNG A SSANGKIYEOK +U+C547(2);; # HANGUL SYLLABLE IEUNG A KIYEOKSIOS +U+C548(2);; # HANGUL SYLLABLE IEUNG A NIEUN * +U+C549(2);; # HANGUL SYLLABLE IEUNG A NIEUNCIEUC * +U+C54A(2);; # HANGUL SYLLABLE IEUNG A NIEUNHIEUH * +U+C54B(2);; # HANGUL SYLLABLE IEUNG A TIKEUT +U+C54C(2);; # HANGUL SYLLABLE IEUNG A RIEUL * +U+C54D(2);; # HANGUL SYLLABLE IEUNG A RIEULKIYEOK * +U+C54E(2);; # HANGUL SYLLABLE IEUNG A RIEULMIEUM * +U+C54F(2);; # HANGUL SYLLABLE IEUNG A RIEULPIEUP +U+C550(2);; # HANGUL SYLLABLE IEUNG A RIEULSIOS +U+C551(2);; # HANGUL SYLLABLE IEUNG A RIEULTHIEUTH +U+C552(2);; # HANGUL SYLLABLE IEUNG A RIEULPHIEUPH +U+C553(2);; # HANGUL SYLLABLE IEUNG A RIEULHIEUH * +U+C554(2);; # HANGUL SYLLABLE IEUNG A MIEUM * +U+C555(2);; # HANGUL SYLLABLE IEUNG A PIEUP * +U+C556(2);; # HANGUL SYLLABLE IEUNG A PIEUPSIOS +U+C557(2);; # HANGUL SYLLABLE IEUNG A SIOS * +U+C558(2);; # HANGUL SYLLABLE IEUNG A SSANGSIOS * +U+C559(2);; # HANGUL SYLLABLE IEUNG A IEUNG * +U+C55A(2);; # HANGUL SYLLABLE IEUNG A CIEUC +U+C55B(2);; # HANGUL SYLLABLE IEUNG A CHIEUCH +U+C55C(2);; # HANGUL SYLLABLE IEUNG A KHIEUKH +U+C55D(2);; # HANGUL SYLLABLE IEUNG A THIEUTH * +U+C55E(2);; # HANGUL SYLLABLE IEUNG A PHIEUPH * +U+C55F(2);; # HANGUL SYLLABLE IEUNG A HIEUH +U+C560(2);; # HANGUL SYLLABLE IEUNG AE * +U+C561(2);; # HANGUL SYLLABLE IEUNG AE KIYEOK * +U+C562(2);; # HANGUL SYLLABLE IEUNG AE SSANGKIYEOK +U+C563(2);; # HANGUL SYLLABLE IEUNG AE KIYEOKSIOS +U+C564(2);; # HANGUL SYLLABLE IEUNG AE NIEUN * +U+C565(2);; # HANGUL SYLLABLE IEUNG AE NIEUNCIEUC +U+C566(2);; # HANGUL SYLLABLE IEUNG AE NIEUNHIEUH +U+C567(2);; # HANGUL SYLLABLE IEUNG AE TIKEUT +U+C568(2);; # HANGUL SYLLABLE IEUNG AE RIEUL * +U+C569(2);; # HANGUL SYLLABLE IEUNG AE RIEULKIYEOK +U+C56A(2);; # HANGUL SYLLABLE IEUNG AE RIEULMIEUM +U+C56B(2);; # HANGUL SYLLABLE IEUNG AE RIEULPIEUP +U+C56C(2);; # HANGUL SYLLABLE IEUNG AE RIEULSIOS +U+C56D(2);; # HANGUL SYLLABLE IEUNG AE RIEULTHIEUTH +U+C56E(2);; # HANGUL SYLLABLE IEUNG AE RIEULPHIEUPH +U+C56F(2);; # HANGUL SYLLABLE IEUNG AE RIEULHIEUH +U+C570(2);; # HANGUL SYLLABLE IEUNG AE MIEUM * +U+C571(2);; # HANGUL SYLLABLE IEUNG AE PIEUP * +U+C572(2);; # HANGUL SYLLABLE IEUNG AE PIEUPSIOS +U+C573(2);; # HANGUL SYLLABLE IEUNG AE SIOS * +U+C574(2);; # HANGUL SYLLABLE IEUNG AE SSANGSIOS * +U+C575(2);; # HANGUL SYLLABLE IEUNG AE IEUNG * +U+C576(2);; # HANGUL SYLLABLE IEUNG AE CIEUC +U+C577(2);; # HANGUL SYLLABLE IEUNG AE CHIEUCH +U+C578(2);; # HANGUL SYLLABLE IEUNG AE KHIEUKH +U+C579(2);; # HANGUL SYLLABLE IEUNG AE THIEUTH +U+C57A(2);; # HANGUL SYLLABLE IEUNG AE PHIEUPH +U+C57B(2);; # HANGUL SYLLABLE IEUNG AE HIEUH +U+C57C(2);; # HANGUL SYLLABLE IEUNG YA * +U+C57D(2);; # HANGUL SYLLABLE IEUNG YA KIYEOK * +U+C57E(2);; # HANGUL SYLLABLE IEUNG YA SSANGKIYEOK +U+C57F(2);; # HANGUL SYLLABLE IEUNG YA KIYEOKSIOS +U+C580(2);; # HANGUL SYLLABLE IEUNG YA NIEUN * +U+C581(2);; # HANGUL SYLLABLE IEUNG YA NIEUNCIEUC +U+C582(2);; # HANGUL SYLLABLE IEUNG YA NIEUNHIEUH +U+C583(2);; # HANGUL SYLLABLE IEUNG YA TIKEUT +U+C584(2);; # HANGUL SYLLABLE IEUNG YA RIEUL * +U+C585(2);; # HANGUL SYLLABLE IEUNG YA RIEULKIYEOK +U+C586(2);; # HANGUL SYLLABLE IEUNG YA RIEULMIEUM +U+C587(2);; # HANGUL SYLLABLE IEUNG YA RIEULPIEUP * +U+C588(2);; # HANGUL SYLLABLE IEUNG YA RIEULSIOS +U+C589(2);; # HANGUL SYLLABLE IEUNG YA RIEULTHIEUTH +U+C58A(2);; # HANGUL SYLLABLE IEUNG YA RIEULPHIEUPH +U+C58B(2);; # HANGUL SYLLABLE IEUNG YA RIEULHIEUH +U+C58C(2);; # HANGUL SYLLABLE IEUNG YA MIEUM * +U+C58D(2);; # HANGUL SYLLABLE IEUNG YA PIEUP * +U+C58E(2);; # HANGUL SYLLABLE IEUNG YA PIEUPSIOS +U+C58F(2);; # HANGUL SYLLABLE IEUNG YA SIOS * +U+C590(2);; # HANGUL SYLLABLE IEUNG YA SSANGSIOS +U+C591(2);; # HANGUL SYLLABLE IEUNG YA IEUNG * +U+C592(2);; # HANGUL SYLLABLE IEUNG YA CIEUC +U+C593(2);; # HANGUL SYLLABLE IEUNG YA CHIEUCH +U+C594(2);; # HANGUL SYLLABLE IEUNG YA KHIEUKH +U+C595(2);; # HANGUL SYLLABLE IEUNG YA THIEUTH * +U+C596(2);; # HANGUL SYLLABLE IEUNG YA PHIEUPH +U+C597(2);; # HANGUL SYLLABLE IEUNG YA HIEUH * +U+C598(2);; # HANGUL SYLLABLE IEUNG YAE * +U+C599(2);; # HANGUL SYLLABLE IEUNG YAE KIYEOK +U+C59A(2);; # HANGUL SYLLABLE IEUNG YAE SSANGKIYEOK +U+C59B(2);; # HANGUL SYLLABLE IEUNG YAE KIYEOKSIOS +U+C59C(2);; # HANGUL SYLLABLE IEUNG YAE NIEUN * +U+C59D(2);; # HANGUL SYLLABLE IEUNG YAE NIEUNCIEUC +U+C59E(2);; # HANGUL SYLLABLE IEUNG YAE NIEUNHIEUH +U+C59F(2);; # HANGUL SYLLABLE IEUNG YAE TIKEUT +U+C5A0(2);; # HANGUL SYLLABLE IEUNG YAE RIEUL * +U+C5A1(2);; # HANGUL SYLLABLE IEUNG YAE RIEULKIYEOK +U+C5A2(2);; # HANGUL SYLLABLE IEUNG YAE RIEULMIEUM +U+C5A3(2);; # HANGUL SYLLABLE IEUNG YAE RIEULPIEUP +U+C5A4(2);; # HANGUL SYLLABLE IEUNG YAE RIEULSIOS +U+C5A5(2);; # HANGUL SYLLABLE IEUNG YAE RIEULTHIEUTH +U+C5A6(2);; # HANGUL SYLLABLE IEUNG YAE RIEULPHIEUPH +U+C5A7(2);; # HANGUL SYLLABLE IEUNG YAE RIEULHIEUH +U+C5A8(2);; # HANGUL SYLLABLE IEUNG YAE MIEUM +U+C5A9(2);; # HANGUL SYLLABLE IEUNG YAE PIEUP * +U+C5AA(2);; # HANGUL SYLLABLE IEUNG YAE PIEUPSIOS +U+C5AB(2);; # HANGUL SYLLABLE IEUNG YAE SIOS +U+C5AC(2);; # HANGUL SYLLABLE IEUNG YAE SSANGSIOS +U+C5AD(2);; # HANGUL SYLLABLE IEUNG YAE IEUNG +U+C5AE(2);; # HANGUL SYLLABLE IEUNG YAE CIEUC +U+C5AF(2);; # HANGUL SYLLABLE IEUNG YAE CHIEUCH +U+C5B0(2);; # HANGUL SYLLABLE IEUNG YAE KHIEUKH +U+C5B1(2);; # HANGUL SYLLABLE IEUNG YAE THIEUTH +U+C5B2(2);; # HANGUL SYLLABLE IEUNG YAE PHIEUPH +U+C5B3(2);; # HANGUL SYLLABLE IEUNG YAE HIEUH +U+C5B4(2);; # HANGUL SYLLABLE IEUNG EO * +U+C5B5(2);; # HANGUL SYLLABLE IEUNG EO KIYEOK * +U+C5B6(2);; # HANGUL SYLLABLE IEUNG EO SSANGKIYEOK +U+C5B7(2);; # HANGUL SYLLABLE IEUNG EO KIYEOKSIOS +U+C5B8(2);; # HANGUL SYLLABLE IEUNG EO NIEUN * +U+C5B9(2);; # HANGUL SYLLABLE IEUNG EO NIEUNCIEUC * +U+C5BA(2);; # HANGUL SYLLABLE IEUNG EO NIEUNHIEUH +U+C5BB(2);; # HANGUL SYLLABLE IEUNG EO TIKEUT * +U+C5BC(2);; # HANGUL SYLLABLE IEUNG EO RIEUL * +U+C5BD(2);; # HANGUL SYLLABLE IEUNG EO RIEULKIYEOK * +U+C5BE(2);; # HANGUL SYLLABLE IEUNG EO RIEULMIEUM * +U+C5BF(2);; # HANGUL SYLLABLE IEUNG EO RIEULPIEUP +U+C5C0(2);; # HANGUL SYLLABLE IEUNG EO RIEULSIOS +U+C5C1(2);; # HANGUL SYLLABLE IEUNG EO RIEULTHIEUTH +U+C5C2(2);; # HANGUL SYLLABLE IEUNG EO RIEULPHIEUPH +U+C5C3(2);; # HANGUL SYLLABLE IEUNG EO RIEULHIEUH +U+C5C4(2);; # HANGUL SYLLABLE IEUNG EO MIEUM * +U+C5C5(2);; # HANGUL SYLLABLE IEUNG EO PIEUP * +U+C5C6(2);; # HANGUL SYLLABLE IEUNG EO PIEUPSIOS * +U+C5C7(2);; # HANGUL SYLLABLE IEUNG EO SIOS * +U+C5C8(2);; # HANGUL SYLLABLE IEUNG EO SSANGSIOS * +U+C5C9(2);; # HANGUL SYLLABLE IEUNG EO IEUNG * +U+C5CA(2);; # HANGUL SYLLABLE IEUNG EO CIEUC * +U+C5CB(2);; # HANGUL SYLLABLE IEUNG EO CHIEUCH +U+C5CC(2);; # HANGUL SYLLABLE IEUNG EO KHIEUKH * +U+C5CD(2);; # HANGUL SYLLABLE IEUNG EO THIEUTH +U+C5CE(2);; # HANGUL SYLLABLE IEUNG EO PHIEUPH * +U+C5CF(2);; # HANGUL SYLLABLE IEUNG EO HIEUH +U+C5D0(2);; # HANGUL SYLLABLE IEUNG E * +U+C5D1(2);; # HANGUL SYLLABLE IEUNG E KIYEOK * +U+C5D2(2);; # HANGUL SYLLABLE IEUNG E SSANGKIYEOK +U+C5D3(2);; # HANGUL SYLLABLE IEUNG E KIYEOKSIOS +U+C5D4(2);; # HANGUL SYLLABLE IEUNG E NIEUN * +U+C5D5(2);; # HANGUL SYLLABLE IEUNG E NIEUNCIEUC +U+C5D6(2);; # HANGUL SYLLABLE IEUNG E NIEUNHIEUH +U+C5D7(2);; # HANGUL SYLLABLE IEUNG E TIKEUT +U+C5D8(2);; # HANGUL SYLLABLE IEUNG E RIEUL * +U+C5D9(2);; # HANGUL SYLLABLE IEUNG E RIEULKIYEOK +U+C5DA(2);; # HANGUL SYLLABLE IEUNG E RIEULMIEUM +U+C5DB(2);; # HANGUL SYLLABLE IEUNG E RIEULPIEUP +U+C5DC(2);; # HANGUL SYLLABLE IEUNG E RIEULSIOS +U+C5DD(2);; # HANGUL SYLLABLE IEUNG E RIEULTHIEUTH +U+C5DE(2);; # HANGUL SYLLABLE IEUNG E RIEULPHIEUPH +U+C5DF(2);; # HANGUL SYLLABLE IEUNG E RIEULHIEUH +U+C5E0(2);; # HANGUL SYLLABLE IEUNG E MIEUM * +U+C5E1(2);; # HANGUL SYLLABLE IEUNG E PIEUP * +U+C5E2(2);; # HANGUL SYLLABLE IEUNG E PIEUPSIOS +U+C5E3(2);; # HANGUL SYLLABLE IEUNG E SIOS * +U+C5E4(2);; # HANGUL SYLLABLE IEUNG E SSANGSIOS +U+C5E5(2);; # HANGUL SYLLABLE IEUNG E IEUNG * +U+C5E6(2);; # HANGUL SYLLABLE IEUNG E CIEUC +U+C5E7(2);; # HANGUL SYLLABLE IEUNG E CHIEUCH +U+C5E8(2);; # HANGUL SYLLABLE IEUNG E KHIEUKH +U+C5E9(2);; # HANGUL SYLLABLE IEUNG E THIEUTH +U+C5EA(2);; # HANGUL SYLLABLE IEUNG E PHIEUPH +U+C5EB(2);; # HANGUL SYLLABLE IEUNG E HIEUH +U+C5EC(2);; # HANGUL SYLLABLE IEUNG YEO * +U+C5ED(2);; # HANGUL SYLLABLE IEUNG YEO KIYEOK * +U+C5EE(2);; # HANGUL SYLLABLE IEUNG YEO SSANGKIYEOK * +U+C5EF(2);; # HANGUL SYLLABLE IEUNG YEO KIYEOKSIOS +U+C5F0(2);; # HANGUL SYLLABLE IEUNG YEO NIEUN * +U+C5F1(2);; # HANGUL SYLLABLE IEUNG YEO NIEUNCIEUC +U+C5F2(2);; # HANGUL SYLLABLE IEUNG YEO NIEUNHIEUH +U+C5F3(2);; # HANGUL SYLLABLE IEUNG YEO TIKEUT +U+C5F4(2);; # HANGUL SYLLABLE IEUNG YEO RIEUL * +U+C5F5(2);; # HANGUL SYLLABLE IEUNG YEO RIEULKIYEOK +U+C5F6(2);; # HANGUL SYLLABLE IEUNG YEO RIEULMIEUM * +U+C5F7(2);; # HANGUL SYLLABLE IEUNG YEO RIEULPIEUP * +U+C5F8(2);; # HANGUL SYLLABLE IEUNG YEO RIEULSIOS +U+C5F9(2);; # HANGUL SYLLABLE IEUNG YEO RIEULTHIEUTH +U+C5FA(2);; # HANGUL SYLLABLE IEUNG YEO RIEULPHIEUPH +U+C5FB(2);; # HANGUL SYLLABLE IEUNG YEO RIEULHIEUH +U+C5FC(2);; # HANGUL SYLLABLE IEUNG YEO MIEUM * +U+C5FD(2);; # HANGUL SYLLABLE IEUNG YEO PIEUP * +U+C5FE(2);; # HANGUL SYLLABLE IEUNG YEO PIEUPSIOS * +U+C5FF(2);; # HANGUL SYLLABLE IEUNG YEO SIOS * +U+C600(2);; # HANGUL SYLLABLE IEUNG YEO SSANGSIOS * +U+C601(2);; # HANGUL SYLLABLE IEUNG YEO IEUNG * +U+C602(2);; # HANGUL SYLLABLE IEUNG YEO CIEUC +U+C603(2);; # HANGUL SYLLABLE IEUNG YEO CHIEUCH +U+C604(2);; # HANGUL SYLLABLE IEUNG YEO KHIEUKH +U+C605(2);; # HANGUL SYLLABLE IEUNG YEO THIEUTH * +U+C606(2);; # HANGUL SYLLABLE IEUNG YEO PHIEUPH * +U+C607(2);; # HANGUL SYLLABLE IEUNG YEO HIEUH * +U+C608(2);; # HANGUL SYLLABLE IEUNG YE * +U+C609(2);; # HANGUL SYLLABLE IEUNG YE KIYEOK +U+C60A(2);; # HANGUL SYLLABLE IEUNG YE SSANGKIYEOK +U+C60B(2);; # HANGUL SYLLABLE IEUNG YE KIYEOKSIOS +U+C60C(2);; # HANGUL SYLLABLE IEUNG YE NIEUN * +U+C60D(2);; # HANGUL SYLLABLE IEUNG YE NIEUNCIEUC +U+C60E(2);; # HANGUL SYLLABLE IEUNG YE NIEUNHIEUH +U+C60F(2);; # HANGUL SYLLABLE IEUNG YE TIKEUT +U+C610(2);; # HANGUL SYLLABLE IEUNG YE RIEUL * +U+C611(2);; # HANGUL SYLLABLE IEUNG YE RIEULKIYEOK +U+C612(2);; # HANGUL SYLLABLE IEUNG YE RIEULMIEUM +U+C613(2);; # HANGUL SYLLABLE IEUNG YE RIEULPIEUP +U+C614(2);; # HANGUL SYLLABLE IEUNG YE RIEULSIOS +U+C615(2);; # HANGUL SYLLABLE IEUNG YE RIEULTHIEUTH +U+C616(2);; # HANGUL SYLLABLE IEUNG YE RIEULPHIEUPH +U+C617(2);; # HANGUL SYLLABLE IEUNG YE RIEULHIEUH +U+C618(2);; # HANGUL SYLLABLE IEUNG YE MIEUM * +U+C619(2);; # HANGUL SYLLABLE IEUNG YE PIEUP * +U+C61A(2);; # HANGUL SYLLABLE IEUNG YE PIEUPSIOS +U+C61B(2);; # HANGUL SYLLABLE IEUNG YE SIOS * +U+C61C(2);; # HANGUL SYLLABLE IEUNG YE SSANGSIOS * +U+C61D(2);; # HANGUL SYLLABLE IEUNG YE IEUNG +U+C61E(2);; # HANGUL SYLLABLE IEUNG YE CIEUC +U+C61F(2);; # HANGUL SYLLABLE IEUNG YE CHIEUCH +U+C620(2);; # HANGUL SYLLABLE IEUNG YE KHIEUKH +U+C621(2);; # HANGUL SYLLABLE IEUNG YE THIEUTH +U+C622(2);; # HANGUL SYLLABLE IEUNG YE PHIEUPH +U+C623(2);; # HANGUL SYLLABLE IEUNG YE HIEUH +U+C624(2);; # HANGUL SYLLABLE IEUNG O * +U+C625(2);; # HANGUL SYLLABLE IEUNG O KIYEOK * +U+C626(2);; # HANGUL SYLLABLE IEUNG O SSANGKIYEOK +U+C627(2);; # HANGUL SYLLABLE IEUNG O KIYEOKSIOS +U+C628(2);; # HANGUL SYLLABLE IEUNG O NIEUN * +U+C629(2);; # HANGUL SYLLABLE IEUNG O NIEUNCIEUC +U+C62A(2);; # HANGUL SYLLABLE IEUNG O NIEUNHIEUH +U+C62B(2);; # HANGUL SYLLABLE IEUNG O TIKEUT +U+C62C(2);; # HANGUL SYLLABLE IEUNG O RIEUL * +U+C62D(2);; # HANGUL SYLLABLE IEUNG O RIEULKIYEOK * +U+C62E(2);; # HANGUL SYLLABLE IEUNG O RIEULMIEUM * +U+C62F(2);; # HANGUL SYLLABLE IEUNG O RIEULPIEUP +U+C630(2);; # HANGUL SYLLABLE IEUNG O RIEULSIOS * +U+C631(2);; # HANGUL SYLLABLE IEUNG O RIEULTHIEUTH +U+C632(2);; # HANGUL SYLLABLE IEUNG O RIEULPHIEUPH +U+C633(2);; # HANGUL SYLLABLE IEUNG O RIEULHIEUH * +U+C634(2);; # HANGUL SYLLABLE IEUNG O MIEUM * +U+C635(2);; # HANGUL SYLLABLE IEUNG O PIEUP * +U+C636(2);; # HANGUL SYLLABLE IEUNG O PIEUPSIOS +U+C637(2);; # HANGUL SYLLABLE IEUNG O SIOS * +U+C638(2);; # HANGUL SYLLABLE IEUNG O SSANGSIOS +U+C639(2);; # HANGUL SYLLABLE IEUNG O IEUNG * +U+C63A(2);; # HANGUL SYLLABLE IEUNG O CIEUC +U+C63B(2);; # HANGUL SYLLABLE IEUNG O CHIEUCH * +U+C63C(2);; # HANGUL SYLLABLE IEUNG O KHIEUKH +U+C63D(2);; # HANGUL SYLLABLE IEUNG O THIEUTH +U+C63E(2);; # HANGUL SYLLABLE IEUNG O PHIEUPH +U+C63F(2);; # HANGUL SYLLABLE IEUNG O HIEUH +U+C640(2);; # HANGUL SYLLABLE IEUNG WA * +U+C641(2);; # HANGUL SYLLABLE IEUNG WA KIYEOK * +U+C642(2);; # HANGUL SYLLABLE IEUNG WA SSANGKIYEOK +U+C643(2);; # HANGUL SYLLABLE IEUNG WA KIYEOKSIOS +U+C644(2);; # HANGUL SYLLABLE IEUNG WA NIEUN * +U+C645(2);; # HANGUL SYLLABLE IEUNG WA NIEUNCIEUC +U+C646(2);; # HANGUL SYLLABLE IEUNG WA NIEUNHIEUH +U+C647(2);; # HANGUL SYLLABLE IEUNG WA TIKEUT +U+C648(2);; # HANGUL SYLLABLE IEUNG WA RIEUL * +U+C649(2);; # HANGUL SYLLABLE IEUNG WA RIEULKIYEOK +U+C64A(2);; # HANGUL SYLLABLE IEUNG WA RIEULMIEUM +U+C64B(2);; # HANGUL SYLLABLE IEUNG WA RIEULPIEUP +U+C64C(2);; # HANGUL SYLLABLE IEUNG WA RIEULSIOS +U+C64D(2);; # HANGUL SYLLABLE IEUNG WA RIEULTHIEUTH +U+C64E(2);; # HANGUL SYLLABLE IEUNG WA RIEULPHIEUPH +U+C64F(2);; # HANGUL SYLLABLE IEUNG WA RIEULHIEUH +U+C650(2);; # HANGUL SYLLABLE IEUNG WA MIEUM * +U+C651(2);; # HANGUL SYLLABLE IEUNG WA PIEUP * +U+C652(2);; # HANGUL SYLLABLE IEUNG WA PIEUPSIOS +U+C653(2);; # HANGUL SYLLABLE IEUNG WA SIOS * +U+C654(2);; # HANGUL SYLLABLE IEUNG WA SSANGSIOS * +U+C655(2);; # HANGUL SYLLABLE IEUNG WA IEUNG * +U+C656(2);; # HANGUL SYLLABLE IEUNG WA CIEUC +U+C657(2);; # HANGUL SYLLABLE IEUNG WA CHIEUCH +U+C658(2);; # HANGUL SYLLABLE IEUNG WA KHIEUKH +U+C659(2);; # HANGUL SYLLABLE IEUNG WA THIEUTH +U+C65A(2);; # HANGUL SYLLABLE IEUNG WA PHIEUPH +U+C65B(2);; # HANGUL SYLLABLE IEUNG WA HIEUH +U+C65C(2);; # HANGUL SYLLABLE IEUNG WAE * +U+C65D(2);; # HANGUL SYLLABLE IEUNG WAE KIYEOK * +U+C65E(2);; # HANGUL SYLLABLE IEUNG WAE SSANGKIYEOK +U+C65F(2);; # HANGUL SYLLABLE IEUNG WAE KIYEOKSIOS +U+C660(2);; # HANGUL SYLLABLE IEUNG WAE NIEUN * +U+C661(2);; # HANGUL SYLLABLE IEUNG WAE NIEUNCIEUC +U+C662(2);; # HANGUL SYLLABLE IEUNG WAE NIEUNHIEUH +U+C663(2);; # HANGUL SYLLABLE IEUNG WAE TIKEUT +U+C664(2);; # HANGUL SYLLABLE IEUNG WAE RIEUL +U+C665(2);; # HANGUL SYLLABLE IEUNG WAE RIEULKIYEOK +U+C666(2);; # HANGUL SYLLABLE IEUNG WAE RIEULMIEUM +U+C667(2);; # HANGUL SYLLABLE IEUNG WAE RIEULPIEUP +U+C668(2);; # HANGUL SYLLABLE IEUNG WAE RIEULSIOS +U+C669(2);; # HANGUL SYLLABLE IEUNG WAE RIEULTHIEUTH +U+C66A(2);; # HANGUL SYLLABLE IEUNG WAE RIEULPHIEUPH +U+C66B(2);; # HANGUL SYLLABLE IEUNG WAE RIEULHIEUH +U+C66C(2);; # HANGUL SYLLABLE IEUNG WAE MIEUM * +U+C66D(2);; # HANGUL SYLLABLE IEUNG WAE PIEUP +U+C66E(2);; # HANGUL SYLLABLE IEUNG WAE PIEUPSIOS +U+C66F(2);; # HANGUL SYLLABLE IEUNG WAE SIOS * +U+C670(2);; # HANGUL SYLLABLE IEUNG WAE SSANGSIOS +U+C671(2);; # HANGUL SYLLABLE IEUNG WAE IEUNG * +U+C672(2);; # HANGUL SYLLABLE IEUNG WAE CIEUC +U+C673(2);; # HANGUL SYLLABLE IEUNG WAE CHIEUCH +U+C674(2);; # HANGUL SYLLABLE IEUNG WAE KHIEUKH +U+C675(2);; # HANGUL SYLLABLE IEUNG WAE THIEUTH +U+C676(2);; # HANGUL SYLLABLE IEUNG WAE PHIEUPH +U+C677(2);; # HANGUL SYLLABLE IEUNG WAE HIEUH +U+C678(2);; # HANGUL SYLLABLE IEUNG OE * +U+C679(2);; # HANGUL SYLLABLE IEUNG OE KIYEOK * +U+C67A(2);; # HANGUL SYLLABLE IEUNG OE SSANGKIYEOK +U+C67B(2);; # HANGUL SYLLABLE IEUNG OE KIYEOKSIOS +U+C67C(2);; # HANGUL SYLLABLE IEUNG OE NIEUN * +U+C67D(2);; # HANGUL SYLLABLE IEUNG OE NIEUNCIEUC +U+C67E(2);; # HANGUL SYLLABLE IEUNG OE NIEUNHIEUH +U+C67F(2);; # HANGUL SYLLABLE IEUNG OE TIKEUT +U+C680(2);; # HANGUL SYLLABLE IEUNG OE RIEUL * +U+C681(2);; # HANGUL SYLLABLE IEUNG OE RIEULKIYEOK +U+C682(2);; # HANGUL SYLLABLE IEUNG OE RIEULMIEUM +U+C683(2);; # HANGUL SYLLABLE IEUNG OE RIEULPIEUP +U+C684(2);; # HANGUL SYLLABLE IEUNG OE RIEULSIOS +U+C685(2);; # HANGUL SYLLABLE IEUNG OE RIEULTHIEUTH +U+C686(2);; # HANGUL SYLLABLE IEUNG OE RIEULPHIEUPH +U+C687(2);; # HANGUL SYLLABLE IEUNG OE RIEULHIEUH +U+C688(2);; # HANGUL SYLLABLE IEUNG OE MIEUM * +U+C689(2);; # HANGUL SYLLABLE IEUNG OE PIEUP * +U+C68A(2);; # HANGUL SYLLABLE IEUNG OE PIEUPSIOS +U+C68B(2);; # HANGUL SYLLABLE IEUNG OE SIOS * +U+C68C(2);; # HANGUL SYLLABLE IEUNG OE SSANGSIOS +U+C68D(2);; # HANGUL SYLLABLE IEUNG OE IEUNG * +U+C68E(2);; # HANGUL SYLLABLE IEUNG OE CIEUC +U+C68F(2);; # HANGUL SYLLABLE IEUNG OE CHIEUCH +U+C690(2);; # HANGUL SYLLABLE IEUNG OE KHIEUKH +U+C691(2);; # HANGUL SYLLABLE IEUNG OE THIEUTH +U+C692(2);; # HANGUL SYLLABLE IEUNG OE PHIEUPH +U+C693(2);; # HANGUL SYLLABLE IEUNG OE HIEUH +U+C694(2);; # HANGUL SYLLABLE IEUNG YO * +U+C695(2);; # HANGUL SYLLABLE IEUNG YO KIYEOK * +U+C696(2);; # HANGUL SYLLABLE IEUNG YO SSANGKIYEOK +U+C697(2);; # HANGUL SYLLABLE IEUNG YO KIYEOKSIOS +U+C698(2);; # HANGUL SYLLABLE IEUNG YO NIEUN * +U+C699(2);; # HANGUL SYLLABLE IEUNG YO NIEUNCIEUC +U+C69A(2);; # HANGUL SYLLABLE IEUNG YO NIEUNHIEUH +U+C69B(2);; # HANGUL SYLLABLE IEUNG YO TIKEUT +U+C69C(2);; # HANGUL SYLLABLE IEUNG YO RIEUL * +U+C69D(2);; # HANGUL SYLLABLE IEUNG YO RIEULKIYEOK +U+C69E(2);; # HANGUL SYLLABLE IEUNG YO RIEULMIEUM +U+C69F(2);; # HANGUL SYLLABLE IEUNG YO RIEULPIEUP +U+C6A0(2);; # HANGUL SYLLABLE IEUNG YO RIEULSIOS +U+C6A1(2);; # HANGUL SYLLABLE IEUNG YO RIEULTHIEUTH +U+C6A2(2);; # HANGUL SYLLABLE IEUNG YO RIEULPHIEUPH +U+C6A3(2);; # HANGUL SYLLABLE IEUNG YO RIEULHIEUH +U+C6A4(2);; # HANGUL SYLLABLE IEUNG YO MIEUM * +U+C6A5(2);; # HANGUL SYLLABLE IEUNG YO PIEUP * +U+C6A6(2);; # HANGUL SYLLABLE IEUNG YO PIEUPSIOS +U+C6A7(2);; # HANGUL SYLLABLE IEUNG YO SIOS * +U+C6A8(2);; # HANGUL SYLLABLE IEUNG YO SSANGSIOS +U+C6A9(2);; # HANGUL SYLLABLE IEUNG YO IEUNG * +U+C6AA(2);; # HANGUL SYLLABLE IEUNG YO CIEUC +U+C6AB(2);; # HANGUL SYLLABLE IEUNG YO CHIEUCH +U+C6AC(2);; # HANGUL SYLLABLE IEUNG YO KHIEUKH +U+C6AD(2);; # HANGUL SYLLABLE IEUNG YO THIEUTH +U+C6AE(2);; # HANGUL SYLLABLE IEUNG YO PHIEUPH +U+C6AF(2);; # HANGUL SYLLABLE IEUNG YO HIEUH +U+C6B0(2);; # HANGUL SYLLABLE IEUNG U * +U+C6B1(2);; # HANGUL SYLLABLE IEUNG U KIYEOK * +U+C6B2(2);; # HANGUL SYLLABLE IEUNG U SSANGKIYEOK +U+C6B3(2);; # HANGUL SYLLABLE IEUNG U KIYEOKSIOS +U+C6B4(2);; # HANGUL SYLLABLE IEUNG U NIEUN * +U+C6B5(2);; # HANGUL SYLLABLE IEUNG U NIEUNCIEUC +U+C6B6(2);; # HANGUL SYLLABLE IEUNG U NIEUNHIEUH +U+C6B7(2);; # HANGUL SYLLABLE IEUNG U TIKEUT +U+C6B8(2);; # HANGUL SYLLABLE IEUNG U RIEUL * +U+C6B9(2);; # HANGUL SYLLABLE IEUNG U RIEULKIYEOK * +U+C6BA(2);; # HANGUL SYLLABLE IEUNG U RIEULMIEUM * +U+C6BB(2);; # HANGUL SYLLABLE IEUNG U RIEULPIEUP +U+C6BC(2);; # HANGUL SYLLABLE IEUNG U RIEULSIOS +U+C6BD(2);; # HANGUL SYLLABLE IEUNG U RIEULTHIEUTH +U+C6BE(2);; # HANGUL SYLLABLE IEUNG U RIEULPHIEUPH +U+C6BF(2);; # HANGUL SYLLABLE IEUNG U RIEULHIEUH +U+C6C0(2);; # HANGUL SYLLABLE IEUNG U MIEUM * +U+C6C1(2);; # HANGUL SYLLABLE IEUNG U PIEUP * +U+C6C2(2);; # HANGUL SYLLABLE IEUNG U PIEUPSIOS +U+C6C3(2);; # HANGUL SYLLABLE IEUNG U SIOS * +U+C6C4(2);; # HANGUL SYLLABLE IEUNG U SSANGSIOS +U+C6C5(2);; # HANGUL SYLLABLE IEUNG U IEUNG * +U+C6C6(2);; # HANGUL SYLLABLE IEUNG U CIEUC +U+C6C7(2);; # HANGUL SYLLABLE IEUNG U CHIEUCH +U+C6C8(2);; # HANGUL SYLLABLE IEUNG U KHIEUKH +U+C6C9(2);; # HANGUL SYLLABLE IEUNG U THIEUTH +U+C6CA(2);; # HANGUL SYLLABLE IEUNG U PHIEUPH +U+C6CB(2);; # HANGUL SYLLABLE IEUNG U HIEUH +U+C6CC(2);; # HANGUL SYLLABLE IEUNG WEO * +U+C6CD(2);; # HANGUL SYLLABLE IEUNG WEO KIYEOK * +U+C6CE(2);; # HANGUL SYLLABLE IEUNG WEO SSANGKIYEOK +U+C6CF(2);; # HANGUL SYLLABLE IEUNG WEO KIYEOKSIOS +U+C6D0(2);; # HANGUL SYLLABLE IEUNG WEO NIEUN * +U+C6D1(2);; # HANGUL SYLLABLE IEUNG WEO NIEUNCIEUC +U+C6D2(2);; # HANGUL SYLLABLE IEUNG WEO NIEUNHIEUH +U+C6D3(2);; # HANGUL SYLLABLE IEUNG WEO TIKEUT +U+C6D4(2);; # HANGUL SYLLABLE IEUNG WEO RIEUL * +U+C6D5(2);; # HANGUL SYLLABLE IEUNG WEO RIEULKIYEOK +U+C6D6(2);; # HANGUL SYLLABLE IEUNG WEO RIEULMIEUM +U+C6D7(2);; # HANGUL SYLLABLE IEUNG WEO RIEULPIEUP +U+C6D8(2);; # HANGUL SYLLABLE IEUNG WEO RIEULSIOS +U+C6D9(2);; # HANGUL SYLLABLE IEUNG WEO RIEULTHIEUTH +U+C6DA(2);; # HANGUL SYLLABLE IEUNG WEO RIEULPHIEUPH +U+C6DB(2);; # HANGUL SYLLABLE IEUNG WEO RIEULHIEUH +U+C6DC(2);; # HANGUL SYLLABLE IEUNG WEO MIEUM * +U+C6DD(2);; # HANGUL SYLLABLE IEUNG WEO PIEUP * +U+C6DE(2);; # HANGUL SYLLABLE IEUNG WEO PIEUPSIOS +U+C6DF(2);; # HANGUL SYLLABLE IEUNG WEO SIOS +U+C6E0(2);; # HANGUL SYLLABLE IEUNG WEO SSANGSIOS * +U+C6E1(2);; # HANGUL SYLLABLE IEUNG WEO IEUNG * +U+C6E2(2);; # HANGUL SYLLABLE IEUNG WEO CIEUC +U+C6E3(2);; # HANGUL SYLLABLE IEUNG WEO CHIEUCH +U+C6E4(2);; # HANGUL SYLLABLE IEUNG WEO KHIEUKH +U+C6E5(2);; # HANGUL SYLLABLE IEUNG WEO THIEUTH +U+C6E6(2);; # HANGUL SYLLABLE IEUNG WEO PHIEUPH +U+C6E7(2);; # HANGUL SYLLABLE IEUNG WEO HIEUH +U+C6E8(2);; # HANGUL SYLLABLE IEUNG WE * +U+C6E9(2);; # HANGUL SYLLABLE IEUNG WE KIYEOK * +U+C6EA(2);; # HANGUL SYLLABLE IEUNG WE SSANGKIYEOK +U+C6EB(2);; # HANGUL SYLLABLE IEUNG WE KIYEOKSIOS +U+C6EC(2);; # HANGUL SYLLABLE IEUNG WE NIEUN * +U+C6ED(2);; # HANGUL SYLLABLE IEUNG WE NIEUNCIEUC +U+C6EE(2);; # HANGUL SYLLABLE IEUNG WE NIEUNHIEUH +U+C6EF(2);; # HANGUL SYLLABLE IEUNG WE TIKEUT +U+C6F0(2);; # HANGUL SYLLABLE IEUNG WE RIEUL * +U+C6F1(2);; # HANGUL SYLLABLE IEUNG WE RIEULKIYEOK +U+C6F2(2);; # HANGUL SYLLABLE IEUNG WE RIEULMIEUM +U+C6F3(2);; # HANGUL SYLLABLE IEUNG WE RIEULPIEUP +U+C6F4(2);; # HANGUL SYLLABLE IEUNG WE RIEULSIOS +U+C6F5(2);; # HANGUL SYLLABLE IEUNG WE RIEULTHIEUTH +U+C6F6(2);; # HANGUL SYLLABLE IEUNG WE RIEULPHIEUPH +U+C6F7(2);; # HANGUL SYLLABLE IEUNG WE RIEULHIEUH +U+C6F8(2);; # HANGUL SYLLABLE IEUNG WE MIEUM * +U+C6F9(2);; # HANGUL SYLLABLE IEUNG WE PIEUP * +U+C6FA(2);; # HANGUL SYLLABLE IEUNG WE PIEUPSIOS +U+C6FB(2);; # HANGUL SYLLABLE IEUNG WE SIOS +U+C6FC(2);; # HANGUL SYLLABLE IEUNG WE SSANGSIOS +U+C6FD(2);; # HANGUL SYLLABLE IEUNG WE IEUNG * +U+C6FE(2);; # HANGUL SYLLABLE IEUNG WE CIEUC +U+C6FF(2);; # HANGUL SYLLABLE IEUNG WE CHIEUCH +U+C700(2);; # HANGUL SYLLABLE IEUNG WE KHIEUKH +U+C701(2);; # HANGUL SYLLABLE IEUNG WE THIEUTH +U+C702(2);; # HANGUL SYLLABLE IEUNG WE PHIEUPH +U+C703(2);; # HANGUL SYLLABLE IEUNG WE HIEUH +U+C704(2);; # HANGUL SYLLABLE IEUNG WI * +U+C705(2);; # HANGUL SYLLABLE IEUNG WI KIYEOK * +U+C706(2);; # HANGUL SYLLABLE IEUNG WI SSANGKIYEOK +U+C707(2);; # HANGUL SYLLABLE IEUNG WI KIYEOKSIOS +U+C708(2);; # HANGUL SYLLABLE IEUNG WI NIEUN * +U+C709(2);; # HANGUL SYLLABLE IEUNG WI NIEUNCIEUC +U+C70A(2);; # HANGUL SYLLABLE IEUNG WI NIEUNHIEUH +U+C70B(2);; # HANGUL SYLLABLE IEUNG WI TIKEUT +U+C70C(2);; # HANGUL SYLLABLE IEUNG WI RIEUL * +U+C70D(2);; # HANGUL SYLLABLE IEUNG WI RIEULKIYEOK +U+C70E(2);; # HANGUL SYLLABLE IEUNG WI RIEULMIEUM +U+C70F(2);; # HANGUL SYLLABLE IEUNG WI RIEULPIEUP +U+C710(2);; # HANGUL SYLLABLE IEUNG WI RIEULSIOS +U+C711(2);; # HANGUL SYLLABLE IEUNG WI RIEULTHIEUTH +U+C712(2);; # HANGUL SYLLABLE IEUNG WI RIEULPHIEUPH +U+C713(2);; # HANGUL SYLLABLE IEUNG WI RIEULHIEUH +U+C714(2);; # HANGUL SYLLABLE IEUNG WI MIEUM * +U+C715(2);; # HANGUL SYLLABLE IEUNG WI PIEUP * +U+C716(2);; # HANGUL SYLLABLE IEUNG WI PIEUPSIOS +U+C717(2);; # HANGUL SYLLABLE IEUNG WI SIOS * +U+C718(2);; # HANGUL SYLLABLE IEUNG WI SSANGSIOS +U+C719(2);; # HANGUL SYLLABLE IEUNG WI IEUNG * +U+C71A(2);; # HANGUL SYLLABLE IEUNG WI CIEUC +U+C71B(2);; # HANGUL SYLLABLE IEUNG WI CHIEUCH +U+C71C(2);; # HANGUL SYLLABLE IEUNG WI KHIEUKH +U+C71D(2);; # HANGUL SYLLABLE IEUNG WI THIEUTH +U+C71E(2);; # HANGUL SYLLABLE IEUNG WI PHIEUPH +U+C71F(2);; # HANGUL SYLLABLE IEUNG WI HIEUH +U+C720(2);; # HANGUL SYLLABLE IEUNG YU * +U+C721(2);; # HANGUL SYLLABLE IEUNG YU KIYEOK * +U+C722(2);; # HANGUL SYLLABLE IEUNG YU SSANGKIYEOK +U+C723(2);; # HANGUL SYLLABLE IEUNG YU KIYEOKSIOS +U+C724(2);; # HANGUL SYLLABLE IEUNG YU NIEUN * +U+C725(2);; # HANGUL SYLLABLE IEUNG YU NIEUNCIEUC +U+C726(2);; # HANGUL SYLLABLE IEUNG YU NIEUNHIEUH +U+C727(2);; # HANGUL SYLLABLE IEUNG YU TIKEUT +U+C728(2);; # HANGUL SYLLABLE IEUNG YU RIEUL * +U+C729(2);; # HANGUL SYLLABLE IEUNG YU RIEULKIYEOK +U+C72A(2);; # HANGUL SYLLABLE IEUNG YU RIEULMIEUM +U+C72B(2);; # HANGUL SYLLABLE IEUNG YU RIEULPIEUP +U+C72C(2);; # HANGUL SYLLABLE IEUNG YU RIEULSIOS +U+C72D(2);; # HANGUL SYLLABLE IEUNG YU RIEULTHIEUTH +U+C72E(2);; # HANGUL SYLLABLE IEUNG YU RIEULPHIEUPH +U+C72F(2);; # HANGUL SYLLABLE IEUNG YU RIEULHIEUH +U+C730(2);; # HANGUL SYLLABLE IEUNG YU MIEUM * +U+C731(2);; # HANGUL SYLLABLE IEUNG YU PIEUP * +U+C732(2);; # HANGUL SYLLABLE IEUNG YU PIEUPSIOS +U+C733(2);; # HANGUL SYLLABLE IEUNG YU SIOS * +U+C734(2);; # HANGUL SYLLABLE IEUNG YU SSANGSIOS +U+C735(2);; # HANGUL SYLLABLE IEUNG YU IEUNG * +U+C736(2);; # HANGUL SYLLABLE IEUNG YU CIEUC +U+C737(2);; # HANGUL SYLLABLE IEUNG YU CHIEUCH * +U+C738(2);; # HANGUL SYLLABLE IEUNG YU KHIEUKH +U+C739(2);; # HANGUL SYLLABLE IEUNG YU THIEUTH +U+C73A(2);; # HANGUL SYLLABLE IEUNG YU PHIEUPH +U+C73B(2);; # HANGUL SYLLABLE IEUNG YU HIEUH +U+C73C(2);; # HANGUL SYLLABLE IEUNG EU * +U+C73D(2);; # HANGUL SYLLABLE IEUNG EU KIYEOK * +U+C73E(2);; # HANGUL SYLLABLE IEUNG EU SSANGKIYEOK +U+C73F(2);; # HANGUL SYLLABLE IEUNG EU KIYEOKSIOS +U+C740(2);; # HANGUL SYLLABLE IEUNG EU NIEUN * +U+C741(2);; # HANGUL SYLLABLE IEUNG EU NIEUNCIEUC +U+C742(2);; # HANGUL SYLLABLE IEUNG EU NIEUNHIEUH +U+C743(2);; # HANGUL SYLLABLE IEUNG EU TIKEUT +U+C744(2);; # HANGUL SYLLABLE IEUNG EU RIEUL * +U+C745(2);; # HANGUL SYLLABLE IEUNG EU RIEULKIYEOK +U+C746(2);; # HANGUL SYLLABLE IEUNG EU RIEULMIEUM +U+C747(2);; # HANGUL SYLLABLE IEUNG EU RIEULPIEUP +U+C748(2);; # HANGUL SYLLABLE IEUNG EU RIEULSIOS +U+C749(2);; # HANGUL SYLLABLE IEUNG EU RIEULTHIEUTH +U+C74A(2);; # HANGUL SYLLABLE IEUNG EU RIEULPHIEUPH * +U+C74B(2);; # HANGUL SYLLABLE IEUNG EU RIEULHIEUH +U+C74C(2);; # HANGUL SYLLABLE IEUNG EU MIEUM * +U+C74D(2);; # HANGUL SYLLABLE IEUNG EU PIEUP * +U+C74E(2);; # HANGUL SYLLABLE IEUNG EU PIEUPSIOS +U+C74F(2);; # HANGUL SYLLABLE IEUNG EU SIOS * +U+C750(2);; # HANGUL SYLLABLE IEUNG EU SSANGSIOS +U+C751(2);; # HANGUL SYLLABLE IEUNG EU IEUNG * +U+C752(2);; # HANGUL SYLLABLE IEUNG EU CIEUC * +U+C753(2);; # HANGUL SYLLABLE IEUNG EU CHIEUCH * +U+C754(2);; # HANGUL SYLLABLE IEUNG EU KHIEUKH * +U+C755(2);; # HANGUL SYLLABLE IEUNG EU THIEUTH * +U+C756(2);; # HANGUL SYLLABLE IEUNG EU PHIEUPH * +U+C757(2);; # HANGUL SYLLABLE IEUNG EU HIEUH * +U+C758(2);; # HANGUL SYLLABLE IEUNG YI * +U+C759(2);; # HANGUL SYLLABLE IEUNG YI KIYEOK +U+C75A(2);; # HANGUL SYLLABLE IEUNG YI SSANGKIYEOK +U+C75B(2);; # HANGUL SYLLABLE IEUNG YI KIYEOKSIOS +U+C75C(2);; # HANGUL SYLLABLE IEUNG YI NIEUN * +U+C75D(2);; # HANGUL SYLLABLE IEUNG YI NIEUNCIEUC +U+C75E(2);; # HANGUL SYLLABLE IEUNG YI NIEUNHIEUH +U+C75F(2);; # HANGUL SYLLABLE IEUNG YI TIKEUT +U+C760(2);; # HANGUL SYLLABLE IEUNG YI RIEUL * +U+C761(2);; # HANGUL SYLLABLE IEUNG YI RIEULKIYEOK +U+C762(2);; # HANGUL SYLLABLE IEUNG YI RIEULMIEUM +U+C763(2);; # HANGUL SYLLABLE IEUNG YI RIEULPIEUP +U+C764(2);; # HANGUL SYLLABLE IEUNG YI RIEULSIOS +U+C765(2);; # HANGUL SYLLABLE IEUNG YI RIEULTHIEUTH +U+C766(2);; # HANGUL SYLLABLE IEUNG YI RIEULPHIEUPH +U+C767(2);; # HANGUL SYLLABLE IEUNG YI RIEULHIEUH +U+C768(2);; # HANGUL SYLLABLE IEUNG YI MIEUM * +U+C769(2);; # HANGUL SYLLABLE IEUNG YI PIEUP +U+C76A(2);; # HANGUL SYLLABLE IEUNG YI PIEUPSIOS +U+C76B(2);; # HANGUL SYLLABLE IEUNG YI SIOS * +U+C76C(2);; # HANGUL SYLLABLE IEUNG YI SSANGSIOS +U+C76D(2);; # HANGUL SYLLABLE IEUNG YI IEUNG +U+C76E(2);; # HANGUL SYLLABLE IEUNG YI CIEUC +U+C76F(2);; # HANGUL SYLLABLE IEUNG YI CHIEUCH +U+C770(2);; # HANGUL SYLLABLE IEUNG YI KHIEUKH +U+C771(2);; # HANGUL SYLLABLE IEUNG YI THIEUTH +U+C772(2);; # HANGUL SYLLABLE IEUNG YI PHIEUPH +U+C773(2);; # HANGUL SYLLABLE IEUNG YI HIEUH +U+C774(2);; # HANGUL SYLLABLE IEUNG I * +U+C775(2);; # HANGUL SYLLABLE IEUNG I KIYEOK * +U+C776(2);; # HANGUL SYLLABLE IEUNG I SSANGKIYEOK +U+C777(2);; # HANGUL SYLLABLE IEUNG I KIYEOKSIOS +U+C778(2);; # HANGUL SYLLABLE IEUNG I NIEUN * +U+C779(2);; # HANGUL SYLLABLE IEUNG I NIEUNCIEUC +U+C77A(2);; # HANGUL SYLLABLE IEUNG I NIEUNHIEUH +U+C77B(2);; # HANGUL SYLLABLE IEUNG I TIKEUT +U+C77C(2);; # HANGUL SYLLABLE IEUNG I RIEUL * +U+C77D(2);; # HANGUL SYLLABLE IEUNG I RIEULKIYEOK * +U+C77E(2);; # HANGUL SYLLABLE IEUNG I RIEULMIEUM * +U+C77F(2);; # HANGUL SYLLABLE IEUNG I RIEULPIEUP +U+C780(2);; # HANGUL SYLLABLE IEUNG I RIEULSIOS +U+C781(2);; # HANGUL SYLLABLE IEUNG I RIEULTHIEUTH +U+C782(2);; # HANGUL SYLLABLE IEUNG I RIEULPHIEUPH +U+C783(2);; # HANGUL SYLLABLE IEUNG I RIEULHIEUH * +U+C784(2);; # HANGUL SYLLABLE IEUNG I MIEUM * +U+C785(2);; # HANGUL SYLLABLE IEUNG I PIEUP * +U+C786(2);; # HANGUL SYLLABLE IEUNG I PIEUPSIOS +U+C787(2);; # HANGUL SYLLABLE IEUNG I SIOS * +U+C788(2);; # HANGUL SYLLABLE IEUNG I SSANGSIOS * +U+C789(2);; # HANGUL SYLLABLE IEUNG I IEUNG * +U+C78A(2);; # HANGUL SYLLABLE IEUNG I CIEUC * +U+C78B(2);; # HANGUL SYLLABLE IEUNG I CHIEUCH +U+C78C(2);; # HANGUL SYLLABLE IEUNG I KHIEUKH +U+C78D(2);; # HANGUL SYLLABLE IEUNG I THIEUTH +U+C78E(2);; # HANGUL SYLLABLE IEUNG I PHIEUPH * +U+C78F(2);; # HANGUL SYLLABLE IEUNG I HIEUH +U+C790(2);; # HANGUL SYLLABLE CIEUC A * +U+C791(2);; # HANGUL SYLLABLE CIEUC A KIYEOK * +U+C792(2);; # HANGUL SYLLABLE CIEUC A SSANGKIYEOK +U+C793(2);; # HANGUL SYLLABLE CIEUC A KIYEOKSIOS +U+C794(2);; # HANGUL SYLLABLE CIEUC A NIEUN * +U+C795(2);; # HANGUL SYLLABLE CIEUC A NIEUNCIEUC +U+C796(2);; # HANGUL SYLLABLE CIEUC A NIEUNHIEUH * +U+C797(2);; # HANGUL SYLLABLE CIEUC A TIKEUT * +U+C798(2);; # HANGUL SYLLABLE CIEUC A RIEUL * +U+C799(2);; # HANGUL SYLLABLE CIEUC A RIEULKIYEOK +U+C79A(2);; # HANGUL SYLLABLE CIEUC A RIEULMIEUM * +U+C79B(2);; # HANGUL SYLLABLE CIEUC A RIEULPIEUP +U+C79C(2);; # HANGUL SYLLABLE CIEUC A RIEULSIOS +U+C79D(2);; # HANGUL SYLLABLE CIEUC A RIEULTHIEUTH +U+C79E(2);; # HANGUL SYLLABLE CIEUC A RIEULPHIEUPH +U+C79F(2);; # HANGUL SYLLABLE CIEUC A RIEULHIEUH +U+C7A0(2);; # HANGUL SYLLABLE CIEUC A MIEUM * +U+C7A1(2);; # HANGUL SYLLABLE CIEUC A PIEUP * +U+C7A2(2);; # HANGUL SYLLABLE CIEUC A PIEUPSIOS +U+C7A3(2);; # HANGUL SYLLABLE CIEUC A SIOS * +U+C7A4(2);; # HANGUL SYLLABLE CIEUC A SSANGSIOS * +U+C7A5(2);; # HANGUL SYLLABLE CIEUC A IEUNG * +U+C7A6(2);; # HANGUL SYLLABLE CIEUC A CIEUC * +U+C7A7(2);; # HANGUL SYLLABLE CIEUC A CHIEUCH +U+C7A8(2);; # HANGUL SYLLABLE CIEUC A KHIEUKH +U+C7A9(2);; # HANGUL SYLLABLE CIEUC A THIEUTH +U+C7AA(2);; # HANGUL SYLLABLE CIEUC A PHIEUPH +U+C7AB(2);; # HANGUL SYLLABLE CIEUC A HIEUH +U+C7AC(2);; # HANGUL SYLLABLE CIEUC AE * +U+C7AD(2);; # HANGUL SYLLABLE CIEUC AE KIYEOK * +U+C7AE(2);; # HANGUL SYLLABLE CIEUC AE SSANGKIYEOK +U+C7AF(2);; # HANGUL SYLLABLE CIEUC AE KIYEOKSIOS +U+C7B0(2);; # HANGUL SYLLABLE CIEUC AE NIEUN * +U+C7B1(2);; # HANGUL SYLLABLE CIEUC AE NIEUNCIEUC +U+C7B2(2);; # HANGUL SYLLABLE CIEUC AE NIEUNHIEUH +U+C7B3(2);; # HANGUL SYLLABLE CIEUC AE TIKEUT +U+C7B4(2);; # HANGUL SYLLABLE CIEUC AE RIEUL * +U+C7B5(2);; # HANGUL SYLLABLE CIEUC AE RIEULKIYEOK +U+C7B6(2);; # HANGUL SYLLABLE CIEUC AE RIEULMIEUM +U+C7B7(2);; # HANGUL SYLLABLE CIEUC AE RIEULPIEUP +U+C7B8(2);; # HANGUL SYLLABLE CIEUC AE RIEULSIOS +U+C7B9(2);; # HANGUL SYLLABLE CIEUC AE RIEULTHIEUTH +U+C7BA(2);; # HANGUL SYLLABLE CIEUC AE RIEULPHIEUPH +U+C7BB(2);; # HANGUL SYLLABLE CIEUC AE RIEULHIEUH +U+C7BC(2);; # HANGUL SYLLABLE CIEUC AE MIEUM * +U+C7BD(2);; # HANGUL SYLLABLE CIEUC AE PIEUP * +U+C7BE(2);; # HANGUL SYLLABLE CIEUC AE PIEUPSIOS +U+C7BF(2);; # HANGUL SYLLABLE CIEUC AE SIOS * +U+C7C0(2);; # HANGUL SYLLABLE CIEUC AE SSANGSIOS * +U+C7C1(2);; # HANGUL SYLLABLE CIEUC AE IEUNG * +U+C7C2(2);; # HANGUL SYLLABLE CIEUC AE CIEUC +U+C7C3(2);; # HANGUL SYLLABLE CIEUC AE CHIEUCH +U+C7C4(2);; # HANGUL SYLLABLE CIEUC AE KHIEUKH +U+C7C5(2);; # HANGUL SYLLABLE CIEUC AE THIEUTH +U+C7C6(2);; # HANGUL SYLLABLE CIEUC AE PHIEUPH +U+C7C7(2);; # HANGUL SYLLABLE CIEUC AE HIEUH +U+C7C8(2);; # HANGUL SYLLABLE CIEUC YA * +U+C7C9(2);; # HANGUL SYLLABLE CIEUC YA KIYEOK * +U+C7CA(2);; # HANGUL SYLLABLE CIEUC YA SSANGKIYEOK +U+C7CB(2);; # HANGUL SYLLABLE CIEUC YA KIYEOKSIOS +U+C7CC(2);; # HANGUL SYLLABLE CIEUC YA NIEUN * +U+C7CD(2);; # HANGUL SYLLABLE CIEUC YA NIEUNCIEUC +U+C7CE(2);; # HANGUL SYLLABLE CIEUC YA NIEUNHIEUH * +U+C7CF(2);; # HANGUL SYLLABLE CIEUC YA TIKEUT +U+C7D0(2);; # HANGUL SYLLABLE CIEUC YA RIEUL * +U+C7D1(2);; # HANGUL SYLLABLE CIEUC YA RIEULKIYEOK +U+C7D2(2);; # HANGUL SYLLABLE CIEUC YA RIEULMIEUM +U+C7D3(2);; # HANGUL SYLLABLE CIEUC YA RIEULPIEUP +U+C7D4(2);; # HANGUL SYLLABLE CIEUC YA RIEULSIOS +U+C7D5(2);; # HANGUL SYLLABLE CIEUC YA RIEULTHIEUTH +U+C7D6(2);; # HANGUL SYLLABLE CIEUC YA RIEULPHIEUPH +U+C7D7(2);; # HANGUL SYLLABLE CIEUC YA RIEULHIEUH +U+C7D8(2);; # HANGUL SYLLABLE CIEUC YA MIEUM * +U+C7D9(2);; # HANGUL SYLLABLE CIEUC YA PIEUP +U+C7DA(2);; # HANGUL SYLLABLE CIEUC YA PIEUPSIOS +U+C7DB(2);; # HANGUL SYLLABLE CIEUC YA SIOS +U+C7DC(2);; # HANGUL SYLLABLE CIEUC YA SSANGSIOS +U+C7DD(2);; # HANGUL SYLLABLE CIEUC YA IEUNG * +U+C7DE(2);; # HANGUL SYLLABLE CIEUC YA CIEUC +U+C7DF(2);; # HANGUL SYLLABLE CIEUC YA CHIEUCH +U+C7E0(2);; # HANGUL SYLLABLE CIEUC YA KHIEUKH +U+C7E1(2);; # HANGUL SYLLABLE CIEUC YA THIEUTH +U+C7E2(2);; # HANGUL SYLLABLE CIEUC YA PHIEUPH +U+C7E3(2);; # HANGUL SYLLABLE CIEUC YA HIEUH +U+C7E4(2);; # HANGUL SYLLABLE CIEUC YAE * +U+C7E5(2);; # HANGUL SYLLABLE CIEUC YAE KIYEOK +U+C7E6(2);; # HANGUL SYLLABLE CIEUC YAE SSANGKIYEOK +U+C7E7(2);; # HANGUL SYLLABLE CIEUC YAE KIYEOKSIOS +U+C7E8(2);; # HANGUL SYLLABLE CIEUC YAE NIEUN * +U+C7E9(2);; # HANGUL SYLLABLE CIEUC YAE NIEUNCIEUC +U+C7EA(2);; # HANGUL SYLLABLE CIEUC YAE NIEUNHIEUH +U+C7EB(2);; # HANGUL SYLLABLE CIEUC YAE TIKEUT +U+C7EC(2);; # HANGUL SYLLABLE CIEUC YAE RIEUL * +U+C7ED(2);; # HANGUL SYLLABLE CIEUC YAE RIEULKIYEOK +U+C7EE(2);; # HANGUL SYLLABLE CIEUC YAE RIEULMIEUM +U+C7EF(2);; # HANGUL SYLLABLE CIEUC YAE RIEULPIEUP +U+C7F0(2);; # HANGUL SYLLABLE CIEUC YAE RIEULSIOS +U+C7F1(2);; # HANGUL SYLLABLE CIEUC YAE RIEULTHIEUTH +U+C7F2(2);; # HANGUL SYLLABLE CIEUC YAE RIEULPHIEUPH +U+C7F3(2);; # HANGUL SYLLABLE CIEUC YAE RIEULHIEUH +U+C7F4(2);; # HANGUL SYLLABLE CIEUC YAE MIEUM +U+C7F5(2);; # HANGUL SYLLABLE CIEUC YAE PIEUP +U+C7F6(2);; # HANGUL SYLLABLE CIEUC YAE PIEUPSIOS +U+C7F7(2);; # HANGUL SYLLABLE CIEUC YAE SIOS +U+C7F8(2);; # HANGUL SYLLABLE CIEUC YAE SSANGSIOS +U+C7F9(2);; # HANGUL SYLLABLE CIEUC YAE IEUNG +U+C7FA(2);; # HANGUL SYLLABLE CIEUC YAE CIEUC +U+C7FB(2);; # HANGUL SYLLABLE CIEUC YAE CHIEUCH +U+C7FC(2);; # HANGUL SYLLABLE CIEUC YAE KHIEUKH +U+C7FD(2);; # HANGUL SYLLABLE CIEUC YAE THIEUTH +U+C7FE(2);; # HANGUL SYLLABLE CIEUC YAE PHIEUPH +U+C7FF(2);; # HANGUL SYLLABLE CIEUC YAE HIEUH +U+C800(2);; # HANGUL SYLLABLE CIEUC EO * +U+C801(2);; # HANGUL SYLLABLE CIEUC EO KIYEOK * +U+C802(2);; # HANGUL SYLLABLE CIEUC EO SSANGKIYEOK +U+C803(2);; # HANGUL SYLLABLE CIEUC EO KIYEOKSIOS +U+C804(2);; # HANGUL SYLLABLE CIEUC EO NIEUN * +U+C805(2);; # HANGUL SYLLABLE CIEUC EO NIEUNCIEUC +U+C806(2);; # HANGUL SYLLABLE CIEUC EO NIEUNHIEUH +U+C807(2);; # HANGUL SYLLABLE CIEUC EO TIKEUT +U+C808(2);; # HANGUL SYLLABLE CIEUC EO RIEUL * +U+C809(2);; # HANGUL SYLLABLE CIEUC EO RIEULKIYEOK +U+C80A(2);; # HANGUL SYLLABLE CIEUC EO RIEULMIEUM * +U+C80B(2);; # HANGUL SYLLABLE CIEUC EO RIEULPIEUP +U+C80C(2);; # HANGUL SYLLABLE CIEUC EO RIEULSIOS +U+C80D(2);; # HANGUL SYLLABLE CIEUC EO RIEULTHIEUTH +U+C80E(2);; # HANGUL SYLLABLE CIEUC EO RIEULPHIEUPH +U+C80F(2);; # HANGUL SYLLABLE CIEUC EO RIEULHIEUH +U+C810(2);; # HANGUL SYLLABLE CIEUC EO MIEUM * +U+C811(2);; # HANGUL SYLLABLE CIEUC EO PIEUP * +U+C812(2);; # HANGUL SYLLABLE CIEUC EO PIEUPSIOS +U+C813(2);; # HANGUL SYLLABLE CIEUC EO SIOS * +U+C814(2);; # HANGUL SYLLABLE CIEUC EO SSANGSIOS +U+C815(2);; # HANGUL SYLLABLE CIEUC EO IEUNG * +U+C816(2);; # HANGUL SYLLABLE CIEUC EO CIEUC * +U+C817(2);; # HANGUL SYLLABLE CIEUC EO CHIEUCH +U+C818(2);; # HANGUL SYLLABLE CIEUC EO KHIEUKH +U+C819(2);; # HANGUL SYLLABLE CIEUC EO THIEUTH +U+C81A(2);; # HANGUL SYLLABLE CIEUC EO PHIEUPH +U+C81B(2);; # HANGUL SYLLABLE CIEUC EO HIEUH +U+C81C(2);; # HANGUL SYLLABLE CIEUC E * +U+C81D(2);; # HANGUL SYLLABLE CIEUC E KIYEOK * +U+C81E(2);; # HANGUL SYLLABLE CIEUC E SSANGKIYEOK +U+C81F(2);; # HANGUL SYLLABLE CIEUC E KIYEOKSIOS +U+C820(2);; # HANGUL SYLLABLE CIEUC E NIEUN * +U+C821(2);; # HANGUL SYLLABLE CIEUC E NIEUNCIEUC +U+C822(2);; # HANGUL SYLLABLE CIEUC E NIEUNHIEUH +U+C823(2);; # HANGUL SYLLABLE CIEUC E TIKEUT +U+C824(2);; # HANGUL SYLLABLE CIEUC E RIEUL * +U+C825(2);; # HANGUL SYLLABLE CIEUC E RIEULKIYEOK +U+C826(2);; # HANGUL SYLLABLE CIEUC E RIEULMIEUM +U+C827(2);; # HANGUL SYLLABLE CIEUC E RIEULPIEUP +U+C828(2);; # HANGUL SYLLABLE CIEUC E RIEULSIOS +U+C829(2);; # HANGUL SYLLABLE CIEUC E RIEULTHIEUTH +U+C82A(2);; # HANGUL SYLLABLE CIEUC E RIEULPHIEUPH +U+C82B(2);; # HANGUL SYLLABLE CIEUC E RIEULHIEUH +U+C82C(2);; # HANGUL SYLLABLE CIEUC E MIEUM * +U+C82D(2);; # HANGUL SYLLABLE CIEUC E PIEUP * +U+C82E(2);; # HANGUL SYLLABLE CIEUC E PIEUPSIOS +U+C82F(2);; # HANGUL SYLLABLE CIEUC E SIOS * +U+C830(2);; # HANGUL SYLLABLE CIEUC E SSANGSIOS +U+C831(2);; # HANGUL SYLLABLE CIEUC E IEUNG * +U+C832(2);; # HANGUL SYLLABLE CIEUC E CIEUC +U+C833(2);; # HANGUL SYLLABLE CIEUC E CHIEUCH +U+C834(2);; # HANGUL SYLLABLE CIEUC E KHIEUKH +U+C835(2);; # HANGUL SYLLABLE CIEUC E THIEUTH +U+C836(2);; # HANGUL SYLLABLE CIEUC E PHIEUPH +U+C837(2);; # HANGUL SYLLABLE CIEUC E HIEUH +U+C838(2);; # HANGUL SYLLABLE CIEUC YEO * +U+C839(2);; # HANGUL SYLLABLE CIEUC YEO KIYEOK +U+C83A(2);; # HANGUL SYLLABLE CIEUC YEO SSANGKIYEOK +U+C83B(2);; # HANGUL SYLLABLE CIEUC YEO KIYEOKSIOS +U+C83C(2);; # HANGUL SYLLABLE CIEUC YEO NIEUN * +U+C83D(2);; # HANGUL SYLLABLE CIEUC YEO NIEUNCIEUC +U+C83E(2);; # HANGUL SYLLABLE CIEUC YEO NIEUNHIEUH +U+C83F(2);; # HANGUL SYLLABLE CIEUC YEO TIKEUT +U+C840(2);; # HANGUL SYLLABLE CIEUC YEO RIEUL * +U+C841(2);; # HANGUL SYLLABLE CIEUC YEO RIEULKIYEOK +U+C842(2);; # HANGUL SYLLABLE CIEUC YEO RIEULMIEUM +U+C843(2);; # HANGUL SYLLABLE CIEUC YEO RIEULPIEUP +U+C844(2);; # HANGUL SYLLABLE CIEUC YEO RIEULSIOS +U+C845(2);; # HANGUL SYLLABLE CIEUC YEO RIEULTHIEUTH +U+C846(2);; # HANGUL SYLLABLE CIEUC YEO RIEULPHIEUPH +U+C847(2);; # HANGUL SYLLABLE CIEUC YEO RIEULHIEUH +U+C848(2);; # HANGUL SYLLABLE CIEUC YEO MIEUM * +U+C849(2);; # HANGUL SYLLABLE CIEUC YEO PIEUP * +U+C84A(2);; # HANGUL SYLLABLE CIEUC YEO PIEUPSIOS +U+C84B(2);; # HANGUL SYLLABLE CIEUC YEO SIOS +U+C84C(2);; # HANGUL SYLLABLE CIEUC YEO SSANGSIOS * +U+C84D(2);; # HANGUL SYLLABLE CIEUC YEO IEUNG * +U+C84E(2);; # HANGUL SYLLABLE CIEUC YEO CIEUC +U+C84F(2);; # HANGUL SYLLABLE CIEUC YEO CHIEUCH +U+C850(2);; # HANGUL SYLLABLE CIEUC YEO KHIEUKH +U+C851(2);; # HANGUL SYLLABLE CIEUC YEO THIEUTH +U+C852(2);; # HANGUL SYLLABLE CIEUC YEO PHIEUPH +U+C853(2);; # HANGUL SYLLABLE CIEUC YEO HIEUH +U+C854(2);; # HANGUL SYLLABLE CIEUC YE * +U+C855(2);; # HANGUL SYLLABLE CIEUC YE KIYEOK +U+C856(2);; # HANGUL SYLLABLE CIEUC YE SSANGKIYEOK +U+C857(2);; # HANGUL SYLLABLE CIEUC YE KIYEOKSIOS +U+C858(2);; # HANGUL SYLLABLE CIEUC YE NIEUN +U+C859(2);; # HANGUL SYLLABLE CIEUC YE NIEUNCIEUC +U+C85A(2);; # HANGUL SYLLABLE CIEUC YE NIEUNHIEUH +U+C85B(2);; # HANGUL SYLLABLE CIEUC YE TIKEUT +U+C85C(2);; # HANGUL SYLLABLE CIEUC YE RIEUL +U+C85D(2);; # HANGUL SYLLABLE CIEUC YE RIEULKIYEOK +U+C85E(2);; # HANGUL SYLLABLE CIEUC YE RIEULMIEUM +U+C85F(2);; # HANGUL SYLLABLE CIEUC YE RIEULPIEUP +U+C860(2);; # HANGUL SYLLABLE CIEUC YE RIEULSIOS +U+C861(2);; # HANGUL SYLLABLE CIEUC YE RIEULTHIEUTH +U+C862(2);; # HANGUL SYLLABLE CIEUC YE RIEULPHIEUPH +U+C863(2);; # HANGUL SYLLABLE CIEUC YE RIEULHIEUH +U+C864(2);; # HANGUL SYLLABLE CIEUC YE MIEUM +U+C865(2);; # HANGUL SYLLABLE CIEUC YE PIEUP +U+C866(2);; # HANGUL SYLLABLE CIEUC YE PIEUPSIOS +U+C867(2);; # HANGUL SYLLABLE CIEUC YE SIOS +U+C868(2);; # HANGUL SYLLABLE CIEUC YE SSANGSIOS +U+C869(2);; # HANGUL SYLLABLE CIEUC YE IEUNG +U+C86A(2);; # HANGUL SYLLABLE CIEUC YE CIEUC +U+C86B(2);; # HANGUL SYLLABLE CIEUC YE CHIEUCH +U+C86C(2);; # HANGUL SYLLABLE CIEUC YE KHIEUKH +U+C86D(2);; # HANGUL SYLLABLE CIEUC YE THIEUTH +U+C86E(2);; # HANGUL SYLLABLE CIEUC YE PHIEUPH +U+C86F(2);; # HANGUL SYLLABLE CIEUC YE HIEUH +U+C870(2);; # HANGUL SYLLABLE CIEUC O * +U+C871(2);; # HANGUL SYLLABLE CIEUC O KIYEOK * +U+C872(2);; # HANGUL SYLLABLE CIEUC O SSANGKIYEOK +U+C873(2);; # HANGUL SYLLABLE CIEUC O KIYEOKSIOS +U+C874(2);; # HANGUL SYLLABLE CIEUC O NIEUN * +U+C875(2);; # HANGUL SYLLABLE CIEUC O NIEUNCIEUC +U+C876(2);; # HANGUL SYLLABLE CIEUC O NIEUNHIEUH +U+C877(2);; # HANGUL SYLLABLE CIEUC O TIKEUT +U+C878(2);; # HANGUL SYLLABLE CIEUC O RIEUL * +U+C879(2);; # HANGUL SYLLABLE CIEUC O RIEULKIYEOK +U+C87A(2);; # HANGUL SYLLABLE CIEUC O RIEULMIEUM * +U+C87B(2);; # HANGUL SYLLABLE CIEUC O RIEULPIEUP +U+C87C(2);; # HANGUL SYLLABLE CIEUC O RIEULSIOS +U+C87D(2);; # HANGUL SYLLABLE CIEUC O RIEULTHIEUTH +U+C87E(2);; # HANGUL SYLLABLE CIEUC O RIEULPHIEUPH +U+C87F(2);; # HANGUL SYLLABLE CIEUC O RIEULHIEUH +U+C880(2);; # HANGUL SYLLABLE CIEUC O MIEUM * +U+C881(2);; # HANGUL SYLLABLE CIEUC O PIEUP * +U+C882(2);; # HANGUL SYLLABLE CIEUC O PIEUPSIOS +U+C883(2);; # HANGUL SYLLABLE CIEUC O SIOS * +U+C884(2);; # HANGUL SYLLABLE CIEUC O SSANGSIOS +U+C885(2);; # HANGUL SYLLABLE CIEUC O IEUNG * +U+C886(2);; # HANGUL SYLLABLE CIEUC O CIEUC * +U+C887(2);; # HANGUL SYLLABLE CIEUC O CHIEUCH * +U+C888(2);; # HANGUL SYLLABLE CIEUC O KHIEUKH +U+C889(2);; # HANGUL SYLLABLE CIEUC O THIEUTH +U+C88A(2);; # HANGUL SYLLABLE CIEUC O PHIEUPH +U+C88B(2);; # HANGUL SYLLABLE CIEUC O HIEUH * +U+C88C(2);; # HANGUL SYLLABLE CIEUC WA * +U+C88D(2);; # HANGUL SYLLABLE CIEUC WA KIYEOK * +U+C88E(2);; # HANGUL SYLLABLE CIEUC WA SSANGKIYEOK +U+C88F(2);; # HANGUL SYLLABLE CIEUC WA KIYEOKSIOS +U+C890(2);; # HANGUL SYLLABLE CIEUC WA NIEUN +U+C891(2);; # HANGUL SYLLABLE CIEUC WA NIEUNCIEUC +U+C892(2);; # HANGUL SYLLABLE CIEUC WA NIEUNHIEUH +U+C893(2);; # HANGUL SYLLABLE CIEUC WA TIKEUT +U+C894(2);; # HANGUL SYLLABLE CIEUC WA RIEUL * +U+C895(2);; # HANGUL SYLLABLE CIEUC WA RIEULKIYEOK +U+C896(2);; # HANGUL SYLLABLE CIEUC WA RIEULMIEUM +U+C897(2);; # HANGUL SYLLABLE CIEUC WA RIEULPIEUP +U+C898(2);; # HANGUL SYLLABLE CIEUC WA RIEULSIOS +U+C899(2);; # HANGUL SYLLABLE CIEUC WA RIEULTHIEUTH +U+C89A(2);; # HANGUL SYLLABLE CIEUC WA RIEULPHIEUPH +U+C89B(2);; # HANGUL SYLLABLE CIEUC WA RIEULHIEUH +U+C89C(2);; # HANGUL SYLLABLE CIEUC WA MIEUM +U+C89D(2);; # HANGUL SYLLABLE CIEUC WA PIEUP * +U+C89E(2);; # HANGUL SYLLABLE CIEUC WA PIEUPSIOS +U+C89F(2);; # HANGUL SYLLABLE CIEUC WA SIOS * +U+C8A0(2);; # HANGUL SYLLABLE CIEUC WA SSANGSIOS +U+C8A1(2);; # HANGUL SYLLABLE CIEUC WA IEUNG * +U+C8A2(2);; # HANGUL SYLLABLE CIEUC WA CIEUC +U+C8A3(2);; # HANGUL SYLLABLE CIEUC WA CHIEUCH +U+C8A4(2);; # HANGUL SYLLABLE CIEUC WA KHIEUKH +U+C8A5(2);; # HANGUL SYLLABLE CIEUC WA THIEUTH +U+C8A6(2);; # HANGUL SYLLABLE CIEUC WA PHIEUPH +U+C8A7(2);; # HANGUL SYLLABLE CIEUC WA HIEUH +U+C8A8(2);; # HANGUL SYLLABLE CIEUC WAE * +U+C8A9(2);; # HANGUL SYLLABLE CIEUC WAE KIYEOK +U+C8AA(2);; # HANGUL SYLLABLE CIEUC WAE SSANGKIYEOK +U+C8AB(2);; # HANGUL SYLLABLE CIEUC WAE KIYEOKSIOS +U+C8AC(2);; # HANGUL SYLLABLE CIEUC WAE NIEUN +U+C8AD(2);; # HANGUL SYLLABLE CIEUC WAE NIEUNCIEUC +U+C8AE(2);; # HANGUL SYLLABLE CIEUC WAE NIEUNHIEUH +U+C8AF(2);; # HANGUL SYLLABLE CIEUC WAE TIKEUT +U+C8B0(2);; # HANGUL SYLLABLE CIEUC WAE RIEUL +U+C8B1(2);; # HANGUL SYLLABLE CIEUC WAE RIEULKIYEOK +U+C8B2(2);; # HANGUL SYLLABLE CIEUC WAE RIEULMIEUM +U+C8B3(2);; # HANGUL SYLLABLE CIEUC WAE RIEULPIEUP +U+C8B4(2);; # HANGUL SYLLABLE CIEUC WAE RIEULSIOS +U+C8B5(2);; # HANGUL SYLLABLE CIEUC WAE RIEULTHIEUTH +U+C8B6(2);; # HANGUL SYLLABLE CIEUC WAE RIEULPHIEUPH +U+C8B7(2);; # HANGUL SYLLABLE CIEUC WAE RIEULHIEUH +U+C8B8(2);; # HANGUL SYLLABLE CIEUC WAE MIEUM +U+C8B9(2);; # HANGUL SYLLABLE CIEUC WAE PIEUP +U+C8BA(2);; # HANGUL SYLLABLE CIEUC WAE PIEUPSIOS +U+C8BB(2);; # HANGUL SYLLABLE CIEUC WAE SIOS +U+C8BC(2);; # HANGUL SYLLABLE CIEUC WAE SSANGSIOS * +U+C8BD(2);; # HANGUL SYLLABLE CIEUC WAE IEUNG * +U+C8BE(2);; # HANGUL SYLLABLE CIEUC WAE CIEUC +U+C8BF(2);; # HANGUL SYLLABLE CIEUC WAE CHIEUCH +U+C8C0(2);; # HANGUL SYLLABLE CIEUC WAE KHIEUKH +U+C8C1(2);; # HANGUL SYLLABLE CIEUC WAE THIEUTH +U+C8C2(2);; # HANGUL SYLLABLE CIEUC WAE PHIEUPH +U+C8C3(2);; # HANGUL SYLLABLE CIEUC WAE HIEUH +U+C8C4(2);; # HANGUL SYLLABLE CIEUC OE * +U+C8C5(2);; # HANGUL SYLLABLE CIEUC OE KIYEOK +U+C8C6(2);; # HANGUL SYLLABLE CIEUC OE SSANGKIYEOK +U+C8C7(2);; # HANGUL SYLLABLE CIEUC OE KIYEOKSIOS +U+C8C8(2);; # HANGUL SYLLABLE CIEUC OE NIEUN * +U+C8C9(2);; # HANGUL SYLLABLE CIEUC OE NIEUNCIEUC +U+C8CA(2);; # HANGUL SYLLABLE CIEUC OE NIEUNHIEUH +U+C8CB(2);; # HANGUL SYLLABLE CIEUC OE TIKEUT +U+C8CC(2);; # HANGUL SYLLABLE CIEUC OE RIEUL * +U+C8CD(2);; # HANGUL SYLLABLE CIEUC OE RIEULKIYEOK +U+C8CE(2);; # HANGUL SYLLABLE CIEUC OE RIEULMIEUM +U+C8CF(2);; # HANGUL SYLLABLE CIEUC OE RIEULPIEUP +U+C8D0(2);; # HANGUL SYLLABLE CIEUC OE RIEULSIOS +U+C8D1(2);; # HANGUL SYLLABLE CIEUC OE RIEULTHIEUTH +U+C8D2(2);; # HANGUL SYLLABLE CIEUC OE RIEULPHIEUPH +U+C8D3(2);; # HANGUL SYLLABLE CIEUC OE RIEULHIEUH +U+C8D4(2);; # HANGUL SYLLABLE CIEUC OE MIEUM * +U+C8D5(2);; # HANGUL SYLLABLE CIEUC OE PIEUP * +U+C8D6(2);; # HANGUL SYLLABLE CIEUC OE PIEUPSIOS +U+C8D7(2);; # HANGUL SYLLABLE CIEUC OE SIOS * +U+C8D8(2);; # HANGUL SYLLABLE CIEUC OE SSANGSIOS +U+C8D9(2);; # HANGUL SYLLABLE CIEUC OE IEUNG * +U+C8DA(2);; # HANGUL SYLLABLE CIEUC OE CIEUC +U+C8DB(2);; # HANGUL SYLLABLE CIEUC OE CHIEUCH +U+C8DC(2);; # HANGUL SYLLABLE CIEUC OE KHIEUKH +U+C8DD(2);; # HANGUL SYLLABLE CIEUC OE THIEUTH +U+C8DE(2);; # HANGUL SYLLABLE CIEUC OE PHIEUPH +U+C8DF(2);; # HANGUL SYLLABLE CIEUC OE HIEUH +U+C8E0(2);; # HANGUL SYLLABLE CIEUC YO * +U+C8E1(2);; # HANGUL SYLLABLE CIEUC YO KIYEOK * +U+C8E2(2);; # HANGUL SYLLABLE CIEUC YO SSANGKIYEOK +U+C8E3(2);; # HANGUL SYLLABLE CIEUC YO KIYEOKSIOS +U+C8E4(2);; # HANGUL SYLLABLE CIEUC YO NIEUN * +U+C8E5(2);; # HANGUL SYLLABLE CIEUC YO NIEUNCIEUC +U+C8E6(2);; # HANGUL SYLLABLE CIEUC YO NIEUNHIEUH +U+C8E7(2);; # HANGUL SYLLABLE CIEUC YO TIKEUT +U+C8E8(2);; # HANGUL SYLLABLE CIEUC YO RIEUL +U+C8E9(2);; # HANGUL SYLLABLE CIEUC YO RIEULKIYEOK +U+C8EA(2);; # HANGUL SYLLABLE CIEUC YO RIEULMIEUM +U+C8EB(2);; # HANGUL SYLLABLE CIEUC YO RIEULPIEUP +U+C8EC(2);; # HANGUL SYLLABLE CIEUC YO RIEULSIOS +U+C8ED(2);; # HANGUL SYLLABLE CIEUC YO RIEULTHIEUTH +U+C8EE(2);; # HANGUL SYLLABLE CIEUC YO RIEULPHIEUPH +U+C8EF(2);; # HANGUL SYLLABLE CIEUC YO RIEULHIEUH +U+C8F0(2);; # HANGUL SYLLABLE CIEUC YO MIEUM +U+C8F1(2);; # HANGUL SYLLABLE CIEUC YO PIEUP +U+C8F2(2);; # HANGUL SYLLABLE CIEUC YO PIEUPSIOS +U+C8F3(2);; # HANGUL SYLLABLE CIEUC YO SIOS +U+C8F4(2);; # HANGUL SYLLABLE CIEUC YO SSANGSIOS +U+C8F5(2);; # HANGUL SYLLABLE CIEUC YO IEUNG * +U+C8F6(2);; # HANGUL SYLLABLE CIEUC YO CIEUC +U+C8F7(2);; # HANGUL SYLLABLE CIEUC YO CHIEUCH +U+C8F8(2);; # HANGUL SYLLABLE CIEUC YO KHIEUKH +U+C8F9(2);; # HANGUL SYLLABLE CIEUC YO THIEUTH +U+C8FA(2);; # HANGUL SYLLABLE CIEUC YO PHIEUPH +U+C8FB(2);; # HANGUL SYLLABLE CIEUC YO HIEUH +U+C8FC(2);; # HANGUL SYLLABLE CIEUC U * +U+C8FD(2);; # HANGUL SYLLABLE CIEUC U KIYEOK * +U+C8FE(2);; # HANGUL SYLLABLE CIEUC U SSANGKIYEOK +U+C8FF(2);; # HANGUL SYLLABLE CIEUC U KIYEOKSIOS +U+C900(2);; # HANGUL SYLLABLE CIEUC U NIEUN * +U+C901(2);; # HANGUL SYLLABLE CIEUC U NIEUNCIEUC +U+C902(2);; # HANGUL SYLLABLE CIEUC U NIEUNHIEUH +U+C903(2);; # HANGUL SYLLABLE CIEUC U TIKEUT +U+C904(2);; # HANGUL SYLLABLE CIEUC U RIEUL * +U+C905(2);; # HANGUL SYLLABLE CIEUC U RIEULKIYEOK * +U+C906(2);; # HANGUL SYLLABLE CIEUC U RIEULMIEUM * +U+C907(2);; # HANGUL SYLLABLE CIEUC U RIEULPIEUP +U+C908(2);; # HANGUL SYLLABLE CIEUC U RIEULSIOS +U+C909(2);; # HANGUL SYLLABLE CIEUC U RIEULTHIEUTH +U+C90A(2);; # HANGUL SYLLABLE CIEUC U RIEULPHIEUPH +U+C90B(2);; # HANGUL SYLLABLE CIEUC U RIEULHIEUH +U+C90C(2);; # HANGUL SYLLABLE CIEUC U MIEUM * +U+C90D(2);; # HANGUL SYLLABLE CIEUC U PIEUP * +U+C90E(2);; # HANGUL SYLLABLE CIEUC U PIEUPSIOS +U+C90F(2);; # HANGUL SYLLABLE CIEUC U SIOS * +U+C910(2);; # HANGUL SYLLABLE CIEUC U SSANGSIOS +U+C911(2);; # HANGUL SYLLABLE CIEUC U IEUNG * +U+C912(2);; # HANGUL SYLLABLE CIEUC U CIEUC +U+C913(2);; # HANGUL SYLLABLE CIEUC U CHIEUCH +U+C914(2);; # HANGUL SYLLABLE CIEUC U KHIEUKH +U+C915(2);; # HANGUL SYLLABLE CIEUC U THIEUTH +U+C916(2);; # HANGUL SYLLABLE CIEUC U PHIEUPH +U+C917(2);; # HANGUL SYLLABLE CIEUC U HIEUH +U+C918(2);; # HANGUL SYLLABLE CIEUC WEO * +U+C919(2);; # HANGUL SYLLABLE CIEUC WEO KIYEOK +U+C91A(2);; # HANGUL SYLLABLE CIEUC WEO SSANGKIYEOK +U+C91B(2);; # HANGUL SYLLABLE CIEUC WEO KIYEOKSIOS +U+C91C(2);; # HANGUL SYLLABLE CIEUC WEO NIEUN +U+C91D(2);; # HANGUL SYLLABLE CIEUC WEO NIEUNCIEUC +U+C91E(2);; # HANGUL SYLLABLE CIEUC WEO NIEUNHIEUH +U+C91F(2);; # HANGUL SYLLABLE CIEUC WEO TIKEUT +U+C920(2);; # HANGUL SYLLABLE CIEUC WEO RIEUL +U+C921(2);; # HANGUL SYLLABLE CIEUC WEO RIEULKIYEOK +U+C922(2);; # HANGUL SYLLABLE CIEUC WEO RIEULMIEUM +U+C923(2);; # HANGUL SYLLABLE CIEUC WEO RIEULPIEUP +U+C924(2);; # HANGUL SYLLABLE CIEUC WEO RIEULSIOS +U+C925(2);; # HANGUL SYLLABLE CIEUC WEO RIEULTHIEUTH +U+C926(2);; # HANGUL SYLLABLE CIEUC WEO RIEULPHIEUPH +U+C927(2);; # HANGUL SYLLABLE CIEUC WEO RIEULHIEUH +U+C928(2);; # HANGUL SYLLABLE CIEUC WEO MIEUM +U+C929(2);; # HANGUL SYLLABLE CIEUC WEO PIEUP +U+C92A(2);; # HANGUL SYLLABLE CIEUC WEO PIEUPSIOS +U+C92B(2);; # HANGUL SYLLABLE CIEUC WEO SIOS +U+C92C(2);; # HANGUL SYLLABLE CIEUC WEO SSANGSIOS * +U+C92D(2);; # HANGUL SYLLABLE CIEUC WEO IEUNG +U+C92E(2);; # HANGUL SYLLABLE CIEUC WEO CIEUC +U+C92F(2);; # HANGUL SYLLABLE CIEUC WEO CHIEUCH +U+C930(2);; # HANGUL SYLLABLE CIEUC WEO KHIEUKH +U+C931(2);; # HANGUL SYLLABLE CIEUC WEO THIEUTH +U+C932(2);; # HANGUL SYLLABLE CIEUC WEO PHIEUPH +U+C933(2);; # HANGUL SYLLABLE CIEUC WEO HIEUH +U+C934(2);; # HANGUL SYLLABLE CIEUC WE * +U+C935(2);; # HANGUL SYLLABLE CIEUC WE KIYEOK +U+C936(2);; # HANGUL SYLLABLE CIEUC WE SSANGKIYEOK +U+C937(2);; # HANGUL SYLLABLE CIEUC WE KIYEOKSIOS +U+C938(2);; # HANGUL SYLLABLE CIEUC WE NIEUN +U+C939(2);; # HANGUL SYLLABLE CIEUC WE NIEUNCIEUC +U+C93A(2);; # HANGUL SYLLABLE CIEUC WE NIEUNHIEUH +U+C93B(2);; # HANGUL SYLLABLE CIEUC WE TIKEUT +U+C93C(2);; # HANGUL SYLLABLE CIEUC WE RIEUL +U+C93D(2);; # HANGUL SYLLABLE CIEUC WE RIEULKIYEOK +U+C93E(2);; # HANGUL SYLLABLE CIEUC WE RIEULMIEUM +U+C93F(2);; # HANGUL SYLLABLE CIEUC WE RIEULPIEUP +U+C940(2);; # HANGUL SYLLABLE CIEUC WE RIEULSIOS +U+C941(2);; # HANGUL SYLLABLE CIEUC WE RIEULTHIEUTH +U+C942(2);; # HANGUL SYLLABLE CIEUC WE RIEULPHIEUPH +U+C943(2);; # HANGUL SYLLABLE CIEUC WE RIEULHIEUH +U+C944(2);; # HANGUL SYLLABLE CIEUC WE MIEUM +U+C945(2);; # HANGUL SYLLABLE CIEUC WE PIEUP +U+C946(2);; # HANGUL SYLLABLE CIEUC WE PIEUPSIOS +U+C947(2);; # HANGUL SYLLABLE CIEUC WE SIOS +U+C948(2);; # HANGUL SYLLABLE CIEUC WE SSANGSIOS +U+C949(2);; # HANGUL SYLLABLE CIEUC WE IEUNG +U+C94A(2);; # HANGUL SYLLABLE CIEUC WE CIEUC +U+C94B(2);; # HANGUL SYLLABLE CIEUC WE CHIEUCH +U+C94C(2);; # HANGUL SYLLABLE CIEUC WE KHIEUKH +U+C94D(2);; # HANGUL SYLLABLE CIEUC WE THIEUTH +U+C94E(2);; # HANGUL SYLLABLE CIEUC WE PHIEUPH +U+C94F(2);; # HANGUL SYLLABLE CIEUC WE HIEUH +U+C950(2);; # HANGUL SYLLABLE CIEUC WI * +U+C951(2);; # HANGUL SYLLABLE CIEUC WI KIYEOK * +U+C952(2);; # HANGUL SYLLABLE CIEUC WI SSANGKIYEOK +U+C953(2);; # HANGUL SYLLABLE CIEUC WI KIYEOKSIOS +U+C954(2);; # HANGUL SYLLABLE CIEUC WI NIEUN * +U+C955(2);; # HANGUL SYLLABLE CIEUC WI NIEUNCIEUC +U+C956(2);; # HANGUL SYLLABLE CIEUC WI NIEUNHIEUH +U+C957(2);; # HANGUL SYLLABLE CIEUC WI TIKEUT +U+C958(2);; # HANGUL SYLLABLE CIEUC WI RIEUL * +U+C959(2);; # HANGUL SYLLABLE CIEUC WI RIEULKIYEOK +U+C95A(2);; # HANGUL SYLLABLE CIEUC WI RIEULMIEUM +U+C95B(2);; # HANGUL SYLLABLE CIEUC WI RIEULPIEUP +U+C95C(2);; # HANGUL SYLLABLE CIEUC WI RIEULSIOS +U+C95D(2);; # HANGUL SYLLABLE CIEUC WI RIEULTHIEUTH +U+C95E(2);; # HANGUL SYLLABLE CIEUC WI RIEULPHIEUPH +U+C95F(2);; # HANGUL SYLLABLE CIEUC WI RIEULHIEUH +U+C960(2);; # HANGUL SYLLABLE CIEUC WI MIEUM * +U+C961(2);; # HANGUL SYLLABLE CIEUC WI PIEUP * +U+C962(2);; # HANGUL SYLLABLE CIEUC WI PIEUPSIOS +U+C963(2);; # HANGUL SYLLABLE CIEUC WI SIOS * +U+C964(2);; # HANGUL SYLLABLE CIEUC WI SSANGSIOS +U+C965(2);; # HANGUL SYLLABLE CIEUC WI IEUNG +U+C966(2);; # HANGUL SYLLABLE CIEUC WI CIEUC +U+C967(2);; # HANGUL SYLLABLE CIEUC WI CHIEUCH +U+C968(2);; # HANGUL SYLLABLE CIEUC WI KHIEUKH +U+C969(2);; # HANGUL SYLLABLE CIEUC WI THIEUTH +U+C96A(2);; # HANGUL SYLLABLE CIEUC WI PHIEUPH +U+C96B(2);; # HANGUL SYLLABLE CIEUC WI HIEUH +U+C96C(2);; # HANGUL SYLLABLE CIEUC YU * +U+C96D(2);; # HANGUL SYLLABLE CIEUC YU KIYEOK +U+C96E(2);; # HANGUL SYLLABLE CIEUC YU SSANGKIYEOK +U+C96F(2);; # HANGUL SYLLABLE CIEUC YU KIYEOKSIOS +U+C970(2);; # HANGUL SYLLABLE CIEUC YU NIEUN * +U+C971(2);; # HANGUL SYLLABLE CIEUC YU NIEUNCIEUC +U+C972(2);; # HANGUL SYLLABLE CIEUC YU NIEUNHIEUH +U+C973(2);; # HANGUL SYLLABLE CIEUC YU TIKEUT +U+C974(2);; # HANGUL SYLLABLE CIEUC YU RIEUL * +U+C975(2);; # HANGUL SYLLABLE CIEUC YU RIEULKIYEOK +U+C976(2);; # HANGUL SYLLABLE CIEUC YU RIEULMIEUM +U+C977(2);; # HANGUL SYLLABLE CIEUC YU RIEULPIEUP +U+C978(2);; # HANGUL SYLLABLE CIEUC YU RIEULSIOS +U+C979(2);; # HANGUL SYLLABLE CIEUC YU RIEULTHIEUTH +U+C97A(2);; # HANGUL SYLLABLE CIEUC YU RIEULPHIEUPH +U+C97B(2);; # HANGUL SYLLABLE CIEUC YU RIEULHIEUH +U+C97C(2);; # HANGUL SYLLABLE CIEUC YU MIEUM * +U+C97D(2);; # HANGUL SYLLABLE CIEUC YU PIEUP +U+C97E(2);; # HANGUL SYLLABLE CIEUC YU PIEUPSIOS +U+C97F(2);; # HANGUL SYLLABLE CIEUC YU SIOS +U+C980(2);; # HANGUL SYLLABLE CIEUC YU SSANGSIOS +U+C981(2);; # HANGUL SYLLABLE CIEUC YU IEUNG +U+C982(2);; # HANGUL SYLLABLE CIEUC YU CIEUC +U+C983(2);; # HANGUL SYLLABLE CIEUC YU CHIEUCH +U+C984(2);; # HANGUL SYLLABLE CIEUC YU KHIEUKH +U+C985(2);; # HANGUL SYLLABLE CIEUC YU THIEUTH +U+C986(2);; # HANGUL SYLLABLE CIEUC YU PHIEUPH +U+C987(2);; # HANGUL SYLLABLE CIEUC YU HIEUH +U+C988(2);; # HANGUL SYLLABLE CIEUC EU * +U+C989(2);; # HANGUL SYLLABLE CIEUC EU KIYEOK * +U+C98A(2);; # HANGUL SYLLABLE CIEUC EU SSANGKIYEOK +U+C98B(2);; # HANGUL SYLLABLE CIEUC EU KIYEOKSIOS +U+C98C(2);; # HANGUL SYLLABLE CIEUC EU NIEUN * +U+C98D(2);; # HANGUL SYLLABLE CIEUC EU NIEUNCIEUC +U+C98E(2);; # HANGUL SYLLABLE CIEUC EU NIEUNHIEUH +U+C98F(2);; # HANGUL SYLLABLE CIEUC EU TIKEUT +U+C990(2);; # HANGUL SYLLABLE CIEUC EU RIEUL * +U+C991(2);; # HANGUL SYLLABLE CIEUC EU RIEULKIYEOK +U+C992(2);; # HANGUL SYLLABLE CIEUC EU RIEULMIEUM +U+C993(2);; # HANGUL SYLLABLE CIEUC EU RIEULPIEUP +U+C994(2);; # HANGUL SYLLABLE CIEUC EU RIEULSIOS +U+C995(2);; # HANGUL SYLLABLE CIEUC EU RIEULTHIEUTH +U+C996(2);; # HANGUL SYLLABLE CIEUC EU RIEULPHIEUPH +U+C997(2);; # HANGUL SYLLABLE CIEUC EU RIEULHIEUH +U+C998(2);; # HANGUL SYLLABLE CIEUC EU MIEUM * +U+C999(2);; # HANGUL SYLLABLE CIEUC EU PIEUP * +U+C99A(2);; # HANGUL SYLLABLE CIEUC EU PIEUPSIOS +U+C99B(2);; # HANGUL SYLLABLE CIEUC EU SIOS * +U+C99C(2);; # HANGUL SYLLABLE CIEUC EU SSANGSIOS +U+C99D(2);; # HANGUL SYLLABLE CIEUC EU IEUNG * +U+C99E(2);; # HANGUL SYLLABLE CIEUC EU CIEUC +U+C99F(2);; # HANGUL SYLLABLE CIEUC EU CHIEUCH +U+C9A0(2);; # HANGUL SYLLABLE CIEUC EU KHIEUKH +U+C9A1(2);; # HANGUL SYLLABLE CIEUC EU THIEUTH +U+C9A2(2);; # HANGUL SYLLABLE CIEUC EU PHIEUPH +U+C9A3(2);; # HANGUL SYLLABLE CIEUC EU HIEUH +U+C9A4(2);; # HANGUL SYLLABLE CIEUC YI +U+C9A5(2);; # HANGUL SYLLABLE CIEUC YI KIYEOK +U+C9A6(2);; # HANGUL SYLLABLE CIEUC YI SSANGKIYEOK +U+C9A7(2);; # HANGUL SYLLABLE CIEUC YI KIYEOKSIOS +U+C9A8(2);; # HANGUL SYLLABLE CIEUC YI NIEUN +U+C9A9(2);; # HANGUL SYLLABLE CIEUC YI NIEUNCIEUC +U+C9AA(2);; # HANGUL SYLLABLE CIEUC YI NIEUNHIEUH +U+C9AB(2);; # HANGUL SYLLABLE CIEUC YI TIKEUT +U+C9AC(2);; # HANGUL SYLLABLE CIEUC YI RIEUL +U+C9AD(2);; # HANGUL SYLLABLE CIEUC YI RIEULKIYEOK +U+C9AE(2);; # HANGUL SYLLABLE CIEUC YI RIEULMIEUM +U+C9AF(2);; # HANGUL SYLLABLE CIEUC YI RIEULPIEUP +U+C9B0(2);; # HANGUL SYLLABLE CIEUC YI RIEULSIOS +U+C9B1(2);; # HANGUL SYLLABLE CIEUC YI RIEULTHIEUTH +U+C9B2(2);; # HANGUL SYLLABLE CIEUC YI RIEULPHIEUPH +U+C9B3(2);; # HANGUL SYLLABLE CIEUC YI RIEULHIEUH +U+C9B4(2);; # HANGUL SYLLABLE CIEUC YI MIEUM +U+C9B5(2);; # HANGUL SYLLABLE CIEUC YI PIEUP +U+C9B6(2);; # HANGUL SYLLABLE CIEUC YI PIEUPSIOS +U+C9B7(2);; # HANGUL SYLLABLE CIEUC YI SIOS +U+C9B8(2);; # HANGUL SYLLABLE CIEUC YI SSANGSIOS +U+C9B9(2);; # HANGUL SYLLABLE CIEUC YI IEUNG +U+C9BA(2);; # HANGUL SYLLABLE CIEUC YI CIEUC +U+C9BB(2);; # HANGUL SYLLABLE CIEUC YI CHIEUCH +U+C9BC(2);; # HANGUL SYLLABLE CIEUC YI KHIEUKH +U+C9BD(2);; # HANGUL SYLLABLE CIEUC YI THIEUTH +U+C9BE(2);; # HANGUL SYLLABLE CIEUC YI PHIEUPH +U+C9BF(2);; # HANGUL SYLLABLE CIEUC YI HIEUH +U+C9C0(2);; # HANGUL SYLLABLE CIEUC I * +U+C9C1(2);; # HANGUL SYLLABLE CIEUC I KIYEOK * +U+C9C2(2);; # HANGUL SYLLABLE CIEUC I SSANGKIYEOK +U+C9C3(2);; # HANGUL SYLLABLE CIEUC I KIYEOKSIOS +U+C9C4(2);; # HANGUL SYLLABLE CIEUC I NIEUN * +U+C9C5(2);; # HANGUL SYLLABLE CIEUC I NIEUNCIEUC +U+C9C6(2);; # HANGUL SYLLABLE CIEUC I NIEUNHIEUH +U+C9C7(2);; # HANGUL SYLLABLE CIEUC I TIKEUT * +U+C9C8(2);; # HANGUL SYLLABLE CIEUC I RIEUL * +U+C9C9(2);; # HANGUL SYLLABLE CIEUC I RIEULKIYEOK +U+C9CA(2);; # HANGUL SYLLABLE CIEUC I RIEULMIEUM * +U+C9CB(2);; # HANGUL SYLLABLE CIEUC I RIEULPIEUP +U+C9CC(2);; # HANGUL SYLLABLE CIEUC I RIEULSIOS +U+C9CD(2);; # HANGUL SYLLABLE CIEUC I RIEULTHIEUTH +U+C9CE(2);; # HANGUL SYLLABLE CIEUC I RIEULPHIEUPH +U+C9CF(2);; # HANGUL SYLLABLE CIEUC I RIEULHIEUH +U+C9D0(2);; # HANGUL SYLLABLE CIEUC I MIEUM * +U+C9D1(2);; # HANGUL SYLLABLE CIEUC I PIEUP * +U+C9D2(2);; # HANGUL SYLLABLE CIEUC I PIEUPSIOS +U+C9D3(2);; # HANGUL SYLLABLE CIEUC I SIOS * +U+C9D4(2);; # HANGUL SYLLABLE CIEUC I SSANGSIOS +U+C9D5(2);; # HANGUL SYLLABLE CIEUC I IEUNG * +U+C9D6(2);; # HANGUL SYLLABLE CIEUC I CIEUC * +U+C9D7(2);; # HANGUL SYLLABLE CIEUC I CHIEUCH +U+C9D8(2);; # HANGUL SYLLABLE CIEUC I KHIEUKH +U+C9D9(2);; # HANGUL SYLLABLE CIEUC I THIEUTH * +U+C9DA(2);; # HANGUL SYLLABLE CIEUC I PHIEUPH * +U+C9DB(2);; # HANGUL SYLLABLE CIEUC I HIEUH +U+C9DC(2);; # HANGUL SYLLABLE SSANGCIEUC A * +U+C9DD(2);; # HANGUL SYLLABLE SSANGCIEUC A KIYEOK * +U+C9DE(2);; # HANGUL SYLLABLE SSANGCIEUC A SSANGKIYEOK +U+C9DF(2);; # HANGUL SYLLABLE SSANGCIEUC A KIYEOKSIOS +U+C9E0(2);; # HANGUL SYLLABLE SSANGCIEUC A NIEUN * +U+C9E1(2);; # HANGUL SYLLABLE SSANGCIEUC A NIEUNCIEUC +U+C9E2(2);; # HANGUL SYLLABLE SSANGCIEUC A NIEUNHIEUH * +U+C9E3(2);; # HANGUL SYLLABLE SSANGCIEUC A TIKEUT +U+C9E4(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEUL * +U+C9E5(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULKIYEOK +U+C9E6(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULMIEUM +U+C9E7(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULPIEUP * +U+C9E8(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULSIOS +U+C9E9(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULTHIEUTH +U+C9EA(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULPHIEUPH +U+C9EB(2);; # HANGUL SYLLABLE SSANGCIEUC A RIEULHIEUH +U+C9EC(2);; # HANGUL SYLLABLE SSANGCIEUC A MIEUM * +U+C9ED(2);; # HANGUL SYLLABLE SSANGCIEUC A PIEUP * +U+C9EE(2);; # HANGUL SYLLABLE SSANGCIEUC A PIEUPSIOS +U+C9EF(2);; # HANGUL SYLLABLE SSANGCIEUC A SIOS * +U+C9F0(2);; # HANGUL SYLLABLE SSANGCIEUC A SSANGSIOS * +U+C9F1(2);; # HANGUL SYLLABLE SSANGCIEUC A IEUNG * +U+C9F2(2);; # HANGUL SYLLABLE SSANGCIEUC A CIEUC +U+C9F3(2);; # HANGUL SYLLABLE SSANGCIEUC A CHIEUCH +U+C9F4(2);; # HANGUL SYLLABLE SSANGCIEUC A KHIEUKH +U+C9F5(2);; # HANGUL SYLLABLE SSANGCIEUC A THIEUTH +U+C9F6(2);; # HANGUL SYLLABLE SSANGCIEUC A PHIEUPH +U+C9F7(2);; # HANGUL SYLLABLE SSANGCIEUC A HIEUH +U+C9F8(2);; # HANGUL SYLLABLE SSANGCIEUC AE * +U+C9F9(2);; # HANGUL SYLLABLE SSANGCIEUC AE KIYEOK * +U+C9FA(2);; # HANGUL SYLLABLE SSANGCIEUC AE SSANGKIYEOK +U+C9FB(2);; # HANGUL SYLLABLE SSANGCIEUC AE KIYEOKSIOS +U+C9FC(2);; # HANGUL SYLLABLE SSANGCIEUC AE NIEUN * +U+C9FD(2);; # HANGUL SYLLABLE SSANGCIEUC AE NIEUNCIEUC +U+C9FE(2);; # HANGUL SYLLABLE SSANGCIEUC AE NIEUNHIEUH +U+C9FF(2);; # HANGUL SYLLABLE SSANGCIEUC AE TIKEUT +U+CA00(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEUL * +U+CA01(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULKIYEOK +U+CA02(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULMIEUM +U+CA03(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULPIEUP +U+CA04(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULSIOS +U+CA05(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULTHIEUTH +U+CA06(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULPHIEUPH +U+CA07(2);; # HANGUL SYLLABLE SSANGCIEUC AE RIEULHIEUH +U+CA08(2);; # HANGUL SYLLABLE SSANGCIEUC AE MIEUM * +U+CA09(2);; # HANGUL SYLLABLE SSANGCIEUC AE PIEUP * +U+CA0A(2);; # HANGUL SYLLABLE SSANGCIEUC AE PIEUPSIOS +U+CA0B(2);; # HANGUL SYLLABLE SSANGCIEUC AE SIOS * +U+CA0C(2);; # HANGUL SYLLABLE SSANGCIEUC AE SSANGSIOS * +U+CA0D(2);; # HANGUL SYLLABLE SSANGCIEUC AE IEUNG * +U+CA0E(2);; # HANGUL SYLLABLE SSANGCIEUC AE CIEUC +U+CA0F(2);; # HANGUL SYLLABLE SSANGCIEUC AE CHIEUCH +U+CA10(2);; # HANGUL SYLLABLE SSANGCIEUC AE KHIEUKH +U+CA11(2);; # HANGUL SYLLABLE SSANGCIEUC AE THIEUTH +U+CA12(2);; # HANGUL SYLLABLE SSANGCIEUC AE PHIEUPH +U+CA13(2);; # HANGUL SYLLABLE SSANGCIEUC AE HIEUH +U+CA14(2);; # HANGUL SYLLABLE SSANGCIEUC YA * +U+CA15(2);; # HANGUL SYLLABLE SSANGCIEUC YA KIYEOK +U+CA16(2);; # HANGUL SYLLABLE SSANGCIEUC YA SSANGKIYEOK +U+CA17(2);; # HANGUL SYLLABLE SSANGCIEUC YA KIYEOKSIOS +U+CA18(2);; # HANGUL SYLLABLE SSANGCIEUC YA NIEUN * +U+CA19(2);; # HANGUL SYLLABLE SSANGCIEUC YA NIEUNCIEUC +U+CA1A(2);; # HANGUL SYLLABLE SSANGCIEUC YA NIEUNHIEUH +U+CA1B(2);; # HANGUL SYLLABLE SSANGCIEUC YA TIKEUT +U+CA1C(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEUL +U+CA1D(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULKIYEOK +U+CA1E(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULMIEUM +U+CA1F(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULPIEUP +U+CA20(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULSIOS +U+CA21(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULTHIEUTH +U+CA22(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULPHIEUPH +U+CA23(2);; # HANGUL SYLLABLE SSANGCIEUC YA RIEULHIEUH +U+CA24(2);; # HANGUL SYLLABLE SSANGCIEUC YA MIEUM +U+CA25(2);; # HANGUL SYLLABLE SSANGCIEUC YA PIEUP +U+CA26(2);; # HANGUL SYLLABLE SSANGCIEUC YA PIEUPSIOS +U+CA27(2);; # HANGUL SYLLABLE SSANGCIEUC YA SIOS +U+CA28(2);; # HANGUL SYLLABLE SSANGCIEUC YA SSANGSIOS +U+CA29(2);; # HANGUL SYLLABLE SSANGCIEUC YA IEUNG * +U+CA2A(2);; # HANGUL SYLLABLE SSANGCIEUC YA CIEUC +U+CA2B(2);; # HANGUL SYLLABLE SSANGCIEUC YA CHIEUCH +U+CA2C(2);; # HANGUL SYLLABLE SSANGCIEUC YA KHIEUKH +U+CA2D(2);; # HANGUL SYLLABLE SSANGCIEUC YA THIEUTH +U+CA2E(2);; # HANGUL SYLLABLE SSANGCIEUC YA PHIEUPH +U+CA2F(2);; # HANGUL SYLLABLE SSANGCIEUC YA HIEUH +U+CA30(2);; # HANGUL SYLLABLE SSANGCIEUC YAE +U+CA31(2);; # HANGUL SYLLABLE SSANGCIEUC YAE KIYEOK +U+CA32(2);; # HANGUL SYLLABLE SSANGCIEUC YAE SSANGKIYEOK +U+CA33(2);; # HANGUL SYLLABLE SSANGCIEUC YAE KIYEOKSIOS +U+CA34(2);; # HANGUL SYLLABLE SSANGCIEUC YAE NIEUN +U+CA35(2);; # HANGUL SYLLABLE SSANGCIEUC YAE NIEUNCIEUC +U+CA36(2);; # HANGUL SYLLABLE SSANGCIEUC YAE NIEUNHIEUH +U+CA37(2);; # HANGUL SYLLABLE SSANGCIEUC YAE TIKEUT +U+CA38(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEUL +U+CA39(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULKIYEOK +U+CA3A(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULMIEUM +U+CA3B(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULPIEUP +U+CA3C(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULSIOS +U+CA3D(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULTHIEUTH +U+CA3E(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULPHIEUPH +U+CA3F(2);; # HANGUL SYLLABLE SSANGCIEUC YAE RIEULHIEUH +U+CA40(2);; # HANGUL SYLLABLE SSANGCIEUC YAE MIEUM +U+CA41(2);; # HANGUL SYLLABLE SSANGCIEUC YAE PIEUP +U+CA42(2);; # HANGUL SYLLABLE SSANGCIEUC YAE PIEUPSIOS +U+CA43(2);; # HANGUL SYLLABLE SSANGCIEUC YAE SIOS +U+CA44(2);; # HANGUL SYLLABLE SSANGCIEUC YAE SSANGSIOS +U+CA45(2);; # HANGUL SYLLABLE SSANGCIEUC YAE IEUNG +U+CA46(2);; # HANGUL SYLLABLE SSANGCIEUC YAE CIEUC +U+CA47(2);; # HANGUL SYLLABLE SSANGCIEUC YAE CHIEUCH +U+CA48(2);; # HANGUL SYLLABLE SSANGCIEUC YAE KHIEUKH +U+CA49(2);; # HANGUL SYLLABLE SSANGCIEUC YAE THIEUTH +U+CA4A(2);; # HANGUL SYLLABLE SSANGCIEUC YAE PHIEUPH +U+CA4B(2);; # HANGUL SYLLABLE SSANGCIEUC YAE HIEUH +U+CA4C(2);; # HANGUL SYLLABLE SSANGCIEUC EO * +U+CA4D(2);; # HANGUL SYLLABLE SSANGCIEUC EO KIYEOK * +U+CA4E(2);; # HANGUL SYLLABLE SSANGCIEUC EO SSANGKIYEOK +U+CA4F(2);; # HANGUL SYLLABLE SSANGCIEUC EO KIYEOKSIOS +U+CA50(2);; # HANGUL SYLLABLE SSANGCIEUC EO NIEUN * +U+CA51(2);; # HANGUL SYLLABLE SSANGCIEUC EO NIEUNCIEUC +U+CA52(2);; # HANGUL SYLLABLE SSANGCIEUC EO NIEUNHIEUH +U+CA53(2);; # HANGUL SYLLABLE SSANGCIEUC EO TIKEUT +U+CA54(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEUL * +U+CA55(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULKIYEOK +U+CA56(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULMIEUM +U+CA57(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULPIEUP +U+CA58(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULSIOS +U+CA59(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULTHIEUTH +U+CA5A(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULPHIEUPH +U+CA5B(2);; # HANGUL SYLLABLE SSANGCIEUC EO RIEULHIEUH +U+CA5C(2);; # HANGUL SYLLABLE SSANGCIEUC EO MIEUM * +U+CA5D(2);; # HANGUL SYLLABLE SSANGCIEUC EO PIEUP * +U+CA5E(2);; # HANGUL SYLLABLE SSANGCIEUC EO PIEUPSIOS +U+CA5F(2);; # HANGUL SYLLABLE SSANGCIEUC EO SIOS * +U+CA60(2);; # HANGUL SYLLABLE SSANGCIEUC EO SSANGSIOS * +U+CA61(2);; # HANGUL SYLLABLE SSANGCIEUC EO IEUNG * +U+CA62(2);; # HANGUL SYLLABLE SSANGCIEUC EO CIEUC +U+CA63(2);; # HANGUL SYLLABLE SSANGCIEUC EO CHIEUCH +U+CA64(2);; # HANGUL SYLLABLE SSANGCIEUC EO KHIEUKH +U+CA65(2);; # HANGUL SYLLABLE SSANGCIEUC EO THIEUTH +U+CA66(2);; # HANGUL SYLLABLE SSANGCIEUC EO PHIEUPH +U+CA67(2);; # HANGUL SYLLABLE SSANGCIEUC EO HIEUH +U+CA68(2);; # HANGUL SYLLABLE SSANGCIEUC E * +U+CA69(2);; # HANGUL SYLLABLE SSANGCIEUC E KIYEOK +U+CA6A(2);; # HANGUL SYLLABLE SSANGCIEUC E SSANGKIYEOK +U+CA6B(2);; # HANGUL SYLLABLE SSANGCIEUC E KIYEOKSIOS +U+CA6C(2);; # HANGUL SYLLABLE SSANGCIEUC E NIEUN +U+CA6D(2);; # HANGUL SYLLABLE SSANGCIEUC E NIEUNCIEUC +U+CA6E(2);; # HANGUL SYLLABLE SSANGCIEUC E NIEUNHIEUH +U+CA6F(2);; # HANGUL SYLLABLE SSANGCIEUC E TIKEUT +U+CA70(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEUL +U+CA71(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULKIYEOK +U+CA72(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULMIEUM +U+CA73(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULPIEUP +U+CA74(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULSIOS +U+CA75(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULTHIEUTH +U+CA76(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULPHIEUPH +U+CA77(2);; # HANGUL SYLLABLE SSANGCIEUC E RIEULHIEUH +U+CA78(2);; # HANGUL SYLLABLE SSANGCIEUC E MIEUM +U+CA79(2);; # HANGUL SYLLABLE SSANGCIEUC E PIEUP +U+CA7A(2);; # HANGUL SYLLABLE SSANGCIEUC E PIEUPSIOS +U+CA7B(2);; # HANGUL SYLLABLE SSANGCIEUC E SIOS +U+CA7C(2);; # HANGUL SYLLABLE SSANGCIEUC E SSANGSIOS +U+CA7D(2);; # HANGUL SYLLABLE SSANGCIEUC E IEUNG * +U+CA7E(2);; # HANGUL SYLLABLE SSANGCIEUC E CIEUC +U+CA7F(2);; # HANGUL SYLLABLE SSANGCIEUC E CHIEUCH +U+CA80(2);; # HANGUL SYLLABLE SSANGCIEUC E KHIEUKH +U+CA81(2);; # HANGUL SYLLABLE SSANGCIEUC E THIEUTH +U+CA82(2);; # HANGUL SYLLABLE SSANGCIEUC E PHIEUPH +U+CA83(2);; # HANGUL SYLLABLE SSANGCIEUC E HIEUH +U+CA84(2);; # HANGUL SYLLABLE SSANGCIEUC YEO * +U+CA85(2);; # HANGUL SYLLABLE SSANGCIEUC YEO KIYEOK +U+CA86(2);; # HANGUL SYLLABLE SSANGCIEUC YEO SSANGKIYEOK +U+CA87(2);; # HANGUL SYLLABLE SSANGCIEUC YEO KIYEOKSIOS +U+CA88(2);; # HANGUL SYLLABLE SSANGCIEUC YEO NIEUN +U+CA89(2);; # HANGUL SYLLABLE SSANGCIEUC YEO NIEUNCIEUC +U+CA8A(2);; # HANGUL SYLLABLE SSANGCIEUC YEO NIEUNHIEUH +U+CA8B(2);; # HANGUL SYLLABLE SSANGCIEUC YEO TIKEUT +U+CA8C(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEUL +U+CA8D(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULKIYEOK +U+CA8E(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULMIEUM +U+CA8F(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULPIEUP +U+CA90(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULSIOS +U+CA91(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULTHIEUTH +U+CA92(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULPHIEUPH +U+CA93(2);; # HANGUL SYLLABLE SSANGCIEUC YEO RIEULHIEUH +U+CA94(2);; # HANGUL SYLLABLE SSANGCIEUC YEO MIEUM +U+CA95(2);; # HANGUL SYLLABLE SSANGCIEUC YEO PIEUP +U+CA96(2);; # HANGUL SYLLABLE SSANGCIEUC YEO PIEUPSIOS +U+CA97(2);; # HANGUL SYLLABLE SSANGCIEUC YEO SIOS +U+CA98(2);; # HANGUL SYLLABLE SSANGCIEUC YEO SSANGSIOS * +U+CA99(2);; # HANGUL SYLLABLE SSANGCIEUC YEO IEUNG +U+CA9A(2);; # HANGUL SYLLABLE SSANGCIEUC YEO CIEUC +U+CA9B(2);; # HANGUL SYLLABLE SSANGCIEUC YEO CHIEUCH +U+CA9C(2);; # HANGUL SYLLABLE SSANGCIEUC YEO KHIEUKH +U+CA9D(2);; # HANGUL SYLLABLE SSANGCIEUC YEO THIEUTH +U+CA9E(2);; # HANGUL SYLLABLE SSANGCIEUC YEO PHIEUPH +U+CA9F(2);; # HANGUL SYLLABLE SSANGCIEUC YEO HIEUH +U+CAA0(2);; # HANGUL SYLLABLE SSANGCIEUC YE +U+CAA1(2);; # HANGUL SYLLABLE SSANGCIEUC YE KIYEOK +U+CAA2(2);; # HANGUL SYLLABLE SSANGCIEUC YE SSANGKIYEOK +U+CAA3(2);; # HANGUL SYLLABLE SSANGCIEUC YE KIYEOKSIOS +U+CAA4(2);; # HANGUL SYLLABLE SSANGCIEUC YE NIEUN +U+CAA5(2);; # HANGUL SYLLABLE SSANGCIEUC YE NIEUNCIEUC +U+CAA6(2);; # HANGUL SYLLABLE SSANGCIEUC YE NIEUNHIEUH +U+CAA7(2);; # HANGUL SYLLABLE SSANGCIEUC YE TIKEUT +U+CAA8(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEUL +U+CAA9(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULKIYEOK +U+CAAA(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULMIEUM +U+CAAB(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULPIEUP +U+CAAC(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULSIOS +U+CAAD(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULTHIEUTH +U+CAAE(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULPHIEUPH +U+CAAF(2);; # HANGUL SYLLABLE SSANGCIEUC YE RIEULHIEUH +U+CAB0(2);; # HANGUL SYLLABLE SSANGCIEUC YE MIEUM +U+CAB1(2);; # HANGUL SYLLABLE SSANGCIEUC YE PIEUP +U+CAB2(2);; # HANGUL SYLLABLE SSANGCIEUC YE PIEUPSIOS +U+CAB3(2);; # HANGUL SYLLABLE SSANGCIEUC YE SIOS +U+CAB4(2);; # HANGUL SYLLABLE SSANGCIEUC YE SSANGSIOS +U+CAB5(2);; # HANGUL SYLLABLE SSANGCIEUC YE IEUNG +U+CAB6(2);; # HANGUL SYLLABLE SSANGCIEUC YE CIEUC +U+CAB7(2);; # HANGUL SYLLABLE SSANGCIEUC YE CHIEUCH +U+CAB8(2);; # HANGUL SYLLABLE SSANGCIEUC YE KHIEUKH +U+CAB9(2);; # HANGUL SYLLABLE SSANGCIEUC YE THIEUTH +U+CABA(2);; # HANGUL SYLLABLE SSANGCIEUC YE PHIEUPH +U+CABB(2);; # HANGUL SYLLABLE SSANGCIEUC YE HIEUH +U+CABC(2);; # HANGUL SYLLABLE SSANGCIEUC O * +U+CABD(2);; # HANGUL SYLLABLE SSANGCIEUC O KIYEOK * +U+CABE(2);; # HANGUL SYLLABLE SSANGCIEUC O SSANGKIYEOK +U+CABF(2);; # HANGUL SYLLABLE SSANGCIEUC O KIYEOKSIOS +U+CAC0(2);; # HANGUL SYLLABLE SSANGCIEUC O NIEUN * +U+CAC1(2);; # HANGUL SYLLABLE SSANGCIEUC O NIEUNCIEUC +U+CAC2(2);; # HANGUL SYLLABLE SSANGCIEUC O NIEUNHIEUH +U+CAC3(2);; # HANGUL SYLLABLE SSANGCIEUC O TIKEUT +U+CAC4(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEUL * +U+CAC5(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULKIYEOK +U+CAC6(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULMIEUM +U+CAC7(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULPIEUP +U+CAC8(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULSIOS +U+CAC9(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULTHIEUTH +U+CACA(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULPHIEUPH +U+CACB(2);; # HANGUL SYLLABLE SSANGCIEUC O RIEULHIEUH +U+CACC(2);; # HANGUL SYLLABLE SSANGCIEUC O MIEUM * +U+CACD(2);; # HANGUL SYLLABLE SSANGCIEUC O PIEUP * +U+CACE(2);; # HANGUL SYLLABLE SSANGCIEUC O PIEUPSIOS +U+CACF(2);; # HANGUL SYLLABLE SSANGCIEUC O SIOS * +U+CAD0(2);; # HANGUL SYLLABLE SSANGCIEUC O SSANGSIOS +U+CAD1(2);; # HANGUL SYLLABLE SSANGCIEUC O IEUNG * +U+CAD2(2);; # HANGUL SYLLABLE SSANGCIEUC O CIEUC +U+CAD3(2);; # HANGUL SYLLABLE SSANGCIEUC O CHIEUCH * +U+CAD4(2);; # HANGUL SYLLABLE SSANGCIEUC O KHIEUKH +U+CAD5(2);; # HANGUL SYLLABLE SSANGCIEUC O THIEUTH +U+CAD6(2);; # HANGUL SYLLABLE SSANGCIEUC O PHIEUPH +U+CAD7(2);; # HANGUL SYLLABLE SSANGCIEUC O HIEUH +U+CAD8(2);; # HANGUL SYLLABLE SSANGCIEUC WA * +U+CAD9(2);; # HANGUL SYLLABLE SSANGCIEUC WA KIYEOK * +U+CADA(2);; # HANGUL SYLLABLE SSANGCIEUC WA SSANGKIYEOK +U+CADB(2);; # HANGUL SYLLABLE SSANGCIEUC WA KIYEOKSIOS +U+CADC(2);; # HANGUL SYLLABLE SSANGCIEUC WA NIEUN +U+CADD(2);; # HANGUL SYLLABLE SSANGCIEUC WA NIEUNCIEUC +U+CADE(2);; # HANGUL SYLLABLE SSANGCIEUC WA NIEUNHIEUH +U+CADF(2);; # HANGUL SYLLABLE SSANGCIEUC WA TIKEUT +U+CAE0(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEUL * +U+CAE1(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULKIYEOK +U+CAE2(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULMIEUM +U+CAE3(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULPIEUP +U+CAE4(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULSIOS +U+CAE5(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULTHIEUTH +U+CAE6(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULPHIEUPH +U+CAE7(2);; # HANGUL SYLLABLE SSANGCIEUC WA RIEULHIEUH +U+CAE8(2);; # HANGUL SYLLABLE SSANGCIEUC WA MIEUM +U+CAE9(2);; # HANGUL SYLLABLE SSANGCIEUC WA PIEUP +U+CAEA(2);; # HANGUL SYLLABLE SSANGCIEUC WA PIEUPSIOS +U+CAEB(2);; # HANGUL SYLLABLE SSANGCIEUC WA SIOS +U+CAEC(2);; # HANGUL SYLLABLE SSANGCIEUC WA SSANGSIOS * +U+CAED(2);; # HANGUL SYLLABLE SSANGCIEUC WA IEUNG +U+CAEE(2);; # HANGUL SYLLABLE SSANGCIEUC WA CIEUC +U+CAEF(2);; # HANGUL SYLLABLE SSANGCIEUC WA CHIEUCH +U+CAF0(2);; # HANGUL SYLLABLE SSANGCIEUC WA KHIEUKH +U+CAF1(2);; # HANGUL SYLLABLE SSANGCIEUC WA THIEUTH +U+CAF2(2);; # HANGUL SYLLABLE SSANGCIEUC WA PHIEUPH +U+CAF3(2);; # HANGUL SYLLABLE SSANGCIEUC WA HIEUH +U+CAF4(2);; # HANGUL SYLLABLE SSANGCIEUC WAE * +U+CAF5(2);; # HANGUL SYLLABLE SSANGCIEUC WAE KIYEOK +U+CAF6(2);; # HANGUL SYLLABLE SSANGCIEUC WAE SSANGKIYEOK +U+CAF7(2);; # HANGUL SYLLABLE SSANGCIEUC WAE KIYEOKSIOS +U+CAF8(2);; # HANGUL SYLLABLE SSANGCIEUC WAE NIEUN +U+CAF9(2);; # HANGUL SYLLABLE SSANGCIEUC WAE NIEUNCIEUC +U+CAFA(2);; # HANGUL SYLLABLE SSANGCIEUC WAE NIEUNHIEUH +U+CAFB(2);; # HANGUL SYLLABLE SSANGCIEUC WAE TIKEUT +U+CAFC(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEUL +U+CAFD(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULKIYEOK +U+CAFE(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULMIEUM +U+CAFF(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULPIEUP +U+CB00(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULSIOS +U+CB01(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULTHIEUTH +U+CB02(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULPHIEUPH +U+CB03(2);; # HANGUL SYLLABLE SSANGCIEUC WAE RIEULHIEUH +U+CB04(2);; # HANGUL SYLLABLE SSANGCIEUC WAE MIEUM +U+CB05(2);; # HANGUL SYLLABLE SSANGCIEUC WAE PIEUP +U+CB06(2);; # HANGUL SYLLABLE SSANGCIEUC WAE PIEUPSIOS +U+CB07(2);; # HANGUL SYLLABLE SSANGCIEUC WAE SIOS +U+CB08(2);; # HANGUL SYLLABLE SSANGCIEUC WAE SSANGSIOS * +U+CB09(2);; # HANGUL SYLLABLE SSANGCIEUC WAE IEUNG +U+CB0A(2);; # HANGUL SYLLABLE SSANGCIEUC WAE CIEUC +U+CB0B(2);; # HANGUL SYLLABLE SSANGCIEUC WAE CHIEUCH +U+CB0C(2);; # HANGUL SYLLABLE SSANGCIEUC WAE KHIEUKH +U+CB0D(2);; # HANGUL SYLLABLE SSANGCIEUC WAE THIEUTH +U+CB0E(2);; # HANGUL SYLLABLE SSANGCIEUC WAE PHIEUPH +U+CB0F(2);; # HANGUL SYLLABLE SSANGCIEUC WAE HIEUH +U+CB10(2);; # HANGUL SYLLABLE SSANGCIEUC OE * +U+CB11(2);; # HANGUL SYLLABLE SSANGCIEUC OE KIYEOK +U+CB12(2);; # HANGUL SYLLABLE SSANGCIEUC OE SSANGKIYEOK +U+CB13(2);; # HANGUL SYLLABLE SSANGCIEUC OE KIYEOKSIOS +U+CB14(2);; # HANGUL SYLLABLE SSANGCIEUC OE NIEUN * +U+CB15(2);; # HANGUL SYLLABLE SSANGCIEUC OE NIEUNCIEUC +U+CB16(2);; # HANGUL SYLLABLE SSANGCIEUC OE NIEUNHIEUH +U+CB17(2);; # HANGUL SYLLABLE SSANGCIEUC OE TIKEUT +U+CB18(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEUL * +U+CB19(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULKIYEOK +U+CB1A(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULMIEUM +U+CB1B(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULPIEUP +U+CB1C(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULSIOS +U+CB1D(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULTHIEUTH +U+CB1E(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULPHIEUPH +U+CB1F(2);; # HANGUL SYLLABLE SSANGCIEUC OE RIEULHIEUH +U+CB20(2);; # HANGUL SYLLABLE SSANGCIEUC OE MIEUM * +U+CB21(2);; # HANGUL SYLLABLE SSANGCIEUC OE PIEUP * +U+CB22(2);; # HANGUL SYLLABLE SSANGCIEUC OE PIEUPSIOS +U+CB23(2);; # HANGUL SYLLABLE SSANGCIEUC OE SIOS +U+CB24(2);; # HANGUL SYLLABLE SSANGCIEUC OE SSANGSIOS +U+CB25(2);; # HANGUL SYLLABLE SSANGCIEUC OE IEUNG +U+CB26(2);; # HANGUL SYLLABLE SSANGCIEUC OE CIEUC +U+CB27(2);; # HANGUL SYLLABLE SSANGCIEUC OE CHIEUCH +U+CB28(2);; # HANGUL SYLLABLE SSANGCIEUC OE KHIEUKH +U+CB29(2);; # HANGUL SYLLABLE SSANGCIEUC OE THIEUTH +U+CB2A(2);; # HANGUL SYLLABLE SSANGCIEUC OE PHIEUPH +U+CB2B(2);; # HANGUL SYLLABLE SSANGCIEUC OE HIEUH +U+CB2C(2);; # HANGUL SYLLABLE SSANGCIEUC YO +U+CB2D(2);; # HANGUL SYLLABLE SSANGCIEUC YO KIYEOK +U+CB2E(2);; # HANGUL SYLLABLE SSANGCIEUC YO SSANGKIYEOK +U+CB2F(2);; # HANGUL SYLLABLE SSANGCIEUC YO KIYEOKSIOS +U+CB30(2);; # HANGUL SYLLABLE SSANGCIEUC YO NIEUN +U+CB31(2);; # HANGUL SYLLABLE SSANGCIEUC YO NIEUNCIEUC +U+CB32(2);; # HANGUL SYLLABLE SSANGCIEUC YO NIEUNHIEUH +U+CB33(2);; # HANGUL SYLLABLE SSANGCIEUC YO TIKEUT +U+CB34(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEUL +U+CB35(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULKIYEOK +U+CB36(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULMIEUM +U+CB37(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULPIEUP +U+CB38(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULSIOS +U+CB39(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULTHIEUTH +U+CB3A(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULPHIEUPH +U+CB3B(2);; # HANGUL SYLLABLE SSANGCIEUC YO RIEULHIEUH +U+CB3C(2);; # HANGUL SYLLABLE SSANGCIEUC YO MIEUM +U+CB3D(2);; # HANGUL SYLLABLE SSANGCIEUC YO PIEUP +U+CB3E(2);; # HANGUL SYLLABLE SSANGCIEUC YO PIEUPSIOS +U+CB3F(2);; # HANGUL SYLLABLE SSANGCIEUC YO SIOS +U+CB40(2);; # HANGUL SYLLABLE SSANGCIEUC YO SSANGSIOS +U+CB41(2);; # HANGUL SYLLABLE SSANGCIEUC YO IEUNG * +U+CB42(2);; # HANGUL SYLLABLE SSANGCIEUC YO CIEUC +U+CB43(2);; # HANGUL SYLLABLE SSANGCIEUC YO CHIEUCH +U+CB44(2);; # HANGUL SYLLABLE SSANGCIEUC YO KHIEUKH +U+CB45(2);; # HANGUL SYLLABLE SSANGCIEUC YO THIEUTH +U+CB46(2);; # HANGUL SYLLABLE SSANGCIEUC YO PHIEUPH +U+CB47(2);; # HANGUL SYLLABLE SSANGCIEUC YO HIEUH +U+CB48(2);; # HANGUL SYLLABLE SSANGCIEUC U * +U+CB49(2);; # HANGUL SYLLABLE SSANGCIEUC U KIYEOK * +U+CB4A(2);; # HANGUL SYLLABLE SSANGCIEUC U SSANGKIYEOK +U+CB4B(2);; # HANGUL SYLLABLE SSANGCIEUC U KIYEOKSIOS +U+CB4C(2);; # HANGUL SYLLABLE SSANGCIEUC U NIEUN * +U+CB4D(2);; # HANGUL SYLLABLE SSANGCIEUC U NIEUNCIEUC +U+CB4E(2);; # HANGUL SYLLABLE SSANGCIEUC U NIEUNHIEUH +U+CB4F(2);; # HANGUL SYLLABLE SSANGCIEUC U TIKEUT +U+CB50(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEUL * +U+CB51(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULKIYEOK +U+CB52(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULMIEUM +U+CB53(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULPIEUP +U+CB54(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULSIOS +U+CB55(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULTHIEUTH +U+CB56(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULPHIEUPH +U+CB57(2);; # HANGUL SYLLABLE SSANGCIEUC U RIEULHIEUH +U+CB58(2);; # HANGUL SYLLABLE SSANGCIEUC U MIEUM * +U+CB59(2);; # HANGUL SYLLABLE SSANGCIEUC U PIEUP * +U+CB5A(2);; # HANGUL SYLLABLE SSANGCIEUC U PIEUPSIOS +U+CB5B(2);; # HANGUL SYLLABLE SSANGCIEUC U SIOS +U+CB5C(2);; # HANGUL SYLLABLE SSANGCIEUC U SSANGSIOS +U+CB5D(2);; # HANGUL SYLLABLE SSANGCIEUC U IEUNG * +U+CB5E(2);; # HANGUL SYLLABLE SSANGCIEUC U CIEUC +U+CB5F(2);; # HANGUL SYLLABLE SSANGCIEUC U CHIEUCH +U+CB60(2);; # HANGUL SYLLABLE SSANGCIEUC U KHIEUKH +U+CB61(2);; # HANGUL SYLLABLE SSANGCIEUC U THIEUTH +U+CB62(2);; # HANGUL SYLLABLE SSANGCIEUC U PHIEUPH +U+CB63(2);; # HANGUL SYLLABLE SSANGCIEUC U HIEUH +U+CB64(2);; # HANGUL SYLLABLE SSANGCIEUC WEO * +U+CB65(2);; # HANGUL SYLLABLE SSANGCIEUC WEO KIYEOK +U+CB66(2);; # HANGUL SYLLABLE SSANGCIEUC WEO SSANGKIYEOK +U+CB67(2);; # HANGUL SYLLABLE SSANGCIEUC WEO KIYEOKSIOS +U+CB68(2);; # HANGUL SYLLABLE SSANGCIEUC WEO NIEUN +U+CB69(2);; # HANGUL SYLLABLE SSANGCIEUC WEO NIEUNCIEUC +U+CB6A(2);; # HANGUL SYLLABLE SSANGCIEUC WEO NIEUNHIEUH +U+CB6B(2);; # HANGUL SYLLABLE SSANGCIEUC WEO TIKEUT +U+CB6C(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEUL +U+CB6D(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULKIYEOK +U+CB6E(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULMIEUM +U+CB6F(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULPIEUP +U+CB70(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULSIOS +U+CB71(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULTHIEUTH +U+CB72(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULPHIEUPH +U+CB73(2);; # HANGUL SYLLABLE SSANGCIEUC WEO RIEULHIEUH +U+CB74(2);; # HANGUL SYLLABLE SSANGCIEUC WEO MIEUM +U+CB75(2);; # HANGUL SYLLABLE SSANGCIEUC WEO PIEUP +U+CB76(2);; # HANGUL SYLLABLE SSANGCIEUC WEO PIEUPSIOS +U+CB77(2);; # HANGUL SYLLABLE SSANGCIEUC WEO SIOS +U+CB78(2);; # HANGUL SYLLABLE SSANGCIEUC WEO SSANGSIOS * +U+CB79(2);; # HANGUL SYLLABLE SSANGCIEUC WEO IEUNG * +U+CB7A(2);; # HANGUL SYLLABLE SSANGCIEUC WEO CIEUC +U+CB7B(2);; # HANGUL SYLLABLE SSANGCIEUC WEO CHIEUCH +U+CB7C(2);; # HANGUL SYLLABLE SSANGCIEUC WEO KHIEUKH +U+CB7D(2);; # HANGUL SYLLABLE SSANGCIEUC WEO THIEUTH +U+CB7E(2);; # HANGUL SYLLABLE SSANGCIEUC WEO PHIEUPH +U+CB7F(2);; # HANGUL SYLLABLE SSANGCIEUC WEO HIEUH +U+CB80(2);; # HANGUL SYLLABLE SSANGCIEUC WE +U+CB81(2);; # HANGUL SYLLABLE SSANGCIEUC WE KIYEOK +U+CB82(2);; # HANGUL SYLLABLE SSANGCIEUC WE SSANGKIYEOK +U+CB83(2);; # HANGUL SYLLABLE SSANGCIEUC WE KIYEOKSIOS +U+CB84(2);; # HANGUL SYLLABLE SSANGCIEUC WE NIEUN +U+CB85(2);; # HANGUL SYLLABLE SSANGCIEUC WE NIEUNCIEUC +U+CB86(2);; # HANGUL SYLLABLE SSANGCIEUC WE NIEUNHIEUH +U+CB87(2);; # HANGUL SYLLABLE SSANGCIEUC WE TIKEUT +U+CB88(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEUL +U+CB89(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULKIYEOK +U+CB8A(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULMIEUM +U+CB8B(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULPIEUP +U+CB8C(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULSIOS +U+CB8D(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULTHIEUTH +U+CB8E(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULPHIEUPH +U+CB8F(2);; # HANGUL SYLLABLE SSANGCIEUC WE RIEULHIEUH +U+CB90(2);; # HANGUL SYLLABLE SSANGCIEUC WE MIEUM +U+CB91(2);; # HANGUL SYLLABLE SSANGCIEUC WE PIEUP +U+CB92(2);; # HANGUL SYLLABLE SSANGCIEUC WE PIEUPSIOS +U+CB93(2);; # HANGUL SYLLABLE SSANGCIEUC WE SIOS +U+CB94(2);; # HANGUL SYLLABLE SSANGCIEUC WE SSANGSIOS +U+CB95(2);; # HANGUL SYLLABLE SSANGCIEUC WE IEUNG +U+CB96(2);; # HANGUL SYLLABLE SSANGCIEUC WE CIEUC +U+CB97(2);; # HANGUL SYLLABLE SSANGCIEUC WE CHIEUCH +U+CB98(2);; # HANGUL SYLLABLE SSANGCIEUC WE KHIEUKH +U+CB99(2);; # HANGUL SYLLABLE SSANGCIEUC WE THIEUTH +U+CB9A(2);; # HANGUL SYLLABLE SSANGCIEUC WE PHIEUPH +U+CB9B(2);; # HANGUL SYLLABLE SSANGCIEUC WE HIEUH +U+CB9C(2);; # HANGUL SYLLABLE SSANGCIEUC WI * +U+CB9D(2);; # HANGUL SYLLABLE SSANGCIEUC WI KIYEOK +U+CB9E(2);; # HANGUL SYLLABLE SSANGCIEUC WI SSANGKIYEOK +U+CB9F(2);; # HANGUL SYLLABLE SSANGCIEUC WI KIYEOKSIOS +U+CBA0(2);; # HANGUL SYLLABLE SSANGCIEUC WI NIEUN +U+CBA1(2);; # HANGUL SYLLABLE SSANGCIEUC WI NIEUNCIEUC +U+CBA2(2);; # HANGUL SYLLABLE SSANGCIEUC WI NIEUNHIEUH +U+CBA3(2);; # HANGUL SYLLABLE SSANGCIEUC WI TIKEUT +U+CBA4(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEUL +U+CBA5(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULKIYEOK +U+CBA6(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULMIEUM +U+CBA7(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULPIEUP +U+CBA8(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULSIOS +U+CBA9(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULTHIEUTH +U+CBAA(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULPHIEUPH +U+CBAB(2);; # HANGUL SYLLABLE SSANGCIEUC WI RIEULHIEUH +U+CBAC(2);; # HANGUL SYLLABLE SSANGCIEUC WI MIEUM +U+CBAD(2);; # HANGUL SYLLABLE SSANGCIEUC WI PIEUP +U+CBAE(2);; # HANGUL SYLLABLE SSANGCIEUC WI PIEUPSIOS +U+CBAF(2);; # HANGUL SYLLABLE SSANGCIEUC WI SIOS +U+CBB0(2);; # HANGUL SYLLABLE SSANGCIEUC WI SSANGSIOS +U+CBB1(2);; # HANGUL SYLLABLE SSANGCIEUC WI IEUNG +U+CBB2(2);; # HANGUL SYLLABLE SSANGCIEUC WI CIEUC +U+CBB3(2);; # HANGUL SYLLABLE SSANGCIEUC WI CHIEUCH +U+CBB4(2);; # HANGUL SYLLABLE SSANGCIEUC WI KHIEUKH +U+CBB5(2);; # HANGUL SYLLABLE SSANGCIEUC WI THIEUTH +U+CBB6(2);; # HANGUL SYLLABLE SSANGCIEUC WI PHIEUPH +U+CBB7(2);; # HANGUL SYLLABLE SSANGCIEUC WI HIEUH +U+CBB8(2);; # HANGUL SYLLABLE SSANGCIEUC YU * +U+CBB9(2);; # HANGUL SYLLABLE SSANGCIEUC YU KIYEOK +U+CBBA(2);; # HANGUL SYLLABLE SSANGCIEUC YU SSANGKIYEOK +U+CBBB(2);; # HANGUL SYLLABLE SSANGCIEUC YU KIYEOKSIOS +U+CBBC(2);; # HANGUL SYLLABLE SSANGCIEUC YU NIEUN +U+CBBD(2);; # HANGUL SYLLABLE SSANGCIEUC YU NIEUNCIEUC +U+CBBE(2);; # HANGUL SYLLABLE SSANGCIEUC YU NIEUNHIEUH +U+CBBF(2);; # HANGUL SYLLABLE SSANGCIEUC YU TIKEUT +U+CBC0(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEUL +U+CBC1(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULKIYEOK +U+CBC2(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULMIEUM +U+CBC3(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULPIEUP +U+CBC4(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULSIOS +U+CBC5(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULTHIEUTH +U+CBC6(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULPHIEUPH +U+CBC7(2);; # HANGUL SYLLABLE SSANGCIEUC YU RIEULHIEUH +U+CBC8(2);; # HANGUL SYLLABLE SSANGCIEUC YU MIEUM +U+CBC9(2);; # HANGUL SYLLABLE SSANGCIEUC YU PIEUP +U+CBCA(2);; # HANGUL SYLLABLE SSANGCIEUC YU PIEUPSIOS +U+CBCB(2);; # HANGUL SYLLABLE SSANGCIEUC YU SIOS +U+CBCC(2);; # HANGUL SYLLABLE SSANGCIEUC YU SSANGSIOS +U+CBCD(2);; # HANGUL SYLLABLE SSANGCIEUC YU IEUNG +U+CBCE(2);; # HANGUL SYLLABLE SSANGCIEUC YU CIEUC +U+CBCF(2);; # HANGUL SYLLABLE SSANGCIEUC YU CHIEUCH +U+CBD0(2);; # HANGUL SYLLABLE SSANGCIEUC YU KHIEUKH +U+CBD1(2);; # HANGUL SYLLABLE SSANGCIEUC YU THIEUTH +U+CBD2(2);; # HANGUL SYLLABLE SSANGCIEUC YU PHIEUPH +U+CBD3(2);; # HANGUL SYLLABLE SSANGCIEUC YU HIEUH +U+CBD4(2);; # HANGUL SYLLABLE SSANGCIEUC EU * +U+CBD5(2);; # HANGUL SYLLABLE SSANGCIEUC EU KIYEOK +U+CBD6(2);; # HANGUL SYLLABLE SSANGCIEUC EU SSANGKIYEOK +U+CBD7(2);; # HANGUL SYLLABLE SSANGCIEUC EU KIYEOKSIOS +U+CBD8(2);; # HANGUL SYLLABLE SSANGCIEUC EU NIEUN +U+CBD9(2);; # HANGUL SYLLABLE SSANGCIEUC EU NIEUNCIEUC +U+CBDA(2);; # HANGUL SYLLABLE SSANGCIEUC EU NIEUNHIEUH +U+CBDB(2);; # HANGUL SYLLABLE SSANGCIEUC EU TIKEUT +U+CBDC(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEUL +U+CBDD(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULKIYEOK +U+CBDE(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULMIEUM +U+CBDF(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULPIEUP +U+CBE0(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULSIOS +U+CBE1(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULTHIEUTH +U+CBE2(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULPHIEUPH +U+CBE3(2);; # HANGUL SYLLABLE SSANGCIEUC EU RIEULHIEUH +U+CBE4(2);; # HANGUL SYLLABLE SSANGCIEUC EU MIEUM * +U+CBE5(2);; # HANGUL SYLLABLE SSANGCIEUC EU PIEUP +U+CBE6(2);; # HANGUL SYLLABLE SSANGCIEUC EU PIEUPSIOS +U+CBE7(2);; # HANGUL SYLLABLE SSANGCIEUC EU SIOS * +U+CBE8(2);; # HANGUL SYLLABLE SSANGCIEUC EU SSANGSIOS +U+CBE9(2);; # HANGUL SYLLABLE SSANGCIEUC EU IEUNG * +U+CBEA(2);; # HANGUL SYLLABLE SSANGCIEUC EU CIEUC +U+CBEB(2);; # HANGUL SYLLABLE SSANGCIEUC EU CHIEUCH +U+CBEC(2);; # HANGUL SYLLABLE SSANGCIEUC EU KHIEUKH +U+CBED(2);; # HANGUL SYLLABLE SSANGCIEUC EU THIEUTH +U+CBEE(2);; # HANGUL SYLLABLE SSANGCIEUC EU PHIEUPH +U+CBEF(2);; # HANGUL SYLLABLE SSANGCIEUC EU HIEUH +U+CBF0(2);; # HANGUL SYLLABLE SSANGCIEUC YI +U+CBF1(2);; # HANGUL SYLLABLE SSANGCIEUC YI KIYEOK +U+CBF2(2);; # HANGUL SYLLABLE SSANGCIEUC YI SSANGKIYEOK +U+CBF3(2);; # HANGUL SYLLABLE SSANGCIEUC YI KIYEOKSIOS +U+CBF4(2);; # HANGUL SYLLABLE SSANGCIEUC YI NIEUN +U+CBF5(2);; # HANGUL SYLLABLE SSANGCIEUC YI NIEUNCIEUC +U+CBF6(2);; # HANGUL SYLLABLE SSANGCIEUC YI NIEUNHIEUH +U+CBF7(2);; # HANGUL SYLLABLE SSANGCIEUC YI TIKEUT +U+CBF8(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEUL +U+CBF9(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULKIYEOK +U+CBFA(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULMIEUM +U+CBFB(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULPIEUP +U+CBFC(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULSIOS +U+CBFD(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULTHIEUTH +U+CBFE(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULPHIEUPH +U+CBFF(2);; # HANGUL SYLLABLE SSANGCIEUC YI RIEULHIEUH +U+CC00(2);; # HANGUL SYLLABLE SSANGCIEUC YI MIEUM +U+CC01(2);; # HANGUL SYLLABLE SSANGCIEUC YI PIEUP +U+CC02(2);; # HANGUL SYLLABLE SSANGCIEUC YI PIEUPSIOS +U+CC03(2);; # HANGUL SYLLABLE SSANGCIEUC YI SIOS +U+CC04(2);; # HANGUL SYLLABLE SSANGCIEUC YI SSANGSIOS +U+CC05(2);; # HANGUL SYLLABLE SSANGCIEUC YI IEUNG +U+CC06(2);; # HANGUL SYLLABLE SSANGCIEUC YI CIEUC +U+CC07(2);; # HANGUL SYLLABLE SSANGCIEUC YI CHIEUCH +U+CC08(2);; # HANGUL SYLLABLE SSANGCIEUC YI KHIEUKH +U+CC09(2);; # HANGUL SYLLABLE SSANGCIEUC YI THIEUTH +U+CC0A(2);; # HANGUL SYLLABLE SSANGCIEUC YI PHIEUPH +U+CC0B(2);; # HANGUL SYLLABLE SSANGCIEUC YI HIEUH +U+CC0C(2);; # HANGUL SYLLABLE SSANGCIEUC I * +U+CC0D(2);; # HANGUL SYLLABLE SSANGCIEUC I KIYEOK * +U+CC0E(2);; # HANGUL SYLLABLE SSANGCIEUC I SSANGKIYEOK +U+CC0F(2);; # HANGUL SYLLABLE SSANGCIEUC I KIYEOKSIOS +U+CC10(2);; # HANGUL SYLLABLE SSANGCIEUC I NIEUN * +U+CC11(2);; # HANGUL SYLLABLE SSANGCIEUC I NIEUNCIEUC +U+CC12(2);; # HANGUL SYLLABLE SSANGCIEUC I NIEUNHIEUH +U+CC13(2);; # HANGUL SYLLABLE SSANGCIEUC I TIKEUT +U+CC14(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEUL * +U+CC15(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULKIYEOK +U+CC16(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULMIEUM +U+CC17(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULPIEUP +U+CC18(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULSIOS +U+CC19(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULTHIEUTH +U+CC1A(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULPHIEUPH +U+CC1B(2);; # HANGUL SYLLABLE SSANGCIEUC I RIEULHIEUH +U+CC1C(2);; # HANGUL SYLLABLE SSANGCIEUC I MIEUM * +U+CC1D(2);; # HANGUL SYLLABLE SSANGCIEUC I PIEUP * +U+CC1E(2);; # HANGUL SYLLABLE SSANGCIEUC I PIEUPSIOS +U+CC1F(2);; # HANGUL SYLLABLE SSANGCIEUC I SIOS +U+CC20(2);; # HANGUL SYLLABLE SSANGCIEUC I SSANGSIOS +U+CC21(2);; # HANGUL SYLLABLE SSANGCIEUC I IEUNG * +U+CC22(2);; # HANGUL SYLLABLE SSANGCIEUC I CIEUC * +U+CC23(2);; # HANGUL SYLLABLE SSANGCIEUC I CHIEUCH +U+CC24(2);; # HANGUL SYLLABLE SSANGCIEUC I KHIEUKH +U+CC25(2);; # HANGUL SYLLABLE SSANGCIEUC I THIEUTH +U+CC26(2);; # HANGUL SYLLABLE SSANGCIEUC I PHIEUPH +U+CC27(2);; # HANGUL SYLLABLE SSANGCIEUC I HIEUH * +U+CC28(2);; # HANGUL SYLLABLE CHIEUCH A * +U+CC29(2);; # HANGUL SYLLABLE CHIEUCH A KIYEOK * +U+CC2A(2);; # HANGUL SYLLABLE CHIEUCH A SSANGKIYEOK +U+CC2B(2);; # HANGUL SYLLABLE CHIEUCH A KIYEOKSIOS +U+CC2C(2);; # HANGUL SYLLABLE CHIEUCH A NIEUN * +U+CC2D(2);; # HANGUL SYLLABLE CHIEUCH A NIEUNCIEUC +U+CC2E(2);; # HANGUL SYLLABLE CHIEUCH A NIEUNHIEUH * +U+CC2F(2);; # HANGUL SYLLABLE CHIEUCH A TIKEUT +U+CC30(2);; # HANGUL SYLLABLE CHIEUCH A RIEUL * +U+CC31(2);; # HANGUL SYLLABLE CHIEUCH A RIEULKIYEOK +U+CC32(2);; # HANGUL SYLLABLE CHIEUCH A RIEULMIEUM +U+CC33(2);; # HANGUL SYLLABLE CHIEUCH A RIEULPIEUP +U+CC34(2);; # HANGUL SYLLABLE CHIEUCH A RIEULSIOS +U+CC35(2);; # HANGUL SYLLABLE CHIEUCH A RIEULTHIEUTH +U+CC36(2);; # HANGUL SYLLABLE CHIEUCH A RIEULPHIEUPH +U+CC37(2);; # HANGUL SYLLABLE CHIEUCH A RIEULHIEUH +U+CC38(2);; # HANGUL SYLLABLE CHIEUCH A MIEUM * +U+CC39(2);; # HANGUL SYLLABLE CHIEUCH A PIEUP * +U+CC3A(2);; # HANGUL SYLLABLE CHIEUCH A PIEUPSIOS +U+CC3B(2);; # HANGUL SYLLABLE CHIEUCH A SIOS * +U+CC3C(2);; # HANGUL SYLLABLE CHIEUCH A SSANGSIOS * +U+CC3D(2);; # HANGUL SYLLABLE CHIEUCH A IEUNG * +U+CC3E(2);; # HANGUL SYLLABLE CHIEUCH A CIEUC * +U+CC3F(2);; # HANGUL SYLLABLE CHIEUCH A CHIEUCH +U+CC40(2);; # HANGUL SYLLABLE CHIEUCH A KHIEUKH +U+CC41(2);; # HANGUL SYLLABLE CHIEUCH A THIEUTH +U+CC42(2);; # HANGUL SYLLABLE CHIEUCH A PHIEUPH +U+CC43(2);; # HANGUL SYLLABLE CHIEUCH A HIEUH +U+CC44(2);; # HANGUL SYLLABLE CHIEUCH AE * +U+CC45(2);; # HANGUL SYLLABLE CHIEUCH AE KIYEOK * +U+CC46(2);; # HANGUL SYLLABLE CHIEUCH AE SSANGKIYEOK +U+CC47(2);; # HANGUL SYLLABLE CHIEUCH AE KIYEOKSIOS +U+CC48(2);; # HANGUL SYLLABLE CHIEUCH AE NIEUN * +U+CC49(2);; # HANGUL SYLLABLE CHIEUCH AE NIEUNCIEUC +U+CC4A(2);; # HANGUL SYLLABLE CHIEUCH AE NIEUNHIEUH +U+CC4B(2);; # HANGUL SYLLABLE CHIEUCH AE TIKEUT +U+CC4C(2);; # HANGUL SYLLABLE CHIEUCH AE RIEUL * +U+CC4D(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULKIYEOK +U+CC4E(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULMIEUM +U+CC4F(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULPIEUP +U+CC50(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULSIOS +U+CC51(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULTHIEUTH +U+CC52(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULPHIEUPH +U+CC53(2);; # HANGUL SYLLABLE CHIEUCH AE RIEULHIEUH +U+CC54(2);; # HANGUL SYLLABLE CHIEUCH AE MIEUM * +U+CC55(2);; # HANGUL SYLLABLE CHIEUCH AE PIEUP * +U+CC56(2);; # HANGUL SYLLABLE CHIEUCH AE PIEUPSIOS +U+CC57(2);; # HANGUL SYLLABLE CHIEUCH AE SIOS * +U+CC58(2);; # HANGUL SYLLABLE CHIEUCH AE SSANGSIOS * +U+CC59(2);; # HANGUL SYLLABLE CHIEUCH AE IEUNG * +U+CC5A(2);; # HANGUL SYLLABLE CHIEUCH AE CIEUC +U+CC5B(2);; # HANGUL SYLLABLE CHIEUCH AE CHIEUCH +U+CC5C(2);; # HANGUL SYLLABLE CHIEUCH AE KHIEUKH +U+CC5D(2);; # HANGUL SYLLABLE CHIEUCH AE THIEUTH +U+CC5E(2);; # HANGUL SYLLABLE CHIEUCH AE PHIEUPH +U+CC5F(2);; # HANGUL SYLLABLE CHIEUCH AE HIEUH +U+CC60(2);; # HANGUL SYLLABLE CHIEUCH YA * +U+CC61(2);; # HANGUL SYLLABLE CHIEUCH YA KIYEOK +U+CC62(2);; # HANGUL SYLLABLE CHIEUCH YA SSANGKIYEOK +U+CC63(2);; # HANGUL SYLLABLE CHIEUCH YA KIYEOKSIOS +U+CC64(2);; # HANGUL SYLLABLE CHIEUCH YA NIEUN * +U+CC65(2);; # HANGUL SYLLABLE CHIEUCH YA NIEUNCIEUC +U+CC66(2);; # HANGUL SYLLABLE CHIEUCH YA NIEUNHIEUH * +U+CC67(2);; # HANGUL SYLLABLE CHIEUCH YA TIKEUT +U+CC68(2);; # HANGUL SYLLABLE CHIEUCH YA RIEUL * +U+CC69(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULKIYEOK +U+CC6A(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULMIEUM +U+CC6B(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULPIEUP +U+CC6C(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULSIOS +U+CC6D(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULTHIEUTH +U+CC6E(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULPHIEUPH +U+CC6F(2);; # HANGUL SYLLABLE CHIEUCH YA RIEULHIEUH +U+CC70(2);; # HANGUL SYLLABLE CHIEUCH YA MIEUM * +U+CC71(2);; # HANGUL SYLLABLE CHIEUCH YA PIEUP +U+CC72(2);; # HANGUL SYLLABLE CHIEUCH YA PIEUPSIOS +U+CC73(2);; # HANGUL SYLLABLE CHIEUCH YA SIOS +U+CC74(2);; # HANGUL SYLLABLE CHIEUCH YA SSANGSIOS +U+CC75(2);; # HANGUL SYLLABLE CHIEUCH YA IEUNG * +U+CC76(2);; # HANGUL SYLLABLE CHIEUCH YA CIEUC +U+CC77(2);; # HANGUL SYLLABLE CHIEUCH YA CHIEUCH +U+CC78(2);; # HANGUL SYLLABLE CHIEUCH YA KHIEUKH +U+CC79(2);; # HANGUL SYLLABLE CHIEUCH YA THIEUTH +U+CC7A(2);; # HANGUL SYLLABLE CHIEUCH YA PHIEUPH +U+CC7B(2);; # HANGUL SYLLABLE CHIEUCH YA HIEUH +U+CC7C(2);; # HANGUL SYLLABLE CHIEUCH YAE +U+CC7D(2);; # HANGUL SYLLABLE CHIEUCH YAE KIYEOK +U+CC7E(2);; # HANGUL SYLLABLE CHIEUCH YAE SSANGKIYEOK +U+CC7F(2);; # HANGUL SYLLABLE CHIEUCH YAE KIYEOKSIOS +U+CC80(2);; # HANGUL SYLLABLE CHIEUCH YAE NIEUN +U+CC81(2);; # HANGUL SYLLABLE CHIEUCH YAE NIEUNCIEUC +U+CC82(2);; # HANGUL SYLLABLE CHIEUCH YAE NIEUNHIEUH +U+CC83(2);; # HANGUL SYLLABLE CHIEUCH YAE TIKEUT +U+CC84(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEUL +U+CC85(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULKIYEOK +U+CC86(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULMIEUM +U+CC87(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULPIEUP +U+CC88(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULSIOS +U+CC89(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULTHIEUTH +U+CC8A(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULPHIEUPH +U+CC8B(2);; # HANGUL SYLLABLE CHIEUCH YAE RIEULHIEUH +U+CC8C(2);; # HANGUL SYLLABLE CHIEUCH YAE MIEUM +U+CC8D(2);; # HANGUL SYLLABLE CHIEUCH YAE PIEUP +U+CC8E(2);; # HANGUL SYLLABLE CHIEUCH YAE PIEUPSIOS +U+CC8F(2);; # HANGUL SYLLABLE CHIEUCH YAE SIOS +U+CC90(2);; # HANGUL SYLLABLE CHIEUCH YAE SSANGSIOS +U+CC91(2);; # HANGUL SYLLABLE CHIEUCH YAE IEUNG +U+CC92(2);; # HANGUL SYLLABLE CHIEUCH YAE CIEUC +U+CC93(2);; # HANGUL SYLLABLE CHIEUCH YAE CHIEUCH +U+CC94(2);; # HANGUL SYLLABLE CHIEUCH YAE KHIEUKH +U+CC95(2);; # HANGUL SYLLABLE CHIEUCH YAE THIEUTH +U+CC96(2);; # HANGUL SYLLABLE CHIEUCH YAE PHIEUPH +U+CC97(2);; # HANGUL SYLLABLE CHIEUCH YAE HIEUH +U+CC98(2);; # HANGUL SYLLABLE CHIEUCH EO * +U+CC99(2);; # HANGUL SYLLABLE CHIEUCH EO KIYEOK * +U+CC9A(2);; # HANGUL SYLLABLE CHIEUCH EO SSANGKIYEOK +U+CC9B(2);; # HANGUL SYLLABLE CHIEUCH EO KIYEOKSIOS +U+CC9C(2);; # HANGUL SYLLABLE CHIEUCH EO NIEUN * +U+CC9D(2);; # HANGUL SYLLABLE CHIEUCH EO NIEUNCIEUC +U+CC9E(2);; # HANGUL SYLLABLE CHIEUCH EO NIEUNHIEUH +U+CC9F(2);; # HANGUL SYLLABLE CHIEUCH EO TIKEUT +U+CCA0(2);; # HANGUL SYLLABLE CHIEUCH EO RIEUL * +U+CCA1(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULKIYEOK +U+CCA2(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULMIEUM +U+CCA3(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULPIEUP +U+CCA4(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULSIOS +U+CCA5(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULTHIEUTH +U+CCA6(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULPHIEUPH +U+CCA7(2);; # HANGUL SYLLABLE CHIEUCH EO RIEULHIEUH +U+CCA8(2);; # HANGUL SYLLABLE CHIEUCH EO MIEUM * +U+CCA9(2);; # HANGUL SYLLABLE CHIEUCH EO PIEUP * +U+CCAA(2);; # HANGUL SYLLABLE CHIEUCH EO PIEUPSIOS +U+CCAB(2);; # HANGUL SYLLABLE CHIEUCH EO SIOS * +U+CCAC(2);; # HANGUL SYLLABLE CHIEUCH EO SSANGSIOS * +U+CCAD(2);; # HANGUL SYLLABLE CHIEUCH EO IEUNG * +U+CCAE(2);; # HANGUL SYLLABLE CHIEUCH EO CIEUC +U+CCAF(2);; # HANGUL SYLLABLE CHIEUCH EO CHIEUCH +U+CCB0(2);; # HANGUL SYLLABLE CHIEUCH EO KHIEUKH +U+CCB1(2);; # HANGUL SYLLABLE CHIEUCH EO THIEUTH +U+CCB2(2);; # HANGUL SYLLABLE CHIEUCH EO PHIEUPH +U+CCB3(2);; # HANGUL SYLLABLE CHIEUCH EO HIEUH +U+CCB4(2);; # HANGUL SYLLABLE CHIEUCH E * +U+CCB5(2);; # HANGUL SYLLABLE CHIEUCH E KIYEOK * +U+CCB6(2);; # HANGUL SYLLABLE CHIEUCH E SSANGKIYEOK +U+CCB7(2);; # HANGUL SYLLABLE CHIEUCH E KIYEOKSIOS +U+CCB8(2);; # HANGUL SYLLABLE CHIEUCH E NIEUN * +U+CCB9(2);; # HANGUL SYLLABLE CHIEUCH E NIEUNCIEUC +U+CCBA(2);; # HANGUL SYLLABLE CHIEUCH E NIEUNHIEUH +U+CCBB(2);; # HANGUL SYLLABLE CHIEUCH E TIKEUT +U+CCBC(2);; # HANGUL SYLLABLE CHIEUCH E RIEUL * +U+CCBD(2);; # HANGUL SYLLABLE CHIEUCH E RIEULKIYEOK +U+CCBE(2);; # HANGUL SYLLABLE CHIEUCH E RIEULMIEUM +U+CCBF(2);; # HANGUL SYLLABLE CHIEUCH E RIEULPIEUP +U+CCC0(2);; # HANGUL SYLLABLE CHIEUCH E RIEULSIOS +U+CCC1(2);; # HANGUL SYLLABLE CHIEUCH E RIEULTHIEUTH +U+CCC2(2);; # HANGUL SYLLABLE CHIEUCH E RIEULPHIEUPH +U+CCC3(2);; # HANGUL SYLLABLE CHIEUCH E RIEULHIEUH +U+CCC4(2);; # HANGUL SYLLABLE CHIEUCH E MIEUM * +U+CCC5(2);; # HANGUL SYLLABLE CHIEUCH E PIEUP * +U+CCC6(2);; # HANGUL SYLLABLE CHIEUCH E PIEUPSIOS +U+CCC7(2);; # HANGUL SYLLABLE CHIEUCH E SIOS * +U+CCC8(2);; # HANGUL SYLLABLE CHIEUCH E SSANGSIOS +U+CCC9(2);; # HANGUL SYLLABLE CHIEUCH E IEUNG * +U+CCCA(2);; # HANGUL SYLLABLE CHIEUCH E CIEUC +U+CCCB(2);; # HANGUL SYLLABLE CHIEUCH E CHIEUCH +U+CCCC(2);; # HANGUL SYLLABLE CHIEUCH E KHIEUKH +U+CCCD(2);; # HANGUL SYLLABLE CHIEUCH E THIEUTH +U+CCCE(2);; # HANGUL SYLLABLE CHIEUCH E PHIEUPH +U+CCCF(2);; # HANGUL SYLLABLE CHIEUCH E HIEUH +U+CCD0(2);; # HANGUL SYLLABLE CHIEUCH YEO * +U+CCD1(2);; # HANGUL SYLLABLE CHIEUCH YEO KIYEOK +U+CCD2(2);; # HANGUL SYLLABLE CHIEUCH YEO SSANGKIYEOK +U+CCD3(2);; # HANGUL SYLLABLE CHIEUCH YEO KIYEOKSIOS +U+CCD4(2);; # HANGUL SYLLABLE CHIEUCH YEO NIEUN * +U+CCD5(2);; # HANGUL SYLLABLE CHIEUCH YEO NIEUNCIEUC +U+CCD6(2);; # HANGUL SYLLABLE CHIEUCH YEO NIEUNHIEUH +U+CCD7(2);; # HANGUL SYLLABLE CHIEUCH YEO TIKEUT +U+CCD8(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEUL +U+CCD9(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULKIYEOK +U+CCDA(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULMIEUM +U+CCDB(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULPIEUP +U+CCDC(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULSIOS +U+CCDD(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULTHIEUTH +U+CCDE(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULPHIEUPH +U+CCDF(2);; # HANGUL SYLLABLE CHIEUCH YEO RIEULHIEUH +U+CCE0(2);; # HANGUL SYLLABLE CHIEUCH YEO MIEUM +U+CCE1(2);; # HANGUL SYLLABLE CHIEUCH YEO PIEUP +U+CCE2(2);; # HANGUL SYLLABLE CHIEUCH YEO PIEUPSIOS +U+CCE3(2);; # HANGUL SYLLABLE CHIEUCH YEO SIOS +U+CCE4(2);; # HANGUL SYLLABLE CHIEUCH YEO SSANGSIOS * +U+CCE5(2);; # HANGUL SYLLABLE CHIEUCH YEO IEUNG +U+CCE6(2);; # HANGUL SYLLABLE CHIEUCH YEO CIEUC +U+CCE7(2);; # HANGUL SYLLABLE CHIEUCH YEO CHIEUCH +U+CCE8(2);; # HANGUL SYLLABLE CHIEUCH YEO KHIEUKH +U+CCE9(2);; # HANGUL SYLLABLE CHIEUCH YEO THIEUTH +U+CCEA(2);; # HANGUL SYLLABLE CHIEUCH YEO PHIEUPH +U+CCEB(2);; # HANGUL SYLLABLE CHIEUCH YEO HIEUH +U+CCEC(2);; # HANGUL SYLLABLE CHIEUCH YE * +U+CCED(2);; # HANGUL SYLLABLE CHIEUCH YE KIYEOK +U+CCEE(2);; # HANGUL SYLLABLE CHIEUCH YE SSANGKIYEOK +U+CCEF(2);; # HANGUL SYLLABLE CHIEUCH YE KIYEOKSIOS +U+CCF0(2);; # HANGUL SYLLABLE CHIEUCH YE NIEUN * +U+CCF1(2);; # HANGUL SYLLABLE CHIEUCH YE NIEUNCIEUC +U+CCF2(2);; # HANGUL SYLLABLE CHIEUCH YE NIEUNHIEUH +U+CCF3(2);; # HANGUL SYLLABLE CHIEUCH YE TIKEUT +U+CCF4(2);; # HANGUL SYLLABLE CHIEUCH YE RIEUL +U+CCF5(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULKIYEOK +U+CCF6(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULMIEUM +U+CCF7(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULPIEUP +U+CCF8(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULSIOS +U+CCF9(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULTHIEUTH +U+CCFA(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULPHIEUPH +U+CCFB(2);; # HANGUL SYLLABLE CHIEUCH YE RIEULHIEUH +U+CCFC(2);; # HANGUL SYLLABLE CHIEUCH YE MIEUM +U+CCFD(2);; # HANGUL SYLLABLE CHIEUCH YE PIEUP +U+CCFE(2);; # HANGUL SYLLABLE CHIEUCH YE PIEUPSIOS +U+CCFF(2);; # HANGUL SYLLABLE CHIEUCH YE SIOS +U+CD00(2);; # HANGUL SYLLABLE CHIEUCH YE SSANGSIOS +U+CD01(2);; # HANGUL SYLLABLE CHIEUCH YE IEUNG * +U+CD02(2);; # HANGUL SYLLABLE CHIEUCH YE CIEUC +U+CD03(2);; # HANGUL SYLLABLE CHIEUCH YE CHIEUCH +U+CD04(2);; # HANGUL SYLLABLE CHIEUCH YE KHIEUKH +U+CD05(2);; # HANGUL SYLLABLE CHIEUCH YE THIEUTH +U+CD06(2);; # HANGUL SYLLABLE CHIEUCH YE PHIEUPH +U+CD07(2);; # HANGUL SYLLABLE CHIEUCH YE HIEUH +U+CD08(2);; # HANGUL SYLLABLE CHIEUCH O * +U+CD09(2);; # HANGUL SYLLABLE CHIEUCH O KIYEOK * +U+CD0A(2);; # HANGUL SYLLABLE CHIEUCH O SSANGKIYEOK +U+CD0B(2);; # HANGUL SYLLABLE CHIEUCH O KIYEOKSIOS +U+CD0C(2);; # HANGUL SYLLABLE CHIEUCH O NIEUN * +U+CD0D(2);; # HANGUL SYLLABLE CHIEUCH O NIEUNCIEUC +U+CD0E(2);; # HANGUL SYLLABLE CHIEUCH O NIEUNHIEUH +U+CD0F(2);; # HANGUL SYLLABLE CHIEUCH O TIKEUT +U+CD10(2);; # HANGUL SYLLABLE CHIEUCH O RIEUL * +U+CD11(2);; # HANGUL SYLLABLE CHIEUCH O RIEULKIYEOK +U+CD12(2);; # HANGUL SYLLABLE CHIEUCH O RIEULMIEUM +U+CD13(2);; # HANGUL SYLLABLE CHIEUCH O RIEULPIEUP +U+CD14(2);; # HANGUL SYLLABLE CHIEUCH O RIEULSIOS +U+CD15(2);; # HANGUL SYLLABLE CHIEUCH O RIEULTHIEUTH +U+CD16(2);; # HANGUL SYLLABLE CHIEUCH O RIEULPHIEUPH +U+CD17(2);; # HANGUL SYLLABLE CHIEUCH O RIEULHIEUH +U+CD18(2);; # HANGUL SYLLABLE CHIEUCH O MIEUM * +U+CD19(2);; # HANGUL SYLLABLE CHIEUCH O PIEUP * +U+CD1A(2);; # HANGUL SYLLABLE CHIEUCH O PIEUPSIOS +U+CD1B(2);; # HANGUL SYLLABLE CHIEUCH O SIOS * +U+CD1C(2);; # HANGUL SYLLABLE CHIEUCH O SSANGSIOS +U+CD1D(2);; # HANGUL SYLLABLE CHIEUCH O IEUNG * +U+CD1E(2);; # HANGUL SYLLABLE CHIEUCH O CIEUC +U+CD1F(2);; # HANGUL SYLLABLE CHIEUCH O CHIEUCH +U+CD20(2);; # HANGUL SYLLABLE CHIEUCH O KHIEUKH +U+CD21(2);; # HANGUL SYLLABLE CHIEUCH O THIEUTH +U+CD22(2);; # HANGUL SYLLABLE CHIEUCH O PHIEUPH +U+CD23(2);; # HANGUL SYLLABLE CHIEUCH O HIEUH +U+CD24(2);; # HANGUL SYLLABLE CHIEUCH WA * +U+CD25(2);; # HANGUL SYLLABLE CHIEUCH WA KIYEOK +U+CD26(2);; # HANGUL SYLLABLE CHIEUCH WA SSANGKIYEOK +U+CD27(2);; # HANGUL SYLLABLE CHIEUCH WA KIYEOKSIOS +U+CD28(2);; # HANGUL SYLLABLE CHIEUCH WA NIEUN * +U+CD29(2);; # HANGUL SYLLABLE CHIEUCH WA NIEUNCIEUC +U+CD2A(2);; # HANGUL SYLLABLE CHIEUCH WA NIEUNHIEUH +U+CD2B(2);; # HANGUL SYLLABLE CHIEUCH WA TIKEUT +U+CD2C(2);; # HANGUL SYLLABLE CHIEUCH WA RIEUL * +U+CD2D(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULKIYEOK +U+CD2E(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULMIEUM +U+CD2F(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULPIEUP +U+CD30(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULSIOS +U+CD31(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULTHIEUTH +U+CD32(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULPHIEUPH +U+CD33(2);; # HANGUL SYLLABLE CHIEUCH WA RIEULHIEUH +U+CD34(2);; # HANGUL SYLLABLE CHIEUCH WA MIEUM +U+CD35(2);; # HANGUL SYLLABLE CHIEUCH WA PIEUP +U+CD36(2);; # HANGUL SYLLABLE CHIEUCH WA PIEUPSIOS +U+CD37(2);; # HANGUL SYLLABLE CHIEUCH WA SIOS +U+CD38(2);; # HANGUL SYLLABLE CHIEUCH WA SSANGSIOS +U+CD39(2);; # HANGUL SYLLABLE CHIEUCH WA IEUNG * +U+CD3A(2);; # HANGUL SYLLABLE CHIEUCH WA CIEUC +U+CD3B(2);; # HANGUL SYLLABLE CHIEUCH WA CHIEUCH +U+CD3C(2);; # HANGUL SYLLABLE CHIEUCH WA KHIEUKH +U+CD3D(2);; # HANGUL SYLLABLE CHIEUCH WA THIEUTH +U+CD3E(2);; # HANGUL SYLLABLE CHIEUCH WA PHIEUPH +U+CD3F(2);; # HANGUL SYLLABLE CHIEUCH WA HIEUH +U+CD40(2);; # HANGUL SYLLABLE CHIEUCH WAE +U+CD41(2);; # HANGUL SYLLABLE CHIEUCH WAE KIYEOK +U+CD42(2);; # HANGUL SYLLABLE CHIEUCH WAE SSANGKIYEOK +U+CD43(2);; # HANGUL SYLLABLE CHIEUCH WAE KIYEOKSIOS +U+CD44(2);; # HANGUL SYLLABLE CHIEUCH WAE NIEUN +U+CD45(2);; # HANGUL SYLLABLE CHIEUCH WAE NIEUNCIEUC +U+CD46(2);; # HANGUL SYLLABLE CHIEUCH WAE NIEUNHIEUH +U+CD47(2);; # HANGUL SYLLABLE CHIEUCH WAE TIKEUT +U+CD48(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEUL +U+CD49(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULKIYEOK +U+CD4A(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULMIEUM +U+CD4B(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULPIEUP +U+CD4C(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULSIOS +U+CD4D(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULTHIEUTH +U+CD4E(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULPHIEUPH +U+CD4F(2);; # HANGUL SYLLABLE CHIEUCH WAE RIEULHIEUH +U+CD50(2);; # HANGUL SYLLABLE CHIEUCH WAE MIEUM +U+CD51(2);; # HANGUL SYLLABLE CHIEUCH WAE PIEUP +U+CD52(2);; # HANGUL SYLLABLE CHIEUCH WAE PIEUPSIOS +U+CD53(2);; # HANGUL SYLLABLE CHIEUCH WAE SIOS +U+CD54(2);; # HANGUL SYLLABLE CHIEUCH WAE SSANGSIOS +U+CD55(2);; # HANGUL SYLLABLE CHIEUCH WAE IEUNG +U+CD56(2);; # HANGUL SYLLABLE CHIEUCH WAE CIEUC +U+CD57(2);; # HANGUL SYLLABLE CHIEUCH WAE CHIEUCH +U+CD58(2);; # HANGUL SYLLABLE CHIEUCH WAE KHIEUKH +U+CD59(2);; # HANGUL SYLLABLE CHIEUCH WAE THIEUTH +U+CD5A(2);; # HANGUL SYLLABLE CHIEUCH WAE PHIEUPH +U+CD5B(2);; # HANGUL SYLLABLE CHIEUCH WAE HIEUH +U+CD5C(2);; # HANGUL SYLLABLE CHIEUCH OE * +U+CD5D(2);; # HANGUL SYLLABLE CHIEUCH OE KIYEOK +U+CD5E(2);; # HANGUL SYLLABLE CHIEUCH OE SSANGKIYEOK +U+CD5F(2);; # HANGUL SYLLABLE CHIEUCH OE KIYEOKSIOS +U+CD60(2);; # HANGUL SYLLABLE CHIEUCH OE NIEUN * +U+CD61(2);; # HANGUL SYLLABLE CHIEUCH OE NIEUNCIEUC +U+CD62(2);; # HANGUL SYLLABLE CHIEUCH OE NIEUNHIEUH +U+CD63(2);; # HANGUL SYLLABLE CHIEUCH OE TIKEUT +U+CD64(2);; # HANGUL SYLLABLE CHIEUCH OE RIEUL * +U+CD65(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULKIYEOK +U+CD66(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULMIEUM +U+CD67(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULPIEUP +U+CD68(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULSIOS +U+CD69(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULTHIEUTH +U+CD6A(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULPHIEUPH +U+CD6B(2);; # HANGUL SYLLABLE CHIEUCH OE RIEULHIEUH +U+CD6C(2);; # HANGUL SYLLABLE CHIEUCH OE MIEUM * +U+CD6D(2);; # HANGUL SYLLABLE CHIEUCH OE PIEUP * +U+CD6E(2);; # HANGUL SYLLABLE CHIEUCH OE PIEUPSIOS +U+CD6F(2);; # HANGUL SYLLABLE CHIEUCH OE SIOS * +U+CD70(2);; # HANGUL SYLLABLE CHIEUCH OE SSANGSIOS +U+CD71(2);; # HANGUL SYLLABLE CHIEUCH OE IEUNG * +U+CD72(2);; # HANGUL SYLLABLE CHIEUCH OE CIEUC +U+CD73(2);; # HANGUL SYLLABLE CHIEUCH OE CHIEUCH +U+CD74(2);; # HANGUL SYLLABLE CHIEUCH OE KHIEUKH +U+CD75(2);; # HANGUL SYLLABLE CHIEUCH OE THIEUTH +U+CD76(2);; # HANGUL SYLLABLE CHIEUCH OE PHIEUPH +U+CD77(2);; # HANGUL SYLLABLE CHIEUCH OE HIEUH +U+CD78(2);; # HANGUL SYLLABLE CHIEUCH YO * +U+CD79(2);; # HANGUL SYLLABLE CHIEUCH YO KIYEOK +U+CD7A(2);; # HANGUL SYLLABLE CHIEUCH YO SSANGKIYEOK +U+CD7B(2);; # HANGUL SYLLABLE CHIEUCH YO KIYEOKSIOS +U+CD7C(2);; # HANGUL SYLLABLE CHIEUCH YO NIEUN +U+CD7D(2);; # HANGUL SYLLABLE CHIEUCH YO NIEUNCIEUC +U+CD7E(2);; # HANGUL SYLLABLE CHIEUCH YO NIEUNHIEUH +U+CD7F(2);; # HANGUL SYLLABLE CHIEUCH YO TIKEUT +U+CD80(2);; # HANGUL SYLLABLE CHIEUCH YO RIEUL +U+CD81(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULKIYEOK +U+CD82(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULMIEUM +U+CD83(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULPIEUP +U+CD84(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULSIOS +U+CD85(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULTHIEUTH +U+CD86(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULPHIEUPH +U+CD87(2);; # HANGUL SYLLABLE CHIEUCH YO RIEULHIEUH +U+CD88(2);; # HANGUL SYLLABLE CHIEUCH YO MIEUM * +U+CD89(2);; # HANGUL SYLLABLE CHIEUCH YO PIEUP +U+CD8A(2);; # HANGUL SYLLABLE CHIEUCH YO PIEUPSIOS +U+CD8B(2);; # HANGUL SYLLABLE CHIEUCH YO SIOS +U+CD8C(2);; # HANGUL SYLLABLE CHIEUCH YO SSANGSIOS +U+CD8D(2);; # HANGUL SYLLABLE CHIEUCH YO IEUNG +U+CD8E(2);; # HANGUL SYLLABLE CHIEUCH YO CIEUC +U+CD8F(2);; # HANGUL SYLLABLE CHIEUCH YO CHIEUCH +U+CD90(2);; # HANGUL SYLLABLE CHIEUCH YO KHIEUKH +U+CD91(2);; # HANGUL SYLLABLE CHIEUCH YO THIEUTH +U+CD92(2);; # HANGUL SYLLABLE CHIEUCH YO PHIEUPH +U+CD93(2);; # HANGUL SYLLABLE CHIEUCH YO HIEUH +U+CD94(2);; # HANGUL SYLLABLE CHIEUCH U * +U+CD95(2);; # HANGUL SYLLABLE CHIEUCH U KIYEOK * +U+CD96(2);; # HANGUL SYLLABLE CHIEUCH U SSANGKIYEOK +U+CD97(2);; # HANGUL SYLLABLE CHIEUCH U KIYEOKSIOS +U+CD98(2);; # HANGUL SYLLABLE CHIEUCH U NIEUN * +U+CD99(2);; # HANGUL SYLLABLE CHIEUCH U NIEUNCIEUC +U+CD9A(2);; # HANGUL SYLLABLE CHIEUCH U NIEUNHIEUH +U+CD9B(2);; # HANGUL SYLLABLE CHIEUCH U TIKEUT +U+CD9C(2);; # HANGUL SYLLABLE CHIEUCH U RIEUL * +U+CD9D(2);; # HANGUL SYLLABLE CHIEUCH U RIEULKIYEOK +U+CD9E(2);; # HANGUL SYLLABLE CHIEUCH U RIEULMIEUM +U+CD9F(2);; # HANGUL SYLLABLE CHIEUCH U RIEULPIEUP +U+CDA0(2);; # HANGUL SYLLABLE CHIEUCH U RIEULSIOS +U+CDA1(2);; # HANGUL SYLLABLE CHIEUCH U RIEULTHIEUTH +U+CDA2(2);; # HANGUL SYLLABLE CHIEUCH U RIEULPHIEUPH +U+CDA3(2);; # HANGUL SYLLABLE CHIEUCH U RIEULHIEUH +U+CDA4(2);; # HANGUL SYLLABLE CHIEUCH U MIEUM * +U+CDA5(2);; # HANGUL SYLLABLE CHIEUCH U PIEUP * +U+CDA6(2);; # HANGUL SYLLABLE CHIEUCH U PIEUPSIOS +U+CDA7(2);; # HANGUL SYLLABLE CHIEUCH U SIOS * +U+CDA8(2);; # HANGUL SYLLABLE CHIEUCH U SSANGSIOS +U+CDA9(2);; # HANGUL SYLLABLE CHIEUCH U IEUNG * +U+CDAA(2);; # HANGUL SYLLABLE CHIEUCH U CIEUC +U+CDAB(2);; # HANGUL SYLLABLE CHIEUCH U CHIEUCH +U+CDAC(2);; # HANGUL SYLLABLE CHIEUCH U KHIEUKH +U+CDAD(2);; # HANGUL SYLLABLE CHIEUCH U THIEUTH +U+CDAE(2);; # HANGUL SYLLABLE CHIEUCH U PHIEUPH +U+CDAF(2);; # HANGUL SYLLABLE CHIEUCH U HIEUH +U+CDB0(2);; # HANGUL SYLLABLE CHIEUCH WEO * +U+CDB1(2);; # HANGUL SYLLABLE CHIEUCH WEO KIYEOK +U+CDB2(2);; # HANGUL SYLLABLE CHIEUCH WEO SSANGKIYEOK +U+CDB3(2);; # HANGUL SYLLABLE CHIEUCH WEO KIYEOKSIOS +U+CDB4(2);; # HANGUL SYLLABLE CHIEUCH WEO NIEUN +U+CDB5(2);; # HANGUL SYLLABLE CHIEUCH WEO NIEUNCIEUC +U+CDB6(2);; # HANGUL SYLLABLE CHIEUCH WEO NIEUNHIEUH +U+CDB7(2);; # HANGUL SYLLABLE CHIEUCH WEO TIKEUT +U+CDB8(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEUL +U+CDB9(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULKIYEOK +U+CDBA(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULMIEUM +U+CDBB(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULPIEUP +U+CDBC(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULSIOS +U+CDBD(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULTHIEUTH +U+CDBE(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULPHIEUPH +U+CDBF(2);; # HANGUL SYLLABLE CHIEUCH WEO RIEULHIEUH +U+CDC0(2);; # HANGUL SYLLABLE CHIEUCH WEO MIEUM +U+CDC1(2);; # HANGUL SYLLABLE CHIEUCH WEO PIEUP +U+CDC2(2);; # HANGUL SYLLABLE CHIEUCH WEO PIEUPSIOS +U+CDC3(2);; # HANGUL SYLLABLE CHIEUCH WEO SIOS +U+CDC4(2);; # HANGUL SYLLABLE CHIEUCH WEO SSANGSIOS * +U+CDC5(2);; # HANGUL SYLLABLE CHIEUCH WEO IEUNG +U+CDC6(2);; # HANGUL SYLLABLE CHIEUCH WEO CIEUC +U+CDC7(2);; # HANGUL SYLLABLE CHIEUCH WEO CHIEUCH +U+CDC8(2);; # HANGUL SYLLABLE CHIEUCH WEO KHIEUKH +U+CDC9(2);; # HANGUL SYLLABLE CHIEUCH WEO THIEUTH +U+CDCA(2);; # HANGUL SYLLABLE CHIEUCH WEO PHIEUPH +U+CDCB(2);; # HANGUL SYLLABLE CHIEUCH WEO HIEUH +U+CDCC(2);; # HANGUL SYLLABLE CHIEUCH WE * +U+CDCD(2);; # HANGUL SYLLABLE CHIEUCH WE KIYEOK +U+CDCE(2);; # HANGUL SYLLABLE CHIEUCH WE SSANGKIYEOK +U+CDCF(2);; # HANGUL SYLLABLE CHIEUCH WE KIYEOKSIOS +U+CDD0(2);; # HANGUL SYLLABLE CHIEUCH WE NIEUN * +U+CDD1(2);; # HANGUL SYLLABLE CHIEUCH WE NIEUNCIEUC +U+CDD2(2);; # HANGUL SYLLABLE CHIEUCH WE NIEUNHIEUH +U+CDD3(2);; # HANGUL SYLLABLE CHIEUCH WE TIKEUT +U+CDD4(2);; # HANGUL SYLLABLE CHIEUCH WE RIEUL +U+CDD5(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULKIYEOK +U+CDD6(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULMIEUM +U+CDD7(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULPIEUP +U+CDD8(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULSIOS +U+CDD9(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULTHIEUTH +U+CDDA(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULPHIEUPH +U+CDDB(2);; # HANGUL SYLLABLE CHIEUCH WE RIEULHIEUH +U+CDDC(2);; # HANGUL SYLLABLE CHIEUCH WE MIEUM +U+CDDD(2);; # HANGUL SYLLABLE CHIEUCH WE PIEUP +U+CDDE(2);; # HANGUL SYLLABLE CHIEUCH WE PIEUPSIOS +U+CDDF(2);; # HANGUL SYLLABLE CHIEUCH WE SIOS +U+CDE0(2);; # HANGUL SYLLABLE CHIEUCH WE SSANGSIOS +U+CDE1(2);; # HANGUL SYLLABLE CHIEUCH WE IEUNG +U+CDE2(2);; # HANGUL SYLLABLE CHIEUCH WE CIEUC +U+CDE3(2);; # HANGUL SYLLABLE CHIEUCH WE CHIEUCH +U+CDE4(2);; # HANGUL SYLLABLE CHIEUCH WE KHIEUKH +U+CDE5(2);; # HANGUL SYLLABLE CHIEUCH WE THIEUTH +U+CDE6(2);; # HANGUL SYLLABLE CHIEUCH WE PHIEUPH +U+CDE7(2);; # HANGUL SYLLABLE CHIEUCH WE HIEUH +U+CDE8(2);; # HANGUL SYLLABLE CHIEUCH WI * +U+CDE9(2);; # HANGUL SYLLABLE CHIEUCH WI KIYEOK +U+CDEA(2);; # HANGUL SYLLABLE CHIEUCH WI SSANGKIYEOK +U+CDEB(2);; # HANGUL SYLLABLE CHIEUCH WI KIYEOKSIOS +U+CDEC(2);; # HANGUL SYLLABLE CHIEUCH WI NIEUN * +U+CDED(2);; # HANGUL SYLLABLE CHIEUCH WI NIEUNCIEUC +U+CDEE(2);; # HANGUL SYLLABLE CHIEUCH WI NIEUNHIEUH +U+CDEF(2);; # HANGUL SYLLABLE CHIEUCH WI TIKEUT +U+CDF0(2);; # HANGUL SYLLABLE CHIEUCH WI RIEUL * +U+CDF1(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULKIYEOK +U+CDF2(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULMIEUM +U+CDF3(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULPIEUP +U+CDF4(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULSIOS +U+CDF5(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULTHIEUTH +U+CDF6(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULPHIEUPH +U+CDF7(2);; # HANGUL SYLLABLE CHIEUCH WI RIEULHIEUH +U+CDF8(2);; # HANGUL SYLLABLE CHIEUCH WI MIEUM * +U+CDF9(2);; # HANGUL SYLLABLE CHIEUCH WI PIEUP * +U+CDFA(2);; # HANGUL SYLLABLE CHIEUCH WI PIEUPSIOS +U+CDFB(2);; # HANGUL SYLLABLE CHIEUCH WI SIOS * +U+CDFC(2);; # HANGUL SYLLABLE CHIEUCH WI SSANGSIOS +U+CDFD(2);; # HANGUL SYLLABLE CHIEUCH WI IEUNG * +U+CDFE(2);; # HANGUL SYLLABLE CHIEUCH WI CIEUC +U+CDFF(2);; # HANGUL SYLLABLE CHIEUCH WI CHIEUCH +U+CE00(2);; # HANGUL SYLLABLE CHIEUCH WI KHIEUKH +U+CE01(2);; # HANGUL SYLLABLE CHIEUCH WI THIEUTH +U+CE02(2);; # HANGUL SYLLABLE CHIEUCH WI PHIEUPH +U+CE03(2);; # HANGUL SYLLABLE CHIEUCH WI HIEUH +U+CE04(2);; # HANGUL SYLLABLE CHIEUCH YU * +U+CE05(2);; # HANGUL SYLLABLE CHIEUCH YU KIYEOK +U+CE06(2);; # HANGUL SYLLABLE CHIEUCH YU SSANGKIYEOK +U+CE07(2);; # HANGUL SYLLABLE CHIEUCH YU KIYEOKSIOS +U+CE08(2);; # HANGUL SYLLABLE CHIEUCH YU NIEUN * +U+CE09(2);; # HANGUL SYLLABLE CHIEUCH YU NIEUNCIEUC +U+CE0A(2);; # HANGUL SYLLABLE CHIEUCH YU NIEUNHIEUH +U+CE0B(2);; # HANGUL SYLLABLE CHIEUCH YU TIKEUT +U+CE0C(2);; # HANGUL SYLLABLE CHIEUCH YU RIEUL * +U+CE0D(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULKIYEOK +U+CE0E(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULMIEUM +U+CE0F(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULPIEUP +U+CE10(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULSIOS +U+CE11(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULTHIEUTH +U+CE12(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULPHIEUPH +U+CE13(2);; # HANGUL SYLLABLE CHIEUCH YU RIEULHIEUH +U+CE14(2);; # HANGUL SYLLABLE CHIEUCH YU MIEUM * +U+CE15(2);; # HANGUL SYLLABLE CHIEUCH YU PIEUP +U+CE16(2);; # HANGUL SYLLABLE CHIEUCH YU PIEUPSIOS +U+CE17(2);; # HANGUL SYLLABLE CHIEUCH YU SIOS +U+CE18(2);; # HANGUL SYLLABLE CHIEUCH YU SSANGSIOS +U+CE19(2);; # HANGUL SYLLABLE CHIEUCH YU IEUNG * +U+CE1A(2);; # HANGUL SYLLABLE CHIEUCH YU CIEUC +U+CE1B(2);; # HANGUL SYLLABLE CHIEUCH YU CHIEUCH +U+CE1C(2);; # HANGUL SYLLABLE CHIEUCH YU KHIEUKH +U+CE1D(2);; # HANGUL SYLLABLE CHIEUCH YU THIEUTH +U+CE1E(2);; # HANGUL SYLLABLE CHIEUCH YU PHIEUPH +U+CE1F(2);; # HANGUL SYLLABLE CHIEUCH YU HIEUH +U+CE20(2);; # HANGUL SYLLABLE CHIEUCH EU * +U+CE21(2);; # HANGUL SYLLABLE CHIEUCH EU KIYEOK * +U+CE22(2);; # HANGUL SYLLABLE CHIEUCH EU SSANGKIYEOK +U+CE23(2);; # HANGUL SYLLABLE CHIEUCH EU KIYEOKSIOS +U+CE24(2);; # HANGUL SYLLABLE CHIEUCH EU NIEUN * +U+CE25(2);; # HANGUL SYLLABLE CHIEUCH EU NIEUNCIEUC +U+CE26(2);; # HANGUL SYLLABLE CHIEUCH EU NIEUNHIEUH +U+CE27(2);; # HANGUL SYLLABLE CHIEUCH EU TIKEUT +U+CE28(2);; # HANGUL SYLLABLE CHIEUCH EU RIEUL * +U+CE29(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULKIYEOK +U+CE2A(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULMIEUM +U+CE2B(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULPIEUP +U+CE2C(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULSIOS +U+CE2D(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULTHIEUTH +U+CE2E(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULPHIEUPH +U+CE2F(2);; # HANGUL SYLLABLE CHIEUCH EU RIEULHIEUH +U+CE30(2);; # HANGUL SYLLABLE CHIEUCH EU MIEUM * +U+CE31(2);; # HANGUL SYLLABLE CHIEUCH EU PIEUP * +U+CE32(2);; # HANGUL SYLLABLE CHIEUCH EU PIEUPSIOS +U+CE33(2);; # HANGUL SYLLABLE CHIEUCH EU SIOS * +U+CE34(2);; # HANGUL SYLLABLE CHIEUCH EU SSANGSIOS +U+CE35(2);; # HANGUL SYLLABLE CHIEUCH EU IEUNG * +U+CE36(2);; # HANGUL SYLLABLE CHIEUCH EU CIEUC +U+CE37(2);; # HANGUL SYLLABLE CHIEUCH EU CHIEUCH +U+CE38(2);; # HANGUL SYLLABLE CHIEUCH EU KHIEUKH +U+CE39(2);; # HANGUL SYLLABLE CHIEUCH EU THIEUTH +U+CE3A(2);; # HANGUL SYLLABLE CHIEUCH EU PHIEUPH +U+CE3B(2);; # HANGUL SYLLABLE CHIEUCH EU HIEUH +U+CE3C(2);; # HANGUL SYLLABLE CHIEUCH YI +U+CE3D(2);; # HANGUL SYLLABLE CHIEUCH YI KIYEOK +U+CE3E(2);; # HANGUL SYLLABLE CHIEUCH YI SSANGKIYEOK +U+CE3F(2);; # HANGUL SYLLABLE CHIEUCH YI KIYEOKSIOS +U+CE40(2);; # HANGUL SYLLABLE CHIEUCH YI NIEUN +U+CE41(2);; # HANGUL SYLLABLE CHIEUCH YI NIEUNCIEUC +U+CE42(2);; # HANGUL SYLLABLE CHIEUCH YI NIEUNHIEUH +U+CE43(2);; # HANGUL SYLLABLE CHIEUCH YI TIKEUT +U+CE44(2);; # HANGUL SYLLABLE CHIEUCH YI RIEUL +U+CE45(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULKIYEOK +U+CE46(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULMIEUM +U+CE47(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULPIEUP +U+CE48(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULSIOS +U+CE49(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULTHIEUTH +U+CE4A(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULPHIEUPH +U+CE4B(2);; # HANGUL SYLLABLE CHIEUCH YI RIEULHIEUH +U+CE4C(2);; # HANGUL SYLLABLE CHIEUCH YI MIEUM +U+CE4D(2);; # HANGUL SYLLABLE CHIEUCH YI PIEUP +U+CE4E(2);; # HANGUL SYLLABLE CHIEUCH YI PIEUPSIOS +U+CE4F(2);; # HANGUL SYLLABLE CHIEUCH YI SIOS +U+CE50(2);; # HANGUL SYLLABLE CHIEUCH YI SSANGSIOS +U+CE51(2);; # HANGUL SYLLABLE CHIEUCH YI IEUNG +U+CE52(2);; # HANGUL SYLLABLE CHIEUCH YI CIEUC +U+CE53(2);; # HANGUL SYLLABLE CHIEUCH YI CHIEUCH +U+CE54(2);; # HANGUL SYLLABLE CHIEUCH YI KHIEUKH +U+CE55(2);; # HANGUL SYLLABLE CHIEUCH YI THIEUTH +U+CE56(2);; # HANGUL SYLLABLE CHIEUCH YI PHIEUPH +U+CE57(2);; # HANGUL SYLLABLE CHIEUCH YI HIEUH +U+CE58(2);; # HANGUL SYLLABLE CHIEUCH I * +U+CE59(2);; # HANGUL SYLLABLE CHIEUCH I KIYEOK * +U+CE5A(2);; # HANGUL SYLLABLE CHIEUCH I SSANGKIYEOK +U+CE5B(2);; # HANGUL SYLLABLE CHIEUCH I KIYEOKSIOS +U+CE5C(2);; # HANGUL SYLLABLE CHIEUCH I NIEUN * +U+CE5D(2);; # HANGUL SYLLABLE CHIEUCH I NIEUNCIEUC +U+CE5E(2);; # HANGUL SYLLABLE CHIEUCH I NIEUNHIEUH +U+CE5F(2);; # HANGUL SYLLABLE CHIEUCH I TIKEUT * +U+CE60(2);; # HANGUL SYLLABLE CHIEUCH I RIEUL * +U+CE61(2);; # HANGUL SYLLABLE CHIEUCH I RIEULKIYEOK * +U+CE62(2);; # HANGUL SYLLABLE CHIEUCH I RIEULMIEUM +U+CE63(2);; # HANGUL SYLLABLE CHIEUCH I RIEULPIEUP +U+CE64(2);; # HANGUL SYLLABLE CHIEUCH I RIEULSIOS +U+CE65(2);; # HANGUL SYLLABLE CHIEUCH I RIEULTHIEUTH +U+CE66(2);; # HANGUL SYLLABLE CHIEUCH I RIEULPHIEUPH +U+CE67(2);; # HANGUL SYLLABLE CHIEUCH I RIEULHIEUH +U+CE68(2);; # HANGUL SYLLABLE CHIEUCH I MIEUM * +U+CE69(2);; # HANGUL SYLLABLE CHIEUCH I PIEUP * +U+CE6A(2);; # HANGUL SYLLABLE CHIEUCH I PIEUPSIOS +U+CE6B(2);; # HANGUL SYLLABLE CHIEUCH I SIOS * +U+CE6C(2);; # HANGUL SYLLABLE CHIEUCH I SSANGSIOS +U+CE6D(2);; # HANGUL SYLLABLE CHIEUCH I IEUNG * +U+CE6E(2);; # HANGUL SYLLABLE CHIEUCH I CIEUC +U+CE6F(2);; # HANGUL SYLLABLE CHIEUCH I CHIEUCH +U+CE70(2);; # HANGUL SYLLABLE CHIEUCH I KHIEUKH +U+CE71(2);; # HANGUL SYLLABLE CHIEUCH I THIEUTH +U+CE72(2);; # HANGUL SYLLABLE CHIEUCH I PHIEUPH +U+CE73(2);; # HANGUL SYLLABLE CHIEUCH I HIEUH +U+CE74(2);; # HANGUL SYLLABLE KHIEUKH A * +U+CE75(2);; # HANGUL SYLLABLE KHIEUKH A KIYEOK * +U+CE76(2);; # HANGUL SYLLABLE KHIEUKH A SSANGKIYEOK +U+CE77(2);; # HANGUL SYLLABLE KHIEUKH A KIYEOKSIOS +U+CE78(2);; # HANGUL SYLLABLE KHIEUKH A NIEUN * +U+CE79(2);; # HANGUL SYLLABLE KHIEUKH A NIEUNCIEUC +U+CE7A(2);; # HANGUL SYLLABLE KHIEUKH A NIEUNHIEUH +U+CE7B(2);; # HANGUL SYLLABLE KHIEUKH A TIKEUT +U+CE7C(2);; # HANGUL SYLLABLE KHIEUKH A RIEUL * +U+CE7D(2);; # HANGUL SYLLABLE KHIEUKH A RIEULKIYEOK +U+CE7E(2);; # HANGUL SYLLABLE KHIEUKH A RIEULMIEUM +U+CE7F(2);; # HANGUL SYLLABLE KHIEUKH A RIEULPIEUP +U+CE80(2);; # HANGUL SYLLABLE KHIEUKH A RIEULSIOS +U+CE81(2);; # HANGUL SYLLABLE KHIEUKH A RIEULTHIEUTH +U+CE82(2);; # HANGUL SYLLABLE KHIEUKH A RIEULPHIEUPH +U+CE83(2);; # HANGUL SYLLABLE KHIEUKH A RIEULHIEUH +U+CE84(2);; # HANGUL SYLLABLE KHIEUKH A MIEUM * +U+CE85(2);; # HANGUL SYLLABLE KHIEUKH A PIEUP * +U+CE86(2);; # HANGUL SYLLABLE KHIEUKH A PIEUPSIOS +U+CE87(2);; # HANGUL SYLLABLE KHIEUKH A SIOS * +U+CE88(2);; # HANGUL SYLLABLE KHIEUKH A SSANGSIOS +U+CE89(2);; # HANGUL SYLLABLE KHIEUKH A IEUNG * +U+CE8A(2);; # HANGUL SYLLABLE KHIEUKH A CIEUC +U+CE8B(2);; # HANGUL SYLLABLE KHIEUKH A CHIEUCH +U+CE8C(2);; # HANGUL SYLLABLE KHIEUKH A KHIEUKH +U+CE8D(2);; # HANGUL SYLLABLE KHIEUKH A THIEUTH +U+CE8E(2);; # HANGUL SYLLABLE KHIEUKH A PHIEUPH +U+CE8F(2);; # HANGUL SYLLABLE KHIEUKH A HIEUH +U+CE90(2);; # HANGUL SYLLABLE KHIEUKH AE * +U+CE91(2);; # HANGUL SYLLABLE KHIEUKH AE KIYEOK * +U+CE92(2);; # HANGUL SYLLABLE KHIEUKH AE SSANGKIYEOK +U+CE93(2);; # HANGUL SYLLABLE KHIEUKH AE KIYEOKSIOS +U+CE94(2);; # HANGUL SYLLABLE KHIEUKH AE NIEUN * +U+CE95(2);; # HANGUL SYLLABLE KHIEUKH AE NIEUNCIEUC +U+CE96(2);; # HANGUL SYLLABLE KHIEUKH AE NIEUNHIEUH +U+CE97(2);; # HANGUL SYLLABLE KHIEUKH AE TIKEUT +U+CE98(2);; # HANGUL SYLLABLE KHIEUKH AE RIEUL * +U+CE99(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULKIYEOK +U+CE9A(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULMIEUM +U+CE9B(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULPIEUP +U+CE9C(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULSIOS +U+CE9D(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULTHIEUTH +U+CE9E(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULPHIEUPH +U+CE9F(2);; # HANGUL SYLLABLE KHIEUKH AE RIEULHIEUH +U+CEA0(2);; # HANGUL SYLLABLE KHIEUKH AE MIEUM * +U+CEA1(2);; # HANGUL SYLLABLE KHIEUKH AE PIEUP * +U+CEA2(2);; # HANGUL SYLLABLE KHIEUKH AE PIEUPSIOS +U+CEA3(2);; # HANGUL SYLLABLE KHIEUKH AE SIOS * +U+CEA4(2);; # HANGUL SYLLABLE KHIEUKH AE SSANGSIOS * +U+CEA5(2);; # HANGUL SYLLABLE KHIEUKH AE IEUNG * +U+CEA6(2);; # HANGUL SYLLABLE KHIEUKH AE CIEUC +U+CEA7(2);; # HANGUL SYLLABLE KHIEUKH AE CHIEUCH +U+CEA8(2);; # HANGUL SYLLABLE KHIEUKH AE KHIEUKH +U+CEA9(2);; # HANGUL SYLLABLE KHIEUKH AE THIEUTH +U+CEAA(2);; # HANGUL SYLLABLE KHIEUKH AE PHIEUPH +U+CEAB(2);; # HANGUL SYLLABLE KHIEUKH AE HIEUH +U+CEAC(2);; # HANGUL SYLLABLE KHIEUKH YA * +U+CEAD(2);; # HANGUL SYLLABLE KHIEUKH YA KIYEOK * +U+CEAE(2);; # HANGUL SYLLABLE KHIEUKH YA SSANGKIYEOK +U+CEAF(2);; # HANGUL SYLLABLE KHIEUKH YA KIYEOKSIOS +U+CEB0(2);; # HANGUL SYLLABLE KHIEUKH YA NIEUN +U+CEB1(2);; # HANGUL SYLLABLE KHIEUKH YA NIEUNCIEUC +U+CEB2(2);; # HANGUL SYLLABLE KHIEUKH YA NIEUNHIEUH +U+CEB3(2);; # HANGUL SYLLABLE KHIEUKH YA TIKEUT +U+CEB4(2);; # HANGUL SYLLABLE KHIEUKH YA RIEUL +U+CEB5(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULKIYEOK +U+CEB6(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULMIEUM +U+CEB7(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULPIEUP +U+CEB8(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULSIOS +U+CEB9(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULTHIEUTH +U+CEBA(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULPHIEUPH +U+CEBB(2);; # HANGUL SYLLABLE KHIEUKH YA RIEULHIEUH +U+CEBC(2);; # HANGUL SYLLABLE KHIEUKH YA MIEUM +U+CEBD(2);; # HANGUL SYLLABLE KHIEUKH YA PIEUP +U+CEBE(2);; # HANGUL SYLLABLE KHIEUKH YA PIEUPSIOS +U+CEBF(2);; # HANGUL SYLLABLE KHIEUKH YA SIOS +U+CEC0(2);; # HANGUL SYLLABLE KHIEUKH YA SSANGSIOS +U+CEC1(2);; # HANGUL SYLLABLE KHIEUKH YA IEUNG * +U+CEC2(2);; # HANGUL SYLLABLE KHIEUKH YA CIEUC +U+CEC3(2);; # HANGUL SYLLABLE KHIEUKH YA CHIEUCH +U+CEC4(2);; # HANGUL SYLLABLE KHIEUKH YA KHIEUKH +U+CEC5(2);; # HANGUL SYLLABLE KHIEUKH YA THIEUTH +U+CEC6(2);; # HANGUL SYLLABLE KHIEUKH YA PHIEUPH +U+CEC7(2);; # HANGUL SYLLABLE KHIEUKH YA HIEUH +U+CEC8(2);; # HANGUL SYLLABLE KHIEUKH YAE +U+CEC9(2);; # HANGUL SYLLABLE KHIEUKH YAE KIYEOK +U+CECA(2);; # HANGUL SYLLABLE KHIEUKH YAE SSANGKIYEOK +U+CECB(2);; # HANGUL SYLLABLE KHIEUKH YAE KIYEOKSIOS +U+CECC(2);; # HANGUL SYLLABLE KHIEUKH YAE NIEUN +U+CECD(2);; # HANGUL SYLLABLE KHIEUKH YAE NIEUNCIEUC +U+CECE(2);; # HANGUL SYLLABLE KHIEUKH YAE NIEUNHIEUH +U+CECF(2);; # HANGUL SYLLABLE KHIEUKH YAE TIKEUT +U+CED0(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEUL +U+CED1(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULKIYEOK +U+CED2(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULMIEUM +U+CED3(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULPIEUP +U+CED4(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULSIOS +U+CED5(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULTHIEUTH +U+CED6(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULPHIEUPH +U+CED7(2);; # HANGUL SYLLABLE KHIEUKH YAE RIEULHIEUH +U+CED8(2);; # HANGUL SYLLABLE KHIEUKH YAE MIEUM +U+CED9(2);; # HANGUL SYLLABLE KHIEUKH YAE PIEUP +U+CEDA(2);; # HANGUL SYLLABLE KHIEUKH YAE PIEUPSIOS +U+CEDB(2);; # HANGUL SYLLABLE KHIEUKH YAE SIOS +U+CEDC(2);; # HANGUL SYLLABLE KHIEUKH YAE SSANGSIOS +U+CEDD(2);; # HANGUL SYLLABLE KHIEUKH YAE IEUNG +U+CEDE(2);; # HANGUL SYLLABLE KHIEUKH YAE CIEUC +U+CEDF(2);; # HANGUL SYLLABLE KHIEUKH YAE CHIEUCH +U+CEE0(2);; # HANGUL SYLLABLE KHIEUKH YAE KHIEUKH +U+CEE1(2);; # HANGUL SYLLABLE KHIEUKH YAE THIEUTH +U+CEE2(2);; # HANGUL SYLLABLE KHIEUKH YAE PHIEUPH +U+CEE3(2);; # HANGUL SYLLABLE KHIEUKH YAE HIEUH +U+CEE4(2);; # HANGUL SYLLABLE KHIEUKH EO * +U+CEE5(2);; # HANGUL SYLLABLE KHIEUKH EO KIYEOK * +U+CEE6(2);; # HANGUL SYLLABLE KHIEUKH EO SSANGKIYEOK +U+CEE7(2);; # HANGUL SYLLABLE KHIEUKH EO KIYEOKSIOS +U+CEE8(2);; # HANGUL SYLLABLE KHIEUKH EO NIEUN * +U+CEE9(2);; # HANGUL SYLLABLE KHIEUKH EO NIEUNCIEUC +U+CEEA(2);; # HANGUL SYLLABLE KHIEUKH EO NIEUNHIEUH +U+CEEB(2);; # HANGUL SYLLABLE KHIEUKH EO TIKEUT * +U+CEEC(2);; # HANGUL SYLLABLE KHIEUKH EO RIEUL * +U+CEED(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULKIYEOK +U+CEEE(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULMIEUM +U+CEEF(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULPIEUP +U+CEF0(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULSIOS +U+CEF1(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULTHIEUTH +U+CEF2(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULPHIEUPH +U+CEF3(2);; # HANGUL SYLLABLE KHIEUKH EO RIEULHIEUH +U+CEF4(2);; # HANGUL SYLLABLE KHIEUKH EO MIEUM * +U+CEF5(2);; # HANGUL SYLLABLE KHIEUKH EO PIEUP * +U+CEF6(2);; # HANGUL SYLLABLE KHIEUKH EO PIEUPSIOS +U+CEF7(2);; # HANGUL SYLLABLE KHIEUKH EO SIOS * +U+CEF8(2);; # HANGUL SYLLABLE KHIEUKH EO SSANGSIOS * +U+CEF9(2);; # HANGUL SYLLABLE KHIEUKH EO IEUNG * +U+CEFA(2);; # HANGUL SYLLABLE KHIEUKH EO CIEUC +U+CEFB(2);; # HANGUL SYLLABLE KHIEUKH EO CHIEUCH +U+CEFC(2);; # HANGUL SYLLABLE KHIEUKH EO KHIEUKH +U+CEFD(2);; # HANGUL SYLLABLE KHIEUKH EO THIEUTH +U+CEFE(2);; # HANGUL SYLLABLE KHIEUKH EO PHIEUPH +U+CEFF(2);; # HANGUL SYLLABLE KHIEUKH EO HIEUH +U+CF00(2);; # HANGUL SYLLABLE KHIEUKH E * +U+CF01(2);; # HANGUL SYLLABLE KHIEUKH E KIYEOK * +U+CF02(2);; # HANGUL SYLLABLE KHIEUKH E SSANGKIYEOK +U+CF03(2);; # HANGUL SYLLABLE KHIEUKH E KIYEOKSIOS +U+CF04(2);; # HANGUL SYLLABLE KHIEUKH E NIEUN * +U+CF05(2);; # HANGUL SYLLABLE KHIEUKH E NIEUNCIEUC +U+CF06(2);; # HANGUL SYLLABLE KHIEUKH E NIEUNHIEUH +U+CF07(2);; # HANGUL SYLLABLE KHIEUKH E TIKEUT +U+CF08(2);; # HANGUL SYLLABLE KHIEUKH E RIEUL * +U+CF09(2);; # HANGUL SYLLABLE KHIEUKH E RIEULKIYEOK +U+CF0A(2);; # HANGUL SYLLABLE KHIEUKH E RIEULMIEUM +U+CF0B(2);; # HANGUL SYLLABLE KHIEUKH E RIEULPIEUP +U+CF0C(2);; # HANGUL SYLLABLE KHIEUKH E RIEULSIOS +U+CF0D(2);; # HANGUL SYLLABLE KHIEUKH E RIEULTHIEUTH +U+CF0E(2);; # HANGUL SYLLABLE KHIEUKH E RIEULPHIEUPH +U+CF0F(2);; # HANGUL SYLLABLE KHIEUKH E RIEULHIEUH +U+CF10(2);; # HANGUL SYLLABLE KHIEUKH E MIEUM * +U+CF11(2);; # HANGUL SYLLABLE KHIEUKH E PIEUP * +U+CF12(2);; # HANGUL SYLLABLE KHIEUKH E PIEUPSIOS +U+CF13(2);; # HANGUL SYLLABLE KHIEUKH E SIOS * +U+CF14(2);; # HANGUL SYLLABLE KHIEUKH E SSANGSIOS +U+CF15(2);; # HANGUL SYLLABLE KHIEUKH E IEUNG * +U+CF16(2);; # HANGUL SYLLABLE KHIEUKH E CIEUC +U+CF17(2);; # HANGUL SYLLABLE KHIEUKH E CHIEUCH +U+CF18(2);; # HANGUL SYLLABLE KHIEUKH E KHIEUKH +U+CF19(2);; # HANGUL SYLLABLE KHIEUKH E THIEUTH +U+CF1A(2);; # HANGUL SYLLABLE KHIEUKH E PHIEUPH +U+CF1B(2);; # HANGUL SYLLABLE KHIEUKH E HIEUH +U+CF1C(2);; # HANGUL SYLLABLE KHIEUKH YEO * +U+CF1D(2);; # HANGUL SYLLABLE KHIEUKH YEO KIYEOK +U+CF1E(2);; # HANGUL SYLLABLE KHIEUKH YEO SSANGKIYEOK +U+CF1F(2);; # HANGUL SYLLABLE KHIEUKH YEO KIYEOKSIOS +U+CF20(2);; # HANGUL SYLLABLE KHIEUKH YEO NIEUN * +U+CF21(2);; # HANGUL SYLLABLE KHIEUKH YEO NIEUNCIEUC +U+CF22(2);; # HANGUL SYLLABLE KHIEUKH YEO NIEUNHIEUH +U+CF23(2);; # HANGUL SYLLABLE KHIEUKH YEO TIKEUT +U+CF24(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEUL * +U+CF25(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULKIYEOK +U+CF26(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULMIEUM +U+CF27(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULPIEUP +U+CF28(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULSIOS +U+CF29(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULTHIEUTH +U+CF2A(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULPHIEUPH +U+CF2B(2);; # HANGUL SYLLABLE KHIEUKH YEO RIEULHIEUH +U+CF2C(2);; # HANGUL SYLLABLE KHIEUKH YEO MIEUM * +U+CF2D(2);; # HANGUL SYLLABLE KHIEUKH YEO PIEUP * +U+CF2E(2);; # HANGUL SYLLABLE KHIEUKH YEO PIEUPSIOS +U+CF2F(2);; # HANGUL SYLLABLE KHIEUKH YEO SIOS * +U+CF30(2);; # HANGUL SYLLABLE KHIEUKH YEO SSANGSIOS * +U+CF31(2);; # HANGUL SYLLABLE KHIEUKH YEO IEUNG * +U+CF32(2);; # HANGUL SYLLABLE KHIEUKH YEO CIEUC +U+CF33(2);; # HANGUL SYLLABLE KHIEUKH YEO CHIEUCH +U+CF34(2);; # HANGUL SYLLABLE KHIEUKH YEO KHIEUKH +U+CF35(2);; # HANGUL SYLLABLE KHIEUKH YEO THIEUTH +U+CF36(2);; # HANGUL SYLLABLE KHIEUKH YEO PHIEUPH +U+CF37(2);; # HANGUL SYLLABLE KHIEUKH YEO HIEUH +U+CF38(2);; # HANGUL SYLLABLE KHIEUKH YE * +U+CF39(2);; # HANGUL SYLLABLE KHIEUKH YE KIYEOK +U+CF3A(2);; # HANGUL SYLLABLE KHIEUKH YE SSANGKIYEOK +U+CF3B(2);; # HANGUL SYLLABLE KHIEUKH YE KIYEOKSIOS +U+CF3C(2);; # HANGUL SYLLABLE KHIEUKH YE NIEUN +U+CF3D(2);; # HANGUL SYLLABLE KHIEUKH YE NIEUNCIEUC +U+CF3E(2);; # HANGUL SYLLABLE KHIEUKH YE NIEUNHIEUH +U+CF3F(2);; # HANGUL SYLLABLE KHIEUKH YE TIKEUT +U+CF40(2);; # HANGUL SYLLABLE KHIEUKH YE RIEUL +U+CF41(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULKIYEOK +U+CF42(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULMIEUM +U+CF43(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULPIEUP +U+CF44(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULSIOS +U+CF45(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULTHIEUTH +U+CF46(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULPHIEUPH +U+CF47(2);; # HANGUL SYLLABLE KHIEUKH YE RIEULHIEUH +U+CF48(2);; # HANGUL SYLLABLE KHIEUKH YE MIEUM +U+CF49(2);; # HANGUL SYLLABLE KHIEUKH YE PIEUP +U+CF4A(2);; # HANGUL SYLLABLE KHIEUKH YE PIEUPSIOS +U+CF4B(2);; # HANGUL SYLLABLE KHIEUKH YE SIOS +U+CF4C(2);; # HANGUL SYLLABLE KHIEUKH YE SSANGSIOS +U+CF4D(2);; # HANGUL SYLLABLE KHIEUKH YE IEUNG +U+CF4E(2);; # HANGUL SYLLABLE KHIEUKH YE CIEUC +U+CF4F(2);; # HANGUL SYLLABLE KHIEUKH YE CHIEUCH +U+CF50(2);; # HANGUL SYLLABLE KHIEUKH YE KHIEUKH +U+CF51(2);; # HANGUL SYLLABLE KHIEUKH YE THIEUTH +U+CF52(2);; # HANGUL SYLLABLE KHIEUKH YE PHIEUPH +U+CF53(2);; # HANGUL SYLLABLE KHIEUKH YE HIEUH +U+CF54(2);; # HANGUL SYLLABLE KHIEUKH O * +U+CF55(2);; # HANGUL SYLLABLE KHIEUKH O KIYEOK * +U+CF56(2);; # HANGUL SYLLABLE KHIEUKH O SSANGKIYEOK +U+CF57(2);; # HANGUL SYLLABLE KHIEUKH O KIYEOKSIOS +U+CF58(2);; # HANGUL SYLLABLE KHIEUKH O NIEUN * +U+CF59(2);; # HANGUL SYLLABLE KHIEUKH O NIEUNCIEUC +U+CF5A(2);; # HANGUL SYLLABLE KHIEUKH O NIEUNHIEUH +U+CF5B(2);; # HANGUL SYLLABLE KHIEUKH O TIKEUT +U+CF5C(2);; # HANGUL SYLLABLE KHIEUKH O RIEUL * +U+CF5D(2);; # HANGUL SYLLABLE KHIEUKH O RIEULKIYEOK +U+CF5E(2);; # HANGUL SYLLABLE KHIEUKH O RIEULMIEUM +U+CF5F(2);; # HANGUL SYLLABLE KHIEUKH O RIEULPIEUP +U+CF60(2);; # HANGUL SYLLABLE KHIEUKH O RIEULSIOS +U+CF61(2);; # HANGUL SYLLABLE KHIEUKH O RIEULTHIEUTH +U+CF62(2);; # HANGUL SYLLABLE KHIEUKH O RIEULPHIEUPH +U+CF63(2);; # HANGUL SYLLABLE KHIEUKH O RIEULHIEUH +U+CF64(2);; # HANGUL SYLLABLE KHIEUKH O MIEUM * +U+CF65(2);; # HANGUL SYLLABLE KHIEUKH O PIEUP * +U+CF66(2);; # HANGUL SYLLABLE KHIEUKH O PIEUPSIOS +U+CF67(2);; # HANGUL SYLLABLE KHIEUKH O SIOS * +U+CF68(2);; # HANGUL SYLLABLE KHIEUKH O SSANGSIOS +U+CF69(2);; # HANGUL SYLLABLE KHIEUKH O IEUNG * +U+CF6A(2);; # HANGUL SYLLABLE KHIEUKH O CIEUC +U+CF6B(2);; # HANGUL SYLLABLE KHIEUKH O CHIEUCH +U+CF6C(2);; # HANGUL SYLLABLE KHIEUKH O KHIEUKH +U+CF6D(2);; # HANGUL SYLLABLE KHIEUKH O THIEUTH +U+CF6E(2);; # HANGUL SYLLABLE KHIEUKH O PHIEUPH +U+CF6F(2);; # HANGUL SYLLABLE KHIEUKH O HIEUH +U+CF70(2);; # HANGUL SYLLABLE KHIEUKH WA * +U+CF71(2);; # HANGUL SYLLABLE KHIEUKH WA KIYEOK * +U+CF72(2);; # HANGUL SYLLABLE KHIEUKH WA SSANGKIYEOK +U+CF73(2);; # HANGUL SYLLABLE KHIEUKH WA KIYEOKSIOS +U+CF74(2);; # HANGUL SYLLABLE KHIEUKH WA NIEUN * +U+CF75(2);; # HANGUL SYLLABLE KHIEUKH WA NIEUNCIEUC +U+CF76(2);; # HANGUL SYLLABLE KHIEUKH WA NIEUNHIEUH +U+CF77(2);; # HANGUL SYLLABLE KHIEUKH WA TIKEUT +U+CF78(2);; # HANGUL SYLLABLE KHIEUKH WA RIEUL * +U+CF79(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULKIYEOK +U+CF7A(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULMIEUM +U+CF7B(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULPIEUP +U+CF7C(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULSIOS +U+CF7D(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULTHIEUTH +U+CF7E(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULPHIEUPH +U+CF7F(2);; # HANGUL SYLLABLE KHIEUKH WA RIEULHIEUH +U+CF80(2);; # HANGUL SYLLABLE KHIEUKH WA MIEUM * +U+CF81(2);; # HANGUL SYLLABLE KHIEUKH WA PIEUP +U+CF82(2);; # HANGUL SYLLABLE KHIEUKH WA PIEUPSIOS +U+CF83(2);; # HANGUL SYLLABLE KHIEUKH WA SIOS +U+CF84(2);; # HANGUL SYLLABLE KHIEUKH WA SSANGSIOS +U+CF85(2);; # HANGUL SYLLABLE KHIEUKH WA IEUNG * +U+CF86(2);; # HANGUL SYLLABLE KHIEUKH WA CIEUC +U+CF87(2);; # HANGUL SYLLABLE KHIEUKH WA CHIEUCH +U+CF88(2);; # HANGUL SYLLABLE KHIEUKH WA KHIEUKH +U+CF89(2);; # HANGUL SYLLABLE KHIEUKH WA THIEUTH +U+CF8A(2);; # HANGUL SYLLABLE KHIEUKH WA PHIEUPH +U+CF8B(2);; # HANGUL SYLLABLE KHIEUKH WA HIEUH +U+CF8C(2);; # HANGUL SYLLABLE KHIEUKH WAE * +U+CF8D(2);; # HANGUL SYLLABLE KHIEUKH WAE KIYEOK +U+CF8E(2);; # HANGUL SYLLABLE KHIEUKH WAE SSANGKIYEOK +U+CF8F(2);; # HANGUL SYLLABLE KHIEUKH WAE KIYEOKSIOS +U+CF90(2);; # HANGUL SYLLABLE KHIEUKH WAE NIEUN +U+CF91(2);; # HANGUL SYLLABLE KHIEUKH WAE NIEUNCIEUC +U+CF92(2);; # HANGUL SYLLABLE KHIEUKH WAE NIEUNHIEUH +U+CF93(2);; # HANGUL SYLLABLE KHIEUKH WAE TIKEUT +U+CF94(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEUL +U+CF95(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULKIYEOK +U+CF96(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULMIEUM +U+CF97(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULPIEUP +U+CF98(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULSIOS +U+CF99(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULTHIEUTH +U+CF9A(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULPHIEUPH +U+CF9B(2);; # HANGUL SYLLABLE KHIEUKH WAE RIEULHIEUH +U+CF9C(2);; # HANGUL SYLLABLE KHIEUKH WAE MIEUM +U+CF9D(2);; # HANGUL SYLLABLE KHIEUKH WAE PIEUP +U+CF9E(2);; # HANGUL SYLLABLE KHIEUKH WAE PIEUPSIOS +U+CF9F(2);; # HANGUL SYLLABLE KHIEUKH WAE SIOS +U+CFA0(2);; # HANGUL SYLLABLE KHIEUKH WAE SSANGSIOS +U+CFA1(2);; # HANGUL SYLLABLE KHIEUKH WAE IEUNG * +U+CFA2(2);; # HANGUL SYLLABLE KHIEUKH WAE CIEUC +U+CFA3(2);; # HANGUL SYLLABLE KHIEUKH WAE CHIEUCH +U+CFA4(2);; # HANGUL SYLLABLE KHIEUKH WAE KHIEUKH +U+CFA5(2);; # HANGUL SYLLABLE KHIEUKH WAE THIEUTH +U+CFA6(2);; # HANGUL SYLLABLE KHIEUKH WAE PHIEUPH +U+CFA7(2);; # HANGUL SYLLABLE KHIEUKH WAE HIEUH +U+CFA8(2);; # HANGUL SYLLABLE KHIEUKH OE * +U+CFA9(2);; # HANGUL SYLLABLE KHIEUKH OE KIYEOK +U+CFAA(2);; # HANGUL SYLLABLE KHIEUKH OE SSANGKIYEOK +U+CFAB(2);; # HANGUL SYLLABLE KHIEUKH OE KIYEOKSIOS +U+CFAC(2);; # HANGUL SYLLABLE KHIEUKH OE NIEUN +U+CFAD(2);; # HANGUL SYLLABLE KHIEUKH OE NIEUNCIEUC +U+CFAE(2);; # HANGUL SYLLABLE KHIEUKH OE NIEUNHIEUH +U+CFAF(2);; # HANGUL SYLLABLE KHIEUKH OE TIKEUT +U+CFB0(2);; # HANGUL SYLLABLE KHIEUKH OE RIEUL * +U+CFB1(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULKIYEOK +U+CFB2(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULMIEUM +U+CFB3(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULPIEUP +U+CFB4(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULSIOS +U+CFB5(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULTHIEUTH +U+CFB6(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULPHIEUPH +U+CFB7(2);; # HANGUL SYLLABLE KHIEUKH OE RIEULHIEUH +U+CFB8(2);; # HANGUL SYLLABLE KHIEUKH OE MIEUM +U+CFB9(2);; # HANGUL SYLLABLE KHIEUKH OE PIEUP +U+CFBA(2);; # HANGUL SYLLABLE KHIEUKH OE PIEUPSIOS +U+CFBB(2);; # HANGUL SYLLABLE KHIEUKH OE SIOS +U+CFBC(2);; # HANGUL SYLLABLE KHIEUKH OE SSANGSIOS +U+CFBD(2);; # HANGUL SYLLABLE KHIEUKH OE IEUNG +U+CFBE(2);; # HANGUL SYLLABLE KHIEUKH OE CIEUC +U+CFBF(2);; # HANGUL SYLLABLE KHIEUKH OE CHIEUCH +U+CFC0(2);; # HANGUL SYLLABLE KHIEUKH OE KHIEUKH +U+CFC1(2);; # HANGUL SYLLABLE KHIEUKH OE THIEUTH +U+CFC2(2);; # HANGUL SYLLABLE KHIEUKH OE PHIEUPH +U+CFC3(2);; # HANGUL SYLLABLE KHIEUKH OE HIEUH +U+CFC4(2);; # HANGUL SYLLABLE KHIEUKH YO * +U+CFC5(2);; # HANGUL SYLLABLE KHIEUKH YO KIYEOK +U+CFC6(2);; # HANGUL SYLLABLE KHIEUKH YO SSANGKIYEOK +U+CFC7(2);; # HANGUL SYLLABLE KHIEUKH YO KIYEOKSIOS +U+CFC8(2);; # HANGUL SYLLABLE KHIEUKH YO NIEUN +U+CFC9(2);; # HANGUL SYLLABLE KHIEUKH YO NIEUNCIEUC +U+CFCA(2);; # HANGUL SYLLABLE KHIEUKH YO NIEUNHIEUH +U+CFCB(2);; # HANGUL SYLLABLE KHIEUKH YO TIKEUT +U+CFCC(2);; # HANGUL SYLLABLE KHIEUKH YO RIEUL +U+CFCD(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULKIYEOK +U+CFCE(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULMIEUM +U+CFCF(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULPIEUP +U+CFD0(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULSIOS +U+CFD1(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULTHIEUTH +U+CFD2(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULPHIEUPH +U+CFD3(2);; # HANGUL SYLLABLE KHIEUKH YO RIEULHIEUH +U+CFD4(2);; # HANGUL SYLLABLE KHIEUKH YO MIEUM +U+CFD5(2);; # HANGUL SYLLABLE KHIEUKH YO PIEUP +U+CFD6(2);; # HANGUL SYLLABLE KHIEUKH YO PIEUPSIOS +U+CFD7(2);; # HANGUL SYLLABLE KHIEUKH YO SIOS +U+CFD8(2);; # HANGUL SYLLABLE KHIEUKH YO SSANGSIOS +U+CFD9(2);; # HANGUL SYLLABLE KHIEUKH YO IEUNG +U+CFDA(2);; # HANGUL SYLLABLE KHIEUKH YO CIEUC +U+CFDB(2);; # HANGUL SYLLABLE KHIEUKH YO CHIEUCH +U+CFDC(2);; # HANGUL SYLLABLE KHIEUKH YO KHIEUKH +U+CFDD(2);; # HANGUL SYLLABLE KHIEUKH YO THIEUTH +U+CFDE(2);; # HANGUL SYLLABLE KHIEUKH YO PHIEUPH +U+CFDF(2);; # HANGUL SYLLABLE KHIEUKH YO HIEUH +U+CFE0(2);; # HANGUL SYLLABLE KHIEUKH U * +U+CFE1(2);; # HANGUL SYLLABLE KHIEUKH U KIYEOK * +U+CFE2(2);; # HANGUL SYLLABLE KHIEUKH U SSANGKIYEOK +U+CFE3(2);; # HANGUL SYLLABLE KHIEUKH U KIYEOKSIOS +U+CFE4(2);; # HANGUL SYLLABLE KHIEUKH U NIEUN * +U+CFE5(2);; # HANGUL SYLLABLE KHIEUKH U NIEUNCIEUC +U+CFE6(2);; # HANGUL SYLLABLE KHIEUKH U NIEUNHIEUH +U+CFE7(2);; # HANGUL SYLLABLE KHIEUKH U TIKEUT +U+CFE8(2);; # HANGUL SYLLABLE KHIEUKH U RIEUL * +U+CFE9(2);; # HANGUL SYLLABLE KHIEUKH U RIEULKIYEOK +U+CFEA(2);; # HANGUL SYLLABLE KHIEUKH U RIEULMIEUM +U+CFEB(2);; # HANGUL SYLLABLE KHIEUKH U RIEULPIEUP +U+CFEC(2);; # HANGUL SYLLABLE KHIEUKH U RIEULSIOS +U+CFED(2);; # HANGUL SYLLABLE KHIEUKH U RIEULTHIEUTH +U+CFEE(2);; # HANGUL SYLLABLE KHIEUKH U RIEULPHIEUPH +U+CFEF(2);; # HANGUL SYLLABLE KHIEUKH U RIEULHIEUH +U+CFF0(2);; # HANGUL SYLLABLE KHIEUKH U MIEUM * +U+CFF1(2);; # HANGUL SYLLABLE KHIEUKH U PIEUP * +U+CFF2(2);; # HANGUL SYLLABLE KHIEUKH U PIEUPSIOS +U+CFF3(2);; # HANGUL SYLLABLE KHIEUKH U SIOS * +U+CFF4(2);; # HANGUL SYLLABLE KHIEUKH U SSANGSIOS +U+CFF5(2);; # HANGUL SYLLABLE KHIEUKH U IEUNG * +U+CFF6(2);; # HANGUL SYLLABLE KHIEUKH U CIEUC +U+CFF7(2);; # HANGUL SYLLABLE KHIEUKH U CHIEUCH +U+CFF8(2);; # HANGUL SYLLABLE KHIEUKH U KHIEUKH +U+CFF9(2);; # HANGUL SYLLABLE KHIEUKH U THIEUTH +U+CFFA(2);; # HANGUL SYLLABLE KHIEUKH U PHIEUPH +U+CFFB(2);; # HANGUL SYLLABLE KHIEUKH U HIEUH +U+CFFC(2);; # HANGUL SYLLABLE KHIEUKH WEO * +U+CFFD(2);; # HANGUL SYLLABLE KHIEUKH WEO KIYEOK +U+CFFE(2);; # HANGUL SYLLABLE KHIEUKH WEO SSANGKIYEOK +U+CFFF(2);; # HANGUL SYLLABLE KHIEUKH WEO KIYEOKSIOS +U+D000(2);; # HANGUL SYLLABLE KHIEUKH WEO NIEUN * +U+D001(2);; # HANGUL SYLLABLE KHIEUKH WEO NIEUNCIEUC +U+D002(2);; # HANGUL SYLLABLE KHIEUKH WEO NIEUNHIEUH +U+D003(2);; # HANGUL SYLLABLE KHIEUKH WEO TIKEUT +U+D004(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEUL * +U+D005(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULKIYEOK +U+D006(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULMIEUM +U+D007(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULPIEUP +U+D008(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULSIOS +U+D009(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULTHIEUTH +U+D00A(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULPHIEUPH +U+D00B(2);; # HANGUL SYLLABLE KHIEUKH WEO RIEULHIEUH +U+D00C(2);; # HANGUL SYLLABLE KHIEUKH WEO MIEUM +U+D00D(2);; # HANGUL SYLLABLE KHIEUKH WEO PIEUP +U+D00E(2);; # HANGUL SYLLABLE KHIEUKH WEO PIEUPSIOS +U+D00F(2);; # HANGUL SYLLABLE KHIEUKH WEO SIOS +U+D010(2);; # HANGUL SYLLABLE KHIEUKH WEO SSANGSIOS +U+D011(2);; # HANGUL SYLLABLE KHIEUKH WEO IEUNG * +U+D012(2);; # HANGUL SYLLABLE KHIEUKH WEO CIEUC +U+D013(2);; # HANGUL SYLLABLE KHIEUKH WEO CHIEUCH +U+D014(2);; # HANGUL SYLLABLE KHIEUKH WEO KHIEUKH +U+D015(2);; # HANGUL SYLLABLE KHIEUKH WEO THIEUTH +U+D016(2);; # HANGUL SYLLABLE KHIEUKH WEO PHIEUPH +U+D017(2);; # HANGUL SYLLABLE KHIEUKH WEO HIEUH +U+D018(2);; # HANGUL SYLLABLE KHIEUKH WE * +U+D019(2);; # HANGUL SYLLABLE KHIEUKH WE KIYEOK +U+D01A(2);; # HANGUL SYLLABLE KHIEUKH WE SSANGKIYEOK +U+D01B(2);; # HANGUL SYLLABLE KHIEUKH WE KIYEOKSIOS +U+D01C(2);; # HANGUL SYLLABLE KHIEUKH WE NIEUN +U+D01D(2);; # HANGUL SYLLABLE KHIEUKH WE NIEUNCIEUC +U+D01E(2);; # HANGUL SYLLABLE KHIEUKH WE NIEUNHIEUH +U+D01F(2);; # HANGUL SYLLABLE KHIEUKH WE TIKEUT +U+D020(2);; # HANGUL SYLLABLE KHIEUKH WE RIEUL +U+D021(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULKIYEOK +U+D022(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULMIEUM +U+D023(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULPIEUP +U+D024(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULSIOS +U+D025(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULTHIEUTH +U+D026(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULPHIEUPH +U+D027(2);; # HANGUL SYLLABLE KHIEUKH WE RIEULHIEUH +U+D028(2);; # HANGUL SYLLABLE KHIEUKH WE MIEUM +U+D029(2);; # HANGUL SYLLABLE KHIEUKH WE PIEUP +U+D02A(2);; # HANGUL SYLLABLE KHIEUKH WE PIEUPSIOS +U+D02B(2);; # HANGUL SYLLABLE KHIEUKH WE SIOS +U+D02C(2);; # HANGUL SYLLABLE KHIEUKH WE SSANGSIOS +U+D02D(2);; # HANGUL SYLLABLE KHIEUKH WE IEUNG * +U+D02E(2);; # HANGUL SYLLABLE KHIEUKH WE CIEUC +U+D02F(2);; # HANGUL SYLLABLE KHIEUKH WE CHIEUCH +U+D030(2);; # HANGUL SYLLABLE KHIEUKH WE KHIEUKH +U+D031(2);; # HANGUL SYLLABLE KHIEUKH WE THIEUTH +U+D032(2);; # HANGUL SYLLABLE KHIEUKH WE PHIEUPH +U+D033(2);; # HANGUL SYLLABLE KHIEUKH WE HIEUH +U+D034(2);; # HANGUL SYLLABLE KHIEUKH WI * +U+D035(2);; # HANGUL SYLLABLE KHIEUKH WI KIYEOK * +U+D036(2);; # HANGUL SYLLABLE KHIEUKH WI SSANGKIYEOK +U+D037(2);; # HANGUL SYLLABLE KHIEUKH WI KIYEOKSIOS +U+D038(2);; # HANGUL SYLLABLE KHIEUKH WI NIEUN * +U+D039(2);; # HANGUL SYLLABLE KHIEUKH WI NIEUNCIEUC +U+D03A(2);; # HANGUL SYLLABLE KHIEUKH WI NIEUNHIEUH +U+D03B(2);; # HANGUL SYLLABLE KHIEUKH WI TIKEUT +U+D03C(2);; # HANGUL SYLLABLE KHIEUKH WI RIEUL * +U+D03D(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULKIYEOK +U+D03E(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULMIEUM +U+D03F(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULPIEUP +U+D040(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULSIOS +U+D041(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULTHIEUTH +U+D042(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULPHIEUPH +U+D043(2);; # HANGUL SYLLABLE KHIEUKH WI RIEULHIEUH +U+D044(2);; # HANGUL SYLLABLE KHIEUKH WI MIEUM * +U+D045(2);; # HANGUL SYLLABLE KHIEUKH WI PIEUP * +U+D046(2);; # HANGUL SYLLABLE KHIEUKH WI PIEUPSIOS +U+D047(2);; # HANGUL SYLLABLE KHIEUKH WI SIOS * +U+D048(2);; # HANGUL SYLLABLE KHIEUKH WI SSANGSIOS +U+D049(2);; # HANGUL SYLLABLE KHIEUKH WI IEUNG * +U+D04A(2);; # HANGUL SYLLABLE KHIEUKH WI CIEUC +U+D04B(2);; # HANGUL SYLLABLE KHIEUKH WI CHIEUCH +U+D04C(2);; # HANGUL SYLLABLE KHIEUKH WI KHIEUKH +U+D04D(2);; # HANGUL SYLLABLE KHIEUKH WI THIEUTH +U+D04E(2);; # HANGUL SYLLABLE KHIEUKH WI PHIEUPH +U+D04F(2);; # HANGUL SYLLABLE KHIEUKH WI HIEUH +U+D050(2);; # HANGUL SYLLABLE KHIEUKH YU * +U+D051(2);; # HANGUL SYLLABLE KHIEUKH YU KIYEOK +U+D052(2);; # HANGUL SYLLABLE KHIEUKH YU SSANGKIYEOK +U+D053(2);; # HANGUL SYLLABLE KHIEUKH YU KIYEOKSIOS +U+D054(2);; # HANGUL SYLLABLE KHIEUKH YU NIEUN * +U+D055(2);; # HANGUL SYLLABLE KHIEUKH YU NIEUNCIEUC +U+D056(2);; # HANGUL SYLLABLE KHIEUKH YU NIEUNHIEUH +U+D057(2);; # HANGUL SYLLABLE KHIEUKH YU TIKEUT +U+D058(2);; # HANGUL SYLLABLE KHIEUKH YU RIEUL * +U+D059(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULKIYEOK +U+D05A(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULMIEUM +U+D05B(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULPIEUP +U+D05C(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULSIOS +U+D05D(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULTHIEUTH +U+D05E(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULPHIEUPH +U+D05F(2);; # HANGUL SYLLABLE KHIEUKH YU RIEULHIEUH +U+D060(2);; # HANGUL SYLLABLE KHIEUKH YU MIEUM * +U+D061(2);; # HANGUL SYLLABLE KHIEUKH YU PIEUP +U+D062(2);; # HANGUL SYLLABLE KHIEUKH YU PIEUPSIOS +U+D063(2);; # HANGUL SYLLABLE KHIEUKH YU SIOS +U+D064(2);; # HANGUL SYLLABLE KHIEUKH YU SSANGSIOS +U+D065(2);; # HANGUL SYLLABLE KHIEUKH YU IEUNG +U+D066(2);; # HANGUL SYLLABLE KHIEUKH YU CIEUC +U+D067(2);; # HANGUL SYLLABLE KHIEUKH YU CHIEUCH +U+D068(2);; # HANGUL SYLLABLE KHIEUKH YU KHIEUKH +U+D069(2);; # HANGUL SYLLABLE KHIEUKH YU THIEUTH +U+D06A(2);; # HANGUL SYLLABLE KHIEUKH YU PHIEUPH +U+D06B(2);; # HANGUL SYLLABLE KHIEUKH YU HIEUH +U+D06C(2);; # HANGUL SYLLABLE KHIEUKH EU * +U+D06D(2);; # HANGUL SYLLABLE KHIEUKH EU KIYEOK * +U+D06E(2);; # HANGUL SYLLABLE KHIEUKH EU SSANGKIYEOK +U+D06F(2);; # HANGUL SYLLABLE KHIEUKH EU KIYEOKSIOS +U+D070(2);; # HANGUL SYLLABLE KHIEUKH EU NIEUN * +U+D071(2);; # HANGUL SYLLABLE KHIEUKH EU NIEUNCIEUC +U+D072(2);; # HANGUL SYLLABLE KHIEUKH EU NIEUNHIEUH +U+D073(2);; # HANGUL SYLLABLE KHIEUKH EU TIKEUT +U+D074(2);; # HANGUL SYLLABLE KHIEUKH EU RIEUL * +U+D075(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULKIYEOK +U+D076(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULMIEUM +U+D077(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULPIEUP +U+D078(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULSIOS +U+D079(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULTHIEUTH +U+D07A(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULPHIEUPH +U+D07B(2);; # HANGUL SYLLABLE KHIEUKH EU RIEULHIEUH +U+D07C(2);; # HANGUL SYLLABLE KHIEUKH EU MIEUM * +U+D07D(2);; # HANGUL SYLLABLE KHIEUKH EU PIEUP * +U+D07E(2);; # HANGUL SYLLABLE KHIEUKH EU PIEUPSIOS +U+D07F(2);; # HANGUL SYLLABLE KHIEUKH EU SIOS +U+D080(2);; # HANGUL SYLLABLE KHIEUKH EU SSANGSIOS +U+D081(2);; # HANGUL SYLLABLE KHIEUKH EU IEUNG * +U+D082(2);; # HANGUL SYLLABLE KHIEUKH EU CIEUC +U+D083(2);; # HANGUL SYLLABLE KHIEUKH EU CHIEUCH +U+D084(2);; # HANGUL SYLLABLE KHIEUKH EU KHIEUKH +U+D085(2);; # HANGUL SYLLABLE KHIEUKH EU THIEUTH +U+D086(2);; # HANGUL SYLLABLE KHIEUKH EU PHIEUPH +U+D087(2);; # HANGUL SYLLABLE KHIEUKH EU HIEUH +U+D088(2);; # HANGUL SYLLABLE KHIEUKH YI +U+D089(2);; # HANGUL SYLLABLE KHIEUKH YI KIYEOK +U+D08A(2);; # HANGUL SYLLABLE KHIEUKH YI SSANGKIYEOK +U+D08B(2);; # HANGUL SYLLABLE KHIEUKH YI KIYEOKSIOS +U+D08C(2);; # HANGUL SYLLABLE KHIEUKH YI NIEUN +U+D08D(2);; # HANGUL SYLLABLE KHIEUKH YI NIEUNCIEUC +U+D08E(2);; # HANGUL SYLLABLE KHIEUKH YI NIEUNHIEUH +U+D08F(2);; # HANGUL SYLLABLE KHIEUKH YI TIKEUT +U+D090(2);; # HANGUL SYLLABLE KHIEUKH YI RIEUL +U+D091(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULKIYEOK +U+D092(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULMIEUM +U+D093(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULPIEUP +U+D094(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULSIOS +U+D095(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULTHIEUTH +U+D096(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULPHIEUPH +U+D097(2);; # HANGUL SYLLABLE KHIEUKH YI RIEULHIEUH +U+D098(2);; # HANGUL SYLLABLE KHIEUKH YI MIEUM +U+D099(2);; # HANGUL SYLLABLE KHIEUKH YI PIEUP +U+D09A(2);; # HANGUL SYLLABLE KHIEUKH YI PIEUPSIOS +U+D09B(2);; # HANGUL SYLLABLE KHIEUKH YI SIOS +U+D09C(2);; # HANGUL SYLLABLE KHIEUKH YI SSANGSIOS +U+D09D(2);; # HANGUL SYLLABLE KHIEUKH YI IEUNG +U+D09E(2);; # HANGUL SYLLABLE KHIEUKH YI CIEUC +U+D09F(2);; # HANGUL SYLLABLE KHIEUKH YI CHIEUCH +U+D0A0(2);; # HANGUL SYLLABLE KHIEUKH YI KHIEUKH +U+D0A1(2);; # HANGUL SYLLABLE KHIEUKH YI THIEUTH +U+D0A2(2);; # HANGUL SYLLABLE KHIEUKH YI PHIEUPH +U+D0A3(2);; # HANGUL SYLLABLE KHIEUKH YI HIEUH +U+D0A4(2);; # HANGUL SYLLABLE KHIEUKH I * +U+D0A5(2);; # HANGUL SYLLABLE KHIEUKH I KIYEOK * +U+D0A6(2);; # HANGUL SYLLABLE KHIEUKH I SSANGKIYEOK +U+D0A7(2);; # HANGUL SYLLABLE KHIEUKH I KIYEOKSIOS +U+D0A8(2);; # HANGUL SYLLABLE KHIEUKH I NIEUN * +U+D0A9(2);; # HANGUL SYLLABLE KHIEUKH I NIEUNCIEUC +U+D0AA(2);; # HANGUL SYLLABLE KHIEUKH I NIEUNHIEUH +U+D0AB(2);; # HANGUL SYLLABLE KHIEUKH I TIKEUT +U+D0AC(2);; # HANGUL SYLLABLE KHIEUKH I RIEUL * +U+D0AD(2);; # HANGUL SYLLABLE KHIEUKH I RIEULKIYEOK +U+D0AE(2);; # HANGUL SYLLABLE KHIEUKH I RIEULMIEUM +U+D0AF(2);; # HANGUL SYLLABLE KHIEUKH I RIEULPIEUP +U+D0B0(2);; # HANGUL SYLLABLE KHIEUKH I RIEULSIOS +U+D0B1(2);; # HANGUL SYLLABLE KHIEUKH I RIEULTHIEUTH +U+D0B2(2);; # HANGUL SYLLABLE KHIEUKH I RIEULPHIEUPH +U+D0B3(2);; # HANGUL SYLLABLE KHIEUKH I RIEULHIEUH +U+D0B4(2);; # HANGUL SYLLABLE KHIEUKH I MIEUM * +U+D0B5(2);; # HANGUL SYLLABLE KHIEUKH I PIEUP * +U+D0B6(2);; # HANGUL SYLLABLE KHIEUKH I PIEUPSIOS +U+D0B7(2);; # HANGUL SYLLABLE KHIEUKH I SIOS * +U+D0B8(2);; # HANGUL SYLLABLE KHIEUKH I SSANGSIOS +U+D0B9(2);; # HANGUL SYLLABLE KHIEUKH I IEUNG * +U+D0BA(2);; # HANGUL SYLLABLE KHIEUKH I CIEUC +U+D0BB(2);; # HANGUL SYLLABLE KHIEUKH I CHIEUCH +U+D0BC(2);; # HANGUL SYLLABLE KHIEUKH I KHIEUKH +U+D0BD(2);; # HANGUL SYLLABLE KHIEUKH I THIEUTH +U+D0BE(2);; # HANGUL SYLLABLE KHIEUKH I PHIEUPH +U+D0BF(2);; # HANGUL SYLLABLE KHIEUKH I HIEUH +U+D0C0(2);; # HANGUL SYLLABLE THIEUTH A * +U+D0C1(2);; # HANGUL SYLLABLE THIEUTH A KIYEOK * +U+D0C2(2);; # HANGUL SYLLABLE THIEUTH A SSANGKIYEOK +U+D0C3(2);; # HANGUL SYLLABLE THIEUTH A KIYEOKSIOS +U+D0C4(2);; # HANGUL SYLLABLE THIEUTH A NIEUN * +U+D0C5(2);; # HANGUL SYLLABLE THIEUTH A NIEUNCIEUC +U+D0C6(2);; # HANGUL SYLLABLE THIEUTH A NIEUNHIEUH +U+D0C7(2);; # HANGUL SYLLABLE THIEUTH A TIKEUT +U+D0C8(2);; # HANGUL SYLLABLE THIEUTH A RIEUL * +U+D0C9(2);; # HANGUL SYLLABLE THIEUTH A RIEULKIYEOK * +U+D0CA(2);; # HANGUL SYLLABLE THIEUTH A RIEULMIEUM +U+D0CB(2);; # HANGUL SYLLABLE THIEUTH A RIEULPIEUP +U+D0CC(2);; # HANGUL SYLLABLE THIEUTH A RIEULSIOS +U+D0CD(2);; # HANGUL SYLLABLE THIEUTH A RIEULTHIEUTH +U+D0CE(2);; # HANGUL SYLLABLE THIEUTH A RIEULPHIEUPH +U+D0CF(2);; # HANGUL SYLLABLE THIEUTH A RIEULHIEUH +U+D0D0(2);; # HANGUL SYLLABLE THIEUTH A MIEUM * +U+D0D1(2);; # HANGUL SYLLABLE THIEUTH A PIEUP * +U+D0D2(2);; # HANGUL SYLLABLE THIEUTH A PIEUPSIOS +U+D0D3(2);; # HANGUL SYLLABLE THIEUTH A SIOS * +U+D0D4(2);; # HANGUL SYLLABLE THIEUTH A SSANGSIOS * +U+D0D5(2);; # HANGUL SYLLABLE THIEUTH A IEUNG * +U+D0D6(2);; # HANGUL SYLLABLE THIEUTH A CIEUC +U+D0D7(2);; # HANGUL SYLLABLE THIEUTH A CHIEUCH +U+D0D8(2);; # HANGUL SYLLABLE THIEUTH A KHIEUKH +U+D0D9(2);; # HANGUL SYLLABLE THIEUTH A THIEUTH +U+D0DA(2);; # HANGUL SYLLABLE THIEUTH A PHIEUPH +U+D0DB(2);; # HANGUL SYLLABLE THIEUTH A HIEUH +U+D0DC(2);; # HANGUL SYLLABLE THIEUTH AE * +U+D0DD(2);; # HANGUL SYLLABLE THIEUTH AE KIYEOK * +U+D0DE(2);; # HANGUL SYLLABLE THIEUTH AE SSANGKIYEOK +U+D0DF(2);; # HANGUL SYLLABLE THIEUTH AE KIYEOKSIOS +U+D0E0(2);; # HANGUL SYLLABLE THIEUTH AE NIEUN * +U+D0E1(2);; # HANGUL SYLLABLE THIEUTH AE NIEUNCIEUC +U+D0E2(2);; # HANGUL SYLLABLE THIEUTH AE NIEUNHIEUH +U+D0E3(2);; # HANGUL SYLLABLE THIEUTH AE TIKEUT +U+D0E4(2);; # HANGUL SYLLABLE THIEUTH AE RIEUL * +U+D0E5(2);; # HANGUL SYLLABLE THIEUTH AE RIEULKIYEOK +U+D0E6(2);; # HANGUL SYLLABLE THIEUTH AE RIEULMIEUM +U+D0E7(2);; # HANGUL SYLLABLE THIEUTH AE RIEULPIEUP +U+D0E8(2);; # HANGUL SYLLABLE THIEUTH AE RIEULSIOS +U+D0E9(2);; # HANGUL SYLLABLE THIEUTH AE RIEULTHIEUTH +U+D0EA(2);; # HANGUL SYLLABLE THIEUTH AE RIEULPHIEUPH +U+D0EB(2);; # HANGUL SYLLABLE THIEUTH AE RIEULHIEUH +U+D0EC(2);; # HANGUL SYLLABLE THIEUTH AE MIEUM * +U+D0ED(2);; # HANGUL SYLLABLE THIEUTH AE PIEUP * +U+D0EE(2);; # HANGUL SYLLABLE THIEUTH AE PIEUPSIOS +U+D0EF(2);; # HANGUL SYLLABLE THIEUTH AE SIOS * +U+D0F0(2);; # HANGUL SYLLABLE THIEUTH AE SSANGSIOS * +U+D0F1(2);; # HANGUL SYLLABLE THIEUTH AE IEUNG * +U+D0F2(2);; # HANGUL SYLLABLE THIEUTH AE CIEUC +U+D0F3(2);; # HANGUL SYLLABLE THIEUTH AE CHIEUCH +U+D0F4(2);; # HANGUL SYLLABLE THIEUTH AE KHIEUKH +U+D0F5(2);; # HANGUL SYLLABLE THIEUTH AE THIEUTH +U+D0F6(2);; # HANGUL SYLLABLE THIEUTH AE PHIEUPH +U+D0F7(2);; # HANGUL SYLLABLE THIEUTH AE HIEUH +U+D0F8(2);; # HANGUL SYLLABLE THIEUTH YA * +U+D0F9(2);; # HANGUL SYLLABLE THIEUTH YA KIYEOK +U+D0FA(2);; # HANGUL SYLLABLE THIEUTH YA SSANGKIYEOK +U+D0FB(2);; # HANGUL SYLLABLE THIEUTH YA KIYEOKSIOS +U+D0FC(2);; # HANGUL SYLLABLE THIEUTH YA NIEUN +U+D0FD(2);; # HANGUL SYLLABLE THIEUTH YA NIEUNCIEUC +U+D0FE(2);; # HANGUL SYLLABLE THIEUTH YA NIEUNHIEUH +U+D0FF(2);; # HANGUL SYLLABLE THIEUTH YA TIKEUT +U+D100(2);; # HANGUL SYLLABLE THIEUTH YA RIEUL +U+D101(2);; # HANGUL SYLLABLE THIEUTH YA RIEULKIYEOK +U+D102(2);; # HANGUL SYLLABLE THIEUTH YA RIEULMIEUM +U+D103(2);; # HANGUL SYLLABLE THIEUTH YA RIEULPIEUP +U+D104(2);; # HANGUL SYLLABLE THIEUTH YA RIEULSIOS +U+D105(2);; # HANGUL SYLLABLE THIEUTH YA RIEULTHIEUTH +U+D106(2);; # HANGUL SYLLABLE THIEUTH YA RIEULPHIEUPH +U+D107(2);; # HANGUL SYLLABLE THIEUTH YA RIEULHIEUH +U+D108(2);; # HANGUL SYLLABLE THIEUTH YA MIEUM +U+D109(2);; # HANGUL SYLLABLE THIEUTH YA PIEUP +U+D10A(2);; # HANGUL SYLLABLE THIEUTH YA PIEUPSIOS +U+D10B(2);; # HANGUL SYLLABLE THIEUTH YA SIOS +U+D10C(2);; # HANGUL SYLLABLE THIEUTH YA SSANGSIOS +U+D10D(2);; # HANGUL SYLLABLE THIEUTH YA IEUNG * +U+D10E(2);; # HANGUL SYLLABLE THIEUTH YA CIEUC +U+D10F(2);; # HANGUL SYLLABLE THIEUTH YA CHIEUCH +U+D110(2);; # HANGUL SYLLABLE THIEUTH YA KHIEUKH +U+D111(2);; # HANGUL SYLLABLE THIEUTH YA THIEUTH +U+D112(2);; # HANGUL SYLLABLE THIEUTH YA PHIEUPH +U+D113(2);; # HANGUL SYLLABLE THIEUTH YA HIEUH +U+D114(2);; # HANGUL SYLLABLE THIEUTH YAE +U+D115(2);; # HANGUL SYLLABLE THIEUTH YAE KIYEOK +U+D116(2);; # HANGUL SYLLABLE THIEUTH YAE SSANGKIYEOK +U+D117(2);; # HANGUL SYLLABLE THIEUTH YAE KIYEOKSIOS +U+D118(2);; # HANGUL SYLLABLE THIEUTH YAE NIEUN +U+D119(2);; # HANGUL SYLLABLE THIEUTH YAE NIEUNCIEUC +U+D11A(2);; # HANGUL SYLLABLE THIEUTH YAE NIEUNHIEUH +U+D11B(2);; # HANGUL SYLLABLE THIEUTH YAE TIKEUT +U+D11C(2);; # HANGUL SYLLABLE THIEUTH YAE RIEUL +U+D11D(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULKIYEOK +U+D11E(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULMIEUM +U+D11F(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULPIEUP +U+D120(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULSIOS +U+D121(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULTHIEUTH +U+D122(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULPHIEUPH +U+D123(2);; # HANGUL SYLLABLE THIEUTH YAE RIEULHIEUH +U+D124(2);; # HANGUL SYLLABLE THIEUTH YAE MIEUM +U+D125(2);; # HANGUL SYLLABLE THIEUTH YAE PIEUP +U+D126(2);; # HANGUL SYLLABLE THIEUTH YAE PIEUPSIOS +U+D127(2);; # HANGUL SYLLABLE THIEUTH YAE SIOS +U+D128(2);; # HANGUL SYLLABLE THIEUTH YAE SSANGSIOS +U+D129(2);; # HANGUL SYLLABLE THIEUTH YAE IEUNG +U+D12A(2);; # HANGUL SYLLABLE THIEUTH YAE CIEUC +U+D12B(2);; # HANGUL SYLLABLE THIEUTH YAE CHIEUCH +U+D12C(2);; # HANGUL SYLLABLE THIEUTH YAE KHIEUKH +U+D12D(2);; # HANGUL SYLLABLE THIEUTH YAE THIEUTH +U+D12E(2);; # HANGUL SYLLABLE THIEUTH YAE PHIEUPH +U+D12F(2);; # HANGUL SYLLABLE THIEUTH YAE HIEUH +U+D130(2);; # HANGUL SYLLABLE THIEUTH EO * +U+D131(2);; # HANGUL SYLLABLE THIEUTH EO KIYEOK * +U+D132(2);; # HANGUL SYLLABLE THIEUTH EO SSANGKIYEOK +U+D133(2);; # HANGUL SYLLABLE THIEUTH EO KIYEOKSIOS +U+D134(2);; # HANGUL SYLLABLE THIEUTH EO NIEUN * +U+D135(2);; # HANGUL SYLLABLE THIEUTH EO NIEUNCIEUC +U+D136(2);; # HANGUL SYLLABLE THIEUTH EO NIEUNHIEUH +U+D137(2);; # HANGUL SYLLABLE THIEUTH EO TIKEUT +U+D138(2);; # HANGUL SYLLABLE THIEUTH EO RIEUL * +U+D139(2);; # HANGUL SYLLABLE THIEUTH EO RIEULKIYEOK +U+D13A(2);; # HANGUL SYLLABLE THIEUTH EO RIEULMIEUM * +U+D13B(2);; # HANGUL SYLLABLE THIEUTH EO RIEULPIEUP +U+D13C(2);; # HANGUL SYLLABLE THIEUTH EO RIEULSIOS +U+D13D(2);; # HANGUL SYLLABLE THIEUTH EO RIEULTHIEUTH +U+D13E(2);; # HANGUL SYLLABLE THIEUTH EO RIEULPHIEUPH +U+D13F(2);; # HANGUL SYLLABLE THIEUTH EO RIEULHIEUH +U+D140(2);; # HANGUL SYLLABLE THIEUTH EO MIEUM * +U+D141(2);; # HANGUL SYLLABLE THIEUTH EO PIEUP * +U+D142(2);; # HANGUL SYLLABLE THIEUTH EO PIEUPSIOS +U+D143(2);; # HANGUL SYLLABLE THIEUTH EO SIOS * +U+D144(2);; # HANGUL SYLLABLE THIEUTH EO SSANGSIOS * +U+D145(2);; # HANGUL SYLLABLE THIEUTH EO IEUNG * +U+D146(2);; # HANGUL SYLLABLE THIEUTH EO CIEUC +U+D147(2);; # HANGUL SYLLABLE THIEUTH EO CHIEUCH +U+D148(2);; # HANGUL SYLLABLE THIEUTH EO KHIEUKH +U+D149(2);; # HANGUL SYLLABLE THIEUTH EO THIEUTH +U+D14A(2);; # HANGUL SYLLABLE THIEUTH EO PHIEUPH +U+D14B(2);; # HANGUL SYLLABLE THIEUTH EO HIEUH +U+D14C(2);; # HANGUL SYLLABLE THIEUTH E * +U+D14D(2);; # HANGUL SYLLABLE THIEUTH E KIYEOK * +U+D14E(2);; # HANGUL SYLLABLE THIEUTH E SSANGKIYEOK +U+D14F(2);; # HANGUL SYLLABLE THIEUTH E KIYEOKSIOS +U+D150(2);; # HANGUL SYLLABLE THIEUTH E NIEUN * +U+D151(2);; # HANGUL SYLLABLE THIEUTH E NIEUNCIEUC +U+D152(2);; # HANGUL SYLLABLE THIEUTH E NIEUNHIEUH +U+D153(2);; # HANGUL SYLLABLE THIEUTH E TIKEUT +U+D154(2);; # HANGUL SYLLABLE THIEUTH E RIEUL * +U+D155(2);; # HANGUL SYLLABLE THIEUTH E RIEULKIYEOK +U+D156(2);; # HANGUL SYLLABLE THIEUTH E RIEULMIEUM +U+D157(2);; # HANGUL SYLLABLE THIEUTH E RIEULPIEUP +U+D158(2);; # HANGUL SYLLABLE THIEUTH E RIEULSIOS +U+D159(2);; # HANGUL SYLLABLE THIEUTH E RIEULTHIEUTH +U+D15A(2);; # HANGUL SYLLABLE THIEUTH E RIEULPHIEUPH +U+D15B(2);; # HANGUL SYLLABLE THIEUTH E RIEULHIEUH +U+D15C(2);; # HANGUL SYLLABLE THIEUTH E MIEUM * +U+D15D(2);; # HANGUL SYLLABLE THIEUTH E PIEUP * +U+D15E(2);; # HANGUL SYLLABLE THIEUTH E PIEUPSIOS +U+D15F(2);; # HANGUL SYLLABLE THIEUTH E SIOS * +U+D160(2);; # HANGUL SYLLABLE THIEUTH E SSANGSIOS +U+D161(2);; # HANGUL SYLLABLE THIEUTH E IEUNG * +U+D162(2);; # HANGUL SYLLABLE THIEUTH E CIEUC +U+D163(2);; # HANGUL SYLLABLE THIEUTH E CHIEUCH +U+D164(2);; # HANGUL SYLLABLE THIEUTH E KHIEUKH +U+D165(2);; # HANGUL SYLLABLE THIEUTH E THIEUTH +U+D166(2);; # HANGUL SYLLABLE THIEUTH E PHIEUPH +U+D167(2);; # HANGUL SYLLABLE THIEUTH E HIEUH +U+D168(2);; # HANGUL SYLLABLE THIEUTH YEO * +U+D169(2);; # HANGUL SYLLABLE THIEUTH YEO KIYEOK +U+D16A(2);; # HANGUL SYLLABLE THIEUTH YEO SSANGKIYEOK +U+D16B(2);; # HANGUL SYLLABLE THIEUTH YEO KIYEOKSIOS +U+D16C(2);; # HANGUL SYLLABLE THIEUTH YEO NIEUN * +U+D16D(2);; # HANGUL SYLLABLE THIEUTH YEO NIEUNCIEUC +U+D16E(2);; # HANGUL SYLLABLE THIEUTH YEO NIEUNHIEUH +U+D16F(2);; # HANGUL SYLLABLE THIEUTH YEO TIKEUT +U+D170(2);; # HANGUL SYLLABLE THIEUTH YEO RIEUL +U+D171(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULKIYEOK +U+D172(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULMIEUM +U+D173(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULPIEUP +U+D174(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULSIOS +U+D175(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULTHIEUTH +U+D176(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULPHIEUPH +U+D177(2);; # HANGUL SYLLABLE THIEUTH YEO RIEULHIEUH +U+D178(2);; # HANGUL SYLLABLE THIEUTH YEO MIEUM +U+D179(2);; # HANGUL SYLLABLE THIEUTH YEO PIEUP +U+D17A(2);; # HANGUL SYLLABLE THIEUTH YEO PIEUPSIOS +U+D17B(2);; # HANGUL SYLLABLE THIEUTH YEO SIOS +U+D17C(2);; # HANGUL SYLLABLE THIEUTH YEO SSANGSIOS * +U+D17D(2);; # HANGUL SYLLABLE THIEUTH YEO IEUNG +U+D17E(2);; # HANGUL SYLLABLE THIEUTH YEO CIEUC +U+D17F(2);; # HANGUL SYLLABLE THIEUTH YEO CHIEUCH +U+D180(2);; # HANGUL SYLLABLE THIEUTH YEO KHIEUKH +U+D181(2);; # HANGUL SYLLABLE THIEUTH YEO THIEUTH +U+D182(2);; # HANGUL SYLLABLE THIEUTH YEO PHIEUPH +U+D183(2);; # HANGUL SYLLABLE THIEUTH YEO HIEUH +U+D184(2);; # HANGUL SYLLABLE THIEUTH YE * +U+D185(2);; # HANGUL SYLLABLE THIEUTH YE KIYEOK +U+D186(2);; # HANGUL SYLLABLE THIEUTH YE SSANGKIYEOK +U+D187(2);; # HANGUL SYLLABLE THIEUTH YE KIYEOKSIOS +U+D188(2);; # HANGUL SYLLABLE THIEUTH YE NIEUN * +U+D189(2);; # HANGUL SYLLABLE THIEUTH YE NIEUNCIEUC +U+D18A(2);; # HANGUL SYLLABLE THIEUTH YE NIEUNHIEUH +U+D18B(2);; # HANGUL SYLLABLE THIEUTH YE TIKEUT +U+D18C(2);; # HANGUL SYLLABLE THIEUTH YE RIEUL +U+D18D(2);; # HANGUL SYLLABLE THIEUTH YE RIEULKIYEOK +U+D18E(2);; # HANGUL SYLLABLE THIEUTH YE RIEULMIEUM +U+D18F(2);; # HANGUL SYLLABLE THIEUTH YE RIEULPIEUP +U+D190(2);; # HANGUL SYLLABLE THIEUTH YE RIEULSIOS +U+D191(2);; # HANGUL SYLLABLE THIEUTH YE RIEULTHIEUTH +U+D192(2);; # HANGUL SYLLABLE THIEUTH YE RIEULPHIEUPH +U+D193(2);; # HANGUL SYLLABLE THIEUTH YE RIEULHIEUH +U+D194(2);; # HANGUL SYLLABLE THIEUTH YE MIEUM +U+D195(2);; # HANGUL SYLLABLE THIEUTH YE PIEUP +U+D196(2);; # HANGUL SYLLABLE THIEUTH YE PIEUPSIOS +U+D197(2);; # HANGUL SYLLABLE THIEUTH YE SIOS +U+D198(2);; # HANGUL SYLLABLE THIEUTH YE SSANGSIOS +U+D199(2);; # HANGUL SYLLABLE THIEUTH YE IEUNG +U+D19A(2);; # HANGUL SYLLABLE THIEUTH YE CIEUC +U+D19B(2);; # HANGUL SYLLABLE THIEUTH YE CHIEUCH +U+D19C(2);; # HANGUL SYLLABLE THIEUTH YE KHIEUKH +U+D19D(2);; # HANGUL SYLLABLE THIEUTH YE THIEUTH +U+D19E(2);; # HANGUL SYLLABLE THIEUTH YE PHIEUPH +U+D19F(2);; # HANGUL SYLLABLE THIEUTH YE HIEUH +U+D1A0(2);; # HANGUL SYLLABLE THIEUTH O * +U+D1A1(2);; # HANGUL SYLLABLE THIEUTH O KIYEOK * +U+D1A2(2);; # HANGUL SYLLABLE THIEUTH O SSANGKIYEOK +U+D1A3(2);; # HANGUL SYLLABLE THIEUTH O KIYEOKSIOS +U+D1A4(2);; # HANGUL SYLLABLE THIEUTH O NIEUN * +U+D1A5(2);; # HANGUL SYLLABLE THIEUTH O NIEUNCIEUC +U+D1A6(2);; # HANGUL SYLLABLE THIEUTH O NIEUNHIEUH +U+D1A7(2);; # HANGUL SYLLABLE THIEUTH O TIKEUT +U+D1A8(2);; # HANGUL SYLLABLE THIEUTH O RIEUL * +U+D1A9(2);; # HANGUL SYLLABLE THIEUTH O RIEULKIYEOK +U+D1AA(2);; # HANGUL SYLLABLE THIEUTH O RIEULMIEUM +U+D1AB(2);; # HANGUL SYLLABLE THIEUTH O RIEULPIEUP +U+D1AC(2);; # HANGUL SYLLABLE THIEUTH O RIEULSIOS +U+D1AD(2);; # HANGUL SYLLABLE THIEUTH O RIEULTHIEUTH +U+D1AE(2);; # HANGUL SYLLABLE THIEUTH O RIEULPHIEUPH +U+D1AF(2);; # HANGUL SYLLABLE THIEUTH O RIEULHIEUH +U+D1B0(2);; # HANGUL SYLLABLE THIEUTH O MIEUM * +U+D1B1(2);; # HANGUL SYLLABLE THIEUTH O PIEUP * +U+D1B2(2);; # HANGUL SYLLABLE THIEUTH O PIEUPSIOS +U+D1B3(2);; # HANGUL SYLLABLE THIEUTH O SIOS * +U+D1B4(2);; # HANGUL SYLLABLE THIEUTH O SSANGSIOS +U+D1B5(2);; # HANGUL SYLLABLE THIEUTH O IEUNG * +U+D1B6(2);; # HANGUL SYLLABLE THIEUTH O CIEUC +U+D1B7(2);; # HANGUL SYLLABLE THIEUTH O CHIEUCH +U+D1B8(2);; # HANGUL SYLLABLE THIEUTH O KHIEUKH +U+D1B9(2);; # HANGUL SYLLABLE THIEUTH O THIEUTH +U+D1BA(2);; # HANGUL SYLLABLE THIEUTH O PHIEUPH * +U+D1BB(2);; # HANGUL SYLLABLE THIEUTH O HIEUH +U+D1BC(2);; # HANGUL SYLLABLE THIEUTH WA * +U+D1BD(2);; # HANGUL SYLLABLE THIEUTH WA KIYEOK +U+D1BE(2);; # HANGUL SYLLABLE THIEUTH WA SSANGKIYEOK +U+D1BF(2);; # HANGUL SYLLABLE THIEUTH WA KIYEOKSIOS +U+D1C0(2);; # HANGUL SYLLABLE THIEUTH WA NIEUN * +U+D1C1(2);; # HANGUL SYLLABLE THIEUTH WA NIEUNCIEUC +U+D1C2(2);; # HANGUL SYLLABLE THIEUTH WA NIEUNHIEUH +U+D1C3(2);; # HANGUL SYLLABLE THIEUTH WA TIKEUT +U+D1C4(2);; # HANGUL SYLLABLE THIEUTH WA RIEUL +U+D1C5(2);; # HANGUL SYLLABLE THIEUTH WA RIEULKIYEOK +U+D1C6(2);; # HANGUL SYLLABLE THIEUTH WA RIEULMIEUM +U+D1C7(2);; # HANGUL SYLLABLE THIEUTH WA RIEULPIEUP +U+D1C8(2);; # HANGUL SYLLABLE THIEUTH WA RIEULSIOS +U+D1C9(2);; # HANGUL SYLLABLE THIEUTH WA RIEULTHIEUTH +U+D1CA(2);; # HANGUL SYLLABLE THIEUTH WA RIEULPHIEUPH +U+D1CB(2);; # HANGUL SYLLABLE THIEUTH WA RIEULHIEUH +U+D1CC(2);; # HANGUL SYLLABLE THIEUTH WA MIEUM +U+D1CD(2);; # HANGUL SYLLABLE THIEUTH WA PIEUP +U+D1CE(2);; # HANGUL SYLLABLE THIEUTH WA PIEUPSIOS +U+D1CF(2);; # HANGUL SYLLABLE THIEUTH WA SIOS +U+D1D0(2);; # HANGUL SYLLABLE THIEUTH WA SSANGSIOS +U+D1D1(2);; # HANGUL SYLLABLE THIEUTH WA IEUNG +U+D1D2(2);; # HANGUL SYLLABLE THIEUTH WA CIEUC +U+D1D3(2);; # HANGUL SYLLABLE THIEUTH WA CHIEUCH +U+D1D4(2);; # HANGUL SYLLABLE THIEUTH WA KHIEUKH +U+D1D5(2);; # HANGUL SYLLABLE THIEUTH WA THIEUTH +U+D1D6(2);; # HANGUL SYLLABLE THIEUTH WA PHIEUPH +U+D1D7(2);; # HANGUL SYLLABLE THIEUTH WA HIEUH +U+D1D8(2);; # HANGUL SYLLABLE THIEUTH WAE * +U+D1D9(2);; # HANGUL SYLLABLE THIEUTH WAE KIYEOK +U+D1DA(2);; # HANGUL SYLLABLE THIEUTH WAE SSANGKIYEOK +U+D1DB(2);; # HANGUL SYLLABLE THIEUTH WAE KIYEOKSIOS +U+D1DC(2);; # HANGUL SYLLABLE THIEUTH WAE NIEUN +U+D1DD(2);; # HANGUL SYLLABLE THIEUTH WAE NIEUNCIEUC +U+D1DE(2);; # HANGUL SYLLABLE THIEUTH WAE NIEUNHIEUH +U+D1DF(2);; # HANGUL SYLLABLE THIEUTH WAE TIKEUT +U+D1E0(2);; # HANGUL SYLLABLE THIEUTH WAE RIEUL +U+D1E1(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULKIYEOK +U+D1E2(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULMIEUM +U+D1E3(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULPIEUP +U+D1E4(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULSIOS +U+D1E5(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULTHIEUTH +U+D1E6(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULPHIEUPH +U+D1E7(2);; # HANGUL SYLLABLE THIEUTH WAE RIEULHIEUH +U+D1E8(2);; # HANGUL SYLLABLE THIEUTH WAE MIEUM +U+D1E9(2);; # HANGUL SYLLABLE THIEUTH WAE PIEUP +U+D1EA(2);; # HANGUL SYLLABLE THIEUTH WAE PIEUPSIOS +U+D1EB(2);; # HANGUL SYLLABLE THIEUTH WAE SIOS +U+D1EC(2);; # HANGUL SYLLABLE THIEUTH WAE SSANGSIOS +U+D1ED(2);; # HANGUL SYLLABLE THIEUTH WAE IEUNG +U+D1EE(2);; # HANGUL SYLLABLE THIEUTH WAE CIEUC +U+D1EF(2);; # HANGUL SYLLABLE THIEUTH WAE CHIEUCH +U+D1F0(2);; # HANGUL SYLLABLE THIEUTH WAE KHIEUKH +U+D1F1(2);; # HANGUL SYLLABLE THIEUTH WAE THIEUTH +U+D1F2(2);; # HANGUL SYLLABLE THIEUTH WAE PHIEUPH +U+D1F3(2);; # HANGUL SYLLABLE THIEUTH WAE HIEUH +U+D1F4(2);; # HANGUL SYLLABLE THIEUTH OE * +U+D1F5(2);; # HANGUL SYLLABLE THIEUTH OE KIYEOK +U+D1F6(2);; # HANGUL SYLLABLE THIEUTH OE SSANGKIYEOK +U+D1F7(2);; # HANGUL SYLLABLE THIEUTH OE KIYEOKSIOS +U+D1F8(2);; # HANGUL SYLLABLE THIEUTH OE NIEUN * +U+D1F9(2);; # HANGUL SYLLABLE THIEUTH OE NIEUNCIEUC +U+D1FA(2);; # HANGUL SYLLABLE THIEUTH OE NIEUNHIEUH +U+D1FB(2);; # HANGUL SYLLABLE THIEUTH OE TIKEUT +U+D1FC(2);; # HANGUL SYLLABLE THIEUTH OE RIEUL +U+D1FD(2);; # HANGUL SYLLABLE THIEUTH OE RIEULKIYEOK +U+D1FE(2);; # HANGUL SYLLABLE THIEUTH OE RIEULMIEUM +U+D1FF(2);; # HANGUL SYLLABLE THIEUTH OE RIEULPIEUP +U+D200(2);; # HANGUL SYLLABLE THIEUTH OE RIEULSIOS +U+D201(2);; # HANGUL SYLLABLE THIEUTH OE RIEULTHIEUTH +U+D202(2);; # HANGUL SYLLABLE THIEUTH OE RIEULPHIEUPH +U+D203(2);; # HANGUL SYLLABLE THIEUTH OE RIEULHIEUH +U+D204(2);; # HANGUL SYLLABLE THIEUTH OE MIEUM +U+D205(2);; # HANGUL SYLLABLE THIEUTH OE PIEUP +U+D206(2);; # HANGUL SYLLABLE THIEUTH OE PIEUPSIOS +U+D207(2);; # HANGUL SYLLABLE THIEUTH OE SIOS * +U+D208(2);; # HANGUL SYLLABLE THIEUTH OE SSANGSIOS +U+D209(2);; # HANGUL SYLLABLE THIEUTH OE IEUNG * +U+D20A(2);; # HANGUL SYLLABLE THIEUTH OE CIEUC +U+D20B(2);; # HANGUL SYLLABLE THIEUTH OE CHIEUCH +U+D20C(2);; # HANGUL SYLLABLE THIEUTH OE KHIEUKH +U+D20D(2);; # HANGUL SYLLABLE THIEUTH OE THIEUTH +U+D20E(2);; # HANGUL SYLLABLE THIEUTH OE PHIEUPH +U+D20F(2);; # HANGUL SYLLABLE THIEUTH OE HIEUH +U+D210(2);; # HANGUL SYLLABLE THIEUTH YO * +U+D211(2);; # HANGUL SYLLABLE THIEUTH YO KIYEOK +U+D212(2);; # HANGUL SYLLABLE THIEUTH YO SSANGKIYEOK +U+D213(2);; # HANGUL SYLLABLE THIEUTH YO KIYEOKSIOS +U+D214(2);; # HANGUL SYLLABLE THIEUTH YO NIEUN +U+D215(2);; # HANGUL SYLLABLE THIEUTH YO NIEUNCIEUC +U+D216(2);; # HANGUL SYLLABLE THIEUTH YO NIEUNHIEUH +U+D217(2);; # HANGUL SYLLABLE THIEUTH YO TIKEUT +U+D218(2);; # HANGUL SYLLABLE THIEUTH YO RIEUL +U+D219(2);; # HANGUL SYLLABLE THIEUTH YO RIEULKIYEOK +U+D21A(2);; # HANGUL SYLLABLE THIEUTH YO RIEULMIEUM +U+D21B(2);; # HANGUL SYLLABLE THIEUTH YO RIEULPIEUP +U+D21C(2);; # HANGUL SYLLABLE THIEUTH YO RIEULSIOS +U+D21D(2);; # HANGUL SYLLABLE THIEUTH YO RIEULTHIEUTH +U+D21E(2);; # HANGUL SYLLABLE THIEUTH YO RIEULPHIEUPH +U+D21F(2);; # HANGUL SYLLABLE THIEUTH YO RIEULHIEUH +U+D220(2);; # HANGUL SYLLABLE THIEUTH YO MIEUM +U+D221(2);; # HANGUL SYLLABLE THIEUTH YO PIEUP +U+D222(2);; # HANGUL SYLLABLE THIEUTH YO PIEUPSIOS +U+D223(2);; # HANGUL SYLLABLE THIEUTH YO SIOS +U+D224(2);; # HANGUL SYLLABLE THIEUTH YO SSANGSIOS +U+D225(2);; # HANGUL SYLLABLE THIEUTH YO IEUNG +U+D226(2);; # HANGUL SYLLABLE THIEUTH YO CIEUC +U+D227(2);; # HANGUL SYLLABLE THIEUTH YO CHIEUCH +U+D228(2);; # HANGUL SYLLABLE THIEUTH YO KHIEUKH +U+D229(2);; # HANGUL SYLLABLE THIEUTH YO THIEUTH +U+D22A(2);; # HANGUL SYLLABLE THIEUTH YO PHIEUPH +U+D22B(2);; # HANGUL SYLLABLE THIEUTH YO HIEUH +U+D22C(2);; # HANGUL SYLLABLE THIEUTH U * +U+D22D(2);; # HANGUL SYLLABLE THIEUTH U KIYEOK * +U+D22E(2);; # HANGUL SYLLABLE THIEUTH U SSANGKIYEOK +U+D22F(2);; # HANGUL SYLLABLE THIEUTH U KIYEOKSIOS +U+D230(2);; # HANGUL SYLLABLE THIEUTH U NIEUN * +U+D231(2);; # HANGUL SYLLABLE THIEUTH U NIEUNCIEUC +U+D232(2);; # HANGUL SYLLABLE THIEUTH U NIEUNHIEUH +U+D233(2);; # HANGUL SYLLABLE THIEUTH U TIKEUT +U+D234(2);; # HANGUL SYLLABLE THIEUTH U RIEUL * +U+D235(2);; # HANGUL SYLLABLE THIEUTH U RIEULKIYEOK +U+D236(2);; # HANGUL SYLLABLE THIEUTH U RIEULMIEUM +U+D237(2);; # HANGUL SYLLABLE THIEUTH U RIEULPIEUP +U+D238(2);; # HANGUL SYLLABLE THIEUTH U RIEULSIOS +U+D239(2);; # HANGUL SYLLABLE THIEUTH U RIEULTHIEUTH +U+D23A(2);; # HANGUL SYLLABLE THIEUTH U RIEULPHIEUPH +U+D23B(2);; # HANGUL SYLLABLE THIEUTH U RIEULHIEUH +U+D23C(2);; # HANGUL SYLLABLE THIEUTH U MIEUM * +U+D23D(2);; # HANGUL SYLLABLE THIEUTH U PIEUP * +U+D23E(2);; # HANGUL SYLLABLE THIEUTH U PIEUPSIOS +U+D23F(2);; # HANGUL SYLLABLE THIEUTH U SIOS * +U+D240(2);; # HANGUL SYLLABLE THIEUTH U SSANGSIOS +U+D241(2);; # HANGUL SYLLABLE THIEUTH U IEUNG * +U+D242(2);; # HANGUL SYLLABLE THIEUTH U CIEUC +U+D243(2);; # HANGUL SYLLABLE THIEUTH U CHIEUCH +U+D244(2);; # HANGUL SYLLABLE THIEUTH U KHIEUKH +U+D245(2);; # HANGUL SYLLABLE THIEUTH U THIEUTH +U+D246(2);; # HANGUL SYLLABLE THIEUTH U PHIEUPH +U+D247(2);; # HANGUL SYLLABLE THIEUTH U HIEUH +U+D248(2);; # HANGUL SYLLABLE THIEUTH WEO * +U+D249(2);; # HANGUL SYLLABLE THIEUTH WEO KIYEOK +U+D24A(2);; # HANGUL SYLLABLE THIEUTH WEO SSANGKIYEOK +U+D24B(2);; # HANGUL SYLLABLE THIEUTH WEO KIYEOKSIOS +U+D24C(2);; # HANGUL SYLLABLE THIEUTH WEO NIEUN +U+D24D(2);; # HANGUL SYLLABLE THIEUTH WEO NIEUNCIEUC +U+D24E(2);; # HANGUL SYLLABLE THIEUTH WEO NIEUNHIEUH +U+D24F(2);; # HANGUL SYLLABLE THIEUTH WEO TIKEUT +U+D250(2);; # HANGUL SYLLABLE THIEUTH WEO RIEUL +U+D251(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULKIYEOK +U+D252(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULMIEUM +U+D253(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULPIEUP +U+D254(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULSIOS +U+D255(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULTHIEUTH +U+D256(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULPHIEUPH +U+D257(2);; # HANGUL SYLLABLE THIEUTH WEO RIEULHIEUH +U+D258(2);; # HANGUL SYLLABLE THIEUTH WEO MIEUM +U+D259(2);; # HANGUL SYLLABLE THIEUTH WEO PIEUP +U+D25A(2);; # HANGUL SYLLABLE THIEUTH WEO PIEUPSIOS +U+D25B(2);; # HANGUL SYLLABLE THIEUTH WEO SIOS +U+D25C(2);; # HANGUL SYLLABLE THIEUTH WEO SSANGSIOS * +U+D25D(2);; # HANGUL SYLLABLE THIEUTH WEO IEUNG +U+D25E(2);; # HANGUL SYLLABLE THIEUTH WEO CIEUC +U+D25F(2);; # HANGUL SYLLABLE THIEUTH WEO CHIEUCH +U+D260(2);; # HANGUL SYLLABLE THIEUTH WEO KHIEUKH +U+D261(2);; # HANGUL SYLLABLE THIEUTH WEO THIEUTH +U+D262(2);; # HANGUL SYLLABLE THIEUTH WEO PHIEUPH +U+D263(2);; # HANGUL SYLLABLE THIEUTH WEO HIEUH +U+D264(2);; # HANGUL SYLLABLE THIEUTH WE * +U+D265(2);; # HANGUL SYLLABLE THIEUTH WE KIYEOK +U+D266(2);; # HANGUL SYLLABLE THIEUTH WE SSANGKIYEOK +U+D267(2);; # HANGUL SYLLABLE THIEUTH WE KIYEOKSIOS +U+D268(2);; # HANGUL SYLLABLE THIEUTH WE NIEUN +U+D269(2);; # HANGUL SYLLABLE THIEUTH WE NIEUNCIEUC +U+D26A(2);; # HANGUL SYLLABLE THIEUTH WE NIEUNHIEUH +U+D26B(2);; # HANGUL SYLLABLE THIEUTH WE TIKEUT +U+D26C(2);; # HANGUL SYLLABLE THIEUTH WE RIEUL +U+D26D(2);; # HANGUL SYLLABLE THIEUTH WE RIEULKIYEOK +U+D26E(2);; # HANGUL SYLLABLE THIEUTH WE RIEULMIEUM +U+D26F(2);; # HANGUL SYLLABLE THIEUTH WE RIEULPIEUP +U+D270(2);; # HANGUL SYLLABLE THIEUTH WE RIEULSIOS +U+D271(2);; # HANGUL SYLLABLE THIEUTH WE RIEULTHIEUTH +U+D272(2);; # HANGUL SYLLABLE THIEUTH WE RIEULPHIEUPH +U+D273(2);; # HANGUL SYLLABLE THIEUTH WE RIEULHIEUH +U+D274(2);; # HANGUL SYLLABLE THIEUTH WE MIEUM +U+D275(2);; # HANGUL SYLLABLE THIEUTH WE PIEUP +U+D276(2);; # HANGUL SYLLABLE THIEUTH WE PIEUPSIOS +U+D277(2);; # HANGUL SYLLABLE THIEUTH WE SIOS +U+D278(2);; # HANGUL SYLLABLE THIEUTH WE SSANGSIOS +U+D279(2);; # HANGUL SYLLABLE THIEUTH WE IEUNG +U+D27A(2);; # HANGUL SYLLABLE THIEUTH WE CIEUC +U+D27B(2);; # HANGUL SYLLABLE THIEUTH WE CHIEUCH +U+D27C(2);; # HANGUL SYLLABLE THIEUTH WE KHIEUKH +U+D27D(2);; # HANGUL SYLLABLE THIEUTH WE THIEUTH +U+D27E(2);; # HANGUL SYLLABLE THIEUTH WE PHIEUPH +U+D27F(2);; # HANGUL SYLLABLE THIEUTH WE HIEUH +U+D280(2);; # HANGUL SYLLABLE THIEUTH WI * +U+D281(2);; # HANGUL SYLLABLE THIEUTH WI KIYEOK * +U+D282(2);; # HANGUL SYLLABLE THIEUTH WI SSANGKIYEOK +U+D283(2);; # HANGUL SYLLABLE THIEUTH WI KIYEOKSIOS +U+D284(2);; # HANGUL SYLLABLE THIEUTH WI NIEUN * +U+D285(2);; # HANGUL SYLLABLE THIEUTH WI NIEUNCIEUC +U+D286(2);; # HANGUL SYLLABLE THIEUTH WI NIEUNHIEUH +U+D287(2);; # HANGUL SYLLABLE THIEUTH WI TIKEUT +U+D288(2);; # HANGUL SYLLABLE THIEUTH WI RIEUL * +U+D289(2);; # HANGUL SYLLABLE THIEUTH WI RIEULKIYEOK +U+D28A(2);; # HANGUL SYLLABLE THIEUTH WI RIEULMIEUM +U+D28B(2);; # HANGUL SYLLABLE THIEUTH WI RIEULPIEUP +U+D28C(2);; # HANGUL SYLLABLE THIEUTH WI RIEULSIOS +U+D28D(2);; # HANGUL SYLLABLE THIEUTH WI RIEULTHIEUTH +U+D28E(2);; # HANGUL SYLLABLE THIEUTH WI RIEULPHIEUPH +U+D28F(2);; # HANGUL SYLLABLE THIEUTH WI RIEULHIEUH +U+D290(2);; # HANGUL SYLLABLE THIEUTH WI MIEUM * +U+D291(2);; # HANGUL SYLLABLE THIEUTH WI PIEUP * +U+D292(2);; # HANGUL SYLLABLE THIEUTH WI PIEUPSIOS +U+D293(2);; # HANGUL SYLLABLE THIEUTH WI SIOS +U+D294(2);; # HANGUL SYLLABLE THIEUTH WI SSANGSIOS +U+D295(2);; # HANGUL SYLLABLE THIEUTH WI IEUNG * +U+D296(2);; # HANGUL SYLLABLE THIEUTH WI CIEUC +U+D297(2);; # HANGUL SYLLABLE THIEUTH WI CHIEUCH +U+D298(2);; # HANGUL SYLLABLE THIEUTH WI KHIEUKH +U+D299(2);; # HANGUL SYLLABLE THIEUTH WI THIEUTH +U+D29A(2);; # HANGUL SYLLABLE THIEUTH WI PHIEUPH +U+D29B(2);; # HANGUL SYLLABLE THIEUTH WI HIEUH +U+D29C(2);; # HANGUL SYLLABLE THIEUTH YU * +U+D29D(2);; # HANGUL SYLLABLE THIEUTH YU KIYEOK +U+D29E(2);; # HANGUL SYLLABLE THIEUTH YU SSANGKIYEOK +U+D29F(2);; # HANGUL SYLLABLE THIEUTH YU KIYEOKSIOS +U+D2A0(2);; # HANGUL SYLLABLE THIEUTH YU NIEUN * +U+D2A1(2);; # HANGUL SYLLABLE THIEUTH YU NIEUNCIEUC +U+D2A2(2);; # HANGUL SYLLABLE THIEUTH YU NIEUNHIEUH +U+D2A3(2);; # HANGUL SYLLABLE THIEUTH YU TIKEUT +U+D2A4(2);; # HANGUL SYLLABLE THIEUTH YU RIEUL * +U+D2A5(2);; # HANGUL SYLLABLE THIEUTH YU RIEULKIYEOK +U+D2A6(2);; # HANGUL SYLLABLE THIEUTH YU RIEULMIEUM +U+D2A7(2);; # HANGUL SYLLABLE THIEUTH YU RIEULPIEUP +U+D2A8(2);; # HANGUL SYLLABLE THIEUTH YU RIEULSIOS +U+D2A9(2);; # HANGUL SYLLABLE THIEUTH YU RIEULTHIEUTH +U+D2AA(2);; # HANGUL SYLLABLE THIEUTH YU RIEULPHIEUPH +U+D2AB(2);; # HANGUL SYLLABLE THIEUTH YU RIEULHIEUH +U+D2AC(2);; # HANGUL SYLLABLE THIEUTH YU MIEUM * +U+D2AD(2);; # HANGUL SYLLABLE THIEUTH YU PIEUP +U+D2AE(2);; # HANGUL SYLLABLE THIEUTH YU PIEUPSIOS +U+D2AF(2);; # HANGUL SYLLABLE THIEUTH YU SIOS +U+D2B0(2);; # HANGUL SYLLABLE THIEUTH YU SSANGSIOS +U+D2B1(2);; # HANGUL SYLLABLE THIEUTH YU IEUNG * +U+D2B2(2);; # HANGUL SYLLABLE THIEUTH YU CIEUC +U+D2B3(2);; # HANGUL SYLLABLE THIEUTH YU CHIEUCH +U+D2B4(2);; # HANGUL SYLLABLE THIEUTH YU KHIEUKH +U+D2B5(2);; # HANGUL SYLLABLE THIEUTH YU THIEUTH +U+D2B6(2);; # HANGUL SYLLABLE THIEUTH YU PHIEUPH +U+D2B7(2);; # HANGUL SYLLABLE THIEUTH YU HIEUH +U+D2B8(2);; # HANGUL SYLLABLE THIEUTH EU * +U+D2B9(2);; # HANGUL SYLLABLE THIEUTH EU KIYEOK * +U+D2BA(2);; # HANGUL SYLLABLE THIEUTH EU SSANGKIYEOK +U+D2BB(2);; # HANGUL SYLLABLE THIEUTH EU KIYEOKSIOS +U+D2BC(2);; # HANGUL SYLLABLE THIEUTH EU NIEUN * +U+D2BD(2);; # HANGUL SYLLABLE THIEUTH EU NIEUNCIEUC +U+D2BE(2);; # HANGUL SYLLABLE THIEUTH EU NIEUNHIEUH +U+D2BF(2);; # HANGUL SYLLABLE THIEUTH EU TIKEUT * +U+D2C0(2);; # HANGUL SYLLABLE THIEUTH EU RIEUL * +U+D2C1(2);; # HANGUL SYLLABLE THIEUTH EU RIEULKIYEOK +U+D2C2(2);; # HANGUL SYLLABLE THIEUTH EU RIEULMIEUM * +U+D2C3(2);; # HANGUL SYLLABLE THIEUTH EU RIEULPIEUP +U+D2C4(2);; # HANGUL SYLLABLE THIEUTH EU RIEULSIOS +U+D2C5(2);; # HANGUL SYLLABLE THIEUTH EU RIEULTHIEUTH +U+D2C6(2);; # HANGUL SYLLABLE THIEUTH EU RIEULPHIEUPH +U+D2C7(2);; # HANGUL SYLLABLE THIEUTH EU RIEULHIEUH +U+D2C8(2);; # HANGUL SYLLABLE THIEUTH EU MIEUM * +U+D2C9(2);; # HANGUL SYLLABLE THIEUTH EU PIEUP * +U+D2CA(2);; # HANGUL SYLLABLE THIEUTH EU PIEUPSIOS +U+D2CB(2);; # HANGUL SYLLABLE THIEUTH EU SIOS * +U+D2CC(2);; # HANGUL SYLLABLE THIEUTH EU SSANGSIOS +U+D2CD(2);; # HANGUL SYLLABLE THIEUTH EU IEUNG +U+D2CE(2);; # HANGUL SYLLABLE THIEUTH EU CIEUC +U+D2CF(2);; # HANGUL SYLLABLE THIEUTH EU CHIEUCH +U+D2D0(2);; # HANGUL SYLLABLE THIEUTH EU KHIEUKH +U+D2D1(2);; # HANGUL SYLLABLE THIEUTH EU THIEUTH +U+D2D2(2);; # HANGUL SYLLABLE THIEUTH EU PHIEUPH +U+D2D3(2);; # HANGUL SYLLABLE THIEUTH EU HIEUH +U+D2D4(2);; # HANGUL SYLLABLE THIEUTH YI * +U+D2D5(2);; # HANGUL SYLLABLE THIEUTH YI KIYEOK +U+D2D6(2);; # HANGUL SYLLABLE THIEUTH YI SSANGKIYEOK +U+D2D7(2);; # HANGUL SYLLABLE THIEUTH YI KIYEOKSIOS +U+D2D8(2);; # HANGUL SYLLABLE THIEUTH YI NIEUN * +U+D2D9(2);; # HANGUL SYLLABLE THIEUTH YI NIEUNCIEUC +U+D2DA(2);; # HANGUL SYLLABLE THIEUTH YI NIEUNHIEUH +U+D2DB(2);; # HANGUL SYLLABLE THIEUTH YI TIKEUT +U+D2DC(2);; # HANGUL SYLLABLE THIEUTH YI RIEUL * +U+D2DD(2);; # HANGUL SYLLABLE THIEUTH YI RIEULKIYEOK +U+D2DE(2);; # HANGUL SYLLABLE THIEUTH YI RIEULMIEUM +U+D2DF(2);; # HANGUL SYLLABLE THIEUTH YI RIEULPIEUP +U+D2E0(2);; # HANGUL SYLLABLE THIEUTH YI RIEULSIOS +U+D2E1(2);; # HANGUL SYLLABLE THIEUTH YI RIEULTHIEUTH +U+D2E2(2);; # HANGUL SYLLABLE THIEUTH YI RIEULPHIEUPH +U+D2E3(2);; # HANGUL SYLLABLE THIEUTH YI RIEULHIEUH +U+D2E4(2);; # HANGUL SYLLABLE THIEUTH YI MIEUM * +U+D2E5(2);; # HANGUL SYLLABLE THIEUTH YI PIEUP * +U+D2E6(2);; # HANGUL SYLLABLE THIEUTH YI PIEUPSIOS +U+D2E7(2);; # HANGUL SYLLABLE THIEUTH YI SIOS +U+D2E8(2);; # HANGUL SYLLABLE THIEUTH YI SSANGSIOS +U+D2E9(2);; # HANGUL SYLLABLE THIEUTH YI IEUNG +U+D2EA(2);; # HANGUL SYLLABLE THIEUTH YI CIEUC +U+D2EB(2);; # HANGUL SYLLABLE THIEUTH YI CHIEUCH +U+D2EC(2);; # HANGUL SYLLABLE THIEUTH YI KHIEUKH +U+D2ED(2);; # HANGUL SYLLABLE THIEUTH YI THIEUTH +U+D2EE(2);; # HANGUL SYLLABLE THIEUTH YI PHIEUPH +U+D2EF(2);; # HANGUL SYLLABLE THIEUTH YI HIEUH +U+D2F0(2);; # HANGUL SYLLABLE THIEUTH I * +U+D2F1(2);; # HANGUL SYLLABLE THIEUTH I KIYEOK * +U+D2F2(2);; # HANGUL SYLLABLE THIEUTH I SSANGKIYEOK +U+D2F3(2);; # HANGUL SYLLABLE THIEUTH I KIYEOKSIOS +U+D2F4(2);; # HANGUL SYLLABLE THIEUTH I NIEUN * +U+D2F5(2);; # HANGUL SYLLABLE THIEUTH I NIEUNCIEUC +U+D2F6(2);; # HANGUL SYLLABLE THIEUTH I NIEUNHIEUH +U+D2F7(2);; # HANGUL SYLLABLE THIEUTH I TIKEUT +U+D2F8(2);; # HANGUL SYLLABLE THIEUTH I RIEUL * +U+D2F9(2);; # HANGUL SYLLABLE THIEUTH I RIEULKIYEOK +U+D2FA(2);; # HANGUL SYLLABLE THIEUTH I RIEULMIEUM +U+D2FB(2);; # HANGUL SYLLABLE THIEUTH I RIEULPIEUP +U+D2FC(2);; # HANGUL SYLLABLE THIEUTH I RIEULSIOS +U+D2FD(2);; # HANGUL SYLLABLE THIEUTH I RIEULTHIEUTH +U+D2FE(2);; # HANGUL SYLLABLE THIEUTH I RIEULPHIEUPH +U+D2FF(2);; # HANGUL SYLLABLE THIEUTH I RIEULHIEUH +U+D300(2);; # HANGUL SYLLABLE THIEUTH I MIEUM * +U+D301(2);; # HANGUL SYLLABLE THIEUTH I PIEUP * +U+D302(2);; # HANGUL SYLLABLE THIEUTH I PIEUPSIOS +U+D303(2);; # HANGUL SYLLABLE THIEUTH I SIOS * +U+D304(2);; # HANGUL SYLLABLE THIEUTH I SSANGSIOS +U+D305(2);; # HANGUL SYLLABLE THIEUTH I IEUNG * +U+D306(2);; # HANGUL SYLLABLE THIEUTH I CIEUC +U+D307(2);; # HANGUL SYLLABLE THIEUTH I CHIEUCH +U+D308(2);; # HANGUL SYLLABLE THIEUTH I KHIEUKH +U+D309(2);; # HANGUL SYLLABLE THIEUTH I THIEUTH +U+D30A(2);; # HANGUL SYLLABLE THIEUTH I PHIEUPH +U+D30B(2);; # HANGUL SYLLABLE THIEUTH I HIEUH +U+D30C(2);; # HANGUL SYLLABLE PHIEUPH A * +U+D30D(2);; # HANGUL SYLLABLE PHIEUPH A KIYEOK * +U+D30E(2);; # HANGUL SYLLABLE PHIEUPH A SSANGKIYEOK * +U+D30F(2);; # HANGUL SYLLABLE PHIEUPH A KIYEOKSIOS +U+D310(2);; # HANGUL SYLLABLE PHIEUPH A NIEUN * +U+D311(2);; # HANGUL SYLLABLE PHIEUPH A NIEUNCIEUC +U+D312(2);; # HANGUL SYLLABLE PHIEUPH A NIEUNHIEUH +U+D313(2);; # HANGUL SYLLABLE PHIEUPH A TIKEUT +U+D314(2);; # HANGUL SYLLABLE PHIEUPH A RIEUL * +U+D315(2);; # HANGUL SYLLABLE PHIEUPH A RIEULKIYEOK +U+D316(2);; # HANGUL SYLLABLE PHIEUPH A RIEULMIEUM * +U+D317(2);; # HANGUL SYLLABLE PHIEUPH A RIEULPIEUP +U+D318(2);; # HANGUL SYLLABLE PHIEUPH A RIEULSIOS +U+D319(2);; # HANGUL SYLLABLE PHIEUPH A RIEULTHIEUTH +U+D31A(2);; # HANGUL SYLLABLE PHIEUPH A RIEULPHIEUPH +U+D31B(2);; # HANGUL SYLLABLE PHIEUPH A RIEULHIEUH +U+D31C(2);; # HANGUL SYLLABLE PHIEUPH A MIEUM * +U+D31D(2);; # HANGUL SYLLABLE PHIEUPH A PIEUP * +U+D31E(2);; # HANGUL SYLLABLE PHIEUPH A PIEUPSIOS +U+D31F(2);; # HANGUL SYLLABLE PHIEUPH A SIOS * +U+D320(2);; # HANGUL SYLLABLE PHIEUPH A SSANGSIOS * +U+D321(2);; # HANGUL SYLLABLE PHIEUPH A IEUNG * +U+D322(2);; # HANGUL SYLLABLE PHIEUPH A CIEUC +U+D323(2);; # HANGUL SYLLABLE PHIEUPH A CHIEUCH +U+D324(2);; # HANGUL SYLLABLE PHIEUPH A KHIEUKH +U+D325(2);; # HANGUL SYLLABLE PHIEUPH A THIEUTH * +U+D326(2);; # HANGUL SYLLABLE PHIEUPH A PHIEUPH +U+D327(2);; # HANGUL SYLLABLE PHIEUPH A HIEUH +U+D328(2);; # HANGUL SYLLABLE PHIEUPH AE * +U+D329(2);; # HANGUL SYLLABLE PHIEUPH AE KIYEOK * +U+D32A(2);; # HANGUL SYLLABLE PHIEUPH AE SSANGKIYEOK +U+D32B(2);; # HANGUL SYLLABLE PHIEUPH AE KIYEOKSIOS +U+D32C(2);; # HANGUL SYLLABLE PHIEUPH AE NIEUN * +U+D32D(2);; # HANGUL SYLLABLE PHIEUPH AE NIEUNCIEUC +U+D32E(2);; # HANGUL SYLLABLE PHIEUPH AE NIEUNHIEUH +U+D32F(2);; # HANGUL SYLLABLE PHIEUPH AE TIKEUT +U+D330(2);; # HANGUL SYLLABLE PHIEUPH AE RIEUL * +U+D331(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULKIYEOK +U+D332(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULMIEUM +U+D333(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULPIEUP +U+D334(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULSIOS +U+D335(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULTHIEUTH +U+D336(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULPHIEUPH +U+D337(2);; # HANGUL SYLLABLE PHIEUPH AE RIEULHIEUH +U+D338(2);; # HANGUL SYLLABLE PHIEUPH AE MIEUM * +U+D339(2);; # HANGUL SYLLABLE PHIEUPH AE PIEUP * +U+D33A(2);; # HANGUL SYLLABLE PHIEUPH AE PIEUPSIOS +U+D33B(2);; # HANGUL SYLLABLE PHIEUPH AE SIOS * +U+D33C(2);; # HANGUL SYLLABLE PHIEUPH AE SSANGSIOS * +U+D33D(2);; # HANGUL SYLLABLE PHIEUPH AE IEUNG * +U+D33E(2);; # HANGUL SYLLABLE PHIEUPH AE CIEUC +U+D33F(2);; # HANGUL SYLLABLE PHIEUPH AE CHIEUCH +U+D340(2);; # HANGUL SYLLABLE PHIEUPH AE KHIEUKH +U+D341(2);; # HANGUL SYLLABLE PHIEUPH AE THIEUTH +U+D342(2);; # HANGUL SYLLABLE PHIEUPH AE PHIEUPH +U+D343(2);; # HANGUL SYLLABLE PHIEUPH AE HIEUH +U+D344(2);; # HANGUL SYLLABLE PHIEUPH YA * +U+D345(2);; # HANGUL SYLLABLE PHIEUPH YA KIYEOK * +U+D346(2);; # HANGUL SYLLABLE PHIEUPH YA SSANGKIYEOK +U+D347(2);; # HANGUL SYLLABLE PHIEUPH YA KIYEOKSIOS +U+D348(2);; # HANGUL SYLLABLE PHIEUPH YA NIEUN +U+D349(2);; # HANGUL SYLLABLE PHIEUPH YA NIEUNCIEUC +U+D34A(2);; # HANGUL SYLLABLE PHIEUPH YA NIEUNHIEUH +U+D34B(2);; # HANGUL SYLLABLE PHIEUPH YA TIKEUT +U+D34C(2);; # HANGUL SYLLABLE PHIEUPH YA RIEUL +U+D34D(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULKIYEOK +U+D34E(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULMIEUM +U+D34F(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULPIEUP +U+D350(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULSIOS +U+D351(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULTHIEUTH +U+D352(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULPHIEUPH +U+D353(2);; # HANGUL SYLLABLE PHIEUPH YA RIEULHIEUH +U+D354(2);; # HANGUL SYLLABLE PHIEUPH YA MIEUM +U+D355(2);; # HANGUL SYLLABLE PHIEUPH YA PIEUP +U+D356(2);; # HANGUL SYLLABLE PHIEUPH YA PIEUPSIOS +U+D357(2);; # HANGUL SYLLABLE PHIEUPH YA SIOS +U+D358(2);; # HANGUL SYLLABLE PHIEUPH YA SSANGSIOS +U+D359(2);; # HANGUL SYLLABLE PHIEUPH YA IEUNG +U+D35A(2);; # HANGUL SYLLABLE PHIEUPH YA CIEUC +U+D35B(2);; # HANGUL SYLLABLE PHIEUPH YA CHIEUCH +U+D35C(2);; # HANGUL SYLLABLE PHIEUPH YA KHIEUKH +U+D35D(2);; # HANGUL SYLLABLE PHIEUPH YA THIEUTH +U+D35E(2);; # HANGUL SYLLABLE PHIEUPH YA PHIEUPH +U+D35F(2);; # HANGUL SYLLABLE PHIEUPH YA HIEUH +U+D360(2);; # HANGUL SYLLABLE PHIEUPH YAE +U+D361(2);; # HANGUL SYLLABLE PHIEUPH YAE KIYEOK +U+D362(2);; # HANGUL SYLLABLE PHIEUPH YAE SSANGKIYEOK +U+D363(2);; # HANGUL SYLLABLE PHIEUPH YAE KIYEOKSIOS +U+D364(2);; # HANGUL SYLLABLE PHIEUPH YAE NIEUN +U+D365(2);; # HANGUL SYLLABLE PHIEUPH YAE NIEUNCIEUC +U+D366(2);; # HANGUL SYLLABLE PHIEUPH YAE NIEUNHIEUH +U+D367(2);; # HANGUL SYLLABLE PHIEUPH YAE TIKEUT +U+D368(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEUL +U+D369(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULKIYEOK +U+D36A(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULMIEUM +U+D36B(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULPIEUP +U+D36C(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULSIOS +U+D36D(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULTHIEUTH +U+D36E(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULPHIEUPH +U+D36F(2);; # HANGUL SYLLABLE PHIEUPH YAE RIEULHIEUH +U+D370(2);; # HANGUL SYLLABLE PHIEUPH YAE MIEUM +U+D371(2);; # HANGUL SYLLABLE PHIEUPH YAE PIEUP +U+D372(2);; # HANGUL SYLLABLE PHIEUPH YAE PIEUPSIOS +U+D373(2);; # HANGUL SYLLABLE PHIEUPH YAE SIOS +U+D374(2);; # HANGUL SYLLABLE PHIEUPH YAE SSANGSIOS +U+D375(2);; # HANGUL SYLLABLE PHIEUPH YAE IEUNG +U+D376(2);; # HANGUL SYLLABLE PHIEUPH YAE CIEUC +U+D377(2);; # HANGUL SYLLABLE PHIEUPH YAE CHIEUCH +U+D378(2);; # HANGUL SYLLABLE PHIEUPH YAE KHIEUKH +U+D379(2);; # HANGUL SYLLABLE PHIEUPH YAE THIEUTH +U+D37A(2);; # HANGUL SYLLABLE PHIEUPH YAE PHIEUPH +U+D37B(2);; # HANGUL SYLLABLE PHIEUPH YAE HIEUH +U+D37C(2);; # HANGUL SYLLABLE PHIEUPH EO * +U+D37D(2);; # HANGUL SYLLABLE PHIEUPH EO KIYEOK * +U+D37E(2);; # HANGUL SYLLABLE PHIEUPH EO SSANGKIYEOK +U+D37F(2);; # HANGUL SYLLABLE PHIEUPH EO KIYEOKSIOS +U+D380(2);; # HANGUL SYLLABLE PHIEUPH EO NIEUN * +U+D381(2);; # HANGUL SYLLABLE PHIEUPH EO NIEUNCIEUC +U+D382(2);; # HANGUL SYLLABLE PHIEUPH EO NIEUNHIEUH +U+D383(2);; # HANGUL SYLLABLE PHIEUPH EO TIKEUT +U+D384(2);; # HANGUL SYLLABLE PHIEUPH EO RIEUL * +U+D385(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULKIYEOK +U+D386(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULMIEUM +U+D387(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULPIEUP +U+D388(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULSIOS +U+D389(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULTHIEUTH +U+D38A(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULPHIEUPH +U+D38B(2);; # HANGUL SYLLABLE PHIEUPH EO RIEULHIEUH +U+D38C(2);; # HANGUL SYLLABLE PHIEUPH EO MIEUM * +U+D38D(2);; # HANGUL SYLLABLE PHIEUPH EO PIEUP * +U+D38E(2);; # HANGUL SYLLABLE PHIEUPH EO PIEUPSIOS +U+D38F(2);; # HANGUL SYLLABLE PHIEUPH EO SIOS * +U+D390(2);; # HANGUL SYLLABLE PHIEUPH EO SSANGSIOS * +U+D391(2);; # HANGUL SYLLABLE PHIEUPH EO IEUNG * +U+D392(2);; # HANGUL SYLLABLE PHIEUPH EO CIEUC +U+D393(2);; # HANGUL SYLLABLE PHIEUPH EO CHIEUCH +U+D394(2);; # HANGUL SYLLABLE PHIEUPH EO KHIEUKH +U+D395(2);; # HANGUL SYLLABLE PHIEUPH EO THIEUTH +U+D396(2);; # HANGUL SYLLABLE PHIEUPH EO PHIEUPH +U+D397(2);; # HANGUL SYLLABLE PHIEUPH EO HIEUH +U+D398(2);; # HANGUL SYLLABLE PHIEUPH E * +U+D399(2);; # HANGUL SYLLABLE PHIEUPH E KIYEOK * +U+D39A(2);; # HANGUL SYLLABLE PHIEUPH E SSANGKIYEOK +U+D39B(2);; # HANGUL SYLLABLE PHIEUPH E KIYEOKSIOS +U+D39C(2);; # HANGUL SYLLABLE PHIEUPH E NIEUN * +U+D39D(2);; # HANGUL SYLLABLE PHIEUPH E NIEUNCIEUC +U+D39E(2);; # HANGUL SYLLABLE PHIEUPH E NIEUNHIEUH +U+D39F(2);; # HANGUL SYLLABLE PHIEUPH E TIKEUT +U+D3A0(2);; # HANGUL SYLLABLE PHIEUPH E RIEUL * +U+D3A1(2);; # HANGUL SYLLABLE PHIEUPH E RIEULKIYEOK +U+D3A2(2);; # HANGUL SYLLABLE PHIEUPH E RIEULMIEUM +U+D3A3(2);; # HANGUL SYLLABLE PHIEUPH E RIEULPIEUP +U+D3A4(2);; # HANGUL SYLLABLE PHIEUPH E RIEULSIOS +U+D3A5(2);; # HANGUL SYLLABLE PHIEUPH E RIEULTHIEUTH +U+D3A6(2);; # HANGUL SYLLABLE PHIEUPH E RIEULPHIEUPH +U+D3A7(2);; # HANGUL SYLLABLE PHIEUPH E RIEULHIEUH +U+D3A8(2);; # HANGUL SYLLABLE PHIEUPH E MIEUM * +U+D3A9(2);; # HANGUL SYLLABLE PHIEUPH E PIEUP * +U+D3AA(2);; # HANGUL SYLLABLE PHIEUPH E PIEUPSIOS +U+D3AB(2);; # HANGUL SYLLABLE PHIEUPH E SIOS * +U+D3AC(2);; # HANGUL SYLLABLE PHIEUPH E SSANGSIOS +U+D3AD(2);; # HANGUL SYLLABLE PHIEUPH E IEUNG * +U+D3AE(2);; # HANGUL SYLLABLE PHIEUPH E CIEUC +U+D3AF(2);; # HANGUL SYLLABLE PHIEUPH E CHIEUCH +U+D3B0(2);; # HANGUL SYLLABLE PHIEUPH E KHIEUKH +U+D3B1(2);; # HANGUL SYLLABLE PHIEUPH E THIEUTH +U+D3B2(2);; # HANGUL SYLLABLE PHIEUPH E PHIEUPH +U+D3B3(2);; # HANGUL SYLLABLE PHIEUPH E HIEUH +U+D3B4(2);; # HANGUL SYLLABLE PHIEUPH YEO * +U+D3B5(2);; # HANGUL SYLLABLE PHIEUPH YEO KIYEOK +U+D3B6(2);; # HANGUL SYLLABLE PHIEUPH YEO SSANGKIYEOK +U+D3B7(2);; # HANGUL SYLLABLE PHIEUPH YEO KIYEOKSIOS +U+D3B8(2);; # HANGUL SYLLABLE PHIEUPH YEO NIEUN * +U+D3B9(2);; # HANGUL SYLLABLE PHIEUPH YEO NIEUNCIEUC +U+D3BA(2);; # HANGUL SYLLABLE PHIEUPH YEO NIEUNHIEUH +U+D3BB(2);; # HANGUL SYLLABLE PHIEUPH YEO TIKEUT +U+D3BC(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEUL * +U+D3BD(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULKIYEOK +U+D3BE(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULMIEUM +U+D3BF(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULPIEUP +U+D3C0(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULSIOS +U+D3C1(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULTHIEUTH +U+D3C2(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULPHIEUPH +U+D3C3(2);; # HANGUL SYLLABLE PHIEUPH YEO RIEULHIEUH +U+D3C4(2);; # HANGUL SYLLABLE PHIEUPH YEO MIEUM * +U+D3C5(2);; # HANGUL SYLLABLE PHIEUPH YEO PIEUP * +U+D3C6(2);; # HANGUL SYLLABLE PHIEUPH YEO PIEUPSIOS +U+D3C7(2);; # HANGUL SYLLABLE PHIEUPH YEO SIOS +U+D3C8(2);; # HANGUL SYLLABLE PHIEUPH YEO SSANGSIOS * +U+D3C9(2);; # HANGUL SYLLABLE PHIEUPH YEO IEUNG * +U+D3CA(2);; # HANGUL SYLLABLE PHIEUPH YEO CIEUC +U+D3CB(2);; # HANGUL SYLLABLE PHIEUPH YEO CHIEUCH +U+D3CC(2);; # HANGUL SYLLABLE PHIEUPH YEO KHIEUKH +U+D3CD(2);; # HANGUL SYLLABLE PHIEUPH YEO THIEUTH +U+D3CE(2);; # HANGUL SYLLABLE PHIEUPH YEO PHIEUPH +U+D3CF(2);; # HANGUL SYLLABLE PHIEUPH YEO HIEUH +U+D3D0(2);; # HANGUL SYLLABLE PHIEUPH YE * +U+D3D1(2);; # HANGUL SYLLABLE PHIEUPH YE KIYEOK +U+D3D2(2);; # HANGUL SYLLABLE PHIEUPH YE SSANGKIYEOK +U+D3D3(2);; # HANGUL SYLLABLE PHIEUPH YE KIYEOKSIOS +U+D3D4(2);; # HANGUL SYLLABLE PHIEUPH YE NIEUN +U+D3D5(2);; # HANGUL SYLLABLE PHIEUPH YE NIEUNCIEUC +U+D3D6(2);; # HANGUL SYLLABLE PHIEUPH YE NIEUNHIEUH +U+D3D7(2);; # HANGUL SYLLABLE PHIEUPH YE TIKEUT +U+D3D8(2);; # HANGUL SYLLABLE PHIEUPH YE RIEUL * +U+D3D9(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULKIYEOK +U+D3DA(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULMIEUM +U+D3DB(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULPIEUP +U+D3DC(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULSIOS +U+D3DD(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULTHIEUTH +U+D3DE(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULPHIEUPH +U+D3DF(2);; # HANGUL SYLLABLE PHIEUPH YE RIEULHIEUH +U+D3E0(2);; # HANGUL SYLLABLE PHIEUPH YE MIEUM +U+D3E1(2);; # HANGUL SYLLABLE PHIEUPH YE PIEUP * +U+D3E2(2);; # HANGUL SYLLABLE PHIEUPH YE PIEUPSIOS +U+D3E3(2);; # HANGUL SYLLABLE PHIEUPH YE SIOS * +U+D3E4(2);; # HANGUL SYLLABLE PHIEUPH YE SSANGSIOS +U+D3E5(2);; # HANGUL SYLLABLE PHIEUPH YE IEUNG +U+D3E6(2);; # HANGUL SYLLABLE PHIEUPH YE CIEUC +U+D3E7(2);; # HANGUL SYLLABLE PHIEUPH YE CHIEUCH +U+D3E8(2);; # HANGUL SYLLABLE PHIEUPH YE KHIEUKH +U+D3E9(2);; # HANGUL SYLLABLE PHIEUPH YE THIEUTH +U+D3EA(2);; # HANGUL SYLLABLE PHIEUPH YE PHIEUPH +U+D3EB(2);; # HANGUL SYLLABLE PHIEUPH YE HIEUH +U+D3EC(2);; # HANGUL SYLLABLE PHIEUPH O * +U+D3ED(2);; # HANGUL SYLLABLE PHIEUPH O KIYEOK * +U+D3EE(2);; # HANGUL SYLLABLE PHIEUPH O SSANGKIYEOK +U+D3EF(2);; # HANGUL SYLLABLE PHIEUPH O KIYEOKSIOS +U+D3F0(2);; # HANGUL SYLLABLE PHIEUPH O NIEUN * +U+D3F1(2);; # HANGUL SYLLABLE PHIEUPH O NIEUNCIEUC +U+D3F2(2);; # HANGUL SYLLABLE PHIEUPH O NIEUNHIEUH +U+D3F3(2);; # HANGUL SYLLABLE PHIEUPH O TIKEUT +U+D3F4(2);; # HANGUL SYLLABLE PHIEUPH O RIEUL * +U+D3F5(2);; # HANGUL SYLLABLE PHIEUPH O RIEULKIYEOK +U+D3F6(2);; # HANGUL SYLLABLE PHIEUPH O RIEULMIEUM +U+D3F7(2);; # HANGUL SYLLABLE PHIEUPH O RIEULPIEUP +U+D3F8(2);; # HANGUL SYLLABLE PHIEUPH O RIEULSIOS +U+D3F9(2);; # HANGUL SYLLABLE PHIEUPH O RIEULTHIEUTH +U+D3FA(2);; # HANGUL SYLLABLE PHIEUPH O RIEULPHIEUPH +U+D3FB(2);; # HANGUL SYLLABLE PHIEUPH O RIEULHIEUH +U+D3FC(2);; # HANGUL SYLLABLE PHIEUPH O MIEUM * +U+D3FD(2);; # HANGUL SYLLABLE PHIEUPH O PIEUP * +U+D3FE(2);; # HANGUL SYLLABLE PHIEUPH O PIEUPSIOS +U+D3FF(2);; # HANGUL SYLLABLE PHIEUPH O SIOS * +U+D400(2);; # HANGUL SYLLABLE PHIEUPH O SSANGSIOS +U+D401(2);; # HANGUL SYLLABLE PHIEUPH O IEUNG * +U+D402(2);; # HANGUL SYLLABLE PHIEUPH O CIEUC +U+D403(2);; # HANGUL SYLLABLE PHIEUPH O CHIEUCH +U+D404(2);; # HANGUL SYLLABLE PHIEUPH O KHIEUKH +U+D405(2);; # HANGUL SYLLABLE PHIEUPH O THIEUTH +U+D406(2);; # HANGUL SYLLABLE PHIEUPH O PHIEUPH +U+D407(2);; # HANGUL SYLLABLE PHIEUPH O HIEUH +U+D408(2);; # HANGUL SYLLABLE PHIEUPH WA * +U+D409(2);; # HANGUL SYLLABLE PHIEUPH WA KIYEOK +U+D40A(2);; # HANGUL SYLLABLE PHIEUPH WA SSANGKIYEOK +U+D40B(2);; # HANGUL SYLLABLE PHIEUPH WA KIYEOKSIOS +U+D40C(2);; # HANGUL SYLLABLE PHIEUPH WA NIEUN +U+D40D(2);; # HANGUL SYLLABLE PHIEUPH WA NIEUNCIEUC +U+D40E(2);; # HANGUL SYLLABLE PHIEUPH WA NIEUNHIEUH +U+D40F(2);; # HANGUL SYLLABLE PHIEUPH WA TIKEUT +U+D410(2);; # HANGUL SYLLABLE PHIEUPH WA RIEUL +U+D411(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULKIYEOK +U+D412(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULMIEUM +U+D413(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULPIEUP +U+D414(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULSIOS +U+D415(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULTHIEUTH +U+D416(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULPHIEUPH +U+D417(2);; # HANGUL SYLLABLE PHIEUPH WA RIEULHIEUH +U+D418(2);; # HANGUL SYLLABLE PHIEUPH WA MIEUM +U+D419(2);; # HANGUL SYLLABLE PHIEUPH WA PIEUP +U+D41A(2);; # HANGUL SYLLABLE PHIEUPH WA PIEUPSIOS +U+D41B(2);; # HANGUL SYLLABLE PHIEUPH WA SIOS +U+D41C(2);; # HANGUL SYLLABLE PHIEUPH WA SSANGSIOS +U+D41D(2);; # HANGUL SYLLABLE PHIEUPH WA IEUNG * +U+D41E(2);; # HANGUL SYLLABLE PHIEUPH WA CIEUC +U+D41F(2);; # HANGUL SYLLABLE PHIEUPH WA CHIEUCH +U+D420(2);; # HANGUL SYLLABLE PHIEUPH WA KHIEUKH +U+D421(2);; # HANGUL SYLLABLE PHIEUPH WA THIEUTH +U+D422(2);; # HANGUL SYLLABLE PHIEUPH WA PHIEUPH +U+D423(2);; # HANGUL SYLLABLE PHIEUPH WA HIEUH +U+D424(2);; # HANGUL SYLLABLE PHIEUPH WAE +U+D425(2);; # HANGUL SYLLABLE PHIEUPH WAE KIYEOK +U+D426(2);; # HANGUL SYLLABLE PHIEUPH WAE SSANGKIYEOK +U+D427(2);; # HANGUL SYLLABLE PHIEUPH WAE KIYEOKSIOS +U+D428(2);; # HANGUL SYLLABLE PHIEUPH WAE NIEUN +U+D429(2);; # HANGUL SYLLABLE PHIEUPH WAE NIEUNCIEUC +U+D42A(2);; # HANGUL SYLLABLE PHIEUPH WAE NIEUNHIEUH +U+D42B(2);; # HANGUL SYLLABLE PHIEUPH WAE TIKEUT +U+D42C(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEUL +U+D42D(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULKIYEOK +U+D42E(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULMIEUM +U+D42F(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULPIEUP +U+D430(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULSIOS +U+D431(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULTHIEUTH +U+D432(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULPHIEUPH +U+D433(2);; # HANGUL SYLLABLE PHIEUPH WAE RIEULHIEUH +U+D434(2);; # HANGUL SYLLABLE PHIEUPH WAE MIEUM +U+D435(2);; # HANGUL SYLLABLE PHIEUPH WAE PIEUP +U+D436(2);; # HANGUL SYLLABLE PHIEUPH WAE PIEUPSIOS +U+D437(2);; # HANGUL SYLLABLE PHIEUPH WAE SIOS +U+D438(2);; # HANGUL SYLLABLE PHIEUPH WAE SSANGSIOS +U+D439(2);; # HANGUL SYLLABLE PHIEUPH WAE IEUNG +U+D43A(2);; # HANGUL SYLLABLE PHIEUPH WAE CIEUC +U+D43B(2);; # HANGUL SYLLABLE PHIEUPH WAE CHIEUCH +U+D43C(2);; # HANGUL SYLLABLE PHIEUPH WAE KHIEUKH +U+D43D(2);; # HANGUL SYLLABLE PHIEUPH WAE THIEUTH +U+D43E(2);; # HANGUL SYLLABLE PHIEUPH WAE PHIEUPH +U+D43F(2);; # HANGUL SYLLABLE PHIEUPH WAE HIEUH +U+D440(2);; # HANGUL SYLLABLE PHIEUPH OE * +U+D441(2);; # HANGUL SYLLABLE PHIEUPH OE KIYEOK +U+D442(2);; # HANGUL SYLLABLE PHIEUPH OE SSANGKIYEOK +U+D443(2);; # HANGUL SYLLABLE PHIEUPH OE KIYEOKSIOS +U+D444(2);; # HANGUL SYLLABLE PHIEUPH OE NIEUN * +U+D445(2);; # HANGUL SYLLABLE PHIEUPH OE NIEUNCIEUC +U+D446(2);; # HANGUL SYLLABLE PHIEUPH OE NIEUNHIEUH +U+D447(2);; # HANGUL SYLLABLE PHIEUPH OE TIKEUT +U+D448(2);; # HANGUL SYLLABLE PHIEUPH OE RIEUL +U+D449(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULKIYEOK +U+D44A(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULMIEUM +U+D44B(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULPIEUP +U+D44C(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULSIOS +U+D44D(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULTHIEUTH +U+D44E(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULPHIEUPH +U+D44F(2);; # HANGUL SYLLABLE PHIEUPH OE RIEULHIEUH +U+D450(2);; # HANGUL SYLLABLE PHIEUPH OE MIEUM +U+D451(2);; # HANGUL SYLLABLE PHIEUPH OE PIEUP +U+D452(2);; # HANGUL SYLLABLE PHIEUPH OE PIEUPSIOS +U+D453(2);; # HANGUL SYLLABLE PHIEUPH OE SIOS +U+D454(2);; # HANGUL SYLLABLE PHIEUPH OE SSANGSIOS +U+D455(2);; # HANGUL SYLLABLE PHIEUPH OE IEUNG +U+D456(2);; # HANGUL SYLLABLE PHIEUPH OE CIEUC +U+D457(2);; # HANGUL SYLLABLE PHIEUPH OE CHIEUCH +U+D458(2);; # HANGUL SYLLABLE PHIEUPH OE KHIEUKH +U+D459(2);; # HANGUL SYLLABLE PHIEUPH OE THIEUTH +U+D45A(2);; # HANGUL SYLLABLE PHIEUPH OE PHIEUPH +U+D45B(2);; # HANGUL SYLLABLE PHIEUPH OE HIEUH +U+D45C(2);; # HANGUL SYLLABLE PHIEUPH YO * +U+D45D(2);; # HANGUL SYLLABLE PHIEUPH YO KIYEOK +U+D45E(2);; # HANGUL SYLLABLE PHIEUPH YO SSANGKIYEOK +U+D45F(2);; # HANGUL SYLLABLE PHIEUPH YO KIYEOKSIOS +U+D460(2);; # HANGUL SYLLABLE PHIEUPH YO NIEUN * +U+D461(2);; # HANGUL SYLLABLE PHIEUPH YO NIEUNCIEUC +U+D462(2);; # HANGUL SYLLABLE PHIEUPH YO NIEUNHIEUH +U+D463(2);; # HANGUL SYLLABLE PHIEUPH YO TIKEUT +U+D464(2);; # HANGUL SYLLABLE PHIEUPH YO RIEUL * +U+D465(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULKIYEOK +U+D466(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULMIEUM +U+D467(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULPIEUP +U+D468(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULSIOS +U+D469(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULTHIEUTH +U+D46A(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULPHIEUPH +U+D46B(2);; # HANGUL SYLLABLE PHIEUPH YO RIEULHIEUH +U+D46C(2);; # HANGUL SYLLABLE PHIEUPH YO MIEUM +U+D46D(2);; # HANGUL SYLLABLE PHIEUPH YO PIEUP * +U+D46E(2);; # HANGUL SYLLABLE PHIEUPH YO PIEUPSIOS +U+D46F(2);; # HANGUL SYLLABLE PHIEUPH YO SIOS * +U+D470(2);; # HANGUL SYLLABLE PHIEUPH YO SSANGSIOS +U+D471(2);; # HANGUL SYLLABLE PHIEUPH YO IEUNG +U+D472(2);; # HANGUL SYLLABLE PHIEUPH YO CIEUC +U+D473(2);; # HANGUL SYLLABLE PHIEUPH YO CHIEUCH +U+D474(2);; # HANGUL SYLLABLE PHIEUPH YO KHIEUKH +U+D475(2);; # HANGUL SYLLABLE PHIEUPH YO THIEUTH +U+D476(2);; # HANGUL SYLLABLE PHIEUPH YO PHIEUPH +U+D477(2);; # HANGUL SYLLABLE PHIEUPH YO HIEUH +U+D478(2);; # HANGUL SYLLABLE PHIEUPH U * +U+D479(2);; # HANGUL SYLLABLE PHIEUPH U KIYEOK * +U+D47A(2);; # HANGUL SYLLABLE PHIEUPH U SSANGKIYEOK +U+D47B(2);; # HANGUL SYLLABLE PHIEUPH U KIYEOKSIOS +U+D47C(2);; # HANGUL SYLLABLE PHIEUPH U NIEUN * +U+D47D(2);; # HANGUL SYLLABLE PHIEUPH U NIEUNCIEUC +U+D47E(2);; # HANGUL SYLLABLE PHIEUPH U NIEUNHIEUH +U+D47F(2);; # HANGUL SYLLABLE PHIEUPH U TIKEUT * +U+D480(2);; # HANGUL SYLLABLE PHIEUPH U RIEUL * +U+D481(2);; # HANGUL SYLLABLE PHIEUPH U RIEULKIYEOK +U+D482(2);; # HANGUL SYLLABLE PHIEUPH U RIEULMIEUM * +U+D483(2);; # HANGUL SYLLABLE PHIEUPH U RIEULPIEUP +U+D484(2);; # HANGUL SYLLABLE PHIEUPH U RIEULSIOS +U+D485(2);; # HANGUL SYLLABLE PHIEUPH U RIEULTHIEUTH +U+D486(2);; # HANGUL SYLLABLE PHIEUPH U RIEULPHIEUPH +U+D487(2);; # HANGUL SYLLABLE PHIEUPH U RIEULHIEUH +U+D488(2);; # HANGUL SYLLABLE PHIEUPH U MIEUM * +U+D489(2);; # HANGUL SYLLABLE PHIEUPH U PIEUP * +U+D48A(2);; # HANGUL SYLLABLE PHIEUPH U PIEUPSIOS +U+D48B(2);; # HANGUL SYLLABLE PHIEUPH U SIOS * +U+D48C(2);; # HANGUL SYLLABLE PHIEUPH U SSANGSIOS +U+D48D(2);; # HANGUL SYLLABLE PHIEUPH U IEUNG * +U+D48E(2);; # HANGUL SYLLABLE PHIEUPH U CIEUC +U+D48F(2);; # HANGUL SYLLABLE PHIEUPH U CHIEUCH +U+D490(2);; # HANGUL SYLLABLE PHIEUPH U KHIEUKH +U+D491(2);; # HANGUL SYLLABLE PHIEUPH U THIEUTH +U+D492(2);; # HANGUL SYLLABLE PHIEUPH U PHIEUPH +U+D493(2);; # HANGUL SYLLABLE PHIEUPH U HIEUH +U+D494(2);; # HANGUL SYLLABLE PHIEUPH WEO * +U+D495(2);; # HANGUL SYLLABLE PHIEUPH WEO KIYEOK +U+D496(2);; # HANGUL SYLLABLE PHIEUPH WEO SSANGKIYEOK +U+D497(2);; # HANGUL SYLLABLE PHIEUPH WEO KIYEOKSIOS +U+D498(2);; # HANGUL SYLLABLE PHIEUPH WEO NIEUN +U+D499(2);; # HANGUL SYLLABLE PHIEUPH WEO NIEUNCIEUC +U+D49A(2);; # HANGUL SYLLABLE PHIEUPH WEO NIEUNHIEUH +U+D49B(2);; # HANGUL SYLLABLE PHIEUPH WEO TIKEUT +U+D49C(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEUL +U+D49D(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULKIYEOK +U+D49E(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULMIEUM +U+D49F(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULPIEUP +U+D4A0(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULSIOS +U+D4A1(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULTHIEUTH +U+D4A2(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULPHIEUPH +U+D4A3(2);; # HANGUL SYLLABLE PHIEUPH WEO RIEULHIEUH +U+D4A4(2);; # HANGUL SYLLABLE PHIEUPH WEO MIEUM +U+D4A5(2);; # HANGUL SYLLABLE PHIEUPH WEO PIEUP +U+D4A6(2);; # HANGUL SYLLABLE PHIEUPH WEO PIEUPSIOS +U+D4A7(2);; # HANGUL SYLLABLE PHIEUPH WEO SIOS +U+D4A8(2);; # HANGUL SYLLABLE PHIEUPH WEO SSANGSIOS +U+D4A9(2);; # HANGUL SYLLABLE PHIEUPH WEO IEUNG * +U+D4AA(2);; # HANGUL SYLLABLE PHIEUPH WEO CIEUC +U+D4AB(2);; # HANGUL SYLLABLE PHIEUPH WEO CHIEUCH +U+D4AC(2);; # HANGUL SYLLABLE PHIEUPH WEO KHIEUKH +U+D4AD(2);; # HANGUL SYLLABLE PHIEUPH WEO THIEUTH +U+D4AE(2);; # HANGUL SYLLABLE PHIEUPH WEO PHIEUPH +U+D4AF(2);; # HANGUL SYLLABLE PHIEUPH WEO HIEUH +U+D4B0(2);; # HANGUL SYLLABLE PHIEUPH WE +U+D4B1(2);; # HANGUL SYLLABLE PHIEUPH WE KIYEOK +U+D4B2(2);; # HANGUL SYLLABLE PHIEUPH WE SSANGKIYEOK +U+D4B3(2);; # HANGUL SYLLABLE PHIEUPH WE KIYEOKSIOS +U+D4B4(2);; # HANGUL SYLLABLE PHIEUPH WE NIEUN +U+D4B5(2);; # HANGUL SYLLABLE PHIEUPH WE NIEUNCIEUC +U+D4B6(2);; # HANGUL SYLLABLE PHIEUPH WE NIEUNHIEUH +U+D4B7(2);; # HANGUL SYLLABLE PHIEUPH WE TIKEUT +U+D4B8(2);; # HANGUL SYLLABLE PHIEUPH WE RIEUL +U+D4B9(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULKIYEOK +U+D4BA(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULMIEUM +U+D4BB(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULPIEUP +U+D4BC(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULSIOS +U+D4BD(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULTHIEUTH +U+D4BE(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULPHIEUPH +U+D4BF(2);; # HANGUL SYLLABLE PHIEUPH WE RIEULHIEUH +U+D4C0(2);; # HANGUL SYLLABLE PHIEUPH WE MIEUM +U+D4C1(2);; # HANGUL SYLLABLE PHIEUPH WE PIEUP +U+D4C2(2);; # HANGUL SYLLABLE PHIEUPH WE PIEUPSIOS +U+D4C3(2);; # HANGUL SYLLABLE PHIEUPH WE SIOS +U+D4C4(2);; # HANGUL SYLLABLE PHIEUPH WE SSANGSIOS +U+D4C5(2);; # HANGUL SYLLABLE PHIEUPH WE IEUNG +U+D4C6(2);; # HANGUL SYLLABLE PHIEUPH WE CIEUC +U+D4C7(2);; # HANGUL SYLLABLE PHIEUPH WE CHIEUCH +U+D4C8(2);; # HANGUL SYLLABLE PHIEUPH WE KHIEUKH +U+D4C9(2);; # HANGUL SYLLABLE PHIEUPH WE THIEUTH +U+D4CA(2);; # HANGUL SYLLABLE PHIEUPH WE PHIEUPH +U+D4CB(2);; # HANGUL SYLLABLE PHIEUPH WE HIEUH +U+D4CC(2);; # HANGUL SYLLABLE PHIEUPH WI * +U+D4CD(2);; # HANGUL SYLLABLE PHIEUPH WI KIYEOK +U+D4CE(2);; # HANGUL SYLLABLE PHIEUPH WI SSANGKIYEOK +U+D4CF(2);; # HANGUL SYLLABLE PHIEUPH WI KIYEOKSIOS +U+D4D0(2);; # HANGUL SYLLABLE PHIEUPH WI NIEUN * +U+D4D1(2);; # HANGUL SYLLABLE PHIEUPH WI NIEUNCIEUC +U+D4D2(2);; # HANGUL SYLLABLE PHIEUPH WI NIEUNHIEUH +U+D4D3(2);; # HANGUL SYLLABLE PHIEUPH WI TIKEUT +U+D4D4(2);; # HANGUL SYLLABLE PHIEUPH WI RIEUL * +U+D4D5(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULKIYEOK +U+D4D6(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULMIEUM +U+D4D7(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULPIEUP +U+D4D8(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULSIOS +U+D4D9(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULTHIEUTH +U+D4DA(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULPHIEUPH +U+D4DB(2);; # HANGUL SYLLABLE PHIEUPH WI RIEULHIEUH +U+D4DC(2);; # HANGUL SYLLABLE PHIEUPH WI MIEUM * +U+D4DD(2);; # HANGUL SYLLABLE PHIEUPH WI PIEUP +U+D4DE(2);; # HANGUL SYLLABLE PHIEUPH WI PIEUPSIOS +U+D4DF(2);; # HANGUL SYLLABLE PHIEUPH WI SIOS * +U+D4E0(2);; # HANGUL SYLLABLE PHIEUPH WI SSANGSIOS +U+D4E1(2);; # HANGUL SYLLABLE PHIEUPH WI IEUNG +U+D4E2(2);; # HANGUL SYLLABLE PHIEUPH WI CIEUC +U+D4E3(2);; # HANGUL SYLLABLE PHIEUPH WI CHIEUCH +U+D4E4(2);; # HANGUL SYLLABLE PHIEUPH WI KHIEUKH +U+D4E5(2);; # HANGUL SYLLABLE PHIEUPH WI THIEUTH +U+D4E6(2);; # HANGUL SYLLABLE PHIEUPH WI PHIEUPH +U+D4E7(2);; # HANGUL SYLLABLE PHIEUPH WI HIEUH +U+D4E8(2);; # HANGUL SYLLABLE PHIEUPH YU * +U+D4E9(2);; # HANGUL SYLLABLE PHIEUPH YU KIYEOK +U+D4EA(2);; # HANGUL SYLLABLE PHIEUPH YU SSANGKIYEOK +U+D4EB(2);; # HANGUL SYLLABLE PHIEUPH YU KIYEOKSIOS +U+D4EC(2);; # HANGUL SYLLABLE PHIEUPH YU NIEUN * +U+D4ED(2);; # HANGUL SYLLABLE PHIEUPH YU NIEUNCIEUC +U+D4EE(2);; # HANGUL SYLLABLE PHIEUPH YU NIEUNHIEUH +U+D4EF(2);; # HANGUL SYLLABLE PHIEUPH YU TIKEUT +U+D4F0(2);; # HANGUL SYLLABLE PHIEUPH YU RIEUL * +U+D4F1(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULKIYEOK +U+D4F2(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULMIEUM +U+D4F3(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULPIEUP +U+D4F4(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULSIOS +U+D4F5(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULTHIEUTH +U+D4F6(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULPHIEUPH +U+D4F7(2);; # HANGUL SYLLABLE PHIEUPH YU RIEULHIEUH +U+D4F8(2);; # HANGUL SYLLABLE PHIEUPH YU MIEUM * +U+D4F9(2);; # HANGUL SYLLABLE PHIEUPH YU PIEUP +U+D4FA(2);; # HANGUL SYLLABLE PHIEUPH YU PIEUPSIOS +U+D4FB(2);; # HANGUL SYLLABLE PHIEUPH YU SIOS * +U+D4FC(2);; # HANGUL SYLLABLE PHIEUPH YU SSANGSIOS +U+D4FD(2);; # HANGUL SYLLABLE PHIEUPH YU IEUNG * +U+D4FE(2);; # HANGUL SYLLABLE PHIEUPH YU CIEUC +U+D4FF(2);; # HANGUL SYLLABLE PHIEUPH YU CHIEUCH +U+D500(2);; # HANGUL SYLLABLE PHIEUPH YU KHIEUKH +U+D501(2);; # HANGUL SYLLABLE PHIEUPH YU THIEUTH +U+D502(2);; # HANGUL SYLLABLE PHIEUPH YU PHIEUPH +U+D503(2);; # HANGUL SYLLABLE PHIEUPH YU HIEUH +U+D504(2);; # HANGUL SYLLABLE PHIEUPH EU * +U+D505(2);; # HANGUL SYLLABLE PHIEUPH EU KIYEOK +U+D506(2);; # HANGUL SYLLABLE PHIEUPH EU SSANGKIYEOK +U+D507(2);; # HANGUL SYLLABLE PHIEUPH EU KIYEOKSIOS +U+D508(2);; # HANGUL SYLLABLE PHIEUPH EU NIEUN * +U+D509(2);; # HANGUL SYLLABLE PHIEUPH EU NIEUNCIEUC +U+D50A(2);; # HANGUL SYLLABLE PHIEUPH EU NIEUNHIEUH +U+D50B(2);; # HANGUL SYLLABLE PHIEUPH EU TIKEUT +U+D50C(2);; # HANGUL SYLLABLE PHIEUPH EU RIEUL * +U+D50D(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULKIYEOK +U+D50E(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULMIEUM +U+D50F(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULPIEUP +U+D510(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULSIOS +U+D511(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULTHIEUTH +U+D512(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULPHIEUPH +U+D513(2);; # HANGUL SYLLABLE PHIEUPH EU RIEULHIEUH +U+D514(2);; # HANGUL SYLLABLE PHIEUPH EU MIEUM * +U+D515(2);; # HANGUL SYLLABLE PHIEUPH EU PIEUP * +U+D516(2);; # HANGUL SYLLABLE PHIEUPH EU PIEUPSIOS +U+D517(2);; # HANGUL SYLLABLE PHIEUPH EU SIOS * +U+D518(2);; # HANGUL SYLLABLE PHIEUPH EU SSANGSIOS +U+D519(2);; # HANGUL SYLLABLE PHIEUPH EU IEUNG +U+D51A(2);; # HANGUL SYLLABLE PHIEUPH EU CIEUC +U+D51B(2);; # HANGUL SYLLABLE PHIEUPH EU CHIEUCH +U+D51C(2);; # HANGUL SYLLABLE PHIEUPH EU KHIEUKH +U+D51D(2);; # HANGUL SYLLABLE PHIEUPH EU THIEUTH +U+D51E(2);; # HANGUL SYLLABLE PHIEUPH EU PHIEUPH +U+D51F(2);; # HANGUL SYLLABLE PHIEUPH EU HIEUH +U+D520(2);; # HANGUL SYLLABLE PHIEUPH YI +U+D521(2);; # HANGUL SYLLABLE PHIEUPH YI KIYEOK +U+D522(2);; # HANGUL SYLLABLE PHIEUPH YI SSANGKIYEOK +U+D523(2);; # HANGUL SYLLABLE PHIEUPH YI KIYEOKSIOS +U+D524(2);; # HANGUL SYLLABLE PHIEUPH YI NIEUN +U+D525(2);; # HANGUL SYLLABLE PHIEUPH YI NIEUNCIEUC +U+D526(2);; # HANGUL SYLLABLE PHIEUPH YI NIEUNHIEUH +U+D527(2);; # HANGUL SYLLABLE PHIEUPH YI TIKEUT +U+D528(2);; # HANGUL SYLLABLE PHIEUPH YI RIEUL +U+D529(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULKIYEOK +U+D52A(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULMIEUM +U+D52B(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULPIEUP +U+D52C(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULSIOS +U+D52D(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULTHIEUTH +U+D52E(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULPHIEUPH +U+D52F(2);; # HANGUL SYLLABLE PHIEUPH YI RIEULHIEUH +U+D530(2);; # HANGUL SYLLABLE PHIEUPH YI MIEUM +U+D531(2);; # HANGUL SYLLABLE PHIEUPH YI PIEUP +U+D532(2);; # HANGUL SYLLABLE PHIEUPH YI PIEUPSIOS +U+D533(2);; # HANGUL SYLLABLE PHIEUPH YI SIOS +U+D534(2);; # HANGUL SYLLABLE PHIEUPH YI SSANGSIOS +U+D535(2);; # HANGUL SYLLABLE PHIEUPH YI IEUNG +U+D536(2);; # HANGUL SYLLABLE PHIEUPH YI CIEUC +U+D537(2);; # HANGUL SYLLABLE PHIEUPH YI CHIEUCH +U+D538(2);; # HANGUL SYLLABLE PHIEUPH YI KHIEUKH +U+D539(2);; # HANGUL SYLLABLE PHIEUPH YI THIEUTH +U+D53A(2);; # HANGUL SYLLABLE PHIEUPH YI PHIEUPH +U+D53B(2);; # HANGUL SYLLABLE PHIEUPH YI HIEUH +U+D53C(2);; # HANGUL SYLLABLE PHIEUPH I * +U+D53D(2);; # HANGUL SYLLABLE PHIEUPH I KIYEOK * +U+D53E(2);; # HANGUL SYLLABLE PHIEUPH I SSANGKIYEOK +U+D53F(2);; # HANGUL SYLLABLE PHIEUPH I KIYEOKSIOS +U+D540(2);; # HANGUL SYLLABLE PHIEUPH I NIEUN * +U+D541(2);; # HANGUL SYLLABLE PHIEUPH I NIEUNCIEUC +U+D542(2);; # HANGUL SYLLABLE PHIEUPH I NIEUNHIEUH +U+D543(2);; # HANGUL SYLLABLE PHIEUPH I TIKEUT +U+D544(2);; # HANGUL SYLLABLE PHIEUPH I RIEUL * +U+D545(2);; # HANGUL SYLLABLE PHIEUPH I RIEULKIYEOK +U+D546(2);; # HANGUL SYLLABLE PHIEUPH I RIEULMIEUM +U+D547(2);; # HANGUL SYLLABLE PHIEUPH I RIEULPIEUP +U+D548(2);; # HANGUL SYLLABLE PHIEUPH I RIEULSIOS +U+D549(2);; # HANGUL SYLLABLE PHIEUPH I RIEULTHIEUTH +U+D54A(2);; # HANGUL SYLLABLE PHIEUPH I RIEULPHIEUPH +U+D54B(2);; # HANGUL SYLLABLE PHIEUPH I RIEULHIEUH +U+D54C(2);; # HANGUL SYLLABLE PHIEUPH I MIEUM * +U+D54D(2);; # HANGUL SYLLABLE PHIEUPH I PIEUP * +U+D54E(2);; # HANGUL SYLLABLE PHIEUPH I PIEUPSIOS +U+D54F(2);; # HANGUL SYLLABLE PHIEUPH I SIOS * +U+D550(2);; # HANGUL SYLLABLE PHIEUPH I SSANGSIOS +U+D551(2);; # HANGUL SYLLABLE PHIEUPH I IEUNG * +U+D552(2);; # HANGUL SYLLABLE PHIEUPH I CIEUC +U+D553(2);; # HANGUL SYLLABLE PHIEUPH I CHIEUCH +U+D554(2);; # HANGUL SYLLABLE PHIEUPH I KHIEUKH +U+D555(2);; # HANGUL SYLLABLE PHIEUPH I THIEUTH +U+D556(2);; # HANGUL SYLLABLE PHIEUPH I PHIEUPH +U+D557(2);; # HANGUL SYLLABLE PHIEUPH I HIEUH +U+D558(2);; # HANGUL SYLLABLE HIEUH A * +U+D559(2);; # HANGUL SYLLABLE HIEUH A KIYEOK * +U+D55A(2);; # HANGUL SYLLABLE HIEUH A SSANGKIYEOK +U+D55B(2);; # HANGUL SYLLABLE HIEUH A KIYEOKSIOS +U+D55C(2);; # HANGUL SYLLABLE HIEUH A NIEUN * +U+D55D(2);; # HANGUL SYLLABLE HIEUH A NIEUNCIEUC +U+D55E(2);; # HANGUL SYLLABLE HIEUH A NIEUNHIEUH +U+D55F(2);; # HANGUL SYLLABLE HIEUH A TIKEUT +U+D560(2);; # HANGUL SYLLABLE HIEUH A RIEUL * +U+D561(2);; # HANGUL SYLLABLE HIEUH A RIEULKIYEOK +U+D562(2);; # HANGUL SYLLABLE HIEUH A RIEULMIEUM +U+D563(2);; # HANGUL SYLLABLE HIEUH A RIEULPIEUP +U+D564(2);; # HANGUL SYLLABLE HIEUH A RIEULSIOS +U+D565(2);; # HANGUL SYLLABLE HIEUH A RIEULTHIEUTH * +U+D566(2);; # HANGUL SYLLABLE HIEUH A RIEULPHIEUPH +U+D567(2);; # HANGUL SYLLABLE HIEUH A RIEULHIEUH +U+D568(2);; # HANGUL SYLLABLE HIEUH A MIEUM * +U+D569(2);; # HANGUL SYLLABLE HIEUH A PIEUP * +U+D56A(2);; # HANGUL SYLLABLE HIEUH A PIEUPSIOS +U+D56B(2);; # HANGUL SYLLABLE HIEUH A SIOS * +U+D56C(2);; # HANGUL SYLLABLE HIEUH A SSANGSIOS +U+D56D(2);; # HANGUL SYLLABLE HIEUH A IEUNG * +U+D56E(2);; # HANGUL SYLLABLE HIEUH A CIEUC +U+D56F(2);; # HANGUL SYLLABLE HIEUH A CHIEUCH +U+D570(2);; # HANGUL SYLLABLE HIEUH A KHIEUKH +U+D571(2);; # HANGUL SYLLABLE HIEUH A THIEUTH +U+D572(2);; # HANGUL SYLLABLE HIEUH A PHIEUPH +U+D573(2);; # HANGUL SYLLABLE HIEUH A HIEUH +U+D574(2);; # HANGUL SYLLABLE HIEUH AE * +U+D575(2);; # HANGUL SYLLABLE HIEUH AE KIYEOK * +U+D576(2);; # HANGUL SYLLABLE HIEUH AE SSANGKIYEOK +U+D577(2);; # HANGUL SYLLABLE HIEUH AE KIYEOKSIOS +U+D578(2);; # HANGUL SYLLABLE HIEUH AE NIEUN * +U+D579(2);; # HANGUL SYLLABLE HIEUH AE NIEUNCIEUC +U+D57A(2);; # HANGUL SYLLABLE HIEUH AE NIEUNHIEUH +U+D57B(2);; # HANGUL SYLLABLE HIEUH AE TIKEUT +U+D57C(2);; # HANGUL SYLLABLE HIEUH AE RIEUL * +U+D57D(2);; # HANGUL SYLLABLE HIEUH AE RIEULKIYEOK +U+D57E(2);; # HANGUL SYLLABLE HIEUH AE RIEULMIEUM +U+D57F(2);; # HANGUL SYLLABLE HIEUH AE RIEULPIEUP +U+D580(2);; # HANGUL SYLLABLE HIEUH AE RIEULSIOS +U+D581(2);; # HANGUL SYLLABLE HIEUH AE RIEULTHIEUTH +U+D582(2);; # HANGUL SYLLABLE HIEUH AE RIEULPHIEUPH +U+D583(2);; # HANGUL SYLLABLE HIEUH AE RIEULHIEUH +U+D584(2);; # HANGUL SYLLABLE HIEUH AE MIEUM * +U+D585(2);; # HANGUL SYLLABLE HIEUH AE PIEUP * +U+D586(2);; # HANGUL SYLLABLE HIEUH AE PIEUPSIOS +U+D587(2);; # HANGUL SYLLABLE HIEUH AE SIOS * +U+D588(2);; # HANGUL SYLLABLE HIEUH AE SSANGSIOS * +U+D589(2);; # HANGUL SYLLABLE HIEUH AE IEUNG * +U+D58A(2);; # HANGUL SYLLABLE HIEUH AE CIEUC +U+D58B(2);; # HANGUL SYLLABLE HIEUH AE CHIEUCH +U+D58C(2);; # HANGUL SYLLABLE HIEUH AE KHIEUKH +U+D58D(2);; # HANGUL SYLLABLE HIEUH AE THIEUTH +U+D58E(2);; # HANGUL SYLLABLE HIEUH AE PHIEUPH +U+D58F(2);; # HANGUL SYLLABLE HIEUH AE HIEUH +U+D590(2);; # HANGUL SYLLABLE HIEUH YA * +U+D591(2);; # HANGUL SYLLABLE HIEUH YA KIYEOK +U+D592(2);; # HANGUL SYLLABLE HIEUH YA SSANGKIYEOK +U+D593(2);; # HANGUL SYLLABLE HIEUH YA KIYEOKSIOS +U+D594(2);; # HANGUL SYLLABLE HIEUH YA NIEUN +U+D595(2);; # HANGUL SYLLABLE HIEUH YA NIEUNCIEUC +U+D596(2);; # HANGUL SYLLABLE HIEUH YA NIEUNHIEUH +U+D597(2);; # HANGUL SYLLABLE HIEUH YA TIKEUT +U+D598(2);; # HANGUL SYLLABLE HIEUH YA RIEUL +U+D599(2);; # HANGUL SYLLABLE HIEUH YA RIEULKIYEOK +U+D59A(2);; # HANGUL SYLLABLE HIEUH YA RIEULMIEUM +U+D59B(2);; # HANGUL SYLLABLE HIEUH YA RIEULPIEUP +U+D59C(2);; # HANGUL SYLLABLE HIEUH YA RIEULSIOS +U+D59D(2);; # HANGUL SYLLABLE HIEUH YA RIEULTHIEUTH +U+D59E(2);; # HANGUL SYLLABLE HIEUH YA RIEULPHIEUPH +U+D59F(2);; # HANGUL SYLLABLE HIEUH YA RIEULHIEUH +U+D5A0(2);; # HANGUL SYLLABLE HIEUH YA MIEUM +U+D5A1(2);; # HANGUL SYLLABLE HIEUH YA PIEUP +U+D5A2(2);; # HANGUL SYLLABLE HIEUH YA PIEUPSIOS +U+D5A3(2);; # HANGUL SYLLABLE HIEUH YA SIOS +U+D5A4(2);; # HANGUL SYLLABLE HIEUH YA SSANGSIOS +U+D5A5(2);; # HANGUL SYLLABLE HIEUH YA IEUNG * +U+D5A6(2);; # HANGUL SYLLABLE HIEUH YA CIEUC +U+D5A7(2);; # HANGUL SYLLABLE HIEUH YA CHIEUCH +U+D5A8(2);; # HANGUL SYLLABLE HIEUH YA KHIEUKH +U+D5A9(2);; # HANGUL SYLLABLE HIEUH YA THIEUTH +U+D5AA(2);; # HANGUL SYLLABLE HIEUH YA PHIEUPH +U+D5AB(2);; # HANGUL SYLLABLE HIEUH YA HIEUH +U+D5AC(2);; # HANGUL SYLLABLE HIEUH YAE +U+D5AD(2);; # HANGUL SYLLABLE HIEUH YAE KIYEOK +U+D5AE(2);; # HANGUL SYLLABLE HIEUH YAE SSANGKIYEOK +U+D5AF(2);; # HANGUL SYLLABLE HIEUH YAE KIYEOKSIOS +U+D5B0(2);; # HANGUL SYLLABLE HIEUH YAE NIEUN +U+D5B1(2);; # HANGUL SYLLABLE HIEUH YAE NIEUNCIEUC +U+D5B2(2);; # HANGUL SYLLABLE HIEUH YAE NIEUNHIEUH +U+D5B3(2);; # HANGUL SYLLABLE HIEUH YAE TIKEUT +U+D5B4(2);; # HANGUL SYLLABLE HIEUH YAE RIEUL +U+D5B5(2);; # HANGUL SYLLABLE HIEUH YAE RIEULKIYEOK +U+D5B6(2);; # HANGUL SYLLABLE HIEUH YAE RIEULMIEUM +U+D5B7(2);; # HANGUL SYLLABLE HIEUH YAE RIEULPIEUP +U+D5B8(2);; # HANGUL SYLLABLE HIEUH YAE RIEULSIOS +U+D5B9(2);; # HANGUL SYLLABLE HIEUH YAE RIEULTHIEUTH +U+D5BA(2);; # HANGUL SYLLABLE HIEUH YAE RIEULPHIEUPH +U+D5BB(2);; # HANGUL SYLLABLE HIEUH YAE RIEULHIEUH +U+D5BC(2);; # HANGUL SYLLABLE HIEUH YAE MIEUM +U+D5BD(2);; # HANGUL SYLLABLE HIEUH YAE PIEUP +U+D5BE(2);; # HANGUL SYLLABLE HIEUH YAE PIEUPSIOS +U+D5BF(2);; # HANGUL SYLLABLE HIEUH YAE SIOS +U+D5C0(2);; # HANGUL SYLLABLE HIEUH YAE SSANGSIOS +U+D5C1(2);; # HANGUL SYLLABLE HIEUH YAE IEUNG +U+D5C2(2);; # HANGUL SYLLABLE HIEUH YAE CIEUC +U+D5C3(2);; # HANGUL SYLLABLE HIEUH YAE CHIEUCH +U+D5C4(2);; # HANGUL SYLLABLE HIEUH YAE KHIEUKH +U+D5C5(2);; # HANGUL SYLLABLE HIEUH YAE THIEUTH +U+D5C6(2);; # HANGUL SYLLABLE HIEUH YAE PHIEUPH +U+D5C7(2);; # HANGUL SYLLABLE HIEUH YAE HIEUH +U+D5C8(2);; # HANGUL SYLLABLE HIEUH EO * +U+D5C9(2);; # HANGUL SYLLABLE HIEUH EO KIYEOK * +U+D5CA(2);; # HANGUL SYLLABLE HIEUH EO SSANGKIYEOK +U+D5CB(2);; # HANGUL SYLLABLE HIEUH EO KIYEOKSIOS +U+D5CC(2);; # HANGUL SYLLABLE HIEUH EO NIEUN * +U+D5CD(2);; # HANGUL SYLLABLE HIEUH EO NIEUNCIEUC +U+D5CE(2);; # HANGUL SYLLABLE HIEUH EO NIEUNHIEUH +U+D5CF(2);; # HANGUL SYLLABLE HIEUH EO TIKEUT +U+D5D0(2);; # HANGUL SYLLABLE HIEUH EO RIEUL * +U+D5D1(2);; # HANGUL SYLLABLE HIEUH EO RIEULKIYEOK +U+D5D2(2);; # HANGUL SYLLABLE HIEUH EO RIEULMIEUM * +U+D5D3(2);; # HANGUL SYLLABLE HIEUH EO RIEULPIEUP +U+D5D4(2);; # HANGUL SYLLABLE HIEUH EO RIEULSIOS +U+D5D5(2);; # HANGUL SYLLABLE HIEUH EO RIEULTHIEUTH +U+D5D6(2);; # HANGUL SYLLABLE HIEUH EO RIEULPHIEUPH +U+D5D7(2);; # HANGUL SYLLABLE HIEUH EO RIEULHIEUH +U+D5D8(2);; # HANGUL SYLLABLE HIEUH EO MIEUM * +U+D5D9(2);; # HANGUL SYLLABLE HIEUH EO PIEUP * +U+D5DA(2);; # HANGUL SYLLABLE HIEUH EO PIEUPSIOS +U+D5DB(2);; # HANGUL SYLLABLE HIEUH EO SIOS * +U+D5DC(2);; # HANGUL SYLLABLE HIEUH EO SSANGSIOS +U+D5DD(2);; # HANGUL SYLLABLE HIEUH EO IEUNG * +U+D5DE(2);; # HANGUL SYLLABLE HIEUH EO CIEUC +U+D5DF(2);; # HANGUL SYLLABLE HIEUH EO CHIEUCH +U+D5E0(2);; # HANGUL SYLLABLE HIEUH EO KHIEUKH +U+D5E1(2);; # HANGUL SYLLABLE HIEUH EO THIEUTH +U+D5E2(2);; # HANGUL SYLLABLE HIEUH EO PHIEUPH +U+D5E3(2);; # HANGUL SYLLABLE HIEUH EO HIEUH +U+D5E4(2);; # HANGUL SYLLABLE HIEUH E * +U+D5E5(2);; # HANGUL SYLLABLE HIEUH E KIYEOK * +U+D5E6(2);; # HANGUL SYLLABLE HIEUH E SSANGKIYEOK +U+D5E7(2);; # HANGUL SYLLABLE HIEUH E KIYEOKSIOS +U+D5E8(2);; # HANGUL SYLLABLE HIEUH E NIEUN * +U+D5E9(2);; # HANGUL SYLLABLE HIEUH E NIEUNCIEUC +U+D5EA(2);; # HANGUL SYLLABLE HIEUH E NIEUNHIEUH +U+D5EB(2);; # HANGUL SYLLABLE HIEUH E TIKEUT +U+D5EC(2);; # HANGUL SYLLABLE HIEUH E RIEUL * +U+D5ED(2);; # HANGUL SYLLABLE HIEUH E RIEULKIYEOK +U+D5EE(2);; # HANGUL SYLLABLE HIEUH E RIEULMIEUM +U+D5EF(2);; # HANGUL SYLLABLE HIEUH E RIEULPIEUP +U+D5F0(2);; # HANGUL SYLLABLE HIEUH E RIEULSIOS +U+D5F1(2);; # HANGUL SYLLABLE HIEUH E RIEULTHIEUTH +U+D5F2(2);; # HANGUL SYLLABLE HIEUH E RIEULPHIEUPH +U+D5F3(2);; # HANGUL SYLLABLE HIEUH E RIEULHIEUH +U+D5F4(2);; # HANGUL SYLLABLE HIEUH E MIEUM * +U+D5F5(2);; # HANGUL SYLLABLE HIEUH E PIEUP * +U+D5F6(2);; # HANGUL SYLLABLE HIEUH E PIEUPSIOS +U+D5F7(2);; # HANGUL SYLLABLE HIEUH E SIOS * +U+D5F8(2);; # HANGUL SYLLABLE HIEUH E SSANGSIOS +U+D5F9(2);; # HANGUL SYLLABLE HIEUH E IEUNG * +U+D5FA(2);; # HANGUL SYLLABLE HIEUH E CIEUC +U+D5FB(2);; # HANGUL SYLLABLE HIEUH E CHIEUCH +U+D5FC(2);; # HANGUL SYLLABLE HIEUH E KHIEUKH +U+D5FD(2);; # HANGUL SYLLABLE HIEUH E THIEUTH +U+D5FE(2);; # HANGUL SYLLABLE HIEUH E PHIEUPH +U+D5FF(2);; # HANGUL SYLLABLE HIEUH E HIEUH +U+D600(2);; # HANGUL SYLLABLE HIEUH YEO * +U+D601(2);; # HANGUL SYLLABLE HIEUH YEO KIYEOK * +U+D602(2);; # HANGUL SYLLABLE HIEUH YEO SSANGKIYEOK +U+D603(2);; # HANGUL SYLLABLE HIEUH YEO KIYEOKSIOS +U+D604(2);; # HANGUL SYLLABLE HIEUH YEO NIEUN * +U+D605(2);; # HANGUL SYLLABLE HIEUH YEO NIEUNCIEUC +U+D606(2);; # HANGUL SYLLABLE HIEUH YEO NIEUNHIEUH +U+D607(2);; # HANGUL SYLLABLE HIEUH YEO TIKEUT +U+D608(2);; # HANGUL SYLLABLE HIEUH YEO RIEUL * +U+D609(2);; # HANGUL SYLLABLE HIEUH YEO RIEULKIYEOK +U+D60A(2);; # HANGUL SYLLABLE HIEUH YEO RIEULMIEUM +U+D60B(2);; # HANGUL SYLLABLE HIEUH YEO RIEULPIEUP +U+D60C(2);; # HANGUL SYLLABLE HIEUH YEO RIEULSIOS +U+D60D(2);; # HANGUL SYLLABLE HIEUH YEO RIEULTHIEUTH +U+D60E(2);; # HANGUL SYLLABLE HIEUH YEO RIEULPHIEUPH +U+D60F(2);; # HANGUL SYLLABLE HIEUH YEO RIEULHIEUH +U+D610(2);; # HANGUL SYLLABLE HIEUH YEO MIEUM * +U+D611(2);; # HANGUL SYLLABLE HIEUH YEO PIEUP * +U+D612(2);; # HANGUL SYLLABLE HIEUH YEO PIEUPSIOS +U+D613(2);; # HANGUL SYLLABLE HIEUH YEO SIOS * +U+D614(2);; # HANGUL SYLLABLE HIEUH YEO SSANGSIOS * +U+D615(2);; # HANGUL SYLLABLE HIEUH YEO IEUNG * +U+D616(2);; # HANGUL SYLLABLE HIEUH YEO CIEUC +U+D617(2);; # HANGUL SYLLABLE HIEUH YEO CHIEUCH +U+D618(2);; # HANGUL SYLLABLE HIEUH YEO KHIEUKH +U+D619(2);; # HANGUL SYLLABLE HIEUH YEO THIEUTH +U+D61A(2);; # HANGUL SYLLABLE HIEUH YEO PHIEUPH +U+D61B(2);; # HANGUL SYLLABLE HIEUH YEO HIEUH +U+D61C(2);; # HANGUL SYLLABLE HIEUH YE * +U+D61D(2);; # HANGUL SYLLABLE HIEUH YE KIYEOK +U+D61E(2);; # HANGUL SYLLABLE HIEUH YE SSANGKIYEOK +U+D61F(2);; # HANGUL SYLLABLE HIEUH YE KIYEOKSIOS +U+D620(2);; # HANGUL SYLLABLE HIEUH YE NIEUN * +U+D621(2);; # HANGUL SYLLABLE HIEUH YE NIEUNCIEUC +U+D622(2);; # HANGUL SYLLABLE HIEUH YE NIEUNHIEUH +U+D623(2);; # HANGUL SYLLABLE HIEUH YE TIKEUT +U+D624(2);; # HANGUL SYLLABLE HIEUH YE RIEUL * +U+D625(2);; # HANGUL SYLLABLE HIEUH YE RIEULKIYEOK +U+D626(2);; # HANGUL SYLLABLE HIEUH YE RIEULMIEUM +U+D627(2);; # HANGUL SYLLABLE HIEUH YE RIEULPIEUP +U+D628(2);; # HANGUL SYLLABLE HIEUH YE RIEULSIOS +U+D629(2);; # HANGUL SYLLABLE HIEUH YE RIEULTHIEUTH +U+D62A(2);; # HANGUL SYLLABLE HIEUH YE RIEULPHIEUPH +U+D62B(2);; # HANGUL SYLLABLE HIEUH YE RIEULHIEUH +U+D62C(2);; # HANGUL SYLLABLE HIEUH YE MIEUM +U+D62D(2);; # HANGUL SYLLABLE HIEUH YE PIEUP * +U+D62E(2);; # HANGUL SYLLABLE HIEUH YE PIEUPSIOS +U+D62F(2);; # HANGUL SYLLABLE HIEUH YE SIOS +U+D630(2);; # HANGUL SYLLABLE HIEUH YE SSANGSIOS +U+D631(2);; # HANGUL SYLLABLE HIEUH YE IEUNG +U+D632(2);; # HANGUL SYLLABLE HIEUH YE CIEUC +U+D633(2);; # HANGUL SYLLABLE HIEUH YE CHIEUCH +U+D634(2);; # HANGUL SYLLABLE HIEUH YE KHIEUKH +U+D635(2);; # HANGUL SYLLABLE HIEUH YE THIEUTH +U+D636(2);; # HANGUL SYLLABLE HIEUH YE PHIEUPH +U+D637(2);; # HANGUL SYLLABLE HIEUH YE HIEUH +U+D638(2);; # HANGUL SYLLABLE HIEUH O * +U+D639(2);; # HANGUL SYLLABLE HIEUH O KIYEOK * +U+D63A(2);; # HANGUL SYLLABLE HIEUH O SSANGKIYEOK +U+D63B(2);; # HANGUL SYLLABLE HIEUH O KIYEOKSIOS +U+D63C(2);; # HANGUL SYLLABLE HIEUH O NIEUN * +U+D63D(2);; # HANGUL SYLLABLE HIEUH O NIEUNCIEUC +U+D63E(2);; # HANGUL SYLLABLE HIEUH O NIEUNHIEUH +U+D63F(2);; # HANGUL SYLLABLE HIEUH O TIKEUT +U+D640(2);; # HANGUL SYLLABLE HIEUH O RIEUL * +U+D641(2);; # HANGUL SYLLABLE HIEUH O RIEULKIYEOK +U+D642(2);; # HANGUL SYLLABLE HIEUH O RIEULMIEUM +U+D643(2);; # HANGUL SYLLABLE HIEUH O RIEULPIEUP +U+D644(2);; # HANGUL SYLLABLE HIEUH O RIEULSIOS +U+D645(2);; # HANGUL SYLLABLE HIEUH O RIEULTHIEUTH * +U+D646(2);; # HANGUL SYLLABLE HIEUH O RIEULPHIEUPH +U+D647(2);; # HANGUL SYLLABLE HIEUH O RIEULHIEUH +U+D648(2);; # HANGUL SYLLABLE HIEUH O MIEUM * +U+D649(2);; # HANGUL SYLLABLE HIEUH O PIEUP * +U+D64A(2);; # HANGUL SYLLABLE HIEUH O PIEUPSIOS +U+D64B(2);; # HANGUL SYLLABLE HIEUH O SIOS * +U+D64C(2);; # HANGUL SYLLABLE HIEUH O SSANGSIOS +U+D64D(2);; # HANGUL SYLLABLE HIEUH O IEUNG * +U+D64E(2);; # HANGUL SYLLABLE HIEUH O CIEUC +U+D64F(2);; # HANGUL SYLLABLE HIEUH O CHIEUCH +U+D650(2);; # HANGUL SYLLABLE HIEUH O KHIEUKH +U+D651(2);; # HANGUL SYLLABLE HIEUH O THIEUTH * +U+D652(2);; # HANGUL SYLLABLE HIEUH O PHIEUPH +U+D653(2);; # HANGUL SYLLABLE HIEUH O HIEUH +U+D654(2);; # HANGUL SYLLABLE HIEUH WA * +U+D655(2);; # HANGUL SYLLABLE HIEUH WA KIYEOK * +U+D656(2);; # HANGUL SYLLABLE HIEUH WA SSANGKIYEOK +U+D657(2);; # HANGUL SYLLABLE HIEUH WA KIYEOKSIOS +U+D658(2);; # HANGUL SYLLABLE HIEUH WA NIEUN * +U+D659(2);; # HANGUL SYLLABLE HIEUH WA NIEUNCIEUC +U+D65A(2);; # HANGUL SYLLABLE HIEUH WA NIEUNHIEUH +U+D65B(2);; # HANGUL SYLLABLE HIEUH WA TIKEUT +U+D65C(2);; # HANGUL SYLLABLE HIEUH WA RIEUL * +U+D65D(2);; # HANGUL SYLLABLE HIEUH WA RIEULKIYEOK +U+D65E(2);; # HANGUL SYLLABLE HIEUH WA RIEULMIEUM +U+D65F(2);; # HANGUL SYLLABLE HIEUH WA RIEULPIEUP +U+D660(2);; # HANGUL SYLLABLE HIEUH WA RIEULSIOS +U+D661(2);; # HANGUL SYLLABLE HIEUH WA RIEULTHIEUTH +U+D662(2);; # HANGUL SYLLABLE HIEUH WA RIEULPHIEUPH +U+D663(2);; # HANGUL SYLLABLE HIEUH WA RIEULHIEUH +U+D664(2);; # HANGUL SYLLABLE HIEUH WA MIEUM +U+D665(2);; # HANGUL SYLLABLE HIEUH WA PIEUP +U+D666(2);; # HANGUL SYLLABLE HIEUH WA PIEUPSIOS +U+D667(2);; # HANGUL SYLLABLE HIEUH WA SIOS * +U+D668(2);; # HANGUL SYLLABLE HIEUH WA SSANGSIOS +U+D669(2);; # HANGUL SYLLABLE HIEUH WA IEUNG * +U+D66A(2);; # HANGUL SYLLABLE HIEUH WA CIEUC +U+D66B(2);; # HANGUL SYLLABLE HIEUH WA CHIEUCH +U+D66C(2);; # HANGUL SYLLABLE HIEUH WA KHIEUKH +U+D66D(2);; # HANGUL SYLLABLE HIEUH WA THIEUTH +U+D66E(2);; # HANGUL SYLLABLE HIEUH WA PHIEUPH +U+D66F(2);; # HANGUL SYLLABLE HIEUH WA HIEUH +U+D670(2);; # HANGUL SYLLABLE HIEUH WAE * +U+D671(2);; # HANGUL SYLLABLE HIEUH WAE KIYEOK * +U+D672(2);; # HANGUL SYLLABLE HIEUH WAE SSANGKIYEOK +U+D673(2);; # HANGUL SYLLABLE HIEUH WAE KIYEOKSIOS +U+D674(2);; # HANGUL SYLLABLE HIEUH WAE NIEUN * +U+D675(2);; # HANGUL SYLLABLE HIEUH WAE NIEUNCIEUC +U+D676(2);; # HANGUL SYLLABLE HIEUH WAE NIEUNHIEUH +U+D677(2);; # HANGUL SYLLABLE HIEUH WAE TIKEUT +U+D678(2);; # HANGUL SYLLABLE HIEUH WAE RIEUL +U+D679(2);; # HANGUL SYLLABLE HIEUH WAE RIEULKIYEOK +U+D67A(2);; # HANGUL SYLLABLE HIEUH WAE RIEULMIEUM +U+D67B(2);; # HANGUL SYLLABLE HIEUH WAE RIEULPIEUP +U+D67C(2);; # HANGUL SYLLABLE HIEUH WAE RIEULSIOS +U+D67D(2);; # HANGUL SYLLABLE HIEUH WAE RIEULTHIEUTH +U+D67E(2);; # HANGUL SYLLABLE HIEUH WAE RIEULPHIEUPH +U+D67F(2);; # HANGUL SYLLABLE HIEUH WAE RIEULHIEUH +U+D680(2);; # HANGUL SYLLABLE HIEUH WAE MIEUM +U+D681(2);; # HANGUL SYLLABLE HIEUH WAE PIEUP +U+D682(2);; # HANGUL SYLLABLE HIEUH WAE PIEUPSIOS +U+D683(2);; # HANGUL SYLLABLE HIEUH WAE SIOS * +U+D684(2);; # HANGUL SYLLABLE HIEUH WAE SSANGSIOS +U+D685(2);; # HANGUL SYLLABLE HIEUH WAE IEUNG * +U+D686(2);; # HANGUL SYLLABLE HIEUH WAE CIEUC +U+D687(2);; # HANGUL SYLLABLE HIEUH WAE CHIEUCH +U+D688(2);; # HANGUL SYLLABLE HIEUH WAE KHIEUKH +U+D689(2);; # HANGUL SYLLABLE HIEUH WAE THIEUTH +U+D68A(2);; # HANGUL SYLLABLE HIEUH WAE PHIEUPH +U+D68B(2);; # HANGUL SYLLABLE HIEUH WAE HIEUH +U+D68C(2);; # HANGUL SYLLABLE HIEUH OE * +U+D68D(2);; # HANGUL SYLLABLE HIEUH OE KIYEOK * +U+D68E(2);; # HANGUL SYLLABLE HIEUH OE SSANGKIYEOK +U+D68F(2);; # HANGUL SYLLABLE HIEUH OE KIYEOKSIOS +U+D690(2);; # HANGUL SYLLABLE HIEUH OE NIEUN * +U+D691(2);; # HANGUL SYLLABLE HIEUH OE NIEUNCIEUC +U+D692(2);; # HANGUL SYLLABLE HIEUH OE NIEUNHIEUH +U+D693(2);; # HANGUL SYLLABLE HIEUH OE TIKEUT +U+D694(2);; # HANGUL SYLLABLE HIEUH OE RIEUL * +U+D695(2);; # HANGUL SYLLABLE HIEUH OE RIEULKIYEOK +U+D696(2);; # HANGUL SYLLABLE HIEUH OE RIEULMIEUM +U+D697(2);; # HANGUL SYLLABLE HIEUH OE RIEULPIEUP +U+D698(2);; # HANGUL SYLLABLE HIEUH OE RIEULSIOS +U+D699(2);; # HANGUL SYLLABLE HIEUH OE RIEULTHIEUTH +U+D69A(2);; # HANGUL SYLLABLE HIEUH OE RIEULPHIEUPH +U+D69B(2);; # HANGUL SYLLABLE HIEUH OE RIEULHIEUH +U+D69C(2);; # HANGUL SYLLABLE HIEUH OE MIEUM +U+D69D(2);; # HANGUL SYLLABLE HIEUH OE PIEUP * +U+D69E(2);; # HANGUL SYLLABLE HIEUH OE PIEUPSIOS +U+D69F(2);; # HANGUL SYLLABLE HIEUH OE SIOS * +U+D6A0(2);; # HANGUL SYLLABLE HIEUH OE SSANGSIOS +U+D6A1(2);; # HANGUL SYLLABLE HIEUH OE IEUNG * +U+D6A2(2);; # HANGUL SYLLABLE HIEUH OE CIEUC +U+D6A3(2);; # HANGUL SYLLABLE HIEUH OE CHIEUCH +U+D6A4(2);; # HANGUL SYLLABLE HIEUH OE KHIEUKH +U+D6A5(2);; # HANGUL SYLLABLE HIEUH OE THIEUTH +U+D6A6(2);; # HANGUL SYLLABLE HIEUH OE PHIEUPH +U+D6A7(2);; # HANGUL SYLLABLE HIEUH OE HIEUH +U+D6A8(2);; # HANGUL SYLLABLE HIEUH YO * +U+D6A9(2);; # HANGUL SYLLABLE HIEUH YO KIYEOK +U+D6AA(2);; # HANGUL SYLLABLE HIEUH YO SSANGKIYEOK +U+D6AB(2);; # HANGUL SYLLABLE HIEUH YO KIYEOKSIOS +U+D6AC(2);; # HANGUL SYLLABLE HIEUH YO NIEUN * +U+D6AD(2);; # HANGUL SYLLABLE HIEUH YO NIEUNCIEUC +U+D6AE(2);; # HANGUL SYLLABLE HIEUH YO NIEUNHIEUH +U+D6AF(2);; # HANGUL SYLLABLE HIEUH YO TIKEUT +U+D6B0(2);; # HANGUL SYLLABLE HIEUH YO RIEUL * +U+D6B1(2);; # HANGUL SYLLABLE HIEUH YO RIEULKIYEOK +U+D6B2(2);; # HANGUL SYLLABLE HIEUH YO RIEULMIEUM +U+D6B3(2);; # HANGUL SYLLABLE HIEUH YO RIEULPIEUP +U+D6B4(2);; # HANGUL SYLLABLE HIEUH YO RIEULSIOS +U+D6B5(2);; # HANGUL SYLLABLE HIEUH YO RIEULTHIEUTH +U+D6B6(2);; # HANGUL SYLLABLE HIEUH YO RIEULPHIEUPH +U+D6B7(2);; # HANGUL SYLLABLE HIEUH YO RIEULHIEUH +U+D6B8(2);; # HANGUL SYLLABLE HIEUH YO MIEUM +U+D6B9(2);; # HANGUL SYLLABLE HIEUH YO PIEUP * +U+D6BA(2);; # HANGUL SYLLABLE HIEUH YO PIEUPSIOS +U+D6BB(2);; # HANGUL SYLLABLE HIEUH YO SIOS * +U+D6BC(2);; # HANGUL SYLLABLE HIEUH YO SSANGSIOS +U+D6BD(2);; # HANGUL SYLLABLE HIEUH YO IEUNG +U+D6BE(2);; # HANGUL SYLLABLE HIEUH YO CIEUC +U+D6BF(2);; # HANGUL SYLLABLE HIEUH YO CHIEUCH +U+D6C0(2);; # HANGUL SYLLABLE HIEUH YO KHIEUKH +U+D6C1(2);; # HANGUL SYLLABLE HIEUH YO THIEUTH +U+D6C2(2);; # HANGUL SYLLABLE HIEUH YO PHIEUPH +U+D6C3(2);; # HANGUL SYLLABLE HIEUH YO HIEUH +U+D6C4(2);; # HANGUL SYLLABLE HIEUH U * +U+D6C5(2);; # HANGUL SYLLABLE HIEUH U KIYEOK * +U+D6C6(2);; # HANGUL SYLLABLE HIEUH U SSANGKIYEOK +U+D6C7(2);; # HANGUL SYLLABLE HIEUH U KIYEOKSIOS +U+D6C8(2);; # HANGUL SYLLABLE HIEUH U NIEUN * +U+D6C9(2);; # HANGUL SYLLABLE HIEUH U NIEUNCIEUC +U+D6CA(2);; # HANGUL SYLLABLE HIEUH U NIEUNHIEUH +U+D6CB(2);; # HANGUL SYLLABLE HIEUH U TIKEUT +U+D6CC(2);; # HANGUL SYLLABLE HIEUH U RIEUL * +U+D6CD(2);; # HANGUL SYLLABLE HIEUH U RIEULKIYEOK +U+D6CE(2);; # HANGUL SYLLABLE HIEUH U RIEULMIEUM +U+D6CF(2);; # HANGUL SYLLABLE HIEUH U RIEULPIEUP +U+D6D0(2);; # HANGUL SYLLABLE HIEUH U RIEULSIOS +U+D6D1(2);; # HANGUL SYLLABLE HIEUH U RIEULTHIEUTH * +U+D6D2(2);; # HANGUL SYLLABLE HIEUH U RIEULPHIEUPH +U+D6D3(2);; # HANGUL SYLLABLE HIEUH U RIEULHIEUH +U+D6D4(2);; # HANGUL SYLLABLE HIEUH U MIEUM * +U+D6D5(2);; # HANGUL SYLLABLE HIEUH U PIEUP +U+D6D6(2);; # HANGUL SYLLABLE HIEUH U PIEUPSIOS +U+D6D7(2);; # HANGUL SYLLABLE HIEUH U SIOS * +U+D6D8(2);; # HANGUL SYLLABLE HIEUH U SSANGSIOS +U+D6D9(2);; # HANGUL SYLLABLE HIEUH U IEUNG * +U+D6DA(2);; # HANGUL SYLLABLE HIEUH U CIEUC +U+D6DB(2);; # HANGUL SYLLABLE HIEUH U CHIEUCH +U+D6DC(2);; # HANGUL SYLLABLE HIEUH U KHIEUKH +U+D6DD(2);; # HANGUL SYLLABLE HIEUH U THIEUTH +U+D6DE(2);; # HANGUL SYLLABLE HIEUH U PHIEUPH +U+D6DF(2);; # HANGUL SYLLABLE HIEUH U HIEUH +U+D6E0(2);; # HANGUL SYLLABLE HIEUH WEO * +U+D6E1(2);; # HANGUL SYLLABLE HIEUH WEO KIYEOK +U+D6E2(2);; # HANGUL SYLLABLE HIEUH WEO SSANGKIYEOK +U+D6E3(2);; # HANGUL SYLLABLE HIEUH WEO KIYEOKSIOS +U+D6E4(2);; # HANGUL SYLLABLE HIEUH WEO NIEUN * +U+D6E5(2);; # HANGUL SYLLABLE HIEUH WEO NIEUNCIEUC +U+D6E6(2);; # HANGUL SYLLABLE HIEUH WEO NIEUNHIEUH +U+D6E7(2);; # HANGUL SYLLABLE HIEUH WEO TIKEUT +U+D6E8(2);; # HANGUL SYLLABLE HIEUH WEO RIEUL * +U+D6E9(2);; # HANGUL SYLLABLE HIEUH WEO RIEULKIYEOK +U+D6EA(2);; # HANGUL SYLLABLE HIEUH WEO RIEULMIEUM +U+D6EB(2);; # HANGUL SYLLABLE HIEUH WEO RIEULPIEUP +U+D6EC(2);; # HANGUL SYLLABLE HIEUH WEO RIEULSIOS +U+D6ED(2);; # HANGUL SYLLABLE HIEUH WEO RIEULTHIEUTH +U+D6EE(2);; # HANGUL SYLLABLE HIEUH WEO RIEULPHIEUPH +U+D6EF(2);; # HANGUL SYLLABLE HIEUH WEO RIEULHIEUH +U+D6F0(2);; # HANGUL SYLLABLE HIEUH WEO MIEUM * +U+D6F1(2);; # HANGUL SYLLABLE HIEUH WEO PIEUP +U+D6F2(2);; # HANGUL SYLLABLE HIEUH WEO PIEUPSIOS +U+D6F3(2);; # HANGUL SYLLABLE HIEUH WEO SIOS +U+D6F4(2);; # HANGUL SYLLABLE HIEUH WEO SSANGSIOS +U+D6F5(2);; # HANGUL SYLLABLE HIEUH WEO IEUNG * +U+D6F6(2);; # HANGUL SYLLABLE HIEUH WEO CIEUC +U+D6F7(2);; # HANGUL SYLLABLE HIEUH WEO CHIEUCH +U+D6F8(2);; # HANGUL SYLLABLE HIEUH WEO KHIEUKH +U+D6F9(2);; # HANGUL SYLLABLE HIEUH WEO THIEUTH +U+D6FA(2);; # HANGUL SYLLABLE HIEUH WEO PHIEUPH +U+D6FB(2);; # HANGUL SYLLABLE HIEUH WEO HIEUH +U+D6FC(2);; # HANGUL SYLLABLE HIEUH WE * +U+D6FD(2);; # HANGUL SYLLABLE HIEUH WE KIYEOK * +U+D6FE(2);; # HANGUL SYLLABLE HIEUH WE SSANGKIYEOK +U+D6FF(2);; # HANGUL SYLLABLE HIEUH WE KIYEOKSIOS +U+D700(2);; # HANGUL SYLLABLE HIEUH WE NIEUN * +U+D701(2);; # HANGUL SYLLABLE HIEUH WE NIEUNCIEUC +U+D702(2);; # HANGUL SYLLABLE HIEUH WE NIEUNHIEUH +U+D703(2);; # HANGUL SYLLABLE HIEUH WE TIKEUT +U+D704(2);; # HANGUL SYLLABLE HIEUH WE RIEUL * +U+D705(2);; # HANGUL SYLLABLE HIEUH WE RIEULKIYEOK +U+D706(2);; # HANGUL SYLLABLE HIEUH WE RIEULMIEUM +U+D707(2);; # HANGUL SYLLABLE HIEUH WE RIEULPIEUP +U+D708(2);; # HANGUL SYLLABLE HIEUH WE RIEULSIOS +U+D709(2);; # HANGUL SYLLABLE HIEUH WE RIEULTHIEUTH +U+D70A(2);; # HANGUL SYLLABLE HIEUH WE RIEULPHIEUPH +U+D70B(2);; # HANGUL SYLLABLE HIEUH WE RIEULHIEUH +U+D70C(2);; # HANGUL SYLLABLE HIEUH WE MIEUM +U+D70D(2);; # HANGUL SYLLABLE HIEUH WE PIEUP +U+D70E(2);; # HANGUL SYLLABLE HIEUH WE PIEUPSIOS +U+D70F(2);; # HANGUL SYLLABLE HIEUH WE SIOS +U+D710(2);; # HANGUL SYLLABLE HIEUH WE SSANGSIOS +U+D711(2);; # HANGUL SYLLABLE HIEUH WE IEUNG * +U+D712(2);; # HANGUL SYLLABLE HIEUH WE CIEUC +U+D713(2);; # HANGUL SYLLABLE HIEUH WE CHIEUCH +U+D714(2);; # HANGUL SYLLABLE HIEUH WE KHIEUKH +U+D715(2);; # HANGUL SYLLABLE HIEUH WE THIEUTH +U+D716(2);; # HANGUL SYLLABLE HIEUH WE PHIEUPH +U+D717(2);; # HANGUL SYLLABLE HIEUH WE HIEUH +U+D718(2);; # HANGUL SYLLABLE HIEUH WI * +U+D719(2);; # HANGUL SYLLABLE HIEUH WI KIYEOK * +U+D71A(2);; # HANGUL SYLLABLE HIEUH WI SSANGKIYEOK +U+D71B(2);; # HANGUL SYLLABLE HIEUH WI KIYEOKSIOS +U+D71C(2);; # HANGUL SYLLABLE HIEUH WI NIEUN * +U+D71D(2);; # HANGUL SYLLABLE HIEUH WI NIEUNCIEUC +U+D71E(2);; # HANGUL SYLLABLE HIEUH WI NIEUNHIEUH +U+D71F(2);; # HANGUL SYLLABLE HIEUH WI TIKEUT +U+D720(2);; # HANGUL SYLLABLE HIEUH WI RIEUL * +U+D721(2);; # HANGUL SYLLABLE HIEUH WI RIEULKIYEOK +U+D722(2);; # HANGUL SYLLABLE HIEUH WI RIEULMIEUM +U+D723(2);; # HANGUL SYLLABLE HIEUH WI RIEULPIEUP +U+D724(2);; # HANGUL SYLLABLE HIEUH WI RIEULSIOS +U+D725(2);; # HANGUL SYLLABLE HIEUH WI RIEULTHIEUTH +U+D726(2);; # HANGUL SYLLABLE HIEUH WI RIEULPHIEUPH +U+D727(2);; # HANGUL SYLLABLE HIEUH WI RIEULHIEUH +U+D728(2);; # HANGUL SYLLABLE HIEUH WI MIEUM * +U+D729(2);; # HANGUL SYLLABLE HIEUH WI PIEUP * +U+D72A(2);; # HANGUL SYLLABLE HIEUH WI PIEUPSIOS +U+D72B(2);; # HANGUL SYLLABLE HIEUH WI SIOS * +U+D72C(2);; # HANGUL SYLLABLE HIEUH WI SSANGSIOS +U+D72D(2);; # HANGUL SYLLABLE HIEUH WI IEUNG * +U+D72E(2);; # HANGUL SYLLABLE HIEUH WI CIEUC +U+D72F(2);; # HANGUL SYLLABLE HIEUH WI CHIEUCH +U+D730(2);; # HANGUL SYLLABLE HIEUH WI KHIEUKH +U+D731(2);; # HANGUL SYLLABLE HIEUH WI THIEUTH +U+D732(2);; # HANGUL SYLLABLE HIEUH WI PHIEUPH +U+D733(2);; # HANGUL SYLLABLE HIEUH WI HIEUH +U+D734(2);; # HANGUL SYLLABLE HIEUH YU * +U+D735(2);; # HANGUL SYLLABLE HIEUH YU KIYEOK * +U+D736(2);; # HANGUL SYLLABLE HIEUH YU SSANGKIYEOK +U+D737(2);; # HANGUL SYLLABLE HIEUH YU KIYEOKSIOS +U+D738(2);; # HANGUL SYLLABLE HIEUH YU NIEUN * +U+D739(2);; # HANGUL SYLLABLE HIEUH YU NIEUNCIEUC +U+D73A(2);; # HANGUL SYLLABLE HIEUH YU NIEUNHIEUH +U+D73B(2);; # HANGUL SYLLABLE HIEUH YU TIKEUT +U+D73C(2);; # HANGUL SYLLABLE HIEUH YU RIEUL * +U+D73D(2);; # HANGUL SYLLABLE HIEUH YU RIEULKIYEOK +U+D73E(2);; # HANGUL SYLLABLE HIEUH YU RIEULMIEUM +U+D73F(2);; # HANGUL SYLLABLE HIEUH YU RIEULPIEUP +U+D740(2);; # HANGUL SYLLABLE HIEUH YU RIEULSIOS +U+D741(2);; # HANGUL SYLLABLE HIEUH YU RIEULTHIEUTH +U+D742(2);; # HANGUL SYLLABLE HIEUH YU RIEULPHIEUPH +U+D743(2);; # HANGUL SYLLABLE HIEUH YU RIEULHIEUH +U+D744(2);; # HANGUL SYLLABLE HIEUH YU MIEUM * +U+D745(2);; # HANGUL SYLLABLE HIEUH YU PIEUP +U+D746(2);; # HANGUL SYLLABLE HIEUH YU PIEUPSIOS +U+D747(2);; # HANGUL SYLLABLE HIEUH YU SIOS * +U+D748(2);; # HANGUL SYLLABLE HIEUH YU SSANGSIOS +U+D749(2);; # HANGUL SYLLABLE HIEUH YU IEUNG * +U+D74A(2);; # HANGUL SYLLABLE HIEUH YU CIEUC +U+D74B(2);; # HANGUL SYLLABLE HIEUH YU CHIEUCH +U+D74C(2);; # HANGUL SYLLABLE HIEUH YU KHIEUKH +U+D74D(2);; # HANGUL SYLLABLE HIEUH YU THIEUTH +U+D74E(2);; # HANGUL SYLLABLE HIEUH YU PHIEUPH +U+D74F(2);; # HANGUL SYLLABLE HIEUH YU HIEUH +U+D750(2);; # HANGUL SYLLABLE HIEUH EU * +U+D751(2);; # HANGUL SYLLABLE HIEUH EU KIYEOK * +U+D752(2);; # HANGUL SYLLABLE HIEUH EU SSANGKIYEOK +U+D753(2);; # HANGUL SYLLABLE HIEUH EU KIYEOKSIOS +U+D754(2);; # HANGUL SYLLABLE HIEUH EU NIEUN * +U+D755(2);; # HANGUL SYLLABLE HIEUH EU NIEUNCIEUC +U+D756(2);; # HANGUL SYLLABLE HIEUH EU NIEUNHIEUH * +U+D757(2);; # HANGUL SYLLABLE HIEUH EU TIKEUT * +U+D758(2);; # HANGUL SYLLABLE HIEUH EU RIEUL * +U+D759(2);; # HANGUL SYLLABLE HIEUH EU RIEULKIYEOK * +U+D75A(2);; # HANGUL SYLLABLE HIEUH EU RIEULMIEUM +U+D75B(2);; # HANGUL SYLLABLE HIEUH EU RIEULPIEUP +U+D75C(2);; # HANGUL SYLLABLE HIEUH EU RIEULSIOS +U+D75D(2);; # HANGUL SYLLABLE HIEUH EU RIEULTHIEUTH +U+D75E(2);; # HANGUL SYLLABLE HIEUH EU RIEULPHIEUPH +U+D75F(2);; # HANGUL SYLLABLE HIEUH EU RIEULHIEUH +U+D760(2);; # HANGUL SYLLABLE HIEUH EU MIEUM * +U+D761(2);; # HANGUL SYLLABLE HIEUH EU PIEUP * +U+D762(2);; # HANGUL SYLLABLE HIEUH EU PIEUPSIOS +U+D763(2);; # HANGUL SYLLABLE HIEUH EU SIOS * +U+D764(2);; # HANGUL SYLLABLE HIEUH EU SSANGSIOS +U+D765(2);; # HANGUL SYLLABLE HIEUH EU IEUNG * +U+D766(2);; # HANGUL SYLLABLE HIEUH EU CIEUC +U+D767(2);; # HANGUL SYLLABLE HIEUH EU CHIEUCH +U+D768(2);; # HANGUL SYLLABLE HIEUH EU KHIEUKH +U+D769(2);; # HANGUL SYLLABLE HIEUH EU THIEUTH * +U+D76A(2);; # HANGUL SYLLABLE HIEUH EU PHIEUPH +U+D76B(2);; # HANGUL SYLLABLE HIEUH EU HIEUH +U+D76C(2);; # HANGUL SYLLABLE HIEUH YI * +U+D76D(2);; # HANGUL SYLLABLE HIEUH YI KIYEOK +U+D76E(2);; # HANGUL SYLLABLE HIEUH YI SSANGKIYEOK +U+D76F(2);; # HANGUL SYLLABLE HIEUH YI KIYEOKSIOS +U+D770(2);; # HANGUL SYLLABLE HIEUH YI NIEUN * +U+D771(2);; # HANGUL SYLLABLE HIEUH YI NIEUNCIEUC +U+D772(2);; # HANGUL SYLLABLE HIEUH YI NIEUNHIEUH +U+D773(2);; # HANGUL SYLLABLE HIEUH YI TIKEUT +U+D774(2);; # HANGUL SYLLABLE HIEUH YI RIEUL * +U+D775(2);; # HANGUL SYLLABLE HIEUH YI RIEULKIYEOK +U+D776(2);; # HANGUL SYLLABLE HIEUH YI RIEULMIEUM +U+D777(2);; # HANGUL SYLLABLE HIEUH YI RIEULPIEUP +U+D778(2);; # HANGUL SYLLABLE HIEUH YI RIEULSIOS +U+D779(2);; # HANGUL SYLLABLE HIEUH YI RIEULTHIEUTH +U+D77A(2);; # HANGUL SYLLABLE HIEUH YI RIEULPHIEUPH +U+D77B(2);; # HANGUL SYLLABLE HIEUH YI RIEULHIEUH +U+D77C(2);; # HANGUL SYLLABLE HIEUH YI MIEUM * +U+D77D(2);; # HANGUL SYLLABLE HIEUH YI PIEUP * +U+D77E(2);; # HANGUL SYLLABLE HIEUH YI PIEUPSIOS +U+D77F(2);; # HANGUL SYLLABLE HIEUH YI SIOS +U+D780(2);; # HANGUL SYLLABLE HIEUH YI SSANGSIOS +U+D781(2);; # HANGUL SYLLABLE HIEUH YI IEUNG * +U+D782(2);; # HANGUL SYLLABLE HIEUH YI CIEUC +U+D783(2);; # HANGUL SYLLABLE HIEUH YI CHIEUCH +U+D784(2);; # HANGUL SYLLABLE HIEUH YI KHIEUKH +U+D785(2);; # HANGUL SYLLABLE HIEUH YI THIEUTH +U+D786(2);; # HANGUL SYLLABLE HIEUH YI PHIEUPH +U+D787(2);; # HANGUL SYLLABLE HIEUH YI HIEUH +U+D788(2);; # HANGUL SYLLABLE HIEUH I * +U+D789(2);; # HANGUL SYLLABLE HIEUH I KIYEOK * +U+D78A(2);; # HANGUL SYLLABLE HIEUH I SSANGKIYEOK +U+D78B(2);; # HANGUL SYLLABLE HIEUH I KIYEOKSIOS +U+D78C(2);; # HANGUL SYLLABLE HIEUH I NIEUN * +U+D78D(2);; # HANGUL SYLLABLE HIEUH I NIEUNCIEUC +U+D78E(2);; # HANGUL SYLLABLE HIEUH I NIEUNHIEUH +U+D78F(2);; # HANGUL SYLLABLE HIEUH I TIKEUT +U+D790(2);; # HANGUL SYLLABLE HIEUH I RIEUL * +U+D791(2);; # HANGUL SYLLABLE HIEUH I RIEULKIYEOK +U+D792(2);; # HANGUL SYLLABLE HIEUH I RIEULMIEUM +U+D793(2);; # HANGUL SYLLABLE HIEUH I RIEULPIEUP +U+D794(2);; # HANGUL SYLLABLE HIEUH I RIEULSIOS +U+D795(2);; # HANGUL SYLLABLE HIEUH I RIEULTHIEUTH +U+D796(2);; # HANGUL SYLLABLE HIEUH I RIEULPHIEUPH +U+D797(2);; # HANGUL SYLLABLE HIEUH I RIEULHIEUH +U+D798(2);; # HANGUL SYLLABLE HIEUH I MIEUM * +U+D799(2);; # HANGUL SYLLABLE HIEUH I PIEUP * +U+D79A(2);; # HANGUL SYLLABLE HIEUH I PIEUPSIOS +U+D79B(2);; # HANGUL SYLLABLE HIEUH I SIOS * +U+D79C(2);; # HANGUL SYLLABLE HIEUH I SSANGSIOS +U+D79D(2);; # HANGUL SYLLABLE HIEUH I IEUNG * +U+D79E(2);; # HANGUL SYLLABLE HIEUH I CIEUC +U+D79F(2);; # HANGUL SYLLABLE HIEUH I CHIEUCH +U+D7A0(2);; # HANGUL SYLLABLE HIEUH I KHIEUKH +U+D7A1(2);; # HANGUL SYLLABLE HIEUH I THIEUTH +U+D7A2(2);; # HANGUL SYLLABLE HIEUH I PHIEUPH +U+D7A3(2);; # HANGUL SYLLABLE HIEUH I HIEUH diff --git a/java/com/google/domain/registry/idn/Latin-IDN.txt b/java/com/google/domain/registry/idn/Latin-IDN.txt new file mode 100644 index 000000000..15d69e85b --- /dev/null +++ b/java/com/google/domain/registry/idn/Latin-IDN.txt @@ -0,0 +1,152 @@ +# Registry: Charleston Road Registry Inc. +# +# Script: Latin +# +# Version: 1.0 +# +# Effective Date: 04-12-2012 +# +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# +# Telephone: +1 (650) 253-0000 +# +# Website: www.charlestonroadregistry.com +# +# Notes: This table describes codepoints allowed for the Latin script. + +U+002D # HYPHEN-MINUS +# +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +# +# The following code points are listed according to the +# European Ordering Rules (ENV 13710). +# +U+0061 # LATIN SMALL LETTER A +U+00E1 # LATIN SMALL LETTER A WITH ACUTE +U+00E0 # LATIN SMALL LETTER A WITH GRAVE +U+0103 # LATIN SMALL LETTER A WITH BREVE +U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX +U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE +U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS +U+00E3 # LATIN SMALL LETTER A WITH TILDE +U+0105 # LATIN SMALL LETTER A WITH OGONEK +U+0101 # LATIN SMALL LETTER A WITH MACRON +U+01CE # LATIN SMALL LETTER A WITH CARON +U+00E6 # LATIN SMALL LETTER AE +U+0062 # LATIN SMALL LETTER B +U+0063 # LATIN SMALL LETTER C +U+0107 # LATIN SMALL LETTER C WITH ACUTE +U+010D # LATIN SMALL LETTER C WITH CARON +U+010B # LATIN SMALL LETTER C WITH DOT ABOVE +U+00E7 # LATIN SMALL LETTER C WITH CEDILLA +U+0064 # LATIN SMALL LETTER D +U+010F # LATIN SMALL LETTER D WITH CARON +U+0111 # LATIN SMALL LETTER D WITH STROKE +U+00F0 # LATIN SMALL LETTER ETH +U+0065 # LATIN SMALL LETTER E +U+00E9 # LATIN SMALL LETTER E WITH ACUTE +U+00E8 # LATIN SMALL LETTER E WITH GRAVE +U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX +U+011B # LATIN SMALL LETTER E WITH CARON +U+00EB # LATIN SMALL LETTER E WITH DIAERESIS +U+0119 # LATIN SMALL LETTER E WITH OGONEK +U+0113 # LATIN SMALL LETTER E WITH MACRON +U+0117 # LATIN SMALL LETTER E WITH DOT ABOVE +U+0259 # LATIN SMALL LETTER SCHWA +U+0066 # LATIN SMALL LETTER F +U+0067 # LATIN SMALL LETTER G +U+011F # LATIN SMALL LETTER G WITH BREVE +U+01E7 # LATIN SMALL LETTER G WITH CARON +U+0121 # LATIN SMALL LETTER G WITH DOT ABOVE +U+0123 # LATIN SMALL LETTER G WITH CEDILLA +U+01E5 # LATIN SMALL LETTER G WITH STROKE +U+0068 # LATIN SMALL LETTER H +U+0127 # LATIN SMALL LETTER H WITH STROKE +U+0069 # LATIN SMALL LETTER I +U+0131 # LATIN SMALL LETTER DOTLESS I +U+00ED # LATIN SMALL LETTER I WITH ACUTE +U+00EC # LATIN SMALL LETTER I WITH GRAVE +U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX +U+00EF # LATIN SMALL LETTER I WITH DIAERESIS +U+012F # LATIN SMALL LETTER I WITH OGONEK +U+012B # LATIN SMALL LETTER I WITH MACRON +U+01D0 # LATIN SMALL LETTER I WITH CARON +U+006A # LATIN SMALL LETTER J +U+006B # LATIN SMALL LETTER K +U+01E9 # LATIN SMALL LETTER K WITH CARON +U+0137 # LATIN SMALL LETTER K WITH CEDILLA +U+006C # LATIN SMALL LETTER L +U+013A # LATIN SMALL LETTER L WITH ACUTE +U+013E # LATIN SMALL LETTER L WITH CARON +U+013C # LATIN SMALL LETTER L WITH CEDILLA +U+0142 # LATIN SMALL LETTER L WITH STROKE +U+006D # LATIN SMALL LETTER M +U+006E # LATIN SMALL LETTER N +U+0144 # LATIN SMALL LETTER N WITH ACUTE +U+0148 # LATIN SMALL LETTER N WITH CARON +U+00F1 # LATIN SMALL LETTER N WITH TILDE +U+0146 # LATIN SMALL LETTER N WITH CEDILLA +U+014B # LATIN SMALL LETTER ENG +U+006F # LATIN SMALL LETTER O +U+00F3 # LATIN SMALL LETTER O WITH ACUTE +U+00F2 # LATIN SMALL LETTER O WITH GRAVE +U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX +U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS +U+0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE +U+00F5 # LATIN SMALL LETTER O WITH TILDE +U+014D # LATIN SMALL LETTER O WITH MACRON +U+01D2 # LATIN SMALL LETTER O WITH CARON +U+00F8 # LATIN SMALL LETTER O WITH STROKE +U+0153 # LATIN SMALL LIGATURE OE +U+0070 # LATIN SMALL LETTER P +U+0071 # LATIN SMALL LETTER Q +U+0072 # LATIN SMALL LETTER R +U+0155 # LATIN SMALL LETTER R WITH ACUTE +U+0159 # LATIN SMALL LETTER R WITH CARON +U+0157 # LATIN SMALL LETTER R WITH CEDILLA +U+0073 # LATIN SMALL LETTER S +U+015B # LATIN SMALL LETTER S WITH ACUTE +U+0161 # LATIN SMALL LETTER S WITH CARON +U+015F # LATIN SMALL LETTER S WITH CEDILLA +U+0074 # LATIN SMALL LETTER T +U+0165 # LATIN SMALL LETTER T WITH CARON +U+0163 # LATIN SMALL LETTER T WITH CEDILLA +U+0167 # LATIN SMALL LETTER T WITH STROKE +U+0075 # LATIN SMALL LETTER U +U+00FA # LATIN SMALL LETTER U WITH ACUTE +U+00F9 # LATIN SMALL LETTER U WITH GRAVE +U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX +U+016F # LATIN SMALL LETTER U WITH RING ABOVE +U+00FC # LATIN SMALL LETTER U WITH DIAERESIS +U+0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE +U+0173 # LATIN SMALL LETTER U WITH OGONEK +U+016B # LATIN SMALL LETTER U WITH MACRON +U+01D4 # LATIN SMALL LETTER U WITH CARON +U+0076 # LATIN SMALL LETTER V +U+0077 # LATIN SMALL LETTER W +U+1E83 # LATIN SMALL LETTER W WITH ACUTE +U+1E81 # LATIN SMALL LETTER W WITH GRAVE +U+0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX +U+1E85 # LATIN SMALL LETTER W WITH DIAERESIS +U+0078 # LATIN SMALL LETTER X +U+0079 # LATIN SMALL LETTER Y +U+00FD # LATIN SMALL LETTER Y WITH ACUTE +U+1EF3 # LATIN SMALL LETTER Y WITH GRAVE +U+0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX +U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS +U+007A # LATIN SMALL LETTER Z +U+017A # LATIN SMALL LETTER Z WITH ACUTE +U+017E # LATIN SMALL LETTER Z WITH CARON +U+017C # LATIN SMALL LETTER Z WITH DOT ABOVE +U+0292 # LATIN SMALL LETTER EZH +U+01EF # LATIN SMALL LETTER EZH WITH CARON +U+00FE # LATIN SMALL LETTER THORN diff --git a/java/com/google/domain/registry/idn/Malayalam-IDN.txt b/java/com/google/domain/registry/idn/Malayalam-IDN.txt new file mode 100644 index 000000000..ab7028bd3 --- /dev/null +++ b/java/com/google/domain/registry/idn/Malayalam-IDN.txt @@ -0,0 +1,112 @@ +# Registry: Charleston Road Registry Inc. +# Script: Malayalam +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Malayalam script. +# +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0D02 # MALAYALAM SIGN ANUSVARA +U+0D03 # MALAYALAM SIGN VISARGA +U+0D05 # MALAYALAM LETTER A +U+0D06 # MALAYALAM LETTER AA +U+0D07 # MALAYALAM LETTER I +U+0D08 # MALAYALAM LETTER II +U+0D09 # MALAYALAM LETTER U +U+0D0A # MALAYALAM LETTER UU +U+0D0B # MALAYALAM LETTER VOCALIC R +U+0D0C # MALAYALAM LETTER VOCALIC L +U+0D0E # MALAYALAM LETTER E +U+0D0F # MALAYALAM LETTER EE +U+0D10 # MALAYALAM LETTER AI +U+0D12 # MALAYALAM LETTER O +U+0D13 # MALAYALAM LETTER OO +U+0D14 # MALAYALAM LETTER AU +U+0D15 # MALAYALAM LETTER KA +U+0D16 # MALAYALAM LETTER KHA +U+0D17 # MALAYALAM LETTER GA +U+0D18 # MALAYALAM LETTER GHA +U+0D19 # MALAYALAM LETTER NGA +U+0D1A # MALAYALAM LETTER CA +U+0D1B # MALAYALAM LETTER CHA +U+0D1C # MALAYALAM LETTER JA +U+0D1D # MALAYALAM LETTER JHA +U+0D1E # MALAYALAM LETTER NYA +U+0D1F # MALAYALAM LETTER TTA +U+0D20 # MALAYALAM LETTER TTHA +U+0D21 # MALAYALAM LETTER DDA +U+0D22 # MALAYALAM LETTER DDHA +U+0D23 # MALAYALAM LETTER NNA +U+0D24 # MALAYALAM LETTER TA +U+0D25 # MALAYALAM LETTER THA +U+0D26 # MALAYALAM LETTER DA +U+0D27 # MALAYALAM LETTER DHA +U+0D28 # MALAYALAM LETTER NA +U+0D2A # MALAYALAM LETTER PA +U+0D2B # MALAYALAM LETTER PHA +U+0D2C # MALAYALAM LETTER BA +U+0D2D # MALAYALAM LETTER BHA +U+0D2E # MALAYALAM LETTER MA +U+0D2F # MALAYALAM LETTER YA +U+0D30 # MALAYALAM LETTER RA +U+0D31 # MALAYALAM LETTER RRA +U+0D32 # MALAYALAM LETTER LA +U+0D33 # MALAYALAM LETTER LLA +U+0D34 # MALAYALAM LETTER LLLA +U+0D35 # MALAYALAM LETTER VA +U+0D36 # MALAYALAM LETTER SHA +U+0D37 # MALAYALAM LETTER SSA +U+0D38 # MALAYALAM LETTER SA +U+0D39 # MALAYALAM LETTER HA +U+0D3D # MALAYALAM SIGN AVAGRAHA +U+0D3E # MALAYALAM VOWEL SIGN AA +U+0D3F # MALAYALAM VOWEL SIGN I +U+0D40 # MALAYALAM VOWEL SIGN II +U+0D41 # MALAYALAM VOWEL SIGN U +U+0D42 # MALAYALAM VOWEL SIGN UU +U+0D43 # MALAYALAM VOWEL SIGN VOCALIC R +U+0D44 # MALAYALAM VOWEL SIGN VOCALIC RR +U+0D46 # MALAYALAM VOWEL SIGN E +U+0D47 # MALAYALAM VOWEL SIGN EE +U+0D48 # MALAYALAM VOWEL SIGN AI +U+0D4A # MALAYALAM VOWEL SIGN O +U+0D4B # MALAYALAM VOWEL SIGN OO +U+0D4C # MALAYALAM VOWEL SIGN AU +U+0D4D # MALAYALAM SIGN VIRAMA +U+0D57 # MALAYALAM AU LENGTH MARK +U+0D60 # MALAYALAM LETTER VOCALIC RR +U+0D61 # MALAYALAM LETTER VOCALIC LL +U+0D62 # MALAYALAM VOWEL SIGN VOCALIC L +U+0D63 # MALAYALAM VOWEL SIGN VOCALIC LL +U+0D66 # MALAYALAM DIGIT ZERO +U+0D67 # MALAYALAM DIGIT ONE +U+0D68 # MALAYALAM DIGIT TWO +U+0D69 # MALAYALAM DIGIT THREE +U+0D6A # MALAYALAM DIGIT FOUR +U+0D6B # MALAYALAM DIGIT FIVE +U+0D6C # MALAYALAM DIGIT SIX +U+0D6D # MALAYALAM DIGIT SEVEN +U+0D6E # MALAYALAM DIGIT EIGHT +U+0D6F # MALAYALAM DIGIT NINE +U+0D7A # MALAYALAM LETTER CHILLU NN +U+0D7B # MALAYALAM LETTER CHILLU N +U+0D7C # MALAYALAM LETTER CHILLU RR +U+0D7D # MALAYALAM LETTER CHILLU L +U+0D7E # MALAYALAM LETTER CHILLU LL +U+0D7F # MALAYALAM LETTER CHILLU K diff --git a/java/com/google/domain/registry/idn/Myanmar-IDN.txt b/java/com/google/domain/registry/idn/Myanmar-IDN.txt new file mode 100644 index 000000000..22e27abcd --- /dev/null +++ b/java/com/google/domain/registry/idn/Myanmar-IDN.txt @@ -0,0 +1,201 @@ +# Registry: Charleston Road Registry Inc. +# Script: Myanmar +# Version: 1.0 +# Effective Date: 04-12-2012 +# +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Myanmar script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+1000 # MYANMAR LETTER KA +U+1001 # MYANMAR LETTER KHA +U+1002 # MYANMAR LETTER GA +U+1003 # MYANMAR LETTER GHA +U+1004 # MYANMAR LETTER NGA +U+1005 # MYANMAR LETTER CA +U+1006 # MYANMAR LETTER CHA +U+1007 # MYANMAR LETTER JA +U+1008 # MYANMAR LETTER JHA +U+1009 # MYANMAR LETTER NYA +U+100A # MYANMAR LETTER NNYA +U+100B # MYANMAR LETTER TTA +U+100C # MYANMAR LETTER TTHA +U+100D # MYANMAR LETTER DDA +U+100E # MYANMAR LETTER DDHA +U+100F # MYANMAR LETTER NNA +U+1010 # MYANMAR LETTER TA +U+1011 # MYANMAR LETTER THA +U+1012 # MYANMAR LETTER DA +U+1013 # MYANMAR LETTER DHA +U+1014 # MYANMAR LETTER NA +U+1015 # MYANMAR LETTER PA +U+1016 # MYANMAR LETTER PHA +U+1017 # MYANMAR LETTER BA +U+1018 # MYANMAR LETTER BHA +U+1019 # MYANMAR LETTER MA +U+101A # MYANMAR LETTER YA +U+101B # MYANMAR LETTER RA +U+101C # MYANMAR LETTER LA +U+101D # MYANMAR LETTER WA +U+101E # MYANMAR LETTER SA +U+101F # MYANMAR LETTER HA +U+1020 # MYANMAR LETTER LLA +U+1021 # MYANMAR LETTER A +U+1022 # MYANMAR LETTER SHAN A +U+1023 # MYANMAR LETTER I +U+1024 # MYANMAR LETTER II +U+1025 # MYANMAR LETTER U +U+1026 # MYANMAR LETTER UU +U+1027 # MYANMAR LETTER E +U+1028 # MYANMAR LETTER MON E +U+1029 # MYANMAR LETTER O +U+102A # MYANMAR LETTER AU +U+102B # MYANMAR VOWEL SIGN TALL AA +U+102C # MYANMAR VOWEL SIGN AA +U+102D # MYANMAR VOWEL SIGN I +U+102E # MYANMAR VOWEL SIGN II +U+102F # MYANMAR VOWEL SIGN U +U+1030 # MYANMAR VOWEL SIGN UU +U+1031 # MYANMAR VOWEL SIGN E +U+1032 # MYANMAR VOWEL SIGN AI +U+1033 # MYANMAR VOWEL SIGN MON II +U+1034 # MYANMAR VOWEL SIGN MON O +U+1035 # MYANMAR VOWEL SIGN E ABOVE +U+1036 # MYANMAR SIGN ANUSVARA +U+1037 # MYANMAR SIGN DOT BELOW +U+1038 # MYANMAR SIGN VISARGA +U+1039 # MYANMAR SIGN VIRAMA +U+103A # MYANMAR SIGN ASAT +U+103B # MYANMAR CONSONANT SIGN MEDIAL YA +U+103C # MYANMAR CONSONANT SIGN MEDIAL RA +U+103D # MYANMAR CONSONANT SIGN MEDIAL WA +U+103E # MYANMAR CONSONANT SIGN MEDIAL HA +U+103F # MYANMAR LETTER GREAT SA +U+1040 # MYANMAR DIGIT ZERO +U+1041 # MYANMAR DIGIT ONE +U+1042 # MYANMAR DIGIT TWO +U+1043 # MYANMAR DIGIT THREE +U+1044 # MYANMAR DIGIT FOUR +U+1045 # MYANMAR DIGIT FIVE +U+1046 # MYANMAR DIGIT SIX +U+1047 # MYANMAR DIGIT SEVEN +U+1048 # MYANMAR DIGIT EIGHT +U+1049 # MYANMAR DIGIT NINE +U+1050 # MYANMAR LETTER SHA +U+1051 # MYANMAR LETTER SSA +U+1052 # MYANMAR LETTER VOCALIC R +U+1053 # MYANMAR LETTER VOCALIC RR +U+1054 # MYANMAR LETTER VOCALIC L +U+1055 # MYANMAR LETTER VOCALIC LL +U+1056 # MYANMAR VOWEL SIGN VOCALIC R +U+1057 # MYANMAR VOWEL SIGN VOCALIC RR +U+1058 # MYANMAR VOWEL SIGN VOCALIC L +U+1059 # MYANMAR VOWEL SIGN VOCALIC LL +U+105A # MYANMAR LETTER MON NGA +U+105B # MYANMAR LETTER MON JHA +U+105C # MYANMAR LETTER MON BBA +U+105D # MYANMAR LETTER MON BBE +U+105E # MYANMAR CONSONANT SIGN MON MEDIAL NA +U+105F # MYANMAR CONSONANT SIGN MON MEDIAL MA +U+1060 # MYANMAR CONSONANT SIGN MON MEDIAL LA +U+1061 # MYANMAR LETTER SGAW KAREN SHA +U+1062 # MYANMAR VOWEL SIGN SGAW KAREN EU +U+1063 # MYANMAR TONE MARK SGAW KAREN HATHI +U+1064 # MYANMAR TONE MARK SGAW KAREN KE PHO +U+1065 # MYANMAR LETTER WESTERN PWO KAREN THA +U+1066 # MYANMAR LETTER WESTERN PWO KAREN PWA +U+1067 # MYANMAR VOWEL SIGN WESTERN PWO KAREN EU +U+1068 # MYANMAR VOWEL SIGN WESTERN PWO KAREN UE +U+1069 # MYANMAR SIGN WESTERN PWO KAREN TONE-1 +U+106A # MYANMAR SIGN WESTERN PWO KAREN TONE-2 +U+106B # MYANMAR SIGN WESTERN PWO KAREN TONE-3 +U+106C # MYANMAR SIGN WESTERN PWO KAREN TONE-4 +U+106D # MYANMAR SIGN WESTERN PWO KAREN TONE-5 +U+106E # MYANMAR LETTER EASTERN PWO KAREN NNA +U+106F # MYANMAR LETTER EASTERN PWO KAREN YWA +U+1070 # MYANMAR LETTER EASTERN PWO KAREN GHWA +U+1071 # MYANMAR VOWEL SIGN GEBA KAREN I +U+1072 # MYANMAR VOWEL SIGN KAYAH OE +U+1073 # MYANMAR VOWEL SIGN KAYAH U +U+1074 # MYANMAR VOWEL SIGN KAYAH EE +U+1075 # MYANMAR LETTER SHAN KA +U+1076 # MYANMAR LETTER SHAN KHA +U+1077 # MYANMAR LETTER SHAN GA +U+1078 # MYANMAR LETTER SHAN CA +U+1079 # MYANMAR LETTER SHAN ZA +U+107A # MYANMAR LETTER SHAN NYA +U+107B # MYANMAR LETTER SHAN DA +U+107C # MYANMAR LETTER SHAN NA +U+107D # MYANMAR LETTER SHAN PHA +U+107E # MYANMAR LETTER SHAN FA +U+107F # MYANMAR LETTER SHAN BA +U+1080 # MYANMAR LETTER SHAN THA +U+1081 # MYANMAR LETTER SHAN HA +U+1082 # MYANMAR CONSONANT SIGN SHAN MEDIAL WA +U+1083 # MYANMAR VOWEL SIGN SHAN AA +U+1084 # MYANMAR VOWEL SIGN SHAN E +U+1085 # MYANMAR VOWEL SIGN SHAN E ABOVE +U+1086 # MYANMAR VOWEL SIGN SHAN FINAL Y +U+1087 # MYANMAR SIGN SHAN TONE-2 +U+1088 # MYANMAR SIGN SHAN TONE-3 +U+1089 # MYANMAR SIGN SHAN TONE-5 +U+108A # MYANMAR SIGN SHAN TONE-6 +U+108B # MYANMAR SIGN SHAN COUNCIL TONE-2 +U+108C # MYANMAR SIGN SHAN COUNCIL TONE-3 +U+108D # MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE +U+108E # MYANMAR LETTER RUMAI PALAUNG FA +U+108F # MYANMAR SIGN RUMAI PALAUNG TONE-5 +U+1090 # MYANMAR SHAN DIGIT ZERO +U+1091 # MYANMAR SHAN DIGIT ONE +U+1092 # MYANMAR SHAN DIGIT TWO +U+1093 # MYANMAR SHAN DIGIT THREE +U+1094 # MYANMAR SHAN DIGIT FOUR +U+1095 # MYANMAR SHAN DIGIT FIVE +U+1096 # MYANMAR SHAN DIGIT SIX +U+1097 # MYANMAR SHAN DIGIT SEVEN +U+1098 # MYANMAR SHAN DIGIT EIGHT +U+1099 # MYANMAR SHAN DIGIT NINE +U+109A # MYANMAR SIGN KHAMTI TONE-1 +U+109B # MYANMAR SIGN KHAMTI TONE-3 +U+109C # MYANMAR VOWEL SIGN AITON A +U+109D # MYANMAR VOWEL SIGN AITON AI +U+AA60 # MYANMAR LETTER KHAMTI GA +U+AA61 # MYANMAR LETTER KHAMTI CA +U+AA62 # MYANMAR LETTER KHAMTI CHA +U+AA63 # MYANMAR LETTER KHAMTI JA +U+AA64 # MYANMAR LETTER KHAMTI JHA +U+AA65 # MYANMAR LETTER KHAMTI NYA +U+AA66 # MYANMAR LETTER KHAMTI TTA +U+AA67 # MYANMAR LETTER KHAMTI TTHA +U+AA68 # MYANMAR LETTER KHAMTI DDA +U+AA69 # MYANMAR LETTER KHAMTI DDHA +U+AA6A # MYANMAR LETTER KHAMTI DHA +U+AA6B # MYANMAR LETTER KHAMTI NA +U+AA6C # MYANMAR LETTER KHAMTI SA +U+AA6D # MYANMAR LETTER KHAMTI HA +U+AA6E # MYANMAR LETTER KHAMTI HHA +U+AA6F # MYANMAR LETTER KHAMTI FA +U+AA70 # MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION +U+AA71 # MYANMAR LETTER KHAMTI XA +U+AA72 # MYANMAR LETTER KHAMTI ZA +U+AA73 # MYANMAR LETTER KHAMTI RA +U+AA74 # MYANMAR LOGOGRAM KHAMTI OAY +U+AA75 # MYANMAR LOGOGRAM KHAMTI QN +U+AA76 # MYANMAR LOGOGRAM KHAMTI HM +U+AA7A # MYANMAR LETTER AITON RA +U+AA7B # MYANMAR SIGN PAO KAREN TONE diff --git a/java/com/google/domain/registry/idn/Oriya-IDN.txt b/java/com/google/domain/registry/idn/Oriya-IDN.txt new file mode 100644 index 000000000..27765fa08 --- /dev/null +++ b/java/com/google/domain/registry/idn/Oriya-IDN.txt @@ -0,0 +1,104 @@ +# Registry: Charleston Road Registry Inc. +# Script: Oriya +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Oriya script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0B01 # ORIYA SIGN CANDRABINDU +U+0B02 # ORIYA SIGN ANUSVARA +U+0B03 # ORIYA SIGN VISARGA +U+0B05 # ORIYA LETTER A +U+0B06 # ORIYA LETTER AA +U+0B07 # ORIYA LETTER I +U+0B08 # ORIYA LETTER II +U+0B09 # ORIYA LETTER U +U+0B0A # ORIYA LETTER UU +U+0B0B # ORIYA LETTER VOCALIC R +U+0B0C # ORIYA LETTER VOCALIC L +U+0B0F # ORIYA LETTER E +U+0B10 # ORIYA LETTER AI +U+0B13 # ORIYA LETTER O +U+0B14 # ORIYA LETTER AU +U+0B15 # ORIYA LETTER KA +U+0B16 # ORIYA LETTER KHA +U+0B17 # ORIYA LETTER GA +U+0B18 # ORIYA LETTER GHA +U+0B19 # ORIYA LETTER NGA +U+0B1A # ORIYA LETTER CA +U+0B1B # ORIYA LETTER CHA +U+0B1C # ORIYA LETTER JA +U+0B1D # ORIYA LETTER JHA +U+0B1E # ORIYA LETTER NYA +U+0B1F # ORIYA LETTER TTA +U+0B20 # ORIYA LETTER TTHA +U+0B21 # ORIYA LETTER DDA +U+0B22 # ORIYA LETTER DDHA +U+0B23 # ORIYA LETTER NNA +U+0B24 # ORIYA LETTER TA +U+0B25 # ORIYA LETTER THA +U+0B26 # ORIYA LETTER DA +U+0B27 # ORIYA LETTER DHA +U+0B28 # ORIYA LETTER NA +U+0B2A # ORIYA LETTER PA +U+0B2B # ORIYA LETTER PHA +U+0B2C # ORIYA LETTER BA +U+0B2D # ORIYA LETTER BHA +U+0B2E # ORIYA LETTER MA +U+0B2F # ORIYA LETTER YA +U+0B30 # ORIYA LETTER RA +U+0B32 # ORIYA LETTER LA +U+0B33 # ORIYA LETTER LLA +U+0B35 # ORIYA LETTER VA +U+0B36 # ORIYA LETTER SHA +U+0B37 # ORIYA LETTER SSA +U+0B38 # ORIYA LETTER SA +U+0B39 # ORIYA LETTER HA +U+0B3C # ORIYA SIGN NUKTA +U+0B3D # ORIYA SIGN AVAGRAHA +U+0B3E # ORIYA VOWEL SIGN AA +U+0B3F # ORIYA VOWEL SIGN I +U+0B40 # ORIYA VOWEL SIGN II +U+0B41 # ORIYA VOWEL SIGN U +U+0B42 # ORIYA VOWEL SIGN UU +U+0B43 # ORIYA VOWEL SIGN VOCALIC R +U+0B44 # ORIYA VOWEL SIGN VOCALIC RR +U+0B47 # ORIYA VOWEL SIGN E +U+0B48 # ORIYA VOWEL SIGN AI +U+0B4B # ORIYA VOWEL SIGN O +U+0B4C # ORIYA VOWEL SIGN AU +U+0B4D # ORIYA SIGN VIRAMA +U+0B56 # ORIYA AI LENGTH MARK +U+0B57 # ORIYA AU LENGTH MARK +U+0B5F # ORIYA LETTER YYA +U+0B60 # ORIYA LETTER VOCALIC RR +U+0B61 # ORIYA LETTER VOCALIC LL +U+0B62 # ORIYA VOWEL SIGN VOCALIC L +U+0B63 # ORIYA VOWEL SIGN VOCALIC LL +U+0B66 # ORIYA DIGIT ZERO +U+0B67 # ORIYA DIGIT ONE +U+0B68 # ORIYA DIGIT TWO +U+0B69 # ORIYA DIGIT THREE +U+0B6A # ORIYA DIGIT FOUR +U+0B6B # ORIYA DIGIT FIVE +U+0B6C # ORIYA DIGIT SIX +U+0B6D # ORIYA DIGIT SEVEN +U+0B6E # ORIYA DIGIT EIGHT +U+0B6F # ORIYA DIGIT NINE +U+0B71 # ORIYA LETTER WA diff --git a/java/com/google/domain/registry/idn/Sinhala-IDN.txt b/java/com/google/domain/registry/idn/Sinhala-IDN.txt new file mode 100644 index 000000000..0478ba8aa --- /dev/null +++ b/java/com/google/domain/registry/idn/Sinhala-IDN.txt @@ -0,0 +1,102 @@ +# Registry: Charleston Road Registry Inc. +# Script: Sinhala +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Sinhala script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0D82 # SINHALA SIGN ANUSVARAYA +U+0D83 # SINHALA SIGN VISARGAYA +U+0D85 # SINHALA LETTER AYANNA +U+0D86 # SINHALA LETTER AAYANNA +U+0D87 # SINHALA LETTER AEYANNA +U+0D88 # SINHALA LETTER AEEYANNA +U+0D89 # SINHALA LETTER IYANNA +U+0D8A # SINHALA LETTER IIYANNA +U+0D8B # SINHALA LETTER UYANNA +U+0D8C # SINHALA LETTER UUYANNA +U+0D8D # SINHALA LETTER IRUYANNA +U+0D8E # SINHALA LETTER IRUUYANNA +U+0D8F # SINHALA LETTER ILUYANNA +U+0D90 # SINHALA LETTER ILUUYANNA +U+0D91 # SINHALA LETTER EYANNA +U+0D92 # SINHALA LETTER EEYANNA +U+0D93 # SINHALA LETTER AIYANNA +U+0D94 # SINHALA LETTER OYANNA +U+0D95 # SINHALA LETTER OOYANNA +U+0D96 # SINHALA LETTER AUYANNA +U+0D9A # SINHALA LETTER ALPAPRAANA KAYANNA +U+0D9B # SINHALA LETTER MAHAAPRAANA KAYANNA +U+0D9C # SINHALA LETTER ALPAPRAANA GAYANNA +U+0D9D # SINHALA LETTER MAHAAPRAANA GAYANNA +U+0D9E # SINHALA LETTER KANTAJA NAASIKYAYA +U+0D9F # SINHALA LETTER SANYAKA GAYANNA +U+0DA0 # SINHALA LETTER ALPAPRAANA CAYANNA +U+0DA1 # SINHALA LETTER MAHAAPRAANA CAYANNA +U+0DA2 # SINHALA LETTER ALPAPRAANA JAYANNA +U+0DA3 # SINHALA LETTER MAHAAPRAANA JAYANNA +U+0DA4 # SINHALA LETTER TAALUJA NAASIKYAYA +U+0DA5 # SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA +U+0DA6 # SINHALA LETTER SANYAKA JAYANNA +U+0DA7 # SINHALA LETTER ALPAPRAANA TTAYANNA +U+0DA8 # SINHALA LETTER MAHAAPRAANA TTAYANNA +U+0DA9 # SINHALA LETTER ALPAPRAANA DDAYANNA +U+0DAA # SINHALA LETTER MAHAAPRAANA DDAYANNA +U+0DAB # SINHALA LETTER MUURDHAJA NAYANNA +U+0DAC # SINHALA LETTER SANYAKA DDAYANNA +U+0DAD # SINHALA LETTER ALPAPRAANA TAYANNA +U+0DAE # SINHALA LETTER MAHAAPRAANA TAYANNA +U+0DAF # SINHALA LETTER ALPAPRAANA DAYANNA +U+0DB0 # SINHALA LETTER MAHAAPRAANA DAYANNA +U+0DB1 # SINHALA LETTER DANTAJA NAYANNA +U+0DB3 # SINHALA LETTER SANYAKA DAYANNA +U+0DB4 # SINHALA LETTER ALPAPRAANA PAYANNA +U+0DB5 # SINHALA LETTER MAHAAPRAANA PAYANNA +U+0DB6 # SINHALA LETTER ALPAPRAANA BAYANNA +U+0DB7 # SINHALA LETTER MAHAAPRAANA BAYANNA +U+0DB8 # SINHALA LETTER MAYANNA +U+0DB9 # SINHALA LETTER AMBA BAYANNA +U+0DBA # SINHALA LETTER YAYANNA +U+0DBB # SINHALA LETTER RAYANNA +U+0DBD # SINHALA LETTER DANTAJA LAYANNA +U+0DC0 # SINHALA LETTER VAYANNA +U+0DC1 # SINHALA LETTER TAALUJA SAYANNA +U+0DC2 # SINHALA LETTER MUURDHAJA SAYANNA +U+0DC3 # SINHALA LETTER DANTAJA SAYANNA +U+0DC4 # SINHALA LETTER HAYANNA +U+0DC5 # SINHALA LETTER MUURDHAJA LAYANNA +U+0DC6 # SINHALA LETTER FAYANNA +U+0DCA # SINHALA SIGN AL-LAKUNA +U+0DCF # SINHALA VOWEL SIGN AELA-PILLA +U+0DD0 # SINHALA VOWEL SIGN KETTI AEDA-PILLA +U+0DD1 # SINHALA VOWEL SIGN DIGA AEDA-PILLA +U+0DD2 # SINHALA VOWEL SIGN KETTI IS-PILLA +U+0DD3 # SINHALA VOWEL SIGN DIGA IS-PILLA +U+0DD4 # SINHALA VOWEL SIGN KETTI PAA-PILLA +U+0DD6 # SINHALA VOWEL SIGN DIGA PAA-PILLA +U+0DD8 # SINHALA VOWEL SIGN GAETTA-PILLA +U+0DD9 # SINHALA VOWEL SIGN KOMBUVA +U+0DDA # SINHALA VOWEL SIGN DIGA KOMBUVA +U+0DDB # SINHALA VOWEL SIGN KOMBU DEKA +U+0DDC # SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA +U+0DDD # SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA +U+0DDE # SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA +U+0DDF # SINHALA VOWEL SIGN GAYANUKITTA +U+0DF2 # SINHALA VOWEL SIGN DIGA GAETTA-PILLA +U+0DF3 # SINHALA VOWEL SIGN DIGA GAYANUKITTA diff --git a/java/com/google/domain/registry/idn/Tamil-IDN.txt b/java/com/google/domain/registry/idn/Tamil-IDN.txt new file mode 100644 index 000000000..d029bd08c --- /dev/null +++ b/java/com/google/domain/registry/idn/Tamil-IDN.txt @@ -0,0 +1,84 @@ +# Registry: Charleston Road Registry Inc. +# Script: Tamil +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Tamil script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0B82 # TAMIL SIGN ANUSVARA +U+0B83 # TAMIL SIGN VISARGA +U+0B85 # TAMIL LETTER A +U+0B86 # TAMIL LETTER AA +U+0B87 # TAMIL LETTER I +U+0B88 # TAMIL LETTER II +U+0B89 # TAMIL LETTER U +U+0B8A # TAMIL LETTER UU +U+0B8E # TAMIL LETTER E +U+0B8F # TAMIL LETTER EE +U+0B90 # TAMIL LETTER AI +U+0B92 # TAMIL LETTER O +U+0B93 # TAMIL LETTER OO +U+0B94 # TAMIL LETTER AU +U+0B95 # TAMIL LETTER KA +U+0B99 # TAMIL LETTER NGA +U+0B9A # TAMIL LETTER CA +U+0B9C # TAMIL LETTER JA +U+0B9E # TAMIL LETTER NYA +U+0B9F # TAMIL LETTER TTA +U+0BA3 # TAMIL LETTER NNA +U+0BA4 # TAMIL LETTER TA +U+0BA8 # TAMIL LETTER NA +U+0BA9 # TAMIL LETTER NNNA +U+0BAA # TAMIL LETTER PA +U+0BAE # TAMIL LETTER MA +U+0BAF # TAMIL LETTER YA +U+0BB0 # TAMIL LETTER RA +U+0BB1 # TAMIL LETTER RRA +U+0BB2 # TAMIL LETTER LA +U+0BB3 # TAMIL LETTER LLA +U+0BB4 # TAMIL LETTER LLLA +U+0BB5 # TAMIL LETTER VA +U+0BB6 # TAMIL LETTER SHA +U+0BB7 # TAMIL LETTER SSA +U+0BB8 # TAMIL LETTER SA +U+0BB9 # TAMIL LETTER HA +U+0BBE # TAMIL VOWEL SIGN AA +U+0BBF # TAMIL VOWEL SIGN I +U+0BC0 # TAMIL VOWEL SIGN II +U+0BC1 # TAMIL VOWEL SIGN U +U+0BC2 # TAMIL VOWEL SIGN UU +U+0BC6 # TAMIL VOWEL SIGN E +U+0BC7 # TAMIL VOWEL SIGN EE +U+0BC8 # TAMIL VOWEL SIGN AI +U+0BCA # TAMIL VOWEL SIGN O +U+0BCB # TAMIL VOWEL SIGN OO +U+0BCC # TAMIL VOWEL SIGN AU +U+0BCD # TAMIL SIGN VIRAMA +U+0BD0 # TAMIL OM +U+0BD7 # TAMIL AU LENGTH MARK +U+0BE6 # TAMIL DIGIT ZERO +U+0BE7 # TAMIL DIGIT ONE +U+0BE8 # TAMIL DIGIT TWO +U+0BE9 # TAMIL DIGIT THREE +U+0BEA # TAMIL DIGIT FOUR +U+0BEB # TAMIL DIGIT FIVE +U+0BEC # TAMIL DIGIT SIX +U+0BED # TAMIL DIGIT SEVEN +U+0BEE # TAMIL DIGIT EIGHT +U+0BEF # TAMIL DIGIT NINE diff --git a/java/com/google/domain/registry/idn/Telugu-IDN.txt b/java/com/google/domain/registry/idn/Telugu-IDN.txt new file mode 100644 index 000000000..4375397ff --- /dev/null +++ b/java/com/google/domain/registry/idn/Telugu-IDN.txt @@ -0,0 +1,108 @@ +# Registry: Charleston Road Registry Inc. +# Script: Telugu +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Telugu script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0C01 # TELUGU SIGN CANDRABINDU +U+0C02 # TELUGU SIGN ANUSVARA +U+0C03 # TELUGU SIGN VISARGA +U+0C05 # TELUGU LETTER A +U+0C06 # TELUGU LETTER AA +U+0C07 # TELUGU LETTER I +U+0C08 # TELUGU LETTER II +U+0C09 # TELUGU LETTER U +U+0C0A # TELUGU LETTER UU +U+0C0B # TELUGU LETTER VOCALIC R +U+0C0C # TELUGU LETTER VOCALIC L +U+0C0E # TELUGU LETTER E +U+0C0F # TELUGU LETTER EE +U+0C10 # TELUGU LETTER AI +U+0C12 # TELUGU LETTER O +U+0C13 # TELUGU LETTER OO +U+0C14 # TELUGU LETTER AU +U+0C15 # TELUGU LETTER KA +U+0C16 # TELUGU LETTER KHA +U+0C17 # TELUGU LETTER GA +U+0C18 # TELUGU LETTER GHA +U+0C19 # TELUGU LETTER NGA +U+0C1A # TELUGU LETTER CA +U+0C1B # TELUGU LETTER CHA +U+0C1C # TELUGU LETTER JA +U+0C1D # TELUGU LETTER JHA +U+0C1E # TELUGU LETTER NYA +U+0C1F # TELUGU LETTER TTA +U+0C20 # TELUGU LETTER TTHA +U+0C21 # TELUGU LETTER DDA +U+0C22 # TELUGU LETTER DDHA +U+0C23 # TELUGU LETTER NNA +U+0C24 # TELUGU LETTER TA +U+0C25 # TELUGU LETTER THA +U+0C26 # TELUGU LETTER DA +U+0C27 # TELUGU LETTER DHA +U+0C28 # TELUGU LETTER NA +U+0C2A # TELUGU LETTER PA +U+0C2B # TELUGU LETTER PHA +U+0C2C # TELUGU LETTER BA +U+0C2D # TELUGU LETTER BHA +U+0C2E # TELUGU LETTER MA +U+0C2F # TELUGU LETTER YA +U+0C30 # TELUGU LETTER RA +U+0C31 # TELUGU LETTER RRA +U+0C32 # TELUGU LETTER LA +U+0C33 # TELUGU LETTER LLA +U+0C35 # TELUGU LETTER VA +U+0C36 # TELUGU LETTER SHA +U+0C37 # TELUGU LETTER SSA +U+0C38 # TELUGU LETTER SA +U+0C39 # TELUGU LETTER HA +U+0C3D # TELUGU SIGN AVAGRAHA +U+0C3E # TELUGU VOWEL SIGN AA +U+0C3F # TELUGU VOWEL SIGN I +U+0C40 # TELUGU VOWEL SIGN II +U+0C41 # TELUGU VOWEL SIGN U +U+0C42 # TELUGU VOWEL SIGN UU +U+0C43 # TELUGU VOWEL SIGN VOCALIC R +U+0C44 # TELUGU VOWEL SIGN VOCALIC RR +U+0C46 # TELUGU VOWEL SIGN E +U+0C47 # TELUGU VOWEL SIGN EE +U+0C48 # TELUGU VOWEL SIGN AI +U+0C4A # TELUGU VOWEL SIGN O +U+0C4B # TELUGU VOWEL SIGN OO +U+0C4C # TELUGU VOWEL SIGN AU +U+0C4D # TELUGU SIGN VIRAMA +U+0C55 # TELUGU LENGTH MARK +U+0C56 # TELUGU AI LENGTH MARK +U+0C58 # TELUGU LETTER TSA +U+0C59 # TELUGU LETTER DZA +U+0C60 # TELUGU LETTER VOCALIC RR +U+0C61 # TELUGU LETTER VOCALIC LL +U+0C62 # TELUGU VOWEL SIGN VOCALIC L +U+0C63 # TELUGU VOWEL SIGN VOCALIC LL +U+0C66 # TELUGU DIGIT ZERO +U+0C67 # TELUGU DIGIT ONE +U+0C68 # TELUGU DIGIT TWO +U+0C69 # TELUGU DIGIT THREE +U+0C6A # TELUGU DIGIT FOUR +U+0C6B # TELUGU DIGIT FIVE +U+0C6C # TELUGU DIGIT SIX +U+0C6D # TELUGU DIGIT SEVEN +U+0C6E # TELUGU DIGIT EIGHT +U+0C6F # TELUGU DIGIT NINE diff --git a/java/com/google/domain/registry/idn/Thai-IDN.txt b/java/com/google/domain/registry/idn/Thai-IDN.txt new file mode 100644 index 000000000..9acea7b1a --- /dev/null +++ b/java/com/google/domain/registry/idn/Thai-IDN.txt @@ -0,0 +1,92 @@ +# Registry: Charleston Road Registry Inc. +# Script: Thai +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Thai script. + +U+0E01 # THAI CHARACTER KO KAI +U+0E02 # THAI CHARACTER KHO KHAI +U+0E03 # THAI CHARACTER KHO KHUAT +U+0E04 # THAI CHARACTER KHO KHWAI +U+0E05 # THAI CHARACTER KHO KHON +U+0E06 # THAI CHARACTER KHO RAKHANG +U+0E07 # THAI CHARACTER NGO NGU +U+0E08 # THAI CHARACTER CHO CHAN +U+0E09 # THAI CHARACTER CHO CHING +U+0E0A # THAI CHARACTER CHO CHANG +U+0E0B # THAI CHARACTER SO SO +U+0E0C # THAI CHARACTER CHO CHOE +U+0E0D # THAI CHARACTER YO YING +U+0E0E # THAI CHARACTER DO CHADA +U+0E0F # THAI CHARACTER TO PATAK +U+0E10 # THAI CHARACTER THO THAN +U+0E11 # THAI CHARACTER THO NANGMONTHO +U+0E12 # THAI CHARACTER THO PHUTHAO +U+0E13 # THAI CHARACTER NO NEN +U+0E14 # THAI CHARACTER DO DEK +U+0E15 # THAI CHARACTER TO TAO +U+0E16 # THAI CHARACTER THO THUNG +U+0E17 # THAI CHARACTER THO THAHAN +U+0E18 # THAI CHARACTER THO THONG +U+0E19 # THAI CHARACTER NO NU +U+0E1A # THAI CHARACTER BO BAIMAI +U+0E1B # THAI CHARACTER PO PLA +U+0E1C # THAI CHARACTER PHO PHUNG +U+0E1D # THAI CHARACTER FO FA +U+0E1E # THAI CHARACTER PHO PHAN +U+0E1F # THAI CHARACTER FO FAN +U+0E20 # THAI CHARACTER PHO SAMPHAO +U+0E21 # THAI CHARACTER MO MA +U+0E22 # THAI CHARACTER YO YAK +U+0E23 # THAI CHARACTER RO RUA +U+0E24 # THAI CHARACTER RU +U+0E25 # THAI CHARACTER LO LING +U+0E26 # THAI CHARACTER LU +U+0E27 # THAI CHARACTER WO WAEN +U+0E28 # THAI CHARACTER SO SALA +U+0E29 # THAI CHARACTER SO RUSI +U+0E2A # THAI CHARACTER SO SUA +U+0E2B # THAI CHARACTER HO HIP +U+0E2C # THAI CHARACTER LO CHULA +U+0E2D # THAI CHARACTER O ANG +U+0E2E # THAI CHARACTER HO NOKHUK +U+0E2F # THAI CHARACTER PAIYANNOI +U+0E30 # THAI CHARACTER SARA A +U+0E31 # THAI CHARACTER MAI HAN-AKAT +U+0E32 # THAI CHARACTER SARA AA +U+0E34 # THAI CHARACTER SARA I +U+0E35 # THAI CHARACTER SARA II +U+0E36 # THAI CHARACTER SARA UE +U+0E37 # THAI CHARACTER SARA UEE +U+0E38 # THAI CHARACTER SARA U +U+0E39 # THAI CHARACTER SARA UU +U+0E3A # THAI CHARACTER PHINTHU +U+0E40 # THAI CHARACTER SARA E +U+0E41 # THAI CHARACTER SARA AE +U+0E42 # THAI CHARACTER SARA O +U+0E43 # THAI CHARACTER SARA AI MAIMUAN +U+0E44 # THAI CHARACTER SARA AI MAIMALAI +U+0E45 # THAI CHARACTER LAKKHANGYAO +U+0E46 # THAI CHARACTER MAIYAMOK +U+0E47 # THAI CHARACTER MAITAIKHU +U+0E48 # THAI CHARACTER MAI EK +U+0E49 # THAI CHARACTER MAI THO +U+0E4A # THAI CHARACTER MAI TRI +U+0E4B # THAI CHARACTER MAI CHATTAWA +U+0E4C # THAI CHARACTER THANTHAKHAT +U+0E4D # THAI CHARACTER NIKHAHIT +U+0E4E # THAI CHARACTER YAMAKK +U+0E50 # THAI DIGIT ZERO +U+0E51 # THAI DIGIT ONE +U+0E52 # THAI DIGIT TWO +U+0E53 # THAI DIGIT THREE +U+0E54 # THAI DIGIT FOUR +U+0E55 # THAI DIGIT FIVE +U+0E56 # THAI DIGIT SIX +U+0E57 # THAI DIGIT SEVEN +U+0E58 # THAI DIGIT EIGHT +U+0E59 # THAI DIGIT NINE diff --git a/java/com/google/domain/registry/idn/Tibetan-IDN.txt b/java/com/google/domain/registry/idn/Tibetan-IDN.txt new file mode 100644 index 000000000..57315bb1f --- /dev/null +++ b/java/com/google/domain/registry/idn/Tibetan-IDN.txt @@ -0,0 +1,138 @@ +# Registry: Charleston Road Registry Inc. +# Script: Tibetan +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Tibetan script. +# +# Common (allowed in all scripts) +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE + +U+0F00 # TIBETAN SYLLABLE OM +U+0F0B # TIBETAN TSEG +U+0F18 # TIBETAN ASTROLOGICAL SIGN -KHYUD PA +U+0F19 # TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS +U+0F20 # TIBETAN DIGIT ZERO +U+0F21 # TIBETAN DIGIT ONE +U+0F22 # TIBETAN DIGIT TWO +U+0F23 # TIBETAN DIGIT THREE +U+0F24 # TIBETAN DIGIT FOUR +U+0F25 # TIBETAN DIGIT FIVE +U+0F26 # TIBETAN DIGIT SIX +U+0F27 # TIBETAN DIGIT SEVEN +U+0F28 # TIBETAN DIGIT EIGHT +U+0F29 # TIBETAN DIGIT NINE +U+0F35 # TIBETAN HONORIFIC UNDER RING +U+0F37 # TIBETAN UNDER RING +U+0F39 # TIBETAN LENITION MARK +U+0F3E # TIBETAN SIGN YAR TSHES +U+0F3F # TIBETAN SIGN MAR TSHES +U+0F40 # TIBETAN LETTER KA +U+0F41 # TIBETAN LETTER KHA +U+0F42 # TIBETAN LETTER GA +U+0F44 # TIBETAN LETTER NGA +U+0F45 # TIBETAN LETTER CA +U+0F46 # TIBETAN LETTER CHA +U+0F47 # TIBETAN LETTER JA +U+0F49 # TIBETAN LETTER NYA +U+0F4A # TIBETAN LETTER REVERSED TA +U+0F4B # TIBETAN LETTER REVERSED THA +U+0F4C # TIBETAN LETTER REVERSED DA +U+0F4E # TIBETAN LETTER REVERSED NA +U+0F4F # TIBETAN LETTER TA +U+0F50 # TIBETAN LETTER THA +U+0F51 # TIBETAN LETTER DA +U+0F53 # TIBETAN LETTER NA +U+0F54 # TIBETAN LETTER PA +U+0F55 # TIBETAN LETTER PHA +U+0F56 # TIBETAN LETTER BA +U+0F58 # TIBETAN LETTER MA +U+0F59 # TIBETAN LETTER TSA +U+0F5A # TIBETAN LETTER TSHA +U+0F5B # TIBETAN LETTER DZA +U+0F5D # TIBETAN LETTER WA +U+0F5E # TIBETAN LETTER ZHA +U+0F5F # TIBETAN LETTER ZA +U+0F60 # TIBETAN LETTER AA +U+0F61 # TIBETAN LETTER YA +U+0F62 # TIBETAN LETTER RA +U+0F63 # TIBETAN LETTER LA +U+0F64 # TIBETAN LETTER SHA +U+0F65 # TIBETAN LETTER REVERSED SHA +U+0F66 # TIBETAN LETTER SA +U+0F67 # TIBETAN LETTER HA +U+0F68 # TIBETAN LETTER A +U+0F6A # TIBETAN LETTER FIXED-FORM RA +U+0F6B # TIBETAN LETTER KKA +U+0F6C # TIBETAN LETTER RRA +U+0F71 # TIBETAN VOWEL SIGN AA +U+0F72 # TIBETAN VOWEL SIGN I +U+0F74 # TIBETAN VOWEL SIGN U +U+0F7A # TIBETAN VOWEL SIGN E +U+0F7B # TIBETAN VOWEL SIGN AI +U+0F7C # TIBETAN VOWEL SIGN O +U+0F7D # TIBETAN VOWEL SIGN AU +U+0F7E # TIBETAN ANUSVARA +U+0F7F # TIBETAN VISARGA +U+0F80 # TIBETAN VOWEL SIGN SHORT I +U+0F82 # TIBETAN CANDRABINDU WITH ORNAMENT +U+0F83 # TIBETAN CANDRABINDU +U+0F84 # TIBETAN VIRAMA +U+0F86 # TIBETAN SIGN LCI RTAGS +U+0F87 # TIBETAN SIGN YANG RTAGS +U+0F88 # TIBETAN SIGN LCE TSA CAN +U+0F89 # TIBETAN SIGN MCHU CAN +U+0F8A # TIBETAN SIGN GRU CAN RGYINGS +U+0F8B # TIBETAN SIGN GRU MED RGYINGS +U+0F90 # TIBETAN SUBJOINED LETTER KA +U+0F91 # TIBETAN SUBJOINED LETTER KHA +U+0F92 # TIBETAN SUBJOINED LETTER GA +U+0F94 # TIBETAN SUBJOINED LETTER NGA +U+0F95 # TIBETAN SUBJOINED LETTER CA +U+0F96 # TIBETAN SUBJOINED LETTER CHA +U+0F97 # TIBETAN SUBJOINED LETTER JA +U+0F99 # TIBETAN SUBJOINED LETTER NYA +U+0F9A # TIBETAN SUBJOINED LETTER TTA +U+0F9B # TIBETAN SUBJOINED LETTER TTHA +U+0F9C # TIBETAN SUBJOINED LETTER DDA +U+0F9E # TIBETAN SUBJOINED LETTER NNA +U+0F9F # TIBETAN SUBJOINED LETTER TA +U+0FA0 # TIBETAN SUBJOINED LETTER THA +U+0FA1 # TIBETAN SUBJOINED LETTER DA +U+0FA3 # TIBETAN SUBJOINED LETTER NA +U+0FA4 # TIBETAN SUBJOINED LETTER PA +U+0FA5 # TIBETAN SUBJOINED LETTER PHA +U+0FA6 # TIBETAN SUBJOINED LETTER BA +U+0FA8 # TIBETAN SUBJOINED LETTER MA +U+0FA9 # TIBETAN SUBJOINED LETTER TSA +U+0FAA # TIBETAN SUBJOINED LETTER TSHA +U+0FAB # TIBETAN SUBJOINED LETTER DZA +U+0FAD # TIBETAN SUBJOINED LETTER WA +U+0FAE # TIBETAN SUBJOINED LETTER ZHA +U+0FAF # TIBETAN SUBJOINED LETTER ZA +U+0FB0 # TIBETAN SUBJOINED LETTER -A +U+0FB1 # TIBETAN SUBJOINED LETTER YA +U+0FB2 # TIBETAN SUBJOINED LETTER RA +U+0FB3 # TIBETAN SUBJOINED LETTER LA +U+0FB4 # TIBETAN SUBJOINED LETTER SHA +U+0FB5 # TIBETAN SUBJOINED LETTER SSA +U+0FB6 # TIBETAN SUBJOINED LETTER SA +U+0FB7 # TIBETAN SUBJOINED LETTER HA +U+0FB8 # TIBETAN SUBJOINED LETTER A +U+0FBA # TIBETAN SUBJOINED LETTER FIXED-FORM WA +U+0FBB # TIBETAN SUBJOINED LETTER FIXED-FORM YA +U+0FBC # TIBETAN SUBJOINED LETTER FIXED-FORM RA +U+0FC6 # TIBETAN SYMBOL PADMA GDAN diff --git a/java/com/google/domain/registry/idn/Traditional-Chinese-IDN.txt b/java/com/google/domain/registry/idn/Traditional-Chinese-IDN.txt new file mode 100644 index 000000000..1726ad6a8 --- /dev/null +++ b/java/com/google/domain/registry/idn/Traditional-Chinese-IDN.txt @@ -0,0 +1,19963 @@ +# Registry: Charleston Road Registry Inc. +# Script: Traditional Chinese +# Version: 1.0 +# Effective Date: 04-12-2012 +# Contact: tas-contact.google.com +# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA +# Telephone: +1 (650) 253-0000 +# Website: www.google.com +# Notes: This table describes codepoints allowed for the Traditional Chinese script. + +Reference 0 Unicode 3.2 +Reference 1 A Complete Set of Simplified Chinese Characters +Reference 2 Chinese Variants Collation Table +Reference 3 Chinese Big Dictionary +Reference 4 Chinese Relationship Table for Unihan Project +Reference 5 GB2312 +Reference 6 General Table for Modern Chinese +Reference 7 International Chinese Standard Big Dictionary +Reference 8 Unihan Database +Reference 9 BIG5 + +U+002D(0);U+002D(0); +U+0030(0);U+0030(0); +U+0031(0);U+0031(0); +U+0032(0);U+0032(0); +U+0033(0);U+0033(0); +U+0034(0);U+0034(0); +U+0035(0);U+0035(0); +U+0036(0);U+0036(0); +U+0037(0);U+0037(0); +U+0038(0);U+0038(0); +U+0039(0);U+0039(0); +U+0061(0);U+0061(0); +U+0062(0);U+0062(0); + +U+0063(0);U+0063(0); +U+0064(0);U+0064(0); +U+0065(0);U+0065(0); +U+0066(0);U+0066(0); +U+0067(0);U+0067(0); +U+0068(0);U+0068(0); +U+0069(0);U+0069(0); +U+006A(0);U+006A(0); +U+006B(0);U+006B(0); +U+006C(0);U+006C(0); +U+006D(0);U+006D(0); +U+006E(0);U+006E(0); +U+006F(0);U+006F(0); +U+0070(0);U+0070(0); +U+0071(0);U+0071(0); +U+0072(0);U+0072(0); +U+0073(0);U+0073(0); +U+0074(0);U+0074(0); +U+0075(0);U+0075(0); +U+0076(0);U+0076(0); +U+0077(0);U+0077(0); +U+0078(0);U+0078(0); +U+0079(0);U+0079(0); +U+007A(0);U+007A(0); +U+3447(0);U+3473(1,3);U+3473(1,3) +U+3473(0);U+3473(0);U+3447(1,3) +U+359E(0);U+558E(1,3,9);U+558E(1,3,9) +U+360E(0);U+361A(1,3);U+361A(1,3) +U+361A(0);U+361A(0);U+360E(1,3) +U+3918(0);U+396E(1);U+396E(1) +U+396E(0);U+396E(0);U+3918(1) +U+39CF(0);U+6386(1,3);U+6386(1,3) +U+39D0(0);U+3A73(1,3);U+3A73(1,3) +U+39DF(0);U+64D3(1,3);U+64D3(1,3) +U+3A73(0);U+3A73(0);U+39D0(1,3) +U+3B4E(0);U+68E1(1,3,9);U+68E1(1,3,9) +U+3C6E(0);U+6BA8(1,3);U+6BA8(1,3) +U+3CE0(0);U+6FBE(1,3);U+6FBE(1,3) +U+4056(0);U+779C(1,3,9);U+779C(1,3,9) +U+415F(0);U+7A47(1,3,9);U+7A47(1,3,9) +U+4337(0);U+7D2C(1,3,9);U+7D2C(1,3,9),U+7EF8(1,3,4),U+7DA2(1,3,4,8,9) +U+43AC(0);U+43B1(1,3);U+43B1(1,3) +U+43B1(0);U+43B1(0);U+43AC(1,3) +U+43DD(0);U+819E(1,3,9);U+819E(1,3,9) +U+44D6(0);U+85ED(1,3,9);U+85ED(1,3,9) +U+464C(0);U+4661(1,3);U+4661(1,3) +U+4661(0);U+4661(0);U+464C(1,3) +U+4723(0);U+8A22(1,3,9);U+8A22(1,3,9) +U+4729(0);U+8B8C(1,3,9);U+8B8C(1,3,9) +U+477C(0);U+477C(0);U+478D(1) +U+478D(0);U+477C(1,3);U+477C(1,3) +U+4947(0);U+4947(0);U+4982(1,3) +U+497A(0);U+91FE(1,3);U+91FE(1,3) +U+497D(0);U+93FA(1,3,9);U+93FA(1,3,9) +U+4982(0);U+4947(1,3);U+4947(1,3) +U+4983(0);U+942F(1,3);U+942F(1,3) +U+4985(0);U+9425(1,3);U+9425(1,3) +U+4986(0);U+9481(1,3,9);U+9481(1,3,9) +U+499B(0);U+499B(0);U+49B6(1,3) +U+499F(0);U+499F(0);U+49B7(1,3) +U+49B6(0);U+499B(1,3);U+499B(1,3) +U+49B7(0);U+499F(1,3);U+499F(1,3) +U+4C77(0);U+4C77(0);U+4CA3(1,3) + +U+4C9F(0);U+9BA3(1,3);U+9BA3(1,3) +U+4CA0(0);U+9C06(1,3,9);U+9C06(1,3,9) +U+4CA1(0);U+9C0C(1,3);U+9C0C(1,3),U+9C0D(1,3,9),U+9CC5(1,3,8) +U+4CA2(0);U+9C27(1,3);U+9C27(1,3) +U+4CA3(0);U+4C77(1,3);U+4C77(1,3) +U+4D13(0);U+9CFE(1,3);U+9CFE(1,3) +U+4D14(0);U+9D41(1,3,9);U+9D41(1,3,9) +U+4D15(0);U+9D37(1,3,9);U+9D37(1,3,9) +U+4D16(0);U+9D84(1,3,9);U+9D84(1,3,9) +U+4D17(0);U+9DAA(1,3,9);U+9DAA(1,3,9) +U+4D18(0);U+9DC9(1,3);U+9DC8(3,9),U+9DC9(1,3) +U+4D19(0);U+9E0A(1,3);U+9DFF(3,9),U+9E0A(1,3) +U+4DAE(0);U+9F91(1,3,9);U+9F91(1,3,9) +U+4E00(0);U+4E00(5,9);U+58F9(3,8,9),U+5F0C(3),U+58F1(3,4,8) +U+4E01(0);U+4E01(5,9); +U+4E02(0);U+4E02(0); +U+4E03(0);U+4E03(5,9); +U+4E04(0);U+4E0A(3,8,9);U+4E0A(3,8,9),U+4EE9(3,4,8,9) +U+4E05(0);U+4E0B(3,8,9);U+4E0B(3,8,9) +U+4E06(0);U+4E06(0); +U+4E07(0);U+842C(1,3,8,9);U+842C(1,3,8,9) +U+4E08(0);U+4E08(5,9); +U+4E09(0);U+4E09(5,9); +U+4E0A(0);U+4E0A(5,9);U+4E04(3,8),U+4EE9(4,9) +U+4E0B(0);U+4E0B(5,9);U+4E05(3,8) +U+4E0C(0);U+4E0C(5,9);U+4E93(4,9),U+5176(3,8,9) +U+4E0D(0);U+4E0D(5,9); +U+4E0E(0);U+8207(1,3,8,9);U+8207(1,3,8,9) +U+4E0F(0);U+4E0F(0,9);U+4E10(4,9) +U+4E10(0);U+4E10(5,9);U+4E0F(4,9) +U+4E11(0);U+4E11(1,3,9),U+919C(1,3,4,8,9);U+919C(1,3,4,8,9) +U+4E13(0);U+5C08(1,3,8,9);U+5C08(1,3,8,9) +U+4E14(0);U+4E14(5,9); +U+4E15(0);U+4E15(5,9); +U+4E16(0);U+4E16(5,9);U+4E17(3,8),U+534B(3,8) +U+4E17(0);U+4E16(3,8,9);U+4E16(3,8,9),U+534B(3,8) +U+4E18(0);U+4E18(5,9);U+4E20(3,8),U+5775(2,3,9) +U+4E19(0);U+4E19(5,9); +U+4E1A(0);U+696D(1,3,8,9);U+696D(1,3,8,9) +U+4E1B(0);U+53E2(1,3,4,8,9),U+6B09(3,9);U+53E2(1,3,4,8,9),U+6B09(3,9),U+85C2(3,9) +U+4E1C(0);U+6771(1,3,8,9);U+6771(1,3,8,9) +U+4E1D(0);U+7D72(1,3,8,9);U+7D72(1,3,8,9),U+7CF8(1,3,8,9),U+7CF9(1,3,8),U+7E9F(1,3,8) +U+4E1E(0);U+4E1E(5,9); +U+4E1F(0);U+4E1F(0,9);U+4E22(3,4,8) +U+4E20(0);U+4E18(3,8,9);U+4E18(3,8,9),U+5775(2,3,8,9) +U+4E21(0);U+5169(3,8,9);U+4E24(3),U+5169(3,8,9) +U+4E22(0);U+4E1F(3,4,8,9);U+4E1F(3,4,8,9) +U+4E23(0);U+9149(3,8,9);U+9149(3,8,9) +U+4E24(0);U+5169(1,3,8,9);U+4E21(3),U+5169(1,3,8,9) +U+4E25(0);U+56B4(1,3,8,9);U+53B3(4),U+56B4(1,3,8,9) +U+4E26(0);U+4E26(0,9);U+4F75(3,9),U+5E76(2,8,9),U+7ADD(3,8),U+5002(3,8),U+5E77(2,3,4,8) +U+4E27(0);U+55AA(1,3,8,9);U+55AA(1,3,8,9) +U+4E28(0);U+4E28(5); +U+4E2A(0);U+500B(1,3,8,9);U+500B(1,3,8,9),U+7B87(4,9) +U+4E2B(0);U+4E2B(5,9); +U+4E2C(0);U+723F(8,9);U+723F(8,9) +U+4E2D(0);U+4E2D(5,9); +U+4E2E(0);U+4E2E(0,9); +U+4E2F(0);U+4E2F(0); +U+4E30(0);U+4E30(1,3,9),U+8C50(1,3,4,8,9);U+8C4A(3,9),U+8C50(1,3,4,8,9) +U+4E31(0);U+4E31(0,9); + +U+4E32(0);U+4E32(5,9);U+8CD7(4,9) +U+4E33(0);U+4E33(0,9); +U+4E34(0);U+81E8(1,3,8,9);U+81E8(1,3,8,9) +U+4E35(0);U+4E35(0); +U+4E36(0);U+4E36(5); +U+4E37(0);U+4E37(0); +U+4E38(0);U+4E38(5,9); +U+4E39(0);U+4E39(5,9); +U+4E3A(0);U+70BA(3,8,9);U+7232(1,3,8),U+70BA(3,8,9) +U+4E3B(0);U+4E3B(5,9); +U+4E3C(0);U+4E3C(0,9);U+4E95(3,8,9) +U+4E3D(0);U+9E97(1,3,8,9);U+9E97(1,3,8,9) +U+4E3E(0);U+8209(1,3,8,9);U+6319(4),U+64E7(4),U+8209(1,3,8,9) +U+4E3F(0);U+4E3F(5); +U+4E40(0);U+4E40(0); +U+4E41(0);U+4E41(0); +U+4E42(0);U+4E42(3,9); +U+4E43(0);U+4E43(5,9),U+8FFA(2,8,9);U+5EFC(2,3,8),U+8FFA(2,8,9) +U+4E44(0);U+4E44(0); +U+4E45(0);U+4E45(5,9);U+4E46(3,8) +U+4E46(0);U+4E45(3,8,9);U+4E45(3,8,9) +U+4E47(0);U+4E47(5,9); +U+4E48(0);U+4E48(1,3,4,9),U+9EBC(4,8,9);U+5E7A(3),U+5E85(4),U+9EBC(4,8,9),U+9EBD(1,3,8) +U+4E49(0);U+7FA9(1,3,8,9);U+7F9B(3,9),U+7FA9(1,3,8,9) +U+4E4A(0);U+4E4A(0); +U+4E4B(0);U+4E4B(5,9); +U+4E4C(0);U+70CF(1,3,8,9);U+70CF(1,3,8,9) +U+4E4D(0);U+4E4D(5,9); +U+4E4E(0);U+4E4E(5,9); +U+4E4F(0);U+4E4F(5,9); +U+4E50(0);U+6A02(1,3,8,9);U+697D(3),U+6A02(1,3,8,9) +U+4E51(0);U+4E51(3); +U+4E52(0);U+4E52(5,9); +U+4E53(0);U+4E53(5,9); +U+4E54(0);U+55AC(1,3,8,9);U+55AC(1,3,8,9) +U+4E56(0);U+4E56(5,9); +U+4E57(0);U+4E58(2,3,8,9);U+4E58(2,3,8,9) +U+4E58(0);U+4E58(5,9);U+4E57(2,3,8) +U+4E59(0);U+4E59(5,9); +U+4E5A(0);U+4E5A(0); +U+4E5B(0);U+4E5B(0); +U+4E5C(0);U+4E5C(5,9); +U+4E5D(0);U+4E5D(5,9); +U+4E5E(0);U+4E5E(5,9); +U+4E5F(0);U+4E5F(5,9); +U+4E60(0);U+7FD2(1,3,8,9);U+7FD2(1,3,8,9) +U+4E61(0);U+9109(1,3,8,9);U+90F7(3),U+9109(1,3,8,9),U+9115(4) +U+4E62(0);U+4E62(0); +U+4E63(0);U+4E63(0); +U+4E64(0);U+4E64(0); +U+4E65(0);U+4E65(0); +U+4E66(0);U+66F8(1,3,8,9);U+66F8(1,3,8,9) +U+4E67(0);U+4E67(0); +U+4E69(0);U+4E69(5,9);U+7A3D(3,8,9) +U+4E6A(0);U+4E6A(0); +U+4E6B(0);U+4E6B(0); +U+4E6C(0);U+4E6C(0); +U+4E6D(0);U+4E6D(0); +U+4E6E(0);U+4E6E(0); +U+4E6F(0);U+4E6F(0); +U+4E70(0);U+8CB7(1,3,8,9);U+8CB7(1,3,8,9) +U+4E71(0);U+4E82(1,3,8,9);U+4E7F(3,9),U+4E82(1,3,8,9) + +U+4E72(0);U+4E72(0); +U+4E73(0);U+4E73(5,9); +U+4E74(0);U+4E74(0); +U+4E75(0);U+4E75(0); +U+4E76(0);U+4E76(0); +U+4E77(0);U+4E77(0); +U+4E78(0);U+4E78(4); +U+4E7A(0);U+4E7A(0); +U+4E7B(0);U+4E7B(0); +U+4E7C(0);U+4E7C(0); +U+4E7D(0);U+4E7D(0); +U+4E7E(0);U+4E7E(1,3,9);U+4E81(2,8),U+5E72(1,3,8,9),U+6F27(3,9),U+5E79(1,3,4,8,9),U+69A6(1,3,4,8,9) +U+4E7F(0);U+4E7F(0,9);U+4E71(3),U+4E82(1,3,8,9) +U+4E80(0);U+9F9C(4,8,9);U+9F9C(4,8,9),U+9F9F(4) +U+4E81(0);U+4E7E(2,8,9);U+4E7E(2,8,9),U+5E72(4,9),U+6F27(2,3,8,9),U+5E79(1,2,3,4,8,9),U+69A6(1,2,3,4,8,9) +U+4E82(0);U+4E82(0,9);U+4E71(1,3,8),U+4E7F(1,3,8,9) +U+4E83(0);U+4E83(0,9); +U+4E84(0);U+4E84(0,9); +U+4E85(0);U+4E85(0); +U+4E86(0);U+4E86(1,3,9),U+77AD(1,3,4,8,9);U+66B8(7,9),U+77AD(1,3,4,8,9) +U+4E87(0);U+4E87(0); +U+4E88(0);U+4E88(5,9); +U+4E89(0);U+722D(3,4,8,9);U+722D(3,4,8,9) +U+4E8B(0);U+4E8B(5,9); +U+4E8C(0);U+4E8C(5,9);U+5F0D(3,8),U+8CB3(3,8,9),U+8CAE(3,4,8),U+8D30(1,3,8) +U+4E8D(0);U+4E8D(5,9); +U+4E8E(0);U+4E8E(5,9);U+65BC(4,8,9),U+6275(3,4,8) +U+4E8F(0);U+8667(1,3,8,9);U+8667(1,3,8,9) +U+4E90(0);U+4E90(0); +U+4E91(0);U+4E91(1,3,9),U+96F2(1,3,4,8,9);U+96F2(1,3,4,8,9) +U+4E92(0);U+4E92(5,9); +U+4E93(0);U+4E93(5,9);U+4E0C(4,9),U+5176(3,8,9) +U+4E94(0);U+4E94(5,9);U+4F0D(3,8,9) +U+4E95(0);U+4E95(5,9);U+4E3C(3,8,9) +U+4E97(0);U+6B72(3,8,9);U+5C81(3),U+6B72(3,8,9),U+6B73(7) +U+4E98(0);U+4E99(2,8,9);U+4E99(2,8,9) +U+4E99(0);U+4E99(0,9);U+4E98(2,8) +U+4E9A(0);U+4E9E(1,3,8,9);U+4E9C(3),U+4E9E(1,3,8,9) +U+4E9B(0);U+4E9B(5,9); +U+4E9C(0);U+4E9E(3,8,9);U+4E9A(3),U+4E9E(3,8,9) +U+4E9D(0);U+9F4A(3,8,9);U+9F4A(3,8,9),U+9F50(3,4),U+6589(3,8) +U+4E9E(0);U+4E9E(0,9);U+4E9A(1,3,8),U+4E9C(3,8) +U+4E9F(0);U+4E9F(5,9); +U+4EA0(0);U+4EA0(5); +U+4EA1(0);U+4EA1(5,9);U+4EBE(2,3,8),U+5166(3,8) +U+4EA2(0);U+4EA2(5,9); +U+4EA4(0);U+4EA4(5,9); +U+4EA5(0);U+4EA5(5,9); +U+4EA6(0);U+4EA6(5,9); +U+4EA7(0);U+7522(4,8,9);U+7522(4,8,9),U+7523(1,3,8) +U+4EA8(0);U+4EA8(5,9); +U+4EA9(0);U+755D(1,3,8,9);U+7546(4),U+755D(1,3,8,9),U+756E(4) +U+4EAA(0);U+4EAA(0); +U+4EAB(0);U+4EAB(5,9);U+4EAF(2,3,8) +U+4EAC(0);U+4EAC(5,9);U+4EB0(4,8) +U+4EAD(0);U+4EAD(5,9); +U+4EAE(0);U+4EAE(5,9); +U+4EAF(0);U+4EAB(2,3,8,9);U+4EAB(2,3,8,9) +U+4EB0(0);U+4EAC(4,8,9);U+4EAC(4,8,9) +U+4EB1(0);U+591C(2,3,8,9);U+591C(2,3,8,9) +U+4EB2(0);U+89AA(1,3,8,9);U+89AA(1,3,8,9) + +U+4EB3(0);U+4EB3(5,9); +U+4EB4(0);U+4EB4(0); +U+4EB5(0);U+893B(1,3,8,9);U+893B(1,3,8,9) +U+4EB6(0);U+4EB6(4,9); +U+4EB7(0);U+5EC9(2,8,9);U+5EC9(2,8,9),U+899D(2,4,8,9) +U+4EB8(0);U+56B2(4,8,9);U+56B2(4,8,9) +U+4EB9(0);U+4EB9(4,9);U+6596(4,9) +U+4EBA(0);U+4EBA(5,9); +U+4EBB(0);U+4EBB(5); +U+4EBD(0);U+4EBD(0); +U+4EBE(0);U+4EA1(2,3,8,9);U+4EA1(2,3,8,9),U+5166(4) +U+4EBF(0);U+5104(1,3,8,9);U+5104(1,3,8,9) +U+4EC0(0);U+4EC0(5,9); +U+4EC1(0);U+4EC1(5,9);U+5FC8(4,8) +U+4EC2(0);U+4EC2(5,9); +U+4EC3(0);U+4EC3(5,9); +U+4EC4(0);U+4EC4(5,9);U+5E82(3,9) +U+4EC5(0);U+50C5(1,3,8,9);U+50C5(1,3,8,9) +U+4EC6(0);U+4EC6(1,3,9),U+50D5(1,3,8,9);U+50D5(1,3,8,9) +U+4EC7(0);U+4EC7(5,9);U+8B8E(3,8,9),U+8B90(2,8),U+96E0(1,3,8) +U+4EC8(0);U+4EC8(0,9); +U+4EC9(0);U+4EC9(5,9); +U+4ECA(0);U+4ECA(5,9); +U+4ECB(0);U+4ECB(5,9); +U+4ECD(0);U+4ECD(5,9); +U+4ECE(0);U+5F9E(1,3,8,9);U+5F93(3),U+5F9E(1,3,8,9) +U+4ECF(0);U+4F5B(3,8,9);U+4F5B(3,8,9),U+5F7F(2,3,8,9),U+9AF4(2,3,8) +U+4ED0(0);U+4ED0(0); +U+4ED1(0);U+4F96(1,3,8,9),U+5D19(4,9);U+4F96(1,3,8,9),U+5D18(4),U+5D19(4,9) +U+4ED2(0);U+4ED2(0); +U+4ED3(0);U+5009(1,3,8,9);U+5009(1,3,8,9) +U+4ED4(0);U+4ED4(5,9); +U+4ED5(0);U+4ED5(5,9); +U+4ED6(0);U+4ED6(5,9);U+6039(3,9) +U+4ED7(0);U+4ED7(5,9); +U+4ED8(0);U+4ED8(5,9); +U+4ED9(0);U+4ED9(5,9);U+4EDA(3,9),U+50CA(2,3,8,9) +U+4EDA(0);U+4EDA(0,9);U+4ED9(3,9),U+50CA(2,3,8,9) +U+4EDB(0);U+4EDB(0); +U+4EDC(0);U+4EDC(0,9); +U+4EDD(0);U+4EDD(5,9);U+540C(2,3,8,9),U+8855(2,3,8,9) +U+4EDE(0);U+4EDE(5,9); +U+4EDF(0);U+4EDF(5,9);U+5343(3,8,9),U+97C6(1,3,4,8,9) +U+4EE0(0);U+4EE0(0); +U+4EE1(0);U+4EE1(5,9); +U+4EE2(0);U+4EE2(0); +U+4EE3(0);U+4EE3(5,9); +U+4EE4(0);U+4EE4(5,9); +U+4EE5(0);U+4EE5(5,9); +U+4EE6(0);U+4EE6(0); +U+4EE8(0);U+4EE8(5,9); +U+4EE9(0);U+4EE9(0,9);U+4E0A(4,9),U+4E04(0,3,4,8) +U+4EEA(0);U+5100(1,3,8,9);U+5100(1,3,8,9) +U+4EEB(0);U+4EEB(5); +U+4EEC(0);U+5011(1,3,8,9);U+5011(1,3,8,9) +U+4EEF(0);U+4EEF(3); +U+4EF0(0);U+4EF0(5,9);U+4F52(3,9) +U+4EF1(0);U+4EF1(0,9); +U+4EF2(0);U+4EF2(5,9);U+72C6(3,9) +U+4EF3(0);U+4EF3(5,9); +U+4EF4(0);U+4EF4(0,9); +U+4EF5(0);U+4EF5(5,9); +U+4EF6(0);U+4EF6(5,9); + +U+4EF7(0);U+50F9(1,3,8,9);U+4FA1(4),U+50F9(1,3,8,9) +U+4EFB(0);U+4EFB(5,9); +U+4EFD(0);U+4EFD(5,9);U+5F6C(3,8,9) +U+4EFF(0);U+4EFF(5,9);U+5023(2,3,8,9),U+5F77(4,8,9),U+9AE3(2,3,8,9) +U+4F00(0);U+4F00(0,9); +U+4F01(0);U+4F01(5,9); +U+4F02(0);U+4F02(0,9);U+6C9B(3,9) +U+4F03(0);U+4F03(0); +U+4F04(0);U+4F04(0,9); +U+4F05(0);U+4F05(0,9); +U+4F06(0);U+4F06(0); +U+4F08(0);U+4F08(0,9); +U+4F09(0);U+4F09(5,9); +U+4F0A(0);U+4F0A(5,9);U+6D22(3,9) +U+4F0B(0);U+4F0B(3,9);U+89D9(3,9) +U+4F0C(0);U+4F0C(0); +U+4F0D(0);U+4F0D(5,9);U+4E94(3,8,9) +U+4F0E(0);U+4F0E(5,9); +U+4F0F(0);U+4F0F(5,9); +U+4F10(0);U+4F10(5,9); +U+4F11(0);U+4F11(5,9); +U+4F12(0);U+4F12(0,9); +U+4F13(0);U+4F13(0,9); +U+4F14(0);U+4F14(0,9);U+628C(4,9) +U+4F15(0);U+4F15(0,9);U+592B(3,9) +U+4F17(0);U+773E(4,9);U+773E(4,9),U+8846(1,3,8) +U+4F18(0);U+512A(1,3,8,9);U+512A(1,3,8,9) +U+4F19(0);U+4F19(1,3,9),U+5925(1,3,8,9);U+5925(1,3,8,9) +U+4F1A(0);U+6703(1,3,8,9);U+6703(1,3,8,9) +U+4F1B(0);U+50B4(1,3,8,9);U+50B4(1,3,8,9) +U+4F1C(0);U+5005(3,8,9);U+5005(3,8,9) +U+4F1D(0);U+4F1D(0,9); +U+4F1E(0);U+5098(1,3,8,9);U+5098(1,3,8,9),U+7E56(4,9) +U+4F1F(0);U+5049(1,3,8,9);U+5049(1,3,8,9) +U+4F20(0);U+50B3(1,3,8,9);U+50B3(1,3,8,9) +U+4F21(0);U+4FE5(4,8);U+4FE5(4,8) +U+4F22(0);U+4F22(5,9); +U+4F23(0);U+4FD4(4,8,9);U+4FD4(4,8,9) +U+4F24(0);U+50B7(1,3,8,9);U+50B7(1,3,8,9) +U+4F25(0);U+5000(1,3,8,9);U+5000(1,3,8,9) +U+4F26(0);U+502B(1,3,8,9);U+502B(1,3,8,9) +U+4F27(0);U+5096(1,3,8,9);U+5096(1,3,8,9) +U+4F29(0);U+4FE1(7,8,9);U+4FE1(7,8,9) +U+4F2A(0);U+507D(4,8,9);U+507D(4,8,9),U+50DE(1,3,8) +U+4F2B(0);U+4F47(2,3,8,9);U+4F47(2,3,8,9) +U+4F2C(0);U+4F2C(0,9); +U+4F2D(0);U+4F2D(0,9); +U+4F2E(0);U+4F2E(0); +U+4F2F(0);U+4F2F(5,9); +U+4F30(0);U+4F30(5,9); +U+4F32(0);U+4F60(3,8,9);U+4F60(3,8,9),U+511E(3,8),U+59B3(2,3,8,9),U+5976(2,3,8,9),U+5B2D(2,3,8,9) +U+4F33(0);U+4F33(0,9); +U+4F34(0);U+4F34(5,9); +U+4F36(0);U+4F36(5,9); +U+4F38(0);U+4F38(5,9);U+62BB(3,8,9) +U+4F39(0);U+4F39(0); +U+4F3A(0);U+4F3A(5,9); +U+4F3B(0);U+4F3B(0,9); +U+4F3C(0);U+4F3C(5,9); +U+4F3D(0);U+4F3D(5,9); +U+4F3E(0);U+4F3E(3,9); +U+4F3F(0);U+4F3F(0,9); + +U+4F41(0);U+4F41(0,9); +U+4F42(0);U+4F42(0); +U+4F43(0);U+4F43(5,9); +U+4F45(0);U+4F45(0); +U+4F46(0);U+4F46(5,9); +U+4F47(0);U+4F47(3,9);U+4F2B(2,3,8) +U+4F48(0);U+4F48(0,9);U+5E03(2,3,8,9) +U+4F49(0);U+4F49(0,9); +U+4F4A(0);U+4F4A(0); +U+4F4B(0);U+4F4B(0); +U+4F4C(0);U+4F4C(0,9); +U+4F4D(0);U+4F4D(5,9); +U+4F4E(0);U+4F4E(5,9); +U+4F4F(0);U+4F4F(5,9); +U+4F50(0);U+4F50(5,9); +U+4F51(0);U+4F51(5,9); +U+4F52(0);U+4F52(0,9);U+4EF0(3,9) +U+4F53(0);U+9AD4(1,3,8,9);U+8EB0(3),U+8EC6(3),U+9AB5(3),U+9AD4(1,3,8,9) +U+4F54(0);U+4F54(0,9);U+5360(2,3,8,9) +U+4F55(0);U+4F55(5,9); +U+4F56(0);U+4F56(0,9); +U+4F57(0);U+4F57(5,9); +U+4F58(0);U+4F58(5,9); +U+4F59(0);U+4F59(1,3,9),U+9918(1,3,8,9);U+9918(1,3,8,9),U+9980(1,3,4,8) +U+4F5A(0);U+4F5A(5,9); +U+4F5B(0);U+4F5B(5,9);U+4ECF(3,8),U+5F7F(2,9),U+9AF4(2) +U+4F5C(0);U+4F5C(5,9); +U+4F5D(0);U+4F5D(5,9);U+6010(3,9) +U+4F5E(0);U+4F5E(5,9);U+4FAB(4,8) +U+4F5F(0);U+4F5F(5,9); +U+4F60(0);U+4F60(5,9);U+4F32(3,8),U+511E(3),U+59B3(2,3,8,9),U+5976(2,3,8,9),U+5B2D(2,3,8,9) +U+4F61(0);U+4F61(0,9); +U+4F62(0);U+4F62(0,9); +U+4F63(0);U+4F63(1,3,9),U+50AD(1,3,8,9);U+50AD(1,3,8,9) +U+4F64(0);U+4F64(5,9); +U+4F65(0);U+50C9(1,3,8,9);U+50C9(1,3,8,9) +U+4F66(0);U+4F66(0); +U+4F67(0);U+4F67(5,9); +U+4F68(0);U+4F68(0); +U+4F69(0);U+4F69(5,9),U+73EE(4,9);U+73EE(4,9) +U+4F6A(0);U+4F6A(0,9);U+5F8A(3,9) +U+4F6B(0);U+4F6B(0,9); +U+4F6C(0);U+4F6C(5,9);U+72EB(3,9) +U+4F6D(0);U+4F6D(0); +U+4F6E(0);U+4F6E(0,9); +U+4F6F(0);U+4F6F(5,9); +U+4F70(0);U+4F70(5,9); +U+4F72(0);U+4F72(0); +U+4F73(0);U+4F73(5,9); +U+4F74(0);U+4F74(5,9); +U+4F75(0);U+4F75(3,9);U+4E26(3,9),U+5002(3,8),U+5E76(2,9),U+7ADD(3,8),U+5E77(2,3,4,8) +U+4F76(0);U+4F76(5,9); +U+4F77(0);U+4F77(0,9);U+5F88(3,9) +U+4F78(0);U+4F78(3,9); +U+4F79(0);U+4F79(0,9); +U+4F7A(0);U+4F7A(0,9); +U+4F7B(0);U+4F7B(5,9); +U+4F7C(0);U+4F7C(5,9); +U+4F7D(0);U+4F7D(0,9); +U+4F7E(0);U+4F7E(5,9); +U+4F7F(0);U+4F7F(5,9); + +U+4F80(0);U+4F80(0,9); +U+4F81(0);U+4F81(0,9); +U+4F82(0);U+4F82(3,9); +U+4F83(0);U+4F83(5,9); +U+4F84(0);U+4F84(5,9),U+59EA(2,8,9);U+59EA(2,8,9) +U+4F85(0);U+4F85(0,9); +U+4F86(0);U+4F86(0,9);U+6765(1,3,8) +U+4F87(0);U+4F87(0,9);U+5937(3,9) +U+4F88(0);U+4F88(5,9); +U+4F89(0);U+4F89(5,9); +U+4F8A(0);U+4F8A(0); +U+4F8B(0);U+4F8B(5,9); +U+4F8D(0);U+4F8D(5,9); +U+4F8F(0);U+4F8F(5,9); +U+4F90(0);U+4F90(3,9); +U+4F91(0);U+4F91(5,9); +U+4F92(0);U+4F92(0,9);U+5B89(3,9) +U+4F93(0);U+4F93(0); +U+4F94(0);U+4F94(5,9); +U+4F95(0);U+4F95(0,9); +U+4F96(0);U+4F96(0,9);U+4ED1(1,3,8),U+5D18(2),U+5D19(2,3,9) +U+4F97(0);U+4F97(5,9); +U+4F98(0);U+4F98(0,9);U+8BE7(3),U+8A6B(1,3,8,9) +U+4F99(0);U+4F99(3); +U+4F9A(0);U+4F9A(0,9); +U+4F9B(0);U+4F9B(5,9); +U+4F9C(0);U+4F9C(3,9); +U+4F9D(0);U+4F9D(5,9); +U+4F9E(0);U+4F9E(0,9); +U+4F9F(0);U+4F9F(0); +U+4FA0(0);U+4FE0(1,3,8,9);U+4FE0(1,3,8,9) +U+4FA1(0);U+50F9(8,9);U+4EF7(4,9),U+50F9(8,9) +U+4FA3(0);U+4FB6(4,8,9);U+4FB6(4,8,9) +U+4FA4(0);U+4FA4(0); +U+4FA5(0);U+50E5(1,8,9);U+50E5(1,8,9),U+510C(4,9),U+5FBA(3) +U+4FA6(0);U+5075(1,3,8,9);U+5075(1,3,8,9),U+9049(4,9) +U+4FA7(0);U+5074(1,3,8,9);U+5074(1,3,8,9) +U+4FA8(0);U+50D1(1,3,8,9);U+50D1(1,3,8,9) +U+4FA9(0);U+5108(1,3,8,9);U+5108(1,3,8,9) +U+4FAA(0);U+5115(1,3,8,9);U+5115(1,3,8,9) +U+4FAB(0);U+4F5E(4,8,9);U+4F5E(4,8,9) +U+4FAC(0);U+5102(1,3,8,9);U+5102(1,3,8,9) +U+4FAE(0);U+4FAE(5,9); +U+4FAF(0);U+4FAF(5,9); +U+4FB0(0);U+4FB0(0); +U+4FB1(0);U+4FB1(0); +U+4FB2(0);U+4FB2(0,9); +U+4FB3(0);U+4FB3(0,9); +U+4FB4(0);U+4FB4(0); +U+4FB5(0);U+4FB5(5,9); +U+4FB6(0);U+4FB6(0,9);U+4FA3(4,8) +U+4FB7(0);U+4FB7(0,9);U+5C40(2,9),U+8DFC(2,9) +U+4FB8(0);U+4FB8(0); +U+4FB9(0);U+4FB9(0,9); +U+4FBA(0);U+4FBA(0,9); +U+4FBB(0);U+4FBB(0,9); +U+4FBC(0);U+4FBC(0); +U+4FBE(0);U+4FBE(0); +U+4FBF(0);U+4FBF(5,9); +U+4FC0(0);U+4FC0(0,9); +U+4FC1(0);U+4FC1(0,9);U+4FE3(4,8) +U+4FC2(0);U+4FC2(0,9);U+7CFB(1,3,8,9),U+7E6B(1,3,4,8,9) +U+4FC3(0);U+4FC3(5,9); + +U+4FC4(0);U+4FC4(5,9); +U+4FC5(0);U+4FC5(5,9); +U+4FC7(0);U+4FC7(3,9); +U+4FC9(0);U+4FC9(0,9); +U+4FCA(0);U+4FCA(5,9);U+5101(2,3,8) +U+4FCB(0);U+4FCB(0,9); +U+4FCD(0);U+4FCD(0,9); +U+4FCE(0);U+4FCE(5,9);U+723C(3,8) +U+4FCF(0);U+4FCF(5,9); +U+4FD0(0);U+4FD0(5,9); +U+4FD1(0);U+4FD1(5,9); +U+4FD2(0);U+4FD2(0); +U+4FD3(0);U+4FD3(0,9); +U+4FD4(0);U+4FD4(0,9);U+4F23(4,8) +U+4FD5(0);U+4FD5(0); +U+4FD6(0);U+4FD6(0,9); +U+4FD7(0);U+4FD7(5,9); +U+4FD8(0);U+4FD8(5,9); +U+4FD9(0);U+4FD9(0,9); +U+4FDA(0);U+4FDA(5,9); +U+4FDB(0);U+4FDB(0,9);U+4FEF(2,3,9),U+982B(2,3,9) +U+4FDC(0);U+4FDC(5,9); +U+4FDD(0);U+4FDD(5,9);U+5AAC(4,9) +U+4FDE(0);U+4FDE(5,9);U+516A(3,8),U+9103(4,9) +U+4FDF(0);U+4FDF(5,9);U+7AE2(2,8) +U+4FE0(0);U+4FE0(0,9);U+4FA0(1,3,8) +U+4FE1(0);U+4FE1(5,9);U+4F29(7,8) +U+4FE3(0);U+4FC1(4,8,9);U+4FC1(4,8,9) +U+4FE4(0);U+4FE4(0); +U+4FE5(0);U+4FE5(0);U+4F21(4,8) +U+4FE6(0);U+5114(1,3,8,9);U+5114(1,3,8,9) +U+4FE7(0);U+4FE7(0); +U+4FE8(0);U+513C(1,3,8,9);U+513C(1,3,8,9) +U+4FE9(0);U+5006(1,3,8,9);U+5006(1,3,8,9) +U+4FEA(0);U+5137(1,3,8,9);U+5137(1,3,8,9) +U+4FEB(0);U+5008(4,8);U+5008(4,8) +U+4FEC(0);U+4FEC(0,9); +U+4FED(0);U+5109(1,3,8,9);U+5039(4),U+5109(1,3,8,9) +U+4FEE(0);U+4FEE(5,9);U+8129(2,3,9) +U+4FEF(0);U+4FEF(5,9);U+4FDB(2,3,9),U+982B(2,3,9) +U+4FF0(0);U+4FF0(0); +U+4FF1(0);U+4FF1(5,9);U+5036(4,8) +U+4FF2(0);U+509A(3,9);U+509A(3,9),U+6548(7,8,9),U+52B9(2,3,7,8) +U+4FF3(0);U+4FF3(5,9); +U+4FF4(0);U+4FF4(0,9); +U+4FF5(0);U+4FF5(3,9); +U+4FF6(0);U+4FF6(3,9); +U+4FF7(0);U+4FF7(0,9); +U+4FF8(0);U+4FF8(5,9); +U+4FF9(0);U+4FF9(0); +U+4FFA(0);U+4FFA(5,9); +U+4FFB(0);U+5099(2,3,8,9);U+5907(4),U+5099(2,3,8,9),U+5079(3,4) +U+4FFE(0);U+4FFE(5,9); +U+4FFF(0);U+4FFF(0); +U+5000(0);U+5000(0,9);U+4F25(1,3,8) +U+5001(0);U+5001(0); +U+5002(0);U+4F75(3,8,9);U+4F75(3,8,9),U+5E76(4,9),U+4E26(0,3,8,9),U+7ADD(3,8),U+5E77(2,3,4,8) +U+5003(0);U+5003(0); +U+5004(0);U+5004(0); +U+5005(0);U+5005(3,9);U+4F1C(3,8) +U+5006(0);U+5006(0,9);U+4FE9(1,3,8) +U+5007(0);U+5007(0,9);U+5A49(4,9) + +U+5008(0);U+5008(0);U+4FEB(4,8) +U+5009(0);U+5009(0,9);U+4ED3(1,3,8) +U+500A(0);U+500A(0); +U+500B(0);U+500B(0,9);U+4E2A(1,3,8),U+7B87(2,3,8,9) +U+500C(0);U+500C(5,9); +U+500D(0);U+500D(5,9); +U+500E(0);U+500E(0,9);U+8146(3,9) +U+500F(0);U+500F(5,9);U+5135(2,3,9) +U+5011(0);U+5011(0,9);U+4EEC(1,3,8) +U+5012(0);U+5012(5,9); +U+5013(0);U+5013(0,9); +U+5014(0);U+5014(5,9); +U+5015(0);U+5015(0,9); +U+5016(0);U+5016(0,9);U+5E78(2,3,8,9) +U+5017(0);U+5017(0,9); +U+5018(0);U+5018(5,9); +U+5019(0);U+5019(5,9); +U+501A(0);U+501A(5,9); +U+501B(0);U+501B(0,9); +U+501C(0);U+501C(5,9); +U+501D(0);U+501D(0); +U+501E(0);U+501E(3,9); +U+501F(0);U+501F(1,3,9),U+85C9(1,3,8,9);U+8024(3,9),U+85C9(1,3,8,9) +U+5020(0);U+5020(0,9); +U+5021(0);U+5021(5,9); +U+5022(0);U+5022(4,9); +U+5023(0);U+5023(3,9);U+4EFF(2,3,8,9),U+5F77(2,3,4,8,9),U+9AE3(2,3,8,9) +U+5024(0);U+503C(7,8,9);U+503C(7,8,9) +U+5025(0);U+5025(5,9); +U+5026(0);U+5026(5,9);U+52B5(3),U+5238(2,3,9) +U+5027(0);U+5027(0,9); +U+5028(0);U+5028(5,9); +U+5029(0);U+5029(5,9); +U+502A(0);U+502A(5,9);U+6DE3(3,9) +U+502B(0);U+502B(0,9);U+4F26(1,3,8) +U+502C(0);U+502C(5,9); +U+502D(0);U+502D(5,9); +U+502E(0);U+502E(5); +U+502F(0);U+502F(0,9); +U+5030(0);U+5030(0,9); +U+5031(0);U+5031(0,9); +U+5032(0);U+5032(4); +U+5033(0);U+5033(4,9);U+525A(3,4,9) +U+5035(0);U+5035(0,9); +U+5036(0);U+4FF1(4,8,9);U+4FF1(4,8,9) +U+5037(0);U+5037(0,9); +U+5039(0);U+5109(7,8,9);U+4FED(4),U+5109(7,8,9) +U+503A(0);U+50B5(1,3,8,9);U+50B5(1,3,8,9) +U+503B(0);U+503B(0); +U+503C(0);U+503C(5,9);U+5024(7,8) +U+503E(0);U+50BE(1,3,8,9);U+50BE(1,3,8,9) +U+503F(0);U+503F(0); +U+5040(0);U+5040(0,9);U+82F1(3,9) +U+5041(0);U+5041(0,9);U+79F0(3),U+7A31(1,3,8,9) +U+5043(0);U+5043(5,9); +U+5044(0);U+5044(3); +U+5045(0);U+5045(0,9); +U+5046(0);U+5046(0,9); +U+5047(0);U+5047(5,9); +U+5048(0);U+5048(5,9); +U+5049(0);U+5049(0,9);U+4F1F(1,3,8) +U+504A(0);U+504A(0,9); +U+504B(0);U+504B(0,9); + +U+504C(0);U+504C(5,9); +U+504D(0);U+504D(0,9); +U+504E(0);U+504E(5,9); +U+504F(0);U+504F(5,9); +U+5051(0);U+5051(0,9); +U+5053(0);U+5053(0,9); +U+5054(0);U+5054(0); +U+5055(0);U+5055(5,9); +U+5056(0);U+5056(0); +U+5057(0);U+5057(0,9); +U+5059(0);U+5059(3); +U+505A(0);U+505A(5,9); +U+505B(0);U+505B(0,9); +U+505C(0);U+505C(5,9); +U+505D(0);U+505D(0,9);U+80CC(3,9),U+63F9(2,3,9) +U+505E(0);U+505E(4,9); +U+505F(0);U+505F(0,9); +U+5060(0);U+5060(3,9); +U+5061(0);U+5061(0,9); +U+5062(0);U+5062(0,9);U+7785(7,9) +U+5063(0);U+5063(0,9); +U+5064(0);U+5064(0,9); +U+5065(0);U+5065(5,9); +U+5066(0);U+5066(3); +U+5067(0);U+5067(0); +U+5068(0);U+5068(0,9); +U+5069(0);U+5069(0,9); +U+506A(0);U+506A(3,9); +U+506B(0);U+506B(0,9); +U+506C(0);U+506C(5);U+50AF(2,3,9) +U+506D(0);U+506D(0,9); +U+506E(0);U+506E(0,9); +U+506F(0);U+506F(0,9); +U+5070(0);U+5070(0,9); +U+5071(0);U+5071(0); +U+5072(0);U+5072(0,9); +U+5073(0);U+5073(0,9); +U+5074(0);U+5074(0,9);U+4FA7(1,3,8) +U+5075(0);U+5075(0,9);U+4FA6(1,3,8),U+9049(1,3,4,8,9) +U+5076(0);U+5076(5,9); +U+5077(0);U+5077(5,9);U+5078(4,8),U+5A7E(4),U+5AAE(2,3,9) +U+5078(0);U+5077(4,8,9);U+5077(4,8,9),U+5A7E(4,8),U+5AAE(2,3,4,8,9) +U+5079(0);U+5099(3,8,9);U+5907(3),U+5099(3,8,9),U+4FFB(0,3,4) +U+507A(0);U+507A(0,9);U+54B1(2,3,9),U+5592(2,3,9) +U+507B(0);U+50C2(1,3,8,9);U+50C2(1,3,8,9) +U+507D(0);U+507D(0,9);U+4F2A(4,8),U+50DE(3,4,8) +U+507E(0);U+50E8(1,3,8,9);U+50E8(1,3,8,9) +U+507F(0);U+511F(1,3,8,9);U+511F(1,3,8,9) +U+5080(0);U+5080(5,9); +U+5082(0);U+5082(0,9); +U+5083(0);U+5083(0,9); +U+5084(0);U+5084(0); +U+5085(0);U+5085(5,9); +U+5086(0);U+5086(0); +U+5087(0);U+5087(0,9); +U+5088(0);U+5088(5); +U+5089(0);U+5089(0); +U+508A(0);U+508A(0); +U+508B(0);U+508B(0,9); +U+508C(0);U+508C(0,9);U+9A82(4),U+7F75(4,8,9),U+99E1(1,3,4,8) +U+508D(0);U+508D(5,9);U+5FAC(3,9) +U+508E(0);U+508E(0,9);U+98A0(3),U+985B(1,3,8,9),U+985A(3) +U+508F(0);U+508F(0); + +U+5090(0);U+5090(0); +U+5091(0);U+5091(0,9);U+6770(2,3,8,9) +U+5092(0);U+5092(0,9); +U+5094(0);U+5094(0,9); +U+5095(0);U+5095(0,9); +U+5096(0);U+5096(0,9);U+4F27(1,3,8) +U+5098(0);U+5098(0,9);U+4F1E(1,3,8),U+7E56(1,3,4,8,9) +U+5099(0);U+5099(0,9);U+5907(1,3,8),U+4FFB(2,3,8),U+5079(3,8) +U+509A(0);U+509A(3,9);U+4FF2(3),U+6548(2,3,9),U+52B9(2,3,7,8) +U+509B(0);U+509B(0,9); +U+509C(0);U+509C(0,9);U+5FAD(4,9) +U+509D(0);U+509D(0,9); +U+509E(0);U+509E(0,9); +U+50A2(0);U+50A2(0,9);U+5BB6(1,3,8,9) +U+50A3(0);U+50A3(5,9); +U+50A4(0);U+510E(4,8);U+510E(4,8) +U+50A5(0);U+513B(1,3,4,8,9);U+513B(1,3,4,8,9) +U+50A6(0);U+50A6(0); +U+50A7(0);U+5110(1,3,8,9);U+5110(1,3,8,9) +U+50A8(0);U+5132(1,3,8,9);U+5132(1,3,8,9) +U+50A9(0);U+513A(1,3,8,9);U+513A(1,3,8,9) +U+50AA(0);U+50AA(0); +U+50AB(0);U+50AB(3); +U+50AC(0);U+50AC(5,9); +U+50AD(0);U+50AD(0,9);U+4F63(1,3,8,9) +U+50AE(0);U+50AE(0,9);U+5608(4,9) +U+50AF(0);U+50AF(0,9);U+506C(2,3) +U+50B0(0);U+50B0(0,9); +U+50B1(0);U+50B1(0,9); +U+50B2(0);U+50B2(5,9); +U+50B3(0);U+50B3(0,9);U+4F20(1,3,8) +U+50B4(0);U+50B4(0,9);U+4F1B(1,3,8) +U+50B5(0);U+50B5(0,9);U+503A(1,3,8) +U+50B6(0);U+50B6(0,9);U+8160(4,9) +U+50B7(0);U+50B7(0,9);U+4F24(1,3,8) +U+50B8(0);U+50B8(0,9); +U+50BA(0);U+50BA(5,9); +U+50BB(0);U+50BB(5,9);U+510D(3,8) +U+50BC(0);U+50BC(0); +U+50BD(0);U+50BD(0,9); +U+50BE(0);U+50BE(0,9);U+503E(1,3,8) +U+50BF(0);U+50BF(0,9); +U+50C0(0);U+50C0(0); +U+50C1(0);U+50C1(0,9); +U+50C2(0);U+50C2(0,9);U+507B(1,3,8) +U+50C4(0);U+50C4(0,9); +U+50C5(0);U+50C5(0,9);U+4EC5(1,3,8) +U+50C6(0);U+50C6(0,9); +U+50C7(0);U+50C7(0,9); +U+50C8(0);U+50C8(0,9); +U+50C9(0);U+50C9(0,9);U+4F65(1,3,8) +U+50CA(0);U+50CA(0,9);U+4ED9(2,3,8,9),U+4EDA(2,3,8,9) +U+50CB(0);U+50CB(0,9); +U+50CC(0);U+50CC(0); +U+50CD(0);U+52D5(2,9);U+52A8(4),U+52D5(2,9) +U+50CE(0);U+50CE(0,9); +U+50CF(0);U+50CF(5,9);U+8C61(3,8,9) +U+50D0(0);U+50D0(0); +U+50D1(0);U+50D1(0,9);U+4FA8(1,3,8) +U+50D2(0);U+50D2(3); +U+50D3(0);U+50D3(0,9); +U+50D4(0);U+50D4(0,9); +U+50D5(0);U+50D5(0,9);U+4EC6(1,3,8,9) + +U+50D6(0);U+50D6(5,9); +U+50D7(0);U+50D7(0,9); +U+50D9(0);U+50D9(3); +U+50DA(0);U+50DA(5,9); +U+50DB(0);U+50DB(0,9); +U+50DC(0);U+50DC(0); +U+50DD(0);U+50DD(0,9); +U+50DE(0);U+507D(3,4,8,9);U+4F2A(1,3,8),U+507D(3,4,8,9) +U+50E0(0);U+50E0(0,9); +U+50E3(0);U+50E3(0,9);U+50ED(3,8,9) +U+50E4(0);U+50E4(0,9); +U+50E5(0);U+50E5(0,9);U+4FA5(1,8),U+510C(2,8,9),U+5FBA(8) +U+50E6(0);U+50E6(5,9); +U+50E7(0);U+50E7(5,9); +U+50E8(0);U+50E8(0,9);U+507E(1,3,8) +U+50E9(0);U+50E9(3,9); +U+50EA(0);U+50EA(0,9); +U+50EC(0);U+50EC(5,9); +U+50ED(0);U+50ED(5,9);U+50E3(3,8,9) +U+50EE(0);U+50EE(5,9);U+735E(3,9) +U+50EF(0);U+50EF(0,9); +U+50F0(0);U+50F0(0,9); +U+50F1(0);U+50F1(0,9);U+96C7(2,3,9) +U+50F2(0);U+50F2(0); +U+50F3(0);U+50F3(5,9); +U+50F5(0);U+50F5(5,9);U+6BAD(2,3,9) +U+50F6(0);U+50F6(0,9); +U+50F8(0);U+50F8(3,9); +U+50F9(0);U+50F9(0,9);U+4EF7(1,3,8,9),U+4FA1(8) +U+50FA(0);U+50FA(0); +U+50FB(0);U+50FB(5,9); +U+50FC(0);U+50FC(0); +U+50FD(0);U+50FD(3,9); +U+50FE(0);U+50FE(3,9); +U+50FF(0);U+50FF(0,9); +U+5100(0);U+5100(0,9);U+4EEA(1,3,8) +U+5101(0);U+4FCA(2,3,8,9);U+4FCA(2,3,8,9) +U+5102(0);U+5102(0,9);U+4FAC(1,3,8) +U+5103(0);U+5103(3,9); +U+5104(0);U+5104(0,9);U+4EBF(1,3,8) +U+5105(0);U+5105(0,9); +U+5106(0);U+5106(5,9);U+61BC(3,9) +U+5107(0);U+5107(5,9); +U+5108(0);U+5108(0,9);U+4FA9(1,3,8) +U+5109(0);U+5109(0,9);U+4FED(1,3,8),U+5039(7,8) +U+510A(0);U+510A(0,9); +U+510B(0);U+510B(5,9); +U+510C(0);U+510C(3,9);U+4FA5(4),U+50E5(2,8,9),U+5FBA(3) +U+510D(0);U+50BB(3,8,9);U+50BB(3,8,9) +U+510E(0);U+510E(0);U+50A4(4,8) +U+510F(0);U+510F(0); +U+5110(0);U+5110(0,9);U+50A7(1,3,8) +U+5111(0);U+5111(0,9); +U+5112(0);U+5112(5,9); +U+5113(0);U+5113(0,9); +U+5114(0);U+5114(0,9);U+4FE6(1,3,8) +U+5115(0);U+5115(0,9);U+4FAA(1,3,8) +U+5116(0);U+5116(0); +U+5117(0);U+5117(0,9);U+62DF(4),U+64EC(2,8,9) +U+5118(0);U+5118(0,9);U+5C3D(1,3,8),U+76E1(4,9) +U+5119(0);U+5119(0); +U+511A(0);U+511A(0,9); +U+511C(0);U+511C(3,9); + +U+511D(0);U+511D(0); +U+511E(0);U+4F60(3,9);U+4F60(3,9),U+4F32(3,5,8),U+59B3(2,3,8,9),U+5976(2,3,8,9),U+5B2D(2,3,8,9) +U+511F(0);U+511F(0,9);U+507F(1,3,8) +U+5120(0);U+5120(0,9); +U+5121(0);U+5121(5,9); +U+5122(0);U+5122(0,9); +U+5123(0);U+5123(0); +U+5124(0);U+5124(3,9); +U+5125(0);U+5125(0,9); +U+5126(0);U+5126(0,9); +U+5127(0);U+5127(0); +U+5129(0);U+5129(0,9); +U+512A(0);U+512A(0,9);U+4F18(1,3,8,9) +U+512C(0);U+512C(0); +U+512D(0);U+512D(0,9); +U+512E(0);U+512E(0,9); +U+512F(0);U+512F(0); +U+5130(0);U+5130(0,9); +U+5131(0);U+5131(0,9); +U+5132(0);U+5132(0,9);U+50A8(1,3,8) +U+5133(0);U+5133(0,9); +U+5134(0);U+5134(0,9); +U+5135(0);U+5135(0,9);U+500F(2,3,9) +U+5136(0);U+5136(0); +U+5137(0);U+5137(0,9);U+4FEA(1,3,8) +U+5138(0);U+5138(0,9); +U+5139(0);U+5139(3,9); +U+513A(0);U+513A(0,9);U+50A9(1,3,8) +U+513B(0);U+513B(0,9);U+50A5(1,3,8) +U+513C(0);U+513C(0,9);U+4FE8(1,3,8) +U+513D(0);U+513D(3,9); +U+513E(0);U+513E(0); +U+513F(0);U+5152(1,3,8,9);U+5150(3),U+5152(1,3,8,9) +U+5140(0);U+5140(5,9); +U+5141(0);U+5141(5,9); +U+5143(0);U+5143(5,9); +U+5144(0);U+5144(5,9); +U+5145(0);U+5145(5,9); +U+5146(0);U+5146(5,9); +U+5147(0);U+5147(0,9);U+51F6(2,3,8,9) +U+5148(0);U+5148(5,9); +U+5149(0);U+5149(5,9);U+706E(3,8),U+709A(3,9),U+70E1(3,9) +U+514B(0);U+514B(1,3,9);U+524B(1,3,4,8,9),U+5C05(4) +U+514C(0);U+514C(0,9);U+5151(4,8) +U+514D(0);U+514D(5,9); +U+514E(0);U+5154(2,3,8,9);U+5154(2,3,8,9) +U+5150(0);U+5152(3,8,9);U+513F(3,9),U+5152(3,8,9) +U+5151(0);U+514C(4,8,9);U+514C(4,8,9) +U+5152(0);U+5152(0,9);U+513F(1,3,8,9),U+5150(3,8) +U+5154(0);U+5154(5,9);U+514E(2,3,8) +U+5155(0);U+5155(5,9); +U+5156(0);U+5157(3,8,9);U+5157(3,8,9) +U+5157(0);U+5157(3,9);U+5156(3,8) +U+5159(0);U+5159(0,9); +U+515A(0);U+9EE8(1,3,4,8,9);U+9EE8(1,3,4,8,9) +U+515B(0);U+515B(0,9); +U+515C(0);U+515C(5,9); +U+515D(0);U+515D(0,9); +U+515E(0);U+515E(0,9); +U+515F(0);U+515F(0,9); +U+5161(0);U+5161(0,9); +U+5162(0);U+5162(5,9); + +U+5163(0);U+5163(0,9); +U+5165(0);U+5165(5,9); +U+5166(0);U+4EA1(3,8,9);U+4EA1(3,8,9),U+4EBE(4) +U+5167(0);U+5167(0,9);U+5185(4,8) +U+5168(0);U+5168(5,9); +U+5169(0);U+5169(0,9);U+4E21(3,8),U+4E24(1,3,8) +U+516A(0);U+4FDE(3,8,9);U+4FDE(3,8,9),U+9103(3,4,8,9) +U+516B(0);U+516B(5,9);U+634C(3,8,9) +U+516C(0);U+516C(5,9); +U+516D(0);U+516D(5,9); +U+516E(0);U+516E(5,9); +U+516F(0);U+516F(0); +U+5170(0);U+862D(1,3,8,9);U+862D(1,3,8,9) +U+5171(0);U+5171(5,9); +U+5173(0);U+95DC(1,3,8,9);U+959E(3,9),U+95A2(3),U+95D7(3),U+95DC(1,3,8,9) +U+5174(0);U+8208(1,3,8,9);U+8208(1,3,8,9) +U+5175(0);U+5175(5,9); +U+5176(0);U+5176(5,9);U+4E0C(3,8,9),U+4E93(3,8,9) +U+5177(0);U+5177(5,9); +U+5178(0);U+5178(5,9); +U+5179(0);U+8332(3,4,8,9);U+7386(7,9),U+8332(3,4,8,9) +U+517A(0);U+517A(0); +U+517B(0);U+990A(1,3,8,9);U+990A(1,3,8,9) +U+517C(0);U+517C(5,9); +U+517D(0);U+7378(1,3,8,9);U+7378(1,3,8,9) +U+517F(0);U+85DD(4,8,9);U+827A(4),U+85DD(4,8,9),U+84FA(3,4,9) +U+5180(0);U+5180(5,9); +U+5181(0);U+56C5(1,3,8,9);U+56C5(1,3,8,9) +U+5182(0);U+5182(5); +U+5185(0);U+5167(4,8,9);U+5167(4,8,9) +U+5186(0);U+5713(4,8,9);U+5706(4),U+5713(4,8,9),U+570E(3,4) +U+5187(0);U+5187(0,9); +U+5188(0);U+5CA1(1,3,8,9);U+5CA1(1,3,8,9),U+5D17(1,3,4,8,9),U+5C97(1,3,4,8) +U+5189(0);U+5189(5,9); +U+518A(0);U+518A(0,9);U+518C(2,3,8) +U+518B(0);U+518B(3); +U+518C(0);U+518A(2,3,8,9);U+518A(2,3,8,9) +U+518D(0);U+518D(5,9); +U+518F(0);U+518F(3,9);U+56E7(3,9) +U+5190(0);U+5192(2,3,8,9);U+5192(2,3,8,9) +U+5191(0);U+5191(0,9);U+80C4(4,8,9) +U+5192(0);U+5192(5,9);U+5190(2,3,8) +U+5193(0);U+5193(0,9);U+6784(3,9),U+6406(3,4,9),U+69CB(1,3,8,9) +U+5194(0);U+5194(0,9); +U+5195(0);U+5195(5,9); +U+5196(0);U+5196(5); +U+5197(0);U+5197(5,9);U+5B82(2,8) +U+5198(0);U+5198(0,9); +U+5199(0);U+5BEB(1,3,8,9);U+5BEB(1,3,8,9) +U+519A(0);U+519A(0); +U+519B(0);U+8ECD(1,3,8,9);U+8ECD(1,3,8,9) +U+519C(0);U+8FB2(1,3,8,9);U+8FB2(1,3,8,9) +U+519D(0);U+5B9C(3,8,9);U+5B9C(3,8,9) +U+519E(0);U+519E(3,9);U+5F25(7),U+5F4C(1,3,7,8,9),U+7030(1,3,7,9) +U+519F(0);U+519F(0); +U+51A0(0);U+51A0(5,9); +U+51A2(0);U+51A2(5,9);U+585A(2,3,8,9) +U+51A4(0);U+51A4(5,9);U+5BC3(2,3,8) +U+51A5(0);U+51A5(5,9); +U+51A6(0);U+5BC7(3,8,9);U+5BC7(3,8,9) +U+51A7(0);U+51A7(0); +U+51A8(0);U+5BCC(3,8,9);U+5BCC(3,8,9) +U+51AA(0);U+51AA(3,9);U+5E42(2,3),U+7F83(3,8,9) + +U+51AB(0);U+51AB(5); +U+51AC(0);U+51AC(1,3,9);U+9F15(1,3,4,8,9) +U+51AE(0);U+51AE(0); +U+51AF(0);U+99AE(1,3,8,9);U+99AE(1,3,8,9) +U+51B0(0);U+51B0(5,9);U+6C37(2,3,8) +U+51B1(0);U+51B1(5,9);U+6C8D(3,8,9) +U+51B2(0);U+6C96(3,4,8,9),U+885D(1,3,4,8,9);U+6C96(3,4,8,9),U+794C(3,9),U+885D(1,3,4,8,9),U+8876(4,9),U+76C5(3,4,8,9) +U+51B3(0);U+6C7A(2,3,8,9);U+6C7A(2,3,8,9) +U+51B5(0);U+6CC1(2,4,8,9);U+6CC1(2,4,8,9) +U+51B6(0);U+51B6(5,9); +U+51B7(0);U+51B7(5,9); +U+51B9(0);U+51B9(0,9); +U+51BB(0);U+51CD(1,3,8,9);U+51CD(1,3,8,9) +U+51BC(0);U+51BC(5,9); +U+51BD(0);U+51BD(5,9);U+6D0C(3,8,9) +U+51BE(0);U+51BE(0,9);U+6D3D(3,9) +U+51BF(0);U+51BF(0); +U+51C0(0);U+6DE8(3,4,8,9);U+51C8(4,8,9),U+6D44(2,4),U+6DE8(3,4,8,9) +U+51C1(0);U+51C1(0); +U+51C3(0);U+6D82(3,9);U+6D82(3,9),U+5857(1,3,4,8,9) +U+51C4(0);U+6DD2(2,3,8,9);U+60BD(2,9),U+6DD2(2,3,8,9) +U+51C5(0);U+51C5(0,9); +U+51C6(0);U+51C6(1,3,9),U+6E96(1,3,8,9);U+51D6(3),U+6E96(1,3,8,9) +U+51C7(0);U+51C7(5); +U+51C8(0);U+51C8(0,9);U+51C0(4,8),U+6D44(2,4,8),U+6DE8(3,4,8,9) +U+51C9(0);U+6DBC(2,3,8,9);U+6DBC(2,3,8,9) +U+51CA(0);U+51CA(0,9);U+6E05(4,9),U+6DF8(4,8) +U+51CB(0);U+51CB(5,9); +U+51CC(0);U+51CC(5,9),U+6DE9(3,9);U+6DE9(3,9) +U+51CD(0);U+51CD(0,9);U+51BB(1,3,8) +U+51CE(0);U+51CE(0,9); +U+51CF(0);U+6E1B(2,3,8,9);U+6E1B(2,3,8,9) +U+51D0(0);U+51D0(3,9); +U+51D1(0);U+6E4A(2,3,9);U+6E4A(2,3,9) +U+51D4(0);U+51D4(3,9); +U+51D5(0);U+51D5(0); +U+51D6(0);U+6E96(3,8,9);U+51C6(3,9),U+6E96(3,8,9) +U+51D7(0);U+51D7(0,9); +U+51D8(0);U+51D8(3,9); +U+51D9(0);U+51D9(0); +U+51DA(0);U+51DA(0); +U+51DB(0);U+51DC(3,4,8,9);U+51DC(3,4,8,9) +U+51DC(0);U+51DC(0,9);U+51DB(3,4,8) +U+51DD(0);U+51DD(5,9); +U+51DE(0);U+51DE(0,9); +U+51E0(0);U+51E0(1,3,9),U+5E7E(1,3,8,9);U+5E7E(1,3,8,9) +U+51E1(0);U+51E1(5,9);U+51E2(2,3,8),U+51E3(4,8) +U+51E2(0);U+51E1(2,3,8,9);U+51E1(2,3,8,9),U+51E3(4) +U+51E3(0);U+51E1(4,8,9);U+51E1(4,8,9),U+51E2(4) +U+51E4(0);U+9CF3(1,3,8,9);U+9CEF(3),U+9CF3(1,3,8,9) +U+51E5(0);U+51E5(0); +U+51E7(0);U+51E7(0); +U+51E8(0);U+98A8(3,8,9);U+98A8(3,8,9),U+98CE(3),U+98CC(3,9) +U+51E9(0);U+51E9(0); +U+51EA(0);U+51EA(0); +U+51EB(0);U+9CE7(4,9);U+9CE7(4,9),U+9CEC(1,3,8) +U+51ED(0);U+6191(1,3,4,8,9);U+51F4(3),U+6191(1,3,4,8,9) +U+51EF(0);U+51F1(1,3,8,9);U+51F1(1,3,8,9) +U+51F0(0);U+51F0(5,9); +U+51F1(0);U+51F1(0,9);U+51EF(1,3,8) +U+51F3(0);U+51F3(5,9); +U+51F4(0);U+6191(2,8,9);U+51ED(3),U+6191(2,8,9) + +U+51F5(0);U+51F5(5,9); +U+51F6(0);U+51F6(5,9),U+5147(2,3,8,9);U+5147(2,3,8,9) +U+51F7(0);U+584A(3,8,9);U+5757(3),U+584A(3,8,9) +U+51F8(0);U+51F8(5,9); +U+51F9(0);U+51F9(5,9); +U+51FA(0);U+51FA(1,9),U+9F63(1,3,9);U+5C80(3,8),U+9F63(1,3,9) +U+51FB(0);U+64CA(1,3,8,9);U+6483(4),U+64CA(1,3,8,9) +U+51FC(0);U+51FC(5); +U+51FD(0);U+51FD(5,9);U+51FE(3,8),U+80A3(3,9) +U+51FE(0);U+51FD(3,8,9);U+51FD(3,8,9),U+80A3(3,8,9) +U+51FF(0);U+947F(1,3,8,9);U+947F(1,3,8,9) +U+5200(0);U+5200(5,9);U+5202(3,8) +U+5201(0);U+5201(5,9); +U+5202(0);U+5200(3,8,9);U+5200(3,8,9) +U+5203(0);U+5203(5,9);U+5204(3,8) +U+5204(0);U+5203(3,8,9);U+5203(3,8,9) +U+5205(0);U+5205(0); +U+5206(0);U+5206(5,9); +U+5207(0);U+5207(5,9); +U+5208(0);U+5208(5,9);U+82C5(3,8) +U+5209(0);U+5209(0,9); +U+520A(0);U+520A(5,9);U+520B(4,8) +U+520B(0);U+520A(4,8,9);U+520A(4,8,9) +U+520C(0);U+520C(0,9);U+5FD6(3,9) +U+520D(0);U+82BB(1,3,8,9);U+82BB(1,3,8,9) +U+520E(0);U+520E(5,9); +U+520F(0);U+520F(3); +U+5210(0);U+5210(0,9); +U+5211(0);U+5211(5,9); +U+5212(0);U+5212(1,3,9),U+5283(1,3,8,9);U+5283(1,3,8,9) +U+5213(0);U+5213(3,9); +U+5214(0);U+6289(7,8,9);U+6289(7,8,9) +U+5215(0);U+5215(0); +U+5216(0);U+5216(5,9); +U+5217(0);U+5217(5,9); +U+5218(0);U+5289(1,3,8,9);U+5289(1,3,8,9) +U+5219(0);U+5247(1,3,8,9);U+5247(1,3,8,9) +U+521A(0);U+525B(1,3,8,9);U+525B(1,3,8,9) +U+521B(0);U+5275(1,3,8,9);U+5231(3,9),U+5259(4),U+5275(1,3,8,9) +U+521C(0);U+521C(0,9); +U+521D(0);U+521D(5,9); +U+521E(0);U+521E(0,9);U+801D(3) +U+521F(0);U+521F(0); +U+5220(0);U+522A(2,3,8,9);U+522A(2,3,8,9) +U+5221(0);U+5221(0,9); +U+5222(0);U+5222(0); +U+5223(0);U+5223(0); +U+5224(0);U+5224(5,9); +U+5225(0);U+5225(0,9);U+522B(4,8),U+5F46(1,3,4,8,9),U+618B(3,4,8,9) +U+5226(0);U+52AB(2,3,8,9);U+52AB(2,3,8,9),U+523C(2,3,8) +U+5228(0);U+5228(4,9);U+9464(2,3,9) +U+5229(0);U+5229(5,9); +U+522A(0);U+522A(0,9);U+5220(2,3,8) +U+522B(0);U+5225(4,8,9),U+5F46(1,3,9);U+5225(4,8,9),U+5F46(1,3,9),U+618B(3,9) +U+522C(0);U+5277(8,9);U+5257(1,3,8),U+5277(8,9),U+93DF(1,3,4,8,9),U+94F2(1,3,4,8) +U+522D(0);U+5244(1,3,8,9);U+5244(1,3,8,9) +U+522E(0);U+522E(1,3,9),U+98B3(1,3,4,8,9);U+5280(3,9),U+98B3(1,3,4,8,9) +U+522F(0);U+522F(0); +U+5230(0);U+5230(5,9); +U+5231(0);U+5231(0,9);U+521B(3),U+5259(3,4),U+5275(1,3,8,9) +U+5232(0);U+5232(0,9); +U+5233(0);U+5233(5,9); +U+5234(0);U+5241(4,8,9);U+5241(4,8,9) + +U+5235(0);U+5235(0,9); +U+5236(0);U+5236(1,3,9),U+88FD(1,3,4,8,9);U+88FD(1,3,4,8,9) +U+5237(0);U+5237(5,9); +U+5238(0);U+5238(5,9);U+52B5(2),U+5026(2,3,9) +U+5239(0);U+524E(4,8,9);U+524E(4,8,9) +U+523A(0);U+523A(5,9);U+523E(7,8),U+673F(3,9) +U+523B(0);U+523B(5,9); +U+523C(0);U+52AB(2,3,8,9);U+52AB(2,3,8,9),U+5226(0,2,3,8) +U+523D(0);U+528A(1,3,8,9);U+528A(1,3,8,9) +U+523E(0);U+523A(7,8,9);U+523A(7,8,9),U+673F(3,7,8,9) +U+523F(0);U+528C(1,3,8,9);U+528C(1,3,8,9) +U+5240(0);U+5274(1,3,8,9);U+5274(1,3,8,9) +U+5241(0);U+5241(5,9);U+5234(4,8) +U+5242(0);U+5291(1,3,8,9);U+5264(4),U+5291(1,3,8,9) +U+5243(0);U+5243(5,9);U+8599(2,9) +U+5244(0);U+5244(0,9);U+522D(1,3,8) +U+5245(0);U+5245(0); +U+5246(0);U+5246(0,9); +U+5247(0);U+5247(0,9);U+5219(1,3,8) +U+5248(0);U+5248(0); +U+5249(0);U+5249(0,9); +U+524A(0);U+524A(5,9); +U+524B(0);U+524B(0,9);U+514B(1,3,8,9),U+5C05(2,3,8) +U+524C(0);U+524C(5,9); +U+524D(0);U+524D(5,9); +U+524E(0);U+524E(0,9);U+5239(4,8) +U+5250(0);U+526E(1,3,8,9);U+526E(1,3,8,9) +U+5251(0);U+528D(1,3,8,9);U+5263(3),U+528D(1,3,8,9),U+5292(4),U+5294(3),U+9431(3,9) +U+5252(0);U+5252(0,9); +U+5254(0);U+5254(5,9); +U+5255(0);U+5255(0,9); +U+5256(0);U+5256(5,9); +U+5257(0);U+5277(8,9);U+522C(1,3,8),U+5277(8,9),U+93DF(4,8,9),U+94F2(4) +U+5258(0);U+5258(0); +U+5259(0);U+5275(2,3,8,9);U+521B(4),U+5275(2,3,8,9),U+5231(3,4,9) +U+525A(0);U+525A(0,9);U+5033(3,4,9) +U+525B(0);U+525B(0,9);U+521A(1,3,8) +U+525C(0);U+525C(5,9); +U+525D(0);U+525D(0,9);U+5265(4,8) +U+525E(0);U+525E(5,9); +U+525F(0);U+525F(0,9); +U+5260(0);U+5260(0); +U+5261(0);U+5261(5,9); +U+5262(0);U+5262(0,9); +U+5263(0);U+528D(3,8,9);U+5251(3),U+528D(3,8,9),U+5292(3,4),U+5294(3),U+9431(3,9) +U+5264(0);U+5291(4,8,9);U+5242(4),U+5291(4,8,9) +U+5265(0);U+525D(4,8,9);U+525D(4,8,9) +U+5267(0);U+5287(1,3,8,9);U+5287(1,3,8,9) +U+5268(0);U+5268(0); +U+5269(0);U+5269(5,9);U+5270(4,8),U+8CF8(2,3,8,9) +U+526A(0);U+526A(5,9); +U+526B(0);U+526B(3,9); +U+526C(0);U+526C(0,9); +U+526D(0);U+526D(3,9); +U+526E(0);U+526E(0,9);U+5250(1,3,8) +U+526F(0);U+526F(5,9);U+8914(4,9) +U+5270(0);U+5269(4,8,9);U+5269(4,8,9),U+8CF8(2,3,4,8,9) +U+5272(0);U+5272(5,9); +U+5273(0);U+5284(4,9);U+624E(4,9),U+5284(4,9),U+672D(2,3,9),U+7B9A(4),U+7D25(2,4),U+7D2E(2,4,8,9) +U+5274(0);U+5274(0,9);U+5240(1,3,8) +U+5275(0);U+5275(0,9);U+521B(1,3,8),U+5259(2,3,8),U+5231(1,3,8,9) +U+5276(0);U+5276(0); + +U+5277(0);U+5277(0,9);U+522C(8),U+5257(8),U+93DF(2,3,8,9),U+94F2(4) +U+5278(0);U+5278(3,9); +U+527A(0);U+527A(3,9); +U+527B(0);U+527B(0,9); +U+527C(0);U+527C(0,9); +U+527D(0);U+527D(5,9);U+6153(4,9) +U+527E(0);U+527E(3); +U+527F(0);U+527F(5,9);U+528B(3,9),U+52E6(2,8,9) +U+5280(0);U+5280(0,9);U+522E(3,9),U+98B3(1,3,4,8,9) +U+5281(0);U+5281(5,9); +U+5282(0);U+5282(5,9); +U+5283(0);U+5283(0,9);U+5212(1,3,8,9) +U+5284(0);U+5284(0,9);U+624E(4,9),U+5273(4),U+672D(2,3,9),U+7B9A(4),U+7D25(2,4),U+7D2E(2,4,8,9) +U+5286(0);U+942E(3,8,9);U+942E(3,8,9),U+9570(3),U+938C(2,3,9) +U+5287(0);U+5287(0,9);U+5267(1,3,8) +U+5288(0);U+5288(5,9); +U+5289(0);U+5289(0,9);U+5218(1,3,8) +U+528A(0);U+528A(0,9);U+523D(1,3,8) +U+528B(0);U+528B(0,9);U+527F(3,9),U+52E6(2,3,8,9) +U+528C(0);U+528C(0,9);U+523F(1,3,8) +U+528D(0);U+528D(0,9);U+5251(1,3,8),U+5263(3,8),U+5292(2,8),U+5294(3,8),U+9431(1,3,8,9) +U+528F(0);U+528F(0); +U+5290(0);U+5290(5); +U+5291(0);U+5291(0,9);U+5242(1,3,8),U+5264(4,8) +U+5292(0);U+528D(2,8,9);U+5251(4),U+528D(2,8,9),U+5294(4),U+5263(3,4),U+9431(3,4,9) +U+5293(0);U+5293(5,9); +U+5294(0);U+528D(3,8,9);U+5251(3),U+528D(3,8,9),U+5292(4),U+5263(3),U+9431(3,9) +U+5295(0);U+5295(0); +U+5296(0);U+5296(0,9); +U+5297(0);U+5297(0,9); +U+5298(0);U+5298(0,9); +U+5299(0);U+5299(3,9);U+882B(3,9) +U+529A(0);U+529A(0); +U+529B(0);U+529B(5,9); +U+529C(0);U+529C(0); +U+529D(0);U+52F8(1,3,8,9);U+52E7(3),U+52F8(1,3,8,9) +U+529E(0);U+8FA6(1,3,8,9);U+8FA6(1,3,8,9),U+8FA8(1,3,8,9),U+8FA7(1,3,8),U+91C6(1,3,4,8,9) +U+529F(0);U+529F(5,9); +U+52A0(0);U+52A0(5,9); +U+52A1(0);U+52D9(1,3,8,9);U+52D9(1,3,8,9) +U+52A2(0);U+52F1(4,8,9);U+52F1(4,8,9) +U+52A3(0);U+52A3(5,9); +U+52A5(0);U+52A5(0); +U+52A6(0);U+52A6(0,9);U+534F(3),U+5354(1,3,8,9),U+604A(3) +U+52A7(0);U+52A7(0); +U+52A8(0);U+52D5(1,3,8,9);U+50CD(4),U+52D5(1,3,8,9) +U+52A9(0);U+52A9(5,9); +U+52AA(0);U+52AA(5,9); +U+52AB(0);U+52AB(5,9);U+5226(2,3,8),U+523C(2,3,8) +U+52AC(0);U+52AC(5,9); +U+52AD(0);U+52AD(5,9); +U+52AE(0);U+52AE(0,9);U+9038(4,9) +U+52AF(0);U+52AF(0); +U+52B0(0);U+52B0(0); +U+52B1(0);U+52F5(1,3,8,9);U+52F5(1,3,8,9) +U+52B2(0);U+52C1(1,3,8,9);U+52C1(1,3,8,9) +U+52B3(0);U+52DE(1,3,8,9);U+52B4(4),U+52DE(1,3,8,9) +U+52B4(0);U+52DE(4,8,9);U+52B3(4),U+52DE(4,8,9) +U+52B5(0);U+5238(2,9);U+5026(3,9),U+5238(2,9) +U+52B6(0);U+52B6(0); + +U+52B7(0);U+52B7(0); +U+52B8(0);U+52B8(0); +U+52B9(0);U+6548(2,3,8,9);U+6548(2,3,8,9),U+4FF2(0,2,3,7,8),U+509A(2,3,7,8,9) +U+52BA(0);U+52BA(3); +U+52BB(0);U+52BB(0,9); +U+52BC(0);U+52BC(0,9); +U+52BD(0);U+52BD(0); +U+52BE(0);U+52BE(5,9);U+52D3(3,9) +U+52BF(0);U+52E2(1,3,8,9);U+52E2(1,3,8,9) +U+52C0(0);U+52C0(4,9); +U+52C1(0);U+52C1(0,9);U+52B2(1,3,8) +U+52C2(0);U+52C2(0,9); +U+52C3(0);U+52C3(5,9); +U+52C6(0);U+52C6(0); +U+52C7(0);U+52C7(5,9); +U+52C9(0);U+52C9(5,9); +U+52CA(0);U+52CA(0); +U+52CB(0);U+52DB(1,3,8,9);U+52DB(1,3,8,9),U+52F2(4),U+52F3(4,9) +U+52CD(0);U+52CD(0,9); +U+52CF(0);U+52CF(0); +U+52D0(0);U+52D0(5); +U+52D2(0);U+52D2(5,9); +U+52D3(0);U+52D3(0,9);U+52BE(3,9) +U+52D5(0);U+52D5(0,9);U+50CD(2),U+52A8(1,3,8) +U+52D6(0);U+52D6(5,9);U+52D7(2,3,9) +U+52D7(0);U+52D7(0,9);U+52D6(2,3,9) +U+52D8(0);U+52D8(5,9); +U+52D9(0);U+52D9(0,9);U+52A1(1,3,8) +U+52DA(0);U+52E9(1,3,8,9);U+52E9(1,3,8,9) +U+52DB(0);U+52DB(0,9);U+52CB(1,3,8),U+52F2(4,8),U+52F3(2,3,8,9) +U+52DC(0);U+52DC(0); +U+52DD(0);U+52DD(0,9);U+80DC(1,3,8,9) +U+52DE(0);U+52DE(0,9);U+52B3(1,3,8),U+52B4(4,8) +U+52DF(0);U+52DF(5,9); +U+52E0(0);U+52E0(3); +U+52E2(0);U+52E2(0,9);U+52BF(1,3,8) +U+52E3(0);U+52E3(0,9);U+7EE9(4),U+7E3E(1,3,4,8,9) +U+52E4(0);U+52E4(5,9);U+61C3(2,3,8,9),U+763D(3,9) +U+52E6(0);U+52E6(0,9);U+527F(2,8,9),U+528B(2,3,8,9) +U+52E7(0);U+52F8(3,8,9);U+529D(3),U+52F8(3,8,9) +U+52E8(0);U+52E8(0); +U+52E9(0);U+52E9(0,9);U+52DA(1,3,8) +U+52EA(0);U+52EA(0); +U+52EB(0);U+52EB(0,9); +U+52EC(0);U+52EC(3); +U+52ED(0);U+52ED(0); +U+52EF(0);U+52EF(0,9); +U+52F0(0);U+52F0(5,9); +U+52F1(0);U+52F1(0,9);U+52A2(4,8) +U+52F2(0);U+52F3(3,9);U+52CB(4),U+52DB(2,3,8,9),U+52F3(3,9) +U+52F3(0);U+52F3(0,9);U+52CB(4),U+52DB(2,3,8,9),U+52F2(3) +U+52F4(0);U+52F4(0,9); +U+52F5(0);U+52F5(0,9);U+52B1(1,3,8) +U+52F6(0);U+52F6(0); +U+52F7(0);U+52F7(0,9); +U+52F8(0);U+52F8(0,9);U+529D(1,3,8),U+52E7(3,8) +U+52F9(0);U+52F9(5); +U+52FA(0);U+52FA(5,9); +U+52FB(0);U+52FB(0,9);U+5300(4,8) +U+52FC(0);U+52FC(3,9); +U+52FD(0);U+52FD(0); +U+52FE(0);U+52FE(5,9);U+53E5(3,8,9) +U+52FF(0);U+52FF(5,9); + +U+5300(0);U+52FB(4,8,9);U+52FB(4,8,9) +U+5301(0);U+5301(0); +U+5302(0);U+5302(0); +U+5305(0);U+5305(5,9); +U+5306(0);U+5306(5,9);U+6031(2,3,8),U+60A4(2,3,8) +U+5307(0);U+5307(0); +U+5308(0);U+5308(5,9); +U+5309(0);U+5309(0,9); +U+530A(0);U+530A(0,9);U+63AC(3,9) +U+530B(0);U+530B(0,9);U+9676(4,9) +U+530C(0);U+530C(0); +U+530D(0);U+530D(5,9); +U+530E(0);U+530E(0,9); +U+530F(0);U+530F(5,9); +U+5310(0);U+5310(5,9); +U+5311(0);U+5311(3,9); +U+5312(0);U+5312(0,9); +U+5313(0);U+5313(0); +U+5314(0);U+5314(4); +U+5315(0);U+5315(5,9); +U+5316(0);U+5316(5,9); +U+5317(0);U+5317(5,9); +U+5319(0);U+5319(5,9); +U+531A(0);U+531A(5,9); +U+531C(0);U+531C(3,9); +U+531D(0);U+531D(5,9); +U+531F(0);U+531F(0,9);U+7095(2,3,9) +U+5320(0);U+5320(5,9); +U+5321(0);U+5321(5,9); +U+5322(0);U+5322(0,9);U+532B(3) +U+5323(0);U+5323(5,9); +U+5324(0);U+5324(0); +U+5325(0);U+5325(0); +U+5326(0);U+532D(1,3,8,9);U+532D(1,3,8,9) +U+5328(0);U+5328(0); +U+532A(0);U+532A(5,9); +U+532B(0);U+532B(3);U+5322(3,9) +U+532C(0);U+532C(0); +U+532D(0);U+532D(0,9);U+5326(1,3,8) +U+532E(0);U+5331(1,3,8,9);U+5331(1,3,8,9),U+9400(7,9) +U+532F(0);U+532F(0,9);U+5F59(4,9),U+6C47(1,3,8),U+5F5A(4,8),U+6ED9(4) +U+5330(0);U+5330(0,9); +U+5331(0);U+5331(0,9);U+532E(1,3,8),U+9400(1,3,7,8,9) +U+5333(0);U+5969(2,8,9);U+5941(7),U+5969(2,8,9) +U+5334(0);U+5334(3,9); +U+5337(0);U+5337(0,9); +U+5339(0);U+5339(5,9);U+758B(2,3,8,9) +U+533A(0);U+5340(1,3,8,9);U+5340(1,3,8,9) +U+533B(0);U+91AB(1,3,8,9);U+6BC9(3,9),U+91AB(1,3,8,9) +U+533C(0);U+533C(3,9); +U+533D(0);U+533D(3,9); +U+533E(0);U+533E(5,9); +U+533F(0);U+533F(5,9); +U+5340(0);U+5340(0,9);U+533A(1,3,8) +U+5341(0);U+5341(5,9); +U+5343(0);U+5343(1,3,9),U+97C6(1,3,4,9);U+4EDF(3,8,9),U+97C6(1,3,4,9) +U+5344(0);U+5344(0,9);U+5EFF(3,8,9) +U+5345(0);U+5345(5,9); +U+5346(0);U+5352(3,8,9);U+5352(3,8,9) +U+5347(0);U+5347(5,9),U+6607(2,3,8,9),U+965E(2,3,8,9);U+965E(2,3,8,9),U+6607(2,3,8,9) +U+5348(0);U+5348(5,9); +U+5349(0);U+5349(5,9); + +U+534A(0);U+534A(5,9); +U+534B(0);U+4E16(3,8,9);U+4E16(3,8,9),U+4E17(3,8) +U+534C(0);U+534C(0,9); +U+534D(0);U+534D(4,9);U+5350(3,4,8) +U+534E(0);U+83EF(1,3,8,9);U+5D0B(3,9),U+83EF(1,3,8,9) +U+534F(0);U+5354(1,3,8,9);U+52A6(3,9),U+5354(1,3,8,9),U+604A(3) +U+5350(0);U+534D(3,4,8,9);U+534D(3,4,8,9) +U+5351(0);U+5351(5,9); +U+5352(0);U+5352(5,9);U+5346(3,8) +U+5353(0);U+5353(5,9); +U+5354(0);U+5354(0,9);U+534F(1,3,8),U+604A(3,8),U+52A6(0,1,3,8,9) +U+5355(0);U+55AE(1,3,8,9);U+5358(4),U+55AE(1,3,8,9) +U+5356(0);U+8CE3(1,3,8,9);U+58F2(4),U+8CE3(1,3,8,9) +U+5357(0);U+5357(5,9); +U+5358(0);U+55AE(8,9);U+5355(4),U+55AE(8,9) +U+5359(0);U+5359(0); +U+535A(0);U+535A(5,9);U+613D(2,3,8) +U+535C(0);U+535C(1,3,9),U+8514(1,3,4,8,9);U+8514(1,3,4,8,9),U+83D4(1,3,4,8,9) +U+535E(0);U+535E(5,9); +U+535F(0);U+535F(5); +U+5360(0);U+5360(5,9),U+4F54(2,3,8,9);U+4F54(2,3,8,9) +U+5361(0);U+5361(5,9); +U+5362(0);U+76E7(1,3,8,9);U+76E7(1,3,8,9) +U+5363(0);U+5363(5,9); +U+5364(0);U+9E75(1,3,9),U+6EF7(1,3,8,9);U+6EF7(1,3,8,9),U+9E75(1,3,9) +U+5365(0);U+5365(0); +U+5366(0);U+5366(5,9); +U+5367(0);U+81E5(3,4,8,9);U+81E5(3,4,8,9) +U+5369(0);U+5369(5); +U+536B(0);U+885B(1,3,8,9);U+885B(1,3,8,9),U+885E(3) +U+536C(0);U+536C(0,9); +U+536E(0);U+536E(5,9);U+5DF5(2,3,8) +U+536F(0);U+536F(5,9);U+5918(2,3,8),U+623C(2,3,8) +U+5370(0);U+5370(5,9); +U+5371(0);U+5371(5,9); +U+5372(0);U+5372(0,9); +U+5373(0);U+5373(5,9);U+537D(3,4,8) +U+5374(0);U+537B(3,8,9);U+537B(3,8,9) +U+5375(0);U+5375(5,9); +U+5376(0);U+5376(3); +U+5377(0);U+5377(1,3,9),U+6372(1,3,4,8,9);U+5DFB(4),U+6372(1,3,4,8,9) +U+5378(0);U+5378(5,9);U+7F37(3,8) +U+5379(0);U+5379(0,9);U+6064(2,8,9),U+8CC9(2,3,8) +U+537A(0);U+537A(5); +U+537B(0);U+537B(0,9);U+5374(3,8) +U+537C(0);U+537C(0,9); +U+537D(0);U+5373(3,4,8,9);U+5373(3,4,8,9) +U+537E(0);U+537E(0); +U+537F(0);U+537F(5,9); +U+5381(0);U+5381(0); +U+5382(0);U+5382(1,3,4,9),U+5EE0(1,3,8,9);U+53B0(4),U+5EE0(1,3,8,9) +U+5383(0);U+5383(0); +U+5384(0);U+5384(5,9);U+9628(2,8,9) +U+5385(0);U+5EF3(1,3,8,9);U+539B(3),U+5EF0(4),U+5EF3(1,3,8,9),U+5E81(1,3,8) +U+5386(0);U+6B77(1,3,4,8,9),U+66C6(1,3,8,9);U+53A4(4,9),U+66A6(4),U+66C6(1,3,8,9),U+6B74(2,3),U+6B77(1,3,4,8,9) +U+5387(0);U+5387(0); +U+5388(0);U+5388(0); +U+5389(0);U+53B2(1,3,8,9);U+53B2(1,3,8,9) +U+538A(0);U+538A(0,9); +U+538B(0);U+58D3(1,3,8,9);U+5727(4),U+58D3(1,3,8,9) +U+538C(0);U+53AD(1,3,8,9);U+53AD(1,3,8,9),U+7312(3,9) +U+538D(0);U+5399(1,3,8,9);U+5399(1,3,8,9) + +U+538E(0);U+538E(0,9);U+5E95(4,9) +U+538F(0);U+538F(0,9); +U+5390(0);U+9F90(8,9);U+5E9E(7),U+9F8E(4),U+9F90(8,9) +U+5391(0);U+5391(0); +U+5392(0);U+5392(0,9); +U+5393(0);U+5393(0); +U+5394(0);U+5394(0,9); +U+5395(0);U+5EC1(4,8,9);U+53A0(1,3,8),U+5EC1(4,8,9) +U+5396(0);U+5396(3,9); +U+5397(0);U+5397(0,9); +U+5398(0);U+5398(5,9),U+91D0(2,3,8,9);U+91D0(2,3,8,9) +U+5399(0);U+5399(0,9);U+538D(1,3,8) +U+539A(0);U+539A(5,9); +U+539B(0);U+5EF3(3,8,9);U+5385(3),U+5EF3(3,8,9),U+5EF0(3,4),U+5E81(1,3,8) +U+539C(0);U+539C(0,9); +U+539D(0);U+539D(5,9); +U+539E(0);U+539E(3,9); +U+539F(0);U+539F(5,9);U+908D(4,9) +U+53A0(0);U+5EC1(2,3,8,9);U+5395(1,3,8),U+5EC1(2,3,8,9) +U+53A2(0);U+5EC2(2,3,8,9);U+5EC2(2,3,8,9) +U+53A3(0);U+53B4(1,3,8,9);U+53B4(1,3,8,9) +U+53A4(0);U+53A4(0,9);U+5386(4),U+66A6(4),U+66C6(1,3,4,8,9),U+6B74(2,3,4),U+6B77(1,3,4,8,9) +U+53A5(0);U+53A5(5,9); +U+53A6(0);U+5EC8(2,3,8,9);U+5EC8(2,3,8,9) +U+53A7(0);U+53A7(0,9); +U+53A8(0);U+5EDA(2,3,8,9);U+5EDA(2,3,8,9) +U+53A9(0);U+5EC4(2,8,9);U+5EC4(2,8,9),U+5ECF(3,4),U+5ED0(2) +U+53AC(0);U+53AC(0,9); +U+53AD(0);U+53AD(0,9);U+538C(1,3,8),U+7312(1,3,8,9) +U+53AE(0);U+5EDD(2,3,8,9);U+5EDD(2,3,8,9) +U+53B0(0);U+5EE0(3,8,9);U+5382(4,9),U+5EE0(3,8,9) +U+53B1(0);U+53B1(0); +U+53B2(0);U+53B2(0,9);U+5389(1,3,8) +U+53B3(0);U+56B4(4,8,9);U+4E25(4),U+56B4(4,8,9) +U+53B4(0);U+53B4(0,9);U+53A3(1,3,8) +U+53B5(0);U+6E90(3,8,9);U+6E90(3,8,9) +U+53B6(0);U+79C1(3,8,9);U+79C1(3,8,9) +U+53B7(0);U+53B7(0); +U+53B8(0);U+53B8(4); +U+53B9(0);U+53B9(0,9); +U+53BB(0);U+53BB(5,9); +U+53BC(0);U+53BC(0); +U+53BD(0);U+53BD(0); +U+53BE(0);U+53BE(0); +U+53BF(0);U+7E23(1,3,8,9);U+7E23(1,3,8,9) +U+53C0(0);U+53C0(0); +U+53C1(0);U+53C3(8,9);U+53C2(4),U+53C3(8,9),U+84E1(4),U+53C4(3,4),U+8460(4,9) +U+53C2(0);U+53C3(1,3,8,9);U+84E1(4),U+53C1(4),U+53C3(1,3,8,9),U+53C4(3),U+8460(4,9) +U+53C3(0);U+53C3(0,9);U+84E1(2,3,8),U+53C1(8),U+53C2(1,3,8),U+53C4(3,8),U+8460(4,8,9) +U+53C4(0);U+53C3(3,8,9);U+53C2(3),U+53C3(3,8,9),U+53C1(3,4,5),U+84E1(3,4),U+8460(3,4,9) +U+53C6(0);U+9749(1,3,8,9);U+9749(1,3,8,9) +U+53C7(0);U+9746(1,3,8,9);U+9746(1,3,8,9) +U+53C8(0);U+53C8(5,9); +U+53C9(0);U+53C9(5,9); +U+53CA(0);U+53CA(5,9); +U+53CB(0);U+53CB(5,9); +U+53CC(0);U+96D9(1,3,8,9);U+96D9(1,3,8,9) +U+53CD(0);U+53CD(5,9);U+6604(4,9) +U+53CE(0);U+6536(3,8,9);U+6536(3,8,9) +U+53D0(0);U+53D0(0); + +U+53D1(0);U+767C(1,3,8,9),U+9AEE(1,3,8,9);U+5F42(4),U+767C(1,3,8,9),U+9AEA(4),U+9AEE(1,3,8,9) +U+53D2(0);U+53D2(0); +U+53D3(0);U+53D3(0); +U+53D4(0);U+53D4(5,9); +U+53D5(0);U+53D5(0); +U+53D6(0);U+53D6(5,9); +U+53D7(0);U+53D7(5,9); +U+53D8(0);U+8B8A(1,3,8,9);U+5909(3),U+8B8A(1,3,8,9) +U+53D9(0);U+6558(2,9);U+654D(2,3,8),U+6558(2,9) +U+53DB(0);U+53DB(5,9); +U+53DC(0);U+53DF(3,8,9);U+53DF(3,8,9) +U+53DF(0);U+53DF(5,9);U+53DC(3,8) +U+53E0(0);U+758A(2,3,8,9);U+66E1(2),U+7589(2),U+758A(2,3,8,9),U+8FED(2,4,9) +U+53E1(0);U+53E1(0,9);U+777F(2,3,8,9) +U+53E2(0);U+53E2(0,9);U+4E1B(1,3,8),U+6B09(1,3,4,8,9),U+85C2(1,3,4,8,9) +U+53E3(0);U+53E3(5,9); +U+53E4(0);U+53E4(5,9); +U+53E5(0);U+53E5(5,9);U+52FE(3,8,9) +U+53E6(0);U+53E6(5,9); +U+53E8(0);U+53E8(5,9); +U+53E9(0);U+53E9(5,9); +U+53EA(0);U+53EA(1,3,9),U+8879(1,8,9),U+96BB(1,3,4,8,9);U+8879(1,8,9),U+96BB(1,3,4,8,9) +U+53EB(0);U+53EB(5,9);U+5602(3,9) +U+53EC(0);U+53EC(5,9); +U+53ED(0);U+53ED(5,9); +U+53EE(0);U+53EE(5,9); +U+53EF(0);U+53EF(5,9); +U+53F0(0);U+53F0(1,3,9),U+6AAF(1,3,4,9),U+81FA(1,3,4,8,9),U+98B1(1,3,4,8,9);U+6AAF(1,3,4,9),U+7C49(4,9),U+81FA(1,3,4,8,9),U+98B1(1,3,4,8,9) +U+53F1(0);U+53F1(5,9); +U+53F2(0);U+53F2(5,9); +U+53F3(0);U+53F3(5,9); +U+53F4(0);U+53F4(0); +U+53F5(0);U+53F5(5,9); +U+53F6(0);U+8449(1,3,4,8,9);U+8449(1,3,4,8,9) +U+53F7(0);U+865F(1,3,8,9);U+865F(1,3,8,9),U+8B79(3,9) +U+53F8(0);U+53F8(5,9); +U+53F9(0);U+5606(1,3,8,9),U+6B4E(4,9);U+5606(1,3,8,9),U+6B4E(4,9) +U+53FA(0);U+53FA(0); +U+53FB(0);U+53FB(5,9); +U+53FC(0);U+53FC(5,9); +U+53FD(0);U+5630(1,3,8,9);U+5630(1,3,8,9) +U+53FE(0);U+53FE(0); +U+5401(0);U+5401(1,3,9),U+7C72(1,3,4,8,9);U+7C72(1,3,4,8,9) +U+5402(0);U+5402(0); +U+5403(0);U+5403(5,9);U+55AB(2,8,9) +U+5404(0);U+5404(5,9); +U+5405(0);U+55A7(3,8,9);U+55A7(3,8,9),U+8AE0(2,3,8,9) +U+5406(0);U+5406(5,9); +U+5407(0);U+5407(0,9); +U+5408(0);U+5408(1,3,9),U+95A4(1,3,8,9);U+6546(3,9),U+95A4(1,3,8,9) +U+5409(0);U+5409(5,9); +U+540A(0);U+540A(5,9),U+5F14(2,3,9);U+5F14(2,3,9) +U+540B(0);U+540B(0,9); +U+540C(0);U+540C(5,9);U+4EDD(2,3,8,9),U+8855(2,9) +U+540D(0);U+540D(5,9); +U+540E(0);U+540E(1,3,9),U+5F8C(1,3,4,8,9);U+5F8C(1,3,4,8,9) +U+540F(0);U+540F(5,9); +U+5410(0);U+5410(5,9); +U+5411(0);U+5411(1,3,9),U+56AE(1,3,4,8,9);U+56AE(1,3,4,8,9),U+66CF(4,9) +U+5412(0);U+5412(5,9); + +U+5413(0);U+5687(1,3,4,8,9);U+5687(1,3,4,8,9) +U+5414(0);U+5414(0); +U+5415(0);U+5442(4,8,9);U+5442(4,8,9),U+90D8(3,9) +U+5416(0);U+5416(5); +U+5417(0);U+55CE(1,3,8,9);U+55CE(1,3,8,9) +U+5418(0);U+5418(0,9); +U+5419(0);U+5419(0,9); +U+541B(0);U+541B(5,9); +U+541C(0);U+541C(0,9); +U+541D(0);U+541D(5,9);U+608B(3,8) +U+541E(0);U+541E(5,9);U+5451(4,8) +U+541F(0);U+541F(5,9); +U+5420(0);U+5420(5,9); +U+5421(0);U+5421(5); +U+5423(0);U+5423(5);U+551A(3,9) +U+5424(0);U+5424(0,9); +U+5425(0);U+5425(0,9); +U+5426(0);U+5426(5,9); +U+5427(0);U+5427(5,9); +U+5428(0);U+5678(1,3,8,9);U+5678(1,3,8,9) +U+5429(0);U+5429(5,9); +U+542A(0);U+542A(3,9); +U+542B(0);U+542B(5,9); +U+542C(0);U+807D(1,3,8,9);U+8074(3),U+807C(3),U+807D(1,3,8,9) +U+542D(0);U+542D(5,9); +U+542E(0);U+542E(5,9); +U+542F(0);U+555F(4,9);U+5553(1,3,8),U+5554(3),U+555F(4,9) +U+5430(0);U+5430(0,9);U+5B8F(3,9) +U+5431(0);U+5431(5,9); +U+5432(0);U+5432(5); +U+5433(0);U+5433(0,9);U+5434(3,8),U+5449(4,8) +U+5434(0);U+5433(3,8,9);U+5433(3,8,9),U+5449(4) +U+5435(0);U+5435(5,9); +U+5436(0);U+5436(0,9);U+5450(4,8) +U+5437(0);U+5437(0,9); +U+5438(0);U+5438(5,9); +U+5439(0);U+5439(5,9); +U+543A(0);U+543A(0); +U+543B(0);U+543B(5,9);U+5445(3,9),U+5461(3,9) +U+543C(0);U+543C(5,9); +U+543D(0);U+543D(0,9); +U+543E(0);U+543E(5,9); +U+543F(0);U+544A(4,8,9);U+544A(4,8,9) +U+5440(0);U+5440(5,9); +U+5441(0);U+5441(0,9); +U+5442(0);U+5442(0,9);U+5415(4,8),U+90D8(3,4,8,9) +U+5443(0);U+5443(5,9); +U+5444(0);U+5444(0); +U+5445(0);U+5445(0,9);U+543B(3,9),U+5461(3,9) +U+5446(0);U+5446(3,9);U+7343(2,3,8,9),U+9A03(2,8,9) +U+5447(0);U+5447(0,9); +U+5448(0);U+5448(5,9); +U+5449(0);U+5433(4,8,9);U+5433(4,8,9),U+5434(4) +U+544A(0);U+544A(5,9);U+543F(4,8) +U+544B(0);U+544B(5); +U+544D(0);U+544D(0); +U+544E(0);U+544E(0,9); +U+544F(0);U+544F(0,9); +U+5450(0);U+5436(4,8,9);U+5436(4,8,9) +U+5451(0);U+541E(4,8,9);U+541E(4,8,9) +U+5452(0);U+5638(1,3,8,9);U+5638(1,3,8,9) +U+5453(0);U+56C8(1,3,8,9);U+56C8(1,3,8,9),U+5BF1(3,9) +U+5454(0);U+5454(5,9); + +U+5455(0);U+5614(1,3,8,9);U+5614(1,3,8,9) +U+5456(0);U+56A6(1,3,8,9);U+56A6(1,3,8,9) +U+5457(0);U+5504(1,3,8,9);U+5504(1,3,8,9) +U+5458(0);U+54E1(1,3,8,9);U+54E1(1,3,8,9) +U+5459(0);U+54BC(3,8,9);U+54BC(3,8,9) +U+545A(0);U+545A(0); +U+545B(0);U+55C6(1,3,8,9);U+55C6(1,3,8,9) +U+545C(0);U+55DA(1,3,8,9);U+55DA(1,3,8,9) +U+545E(0);U+545E(4); +U+545F(0);U+545F(0); +U+5460(0);U+5460(0,9); +U+5461(0);U+5461(0,9);U+543B(3,9),U+5445(3,9) +U+5462(0);U+5462(5,9); +U+5463(0);U+5463(0,9); +U+5464(0);U+5464(5,9); +U+5465(0);U+5465(0,9); +U+5466(0);U+5466(5,9); +U+5467(0);U+5467(0,9);U+8BCB(3),U+8A46(1,3,8,9) +U+5468(0);U+5468(5,9),U+9031(2,3,9);U+9031(2,3,9) +U+546A(0);U+5492(2,3,8,9);U+5492(2,3,8,9) +U+546B(0);U+546B(3,9); +U+546C(0);U+546C(0,9); +U+546D(0);U+546D(0); +U+546E(0);U+546E(0); +U+546F(0);U+546F(0,9); +U+5470(0);U+5470(0,9); +U+5471(0);U+5471(5,9);U+54CC(3,8) +U+5472(0);U+5472(5,9); +U+5473(0);U+5473(5,9); +U+5474(0);U+5474(3,9); +U+5475(0);U+5475(5,9);U+55EC(4,8),U+8A36(3,4,8,9),U+8BC3(1,3,4,8) +U+5476(0);U+5476(5,9); +U+5477(0);U+5477(5,9); +U+5478(0);U+5478(5,9); +U+5479(0);U+5479(0); +U+547A(0);U+547A(3,9); +U+547B(0);U+547B(5,9); +U+547C(0);U+547C(5,9);U+5611(2,3,8),U+8656(2,3,8,9),U+8B3C(2,3,8,9) +U+547D(0);U+547D(5,9); +U+547E(0);U+547E(0,9); +U+547F(0);U+547F(0,9); +U+5480(0);U+5480(5,9);U+5634(3,8,9) +U+5481(0);U+5481(0,9); +U+5482(0);U+5482(5,9); +U+5483(0);U+5483(0); +U+5484(0);U+5484(5,9); +U+5485(0);U+5485(3); +U+5486(0);U+5486(5,9); +U+5487(0);U+5487(3,9); +U+5488(0);U+5488(0,9); +U+5489(0);U+5489(0); +U+548B(0);U+548B(5,9); +U+548C(0);U+548C(5,9);U+924C(3,9),U+9FA2(2,3,8,9) +U+548D(0);U+548D(0,9); +U+548E(0);U+548E(5,9); +U+548F(0);U+8A60(2,3,8,9);U+8A60(2,3,8,9) +U+5490(0);U+5490(5,9); +U+5491(0);U+5491(0,9); +U+5492(0);U+5492(5,9);U+546A(2,3,8) +U+5493(0);U+5493(0); +U+5494(0);U+5494(5); +U+5495(0);U+5495(5,9); +U+5496(0);U+5496(5,9); + +U+5497(0);U+5497(0); +U+5498(0);U+5498(0,9); +U+5499(0);U+56A8(1,3,8,9);U+56A8(1,3,8,9) +U+549A(0);U+549A(5,9); +U+549B(0);U+5680(1,3,8,9);U+5680(1,3,8,9) +U+549C(0);U+549C(0); +U+549D(0);U+549D(1,3);U+565D(1,3,8) +U+549E(0);U+549E(0); +U+549F(0);U+549F(0); +U+54A0(0);U+54A0(0,9); +U+54A1(0);U+54A1(0,9); +U+54A2(0);U+54A2(0,9); +U+54A3(0);U+54A3(5); +U+54A4(0);U+54A4(5); +U+54A5(0);U+54A5(3,9); +U+54A6(0);U+54A6(5,9); +U+54A7(0);U+54A7(5,9); +U+54A8(0);U+54A8(5,9);U+8AEE(3,8,9),U+8C18(1,3,8) +U+54A9(0);U+54A9(5,9); +U+54AA(0);U+54AA(5,9); +U+54AB(0);U+54AB(5,9); +U+54AC(0);U+54AC(5,9);U+9F69(2,3,8) +U+54AD(0);U+54AD(5,9); +U+54AE(0);U+54AE(3,9); +U+54AF(0);U+54AF(5,9);U+8A7B(3,8,9) +U+54B0(0);U+54B0(0,9); +U+54B1(0);U+54B1(5,9);U+507A(2,3,9),U+5592(2,3,9) +U+54B2(0);U+7B11(2,8,9);U+7B11(2,8,9) +U+54B3(0);U+54B3(5,9); +U+54B4(0);U+54B4(5); +U+54B6(0);U+54B6(0,9); +U+54B7(0);U+54B7(0,9);U+5555(4,9) +U+54B8(0);U+54B8(1,3,9),U+9E79(1,3,4,8,9);U+9E79(1,3,4,8,9) +U+54B9(0);U+54B9(0); +U+54BA(0);U+54BA(3,9); +U+54BB(0);U+54BB(5,9); +U+54BC(0);U+54BC(0,9);U+5459(3,8) +U+54BD(0);U+54BD(5,9),U+56A5(2,3,9);U+56A5(2,3,9) +U+54BE(0);U+54BE(0,9); +U+54BF(0);U+54BF(5,9); +U+54C0(0);U+54C0(5,9); +U+54C1(0);U+54C1(5,9); +U+54C2(0);U+54C2(5,9); +U+54C3(0);U+54C3(0,9); +U+54C4(0);U+54C4(5,9),U+9B28(2,3,8,9);U+95A7(2,8),U+9B28(2,3,8,9) +U+54C5(0);U+54C5(0,9);U+8BBB(3),U+8A29(1,3,8) +U+54C6(0);U+54C6(5,9); +U+54C7(0);U+54C7(5,9); +U+54C8(0);U+54C8(5,9); +U+54C9(0);U+54C9(5,9); +U+54CA(0);U+54CA(0); +U+54CB(0);U+54CB(0); +U+54CC(0);U+5471(3,8,9);U+5471(3,8,9) +U+54CD(0);U+97FF(1,3,8,9);U+97FF(1,3,8,9) +U+54CE(0);U+54CE(5,9); +U+54CF(0);U+54CF(5,9); +U+54D0(0);U+54D0(5); +U+54D1(0);U+555E(1,3,8,9);U+5516(3),U+555E(1,3,8,9),U+75D6(7),U+7602(7) +U+54D2(0);U+5660(1,3,8,9);U+5660(1,3,8,9) +U+54D3(0);U+5635(1,3,8,9);U+5635(1,3,8,9) +U+54D4(0);U+55F6(1,3,8,9);U+55F6(1,3,8,9) +U+54D5(0);U+5666(1,3,8,9);U+5666(1,3,8,9) +U+54D6(0);U+54D6(0,9); + +U+54D7(0);U+5629(1,3,8,9);U+5629(1,3,8,9),U+8B41(4,8,9) +U+54D8(0);U+54D8(0); +U+54D9(0);U+5672(1,3,8,9);U+5672(1,3,8,9) +U+54DA(0);U+54DA(5); +U+54DB(0);U+54DB(0); +U+54DC(0);U+568C(4,8,9);U+568C(4,8,9) +U+54DD(0);U+5665(1,3,8,9);U+5665(1,3,8,9) +U+54DE(0);U+54DE(5,9); +U+54DF(0);U+55B2(1,3,8,9);U+55B2(1,3,8,9) +U+54E0(0);U+54E0(0,9); +U+54E1(0);U+54E1(0,9);U+5458(1,3,8) +U+54E2(0);U+54E2(3,9); +U+54E3(0);U+54E3(0); +U+54E4(0);U+54E4(0,9); +U+54E5(0);U+54E5(5,9); +U+54E6(0);U+54E6(5,9); +U+54E7(0);U+54E7(5,9); +U+54E8(0);U+54E8(5,9); +U+54E9(0);U+54E9(5,9); +U+54EA(0);U+54EA(5,9); +U+54EB(0);U+54EB(0,9); +U+54EC(0);U+54EC(0); +U+54ED(0);U+54ED(5,9); +U+54EE(0);U+54EE(5,9); +U+54EF(0);U+54EF(0); +U+54F0(0);U+54F0(0); +U+54F1(0);U+54F1(0,9); +U+54F2(0);U+54F2(5,9);U+5586(2,3) +U+54F3(0);U+54F3(5,9); +U+54F4(0);U+54F4(3); +U+54F5(0);U+54F5(0); +U+54F7(0);U+54F7(0,9); +U+54F8(0);U+54F8(0,9); +U+54F9(0);U+54F9(0); +U+54FA(0);U+54FA(5,9); +U+54FB(0);U+54FB(0,9);U+9F3E(3,9) +U+54FC(0);U+54FC(5,9); +U+54FD(0);U+54FD(5,9); +U+54FE(0);U+54FE(0); +U+54FF(0);U+54FF(5,9); +U+5500(0);U+5500(0); +U+5501(0);U+5501(5,9); +U+5502(0);U+5502(3); +U+5503(0);U+5503(0,9); +U+5504(0);U+5504(0,9);U+5457(1,3,8) +U+5505(0);U+5505(0,9); +U+5506(0);U+5506(5,9); +U+5507(0);U+5507(5,9),U+8123(3,8,9);U+8123(3,8,9) +U+5508(0);U+5508(0,9); +U+5509(0);U+5509(5,9); +U+550A(0);U+550A(0,9); +U+550B(0);U+550B(0,9); +U+550C(0);U+550C(0,9); +U+550D(0);U+550D(0); +U+550E(0);U+550E(0,9); +U+550F(0);U+550F(5,9); +U+5510(0);U+5510(5,9); +U+5511(0);U+5511(5,9); +U+5512(0);U+5512(0,9); +U+5513(0);U+5513(0); +U+5514(0);U+5514(5,9); +U+5516(0);U+555E(3,8,9);U+54D1(3),U+555E(3,8,9),U+75D6(7),U+7602(7) +U+5517(0);U+5517(0,9); + +U+551A(0);U+551A(0,9);U+5423(3) +U+551B(0);U+561C(1,3,8,9);U+561C(1,3,8,9) +U+551C(0);U+551C(0); +U+551D(0);U+55CA(1,3,8,9);U+55CA(1,3,8,9) +U+551E(0);U+551E(0); +U+551F(0);U+551F(0); +U+5520(0);U+562E(1,3,8,9);U+562E(1,3,8,9) +U+5521(0);U+5562(1,3,8,9);U+5562(1,3,8,9) +U+5522(0);U+55E9(1,3,8,9);U+55E9(1,3,8,9) +U+5523(0);U+5523(5); +U+5524(0);U+559A(4,8,9);U+559A(4,8,9) +U+5525(0);U+5525(0); +U+5526(0);U+5526(0,9); +U+5527(0);U+5527(5,9);U+559E(4,8) +U+5528(0);U+5528(0); +U+5529(0);U+5529(0); +U+552A(0);U+552A(5,9); +U+552B(0);U+552B(0); +U+552C(0);U+552C(5,9); +U+552D(0);U+552D(0,9); +U+552E(0);U+552E(5,9); +U+552F(0);U+552F(5,9); +U+5530(0);U+5530(5,9); +U+5531(0);U+5531(5,9); +U+5532(0);U+5532(0,9); +U+5533(0);U+5533(5,9); +U+5534(0);U+5534(0,9); +U+5535(0);U+5535(0,9); +U+5536(0);U+5536(3,9); +U+5537(0);U+5537(5,9); +U+5538(0);U+5538(0,9);U+5FF5(2,3,9) +U+5539(0);U+5539(0,9); +U+553A(0);U+553A(0); +U+553B(0);U+553B(0,9); +U+553C(0);U+553C(5,9); +U+553D(0);U+553D(0); +U+553E(0);U+553E(5,9); +U+553F(0);U+553F(5); +U+5540(0);U+5540(3,9); +U+5541(0);U+5541(5,9); +U+5542(0);U+5542(0); +U+5543(0);U+5543(5,9); +U+5544(0);U+5544(5,9); +U+5545(0);U+5545(0,9); +U+5546(0);U+5546(5,9);U+8B2A(3,9) +U+5548(0);U+5548(0,9); +U+5549(0);U+5549(5); +U+554A(0);U+554A(5,9); +U+554B(0);U+554B(0,9); +U+554C(0);U+554C(0); +U+554D(0);U+554D(3,9); +U+554E(0);U+554E(3,9); +U+554F(0);U+554F(0,9);U+95EE(1,3,8) +U+5550(0);U+5550(5,9); +U+5551(0);U+5551(0,9); +U+5552(0);U+5552(3,9); +U+5553(0);U+555F(2,3,8,9);U+542F(1,3,8),U+5554(3,8),U+555F(2,3,8,9) +U+5554(0);U+555F(8,9);U+542F(3),U+5553(3,8),U+555F(8,9) +U+5555(0);U+5555(5,9);U+54B7(4,9) +U+5556(0);U+5556(5,9);U+5557(2,3,8,9),U+5649(2,3,9),U+56AA(3,9) +U+5557(0);U+5557(4,9);U+5556(2,3,8,9),U+5649(2,3,8,9),U+56AA(2,3,8,9) +U+5558(0);U+5558(0); +U+5559(0);U+5559(0); + +U+555A(0);U+555A(0); +U+555B(0);U+555B(0); +U+555C(0);U+555C(5,9);U+56BD(3,9) +U+555D(0);U+555D(0); +U+555E(0);U+555E(0,9);U+54D1(1,3,8),U+5516(3,8),U+75D6(4),U+7602(3) +U+555F(0);U+555F(0,9);U+542F(4),U+5553(2,3,8),U+5554(8) +U+5561(0);U+5561(5,9); +U+5562(0);U+5562(0,9);U+5521(1,3,8) +U+5563(0);U+5563(0,9);U+8854(4),U+929C(1,3,4,8,9) +U+5564(0);U+5564(5,9); +U+5565(0);U+5565(5,9); +U+5566(0);U+5566(5,9); +U+5567(0);U+5616(1,3,8,9);U+5616(1,3,8,9) +U+5568(0);U+5568(0); +U+5569(0);U+5569(0); +U+556A(0);U+556A(5,9); +U+556B(0);U+556B(0); +U+556C(0);U+55C7(1,3,8,9);U+55C7(1,3,8,9) +U+556D(0);U+56C0(1,3,8,9);U+56C0(1,3,8,9) +U+556E(0);U+9F67(4,9);U+5699(1,3,8,9),U+56D3(4,9),U+9F67(4,9) +U+556F(0);U+5613(4,8,9);U+5613(4,8,9) +U+5570(0);U+56C9(1,3,8,9);U+56C9(1,3,8,9) +U+5571(0);U+5571(0); +U+5572(0);U+5572(0); +U+5573(0);U+5573(0); +U+5574(0);U+563D(4,8,9);U+563D(4,8,9) +U+5575(0);U+5575(5,9); +U+5576(0);U+5576(5,9); +U+5577(0);U+5577(5,9); +U+5578(0);U+562F(1,3,8,9);U+5628(4),U+562F(1,3,8,9) +U+5579(0);U+5579(0); +U+557B(0);U+557B(5,9); +U+557C(0);U+557C(5,9);U+8B15(3,9) +U+557D(0);U+557D(0,9); +U+557E(0);U+557E(5,9); +U+557F(0);U+557F(0,9); +U+5580(0);U+5580(5,9); +U+5581(0);U+5581(5,9); +U+5582(0);U+5582(5,9),U+9935(2,3,9);U+9935(2,3,9) +U+5583(0);U+5583(5,9);U+5A1A(3,8),U+8AF5(3,9) +U+5584(0);U+5584(5,9);U+8B71(3,8) +U+5585(0);U+5585(3); +U+5586(0);U+54F2(2,3,9);U+54F2(2,3,9) +U+5587(0);U+5587(5,9); +U+5588(0);U+5588(5,9); +U+5589(0);U+5589(5,9); +U+558A(0);U+558A(5,9); +U+558B(0);U+558B(5,9); +U+558C(0);U+558C(0,9); +U+558D(0);U+558D(0,9); +U+558E(0);U+558E(0,9);U+359E(1,3) +U+558F(0);U+558F(5,9); +U+5590(0);U+5590(0); +U+5591(0);U+5591(5,9);U+567E(3,9),U+7616(2,9) +U+5592(0);U+5592(0,9);U+54B1(2,3,9),U+507A(0,2,3,9) +U+5593(0);U+5593(0,9); +U+5594(0);U+5594(5,9); +U+5595(0);U+5595(0,9); +U+5596(0);U+5596(0); +U+5597(0);U+5597(0); +U+5598(0);U+5598(5,9); +U+5599(0);U+5599(5,9); +U+559A(0);U+559A(0,9);U+5524(4,8) + +U+559B(0);U+559B(0); +U+559C(0);U+559C(5,9);U+6199(3,8) +U+559D(0);U+559D(5,9); +U+559E(0);U+5527(4,8,9);U+5527(4,8,9) +U+559F(0);U+559F(5,9);U+5633(3,9),U+6B33(3,9) +U+55A0(0);U+55A0(0); +U+55A1(0);U+55A1(0,9); +U+55A2(0);U+55A2(0,9); +U+55A3(0);U+55A3(0,9); +U+55A4(0);U+55A4(3,9); +U+55A5(0);U+55A5(0,9); +U+55A6(0);U+55A6(0,9);U+5CA9(4,9),U+5D52(2,4,9),U+58E7(3,4,9),U+5DCC(4),U+5DD6(2,3,4,8,9),U+789E(3,4,9),U+7939(3,4,9) +U+55A7(0);U+55A7(5,9);U+5405(3,8),U+8AE0(2,3,8,9) +U+55A8(0);U+55A8(0,9); +U+55A9(0);U+55BB(4,8,9);U+55BB(4,8,9) +U+55AA(0);U+55AA(0,9);U+4E27(1,3,8) +U+55AB(0);U+55AB(0,9);U+5403(2,8,9) +U+55AC(0);U+55AC(0,9);U+4E54(1,3,8) +U+55AD(0);U+55AD(0,9); +U+55AE(0);U+55AE(0,9);U+5355(1,3,8),U+5358(8) +U+55AF(0);U+55AF(0); +U+55B0(0);U+9910(3,8,9);U+9910(3,8,9) +U+55B1(0);U+55B1(5,9); +U+55B2(0);U+55B2(0,9);U+54DF(1,3,8) +U+55B3(0);U+55B3(5,9); +U+55B4(0);U+55B4(0); +U+55B5(0);U+55B5(5,9); +U+55B6(0);U+71DF(4,8,9);U+71DF(4,8,9),U+8425(4) +U+55B7(0);U+5674(1,3,8,9);U+5674(1,3,8,9),U+6B55(3,9) +U+55B8(0);U+55B8(0); +U+55B9(0);U+55B9(5); +U+55BA(0);U+55BA(0); +U+55BB(0);U+55BB(5,9);U+55A9(4,8) +U+55BC(0);U+55BC(0); +U+55BD(0);U+560D(1,3,8,9);U+560D(1,3,8,9) +U+55BE(0);U+56B3(1,3,8,9);U+56B3(1,3,8,9) +U+55BF(0);U+55BF(0,9); +U+55C0(0);U+55C0(0,9); +U+55C1(0);U+55C1(4); +U+55C2(0);U+55C2(0,9); +U+55C3(0);U+55C3(0,9); +U+55C4(0);U+55C4(5,9); +U+55C5(0);U+55C5(5,9); +U+55C6(0);U+55C6(0,9);U+545B(1,3,8) +U+55C7(0);U+55C7(0,9);U+556C(1,3,8) +U+55C8(0);U+55C8(0,9); +U+55C9(0);U+55C9(5,9);U+8186(3,9) +U+55CA(0);U+55CA(0,9);U+551D(1,3,8) +U+55CB(0);U+55CB(0,9); +U+55CC(0);U+55CC(5,9); +U+55CD(0);U+55CD(5,9); +U+55CE(0);U+55CE(0,9);U+5417(1,3,8) +U+55CF(0);U+55CF(0,9); +U+55D0(0);U+55D0(0,9); +U+55D1(0);U+55D1(5,9); +U+55D2(0);U+55D2(5,9); +U+55D3(0);U+55D3(5,9); +U+55D4(0);U+55D4(5,9); +U+55D5(0);U+55D5(0,9); +U+55D6(0);U+55D6(5,9); +U+55D7(0);U+55D7(0); +U+55D8(0);U+55D8(0); + +U+55D9(0);U+55D9(0,9); +U+55DA(0);U+55DA(0,9);U+545C(1,3,8) +U+55DB(0);U+55DB(4,9); +U+55DC(0);U+55DC(5,9); +U+55DD(0);U+55DD(5,9); +U+55DE(0);U+55DE(0); +U+55DF(0);U+55DF(5,9); +U+55E1(0);U+55E1(5,9); +U+55E2(0);U+55E2(0,9); +U+55E3(0);U+55E3(5,9); +U+55E4(0);U+55E4(5,9); +U+55E5(0);U+55E5(5,9); +U+55E6(0);U+55E6(5,9); +U+55E7(0);U+55E7(0,9); +U+55E8(0);U+55E8(5,9); +U+55E9(0);U+55E9(0,9);U+5522(1,3,8) +U+55EA(0);U+55EA(5); +U+55EB(0);U+56C1(1,3,8,9);U+56C1(1,3,8,9) +U+55EC(0);U+5475(4,8,9);U+5475(4,8,9),U+8A36(3,4,8,9),U+8BC3(1,3,4,8) +U+55ED(0);U+55ED(0); +U+55EE(0);U+55EE(0); +U+55EF(0);U+55EF(5,9); +U+55F0(0);U+55F0(0); +U+55F1(0);U+55F1(0); +U+55F2(0);U+55F2(5,9); +U+55F3(0);U+566F(1,3,8,9);U+566F(1,3,8,9) +U+55F4(0);U+55F4(0); +U+55F5(0);U+55F5(5); +U+55F6(0);U+55F6(0,9);U+54D4(1,3,8) +U+55F7(0);U+55F7(5,9); +U+55F9(0);U+55F9(0,9); +U+55FA(0);U+55FA(3,9); +U+55FB(0);U+55FB(3); +U+55FC(0);U+55FC(0,9);U+5BDE(4,9) +U+55FD(0);U+55FD(5,9);U+6B36(3,9) +U+55FE(0);U+55FE(5,9); +U+55FF(0);U+55FF(0,9); +U+5600(0);U+5600(5,9); +U+5601(0);U+5601(5,9); +U+5602(0);U+5602(0,9);U+53EB(3,9) +U+5603(0);U+5603(0); +U+5604(0);U+5604(0,9); +U+5606(0);U+5606(0,9);U+53F9(1,3,8),U+6B4E(1,3,4,8,9) +U+5607(0);U+5607(0); +U+5608(0);U+5608(5,9);U+50AE(4,9) +U+5609(0);U+5609(5,9); +U+560C(0);U+560C(5,9); +U+560D(0);U+560D(0,9);U+55BD(1,3,8) +U+560E(0);U+560E(5,9); +U+560F(0);U+560F(5,9); +U+5610(0);U+5610(0,9); +U+5611(0);U+547C(2,3,8,9);U+547C(2,3,8,9),U+8656(2,3,8,9),U+8B3C(2,3,8,9) +U+5612(0);U+5612(3,9); +U+5613(0);U+5613(0,9);U+556F(4,8) +U+5614(0);U+5614(0,9);U+5455(1,3,8) +U+5615(0);U+5615(0,9); +U+5616(0);U+5616(0,9);U+5567(1,3,8) +U+5617(0);U+5617(0,9);U+5C1D(1,3,8),U+751E(2,3,8),U+5690(1,3,4,8,9) +U+5618(0);U+5653(4,8,9);U+5653(4,8,9) +U+5619(0);U+5619(0); +U+561A(0);U+561A(0); +U+561B(0);U+561B(5,9); +U+561C(0);U+561C(0,9);U+551B(1,3,8) + +U+561D(0);U+561D(0,9); +U+561E(0);U+561E(5); +U+561F(0);U+561F(5,9); +U+5621(0);U+5621(0); +U+5622(0);U+5622(0); +U+5623(0);U+5623(5); +U+5624(0);U+56B6(1,3,8,9);U+56B6(1,3,8,9),U+8B7B(3,9) +U+5625(0);U+5625(0); +U+5626(0);U+5626(0); +U+5627(0);U+5627(5,9); +U+5628(0);U+562F(4,8,9);U+5578(4),U+562F(4,8,9) +U+5629(0);U+5629(0,9);U+54D7(1,3,8),U+8B41(2,3,8,9) +U+562A(0);U+562A(0,9); +U+562C(0);U+562C(5,9); +U+562D(0);U+562D(5); +U+562E(0);U+562E(0,9);U+5520(1,3,8) +U+562F(0);U+562F(0,9);U+5578(1,3,8),U+5628(4,8) +U+5630(0);U+5630(0,9);U+53FD(1,3,8) +U+5631(0);U+56D1(1,3,8,9);U+56D1(1,3,8,9) +U+5632(0);U+5632(5,9); +U+5633(0);U+5633(0,9);U+559F(3,9),U+6B33(3,9) +U+5634(0);U+5634(5,9);U+5480(3,8,9) +U+5635(0);U+5635(0,9);U+54D3(1,3,8) +U+5636(0);U+5636(5,9); +U+5638(0);U+5638(0,9);U+5452(1,3,8) +U+5639(0);U+5639(5,9); +U+563A(0);U+563A(0,9); +U+563B(0);U+563B(5,9);U+8B46(2,9) +U+563D(0);U+563D(0,9);U+5574(4,8) +U+563E(0);U+563E(0,9); +U+563F(0);U+563F(5,9); +U+5640(0);U+5640(4,9); +U+5641(0);U+5641(0,9);U+6076(1,3,8),U+60E1(4,9),U+60AA(1,3,8) +U+5642(0);U+5642(3,9);U+8B50(3,9) +U+5643(0);U+5643(0); +U+5645(0);U+5645(3,9);U+5655(3,8) +U+5646(0);U+5646(0,9); +U+5647(0);U+5647(3); +U+5648(0);U+5648(0,9); +U+5649(0);U+5649(0,9);U+5556(2,3,9),U+5557(2,3,8,9),U+56AA(2,3,9) +U+564A(0);U+564A(0,9);U+8C32(3),U+8B4E(1,3,8,9) +U+564C(0);U+564C(5,9); +U+564D(0);U+564D(5); +U+564E(0);U+564E(5,9); +U+564F(0);U+564F(0); +U+5650(0);U+5668(3,8,9);U+5668(3,8,9) +U+5652(0);U+5652(0); +U+5653(0);U+5653(0,9);U+5618(4,8) +U+5654(0);U+5654(5); +U+5655(0);U+5645(3,8,9);U+5645(3,8,9) +U+5657(0);U+5657(5,9); +U+5658(0);U+5658(5,9); +U+5659(0);U+5659(5,9); +U+565A(0);U+565A(0,9); +U+565B(0);U+565B(0); +U+565C(0);U+5695(1,3,8,9);U+5695(1,3,8,9) +U+565D(0);U+565D(0);U+549D(1,3,8) +U+565E(0);U+565E(0,9); +U+5660(0);U+5660(0,9);U+54D2(1,3,8) +U+5662(0);U+5662(5,9); +U+5663(0);U+5663(0,9); +U+5664(0);U+5664(5,9); +U+5665(0);U+5665(0,9);U+54DD(1,3,8) + +U+5666(0);U+5666(0,9);U+54D5(1,3,8) +U+5667(0);U+5667(0); +U+5668(0);U+5668(5,9);U+5650(3,8) +U+5669(0);U+5669(5,9); +U+566A(0);U+566A(5,9);U+8B5F(2,3,8,9) +U+566B(0);U+566B(5,9); +U+566C(0);U+566C(5,9); +U+566D(0);U+566D(0,9); +U+566E(0);U+566E(0,9); +U+566F(0);U+566F(0,9);U+55F3(1,3,8) +U+5670(0);U+5670(3,9); +U+5671(0);U+5671(5,9); +U+5672(0);U+5672(0,9);U+54D9(1,3,8) +U+5673(0);U+5673(0,9); +U+5674(0);U+5674(0,9);U+55B7(1,3,8),U+6B55(1,3,8,9) +U+5676(0);U+5676(5,9); +U+5677(0);U+5677(0,9); +U+5678(0);U+5678(0,9);U+5428(1,3,8,9) +U+5679(0);U+5679(0,9);U+5F53(1,3,8),U+7576(3,4,9) +U+567A(0);U+567A(0); +U+567B(0);U+567B(5); +U+567C(0);U+567C(5); +U+567E(0);U+567E(0,9);U+5591(3,9),U+7616(2,3,9) +U+567F(0);U+567F(0,9); +U+5680(0);U+5680(0,9);U+549B(1,3,8) +U+5681(0);U+5681(0,9); +U+5682(0);U+5682(0,9); +U+5683(0);U+5683(4,9); +U+5684(0);U+5684(0,9); +U+5685(0);U+5685(5,9); +U+5686(0);U+5686(5,9); +U+5687(0);U+5687(0,9);U+5413(1,3,8) +U+568A(0);U+568A(0); +U+568C(0);U+568C(0,9);U+54DC(4,8) +U+568D(0);U+568D(0,9); +U+568E(0);U+568E(5,9); +U+568F(0);U+568F(5,9);U+5694(4,8) +U+5690(0);U+5690(0,9);U+5C1D(4),U+5617(0,1,3,4,8,9),U+751E(1,2,3,4,8) +U+5691(0);U+5691(0); +U+5692(0);U+5692(0); +U+5693(0);U+5693(5,9); +U+5694(0);U+568F(4,8,9);U+568F(4,8,9) +U+5695(0);U+5695(0,9);U+565C(1,3,8) +U+5697(0);U+5697(0,9); +U+5698(0);U+5698(0,9); +U+5699(0);U+5699(0,9);U+556E(1,3,8),U+56D3(2,8,9),U+9F67(2,3,8,9) +U+569A(0);U+569A(0,9); +U+569B(0);U+569B(0); +U+569C(0);U+569C(0,9); +U+569D(0);U+569D(0,9); +U+569F(0);U+569F(0); +U+56A0(0);U+700F(4,8,9);U+6D4F(4),U+700F(4,8,9) +U+56A1(0);U+56A1(0); +U+56A3(0);U+56C2(1,3,8,9);U+56BB(3),U+56C2(1,3,8,9) +U+56A4(0);U+56A4(0); +U+56A5(0);U+56A5(0,9);U+54BD(2,3,9) +U+56A6(0);U+56A6(0,9);U+5456(1,3,8) +U+56A7(0);U+56A7(0,9); +U+56A8(0);U+56A8(0,9);U+5499(1,3,8) +U+56A9(0);U+56A9(0); +U+56AA(0);U+56AA(0,9);U+5556(2,3,9),U+5557(2,3,8,9),U+5649(2,3,9) +U+56AB(0);U+56AB(0,9); +U+56AC(0);U+56AC(0,9); + +U+56AD(0);U+56AD(3,9); +U+56AE(0);U+56AE(0,9);U+5411(1,3,8,9),U+66CF(1,3,4,8,9) +U+56AF(0);U+56AF(5); +U+56B0(0);U+56B0(0); +U+56B1(0);U+56B1(0); +U+56B2(0);U+56B2(0,9);U+4EB8(4,8) +U+56B3(0);U+56B3(0,9);U+55BE(1,3,8) +U+56B4(0);U+56B4(0,9);U+4E25(1,3,8),U+53B3(4,8) +U+56B5(0);U+56B5(0,9); +U+56B6(0);U+56B6(0,9);U+5624(1,3,8),U+8B7B(1,3,8,9) +U+56B7(0);U+56B7(5,9); +U+56B8(0);U+56B8(0); +U+56B9(0);U+56B9(0); +U+56BB(0);U+56C2(3,8,9);U+56A3(3),U+56C2(3,8,9) +U+56BC(0);U+56BC(5,9); +U+56BD(0);U+56BD(0,9);U+555C(3,9) +U+56BE(0);U+56BE(0,9); +U+56BF(0);U+56BF(0); +U+56C0(0);U+56C0(0,9);U+556D(1,3,8) +U+56C1(0);U+56C1(0,9);U+55EB(1,3,8) +U+56C2(0);U+56C2(0,9);U+56A3(1,3,8),U+56BB(3,8) +U+56C3(0);U+56C3(0,9); +U+56C4(0);U+56C4(0); +U+56C5(0);U+56C5(0,9);U+5181(1,3,8) +U+56C6(0);U+56C6(0,9); +U+56C7(0);U+56C7(0); +U+56C8(0);U+56C8(0,9);U+5453(1,3,8),U+5BF1(1,3,8,9) +U+56C9(0);U+56C9(0,9);U+5570(1,3,8) +U+56CA(0);U+56CA(5,9); +U+56CB(0);U+56CB(3,9); +U+56CC(0);U+56CC(0,9);U+82CF(1,3),U+8607(4,8,9),U+7526(1,3,4,9),U+8613(1,3,4) +U+56CD(0);U+56CD(0,9); +U+56CE(0);U+56CE(0); +U+56D0(0);U+56D0(0); +U+56D1(0);U+56D1(0,9);U+5631(1,3,8) +U+56D2(0);U+56D2(0); +U+56D3(0);U+56D3(0,9);U+556E(4),U+5699(2,8,9),U+9F67(3,9) +U+56D4(0);U+56D4(5,9); +U+56D5(0);U+56D5(0); +U+56D6(0);U+56D6(0); +U+56D7(0);U+56D7(5,9); +U+56D8(0);U+56DE(3,8,9);U+56DE(3,8,9),U+56EC(3,8),U+5EFB(3,8),U+5EFD(2,3,8),U+8FF4(1,3,4,8,9),U+9025(3,4,8) +U+56DA(0);U+56DA(5,9); +U+56DB(0);U+56DB(5,9);U+8086(3,8,9) +U+56DC(0);U+56DC(0); +U+56DD(0);U+56DD(5,9); +U+56DE(0);U+56DE(1,3,9),U+8FF4(1,3,4,8,9);U+56D8(3,8),U+56EC(3,8),U+5EFB(3,8),U+5EFD(2,8),U+8FF4(1,3,4,8,9),U+9025(4,8) +U+56DF(0);U+56DF(5,9); +U+56E0(0);U+56E0(5,9); +U+56E1(0);U+56E1(5,9); +U+56E2(0);U+5718(1,3,8,9),U+7CF0(1,3,9);U+56E3(4),U+5718(1,3,8,9),U+7CF0(1,3,9) +U+56E3(0);U+5718(4,8,9);U+56E2(4),U+5718(4,8,9),U+7CF0(1,3,4,9) +U+56E4(0);U+56E4(5,9); +U+56E5(0);U+56E5(0,9); +U+56E7(0);U+56E7(0,9);U+518F(3,9) +U+56E8(0);U+56E8(0); +U+56E9(0);U+56E9(0); +U+56EA(0);U+56EA(0,9);U+56F1(4,8) +U+56EB(0);U+56EB(5,9); +U+56EC(0);U+56DE(3,8,9);U+56DE(3,8,9),U+56D8(0,3,8),U+5EFB(3,8),U+5EFD(2,3,8),U+8FF4(1,3,4,8,9),U+9025(3,4,8) + +U+56ED(0);U+5712(1,3,8,9);U+5712(1,3,8,9) +U+56EE(0);U+56EE(0,9); +U+56EF(0);U+570B(3,8,9);U+56FD(4),U+570B(3,8,9),U+5700(3,4) +U+56F0(0);U+56F0(1,9),U+774F(1,4,8,9);U+774F(1,4,8,9) +U+56F1(0);U+56EA(4,8,9);U+56EA(4,8,9) +U+56F2(0);U+570D(4,8,9);U+56F4(4),U+570D(4,8,9) +U+56F3(0);U+5716(4,8,9);U+56FE(4),U+5716(4,8,9) +U+56F4(0);U+570D(1,3,8,9);U+56F2(4),U+570D(1,3,8,9) +U+56F5(0);U+5707(1,3,8,9);U+5707(1,3,8,9) +U+56F7(0);U+56F7(0,9); +U+56F9(0);U+56F9(5,9); +U+56FA(0);U+56FA(5,9); +U+56FD(0);U+570B(1,3,8,9);U+56EF(4),U+5700(3),U+570B(1,3,8,9) +U+56FE(0);U+5716(1,3,8,9);U+56F3(4),U+5716(1,3,8,9) +U+56FF(0);U+56FF(5,9); +U+5700(0);U+570B(3,8,9);U+56FD(3),U+570B(3,8,9),U+56EF(0,3,4) +U+5701(0);U+5701(0,9); +U+5702(0);U+5702(3,9); +U+5703(0);U+5703(5,9); +U+5704(0);U+5704(5,9); +U+5706(0);U+5713(1,3,8,9);U+5186(4),U+570E(3),U+5713(1,3,8,9) +U+5707(0);U+5707(0,9);U+56F5(1,3,8) +U+5708(0);U+5708(5,9);U+570F(4,8) +U+5709(0);U+5709(5,9); +U+570A(0);U+570A(5,9); +U+570B(0);U+570B(0,9);U+56EF(3,8),U+56FD(1,3,8),U+5700(3,8) +U+570C(0);U+570C(0,9); +U+570D(0);U+570D(0,9);U+56F2(4,8),U+56F4(1,3,8) +U+570E(0);U+5713(3,8,9);U+5706(3),U+5713(3,8,9),U+5186(0,3,4) +U+570F(0);U+5708(4,8,9);U+5708(4,8,9) +U+5710(0);U+5710(0); +U+5712(0);U+5712(0,9);U+56ED(1,3,8) +U+5713(0);U+5713(0,9);U+5186(4,8),U+5706(1,3,8),U+570E(3,8) +U+5714(0);U+5714(0,9); +U+5715(0);U+5715(0); +U+5716(0);U+5716(0,9);U+56F3(4,8),U+56FE(1,3,8) +U+5718(0);U+5718(0,9);U+56E2(1,3,8),U+56E3(4,8),U+7CF0(4,9) +U+5719(0);U+5719(0); +U+571A(0);U+571A(0,9); +U+571B(0);U+571B(0,9); +U+571C(0);U+571C(5,9); +U+571D(0);U+571D(3); +U+571E(0);U+571E(0,9); +U+571F(0);U+571F(5,9); +U+5720(0);U+5720(0,9); +U+5722(0);U+5722(0,9);U+753A(4,9) +U+5723(0);U+8056(1,3,8,9);U+8056(1,3,8,9),U+57A9(1,3,8),U+580A(1,3,8,9) +U+5725(0);U+5725(0); +U+5726(0);U+5726(0); +U+5727(0);U+58D3(4,8,9);U+538B(4),U+58D3(4,8,9) +U+5728(0);U+5728(5,9); +U+5729(0);U+5729(5,9); +U+572A(0);U+572A(5,9); +U+572B(0);U+572B(0); +U+572C(0);U+572C(5,9);U+6747(3,9) +U+572D(0);U+572D(5,9);U+73EA(3,9) +U+572E(0);U+572E(5,9); +U+572F(0);U+572F(5,9); +U+5730(0);U+5730(5,9);U+58AC(3,9) +U+5731(0);U+5731(3); +U+5732(0);U+5732(0); +U+5733(0);U+5733(5,9); +U+5734(0);U+5734(0,9); + +U+5735(0);U+5735(0); +U+5736(0);U+5736(0); +U+5737(0);U+5737(0); +U+5738(0);U+5738(0); +U+5739(0);U+58D9(1,3,8,9);U+58D9(1,3,8,9) +U+573A(0);U+5834(1,3,8,9);U+5834(1,3,8,9),U+5872(4) +U+573B(0);U+573B(5,9);U+57A0(3,8,9) +U+573C(0);U+573C(0); +U+573E(0);U+573E(5,9); +U+573F(0);U+573F(0); +U+5740(0);U+5740(5,9);U+962F(2,3,8,9) +U+5741(0);U+5741(3,9); +U+5742(0);U+962A(3,8,9);U+962A(3,8,9) +U+5744(0);U+5744(3); +U+5745(0);U+5745(0,9); +U+5746(0);U+5746(0); +U+5747(0);U+5747(5,9); +U+5749(0);U+5749(0,9); +U+574A(0);U+574A(5,9); +U+574B(0);U+574B(3,9); +U+574C(0);U+574C(5,9); +U+574D(0);U+574D(5,9); +U+574E(0);U+574E(5,9); +U+574F(0);U+574F(1,3,9),U+58DE(1,3,8,9);U+576F(4,9),U+58CA(4),U+58DE(1,3,8,9),U+7623(4,9) +U+5750(0);U+5750(5,9);U+5EA7(3,8,9) +U+5751(0);U+5751(5,9);U+962C(2,3,8,9) +U+5752(0);U+5752(0,9); +U+5753(0);U+5753(0); +U+5754(0);U+5754(0); +U+5757(0);U+584A(1,3,8,9);U+51F7(3),U+584A(1,3,8,9) +U+5759(0);U+5759(0); +U+575A(0);U+5805(1,3,8,9);U+5805(1,3,8,9) +U+575B(0);U+58C7(1,3,8,9),U+7F48(4,9);U+58C7(1,3,8,9),U+7F48(4,9),U+7F4E(1,3) +U+575C(0);U+58E2(1,3,8,9);U+58E2(1,3,8,9) +U+575D(0);U+58E9(1,3,8,9);U+57BB(4),U+58E9(1,3,8,9) +U+575E(0);U+5862(1,3,8,9);U+5862(1,3,8,9) +U+575F(0);U+58B3(1,3,8,9);U+58B3(1,3,8,9) +U+5760(0);U+589C(1,3,8,9);U+589C(1,3,8,9) +U+5761(0);U+5761(5,9);U+5CA5(3,9) +U+5762(0);U+5762(0,9); +U+5764(0);U+5764(5,9);U+5803(2,3) +U+5765(0);U+5765(0); +U+5766(0);U+5766(5,9); +U+5767(0);U+5767(0); +U+5768(0);U+5768(5,9); +U+5769(0);U+5769(5,9); +U+576A(0);U+576A(5,9); +U+576B(0);U+576B(5,9);U+5E97(3,8,9) +U+576C(0);U+576C(0); +U+576D(0);U+576D(5,9); +U+576F(0);U+576F(5,9);U+574F(4,9),U+58DE(3,8,9),U+58CA(4),U+7623(4,9) +U+5770(0);U+5770(3,9); +U+5771(0);U+5771(0,9); +U+5772(0);U+5772(0,9); +U+5773(0);U+5773(5,9); +U+5774(0);U+5774(0,9);U+9646(3),U+9678(1,3,8,9) +U+5775(0);U+5775(0,9);U+4E18(2,3,9),U+4E20(2,3,8) +U+5776(0);U+5776(5,9); +U+5777(0);U+5777(5,9); +U+5779(0);U+5779(0); +U+577A(0);U+577A(0); +U+577B(0);U+577B(5,9); + +U+577C(0);U+577C(5,9); +U+577D(0);U+577D(0,9); +U+577E(0);U+577E(0); +U+577F(0);U+9644(2,3,9);U+9644(2,3,9) +U+5780(0);U+5780(0,9); +U+5782(0);U+5782(5,9);U+57C0(3,8) +U+5783(0);U+5783(5,9); +U+5784(0);U+58DF(1,3,8,9);U+5785(7),U+58DF(1,3,8,9),U+58E0(7) +U+5785(0);U+58DF(4,9);U+5784(7),U+58DF(4,9),U+58E0(4,8) +U+5786(0);U+58DA(1,3,8,9);U+58DA(1,3,8,9),U+7F4F(3,9) +U+5788(0);U+5788(0); +U+5789(0);U+5789(0); +U+578A(0);U+578A(0); +U+578B(0);U+578B(5,9); +U+578C(0);U+578C(5,9); +U+578D(0);U+578D(0); +U+578E(0);U+578E(0); +U+578F(0);U+578F(0,9); +U+5790(0);U+5790(3); +U+5791(0);U+5791(0); +U+5792(0);U+58D8(1,3,8,9);U+58D8(1,3,8,9),U+58E8(3,9) +U+5793(0);U+5793(5,9);U+9654(3,8,9) +U+5794(0);U+5794(0,9); +U+5795(0);U+5795(0,9); +U+5797(0);U+5797(3,9); +U+5798(0);U+5798(0,9); +U+5799(0);U+5799(0,9); +U+579A(0);U+579A(0,9);U+5C27(3),U+582F(1,3,8,9),U+5C2D(3,4) +U+579B(0);U+579B(5,9);U+579C(2,3,8) +U+579C(0);U+579B(2,3,8,9);U+579B(2,3,8,9) +U+579D(0);U+579D(3,9); +U+579E(0);U+579E(0,9); +U+579F(0);U+579F(0,9); +U+57A0(0);U+57A0(5,9);U+573B(3,8,9) +U+57A1(0);U+57A1(5); +U+57A2(0);U+57A2(5,9); +U+57A3(0);U+57A3(5,9); +U+57A4(0);U+57A4(5,9); +U+57A5(0);U+57A5(0,9); +U+57A6(0);U+58BE(1,3,8,9);U+58BE(1,3,8,9) +U+57A7(0);U+57A7(5); +U+57A9(0);U+580A(1,3,8,9);U+580A(1,3,8,9),U+8056(3,8,9),U+5723(1,3,8,9) +U+57AA(0);U+57AA(0); +U+57AB(0);U+588A(1,3,8,9);U+588A(1,3,8,9) +U+57AC(0);U+57AC(0); +U+57AD(0);U+57E1(1,3,8,9);U+57E1(1,3,8,9) +U+57AE(0);U+57AE(5,9); +U+57AF(0);U+57AF(4); +U+57B0(0);U+57B0(0); +U+57B1(0);U+58CB(4,8);U+58CB(4,8) +U+57B2(0);U+584F(1,3,8,9);U+584F(1,3,8,9) +U+57B3(0);U+57B3(0); +U+57B4(0);U+57B4(5);U+5816(7,8) +U+57B5(0);U+57B5(0,9); +U+57B6(0);U+57B6(0,9); +U+57B7(0);U+57B7(0); +U+57B8(0);U+57B8(5,9); +U+57B9(0);U+57B9(4,9); +U+57BA(0);U+57BA(0,9); +U+57BB(0);U+58E9(3,8,9);U+575D(4),U+58E9(3,8,9) +U+57BC(0);U+57BC(0,9); +U+57BD(0);U+57BD(0,9); +U+57BE(0);U+57BE(0); + +U+57BF(0);U+57BF(0,9); +U+57C0(0);U+5782(3,8,9);U+5782(3,8,9) +U+57C1(0);U+57C1(0,9); +U+57C2(0);U+57C2(5,9); +U+57C3(0);U+57C3(5,9); +U+57C4(0);U+57C4(0); +U+57C5(0);U+57C5(0); +U+57C6(0);U+57C6(0,9); +U+57C7(0);U+57C7(3,9); +U+57C8(0);U+57C8(0); +U+57C9(0);U+57C9(0); +U+57CB(0);U+57CB(5,9); +U+57CC(0);U+57CC(4,9); +U+57CD(0);U+57CD(0); +U+57CE(0);U+57CE(5,9); +U+57CF(0);U+57CF(5,9); +U+57D0(0);U+57D0(0,9); +U+57D2(0);U+57D2(5,9);U+57D3(4,8) +U+57D3(0);U+57D2(4,8,9);U+57D2(4,8,9) +U+57D4(0);U+57D4(5,9); +U+57D5(0);U+57D5(5,9); +U+57D6(0);U+57D6(0); +U+57D8(0);U+5852(1,3,8,9);U+5852(1,3,8,9) +U+57D9(0);U+5864(1,3,8,9);U+5864(1,3,8,9),U+58CE(4,9) +U+57DA(0);U+581D(1,3,8,9);U+581D(1,3,8,9) +U+57DC(0);U+57DC(0,9);U+91CE(2,3,8,9) +U+57DD(0);U+57DD(5); +U+57DF(0);U+57DF(5,9); +U+57E0(0);U+57E0(5,9); +U+57E1(0);U+57E1(0,9);U+57AD(1,3,8) +U+57E2(0);U+57E2(0,9); +U+57E3(0);U+57E3(0,9); +U+57E4(0);U+57E4(5,9); +U+57E5(0);U+57E5(0,9); +U+57E6(0);U+57E6(0); +U+57E7(0);U+57E7(3,9); +U+57E8(0);U+57E8(0); +U+57E9(0);U+57E9(3,9); +U+57EA(0);U+57EA(0); +U+57EB(0);U+57EB(0); +U+57EC(0);U+57EC(0,9); +U+57ED(0);U+57ED(5,9); +U+57EE(0);U+57EE(0,9); +U+57EF(0);U+57EF(5); +U+57F0(0);U+57F0(0,9); +U+57F1(0);U+57F1(0,9); +U+57F2(0);U+57F2(3,9); +U+57F3(0);U+57F3(4,9); +U+57F4(0);U+57F4(5,9); +U+57F5(0);U+57F5(0,9); +U+57F6(0);U+57F6(0,9); +U+57F7(0);U+57F7(0,9);U+6267(1,3,8),U+74E1(1,3,8,9) +U+57F8(0);U+57F8(5,9); +U+57F9(0);U+57F9(5,9); +U+57FA(0);U+57FA(5,9); +U+57FB(0);U+57FB(0,9); +U+57FC(0);U+57FC(0,9);U+5D0E(7,8,9),U+7895(3,9) +U+57FD(0);U+57FD(5,9); +U+57FE(0);U+57FE(0); +U+57FF(0);U+57FF(0); +U+5800(0);U+5800(5,9); +U+5801(0);U+5801(0,9); +U+5802(0);U+5802(5,9); + +U+5803(0);U+5764(2,3,9);U+5764(2,3,9) +U+5804(0);U+5804(0,9); +U+5805(0);U+5805(0,9);U+575A(1,3,8) +U+5806(0);U+5806(5,9); +U+5807(0);U+5807(5,9);U+84F3(3,9),U+83EB(4,8,9) +U+5808(0);U+5808(0,9);U+7F38(3,9) +U+5809(0);U+5809(0,9); +U+580A(0);U+580A(0,9);U+57A9(1,3,8),U+8056(1,3,8,9),U+5723(1,3,8,9) +U+580B(0);U+580B(5,9);U+5874(3,9) +U+580C(0);U+580C(0,9); +U+580D(0);U+580D(5,9); +U+580E(0);U+580E(0,9); +U+580F(0);U+580F(0); +U+5810(0);U+5810(0,9); +U+5811(0);U+5879(1,3,8,9);U+5879(1,3,8,9) +U+5812(0);U+5812(0); +U+5813(0);U+5813(0); +U+5814(0);U+5814(0,9); +U+5815(0);U+58AE(1,3,8,9);U+58AE(1,3,8,9),U+58AF(3,9) +U+5816(0);U+57B4(7,8);U+57B4(7,8) +U+5819(0);U+5819(5,9); +U+581A(0);U+581A(0); +U+581B(0);U+581B(0,9); +U+581C(0);U+581C(0,9); +U+581D(0);U+581D(0,9);U+57DA(1,3,8) +U+581E(0);U+581E(5,9); +U+581F(0);U+581F(0); +U+5820(0);U+5820(5,9); +U+5821(0);U+5821(5,9); +U+5822(0);U+5822(0); +U+5823(0);U+5823(0,9); +U+5824(0);U+5824(5,9);U+9684(2,3,9) +U+5825(0);U+5825(0,9); +U+5826(0);U+968E(2,3,8,9);U+968E(2,3,8,9),U+9636(4) +U+5827(0);U+5827(0,9);U+58D6(4,9) +U+5828(0);U+5828(0,9); +U+5829(0);U+5829(0,9); +U+582A(0);U+582A(5,9); +U+582B(0);U+582B(0); +U+582C(0);U+582C(0,9); +U+582D(0);U+582D(3,9); +U+582E(0);U+582E(3,9); +U+582F(0);U+582F(0,9);U+5C27(1,3,8),U+5C2D(4,8),U+579A(0,1,3,8,9) +U+5830(0);U+5830(5,9); +U+5831(0);U+5831(0,9);U+62A5(1,3,8) +U+5832(0);U+5832(3,9); +U+5833(0);U+5833(0,9); +U+5834(0);U+5834(0,9);U+573A(1,3,8),U+5872(2,3,8) +U+5835(0);U+5835(5,9); +U+5836(0);U+5836(3,9); +U+5837(0);U+5837(0,9);U+7AA8(3,9) +U+5838(0);U+5838(0,9); +U+5839(0);U+5839(0,9); +U+583A(0);U+754C(3,8,9);U+754C(3,8,9),U+754D(3,8) +U+583B(0);U+583B(0,9); +U+583C(0);U+583C(0); +U+583D(0);U+583D(0,9); +U+583E(0);U+583E(0); +U+583F(0);U+583F(0,9); +U+5840(0);U+5840(0); +U+5842(0);U+5842(0); +U+5843(0);U+5843(0); +U+5844(0);U+5844(5); + +U+5845(0);U+5845(0); +U+5846(0);U+58EA(4,8);U+58EA(4,8) +U+5847(0);U+5847(0); +U+5848(0);U+5848(0,9);U+588D(4,8) +U+5849(0);U+5849(0,9); +U+584A(0);U+584A(0,9);U+51F7(3,8),U+5757(1,3,8) +U+584B(0);U+584B(0,9);U+8314(1,3,8) +U+584C(0);U+584C(5,9); +U+584D(0);U+584D(5,9); +U+584E(0);U+584E(0,9); +U+584F(0);U+584F(0,9);U+57B2(1,3,8) +U+5851(0);U+5851(5,9); +U+5852(0);U+5852(0,9);U+57D8(1,3,8) +U+5853(0);U+5853(0,9); +U+5854(0);U+5854(5,9);U+5896(2,3,8) +U+5855(0);U+5855(0,9); +U+5857(0);U+5857(0,9);U+6D82(1,3,8,9),U+51C3(0,1,3,4,8) +U+5858(0);U+5858(5,9); +U+5859(0);U+5859(0,9);U+786E(4,9),U+78BA(1,3,4,8,9),U+78BB(4,9),U+792D(3,4,9) +U+585A(0);U+585A(4,9);U+51A2(2,3,8,9) +U+585B(0);U+585B(0,9); +U+585C(0);U+585C(0);U+5873(3,8) +U+585D(0);U+585D(0,9); +U+585E(0);U+585E(5,9); +U+585F(0);U+846C(2,3,8,9);U+846C(2,3,8,9) +U+5861(0);U+586B(4,8,9);U+586B(4,8,9) +U+5862(0);U+5862(0,9);U+575E(1,3,8) +U+5863(0);U+5863(3,9); +U+5864(0);U+5864(0,9);U+57D9(1,3,8),U+58CE(1,3,4,8,9) +U+5865(0);U+5865(5,9); +U+5868(0);U+5868(0,9); +U+5869(0);U+9E7D(3,8,9);U+76D0(3),U+9E7D(3,8,9) +U+586A(0);U+586A(0); +U+586B(0);U+586B(5,9);U+5861(4,8) +U+586C(0);U+586C(5); +U+586D(0);U+586D(0,9); +U+586E(0);U+586E(0); +U+586F(0);U+586F(0,9); +U+5870(0);U+5870(0); +U+5871(0);U+5871(0,9); +U+5872(0);U+5834(2,3,8,9);U+573A(4),U+5834(2,3,8,9) +U+5873(0);U+5873(3);U+585C(3,8) +U+5874(0);U+5874(0,9);U+580B(3,9) +U+5875(0);U+5875(0,9);U+5C18(1,3,8) +U+5876(0);U+5876(0,9); +U+5878(0);U+5878(3); +U+5879(0);U+5879(0,9);U+5811(1,3,8) +U+587A(0);U+587A(3,9); +U+587B(0);U+587B(0,9); +U+587C(0);U+587C(0,9); +U+587D(0);U+587D(3,9); +U+587E(0);U+587E(5,9); +U+587F(0);U+587F(0,9); +U+5880(0);U+5880(5,9); +U+5881(0);U+5881(5,9); +U+5882(0);U+5882(0,9);U+6807(3),U+6A19(1,3,8,9) +U+5883(0);U+5883(5,9); +U+5884(0);U+5884(0); +U+5885(0);U+5885(5,9); +U+5886(0);U+5886(0,9); +U+5887(0);U+5887(0,9);U+969C(3,9) +U+5888(0);U+5888(0,9); +U+5889(0);U+5889(5,9); + +U+588A(0);U+588A(0,9);U+57AB(1,3,8) +U+588B(0);U+588B(3,9); +U+588C(0);U+588C(3); +U+588D(0);U+5848(4,8,9);U+5848(4,8,9) +U+588E(0);U+588E(0,9);U+90ED(3,9) +U+588F(0);U+588F(0,9); +U+5890(0);U+5890(3,9); +U+5891(0);U+5891(0,9); +U+5892(0);U+5892(5); +U+5893(0);U+5893(5,9); +U+5894(0);U+5894(0,9); +U+5896(0);U+5854(2,3,8,9);U+5854(2,3,8,9) +U+5897(0);U+589E(4,8,9);U+589E(4,8,9) +U+5898(0);U+5898(0,9); +U+5899(0);U+58BB(1,3,8,9),U+7246(4,8,9);U+58BB(1,3,8,9),U+7246(4,8,9) +U+589A(0);U+589A(5); +U+589B(0);U+589B(0); +U+589C(0);U+589C(0,9);U+5760(1,3,8) +U+589D(0);U+589D(3,9); +U+589E(0);U+589E(5,9);U+5897(4,8) +U+589F(0);U+589F(5,9); +U+58A0(0);U+58A0(0,9); +U+58A1(0);U+58A1(3,9); +U+58A2(0);U+58A2(3); +U+58A3(0);U+58A3(3,9); +U+58A4(0);U+58A4(0); +U+58A5(0);U+58A5(0,9);U+7583(3),U+757D(3,9) +U+58A6(0);U+58A6(0,9); +U+58A7(0);U+58A7(0); +U+58A8(0);U+58A8(5,9); +U+58A9(0);U+58A9(5,9); +U+58AB(0);U+58AB(0,9);U+6A3D(3,8,9),U+7F47(2,3,8) +U+58AC(0);U+58AC(0,9);U+5730(3,9) +U+58AD(0);U+58AD(0); +U+58AE(0);U+58AE(0,9);U+5815(1,3,8),U+58AF(1,3,8,9) +U+58AF(0);U+58AF(0,9);U+5815(3),U+58AE(1,3,8,9) +U+58B0(0);U+58B0(0); +U+58B1(0);U+58B1(0,9); +U+58B2(0);U+58B2(0); +U+58B3(0);U+58B3(0,9);U+575F(1,3,8) +U+58B4(0);U+58B4(0); +U+58B7(0);U+58B7(0); +U+58B8(0);U+58B8(0); +U+58B9(0);U+58B9(0); +U+58BA(0);U+58BA(3,9); +U+58BB(0);U+58BB(0,9);U+5899(1,3,8),U+7246(2,3,8,9) +U+58BC(0);U+58BC(5,9); +U+58BD(0);U+58BD(3,9); +U+58BE(0);U+58BE(0,9);U+57A6(1,3,8) +U+58BF(0);U+58BF(0,9); +U+58C1(0);U+58C1(5,9); +U+58C2(0);U+58C2(0,9); +U+58C5(0);U+58C5(5,9); +U+58C6(0);U+58C6(0,9); +U+58C7(0);U+58C7(0,9);U+575B(1,3,8),U+7F4E(4),U+7F48(1,3,4,8,9) +U+58C8(0);U+58C8(0,9); +U+58C9(0);U+58C9(0,9); +U+58CA(0);U+58DE(4,8,9);U+574F(4,9),U+58DE(4,8,9),U+576F(4,9),U+7623(4,9) +U+58CB(0);U+58CB(0);U+57B1(4,8) +U+58CE(0);U+58CE(0,9);U+57D9(4),U+5864(1,3,4,8,9) +U+58CF(0);U+58CF(0,9); +U+58D1(0);U+58D1(5,9); +U+58D2(0);U+58D2(3,9); + +U+58D3(0);U+58D3(0,9);U+538B(1,3,8),U+5727(4,8) +U+58D4(0);U+58D4(0,9); +U+58D5(0);U+58D5(5,9); +U+58D6(0);U+58D6(4,9);U+5827(4,9) +U+58D7(0);U+58D7(0); +U+58D8(0);U+58D8(0,9);U+5792(1,3,8),U+58E8(1,3,8,9) +U+58D9(0);U+58D9(0,9);U+5739(1,3,8) +U+58DA(0);U+58DA(0,9);U+5786(1,3,8),U+7F4F(1,3,8,9) +U+58DB(0);U+58DB(0,9); +U+58DD(0);U+58DD(0,9); +U+58DE(0);U+58DE(0,9);U+574F(1,3,8,9),U+576F(3,8,9),U+58CA(4,8),U+7623(1,3,4,8,9) +U+58DF(0);U+58DF(0,9);U+5784(1,3,4,8),U+5785(4),U+58E0(3) +U+58E0(0);U+58DF(3,9);U+5784(7),U+5785(4,8),U+58DF(3,9) +U+58E2(0);U+58E2(0,9);U+575C(1,3,8) +U+58E3(0);U+58E3(3,9); +U+58E4(0);U+58E4(5,9); +U+58E5(0);U+58E5(0); +U+58E7(0);U+58E7(0,9);U+5CA9(3,9),U+55A6(0,3,4,9),U+5D52(2,3,4,9),U+5DCC(3,4),U+5DD6(2,3,4,8,9),U+789E(3,4,9),U+7939(3,4,9) +U+58E8(0);U+58E8(0,9);U+5792(3),U+58D8(1,3,8,9) +U+58E9(0);U+58E9(0,9);U+575D(1,3,8),U+57BB(3,8) +U+58EA(0);U+58EA(0);U+5846(4,8) +U+58EB(0);U+58EB(5,9); +U+58EC(0);U+58EC(5,9); +U+58ED(0);U+58ED(0); +U+58EE(0);U+58EF(1,3,4,8,9);U+58EF(1,3,4,8,9) +U+58EF(0);U+58EF(0,9);U+58EE(1,3,8) +U+58F0(0);U+8072(1,3,8,9);U+8072(1,3,8,9) +U+58F1(0);U+58F9(4,9);U+58F9(4,9),U+4E00(3,4,5,8,9),U+5F0C(3,4,8) +U+58F2(0);U+8CE3(4,8,9);U+5356(4),U+8CE3(4,8,9) +U+58F3(0);U+6BBC(4,8,9);U+6BBB(1,3,8),U+6BBC(4,8,9) +U+58F4(0);U+58F4(3,9); +U+58F6(0);U+58FA(1,3,8,9);U+58FA(1,3,8,9),U+58F7(3) +U+58F7(0);U+58FA(3,8,9);U+58F6(3),U+58FA(3,8,9) +U+58F8(0);U+58FC(1,3,8,9);U+58FC(1,3,8,9) +U+58F9(0);U+58F9(5,9);U+4E00(3,8,9),U+58F1(4),U+5F0C(3,8) +U+58FA(0);U+58FA(0,9);U+58F6(1,3,8),U+58F7(3,8) +U+58FB(0);U+58FB(3); +U+58FC(0);U+58FC(0,9);U+58F8(1,3,8) +U+58FD(0);U+58FD(0,9);U+5900(4,8),U+5BFF(1,3,8) +U+58FE(0);U+58FE(0,9); +U+58FF(0);U+58FF(0,9);U+8E72(4,9) +U+5900(0);U+58FD(4,8,9);U+58FD(4,8,9),U+5BFF(4) +U+5902(0);U+5902(5); +U+5903(0);U+5903(0,9); +U+5904(0);U+8655(1,3,8,9);U+8655(1,3,8,9) +U+5906(0);U+5906(0,9); +U+5907(0);U+5099(1,3,8,9);U+4FFB(4),U+5079(3),U+5099(1,3,8,9) +U+5909(0);U+8B8A(3,8,9);U+53D8(3),U+8B8A(3,8,9) +U+590A(0);U+590A(0); +U+590B(0);U+590B(0); +U+590C(0);U+590C(0,9); +U+590D(0);U+590D(1,3,9),U+5FA9(1,3,8,9),U+8907(1,3,9);U+5FA9(1,3,8,9),U+8907(1,3,9),U+8986(1,3,8,9) +U+590E(0);U+590E(0,9); +U+590F(0);U+590F(5,9); +U+5910(0);U+657B(4,8,9);U+657B(4,8,9) +U+5912(0);U+5912(3,9); +U+5914(0);U+5914(5,9); +U+5915(0);U+5915(5,9); +U+5916(0);U+5916(5,9); +U+5917(0);U+5917(3,9); +U+5918(0);U+536F(2,3,8,9);U+536F(2,3,8,9),U+623C(2,3,8) + +U+5919(0);U+5919(5,9); +U+591A(0);U+591A(5,9);U+591B(4,8) +U+591B(0);U+591A(4,8,9);U+591A(4,8,9) +U+591C(0);U+591C(5,9);U+4EB1(2,3,8) +U+591D(0);U+591D(4); +U+591E(0);U+591E(0); +U+591F(0);U+5920(2,3,8,9);U+5920(2,3,8,9) +U+5920(0);U+5920(0,9);U+591F(2,3,8) +U+5921(0);U+5921(0); +U+5922(0);U+5922(0,9);U+68A6(1,3,8) +U+5924(0);U+5924(5,9); +U+5925(0);U+5925(0,9);U+4F19(1,3,8,9) +U+5926(0);U+5926(0); +U+5927(0);U+5927(5,9); +U+5928(0);U+5928(0); +U+5929(0);U+5929(5,9); +U+592A(0);U+592A(5,9); +U+592B(0);U+592B(5,9),U+4F15(3,9);U+4F15(3,9) +U+592C(0);U+592C(4,9); +U+592D(0);U+592D(5,9);U+6B80(2,3,8,9) +U+592E(0);U+592E(5,9); +U+592F(0);U+592F(5,9); +U+5930(0);U+5930(0); +U+5931(0);U+5931(5,9); +U+5932(0);U+672C(3,8,9);U+672C(3,8,9) +U+5934(0);U+982D(1,3,8,9);U+982D(1,3,8,9) +U+5935(0);U+5935(0); +U+5937(0);U+5937(5,9);U+4F87(3,9) +U+5938(0);U+5938(1,3,9),U+8A87(1,3,8,9);U+8A87(1,3,8,9) +U+5939(0);U+593E(1,3,8,9);U+593E(1,3,8,9),U+88CC(4,9) +U+593A(0);U+596A(1,3,8,9);U+596A(1,3,8,9),U+6553(3,9) +U+593B(0);U+593B(0); +U+593C(0);U+593C(5,9); +U+593D(0);U+593D(0); +U+593E(0);U+593E(0,9);U+5939(1,3,8),U+88CC(1,3,4,8,9) +U+593F(0);U+593F(0); +U+5940(0);U+5940(0,9); +U+5941(0);U+5969(1,3,8,9);U+5333(7),U+5969(1,3,8,9) +U+5942(0);U+5950(4,8,9);U+5950(4,8,9) +U+5943(0);U+5943(0); +U+5944(0);U+5944(5,9); +U+5945(0);U+5945(3,9); +U+5946(0);U+5946(0); +U+5947(0);U+5947(5,9);U+7AD2(3,8) +U+5948(0);U+5948(5,9);U+67F0(3,8,9) +U+5949(0);U+5949(5,9); +U+594A(0);U+594A(0,9); +U+594B(0);U+596E(1,3,8,9);U+596E(1,3,8,9) +U+594C(0);U+9EDE(4,8,9);U+70B9(4),U+9EDE(4,8,9) +U+594D(0);U+594D(0); +U+594E(0);U+594E(5,9); +U+594F(0);U+594F(5,9); +U+5950(0);U+5950(0,9);U+5942(4,8) +U+5951(0);U+5951(5,9);U+6814(3,9) +U+5952(0);U+5952(0); +U+5953(0);U+5953(3,9); +U+5954(0);U+5954(5,9);U+7287(2,3,8),U+9029(2,3,8) +U+5955(0);U+5955(5,9); +U+5956(0);U+734E(4,9);U+734E(4,9),U+5968(4),U+596C(1,3,8) +U+5957(0);U+5957(5,9); +U+5958(0);U+5958(5,9); +U+595A(0);U+595A(5,9); +U+595C(0);U+595C(0,9); + +U+595D(0);U+595D(0); +U+595E(0);U+595E(0); +U+595F(0);U+595F(0); +U+5960(0);U+5960(5,9); +U+5961(0);U+5961(0,9); +U+5962(0);U+5962(5,9); +U+5963(0);U+5963(0); +U+5964(0);U+5964(0); +U+5965(0);U+5967(7,8,9);U+5967(7,8,9) +U+5966(0);U+5966(0); +U+5967(0);U+5967(0,9);U+5965(7,8) +U+5968(0);U+734E(8,9);U+734E(8,9),U+5956(4),U+596C(3,8) +U+5969(0);U+5969(0,9);U+5333(2,8),U+5941(1,3,8) +U+596A(0);U+596A(0,9);U+593A(1,3,8),U+6553(1,3,8,9) +U+596B(0);U+596B(0,9); +U+596C(0);U+734E(2,8,9);U+734E(2,8,9),U+5956(1,3,8),U+5968(3,8) +U+596D(0);U+596D(0,9); +U+596E(0);U+596E(0,9);U+594B(1,3,8) +U+596F(0);U+596F(0); +U+5970(0);U+5970(0,9); +U+5971(0);U+5971(3,9); +U+5972(0);U+5972(0,9); +U+5973(0);U+5973(5,9); +U+5974(0);U+5974(5,9); +U+5975(0);U+5975(0); +U+5976(0);U+5976(5,9);U+59B3(2,9),U+5B2D(2,3,8,9),U+4F32(2,3,8),U+4F60(2,3,5,8,9),U+511E(2,3,8) +U+5977(0);U+5977(0,9); +U+5978(0);U+5978(5,9),U+59E6(2,9);U+59E6(2,9) +U+5979(0);U+5979(5,9); +U+597A(0);U+597A(0); +U+597B(0);U+597B(0,9); +U+597C(0);U+597C(0,9);U+59F9(3) +U+597D(0);U+597D(5,9); +U+597E(0);U+597E(0,9); +U+597F(0);U+597F(0,9); +U+5980(0);U+5980(0,9); +U+5981(0);U+5981(5,9); +U+5982(0);U+5982(5,9); +U+5983(0);U+5983(5,9); +U+5984(0);U+5984(5,9); +U+5985(0);U+5985(0,9); +U+5986(0);U+599D(1,3,4,8,9);U+599D(1,3,4,8,9) +U+5987(0);U+5A66(1,3,8,9);U+5A66(1,3,8,9) +U+5988(0);U+5ABD(1,3,8,9);U+5ABD(1,3,8,9) +U+5989(0);U+5989(3); +U+598A(0);U+598A(5,9);U+59D9(2,8) +U+598B(0);U+598B(0); +U+598C(0);U+598C(0); +U+598D(0);U+598D(5,9);U+59F8(3,8) +U+598E(0);U+598E(0,9); +U+598F(0);U+598F(0,9); +U+5990(0);U+5990(0,9); +U+5991(0);U+5991(0); +U+5992(0);U+5992(5,9);U+59AC(2,3,8) +U+5993(0);U+5993(5,9); +U+5994(0);U+5994(0); +U+5995(0);U+5995(0); +U+5996(0);U+5996(5,9);U+7945(3,9),U+8A1E(3,9) +U+5997(0);U+5997(5,9); +U+5998(0);U+5998(0,9); +U+5999(0);U+5999(5,9);U+7385(2,3,8,9) +U+599A(0);U+599A(0); + +U+599C(0);U+599C(0); +U+599D(0);U+599D(0,9);U+5986(1,3,8) +U+599E(0);U+599E(5,9); +U+599F(0);U+599F(0); +U+59A0(0);U+59A0(0,9); +U+59A1(0);U+59A1(0,9); +U+59A2(0);U+59A2(0,9); +U+59A3(0);U+59A3(5,9); +U+59A4(0);U+59A4(5,9); +U+59A5(0);U+59A5(5,9); +U+59A6(0);U+59A6(0,9); +U+59A7(0);U+59A7(0,9); +U+59A8(0);U+59A8(5,9); +U+59A9(0);U+5AF5(1,3,8,9);U+5AF5(1,3,8,9) +U+59AA(0);U+5AD7(1,3,8,9);U+5AD7(1,3,8,9) +U+59AB(0);U+5AAF(3,8,9);U+5AAF(3,8,9),U+5B00(1,8) +U+59AC(0);U+5992(2,3,8,9);U+5992(2,3,8,9) +U+59AD(0);U+59AD(0); +U+59AE(0);U+59AE(5,9); +U+59AF(0);U+59AF(5,9); +U+59B0(0);U+59B0(0); +U+59B1(0);U+59B1(0,9); +U+59B2(0);U+59B2(5,9); +U+59B3(0);U+59B3(0,9);U+4F60(2,3,8,9),U+5976(2,9),U+5B2D(3,9),U+4F32(2,3,5,8),U+511E(2,3,8) +U+59B4(0);U+59B4(0,9); +U+59B5(0);U+59B5(0,9); +U+59B6(0);U+59B6(0,9); +U+59B8(0);U+59B8(3); +U+59B9(0);U+59B9(5,9); +U+59BA(0);U+59BA(0,9); +U+59BB(0);U+59BB(5,9); +U+59BC(0);U+59BC(0,9); +U+59BD(0);U+59BD(0,9); +U+59BE(0);U+59BE(5,9); +U+59BF(0);U+59BF(3); +U+59C0(0);U+59C0(0,9); +U+59C1(0);U+59C1(0,9); +U+59C2(0);U+59C2(0); +U+59C3(0);U+59C3(0,9); +U+59C4(0);U+59C4(0); +U+59C5(0);U+59C5(0,9); +U+59C6(0);U+59C6(5,9); +U+59C7(0);U+59C7(0,9); +U+59C8(0);U+59C8(0,9); +U+59C9(0);U+59CA(2,3,8,9);U+59CA(2,3,8,9) +U+59CA(0);U+59CA(5,9);U+59C9(2,3,8) +U+59CB(0);U+59CB(5,9); +U+59CC(0);U+59CC(0,9); +U+59CD(0);U+59CD(0,9);U+59D7(2,3,8) +U+59CE(0);U+59CE(0,9); +U+59CF(0);U+59CF(0,9); +U+59D0(0);U+59D0(5,9);U+5A8E(3,9) +U+59D1(0);U+59D1(5,9); +U+59D2(0);U+59D2(5,9); +U+59D3(0);U+59D3(5,9); +U+59D4(0);U+59D4(5,9); +U+59D5(0);U+59D5(0); +U+59D6(0);U+59D6(0,9); +U+59D7(0);U+59CD(2,3,8,9);U+59CD(2,3,8,9) +U+59D8(0);U+59D8(5,9); +U+59D9(0);U+598A(2,8,9);U+598A(2,8,9) +U+59DA(0);U+59DA(5,9); + +U+59DB(0);U+59DB(0,9); +U+59DC(0);U+59DC(1,3,9),U+8591(1,3,4,8,9);U+8591(1,3,4,8,9) +U+59DD(0);U+59DD(5,9); +U+59DE(0);U+59DE(3,9); +U+59DF(0);U+59DF(0); +U+59E0(0);U+59E0(0,9); +U+59E1(0);U+59E1(0,9); +U+59E2(0);U+5A1F(3,8,9);U+5A1F(3,8,9) +U+59E3(0);U+59E3(5,9); +U+59E4(0);U+59E4(3,9); +U+59E5(0);U+59E5(5,9); +U+59E6(0);U+59E6(0,9);U+5978(2,9) +U+59E8(0);U+59E8(5,9); +U+59E9(0);U+59E9(0,9); +U+59EA(0);U+59EA(0,9);U+4F84(2,8,9) +U+59EB(0);U+59EC(4,8,9);U+59EC(4,8,9) +U+59EC(0);U+59EC(5,9);U+59EB(4,8) +U+59ED(0);U+59ED(0,9); +U+59EE(0);U+59EE(0,9); +U+59EF(0);U+59EF(0); +U+59F0(0);U+59F0(0); +U+59F1(0);U+59F1(3,9); +U+59F2(0);U+59F2(0,9); +U+59F3(0);U+59F3(0,9); +U+59F4(0);U+59F4(0,9); +U+59F5(0);U+59F5(0,9); +U+59F6(0);U+59F6(0,9); +U+59F7(0);U+59F7(3,9); +U+59F8(0);U+598D(3,8,9);U+598D(3,8,9) +U+59F9(0);U+59F9(5);U+597C(3,9) +U+59FA(0);U+59FA(0,9); +U+59FB(0);U+59FB(5,9);U+5A63(2,8) +U+59FC(0);U+59FC(0,9); +U+59FD(0);U+59FD(0,9); +U+59FE(0);U+59FE(0,9); +U+59FF(0);U+59FF(5,9); +U+5A00(0);U+5A00(0,9); +U+5A01(0);U+5A01(5,9); +U+5A02(0);U+5A02(3); +U+5A03(0);U+5A03(5,9); +U+5A04(0);U+5A41(1,3,8,9);U+5A41(1,3,8,9) +U+5A05(0);U+5A6D(1,3,8,9);U+5A6D(1,3,8,9) +U+5A06(0);U+5B08(1,3,8,9);U+5B08(1,3,8,9) +U+5A07(0);U+5B0C(1,3,8,9);U+5B0C(1,3,8,9) +U+5A08(0);U+5B4C(1,3,8,9);U+5B4C(1,3,8,9) +U+5A09(0);U+5A09(5,9); +U+5A0A(0);U+5A0A(0,9); +U+5A0B(0);U+5A0B(0); +U+5A0C(0);U+5A0C(5,9); +U+5A0D(0);U+5A0D(0); +U+5A0E(0);U+5A0E(0); +U+5A0F(0);U+5A0F(0,9); +U+5A10(0);U+5A10(0); +U+5A11(0);U+5A11(5,9); +U+5A12(0);U+5A12(0); +U+5A13(0);U+5A13(5,9); +U+5A14(0);U+5A14(0); +U+5A15(0);U+5A15(3,9); +U+5A16(0);U+5A16(4,9); +U+5A17(0);U+5A17(3,9); +U+5A18(0);U+5A18(5,9),U+5B43(2,8,9);U+5B22(7,8),U+5B43(2,8,9) +U+5A19(0);U+5A19(0,9); +U+5A1A(0);U+5583(3,8,9);U+5583(3,8,9),U+8AF5(3,8,9) + +U+5A1B(0);U+5A1B(0,9);U+5A2F(8),U+5A31(4,8) +U+5A1C(0);U+5A1C(5,9); +U+5A1D(0);U+5A1D(0); +U+5A1E(0);U+5A1E(3,9); +U+5A1F(0);U+5A1F(5,9);U+59E2(3,8) +U+5A20(0);U+5A20(5,9); +U+5A21(0);U+5A21(0); +U+5A22(0);U+5A22(0); +U+5A23(0);U+5A23(5,9); +U+5A25(0);U+5A25(5,9); +U+5A27(0);U+5A27(0); +U+5A28(0);U+5A28(0); +U+5A29(0);U+5A29(5,9); +U+5A2A(0);U+5A2A(0); +U+5A2B(0);U+5A2B(0); +U+5A2D(0);U+5A2D(0,9); +U+5A2E(0);U+5A2E(0,9); +U+5A2F(0);U+5A1B(8,9);U+5A1B(8,9),U+5A31(4) +U+5A31(0);U+5A1B(4,8,9);U+5A1B(4,8,9),U+5A2F(4) +U+5A32(0);U+5AA7(1,3,8,9);U+5AA7(1,3,8,9) +U+5A33(0);U+5A33(0,9); +U+5A34(0);U+5AFB(1,3,8,9);U+5AFA(4,9),U+5AFB(1,3,8,9) +U+5A35(0);U+5A35(0,9); +U+5A36(0);U+5A36(5,9); +U+5A37(0);U+5A37(0,9); +U+5A38(0);U+5A38(0,9); +U+5A39(0);U+5A39(3,9); +U+5A3A(0);U+5A3A(0); +U+5A3B(0);U+5A3B(0); +U+5A3C(0);U+5A3C(5,9); +U+5A3D(0);U+5A3D(0); +U+5A3E(0);U+5A3E(0,9); +U+5A3F(0);U+5A40(2,4,8,9);U+5A40(2,4,8,9) +U+5A40(0);U+5A40(5,9);U+5A3F(2,4,8) +U+5A41(0);U+5A41(0,9);U+5A04(1,3,8) +U+5A42(0);U+5A42(0,9); +U+5A43(0);U+5A43(0,9); +U+5A44(0);U+5A44(0,9); +U+5A45(0);U+5A45(0); +U+5A46(0);U+5A46(5,9); +U+5A47(0);U+5A47(0,9); +U+5A48(0);U+5A48(0,9); +U+5A49(0);U+5A49(5,9);U+5007(4,9) +U+5A4A(0);U+5A4A(5,9); +U+5A4B(0);U+5A4B(0); +U+5A4C(0);U+5A4C(0,9); +U+5A4D(0);U+5A4D(0,9); +U+5A4E(0);U+5A4E(0); +U+5A4F(0);U+5A4F(0); +U+5A50(0);U+5A50(3,9); +U+5A51(0);U+5A51(0,9); +U+5A52(0);U+5A52(0,9); +U+5A53(0);U+5A53(3,9); +U+5A55(0);U+5A55(5,9); +U+5A56(0);U+5A56(0,9); +U+5A57(0);U+5A57(3,9); +U+5A58(0);U+5A58(3,9); +U+5A5A(0);U+5A5A(5,9); +U+5A5B(0);U+5A5B(0,9); +U+5A5C(0);U+5A5C(0,9); +U+5A5D(0);U+5A5D(0,9); +U+5A5E(0);U+5A5E(3,9); +U+5A5F(0);U+5A5F(0,9); + +U+5A60(0);U+5A60(0,9); +U+5A61(0);U+5A61(0); +U+5A62(0);U+5A62(5,9); +U+5A63(0);U+59FB(2,8,9);U+59FB(2,8,9) +U+5A64(0);U+5A64(0,9); +U+5A65(0);U+5A65(0,9); +U+5A66(0);U+5A66(0,9);U+5987(1,3,8) +U+5A67(0);U+5A67(5,9); +U+5A68(0);U+5A68(0); +U+5A69(0);U+5A69(0,9); +U+5A6A(0);U+5A6A(5,9); +U+5A6B(0);U+5A6B(0); +U+5A6C(0);U+5A6C(0,9);U+6DEB(2,3,8,9) +U+5A6D(0);U+5A6D(0,9);U+5A05(1,3,8) +U+5A6E(0);U+5A6E(0); +U+5A70(0);U+5A70(0,9); +U+5A72(0);U+5A72(0); +U+5A73(0);U+5AFF(1,3,8,9);U+5AFF(1,3,8,9) +U+5A74(0);U+5B30(1,3,8,9);U+5B30(1,3,8,9) +U+5A75(0);U+5B0B(1,3,8,9);U+5B0B(1,3,8,9) +U+5A76(0);U+5B38(1,3,8,9);U+5B38(1,3,8,9) +U+5A77(0);U+5A77(5,9); +U+5A78(0);U+5A78(0,9); +U+5A79(0);U+5A79(0); +U+5A7A(0);U+5A7A(5,9); +U+5A7B(0);U+5A7B(0,9); +U+5A7C(0);U+5A7C(0,9); +U+5A7D(0);U+5A7D(0,9); +U+5A7E(0);U+5AAE(4,8,9);U+5077(4,9),U+5AAE(4,8,9),U+5078(4,8) +U+5A7F(0);U+5A7F(5,9);U+805F(7,8) +U+5A80(0);U+5A80(0); +U+5A81(0);U+5A81(0); +U+5A82(0);U+5A82(0); +U+5A83(0);U+5A83(0,9); +U+5A84(0);U+5A84(0,9); +U+5A85(0);U+5A85(4); +U+5A86(0);U+5A86(3); +U+5A88(0);U+5A88(0); +U+5A89(0);U+5A89(0); +U+5A8A(0);U+5A8A(0,9); +U+5A8B(0);U+5A8B(0,9); +U+5A8C(0);U+5A8C(3,9);U+5AF9(3,9) +U+5A8E(0);U+5A8E(0,9);U+59D0(3,9) +U+5A8F(0);U+5A8F(0,9); +U+5A90(0);U+5A90(0,9); +U+5A91(0);U+5A91(0); +U+5A92(0);U+5A92(5,9); +U+5A93(0);U+5A93(0,9); +U+5A94(0);U+5A94(0,9); +U+5A95(0);U+5A95(4,9); +U+5A96(0);U+5A96(0); +U+5A97(0);U+5A97(0,9); +U+5A98(0);U+5A98(0); +U+5A99(0);U+5A99(0); +U+5A9A(0);U+5A9A(5,9); +U+5A9B(0);U+5A9B(5,9); +U+5A9C(0);U+5A9C(0,9); +U+5A9D(0);U+5A9D(0,9); +U+5A9E(0);U+5A9E(3,9); +U+5A9F(0);U+5A9F(0,9); +U+5AA0(0);U+5AA0(3);U+5AF7(3,9) +U+5AA1(0);U+5AA1(0); +U+5AA2(0);U+5AA2(3,9); + +U+5AA3(0);U+5AA3(0); +U+5AA4(0);U+5AA4(0); +U+5AA5(0);U+5AA5(0,9); +U+5AA6(0);U+5AA6(0,9); +U+5AA7(0);U+5AA7(0,9);U+5A32(1,3,8) +U+5AA8(0);U+5AA8(0); +U+5AA9(0);U+5AA9(0,9); +U+5AAA(0);U+5ABC(4,8,9);U+5ABC(4,8,9) +U+5AAC(0);U+5AAC(0,9);U+4FDD(4,9) +U+5AAD(0);U+5B03(4,8,9);U+5B03(4,8,9) +U+5AAE(0);U+5AAE(0,9);U+5077(2,3,9),U+5A7E(4,8),U+5078(2,3,4,8) +U+5AAF(0);U+5AAF(0,9);U+59AB(3,8),U+5B00(4,8) +U+5AB0(0);U+5AB0(3,9); +U+5AB1(0);U+5AB1(0,9); +U+5AB2(0);U+5AB2(5,9); +U+5AB3(0);U+5AB3(5,9); +U+5AB4(0);U+5AB4(0,9); +U+5AB5(0);U+5AB5(5,9); +U+5AB6(0);U+5AB6(0,9); +U+5AB7(0);U+5AB7(0,9); +U+5AB8(0);U+5AB8(5,9); +U+5AB9(0);U+5AB9(0,9); +U+5ABA(0);U+5ABA(0,9);U+7F8E(3,9) +U+5ABB(0);U+5ABB(0,9); +U+5ABC(0);U+5ABC(0,9);U+5AAA(4,8) +U+5ABD(0);U+5ABD(0,9);U+5988(1,3,8) +U+5ABE(0);U+5ABE(5,9); +U+5ABF(0);U+5ABF(4,9);U+6127(2,3,8,9) +U+5AC0(0);U+5AC0(0,9); +U+5AC1(0);U+5AC1(5,9); +U+5AC2(0);U+5AC2(5,9); +U+5AC3(0);U+5AC3(0); +U+5AC4(0);U+5AC4(0,9); +U+5AC5(0);U+5AC5(0); +U+5AC6(0);U+5AC6(0,9); +U+5AC7(0);U+5AC7(0,9); +U+5AC8(0);U+5AC8(0,9); +U+5AC9(0);U+5AC9(5,9); +U+5ACA(0);U+5ACA(0,9); +U+5ACB(0);U+5ACB(3,9);U+5B1D(3,8,9),U+8885(7),U+88CA(2,9),U+892D(3,7,9) +U+5ACC(0);U+5ACC(5,9); +U+5ACD(0);U+5ACD(0,9); +U+5ACE(0);U+5ACE(0); +U+5ACF(0);U+5ACF(0); +U+5AD1(0);U+5AD1(0); +U+5AD2(0);U+5B21(1,3,8,9);U+5B21(1,3,8,9) +U+5AD4(0);U+5B2A(1,3,8,9);U+5B2A(1,3,8,9) +U+5AD5(0);U+5AD5(0,9); +U+5AD6(0);U+5AD6(5,9); +U+5AD7(0);U+5AD7(0,9);U+59AA(1,3,8) +U+5AD8(0);U+5AD8(5,9); +U+5AD9(0);U+5AD9(0,9); +U+5ADA(0);U+5ADA(0,9); +U+5ADB(0);U+5ADB(0,9); +U+5ADC(0);U+5ADC(5,9); +U+5ADD(0);U+5ADD(0,9); +U+5ADE(0);U+5ADE(0,9);U+6175(4,9) +U+5ADF(0);U+5ADF(3,9); +U+5AE0(0);U+5AE0(5,9); +U+5AE1(0);U+5AE1(5,9); +U+5AE2(0);U+5AE2(0,9); +U+5AE3(0);U+5AE3(5,9); +U+5AE4(0);U+5AE4(0); + +U+5AE5(0);U+5AE5(0,9); +U+5AE6(0);U+5AE6(5,9); +U+5AE7(0);U+5AE7(0); +U+5AE8(0);U+5AE8(0,9); +U+5AE9(0);U+5AE9(5,9); +U+5AEA(0);U+5AEA(0,9); +U+5AEB(0);U+5AEB(5,9); +U+5AEC(0);U+5AEC(0,9); +U+5AED(0);U+5AED(3,9); +U+5AEE(0);U+5AEE(4,9); +U+5AF1(0);U+5B19(1,3,4,8,9);U+5B19(1,3,4,8,9) +U+5AF2(0);U+5AF2(0); +U+5AF3(0);U+5AF3(0,9); +U+5AF4(0);U+5AF4(0,9); +U+5AF5(0);U+5AF5(0,9);U+59A9(1,3,8) +U+5AF6(0);U+5AF6(0,9); +U+5AF7(0);U+5AF7(0,9);U+5AA0(3) +U+5AF8(0);U+5AF8(0,9); +U+5AF9(0);U+5AF9(0,9);U+5A8C(3,9) +U+5AFA(0);U+5AFA(0,9);U+5A34(4),U+5AFB(2,3,8,9) +U+5AFB(0);U+5AFB(0,9);U+5A34(1,3,8),U+5AFA(2,3,8,9) +U+5AFC(0);U+5AFC(0); +U+5AFD(0);U+5AFD(0,9); +U+5AFE(0);U+5AFE(0); +U+5AFF(0);U+5AFF(0,9);U+5A73(1,3,8) +U+5B00(0);U+5AAF(4,8,9);U+59AB(1,8),U+5AAF(4,8,9) +U+5B01(0);U+5B01(0,9); +U+5B02(0);U+5B02(0,9); +U+5B03(0);U+5B03(0,9);U+5AAD(4,8) +U+5B04(0);U+5B04(0); +U+5B05(0);U+5B05(0,9); +U+5B06(0);U+5B06(0); +U+5B07(0);U+5B07(0,9); +U+5B08(0);U+5B08(0,9);U+5A06(1,3,8) +U+5B09(0);U+5B09(5,9); +U+5B0B(0);U+5B0B(0,9);U+5A75(1,3,8) +U+5B0C(0);U+5B0C(0,9);U+5A07(1,3,8) +U+5B0E(0);U+5B0E(4); +U+5B0F(0);U+5B0F(0,9); +U+5B10(0);U+5B10(0,9); +U+5B11(0);U+5B11(0); +U+5B12(0);U+5B12(0); +U+5B13(0);U+5B13(0,9); +U+5B14(0);U+5B14(4,9); +U+5B15(0);U+5B15(0); +U+5B16(0);U+5B16(5,9); +U+5B17(0);U+5B17(5,9); +U+5B18(0);U+5B18(0); +U+5B19(0);U+5B19(0,9);U+5AF1(1,3,8) +U+5B1A(0);U+5B1A(0,9); +U+5B1B(0);U+5B1B(0,9); +U+5B1C(0);U+5B1C(0); +U+5B1D(0);U+5B1D(0,9);U+5ACB(3,8,9),U+8885(4,8),U+88CA(2,8,9),U+892D(3,7,8,9) +U+5B1E(0);U+5B1E(0,9); +U+5B1F(0);U+5B1F(0); +U+5B20(0);U+5B20(0,9); +U+5B21(0);U+5B21(0,9);U+5AD2(1,3,8) +U+5B22(0);U+5B43(4,9);U+5A18(7,8,9),U+5B43(4,9) +U+5B23(0);U+5B23(0,9); +U+5B24(0);U+5B24(0,9);U+5B37(4,8) +U+5B25(0);U+5B25(0,9); +U+5B26(0);U+5B26(0,9); +U+5B27(0);U+5B27(0,9); + +U+5B28(0);U+5B28(0,9); +U+5B29(0);U+5B29(0); +U+5B2A(0);U+5B2A(0,9);U+5AD4(1,3,8) +U+5B2B(0);U+5B2B(0); +U+5B2C(0);U+5B2C(0,9); +U+5B2D(0);U+5B2D(0,9);U+5976(2,3,8,9),U+59B3(3,9),U+4F32(2,3,8),U+4F60(2,3,5,8,9),U+511E(2,3,8) +U+5B2E(0);U+5B2E(0,9); +U+5B2F(0);U+5B2F(3,9); +U+5B30(0);U+5B30(0,9);U+5A74(1,3,8) +U+5B31(0);U+5B31(0); +U+5B32(0);U+5B32(5,9); +U+5B33(0);U+5B33(0); +U+5B34(0);U+5B34(5,9); +U+5B35(0);U+5B35(3); +U+5B36(0);U+5B36(0); +U+5B37(0);U+5B24(4,8,9);U+5B24(4,8,9) +U+5B38(0);U+5B38(0,9);U+5A76(1,3,8) +U+5B3A(0);U+5B3A(0); +U+5B3B(0);U+5B3B(0); +U+5B3C(0);U+5B3C(0,9); +U+5B3D(0);U+5B3D(0,9); +U+5B3E(0);U+5B3E(4,9);U+61D2(4),U+61F6(2,3,8,9) +U+5B3F(0);U+5B3F(3,9); +U+5B40(0);U+5B40(5,9); +U+5B41(0);U+5B41(0); +U+5B42(0);U+5B42(0); +U+5B43(0);U+5B43(4,9);U+5A18(2,8,9),U+5B22(4) +U+5B44(0);U+5B44(0); +U+5B45(0);U+5B45(0,9);U+7EA4(3),U+7E34(1,3,8,9),U+7E8E(3),U+7E96(1,3,8,9) +U+5B47(0);U+5B47(0,9); +U+5B48(0);U+5B48(0,9); +U+5B49(0);U+5B49(0); +U+5B4A(0);U+5B4A(0); +U+5B4B(0);U+5B4B(0,9); +U+5B4C(0);U+5B4C(0,9);U+5A08(1,3,8) +U+5B4D(0);U+5B4D(0,9); +U+5B4E(0);U+5B4E(0,9); +U+5B50(0);U+5B50(5,9); +U+5B51(0);U+5B51(5,9); +U+5B53(0);U+5B53(5,9); +U+5B54(0);U+5B54(5,9); +U+5B55(0);U+5B55(5,9); +U+5B56(0);U+5B56(0,9); +U+5B57(0);U+5B57(5,9); +U+5B58(0);U+5B58(5,9); +U+5B59(0);U+5B6B(1,3,8,9);U+5B6B(1,3,8,9) +U+5B5A(0);U+5B5A(5,9);U+5B75(3,8,9) +U+5B5B(0);U+5B5B(5,9); +U+5B5C(0);U+5B5C(5,9); +U+5B5D(0);U+5B5D(5,9); +U+5B5E(0);U+5B5E(0); +U+5B5F(0);U+5B5F(5,9); +U+5B62(0);U+5B62(5,9); +U+5B63(0);U+5B63(5,9); +U+5B64(0);U+5B64(5,9); +U+5B65(0);U+5B65(5,9); +U+5B66(0);U+5B78(1,3,8,9);U+5B78(1,3,8,9),U+6588(3) +U+5B67(0);U+5B67(0); +U+5B68(0);U+5B68(0); +U+5B69(0);U+5B69(5,9); +U+5B6A(0);U+5B7F(1,3,8,9);U+5B7F(1,3,8,9) +U+5B6B(0);U+5B6B(0,9);U+5B59(1,3,8) + +U+5B6C(0);U+5B6C(5,9); +U+5B6D(0);U+5B6D(0); +U+5B6E(0);U+5B6E(0,9); +U+5B70(0);U+5B70(5,9); +U+5B71(0);U+5B71(5,9); +U+5B72(0);U+5B72(0,9); +U+5B73(0);U+5B73(5,9);U+5B76(4,8) +U+5B74(0);U+5B74(3); +U+5B75(0);U+5B75(5,9);U+5B5A(3,8,9) +U+5B76(0);U+5B73(4,8,9);U+5B73(4,8,9) +U+5B77(0);U+5B77(0,9); +U+5B78(0);U+5B78(0,9);U+5B66(1,3,8),U+6588(3,8) +U+5B7A(0);U+5B7A(5,9); +U+5B7B(0);U+5B7B(0,9); +U+5B7C(0);U+5B7D(2,3,8,9);U+5B7D(2,3,8,9) +U+5B7D(0);U+5B7D(5,9);U+5B7C(2,3,8) +U+5B7F(0);U+5B7F(0,9);U+5B6A(1,3,8) +U+5B80(0);U+5B80(5); +U+5B81(0);U+5B81(1,3,9),U+5BE7(1,3,8,9);U+5BCD(3,9),U+5BD5(4),U+5BDC(4),U+5BE7(1,3,8,9) +U+5B82(0);U+5197(2,8,9);U+5197(2,8,9) +U+5B83(0);U+5B83(5,9),U+7260(2,3,8,9);U+7260(2,3,8,9) +U+5B84(0);U+5B84(5,9); +U+5B85(0);U+5B85(5,9); +U+5B87(0);U+5B87(5,9);U+7A7B(3,9) +U+5B88(0);U+5B88(5,9); +U+5B89(0);U+5B89(5,9);U+4F92(3,9) +U+5B8A(0);U+5B8A(0); +U+5B8B(0);U+5B8B(5,9); +U+5B8C(0);U+5B8C(5,9); +U+5B8D(0);U+8089(4,8,9);U+8089(4,8,9) +U+5B8E(0);U+5B8E(0,9); +U+5B8F(0);U+5B8F(5,9);U+5430(3,9) +U+5B91(0);U+5B91(0); +U+5B92(0);U+5B92(0,9); +U+5B93(0);U+5B93(5,9); +U+5B94(0);U+5B94(3); +U+5B95(0);U+5B95(5,9); +U+5B96(0);U+5B96(0); +U+5B97(0);U+5B97(5,9); +U+5B98(0);U+5B98(5,9); +U+5B99(0);U+5B99(5,9); +U+5B9A(0);U+5B9A(5,9); +U+5B9B(0);U+5B9B(5,9); +U+5B9C(0);U+5B9C(5,9);U+519D(3,8) +U+5B9D(0);U+5BF6(1,3,8,9);U+5BF3(3),U+5BF6(1,3,8,9) +U+5B9E(0);U+5BE6(1,3,8,9);U+5B9F(4),U+5BE6(1,3,8,9) +U+5B9F(0);U+5BE6(4,8,9);U+5B9E(4),U+5BE6(4,8,9) +U+5BA0(0);U+5BF5(1,3,8,9);U+5BF5(1,3,8,9) +U+5BA1(0);U+5BE9(1,3,8,9);U+5BE9(1,3,8,9) +U+5BA2(0);U+5BA2(5,9); +U+5BA3(0);U+5BA3(5,9); +U+5BA4(0);U+5BA4(5,9); +U+5BA5(0);U+5BA5(5,9); +U+5BA6(0);U+5BA6(5,9); +U+5BA7(0);U+5BA7(0,9); +U+5BA8(0);U+5BA8(0,9); +U+5BAA(0);U+61B2(1,3,8,9);U+61B2(1,3,8,9) +U+5BAB(0);U+5BAE(4,8,9);U+5BAE(4,8,9) +U+5BAC(0);U+5BAC(3,9); +U+5BAD(0);U+5BAD(0,9); +U+5BAE(0);U+5BAE(0,9);U+5BAB(4,8) +U+5BAF(0);U+5BAF(3); + +U+5BB0(0);U+5BB0(5,9); +U+5BB1(0);U+5BB1(0); +U+5BB3(0);U+5BB3(5,9); +U+5BB4(0);U+5BB4(5,9);U+91BC(2,3,9) +U+5BB5(0);U+5BB5(5,9); +U+5BB6(0);U+5BB6(1,3,9),U+50A2(1,3,4,8,9);U+50A2(1,3,4,8,9) +U+5BB8(0);U+5BB8(5,9); +U+5BB9(0);U+5BB9(5,9); +U+5BBA(0);U+5BBA(0); +U+5BBB(0);U+5BC6(3,8,9);U+5BC6(3,8,9) +U+5BBD(0);U+5BEC(1,3,8,9);U+5BDB(3),U+5BEC(1,3,8,9) +U+5BBE(0);U+8CD3(1,3,8,9);U+8CD3(1,3,8,9),U+8CD4(3) +U+5BBF(0);U+5BBF(5,9); +U+5BC0(0);U+5BC0(0,9); +U+5BC1(0);U+5BC1(0,9); +U+5BC2(0);U+5BC2(5,9); +U+5BC3(0);U+51A4(2,3,8,9);U+51A4(2,3,8,9) +U+5BC4(0);U+5BC4(5,9); +U+5BC5(0);U+5BC5(5,9); +U+5BC6(0);U+5BC6(5,9);U+5BBB(3,8) +U+5BC7(0);U+5BC7(5,9);U+51A6(3,8) +U+5BCA(0);U+5BCA(0,9); +U+5BCB(0);U+5BCB(0,9); +U+5BCC(0);U+5BCC(5,9);U+51A8(3,8) +U+5BCD(0);U+5BCD(0,9);U+5B81(3,9),U+5BD5(3,4),U+5BDC(3,4),U+5BE7(1,3,8,9) +U+5BCE(0);U+5BCE(3,9); +U+5BCF(0);U+5BCF(0); +U+5BD0(0);U+5BD0(5,9); +U+5BD1(0);U+5BD1(0,9);U+5BDD(4),U+5BE2(1,3,4,8,9) +U+5BD2(0);U+5BD2(5,9); +U+5BD3(0);U+5BD3(5,9);U+5EBD(2,3,8) +U+5BD4(0);U+5BD4(0,9); +U+5BD5(0);U+5BE7(2,3,8,9);U+5B81(4,9),U+5BE7(2,3,8,9),U+5BCD(3,4,9),U+5BDC(4) +U+5BD6(0);U+5BD6(0,9); +U+5BD8(0);U+5BD8(0,9);U+7F6E(2,8,9) +U+5BD9(0);U+5BD9(0,9); +U+5BDB(0);U+5BEC(3,8,9);U+5BBD(3),U+5BEC(3,8,9) +U+5BDC(0);U+5BE7(4,8,9);U+5B81(4,9),U+5BE7(4,8,9),U+5BCD(3,4,9),U+5BD5(4) +U+5BDD(0);U+5BE2(1,3,4,8,9);U+5BD1(4,9),U+5BE2(1,3,4,8,9) +U+5BDE(0);U+5BDE(5,9);U+55FC(4,9) +U+5BDF(0);U+5BDF(5,9);U+8A67(2,8) +U+5BE0(0);U+5BE0(0,9);U+7AAD(4),U+7AB6(1,3,4,8,9) +U+5BE1(0);U+5BE1(5,9); +U+5BE2(0);U+5BE2(0,9);U+5BDD(1,3,8),U+5BD1(0,1,3,4,8,9) +U+5BE3(0);U+5BE3(0,9); +U+5BE4(0);U+5BE4(5,9); +U+5BE5(0);U+5BE5(5,9); +U+5BE6(0);U+5BE6(0,9);U+5B9E(1,3,8),U+5B9F(4,8) +U+5BE7(0);U+5BE7(0,9);U+5B81(1,3,8,9),U+5BD5(2,3,8),U+5BDC(4,8),U+5BCD(1,3,8,9) +U+5BE8(0);U+5BE8(5,9); +U+5BE9(0);U+5BE9(0,9);U+5BA1(1,3,8) +U+5BEA(0);U+5BEA(0,9); +U+5BEB(0);U+5BEB(0,9);U+5199(1,3,8) +U+5BEC(0);U+5BEC(0,9);U+5BBD(1,3,8),U+5BDB(3,8) +U+5BED(0);U+5BED(0); +U+5BEE(0);U+5BEE(5,9); +U+5BEF(0);U+5BEF(0,9); +U+5BF0(0);U+5BF0(5,9); +U+5BF1(0);U+5BF1(0,9);U+5453(3),U+56C8(1,3,8,9) +U+5BF2(0);U+5BF2(0,9); +U+5BF3(0);U+5BF6(2,3,8,9);U+5B9D(3),U+5BF6(2,3,8,9) +U+5BF4(0);U+5BF4(0); +U+5BF5(0);U+5BF5(0,9);U+5BA0(1,3,8) + +U+5BF6(0);U+5BF6(0,9);U+5B9D(1,3,8),U+5BF3(2,3,8) +U+5BF7(0);U+5BF7(0); +U+5BF8(0);U+5BF8(5,9); +U+5BF9(0);U+5C0D(1,3,8,9);U+5C0D(1,3,8,9) +U+5BFA(0);U+5BFA(5,9); +U+5BFB(0);U+5C0B(1,3,8,9);U+5C0B(1,3,8,9) +U+5BFC(0);U+5C0E(1,3,8,9);U+5C0E(1,3,8,9) +U+5BFD(0);U+5BFD(0); +U+5BFF(0);U+58FD(1,3,8,9);U+58FD(1,3,8,9),U+5900(4) +U+5C01(0);U+5C01(5,9); +U+5C03(0);U+5C03(0,9);U+6577(3,9) +U+5C04(0);U+5C04(5,9); +U+5C05(0);U+524B(2,3,8,9);U+514B(4,9),U+524B(2,3,8,9) +U+5C06(0);U+5C07(1,3,4,8,9);U+5C07(1,3,4,8,9) +U+5C07(0);U+5C07(0,9);U+5C06(1,3,8) +U+5C08(0);U+5C08(0,9);U+4E13(1,3,8) +U+5C09(0);U+5C09(5,9); +U+5C0A(0);U+5C0A(5,9); +U+5C0B(0);U+5C0B(0,9);U+5BFB(1,3,8) +U+5C0C(0);U+5C0C(0,9);U+6811(3),U+6A39(1,3,8,9) +U+5C0D(0);U+5C0D(0,9);U+5BF9(1,3,8) +U+5C0E(0);U+5C0E(0,9);U+5BFC(1,3,8) +U+5C0F(0);U+5C0F(5,9); +U+5C10(0);U+5C10(0,9); +U+5C11(0);U+5C11(5,9); +U+5C12(0);U+5C12(0,9);U+5C13(8),U+5C14(4),U+723E(2,3,8,9) +U+5C13(0);U+5C12(8,9);U+5C12(8,9),U+5C14(4),U+723E(3,8,9) +U+5C14(0);U+723E(1,3,8,9);U+5C12(4,9),U+5C13(4),U+723E(1,3,8,9) +U+5C15(0);U+5C15(5,9); +U+5C16(0);U+5C16(5,9);U+946F(4,9) +U+5C17(0);U+5C17(0); +U+5C18(0);U+5875(1,3,8,9);U+5875(1,3,8,9) +U+5C19(0);U+5C1A(4,8,9);U+5C1A(4,8,9) +U+5C1A(0);U+5C1A(5,9);U+5C19(4,8) +U+5C1C(0);U+5C1C(5); +U+5C1D(0);U+5617(1,3,8,9),U+5690(4,9);U+5617(1,3,8,9),U+5690(4,9),U+751E(4) +U+5C1E(0);U+5C1E(0); +U+5C1F(0);U+5C1F(0,9);U+9BAE(2,3,8,9),U+9C9C(3),U+5C20(2,3,8) +U+5C20(0);U+9BAE(2,8,9);U+9BAE(2,8,9),U+9C9C(2),U+5C1F(0,2,3,8,9) +U+5C21(0);U+5C21(0); +U+5C22(0);U+5C22(5,9); +U+5C24(0);U+5C24(5,9);U+8A27(3,9) +U+5C25(0);U+5C25(5,9); +U+5C27(0);U+582F(1,3,8,9);U+579A(3,9),U+582F(1,3,8,9),U+5C2D(4) +U+5C28(0);U+5C28(3,9); +U+5C2A(0);U+5C2A(4,9);U+5C2B(4,8) +U+5C2B(0);U+5C2A(4,8,9);U+5C2A(4,8,9) +U+5C2C(0);U+5C2C(5,9); +U+5C2D(0);U+582F(4,8,9);U+582F(4,8,9),U+5C27(4),U+579A(0,3,4,9) +U+5C2E(0);U+5C2E(0); +U+5C2F(0);U+5C2F(0); +U+5C30(0);U+5C30(0,9); +U+5C31(0);U+5C31(5,9); +U+5C32(0);U+5C32(4); +U+5C33(0);U+5C33(0,9); +U+5C34(0);U+5C37(1,3,8,9);U+5C37(1,3,8,9) +U+5C35(0);U+5C35(0); +U+5C37(0);U+5C37(0,9);U+5C34(1,3,8) +U+5C38(0);U+5C38(5,9),U+5C4D(2,3,9);U+5C4D(2,3,9) +U+5C39(0);U+5C39(5,9); +U+5C3A(0);U+5C3A(5,9); +U+5C3B(0);U+5C3B(5,9); +U+5C3C(0);U+5C3C(5,9); + +U+5C3D(0);U+5118(1,3,8,9),U+76E1(1,3,8,9);U+5118(1,3,8,9),U+76E1(1,3,8,9) +U+5C3E(0);U+5C3E(5,9); +U+5C3F(0);U+5C3F(5,9);U+6EBA(3,8,9) +U+5C40(0);U+5C40(5,9),U+4FB7(2,9),U+8DFC(2,9);U+4FB7(2,9),U+8DFC(2,9) +U+5C41(0);U+5C41(5,9); +U+5C42(0);U+5C64(1,3,8,9);U+5C64(1,3,8,9) +U+5C43(0);U+5C6D(4,9);U+5C53(4,8),U+5C6D(4,9) +U+5C44(0);U+5C44(3,9); +U+5C45(0);U+5C45(5,9); +U+5C46(0);U+5C46(0,9);U+5C4A(2,3,8),U+8250(2,3,8,9) +U+5C47(0);U+5C47(0,9); +U+5C48(0);U+5C48(5,9); +U+5C49(0);U+5C49(5); +U+5C4A(0);U+5C46(2,3,8,9);U+5C46(2,3,8,9),U+8250(3,9) +U+5C4B(0);U+5C4B(5,9); +U+5C4C(0);U+5C4C(0,9); +U+5C4D(0);U+5C4D(3,9);U+5C38(2,3,9) +U+5C4E(0);U+5C4E(5,9); +U+5C4F(0);U+5C4F(5,9);U+5C5B(3),U+5EB0(4,9) +U+5C50(0);U+5C50(5,9); +U+5C51(0);U+5C51(5,9); +U+5C52(0);U+5C52(0); +U+5C53(0);U+5C6D(4,8,9);U+5C43(4,8),U+5C6D(4,8,9) +U+5C54(0);U+5C54(0,9); +U+5C55(0);U+5C55(5,9); +U+5C56(0);U+5C56(3,9); +U+5C57(0);U+5C57(0); +U+5C58(0);U+5C58(0,9); +U+5C59(0);U+5C59(5,9); +U+5C5B(0);U+5C4F(3,9);U+5C4F(3,9),U+5EB0(3,4,9) +U+5C5C(0);U+5C5C(4,9); +U+5C5D(0);U+5C5D(3,9); +U+5C5E(0);U+5C6C(1,3,8,9);U+5C6C(1,3,8,9) +U+5C5F(0);U+5C5F(4); +U+5C60(0);U+5C60(5,9); +U+5C61(0);U+5C62(1,3,8,9);U+5C62(1,3,8,9) +U+5C62(0);U+5C62(0,9);U+5C61(1,3,8) +U+5C63(0);U+5C63(5,9); +U+5C64(0);U+5C64(0,9);U+5C42(1,3,8) +U+5C65(0);U+5C65(5,9); +U+5C66(0);U+5C68(1,3,8,9);U+5C68(1,3,8,9) +U+5C67(0);U+5C67(3,9); +U+5C68(0);U+5C68(0,9);U+5C66(1,3,8) +U+5C69(0);U+5C69(3,9); +U+5C6A(0);U+5C6A(3,9); +U+5C6B(0);U+5C6B(0); +U+5C6C(0);U+5C6C(0,9);U+5C5E(1,3,8) +U+5C6D(0);U+5C6D(0,9);U+5C43(4),U+5C53(4,8) +U+5C6E(0);U+5C6E(5,9); +U+5C6F(0);U+5C6F(5,9); +U+5C70(0);U+5C70(0); +U+5C71(0);U+5C71(5,9); +U+5C72(0);U+5C72(0); +U+5C73(0);U+5C73(0,9); +U+5C74(0);U+5C74(0,9); +U+5C75(0);U+5C75(0); +U+5C76(0);U+5C76(0); +U+5C77(0);U+5C77(0); +U+5C78(0);U+5C78(0); +U+5C79(0);U+5C79(5,9);U+9623(3,9) +U+5C7A(0);U+5C7A(5,9); +U+5C7B(0);U+5C7B(0,9); +U+5C7C(0);U+5C7C(0,9); + +U+5C7D(0);U+5C7D(0); +U+5C7E(0);U+5C7E(0,9); +U+5C7F(0);U+5DBC(1,3,8,9);U+5DBC(1,3,8,9) +U+5C80(0);U+51FA(3,8,9);U+51FA(3,8,9),U+9F63(3,9) +U+5C81(0);U+6B72(1,3,8,9);U+4E97(3),U+6B72(1,3,8,9),U+6B73(4) +U+5C82(0);U+8C48(1,3,8,9);U+8C48(1,3,8,9) +U+5C83(0);U+5C83(0); +U+5C84(0);U+5C84(0); +U+5C86(0);U+5C86(0,9); +U+5C87(0);U+5C87(0); +U+5C88(0);U+5C88(5,9); +U+5C89(0);U+5C89(0,9); +U+5C8A(0);U+5C8A(3,9); +U+5C8B(0);U+5C8B(0,9); +U+5C8C(0);U+5C8C(5,9); +U+5C8D(0);U+5C8D(5,9); +U+5C8E(0);U+5C8E(0); +U+5C8F(0);U+5C8F(0,9); +U+5C90(0);U+5C90(5,9);U+6B67(3,8,9) +U+5C91(0);U+5C91(5,9); +U+5C92(0);U+5C92(0,9); +U+5C93(0);U+5C93(0,9); +U+5C94(0);U+5C94(5,9); +U+5C95(0);U+5C95(0,9); +U+5C96(0);U+5D87(1,3,8,9);U+5D87(1,3,8,9) +U+5C97(0);U+5D17(1,3,8,9);U+5D17(1,3,8,9),U+5CA1(1,3,4,8,9),U+5188(1,3,4,8) +U+5C98(0);U+5CF4(1,3,8,9);U+5CF4(1,3,8,9) +U+5C99(0);U+5C99(5); +U+5C9A(0);U+5D50(1,3,8,9);U+5D50(1,3,8,9) +U+5C9B(0);U+5CF6(1,3,8,9);U+5D8B(3),U+5D8C(7),U+5CF6(1,3,8,9) +U+5C9C(0);U+5C9C(5); +U+5C9D(0);U+5C9D(3,9); +U+5C9E(0);U+5C9E(0); +U+5C9F(0);U+5C9F(0,9); +U+5CA0(0);U+5CA0(0,9); +U+5CA1(0);U+5CA1(0,9);U+5188(1,3,8),U+5D17(4,8,9),U+5C97(1,3,4,8) +U+5CA2(0);U+5CA2(5,9); +U+5CA3(0);U+5CA3(5,9); +U+5CA4(0);U+5CA4(0,9);U+7A74(4,9) +U+5CA5(0);U+5CA5(0,9);U+5761(3,9) +U+5CA6(0);U+5CA6(0,9); +U+5CA7(0);U+5CA7(3,9); +U+5CA8(0);U+5CA8(3,9); +U+5CA9(0);U+5CA9(4,9),U+5DD6(2,3,8,9);U+5D52(2,9),U+55A6(4,9),U+58E7(3,9),U+5DCC(4),U+5DD6(2,3,8,9),U+789E(3,9),U+7939(3,9) +U+5CAA(0);U+5CAA(0,9); +U+5CAB(0);U+5CAB(5,9); +U+5CAC(0);U+5CAC(5,9); +U+5CAD(0);U+5CAD(1,3,9),U+5DBA(1,3,8,9);U+5CBA(3,8),U+5DBA(1,3,8,9) +U+5CAE(0);U+5CAE(0,9); +U+5CAF(0);U+5CAF(3,9); +U+5CB0(0);U+5CB0(0,9); +U+5CB1(0);U+5CB1(5,9); +U+5CB2(0);U+5CB2(0); +U+5CB3(0);U+5CB3(5,9),U+5DBD(2,3,8,9);U+5DBD(2,3,8,9) +U+5CB5(0);U+5CB5(5,9); +U+5CB6(0);U+5CB6(0,9); +U+5CB7(0);U+5CB7(5,9);U+5D0F(3,9) +U+5CB8(0);U+5CB8(5,9); +U+5CBA(0);U+5CAD(3,8,9);U+5CAD(3,8,9),U+5DBA(7,9) +U+5CBB(0);U+5CBB(0); +U+5CBC(0);U+5CBC(0); +U+5CBD(0);U+5D2C(1,3,8);U+5D2C(1,3,8) + +U+5CBE(0);U+5CBE(0); +U+5CBF(0);U+5DCB(1,3,8,9);U+5DCB(1,3,8,9) +U+5CC1(0);U+5CC1(5); +U+5CC2(0);U+5CC2(0); +U+5CC3(0);U+5DA8(1,3,9);U+5DA8(1,3,9) +U+5CC4(0);U+5DA7(1,3,8,9);U+5DA7(1,3,8,9) +U+5CC5(0);U+5CC5(0); +U+5CC6(0);U+5CC6(0,9); +U+5CC7(0);U+5CC7(0,9); +U+5CC8(0);U+5CC8(0,9); +U+5CC9(0);U+5CC9(0,9); +U+5CCA(0);U+5CCA(0,9);U+961C(3,9),U+961D(3,8) +U+5CCB(0);U+5CCB(5,9); +U+5CCC(0);U+5CCC(0,9); +U+5CCD(0);U+5CCD(0); +U+5CCE(0);U+5CCE(0,9); +U+5CCF(0);U+5CCF(0,9); +U+5CD0(0);U+5CD0(0,9); +U+5CD1(0);U+5CD1(0); +U+5CD2(0);U+5CD2(5,9); +U+5CD3(0);U+5CD3(0,9); +U+5CD4(0);U+5CD4(0,9); +U+5CD6(0);U+5CD6(0,9); +U+5CD7(0);U+5CD7(3,9); +U+5CD8(0);U+5CD8(0,9); +U+5CD9(0);U+5CD9(5,9); +U+5CDA(0);U+5CDA(0,9); +U+5CDB(0);U+5CDB(0,9); +U+5CDC(0);U+5CDC(0); +U+5CDE(0);U+5CDE(0,9); +U+5CDF(0);U+5CDF(0,9); +U+5CE0(0);U+5CE0(0); +U+5CE1(0);U+5CFD(1,3,8,9);U+5CFD(1,3,8,9) +U+5CE2(0);U+5CE2(0); +U+5CE3(0);U+5DA2(1,3,8,9);U+5DA2(1,3,8,9) +U+5CE4(0);U+5DA0(1,3,8,9);U+5DA0(1,3,8,9) +U+5CE5(0);U+5D22(4,8,9);U+5D22(4,8,9) +U+5CE6(0);U+5DD2(1,3,8,9);U+5DD2(1,3,8,9) +U+5CE7(0);U+5CE7(0); +U+5CE8(0);U+5CE8(5,9);U+5CE9(2,3,8) +U+5CE9(0);U+5CE8(2,3,8,9);U+5CE8(2,3,8,9) +U+5CEA(0);U+5CEA(5,9); +U+5CEB(0);U+5CEB(0); +U+5CEC(0);U+5CEC(0,9); +U+5CED(0);U+5CED(5,9); +U+5CEE(0);U+5CEE(0,9); +U+5CEF(0);U+5CF0(2,3,8,9);U+5CF0(2,3,8,9) +U+5CF0(0);U+5CF0(5,9);U+5CEF(2,3,8) +U+5CF1(0);U+5CF1(3,9);U+5DA9(3,9) +U+5CF2(0);U+5CF2(0); +U+5CF3(0);U+5CF3(0); +U+5CF4(0);U+5CF4(0,9);U+5C98(1,3,8) +U+5CF6(0);U+5CF6(0,9);U+5D8B(3,8),U+5D8C(8),U+5C9B(1,3,8) +U+5CF7(0);U+5CF7(0,9); +U+5CF8(0);U+5CF8(0,9); +U+5CF9(0);U+5CF9(0,9); +U+5CFA(0);U+786C(3,8,9);U+786C(3,8,9) +U+5CFB(0);U+5CFB(5,9); +U+5CFC(0);U+5CFC(0); +U+5CFD(0);U+5CFD(0,9);U+5CE1(1,3,8) +U+5CFE(0);U+5CFE(0); +U+5CFF(0);U+5CFF(0,9); +U+5D00(0);U+5D00(0,9); + +U+5D01(0);U+5D01(0,9); +U+5D02(0);U+5D97(1,3,8,9);U+5D97(1,3,8,9) +U+5D03(0);U+5D0D(1,3,8,9);U+5D0D(1,3,8,9) +U+5D04(0);U+5DAE(4,8,9);U+5DAE(4,8,9) +U+5D05(0);U+5D05(0); +U+5D06(0);U+5D06(5,9); +U+5D07(0);U+5D07(5,9);U+5D08(3,8) +U+5D08(0);U+5D07(3,8,9);U+5D07(3,8,9) +U+5D09(0);U+5D09(0); +U+5D0A(0);U+5D0A(0); +U+5D0B(0);U+5D0B(0,9);U+534E(3),U+83EF(3,8,9) +U+5D0C(0);U+5D0C(0,9); +U+5D0D(0);U+5D0D(0,9);U+5D03(1,3,8) +U+5D0E(0);U+5D0E(5,9);U+57FC(7,8,9),U+7895(7,8,9) +U+5D0F(0);U+5D0F(0,9);U+5CB7(3,9) +U+5D10(0);U+5D11(3,8,9);U+5D11(3,8,9),U+6606(2,9),U+665C(2,3,9) +U+5D11(0);U+5D11(3,9);U+5D10(3,8),U+6606(2,9),U+665C(2,3,8,9) +U+5D12(0);U+5D12(3,9); +U+5D13(0);U+5D13(0); +U+5D14(0);U+5D14(5,9); +U+5D15(0);U+5D16(3,8,9);U+5D16(3,8,9) +U+5D16(0);U+5D16(5,9);U+5D15(3,8) +U+5D17(0);U+5D17(0,9);U+5C97(1,3,8),U+5CA1(4,8,9),U+5188(1,3,4,8) +U+5D18(0);U+5D19(3,8,9);U+4ED1(4),U+4F96(2,9),U+5D19(3,8,9) +U+5D19(0);U+5D19(3,9);U+4ED1(4),U+4F96(2,3,9),U+5D18(3,8) +U+5D1A(0);U+5D1A(3,9); +U+5D1B(0);U+5D1B(5,9); +U+5D1C(0);U+5D1C(0); +U+5D1D(0);U+5D1D(3,9); +U+5D1E(0);U+5D1E(5,9); +U+5D1F(0);U+5D1F(3,9); +U+5D20(0);U+5D20(0,9); +U+5D21(0);U+5D21(0); +U+5D22(0);U+5D22(0,9);U+5CE5(4,8) +U+5D23(0);U+5D23(0,9); +U+5D24(0);U+5D24(5,9); +U+5D25(0);U+5D25(0,9); +U+5D26(0);U+5D26(5,9); +U+5D27(0);U+5D27(5,9); +U+5D28(0);U+5D28(0,9); +U+5D29(0);U+5D29(5,9); +U+5D2A(0);U+5D2A(0); +U+5D2C(0);U+5D2C(0);U+5CBD(1,3,8) +U+5D2D(0);U+5D84(1,3,8,9);U+5D84(1,3,8,9) +U+5D2E(0);U+5D2E(5,9); +U+5D30(0);U+5D30(0,9); +U+5D31(0);U+5D31(0,9); +U+5D32(0);U+5D32(0,9); +U+5D33(0);U+5D33(0,9); +U+5D34(0);U+5D34(5,9); +U+5D35(0);U+5D35(0,9); +U+5D36(0);U+5D36(0,9); +U+5D37(0);U+5D37(0,9); +U+5D38(0);U+5D38(0,9); +U+5D39(0);U+5D39(0,9); +U+5D3A(0);U+5D3A(0,9); +U+5D3C(0);U+5D3C(0,9); +U+5D3D(0);U+5D3D(5,9); +U+5D3E(0);U+5D3E(5); +U+5D3F(0);U+5D3F(0,9); +U+5D40(0);U+5D40(0,9); +U+5D41(0);U+5D41(3,9); +U+5D42(0);U+5D42(3,9); + +U+5D43(0);U+5D43(0,9); +U+5D44(0);U+5D44(0); +U+5D45(0);U+5D45(0,9); +U+5D46(0);U+5D47(3,8,9);U+5D47(3,8,9) +U+5D47(0);U+5D47(5,9);U+5D46(3,8) +U+5D48(0);U+5D48(0); +U+5D49(0);U+5D49(0,9); +U+5D4A(0);U+5D4A(5,9); +U+5D4B(0);U+5D4B(5,9); +U+5D4C(0);U+5D4C(5,9); +U+5D4D(0);U+5D4D(3); +U+5D4E(0);U+5D4E(0,9); +U+5D4F(0);U+5D4F(3);U+5D55(3,9) +U+5D50(0);U+5D50(0,9);U+5C9A(1,3,8) +U+5D51(0);U+5D51(0,9); +U+5D52(0);U+5D52(0,9);U+5CA9(2,9),U+55A6(0,2,4,9),U+58E7(2,3,4,9),U+5DCC(2,4),U+5DD6(2,3,4,8,9),U+789E(2,3,4,9),U+7939(2,3,4,9) +U+5D54(0);U+5D54(0); +U+5D55(0);U+5D55(0,9);U+5D4F(3) +U+5D56(0);U+5D56(0); +U+5D58(0);U+5DB8(1,3,8,9);U+5DB8(1,3,8,9) +U+5D59(0);U+5D59(0,9); +U+5D5A(0);U+5D94(1,3,8,9);U+5D94(1,3,8,9) +U+5D5B(0);U+5D5B(5); +U+5D5D(0);U+5D81(1,3,8,9);U+5D81(1,3,8,9) +U+5D5E(0);U+5D5E(3,9); +U+5D5F(0);U+5D5F(0); +U+5D61(0);U+5D61(0); +U+5D62(0);U+5D62(0,9); +U+5D63(0);U+5D63(0,9); +U+5D64(0);U+5D64(0); +U+5D65(0);U+5D65(0,9); +U+5D66(0);U+5D66(0); +U+5D67(0);U+5D67(0,9); +U+5D68(0);U+5D68(0,9); +U+5D69(0);U+5D69(5,9); +U+5D6A(0);U+5D6A(0); +U+5D6B(0);U+5D6B(5,9); +U+5D6C(0);U+5D6C(5,9); +U+5D6D(0);U+5D6D(0); +U+5D6E(0);U+5D6E(0); +U+5D6F(0);U+5D6F(5,9);U+5D73(3,8) +U+5D70(0);U+5D70(0); +U+5D71(0);U+5D71(0,9); +U+5D72(0);U+5D72(0,9); +U+5D73(0);U+5D6F(3,8,9);U+5D6F(3,8,9) +U+5D74(0);U+5D74(5); +U+5D75(0);U+5D75(0); +U+5D76(0);U+5D76(0); +U+5D77(0);U+5D77(0,9); +U+5D78(0);U+5D78(0); +U+5D79(0);U+5D79(0,9); +U+5D7A(0);U+5D7A(0,9); +U+5D7B(0);U+5D7B(0); +U+5D7C(0);U+5D7C(0,9); +U+5D7D(0);U+5D7D(3,9); +U+5D7E(0);U+5D7E(0,9); +U+5D7F(0);U+5D7F(0,9); +U+5D80(0);U+5D80(0,9); +U+5D81(0);U+5D81(0,9);U+5D5D(1,3,8) +U+5D82(0);U+5D82(5,9); +U+5D84(0);U+5D84(0,9);U+5D2D(1,3,8) +U+5D85(0);U+5D85(3); + +U+5D86(0);U+5D86(0,9); +U+5D87(0);U+5D87(0,9);U+5C96(1,3,8) +U+5D88(0);U+5D88(0,9); +U+5D89(0);U+5D89(0,9); +U+5D8A(0);U+5D8A(0,9); +U+5D8B(0);U+5CF6(3,8,9);U+5C9B(3),U+5CF6(3,8,9),U+5D8C(3,7) +U+5D8C(0);U+5CF6(8,9);U+5C9B(7),U+5CF6(8,9),U+5D8B(3,7) +U+5D8D(0);U+5D8D(0,9); +U+5D8E(0);U+5D8E(0); +U+5D8F(0);U+5D8F(0); +U+5D90(0);U+5D90(0); +U+5D91(0);U+5D91(0); +U+5D92(0);U+5D92(0,9); +U+5D93(0);U+5D93(0,9); +U+5D94(0);U+5D94(0,9);U+5D5A(1,3,8) +U+5D95(0);U+5D95(4,9); +U+5D97(0);U+5D97(0,9);U+5D02(1,3,8) +U+5D98(0);U+5D98(0); +U+5D99(0);U+5D99(5,9); +U+5D9A(0);U+5D9A(3,9); +U+5D9B(0);U+5D9B(0); +U+5D9C(0);U+5D9C(0,9); +U+5D9D(0);U+5D9D(5,9); +U+5D9E(0);U+5D9E(0,9); +U+5D9F(0);U+5D9F(0,9); +U+5DA0(0);U+5DA0(0,9);U+5CE4(1,3,8) +U+5DA1(0);U+5DA1(3,9); +U+5DA2(0);U+5DA2(0,9);U+5CE3(1,3,8) +U+5DA5(0);U+5DA5(0); +U+5DA6(0);U+5DA6(0); +U+5DA7(0);U+5DA7(0,9);U+5CC4(1,3,8) +U+5DA8(0);U+5DA8(0,9);U+5CC3(1,3) +U+5DA9(0);U+5DA9(0,9);U+5CF1(3,9) +U+5DAA(0);U+5DAA(3,9); +U+5DAC(0);U+5DAC(0,9); +U+5DAD(0);U+5DAD(0,9); +U+5DAE(0);U+5DAE(0,9);U+5D04(4,8) +U+5DAF(0);U+5DAF(0,9); +U+5DB0(0);U+5DB0(0,9); +U+5DB1(0);U+5DB1(0,9); +U+5DB2(0);U+5DB2(0,9); +U+5DB4(0);U+5DB4(3,9); +U+5DB5(0);U+5DB5(0,9); +U+5DB6(0);U+5DB6(0); +U+5DB7(0);U+5DB7(5,9); +U+5DB8(0);U+5DB8(0,9);U+5D58(1,3,8) +U+5DBA(0);U+5DBA(0,9);U+5CAD(1,3,8,9),U+5CBA(7) +U+5DBB(0);U+5DBB(4); +U+5DBC(0);U+5DBC(0,9);U+5C7F(1,3,8) +U+5DBD(0);U+5DBD(3,9);U+5CB3(2,3,8,9) +U+5DBE(0);U+5DBE(0); +U+5DBF(0);U+5DBF(0); +U+5DC0(0);U+5DC0(3,9); +U+5DC1(0);U+5DC1(0); +U+5DC2(0);U+5DC2(3,9); +U+5DC3(0);U+5DC3(3,9); +U+5DC5(0);U+5DD4(1,3,8,9);U+5DD3(4),U+5DD4(1,3,8,9) +U+5DC6(0);U+5DC6(0,9); +U+5DC7(0);U+5DC7(3,9); +U+5DC8(0);U+5DC8(0); +U+5DC9(0);U+5DC9(0,9);U+6E10(4),U+6F38(1,3,4,8,9) +U+5DCA(0);U+5DCA(0); +U+5DCB(0);U+5DCB(0,9);U+5CBF(1,3,8) + +U+5DCC(0);U+5DD6(7,8,9);U+5CA9(4,9),U+5DD6(7,8,9),U+55A6(0,4,9),U+5D52(2,4,9),U+58E7(3,4,9),U+789E(3,4,9),U+7939(3,4,9) +U+5DCD(0);U+5DCD(5,9); +U+5DCE(0);U+5DCE(4); +U+5DCF(0);U+5DCF(0,9); +U+5DD0(0);U+5DD0(0); +U+5DD1(0);U+5DD1(0,9); +U+5DD2(0);U+5DD2(0,9);U+5CE6(1,3,8) +U+5DD3(0);U+5DD4(4,8,9);U+5DC5(4),U+5DD4(4,8,9) +U+5DD4(0);U+5DD4(0,9);U+5DC5(1,3,8),U+5DD3(4,8) +U+5DD5(0);U+5DD5(0,9); +U+5DD6(0);U+5DD6(0,9);U+5CA9(2,3,8,9),U+5DCC(7,8),U+55A6(0,2,3,4,8,9),U+5D52(2,3,4,8,9),U+58E7(2,3,4,8,9),U+789E(2,3,4,8,9),U+7939(2,3,4,8,9) +U+5DD8(0);U+5DD8(3,9); +U+5DD9(0);U+5DD9(0); +U+5DDB(0);U+5DDB(5); +U+5DDD(0);U+5DDD(5,9); +U+5DDE(0);U+5DDE(5,9); +U+5DDF(0);U+5DDF(0,9); +U+5DE0(0);U+5DE0(3,9); +U+5DE1(0);U+5DE1(5,9);U+5EF5(2,3,8) +U+5DE2(0);U+5DE2(5,9);U+5DE3(3,8),U+6F05(3,9) +U+5DE3(0);U+5DE2(3,8,9);U+5DE2(3,8,9),U+6F05(3,8,9) +U+5DE4(0);U+5DE4(0); +U+5DE5(0);U+5DE5(5,9); +U+5DE6(0);U+5DE6(5,9); +U+5DE7(0);U+5DE7(5,9); +U+5DE8(0);U+5DE8(5,9),U+9245(2,3,8,9);U+9245(2,3,8,9),U+949C(2,3,4,8) +U+5DE9(0);U+978F(1,3,8,9);U+978F(1,3,8,9) +U+5DEA(0);U+5DEA(0); +U+5DEB(0);U+5DEB(5,9); +U+5DEC(0);U+5DEC(0); +U+5DED(0);U+5DED(0); +U+5DEE(0);U+5DEE(5,9); +U+5DEF(0);U+5DF0(1,3,8,9);U+5DF0(1,3,8,9) +U+5DF0(0);U+5DF0(0,9);U+5DEF(1,3,8) +U+5DF1(0);U+5DF1(5,9); +U+5DF2(0);U+5DF2(5,9); +U+5DF3(0);U+5DF3(5,9); +U+5DF4(0);U+5DF4(5,9);U+7B06(3,8,9) +U+5DF5(0);U+536E(2,3,8,9);U+536E(2,3,8,9) +U+5DF7(0);U+5DF7(5,9); +U+5DF8(0);U+5DF8(3); +U+5DF9(0);U+5DF9(0,9); +U+5DFA(0);U+5DFD(3,8,9);U+5DFD(3,8,9) +U+5DFB(0);U+5377(4,9);U+5377(4,9),U+6372(1,3,4,8,9) +U+5DFC(0);U+5DFC(0); +U+5DFD(0);U+5DFD(5,9);U+5DFA(3,8) +U+5DFE(0);U+5DFE(5,9); +U+5DFF(0);U+5DFF(0,9); +U+5E00(0);U+5E00(3); +U+5E01(0);U+5E63(1,3,8,9);U+5E63(1,3,8,9),U+5E64(4) +U+5E02(0);U+5E02(5,9); +U+5E03(0);U+5E03(3,9),U+4F48(2,3,8,9);U+4F48(2,3,8,9) +U+5E04(0);U+5E04(0,9); +U+5E05(0);U+5E25(1,3,8,9);U+5E25(1,3,8,9) +U+5E06(0);U+5E06(5,9); +U+5E07(0);U+5E07(0); +U+5E08(0);U+5E2B(1,3,8,9);U+5E2B(1,3,8,9) +U+5E09(0);U+5E09(0); +U+5E0A(0);U+5E0A(3,9); +U+5E0B(0);U+7D19(2,3,8,9);U+7D19(2,3,8,9),U+7EB8(4) +U+5E0C(0);U+5E0C(5,9);U+7A00(3,8,9) + +U+5E0D(0);U+5E0D(0); +U+5E0E(0);U+5E0E(0,9); +U+5E0F(0);U+5E43(1,3,8,9);U+5E43(1,3,8,9) +U+5E10(0);U+5E33(1,3,8,9);U+5E33(1,3,8,9),U+8CEC(1,3,8,9),U+8D26(1,3,8) +U+5E11(0);U+5E11(5,9); +U+5E13(0);U+5E13(0); +U+5E14(0);U+5E14(5,9); +U+5E15(0);U+5E15(5,9); +U+5E16(0);U+5E16(5,9); +U+5E17(0);U+5E17(0,9); +U+5E18(0);U+5E18(1,3,9),U+7C3E(1,3,8,9);U+7C3E(1,3,8,9) +U+5E19(0);U+5E19(5,9);U+889F(2,3,9) +U+5E1A(0);U+5E1A(5,9);U+83F7(3,8) +U+5E1B(0);U+5E1B(5,9); +U+5E1C(0);U+5E5F(1,3,8,9);U+5E5F(1,3,8,9) +U+5E1D(0);U+5E1D(5,9); +U+5E1E(0);U+5E1E(3); +U+5E1F(0);U+5E1F(0,9); +U+5E20(0);U+5E20(0,9); +U+5E21(0);U+5E21(3,9);U+5E32(3,8) +U+5E22(0);U+5E22(0,9); +U+5E23(0);U+5E23(0,9); +U+5E24(0);U+5E24(0,9); +U+5E25(0);U+5E25(0,9);U+5E05(1,3,8) +U+5E26(0);U+5E36(1,3,8,9);U+5E2F(3),U+5E36(1,3,8,9) +U+5E27(0);U+5E40(1,3,8,9);U+5E40(1,3,8,9) +U+5E28(0);U+5E28(0,9); +U+5E29(0);U+5E29(0,9); +U+5E2A(0);U+5E2A(0); +U+5E2B(0);U+5E2B(0,9);U+5E08(1,3,8) +U+5E2C(0);U+88D9(2,3,8,9);U+88D9(2,3,8,9),U+88E0(2,3,8) +U+5E2D(0);U+5E2D(5,9),U+84C6(2,3,8,9);U+5ED7(4,9),U+84C6(2,3,8,9) +U+5E2E(0);U+5E6B(1,3,4,8,9);U+5E47(4),U+5E5A(3),U+5E6B(1,3,4,8,9),U+7E0D(3,9),U+97A4(4,9) +U+5E2F(0);U+5E36(3,8,9);U+5E26(3),U+5E36(3,8,9) +U+5E30(0);U+6B78(3,8,9);U+5F52(3),U+6B78(3,8,9),U+7688(3,8,9) +U+5E31(0);U+5E6C(4,8,9);U+5E6C(4,8,9) +U+5E32(0);U+5E21(3,8,9);U+5E21(3,8,9) +U+5E33(0);U+5E33(0,9);U+5E10(1,3,8),U+8CEC(3,8,9),U+8D26(1,3,8) +U+5E34(0);U+5E34(0,9); +U+5E35(0);U+5E35(0); +U+5E36(0);U+5E36(0,9);U+5E26(1,3,8),U+5E2F(3,8) +U+5E37(0);U+5E37(5,9); +U+5E38(0);U+5E38(5,9); +U+5E39(0);U+5E39(0); +U+5E3A(0);U+5E3A(4);U+8900(4) +U+5E3B(0);U+5E58(1,3,8,9);U+5E58(1,3,8,9) +U+5E3C(0);U+5E57(1,3,8,9);U+5E57(1,3,8,9),U+852E(4,9) +U+5E3D(0);U+5E3D(5,9); +U+5E3E(0);U+5E3E(0,9); +U+5E40(0);U+5E40(0,9);U+5E27(1,3,8) +U+5E41(0);U+5E41(0,9); +U+5E42(0);U+51AA(2,3,9);U+51AA(2,3,9),U+7F83(7,9) +U+5E43(0);U+5E43(0,9);U+5E0F(1,3,8) +U+5E44(0);U+5E44(5,9); +U+5E45(0);U+5E45(5,9); +U+5E46(0);U+5E46(0); +U+5E47(0);U+5E6B(2,3,8,9);U+5E2E(4),U+5E6B(2,3,8,9),U+5E5A(3,4),U+7E0D(3,4,9),U+97A4(4,9) +U+5E49(0);U+5E49(0); +U+5E4A(0);U+5E4A(0,9); +U+5E4B(0);U+5E4B(3,9); +U+5E4C(0);U+5E4C(5,9); + +U+5E4D(0);U+5E4D(0,9); +U+5E4E(0);U+5E4E(0,9); +U+5E4F(0);U+5E4F(0,9); +U+5E50(0);U+5E50(0); +U+5E52(0);U+5E52(0); +U+5E53(0);U+5E53(0,9); +U+5E54(0);U+5E54(5,9); +U+5E55(0);U+5E55(5,9);U+5E59(2,3,9) +U+5E56(0);U+5E56(0); +U+5E57(0);U+5E57(0,9);U+5E3C(1,3,8),U+852E(1,3,4,8,9) +U+5E58(0);U+5E58(0,9);U+5E3B(1,3,8) +U+5E59(0);U+5E59(0,9);U+5E55(2,3,9) +U+5E5A(0);U+5E6B(2,3,8,9);U+5E2E(3),U+5E6B(2,3,8,9),U+5E47(3,4),U+7E0D(3,9),U+97A4(3,4,9) +U+5E5B(0);U+5E5B(5,9); +U+5E5C(0);U+5E5C(0,9); +U+5E5D(0);U+5E5D(0,9); +U+5E5E(0);U+5E5E(5); +U+5E5F(0);U+5E5F(0,9);U+5E1C(1,3,8) +U+5E60(0);U+5E60(0,9); +U+5E61(0);U+5E61(5,9); +U+5E62(0);U+5E62(5,9); +U+5E63(0);U+5E63(0,9);U+5E01(1,3,8),U+5E64(4,8) +U+5E64(0);U+5E63(4,8,9);U+5E01(4),U+5E63(4,8,9) +U+5E65(0);U+5E65(0); +U+5E66(0);U+5E66(0,9); +U+5E67(0);U+5E67(3,9); +U+5E68(0);U+5E68(0,9); +U+5E69(0);U+5E69(0,9); +U+5E6A(0);U+5E6A(0,9); +U+5E6B(0);U+5E6B(0,9);U+5E2E(1,3,8),U+5E47(2,3,8),U+5E5A(2,3,8),U+7E0D(1,3,4,8,9),U+97A4(1,3,4,8,9) +U+5E6C(0);U+5E6C(0,9);U+5E31(4,8) +U+5E6D(0);U+5E6D(0,9); +U+5E6E(0);U+5E6E(3,9); +U+5E6F(0);U+5E6F(3,9); +U+5E70(0);U+5E70(0,9); +U+5E71(0);U+8974(3,8,9);U+8955(3),U+8974(3,8,9) +U+5E72(0);U+5E72(1,3,4,9),U+4E7E(1,3,4,8,9),U+5E79(1,3,4,8,9);U+4E7E(1,3,4,8,9),U+4E81(4),U+5E79(1,3,4,8,9),U+69A6(4,9),U+6F27(1,3,8,9) +U+5E73(0);U+5E73(5,9); +U+5E74(0);U+5E74(5,9);U+79CA(2,3) +U+5E75(0);U+5E75(0,9); +U+5E76(0);U+5E76(4,9),U+4E26(2,8,9),U+4F75(2,9);U+4E26(2,8,9),U+4F75(2,9),U+5002(4),U+5E77(3,4),U+7ADD(2) +U+5E77(0);U+5E76(4,9);U+5E76(4,9),U+4E26(0,2,3,4,8,9),U+4F75(2,3,4,8,9),U+7ADD(2,3,4,8),U+5002(2,3,4,8) +U+5E78(0);U+5E78(5,9),U+5016(2,3,8,9);U+5016(2,3,8,9) +U+5E79(0);U+5E79(0,9);U+5E72(1,3,8,9),U+69A6(2,3,9),U+4E7E(1,3,4,8,9),U+4E81(1,2,3,4,8),U+6F27(1,3,4,8,9) +U+5E7A(0);U+4E48(3,9);U+4E48(3,9),U+5E85(3,4),U+9EBC(3,4,8,9),U+9EBD(1,3,8) +U+5E7B(0);U+5E7B(5,9); +U+5E7C(0);U+5E7C(5,9); +U+5E7D(0);U+5E7D(5,9); +U+5E7E(0);U+5E7E(0,9);U+51E0(1,3,8,9) +U+5E7F(0);U+5EE3(1,3,8,9);U+5E83(4),U+5EE3(1,3,8,9) +U+5E80(0);U+5E80(5,9); +U+5E81(0);U+5EF3(3,8,9);U+5EF3(3,8,9),U+5385(1,3,8),U+539B(1,3,8),U+5EF0(1,3,4,8) +U+5E82(0);U+5E82(0,9);U+4EC4(3,9) +U+5E83(0);U+5EE3(4,8,9);U+5E7F(4),U+5EE3(4,8,9) +U+5E84(0);U+5E84(1,3,9),U+838A(1,3,8,9);U+8358(4),U+838A(1,3,8,9) +U+5E85(0);U+9EBC(8,9);U+4E48(4,9),U+9EBC(8,9),U+9EBD(4),U+5E7A(3,4) +U+5E86(0);U+6176(1,3,8,9);U+6176(1,3,8,9) + +U+5E87(0);U+5E87(5,9); +U+5E88(0);U+5E88(0,9); +U+5E89(0);U+5E89(0,9); +U+5E8A(0);U+5E8A(5,9);U+7240(2,3,8) +U+5E8B(0);U+5E8B(5,9); +U+5E8C(0);U+5E8C(0,9); +U+5E8D(0);U+5E8D(0,9); +U+5E8E(0);U+5E8E(3); +U+5E8F(0);U+5E8F(5,9); +U+5E90(0);U+5EEC(1,3,8,9);U+5EEC(1,3,8,9) +U+5E91(0);U+5EE1(1,3,8,9);U+5EE1(1,3,8,9) +U+5E93(0);U+5EAB(1,3,8,9);U+5EAB(1,3,8,9) +U+5E94(0);U+61C9(1,3,8,9);U+5FDC(4),U+61C9(1,3,8,9),U+8B4D(3) +U+5E95(0);U+5E95(5,9);U+538E(4,9) +U+5E96(0);U+5E96(5,9); +U+5E97(0);U+5E97(5,9);U+576B(3,8,9) +U+5E98(0);U+5E98(0); +U+5E99(0);U+5EDF(1,3,8,9);U+5EBF(3),U+5EDF(1,3,8,9) +U+5E9A(0);U+5E9A(5,9); +U+5E9B(0);U+5E9B(0,9); +U+5E9C(0);U+5E9C(5,9); +U+5E9D(0);U+5E9D(0); +U+5E9E(0);U+9F90(1,3,8,9);U+5390(7),U+9F8E(7),U+9F90(1,3,8,9) +U+5E9F(0);U+5EE2(1,3,8,9);U+5EC3(4),U+5EE2(1,3,8,9),U+7648(2,9) +U+5EA0(0);U+5EA0(5,9); +U+5EA1(0);U+5EA1(0); +U+5EA2(0);U+5EA2(3,9); +U+5EA3(0);U+5EA3(0,9); +U+5EA4(0);U+5EA4(0,9); +U+5EA5(0);U+5EA5(5,9); +U+5EA6(0);U+5EA6(5,9); +U+5EA7(0);U+5EA7(5,9);U+5750(3,8,9) +U+5EA8(0);U+5EA8(0,9); +U+5EA9(0);U+5EA9(0); +U+5EAA(0);U+5EAA(0,9); +U+5EAB(0);U+5EAB(0,9);U+5E93(1,3,8) +U+5EAC(0);U+5EAC(3,9); +U+5EAD(0);U+5EAD(5,9); +U+5EAE(0);U+5EAE(0,9); +U+5EAF(0);U+5EAF(3); +U+5EB0(0);U+5EB0(0,9);U+5C4F(4,9),U+5C5B(3,4) +U+5EB1(0);U+5EB1(0,9); +U+5EB2(0);U+5EB2(0,9); +U+5EB3(0);U+5EB3(5,9); +U+5EB4(0);U+5EB4(0,9); +U+5EB5(0);U+5EB5(5,9);U+83F4(2,3,8,9) +U+5EB6(0);U+5EB6(5,9);U+5EBB(2,8),U+8B36(3,9) +U+5EB7(0);U+5EB7(5,9); +U+5EB8(0);U+5EB8(5,9); +U+5EB9(0);U+5EB9(5,9); +U+5EBB(0);U+5EB6(2,8,9);U+5EB6(2,8,9),U+8B36(2,3,8,9) +U+5EBC(0);U+5ECE(1,3,8,9);U+5ECE(1,3,8,9) +U+5EBD(0);U+5BD3(2,3,8,9);U+5BD3(2,3,8,9) +U+5EBE(0);U+5EBE(5,9);U+6594(3,9),U+659E(3,9) +U+5EBF(0);U+5EDF(3,8,9);U+5E99(3),U+5EDF(3,8,9) +U+5EC1(0);U+5EC1(0,9);U+5395(4,8),U+53A0(2,3,8) +U+5EC2(0);U+5EC2(0,9);U+53A2(2,3,8) +U+5EC3(0);U+5EE2(4,8,9);U+5E9F(4),U+5EE2(4,8,9),U+7648(2,4,9) +U+5EC4(0);U+5EC4(0,9);U+53A9(2,8),U+5ECF(4,8),U+5ED0(8) +U+5EC5(0);U+5EC5(0,9); +U+5EC6(0);U+5EC6(0,9); +U+5EC7(0);U+5EC7(0,9); +U+5EC8(0);U+5EC8(0,9);U+53A6(2,3,8) + +U+5EC9(0);U+5EC9(5,9);U+4EB7(2,8),U+899D(4,9) +U+5ECA(0);U+5ECA(5,9); +U+5ECB(0);U+5ECB(3,9); +U+5ECC(0);U+5ECC(0,9); +U+5ECD(0);U+5ECD(0); +U+5ECE(0);U+5ECE(0,9);U+5EBC(1,3,8) +U+5ECF(0);U+5EC4(4,8,9);U+53A9(3,4),U+5EC4(4,8,9),U+5ED0(3) +U+5ED0(0);U+5EC4(8,9);U+53A9(2),U+5EC4(8,9),U+5ECF(3) +U+5ED1(0);U+5ED1(5,9); +U+5ED2(0);U+5ED2(5,9); +U+5ED3(0);U+5ED3(5,9);U+9729(3,9) +U+5ED4(0);U+5ED4(0,9); +U+5ED5(0);U+5ED5(0,9);U+836B(4),U+852D(1,3,4,8,9) +U+5ED6(0);U+5ED6(5,9); +U+5ED7(0);U+5ED7(0,9);U+5E2D(4,9),U+84C6(2,3,4,8,9) +U+5ED8(0);U+5ED8(3,9); +U+5ED9(0);U+5ED9(0,9); +U+5EDA(0);U+5EDA(0,9);U+53A8(2,3,8) +U+5EDB(0);U+5EDB(5,9); +U+5EDC(0);U+5EDC(0,9); +U+5EDD(0);U+5EDD(0,9);U+53AE(2,3,8) +U+5EDE(0);U+5EDE(0,9); +U+5EDF(0);U+5EDF(0,9);U+5E99(1,3,8),U+5EBF(3,8) +U+5EE0(0);U+5EE0(0,9);U+5382(1,3,8,9),U+53B0(3,8) +U+5EE1(0);U+5EE1(0,9);U+5E91(1,3,8) +U+5EE2(0);U+5EE2(0,9);U+5E9F(1,3,8),U+5EC3(4,8),U+7648(1,2,3,8,9) +U+5EE3(0);U+5EE3(0,9);U+5E7F(1,3,8),U+5E83(4,8) +U+5EE4(0);U+5EE4(0); +U+5EE5(0);U+5EE5(0,9); +U+5EE6(0);U+5EE6(0,9); +U+5EE7(0);U+5EE7(0,9); +U+5EE8(0);U+5EE8(5,9); +U+5EE9(0);U+5EE9(0,9);U+5EEA(3),U+7A1F(3,8,9),U+7980(2,3,8) +U+5EEA(0);U+5EE9(3,9);U+5EE9(3,9),U+7A1F(3,8,9),U+7980(2,3,8) +U+5EEC(0);U+5EEC(0,9);U+5E90(1,3,8) +U+5EED(0);U+5EED(0); +U+5EEE(0);U+5EEE(0,9); +U+5EEF(0);U+5EEF(0,9); +U+5EF0(0);U+5EF3(4,8,9);U+5385(4),U+5EF3(4,8,9),U+539B(3,4),U+5E81(1,3,4,8) +U+5EF1(0);U+5EF1(0,9); +U+5EF2(0);U+5EF2(0,9); +U+5EF3(0);U+5EF3(0,9);U+5385(1,3,8),U+539B(3,8),U+5E81(3,8),U+5EF0(4,8) +U+5EF4(0);U+5EF4(5); +U+5EF5(0);U+5DE1(2,3,8,9);U+5DE1(2,3,8,9) +U+5EF6(0);U+5EF6(5,9); +U+5EF7(0);U+5EF7(5,9); +U+5EF8(0);U+8FEA(3,8,9);U+8FEA(3,8,9) +U+5EFA(0);U+5EFA(5,9); +U+5EFB(0);U+8FF4(2,9);U+56DE(2,8,9),U+5EFD(4),U+8FF4(2,9),U+9025(3),U+56D8(0,3,8),U+56EC(3,8) +U+5EFC(0);U+8FFA(4,9);U+4E43(2,3,8,9),U+8FFA(4,9) +U+5EFD(0);U+8FF4(8,9);U+56DE(4,8,9),U+5EFB(4),U+8FF4(8,9),U+56D8(0,2,3,8),U+56EC(2,3,8),U+9025(2,3,4,8) +U+5EFE(0);U+5EFE(5,9); +U+5EFF(0);U+5EFF(5,9);U+5344(3,8,9) +U+5F00(0);U+958B(1,3,8,9);U+958B(1,3,8,9) +U+5F01(0);U+5F01(5,9); +U+5F02(0);U+7570(2,3,8,9);U+7570(2,3,8,9) +U+5F03(0);U+68C4(2,3,8,9);U+68C4(2,3,8,9) +U+5F04(0);U+5F04(5,9);U+8856(2,9) +U+5F05(0);U+5F05(0,9); +U+5F06(0);U+5F06(3); +U+5F07(0);U+5F07(0,9); + +U+5F08(0);U+5F08(5,9); +U+5F0A(0);U+5F0A(5,9); +U+5F0B(0);U+5F0B(5,9);U+96BF(3,9) +U+5F0C(0);U+4E00(3,9);U+4E00(3,9),U+58F9(3,8,9),U+58F1(3,4,8) +U+5F0D(0);U+4E8C(3,8,9);U+4E8C(3,8,9),U+8CB3(3,8,9),U+8CAE(3,4,8),U+8D30(1,3,8) +U+5F0F(0);U+5F0F(5,9); +U+5F11(0);U+5F12(4,8,9);U+5F12(4,8,9) +U+5F12(0);U+5F12(0,9);U+5F11(4,8) +U+5F13(0);U+5F13(5,9); +U+5F14(0);U+5F14(0,9);U+540A(2,3,9) +U+5F15(0);U+5F15(5,9); +U+5F16(0);U+5F16(0); +U+5F17(0);U+5F17(5,9); +U+5F18(0);U+5F18(5,9); +U+5F19(0);U+5F19(0); +U+5F1A(0);U+5F1A(0,9); +U+5F1B(0);U+5F1B(5,9); +U+5F1C(0);U+5F1C(0); +U+5F1D(0);U+5F1D(0,9); +U+5F1E(0);U+5F1E(3); +U+5F1F(0);U+5F1F(5,9); +U+5F20(0);U+5F35(1,3,8,9);U+5F35(1,3,8,9) +U+5F21(0);U+5F21(0); +U+5F22(0);U+5F22(3,9); +U+5F23(0);U+5F23(3,9); +U+5F24(0);U+5F24(0,9); +U+5F25(0);U+5F4C(1,3,8,9);U+519E(7,9),U+5F4C(1,3,8,9),U+7030(1,3,9) +U+5F26(0);U+5F26(5,9);U+7D43(2,8,9) +U+5F27(0);U+5F27(5,9); +U+5F28(0);U+5F28(0,9); +U+5F29(0);U+5F29(5,9); +U+5F2A(0);U+5F33(4,8,9);U+5F33(4,8,9) +U+5F2B(0);U+5F2B(0); +U+5F2C(0);U+5F2C(0); +U+5F2D(0);U+5F2D(5,9); +U+5F2E(0);U+5F2E(0,9); +U+5F2F(0);U+5F4E(1,3,8,9);U+5F4E(1,3,8,9) +U+5F30(0);U+5F30(0,9); +U+5F31(0);U+5F31(5,9); +U+5F32(0);U+5F32(0); +U+5F33(0);U+5F33(0,9);U+5F2A(4,8) +U+5F34(0);U+5F34(0); +U+5F35(0);U+5F35(0,9);U+5F20(1,3,8) +U+5F36(0);U+5F36(4,9); +U+5F37(0);U+5F37(0,9);U+5F3A(2,3,8),U+5F4A(7,9) +U+5F38(0);U+5F38(0,9); +U+5F39(0);U+5F48(1,3,8,9);U+5F3E(4),U+5F48(1,3,8,9) +U+5F3A(0);U+5F37(2,3,8,9);U+5F37(2,3,8,9),U+5F4A(2,3,8,9) +U+5F3C(0);U+5F3C(5,9); +U+5F3E(0);U+5F48(8,9);U+5F39(4),U+5F48(8,9) +U+5F3F(0);U+5F3F(0); +U+5F40(0);U+5F40(5,9); +U+5F41(0);U+5F41(0); +U+5F42(0);U+767C(4,8,9);U+53D1(4),U+767C(4,8,9),U+9AEA(4),U+9AEE(1,3,4,8,9) +U+5F43(0);U+5F43(3,9); +U+5F44(0);U+5F44(3,9); +U+5F45(0);U+5F45(0); +U+5F46(0);U+5F46(0,9);U+522B(1,3),U+618B(3,9),U+5225(0,1,3,4,8,9) +U+5F47(0);U+5F47(0); +U+5F48(0);U+5F48(0,9);U+5F39(1,3,8),U+5F3E(8) +U+5F49(0);U+5F49(0,9);U+5F4D(3) +U+5F4A(0);U+5F4A(0,9);U+5F37(7,9),U+5F3A(2,3,8) +U+5F4B(0);U+5F4B(0,9); + +U+5F4C(0);U+5F4C(0,9);U+5F25(1,3,8),U+7030(4,8,9),U+519E(1,3,7,8,9) +U+5F4D(0);U+5F4D(3);U+5F49(3,9) +U+5F4E(0);U+5F4E(0,9);U+5F2F(1,3,8) +U+5F4F(0);U+5F4F(0,9); +U+5F50(0);U+5F50(5);U+5F51(4,8) +U+5F51(0);U+5F51(0);U+5F50(4,8) +U+5F52(0);U+6B78(1,3,8,9);U+5E30(3),U+6B78(1,3,8,9),U+7688(3,8,9) +U+5F53(0);U+7576(1,3,8,9),U+5679(1,3,8,9);U+5679(1,3,8,9),U+7576(1,3,8,9) +U+5F54(0);U+5F54(0,9);U+5F55(3),U+9304(3,4,8,9),U+9332(1,3,8) +U+5F55(0);U+5F54(3,9),U+9304(4,8,9);U+5F54(3,9),U+9304(4,8,9),U+9332(1,3,8) +U+5F56(0);U+5F56(5,9); +U+5F57(0);U+5F57(5,9);U+7BF2(3,8,9) +U+5F58(0);U+5F58(5,9); +U+5F59(0);U+5F59(0,9);U+532F(4,9),U+5F5A(4,8),U+6C47(1,3,8),U+6ED9(4) +U+5F5A(0);U+5F59(4,8,9);U+5F59(4,8,9),U+6C47(4),U+532F(0,4,8,9),U+6ED9(4) +U+5F5B(0);U+5F5D(4,8,9);U+5F5C(4),U+5F5D(4,8,9),U+5F5E(4,8) +U+5F5C(0);U+5F5D(3,8,9);U+5F5B(4),U+5F5D(3,8,9),U+5F5E(4,8) +U+5F5D(0);U+5F5D(5,9);U+5F5B(4,8),U+5F5C(3,8),U+5F5E(4,8) +U+5F5E(0);U+5F5D(4,8,9);U+5F5D(4,8,9),U+5F5B(0,4,8),U+5F5C(4,8) +U+5F5F(0);U+5F60(4,8);U+5F60(4,8) +U+5F60(0);U+5F60(0);U+5F5F(4,8) +U+5F61(0);U+5F61(5); +U+5F62(0);U+5F62(5,9); +U+5F63(0);U+5F63(0); +U+5F64(0);U+5F64(5,9); +U+5F65(0);U+5F65(0,9);U+5F66(4,8) +U+5F66(0);U+5F65(4,8,9);U+5F65(4,8,9) +U+5F67(0);U+5F67(3,9); +U+5F68(0);U+5F72(4,8);U+5F72(4,8) +U+5F69(0);U+5F69(5,9),U+7DB5(2,9);U+7DB5(2,9) +U+5F6A(0);U+5F6A(5,9); +U+5F6B(0);U+5F6B(3,9);U+96D5(2,8,9),U+7431(2,3,8,9),U+9D70(2,3,8,9) +U+5F6C(0);U+5F6C(5,9);U+4EFD(3,8,9) +U+5F6D(0);U+5F6D(5,9); +U+5F6E(0);U+5F6E(0); +U+5F6F(0);U+5F6F(0,9); +U+5F70(0);U+5F70(5,9); +U+5F71(0);U+5F71(5,9); +U+5F72(0);U+5F72(0);U+5F68(4,8) +U+5F73(0);U+5F73(5,9); +U+5F74(0);U+5F74(0,9); +U+5F75(0);U+5F75(0); +U+5F76(0);U+5F76(0,9); +U+5F77(0);U+5F77(5,9);U+4EFF(4,8,9),U+5023(2,3,4,8,9),U+9AE3(2,3,4,8,9) +U+5F78(0);U+5F78(0,9); +U+5F79(0);U+5F79(5,9); +U+5F7A(0);U+5F7A(0); +U+5F7B(0);U+5FB9(1,3,8,9);U+5FB9(1,3,8,9) +U+5F7C(0);U+5F7C(5,9); +U+5F7D(0);U+5F7D(0,9); +U+5F7E(0);U+5F7E(0,9); +U+5F7F(0);U+5F7F(0,9);U+4F5B(2,9),U+9AF4(8),U+4ECF(0,2,3,8) +U+5F80(0);U+5F80(5,9);U+5F83(2,3,8),U+8FEC(3,8) +U+5F81(0);U+5F81(1,3,9),U+5FB5(1,3,4,8,9);U+5FB4(4),U+5FB5(1,3,4,8,9) +U+5F82(0);U+5F82(5,9); +U+5F83(0);U+5F80(2,3,8,9);U+5F80(2,3,8,9),U+8FEC(2,3,8) +U+5F84(0);U+5F91(1,3,8,9);U+5F91(1,3,8,9),U+9015(4,9),U+8FF3(4,8) +U+5F85(0);U+5F85(5,9); +U+5F86(0);U+5F86(0,9); +U+5F87(0);U+5F87(5,9); +U+5F88(0);U+5F88(5,9);U+4F77(3,9) +U+5F89(0);U+5F89(5,9); +U+5F8A(0);U+5F8A(5,9);U+4F6A(3,9) + +U+5F8B(0);U+5F8B(5,9); +U+5F8C(0);U+5F8C(0,9);U+540E(1,3,8,9) +U+5F8D(0);U+5F8D(0); +U+5F8E(0);U+5F8E(0); +U+5F90(0);U+5F90(5,9); +U+5F91(0);U+5F91(0,9);U+5F84(1,3,8),U+9015(2,3,8,9),U+8FF3(1,3,4,8) +U+5F92(0);U+5F92(5,9); +U+5F93(0);U+5F9E(3,8,9);U+4ECE(3),U+5F9E(3,8,9) +U+5F94(0);U+5F94(0); +U+5F95(0);U+5FA0(1,3,8,9);U+5FA0(1,3,8,9) +U+5F96(0);U+5F96(0,9); +U+5F97(0);U+5F97(5,9); +U+5F98(0);U+5F98(5,9); +U+5F99(0);U+5F99(5,9); +U+5F9B(0);U+5F9B(3,9); +U+5F9C(0);U+5F9C(5,9); +U+5F9D(0);U+5F9D(0); +U+5F9E(0);U+5F9E(0,9);U+4ECE(1,3,8),U+5F93(3,8) +U+5F9F(0);U+5F9F(0,9); +U+5FA0(0);U+5FA0(0,9);U+5F95(1,3,8) +U+5FA1(0);U+5FA1(1,3,9),U+79A6(1,3,8,9);U+79A6(1,3,8,9) +U+5FA2(0);U+5FA2(0); +U+5FA5(0);U+5FA5(0,9); +U+5FA6(0);U+5FA6(0,9); +U+5FA7(0);U+904D(2,3,8,9);U+904D(2,3,8,9) +U+5FA8(0);U+5FA8(5,9);U+9051(3,8,9) +U+5FA9(0);U+5FA9(0,9);U+590D(1,3,8,9),U+8986(3,8,9),U+8907(1,3,8,9) +U+5FAA(0);U+5FAA(5,9); +U+5FAB(0);U+5FAB(0,9); +U+5FAC(0);U+5FAC(0,9);U+508D(3,9) +U+5FAD(0);U+5FAD(5,9);U+509C(4,9) +U+5FAE(0);U+5FAE(5,9); +U+5FAF(0);U+5FAF(3,9); +U+5FB1(0);U+5FB1(0); +U+5FB2(0);U+5FB2(4,9); +U+5FB3(0);U+5FB7(3,8,9);U+5FB7(3,8,9),U+60B3(2,3,8),U+60EA(3,4,8) +U+5FB4(0);U+5FB5(4,8,9);U+5F81(4,9),U+5FB5(4,8,9) +U+5FB5(0);U+5FB5(0,9);U+5F81(1,3,8,9),U+5FB4(4,8) +U+5FB6(0);U+5FB6(0,9); +U+5FB7(0);U+5FB7(5,9);U+5FB3(3,8),U+60B3(2,3,8),U+60EA(4,8) +U+5FB8(0);U+5FB8(0); +U+5FB9(0);U+5FB9(0,9);U+5F7B(1,3,8) +U+5FBA(0);U+50E5(8,9);U+4FA5(3),U+50E5(8,9),U+510C(3,9) +U+5FBB(0);U+5FBB(0,9); +U+5FBC(0);U+5FBC(5,9); +U+5FBD(0);U+5FBD(5,9); +U+5FBE(0);U+5FBE(0,9); +U+5FBF(0);U+5FBF(0,9); +U+5FC0(0);U+5FC0(0,9); +U+5FC1(0);U+5FC1(0,9); +U+5FC3(0);U+5FC3(5,9); +U+5FC4(0);U+5FC4(5); +U+5FC5(0);U+5FC5(5,9); +U+5FC6(0);U+61B6(1,3,8,9);U+61B6(1,3,8,9) +U+5FC7(0);U+5FC7(0); +U+5FC8(0);U+4EC1(4,8,9);U+4EC1(4,8,9) +U+5FC9(0);U+5FC9(5,9); +U+5FCA(0);U+5FCA(0); +U+5FCB(0);U+5FCB(0); +U+5FCC(0);U+5FCC(5,9);U+8A8B(3,9),U+8AC5(3,9) +U+5FCD(0);U+5FCD(5,9); +U+5FCF(0);U+5FCF(1,3,9),U+61FA(1,3,8,9);U+61FA(1,3,8,9) +U+5FD0(0);U+5FD0(5,9); + +U+5FD1(0);U+5FD1(5,9); +U+5FD2(0);U+5FD2(5,9); +U+5FD3(0);U+5FD3(0); +U+5FD4(0);U+5FD4(3,9); +U+5FD5(0);U+5FD5(0,9); +U+5FD6(0);U+5FD6(5,9);U+520C(3,9) +U+5FD7(0);U+5FD7(5,9),U+8A8C(2,3,8,9);U+8A8C(2,3,8,9) +U+5FD8(0);U+5FD8(5,9); +U+5FD9(0);U+5FD9(5,9); +U+5FDA(0);U+5FDA(0); +U+5FDC(0);U+61C9(4,8,9);U+5E94(4),U+61C9(4,8,9),U+8B4D(3) +U+5FDD(0);U+5FDD(5,9); +U+5FDE(0);U+5FDE(3,9); +U+5FE0(0);U+5FE0(5,9); +U+5FE1(0);U+5FE1(5,9); +U+5FE3(0);U+5FE3(0,9);U+6025(3,9) +U+5FE4(0);U+5FE4(5,9); +U+5FE5(0);U+5FE5(0,9); +U+5FE6(0);U+5FE6(3); +U+5FE7(0);U+6182(1,3,8,9);U+6182(1,3,8,9) +U+5FE8(0);U+5FE8(0,9); +U+5FE9(0);U+5FE9(0); +U+5FEA(0);U+5FEA(5,9); +U+5FEB(0);U+5FEB(5,9); +U+5FED(0);U+5FED(5,9); +U+5FEE(0);U+5FEE(5,9); +U+5FEF(0);U+5FEF(0,9); +U+5FF0(0);U+60B4(3,8,9);U+60B4(3,8,9) +U+5FF1(0);U+5FF1(5,9); +U+5FF2(0);U+5FF2(3); +U+5FF3(0);U+5FF3(3,9); +U+5FF4(0);U+5FF4(0,9); +U+5FF5(0);U+5FF5(5,9),U+5538(2,3,9);U+5538(2,3,9) +U+5FF6(0);U+5FF6(0); +U+5FF7(0);U+5FF7(0,9); +U+5FF8(0);U+5FF8(5,9); +U+5FF9(0);U+5FF9(0); +U+5FFA(0);U+5FFA(0,9); +U+5FFB(0);U+5FFB(5,9); +U+5FFD(0);U+5FFD(5,9); +U+5FFE(0);U+613E(1,3,8,9);U+613E(1,3,8,9) +U+5FFF(0);U+5FFF(5,9); +U+6000(0);U+61F7(1,3,8,9);U+61F7(1,3,8,9),U+61D0(3),U+8922(3,9),U+8931(3,9) +U+6001(0);U+614B(1,3,8,9);U+614B(1,3,8,9) +U+6002(0);U+616B(1,3,8,9);U+616B(1,3,8,9) +U+6003(0);U+61AE(1,3,8,9);U+61AE(1,3,8,9) +U+6004(0);U+616A(1,3,8,9);U+616A(1,3,8,9) +U+6005(0);U+60B5(1,3,8,9);U+60B5(1,3,8,9) +U+6006(0);U+6134(1,3,8,9);U+6134(1,3,8,9) +U+6007(0);U+6007(0); +U+6008(0);U+6008(0); +U+6009(0);U+6009(0,9); +U+600A(0);U+600A(5,9); +U+600B(0);U+600B(3,9); +U+600C(0);U+600C(0,9); +U+600D(0);U+600D(5,9); +U+600E(0);U+600E(5,9); +U+600F(0);U+600F(5,9); +U+6010(0);U+6010(0,9);U+4F5D(3,9) +U+6011(0);U+6011(0,9); +U+6012(0);U+6012(5,9); +U+6013(0);U+6013(0,9); +U+6014(0);U+6014(5,9); + +U+6015(0);U+6015(5,9); +U+6016(0);U+6016(5,9); +U+6017(0);U+6017(3,9); +U+6018(0);U+6018(0); +U+6019(0);U+6019(5,9); +U+601A(0);U+601A(0,9); +U+601B(0);U+601B(5,9); +U+601C(0);U+601C(1,3,9),U+6190(1,3,8,9);U+6190(1,3,8,9) +U+601D(0);U+601D(5,9); +U+601E(0);U+601E(0,9); +U+601F(0);U+601F(0); +U+6020(0);U+6020(5,9); +U+6021(0);U+6021(5,9); +U+6022(0);U+6022(0,9); +U+6024(0);U+6024(3,9); +U+6025(0);U+6025(5,9);U+5FE3(3,9) +U+6026(0);U+6026(5,9); +U+6027(0);U+6027(5,9); +U+6028(0);U+6028(5,9); +U+6029(0);U+6029(5,9); +U+602A(0);U+602A(5,9); +U+602B(0);U+602B(5,9); +U+602C(0);U+602C(0,9); +U+602D(0);U+602D(0,9); +U+602E(0);U+602E(0,9); +U+602F(0);U+602F(5,9); +U+6030(0);U+6030(0); +U+6031(0);U+5306(2,3,8,9);U+5306(2,3,8,9),U+60A4(4) +U+6032(0);U+6032(0,9); +U+6033(0);U+6033(0,9);U+604D(2,9) +U+6034(0);U+6034(0,9); +U+6035(0);U+6035(5,9); +U+6036(0);U+6036(0); +U+6037(0);U+6037(0,9); +U+6038(0);U+6038(0); +U+6039(0);U+6039(0,9);U+4ED6(3,9) +U+603A(0);U+603A(0); +U+603B(0);U+7E3D(1,3,8,9);U+6374(4),U+6403(3),U+6460(3,9),U+7DCF(3),U+7E02(4),U+7E3D(1,3,8,9) +U+603C(0);U+61DF(1,3,8,9);U+61DF(1,3,8,9) +U+603D(0);U+603D(0); +U+603E(0);U+603E(0); +U+603F(0);U+61CC(1,3,8,9);U+61CC(1,3,8,9) +U+6040(0);U+6040(3,9); +U+6041(0);U+6041(5,9); +U+6042(0);U+6042(5,9);U+609B(4,8,9) +U+6043(0);U+6043(5,9); +U+6044(0);U+6044(0,9); +U+6045(0);U+6045(0,9); +U+6046(0);U+6046(0,9);U+6052(2,3,8,9) +U+6047(0);U+6047(0,9); +U+6048(0);U+6048(0); +U+6049(0);U+6049(0,9);U+65E8(4,9) +U+604A(0);U+5354(3,8,9);U+534F(3),U+5354(3,8,9),U+52A6(0,3,9) +U+604B(0);U+6200(1,3,8,9);U+6200(1,3,8,9) +U+604C(0);U+604C(0,9); +U+604D(0);U+604D(5,9);U+6033(2,9) +U+604E(0);U+604E(0); +U+604F(0);U+604F(0); +U+6050(0);U+6050(5,9); +U+6051(0);U+6051(0); +U+6052(0);U+6052(5,9);U+6046(2,3,8,9) +U+6053(0);U+6053(0,9); + +U+6054(0);U+6054(0,9); +U+6055(0);U+6055(5,9); +U+6057(0);U+6057(0); +U+6058(0);U+6058(3,9); +U+6059(0);U+6059(5,9); +U+605A(0);U+605A(5,9); +U+605B(0);U+605B(0,9); +U+605C(0);U+605C(0); +U+605D(0);U+605D(5,9); +U+605E(0);U+605E(3,9); +U+605F(0);U+605F(3,9); +U+6062(0);U+6062(5,9); +U+6063(0);U+6063(5,9); +U+6064(0);U+6064(5,9),U+5379(2,8,9);U+5379(2,8,9),U+8CC9(2,3,8) +U+6065(0);U+6065(0,9);U+803B(2,3,8) +U+6066(0);U+6066(0,9); +U+6067(0);U+6067(5,9); +U+6068(0);U+6068(5,9); +U+6069(0);U+6069(5,9); +U+606A(0);U+606A(5,9);U+6118(3,9) +U+606B(0);U+606B(5,9);U+75CC(3,9) +U+606C(0);U+606C(5,9); +U+606D(0);U+606D(5,9); +U+606E(0);U+606E(0,9); +U+606F(0);U+606F(5,9); +U+6070(0);U+6070(5,9); +U+6072(0);U+6072(0,9); +U+6073(0);U+61C7(1,3,8,9);U+61C7(1,3,8,9) +U+6075(0);U+60E0(4,8,9);U+60E0(4,8,9),U+6193(4,8,9) +U+6076(0);U+60E1(1,3,8,9),U+5641(1,3,8,9);U+5641(1,3,8,9),U+60AA(3),U+60E1(1,3,8,9) +U+6077(0);U+6077(0); +U+6078(0);U+615F(1,3,8,9);U+615F(1,3,8,9),U+6185(3) +U+6079(0);U+61E8(1,3,8,9);U+61E8(1,3,8,9) +U+607A(0);U+6137(1,3,8,9);U+6137(1,3,8,9) +U+607B(0);U+60FB(1,3,8,9);U+60FB(1,3,8,9) +U+607C(0);U+60F1(1,3,8,9);U+60F1(1,3,8,9) +U+607D(0);U+60F2(1,3,8,9);U+60F2(1,3,8,9) +U+607E(0);U+607E(3); +U+607F(0);U+607F(5,9);U+6142(2,3,8) +U+6080(0);U+6080(3,9); +U+6081(0);U+6081(0,9); +U+6082(0);U+6082(0); +U+6083(0);U+6083(5,9); +U+6084(0);U+6084(5,9); +U+6085(0);U+6085(0,9);U+60A6(4,8) +U+6086(0);U+6086(0,9); +U+6087(0);U+6087(0,9); +U+6088(0);U+6088(0,9); +U+6089(0);U+6089(5,9); +U+608A(0);U+608A(0,9); +U+608B(0);U+541D(3,8,9);U+541D(3,8,9) +U+608C(0);U+608C(5,9); +U+608D(0);U+608D(5,9); +U+608E(0);U+608E(0,9); +U+608F(0);U+608F(0); +U+6090(0);U+6090(0,9);U+60D5(3,9) +U+6092(0);U+6092(5,9); +U+6094(0);U+6094(5,9); +U+6095(0);U+6095(0,9); +U+6096(0);U+6096(5,9);U+8A96(2,3,9) +U+6097(0);U+6097(3,9); +U+6098(0);U+6098(0); +U+6099(0);U+6099(0); + +U+609A(0);U+609A(5,9); +U+609B(0);U+609B(5,9);U+6042(4,8,9) +U+609C(0);U+609C(0,9); +U+609D(0);U+609D(5,9); +U+609E(0);U+8AA4(3,9);U+60AE(7,8),U+8AA4(3,9),U+8BEF(3) +U+609F(0);U+609F(5,9); +U+60A0(0);U+60A0(5,9); +U+60A1(0);U+60A1(0); +U+60A2(0);U+60A2(3,9); +U+60A3(0);U+60A3(5,9); +U+60A4(0);U+5306(2,3,8,9);U+5306(2,3,8,9),U+6031(4) +U+60A6(0);U+6085(4,8,9);U+6085(4,8,9) +U+60A7(0);U+60A7(0); +U+60A8(0);U+60A8(5,9); +U+60AA(0);U+60E1(3,8,9);U+6076(3),U+60E1(3,8,9),U+5641(0,1,3,8,9) +U+60AB(0);U+6128(3,9);U+6128(3,9),U+6164(1,3,8) +U+60AC(0);U+61F8(1,3,8,9);U+61F8(1,3,8,9) +U+60AD(0);U+6173(1,3,8,9);U+6173(1,3,8,9) +U+60AE(0);U+8AA4(4,9);U+609E(7,8),U+8AA4(4,9),U+8BEF(4) +U+60AF(0);U+61AB(1,3,8,9);U+61AB(1,3,8,9) +U+60B0(0);U+60B0(0,9); +U+60B1(0);U+60B1(5,9); +U+60B2(0);U+60B2(5,9); +U+60B3(0);U+5FB7(2,3,8,9);U+5FB7(2,3,8,9),U+5FB3(0,2,3,8),U+60EA(2,3,4,8) +U+60B4(0);U+60B4(5,9);U+5FF0(3,8) +U+60B5(0);U+60B5(0,9);U+6005(1,3,8) +U+60B6(0);U+60B6(0,9);U+95F7(1,3,8) +U+60B7(0);U+60B7(0,9); +U+60B8(0);U+60B8(5,9);U+75F5(3,4,9) +U+60B9(0);U+60B9(3,9);U+60BA(3,9) +U+60BA(0);U+60BA(0,9);U+60B9(3,9) +U+60BB(0);U+60BB(5,9); +U+60BC(0);U+60BC(5,9); +U+60BD(0);U+60BD(0,9);U+51C4(2,9),U+6DD2(2,3,8,9) +U+60BE(0);U+60BE(0,9); +U+60BF(0);U+60BF(0,9); +U+60C0(0);U+60C0(0,9); +U+60C1(0);U+60C1(0,9); +U+60C2(0);U+60C2(0); +U+60C3(0);U+60C3(0,9); +U+60C4(0);U+60C4(3,9); +U+60C5(0);U+60C5(5,9); +U+60C6(0);U+60C6(5,9); +U+60C7(0);U+60C7(0,9); +U+60C8(0);U+60C8(4,9); +U+60C9(0);U+60C9(3,9); +U+60CA(0);U+9A5A(1,3,8,9);U+9A5A(1,3,8,9) +U+60CB(0);U+60CB(5,9); +U+60CC(0);U+60CC(0,9); +U+60CD(0);U+60CD(0,9); +U+60CE(0);U+60CE(0,9); +U+60CF(0);U+60CF(0,9); +U+60D0(0);U+60D0(3); +U+60D1(0);U+60D1(5,9); +U+60D3(0);U+60D3(0,9); +U+60D4(0);U+60D4(0,9); +U+60D5(0);U+60D5(5,9);U+6090(3,9) +U+60D7(0);U+60D7(0); +U+60D8(0);U+60D8(5,9); +U+60D9(0);U+60D9(0,9); +U+60DA(0);U+60DA(5,9); +U+60DB(0);U+60DB(3,9); +U+60DC(0);U+60DC(5,9); + +U+60DD(0);U+60DD(5,9); +U+60DF(0);U+60DF(5,9); +U+60E0(0);U+60E0(5,9);U+6075(4,8),U+6193(4,9) +U+60E1(0);U+60E1(0,9);U+5641(4,9),U+6076(1,3,8),U+60AA(3,8) +U+60E2(0);U+60E2(0,9); +U+60E4(0);U+60E4(0,9); +U+60E6(0);U+60E6(5,9); +U+60E7(0);U+61FC(1,3,8,9);U+61FC(1,3,8,9) +U+60E8(0);U+6158(1,3,8,9);U+6158(1,3,8,9) +U+60E9(0);U+61F2(1,3,8,9);U+61F2(1,3,8,9) +U+60EA(0);U+5FB7(4,8,9);U+5FB7(4,8,9),U+5FB3(0,3,4,8),U+60B3(2,3,4,8) +U+60EB(0);U+618A(1,3,8,9);U+618A(1,3,8,9) +U+60EC(0);U+611C(1,3,8,9);U+611C(1,3,8,9) +U+60ED(0);U+615A(1,3,8,9);U+6159(4),U+615A(1,3,8,9) +U+60EE(0);U+619A(1,3,8,9);U+619A(1,3,8,9) +U+60EF(0);U+6163(1,3,8,9);U+6163(1,3,8,9) +U+60F0(0);U+60F0(5,9); +U+60F1(0);U+60F1(0,9);U+607C(1,3,8) +U+60F2(0);U+60F2(0,9);U+607D(1,3,8) +U+60F3(0);U+60F3(5,9); +U+60F4(0);U+60F4(5,9); +U+60F5(0);U+60F5(0,9); +U+60F6(0);U+60F6(5,9); +U+60F7(0);U+60F7(0,9);U+8822(2,3,8,9) +U+60F8(0);U+60F8(0,9);U+8315(4),U+7162(1,3,4,8,9),U+712D(0,1,3,4,8) +U+60F9(0);U+60F9(5,9); +U+60FA(0);U+60FA(5,9); +U+60FB(0);U+60FB(0,9);U+607B(1,3,8) +U+60FC(0);U+60FC(0,9);U+890A(3,9) +U+60FE(0);U+60FE(0,9); +U+60FF(0);U+60FF(3,9); +U+6100(0);U+6100(5,9); +U+6101(0);U+6101(5,9); +U+6103(0);U+6103(0,9); +U+6104(0);U+6104(0,9);U+754F(4,9) +U+6105(0);U+6105(0,9); +U+6106(0);U+6106(5,9); +U+6108(0);U+6108(5,9),U+7652(2,8,9);U+7609(2,3,9),U+7652(2,8,9) +U+6109(0);U+6109(5,9); +U+610A(0);U+610A(0,9); +U+610B(0);U+610B(0,9);U+63F4(3,9) +U+610C(0);U+610C(0); +U+610D(0);U+610D(5,9);U+656F(4,9) +U+610E(0);U+610E(5,9); +U+610F(0);U+610F(5,9); +U+6110(0);U+6110(0,9); +U+6112(0);U+6112(3,9); +U+6113(0);U+6113(0,9); +U+6114(0);U+6114(0,9); +U+6115(0);U+6115(5,9); +U+6116(0);U+6116(0,9); +U+6117(0);U+6117(0); +U+6118(0);U+6118(0,9);U+606A(3,9) +U+6119(0);U+6119(4); +U+611A(0);U+611A(5,9); +U+611B(0);U+611B(0,9);U+7231(1,3,8) +U+611C(0);U+611C(0,9);U+60EC(1,3,8) +U+611D(0);U+611D(0,9); +U+611F(0);U+611F(5,9); +U+6120(0);U+614D(3,8,9);U+614D(3,8,9) +U+6122(0);U+6122(0); +U+6123(0);U+6123(5,9); +U+6124(0);U+61A4(1,3,8,9);U+61A4(1,3,8,9) + +U+6125(0);U+6125(0); +U+6126(0);U+6192(1,3,8,9);U+6192(1,3,8,9) +U+6127(0);U+6127(5,9);U+5ABF(2,3,8,9) +U+6128(0);U+6128(3,9);U+60AB(3),U+6164(3,8) +U+6129(0);U+6129(0,9); +U+612A(0);U+612A(0); +U+612B(0);U+612B(5,9); +U+612C(0);U+612C(0,9);U+8BC9(3),U+8A34(2,3,8,9) +U+612D(0);U+612D(0); +U+612E(0);U+612E(0,9); +U+612F(0);U+612F(0,9); +U+6130(0);U+6130(0); +U+6132(0);U+6132(0,9); +U+6134(0);U+6134(0,9);U+6006(1,3,8) +U+6136(0);U+6136(3,9); +U+6137(0);U+6137(0,9);U+607A(1,3,8) +U+613A(0);U+613A(0); +U+613B(0);U+613B(0,9);U+900A(3),U+905C(1,3,8,9) +U+613C(0);U+614E(4,8,9);U+614E(4,8,9),U+661A(2,3,4,8),U+7718(3,4,8) +U+613D(0);U+535A(2,3,8,9);U+535A(2,3,8,9) +U+613E(0);U+613E(0,9);U+5FFE(1,3,8) +U+613F(0);U+613F(1,3,9),U+9858(1,3,8,9);U+9858(1,3,8,9) +U+6140(0);U+6140(0,9); +U+6141(0);U+6141(0,9); +U+6142(0);U+607F(2,3,8,9);U+607F(2,3,8,9) +U+6143(0);U+6143(3); +U+6144(0);U+6144(4,9);U+6817(2,9) +U+6145(0);U+6145(3,9); +U+6146(0);U+6146(0,9); +U+6147(0);U+6147(3,9);U+6BB7(2,3,9) +U+6148(0);U+6148(5,9); +U+6149(0);U+6149(3,9); +U+614A(0);U+614A(5,9); +U+614B(0);U+614B(0,9);U+6001(1,3,8) +U+614C(0);U+614C(5,9); +U+614D(0);U+614D(0,9);U+6120(3,8) +U+614E(0);U+614E(5,9);U+613C(4,8),U+661A(2,3),U+7718(3) +U+614F(0);U+614F(0,9); +U+6150(0);U+6150(0); +U+6151(0);U+61FE(1,3,8,9);U+61FE(1,3,8,9),U+6174(4,9) +U+6152(0);U+6152(0,9); +U+6153(0);U+6153(0,9);U+527D(4,9) +U+6154(0);U+6154(0,9); +U+6155(0);U+6155(5,9); +U+6156(0);U+6156(0,9); +U+6157(0);U+6157(0); +U+6158(0);U+6158(0,9);U+60E8(1,3,8) +U+6159(0);U+615A(2,3,8,9);U+60ED(4),U+615A(2,3,8,9) +U+615A(0);U+615A(0,9);U+60ED(1,3,8),U+6159(2,3,8) +U+615B(0);U+615B(0,9); +U+615C(0);U+615C(0); +U+615D(0);U+615D(5,9); +U+615E(0);U+615E(0,9); +U+615F(0);U+615F(0,9);U+6078(1,3,8),U+6185(3,8) +U+6161(0);U+6161(0,9);U+723D(3,9) +U+6162(0);U+6162(5,9); +U+6163(0);U+6163(0,9);U+60EF(1,3,8) +U+6164(0);U+6128(3,8,9);U+60AB(1,3,8),U+6128(3,8,9) +U+6165(0);U+6165(0,9); +U+6166(0);U+6166(0,9); +U+6167(0);U+6167(5,9);U+8B7F(3,9) +U+6168(0);U+6168(5,9); +U+6169(0);U+6169(0); + +U+616A(0);U+616A(0,9);U+6004(1,3,8) +U+616B(0);U+616B(0,9);U+6002(1,3,8) +U+616C(0);U+616C(3,9); +U+616D(0);U+6196(3,8,9);U+6196(3,8,9) +U+616E(0);U+616E(0,9);U+8651(1,3,8) +U+6170(0);U+6170(5,9); +U+6171(0);U+6171(0,9); +U+6172(0);U+6172(0,9); +U+6173(0);U+6173(0,9);U+60AD(1,3,8) +U+6174(0);U+6174(0,9);U+6151(4),U+61FE(1,3,4,8,9) +U+6175(0);U+6175(5,9);U+5ADE(4,9) +U+6176(0);U+6176(0,9);U+5E86(1,3,8) +U+6177(0);U+6177(5,9); +U+6178(0);U+6178(0); +U+6179(0);U+6179(0,9); +U+617A(0);U+617A(0,9); +U+617C(0);U+617C(3,9); +U+617E(0);U+617E(0,9);U+6B32(2,8,9) +U+6180(0);U+6180(0,9); +U+6181(0);U+6181(3); +U+6182(0);U+6182(0,9);U+5FE7(1,3,8) +U+6183(0);U+6183(0,9); +U+6184(0);U+6184(0); +U+6185(0);U+615F(3,8,9);U+6078(3),U+615F(3,8,9) +U+6187(0);U+61A9(2,3,8,9);U+61A9(2,3,8,9) +U+6188(0);U+6188(0); +U+6189(0);U+6189(0,9); +U+618A(0);U+618A(0,9);U+60EB(1,3,8) +U+618B(0);U+618B(5,9);U+522B(3),U+5F46(3,9),U+5225(0,3,4,8,9) +U+618C(0);U+618C(0,9); +U+618D(0);U+618D(0,9);U+9A84(3),U+9A55(1,3,8,9) +U+618E(0);U+618E(5,9); +U+618F(0);U+618F(0); +U+6190(0);U+6190(0,9);U+601C(1,3,8,9) +U+6191(0);U+6191(0,9);U+51ED(1,3,8),U+51F4(2,8) +U+6192(0);U+6192(0,9);U+6126(1,3,8) +U+6193(0);U+6193(0,9);U+60E0(4,9),U+6075(0,4,8) +U+6194(0);U+6194(5,9); +U+6195(0);U+6195(0); +U+6196(0);U+6196(0,9);U+616D(3,8) +U+6198(0);U+6198(0); +U+6199(0);U+559C(3,8,9);U+559C(3,8,9) +U+619A(0);U+619A(0,9);U+60EE(1,3,8) +U+619B(0);U+619B(0,9); +U+619D(0);U+619D(5,9);U+8B48(3,9) +U+619E(0);U+619E(3); +U+619F(0);U+619F(0,9); +U+61A0(0);U+61A0(0); +U+61A1(0);U+61A1(0,9); +U+61A2(0);U+61A2(0,9); +U+61A3(0);U+61A3(0); +U+61A4(0);U+61A4(0,9);U+6124(1,3,8) +U+61A5(0);U+61A5(3); +U+61A6(0);U+61A6(0); +U+61A7(0);U+61A7(5,9); +U+61A8(0);U+61A8(5,9); +U+61A9(0);U+61A9(5,9);U+6187(2,3,8) +U+61AA(0);U+61AA(0,9); +U+61AB(0);U+61AB(0,9);U+60AF(1,3,8) +U+61AC(0);U+61AC(5,9); +U+61AD(0);U+61AD(0,9); +U+61AE(0);U+61AE(0,9);U+6003(1,3,8) +U+61AF(0);U+61AF(0,9); + +U+61B0(0);U+61B0(0,9); +U+61B1(0);U+61B1(0,9); +U+61B2(0);U+61B2(0,9);U+5BAA(1,3,8) +U+61B3(0);U+61B3(0,9); +U+61B4(0);U+61B4(0,9); +U+61B5(0);U+61B5(0,9); +U+61B6(0);U+61B6(0,9);U+5FC6(1,3,8) +U+61B7(0);U+61B7(5); +U+61B8(0);U+61B8(0,9); +U+61BA(0);U+61BA(0,9); +U+61BC(0);U+61BC(0,9);U+5106(3,9) +U+61BD(0);U+61BD(0); +U+61BE(0);U+61BE(5,9); +U+61BF(0);U+61BF(0,9); +U+61C0(0);U+61C0(0); +U+61C1(0);U+61C1(0,9); +U+61C2(0);U+61C2(5,9); +U+61C3(0);U+61C3(0,9);U+52E4(2,3,8,9),U+763D(2,3,8,9) +U+61C4(0);U+61C4(0); +U+61C5(0);U+61C5(0,9); +U+61C6(0);U+61C6(0,9); +U+61C7(0);U+61C7(0,9);U+6073(1,3,8) +U+61C8(0);U+61C8(5,9); +U+61C9(0);U+61C9(0,1,3,4,9);U+5E94(1,3,4,8),U+5FDC(4,8),U+8B4D(3) +U+61CA(0);U+61CA(5,9); +U+61CB(0);U+61CB(5,9); +U+61CC(0);U+61CC(0,9);U+603F(1,3,8) +U+61CD(0);U+61CD(0,9);U+61D4(4,8) +U+61CE(0);U+61CE(0); +U+61CF(0);U+61CF(0); +U+61D0(0);U+61F7(3,8,9);U+61F7(3,8,9),U+6000(3,9),U+8922(3,9),U+8931(3,9) +U+61D1(0);U+61E3(1,3,8,9);U+61E3(1,3,8,9) +U+61D2(0);U+61F6(1,3,8,9);U+61F6(1,3,8,9),U+5B3E(4,9) +U+61D4(0);U+61CD(4,8,9);U+61CD(4,8,9) +U+61D6(0);U+61D6(0,9); +U+61D7(0);U+61D7(0); +U+61D8(0);U+61D8(3,9); +U+61D9(0);U+61D9(0); +U+61DA(0);U+61DA(0); +U+61DB(0);U+61DB(0); +U+61DC(0);U+61DC(3); +U+61DD(0);U+61DD(0); +U+61DE(0);U+61DE(0,9);U+8499(1,8,9),U+6FDB(1,3,4,8,9),U+77C7(1,4,8,9) +U+61DF(0);U+61DF(0,9);U+603C(1,3,8) +U+61E0(0);U+61E0(0,9); +U+61E1(0);U+61E1(0); +U+61E2(0);U+61E2(0); +U+61E3(0);U+61E3(0,9);U+61D1(1,3,8) +U+61E4(0);U+61E4(0,9); +U+61E5(0);U+61E5(0,9); +U+61E6(0);U+61E6(5,9);U+61E7(3,9) +U+61E7(0);U+61E7(0,9);U+61E6(3,9) +U+61E8(0);U+61E8(0,9);U+6079(1,3,8) +U+61E9(0);U+61E9(0,9); +U+61EA(0);U+61EA(0,9); +U+61EB(0);U+61EB(0,9); +U+61ED(0);U+61ED(0,9); +U+61EE(0);U+61EE(0,9); +U+61F0(0);U+61F0(0,9); +U+61F1(0);U+61F1(0,9); +U+61F2(0);U+61F2(0,9);U+60E9(1,3,8) +U+61F3(0);U+61F3(0); +U+61F5(0);U+61F5(5,9); + +U+61F6(0);U+61F6(0,9);U+61D2(1,3,8),U+5B3E(2,3,8,9) +U+61F7(0);U+61F7(0,9);U+61D0(3,8),U+6000(1,3,8,9),U+8922(1,3,8,9),U+8931(1,3,8,9) +U+61F8(0);U+61F8(0,9);U+60AC(1,3,8) +U+61F9(0);U+61F9(0,9); +U+61FA(0);U+61FA(0,9);U+5FCF(1,3,8,9) +U+61FB(0);U+61FB(0,9); +U+61FC(0);U+61FC(0,9);U+60E7(1,3,8) +U+61FD(0);U+61FD(0,9);U+6B22(4),U+6B61(2,3,8,9),U+6B53(3,4),U+8B99(4,9),U+9A69(4,9) +U+61FE(0);U+61FE(0,9);U+6151(1,3,8),U+6174(1,3,4,8,9) +U+61FF(0);U+61FF(5,9); +U+6200(0);U+6200(0,9);U+604B(1,3,8) +U+6201(0);U+6201(3,9); +U+6202(0);U+6202(0); +U+6203(0);U+6203(0,9); +U+6204(0);U+6204(0,9); +U+6206(0);U+6207(1,3,8,9);U+6207(1,3,8,9) +U+6207(0);U+6207(0,9);U+6206(1,3,8) +U+6208(0);U+6208(5,9); +U+6209(0);U+6209(0,9); +U+620A(0);U+620A(5,9); +U+620B(0);U+6214(1,3,8,9);U+6214(1,3,8,9) +U+620C(0);U+620C(5,9); +U+620D(0);U+620D(5,9); +U+620E(0);U+620E(5,9); +U+620F(0);U+6232(1,3,8,9);U+6231(4),U+6232(1,3,8,9),U+622F(4) +U+6210(0);U+6210(5,9); +U+6211(0);U+6211(5,9); +U+6212(0);U+6212(5,9); +U+6213(0);U+6213(0); +U+6214(0);U+6214(0,9);U+620B(1,3,8) +U+6215(0);U+6215(5,9); +U+6216(0);U+6216(5,9); +U+6217(0);U+6227(1,3,8,9);U+6227(1,3,8,9) +U+6218(0);U+6230(1,3,8,9);U+6230(1,3,8,9),U+6226(4) +U+6219(0);U+6219(0,9); +U+621A(0);U+621A(5,9); +U+621B(0);U+621B(5,9);U+621E(2,3,8) +U+621C(0);U+621C(0); +U+621D(0);U+8CCA(3,8,9);U+8CCA(3,8,9),U+8D3C(3) +U+621E(0);U+621B(2,3,8,9);U+621B(2,3,8,9) +U+621F(0);U+621F(5,9); +U+6220(0);U+6220(0,9); +U+6221(0);U+6221(5,9); +U+6222(0);U+6222(5,9); +U+6223(0);U+6223(3,9); +U+6224(0);U+6224(5,9); +U+6225(0);U+6225(5,9); +U+6226(0);U+6230(4,8,9);U+6218(4),U+6230(4,8,9) +U+6227(0);U+6227(0,9);U+6217(1,3,8) +U+6228(0);U+6228(0); +U+6229(0);U+6229(0,9);U+622C(4,8) +U+622A(0);U+622A(5,9); +U+622B(0);U+622B(0,9); +U+622C(0);U+6229(4,8,9);U+6229(4,8,9) +U+622D(0);U+622D(0,9); +U+622E(0);U+622E(5,9); +U+622F(0);U+6232(2,3,8,9);U+620F(4),U+6231(4),U+6232(2,3,8,9) +U+6230(0);U+6230(0,9);U+6218(1,3,8),U+6226(4,8) +U+6231(0);U+6232(4,8,9);U+620F(4),U+622F(4),U+6232(4,8,9) +U+6232(0);U+6232(0,9);U+620F(1,3,8),U+622F(2,3,8),U+6231(4,8) +U+6233(0);U+6233(5,9); +U+6234(0);U+6234(5,9); +U+6236(0);U+6236(0,9);U+6237(4,8),U+6238(8) + +U+6237(0);U+6236(4,8,9);U+6236(4,8,9),U+6238(4) +U+6238(0);U+6236(8,9);U+6237(4),U+6236(8,9) +U+623A(0);U+623A(0,9); +U+623B(0);U+623E(4,8,9);U+623E(4,8,9),U+76ED(4,8,9) +U+623C(0);U+536F(2,3,8,9);U+536F(2,3,8,9),U+5918(2,3,8) +U+623D(0);U+623D(5,9); +U+623E(0);U+623E(5,9);U+623B(4,8),U+76ED(4,9) +U+623F(0);U+623F(5,9); +U+6240(0);U+6240(5,9); +U+6241(0);U+6241(5,9); +U+6242(0);U+6242(0,9); +U+6243(0);U+6243(5,9); +U+6244(0);U+6244(0); +U+6245(0);U+6245(0); +U+6246(0);U+6246(0,9); +U+6247(0);U+6247(5,9);U+6427(4,9) +U+6248(0);U+6248(5,9); +U+6249(0);U+6249(5,9); +U+624A(0);U+624A(0,9); +U+624B(0);U+624B(5,9); +U+624C(0);U+624C(5); +U+624D(0);U+624D(1,3,9),U+7E94(1,3,9);U+7E94(1,3,9) +U+624E(0);U+624E(4,9),U+7D2E(2,8,9);U+5273(4),U+5284(4,9),U+672D(3,9),U+7B9A(4),U+7D25(2),U+7D2E(2,8,9) + +U+624F(0);U+624F(0); +U+6250(0);U+6250(3,9); +U+6251(0);U+6251(1,3,9),U+64B2(1,3,8,9);U+64B2(1,3,8,9),U+6534(3) +U+6252(0);U+6252(5,9); +U+6253(0);U+6253(5,9); +U+6254(0);U+6254(5,9); +U+6255(0);U+62C2(4,8,9);U+62C2(4,8,9) +U+6256(0);U+6256(0); +U+6258(0);U+6258(4,9),U+8A17(2,4,9);U+8A17(2,4,9),U+8BAC(4) +U+6259(0);U+6259(0,9); +U+625A(0);U+625A(0,9); +U+625B(0);U+625B(5,9);U+6443(2,3,8,9) +U+625C(0);U+625C(0,9); +U+625D(0);U+625D(0); +U+625E(0);U+625E(0,9);U+634D(2,3,8,9),U+64C0(3,8) +U+625F(0);U+625F(0); +U+6260(0);U+6260(3,9);U+640B(3,8,9) +U+6261(0);U+6261(0,9); +U+6262(0);U+6262(0,9); +U+6263(0);U+6263(5,9),U+91E6(2,9);U+91E6(2,9) +U+6264(0);U+6264(0,9); +U+6265(0);U+6265(0,9); +U+6266(0);U+6266(5,9); +U+6267(0);U+57F7(1,3,8,9);U+57F7(1,3,8,9),U+74E1(3,9) +U+6268(0);U+6268(0); +U+6269(0);U+64F4(1,3,8,9);U+62E1(4),U+64F4(1,3,8,9) +U+626A(0);U+636B(1,3,8,9);U+636B(1,3,8,9) +U+626B(0);U+6383(1,3,8,9);U+6383(1,3,8,9) +U+626C(0);U+63DA(1,3,8,9);U+63DA(1,3,8,9),U+98BA(4,9),U+98CF(4) +U+626D(0);U+626D(5,9); +U+626E(0);U+626E(5,9); +U+626F(0);U+626F(5,9);U+64A6(2,3,8,9) +U+6270(0);U+64FE(1,3,8,9);U+64FE(1,3,8,9) +U+6271(0);U+6271(3,9); +U+6272(0);U+6272(0,9); +U+6273(0);U+6273(5,9); +U+6274(0);U+6274(0,9); +U+6275(0);U+65BC(3,9);U+65BC(3,9),U+4E8E(3,4,5,8,9) +U+6276(0);U+6276(5,9); + +U+6277(0);U+6277(0,9); +U+6278(0);U+6278(0); +U+6279(0);U+6279(5,9); +U+627A(0);U+627A(3,9);U+62B5(3,8,9),U+89DD(3,9),U+7274(2,3,8,9),U+7F9D(2,3,8,9) +U+627B(0);U+627B(0,9); +U+627C(0);U+627C(5,9);U+6424(2,3,9),U+6439(3,9) +U+627D(0);U+627D(3,9); +U+627E(0);U+627E(5,9); +U+627F(0);U+627F(5,9); +U+6280(0);U+6280(5,9); +U+6281(0);U+6281(3,9); +U+6283(0);U+6283(0,9);U+62DA(3,8,9) +U+6284(0);U+6284(5,9); +U+6285(0);U+6285(0); +U+6286(0);U+6286(3,9); +U+6287(0);U+6287(0,9); +U+6288(0);U+6288(0,9); +U+6289(0);U+6289(5,9);U+5214(7,8) +U+628A(0);U+628A(5,9); +U+628B(0);U+628B(0); +U+628C(0);U+628C(4,9);U+4F14(4,9) +U+628E(0);U+628E(0,9); +U+628F(0);U+628F(0,9); +U+6290(0);U+6290(0); +U+6291(0);U+6291(5,9); +U+6292(0);U+6292(5,9); +U+6293(0);U+6293(5,9); +U+6294(0);U+6294(3,9); +U+6295(0);U+6295(5,9); +U+6296(0);U+6296(5,9); +U+6297(0);U+6297(5,9); +U+6298(0);U+6298(1,3,9),U+647A(1,3,4,9);U+647A(1,3,4,9) +U+6299(0);U+6299(0); +U+629A(0);U+64AB(1,3,8,9);U+64AB(1,3,8,9),U+62CA(1,3,8,9) +U+629B(0);U+62CB(4,8,9);U+62CB(4,8,9) +U+629C(0);U+62D4(4,8,9);U+62D4(4,8,9) +U+629E(0);U+64C7(8,9);U+62E9(4),U+64C7(8,9) +U+629F(0);U+6476(1,3,8,9);U+6476(1,3,8,9) +U+62A0(0);U+6473(1,3,8,9);U+6473(1,3,8,9) +U+62A1(0);U+6384(1,3,8,9);U+6384(1,3,8,9) +U+62A2(0);U+6436(1,3,8,9);U+6436(1,3,8,9) +U+62A3(0);U+62A3(0); +U+62A4(0);U+8B77(1,3,8,9);U+8B77(1,3,8,9) +U+62A5(0);U+5831(1,3,8,9);U+5831(1,3,8,9) +U+62A7(0);U+62A7(0); +U+62A8(0);U+62A8(5,9); +U+62A9(0);U+62A9(0,9); +U+62AA(0);U+62AA(0,9); +U+62AB(0);U+62AB(5,9); +U+62AC(0);U+62AC(5,9); +U+62AD(0);U+62AD(0,9);U+8200(4,9) +U+62AE(0);U+62AE(0,9); +U+62AF(0);U+62AF(3,9); +U+62B0(0);U+62B0(0,9); +U+62B1(0);U+62B1(5,9); +U+62B2(0);U+62B2(3); +U+62B3(0);U+62B3(0,9); +U+62B4(0);U+62B4(0,9); +U+62B5(0);U+62B5(5,9),U+89DD(2,9);U+627A(3,8,9),U+7274(2,3,9),U+89DD(2,9),U+7F9D(2,3,8,9) + +U+62B6(0);U+62B6(0,9); +U+62B7(0);U+62B7(0); +U+62B8(0);U+62B8(0,9); + +U+62B9(0);U+62B9(5,9); +U+62BA(0);U+62BA(0); +U+62BB(0);U+62BB(5,9);U+4F38(3,8,9) +U+62BC(0);U+62BC(5,9); +U+62BD(0);U+62BD(5,9); +U+62BE(0);U+62BE(0,9); +U+62BF(0);U+62BF(5,9); +U+62C0(0);U+62C0(0); +U+62C1(0);U+62C1(0); +U+62C2(0);U+62C2(5,9);U+6255(4,8) +U+62C3(0);U+62C3(3); +U+62C4(0);U+62C4(5,9); +U+62C5(0);U+64D4(1,3,4,8,9);U+64D4(1,3,4,8,9) +U+62C6(0);U+62C6(5,9); +U+62C7(0);U+62C7(5,9); +U+62C8(0);U+62C8(5,9); +U+62C9(0);U+62C9(5,9); +U+62CA(0);U+62CA(5,9);U+64AB(3,8,9),U+629A(1,3,8) +U+62CB(0);U+62CB(0,9);U+629B(4,8) +U+62CC(0);U+62CC(5,9); +U+62CD(0);U+62CD(5,9); +U+62CE(0);U+62CE(5,9); +U+62CF(0);U+62CF(3,9);U+62FF(2,3,9) +U+62D0(0);U+62D0(4,9),U+67B4(4,8,9);U+67B4(4,8,9) +U+62D1(0);U+62D1(0,9);U+94B3(4),U+9257(1,3,4,8,9),U+7B9D(0,1,3,4,5,8,9) +U+62D2(0);U+62D2(5,9); +U+62D3(0);U+62D3(5,9);U+646D(3,8,9) +U+62D4(0);U+62D4(5,9);U+629C(4,8) +U+62D5(0);U+62D6(2,3,8,9);U+62D6(2,3,8,9) +U+62D6(0);U+62D6(5,9);U+62D5(2,3,8) +U+62D7(0);U+62D7(5,9); +U+62D8(0);U+62D8(5,9); +U+62D9(0);U+62D9(5,9); +U+62DA(0);U+62DA(5,9);U+6283(3,8,9) +U+62DB(0);U+62DB(5,9); +U+62DC(0);U+62DC(5,9);U+62DD(4,8) +U+62DD(0);U+62DC(4,8,9);U+62DC(4,8,9) +U+62DF(0);U+64EC(1,3,8,9);U+5117(4,9),U+64EC(1,3,8,9) +U+62E0(0);U+636E(3,9);U+636E(3,9),U+64DA(3,8,9) +U+62E1(0);U+64F4(4,8,9);U+6269(4),U+64F4(4,8,9) +U+62E2(0);U+650F(1,3,8,9);U+650F(1,3,8,9) +U+62E3(0);U+63C0(1,3,8,9);U+63C0(1,3,8,9) +U+62E4(0);U+62E4(0); +U+62E5(0);U+64C1(1,3,8,9);U+64C1(1,3,8,9) +U+62E6(0);U+6514(1,3,8,9);U+6514(1,3,8,9) +U+62E7(0);U+64F0(1,3,8,9);U+64F0(1,3,8,9) +U+62E8(0);U+64A5(1,3,8,9);U+64A5(1,3,8,9) +U+62E9(0);U+64C7(1,3,8,9);U+629E(4),U+64C7(1,3,8,9) +U+62EB(0);U+62EB(3,9); +U+62EC(0);U+62EC(5,9); +U+62ED(0);U+62ED(5,9); +U+62EE(0);U+62EE(5,9); +U+62EF(0);U+62EF(5,9); +U+62F0(0);U+62F0(0,9); +U+62F1(0);U+62F1(5,9); +U+62F2(0);U+62F2(0,9); +U+62F3(0);U+62F3(5,9); +U+62F4(0);U+62F4(5,9); +U+62F5(0);U+62F5(0,9); +U+62F6(0);U+62F6(5,9); +U+62F7(0);U+62F7(5,9); +U+62F8(0);U+62F8(3,9); +U+62F9(0);U+62F9(3,9); + +U+62FA(0);U+62FA(0,9); +U+62FB(0);U+62FB(0,9);U+8C57(3,9) +U+62FC(0);U+62FC(5,9); +U+62FD(0);U+62FD(5,9);U+6359(4,9) +U+62FE(0);U+62FE(5,9); +U+62FF(0);U+62FF(5,9);U+62CF(2,3,9) +U+6300(0);U+6300(0,9); +U+6301(0);U+6301(5,9); +U+6302(0);U+639B(2,3,8,9);U+639B(2,3,8,9),U+7F63(4,9) +U+6303(0);U+6303(3,9); +U+6304(0);U+6304(0); +U+6305(0);U+6305(0);U+6306(3,4,8) +U+6306(0);U+6306(4);U+6305(3,4,8) +U+6307(0);U+6307(5,9); +U+6308(0);U+6308(5,9); +U+6309(0);U+6309(5,9); +U+630B(0);U+630B(0,9); +U+630C(0);U+630C(0,9); +U+630D(0);U+630D(0,9);U+6821(3,9) +U+630E(0);U+630E(5,9); +U+630F(0);U+630F(0,9); +U+6310(0);U+6310(0,9); +U+6311(0);U+6311(5,9); +U+6312(0);U+6312(0); +U+6313(0);U+6313(0,9); +U+6314(0);U+6314(0,9); +U+6315(0);U+6315(0,9);U+6444(3),U+651D(1,3,8,9) +U+6316(0);U+6316(5,9);U+7A75(3,9) +U+6318(0);U+6318(0); +U+6319(0);U+8209(4,8,9);U+4E3E(4),U+8209(4,8,9),U+64E7(4) +U+631A(0);U+646F(1,3,8,9);U+646F(1,3,8,9) +U+631B(0);U+6523(1,3,8,9);U+6523(1,3,8,9) +U+631C(0);U+6397(1,3,8,9);U+6397(1,3,8,9) +U+631D(0);U+64BE(1,3,8,9);U+64BE(1,3,8,9) +U+631E(0);U+64BB(1,3,8,9);U+64BB(1,3,8,9) +U+631F(0);U+633E(1,3,8,9);U+633E(1,3,8,9) +U+6320(0);U+6493(1,3,8,9);U+6493(1,3,8,9) +U+6321(0);U+64CB(1,3,8,9);U+64CB(1,3,8,9) +U+6322(0);U+649F(1,3,8,9);U+649F(1,3,8,9),U+8B51(4,9) +U+6323(0);U+6399(4,8,9);U+6399(4,8,9) +U+6324(0);U+64E0(1,3,8,9);U+64E0(1,3,8,9) +U+6325(0);U+63EE(1,3,8,9);U+63EE(1,3,8,9) +U+6326(0);U+648F(1,3,8,9);U+648F(1,3,8,9) +U+6327(0);U+6327(0); +U+6328(0);U+6328(5,9); +U+6329(0);U+6329(0,9);U+635D(7,8) +U+632A(0);U+632A(5,9); +U+632B(0);U+632B(5,9); +U+632C(0);U+632C(0,9); +U+632D(0);U+632D(0,9); +U+632E(0);U+632E(0); +U+632F(0);U+632F(5,9); +U+6330(0);U+6330(0); +U+6332(0);U+6332(5,9); +U+6333(0);U+6333(0,9);U+647C(3) +U+6334(0);U+6334(0,9); +U+6336(0);U+6336(3,9); +U+6338(0);U+6338(0,9); +U+6339(0);U+6339(5,9); +U+633A(0);U+633A(5,9); +U+633B(0);U+633B(0,9); +U+633C(0);U+633C(0,9); +U+633D(0);U+633D(5,9),U+8F13(2,3,9);U+8F13(2,3,9) + +U+633E(0);U+633E(0,9);U+631F(1,3,8) +U+6340(0);U+6340(0,9); +U+6341(0);U+6341(0,9);U+6405(3),U+64B9(3,4),U+652A(1,3,8,9) +U+6342(0);U+6440(3,9);U+6440(3,9) +U+6343(0);U+6343(5,9); +U+6344(0);U+6344(0,9); +U+6345(0);U+6345(5,9); +U+6346(0);U+6346(5,9),U+7D91(2,3,8,9);U+7D91(2,3,8,9) +U+6347(0);U+6347(0,9); +U+6348(0);U+6348(0,9);U+6445(3),U+6504(1,3,8,9) +U+6349(0);U+6349(5,9); +U+634A(0);U+634A(3,9); +U+634B(0);U+634B(5,9); +U+634C(0);U+634C(5,9);U+516B(3,8,9) +U+634D(0);U+634D(5,9);U+625E(2,3,8,9),U+64C0(8) +U+634E(0);U+634E(5,9); +U+634F(0);U+634F(5,9); +U+6350(0);U+6350(5,9); +U+6351(0);U+6351(0,9); +U+6352(0);U+6352(0); +U+6353(0);U+6353(0); +U+6354(0);U+6354(3,9); +U+6355(0);U+6355(5,9); +U+6356(0);U+6356(0,9); +U+6357(0);U+6357(0,9); +U+6358(0);U+6358(0,9); +U+6359(0);U+6359(0,9);U+62FD(4,9) +U+635A(0);U+635A(0,9); +U+635C(0);U+641C(4,8,9);U+641C(4,8,9),U+9A2A(3,4,8,9) +U+635D(0);U+6329(7,8,9);U+6329(7,8,9) +U+635E(0);U+6488(1,3,8,9);U+6488(1,3,8,9) +U+635F(0);U+640D(1,3,8,9);U+640D(1,3,8,9) +U+6360(0);U+6360(0); +U+6361(0);U+64BF(1,3,8,9);U+64BF(1,3,8,9) +U+6362(0);U+63DB(4,8,9);U+63DB(4,8,9) +U+6363(0);U+6417(1,3,8,9);U+6417(1,3,8,9),U+64E3(4,9) +U+6364(0);U+6364(0); +U+6365(0);U+6365(0,9); +U+6366(0);U+6366(4); +U+6367(0);U+6367(5,9); +U+6368(0);U+6368(0,9);U+820D(1,3,8,9),U+820E(1,3,4,8) +U+6369(0);U+6369(5,9); +U+636A(0);U+636A(0); +U+636B(0);U+636B(0,9);U+626A(1,3,8) +U+636C(0);U+636C(0); +U+636D(0);U+636D(5,9); +U+636E(0);U+64DA(1,3,8,9);U+62E0(3),U+64DA(1,3,8,9) +U+636F(0);U+636F(0,9); +U+6370(0);U+6370(3,9); +U+6371(0);U+6371(5,9); +U+6372(0);U+6372(0,9);U+5377(1,3,8,9),U+5DFB(1,3,4,8) +U+6373(0);U+6373(0); +U+6374(0);U+7E3D(4,8,9);U+603B(4),U+7E3D(4,8,9),U+6403(3,4),U+6460(3,4,9),U+7DCF(3,4),U+7E02(4) + +U+6375(0);U+6375(0,9); +U+6376(0);U+6376(5,9);U+6425(2,8,9) +U+6377(0);U+6377(5,9); +U+6378(0);U+6378(0,9); +U+6379(0);U+6379(0); +U+637A(0);U+637A(5,9);U+933C(4,9) +U+637B(0);U+637B(5,9);U+649A(4,9) +U+637C(0);U+637C(3,9); +U+637D(0);U+637D(0,9); + +U+637E(0);U+637E(0); +U+6380(0);U+6380(5,9); +U+6381(0);U+6381(4,9); +U+6382(0);U+6382(5,9); +U+6383(0);U+6383(0,9);U+626B(1,3,8) +U+6384(0);U+6384(0,9);U+62A1(1,3,8) +U+6385(0);U+6385(0,9); +U+6386(0);U+6386(0);U+39CF(1,3) +U+6387(0);U+6387(5,9); +U+6388(0);U+6388(5,9); +U+6389(0);U+6389(5,9); +U+638A(0);U+638A(5,9); +U+638C(0);U+638C(5,9); +U+638D(0);U+638D(0,9); +U+638E(0);U+638E(5,9); +U+638F(0);U+638F(5,9);U+642F(2,3,8,9) +U+6390(0);U+6390(5,9); +U+6391(0);U+6391(0,9); +U+6392(0);U+6392(5,9); +U+6394(0);U+6394(0,9); +U+6395(0);U+6395(3); +U+6396(0);U+6396(5,9); +U+6397(0);U+6397(0,9);U+631C(1,3,8) +U+6398(0);U+6398(5,9);U+6485(3,8,9) +U+6399(0);U+6399(0,9);U+6323(4,8) +U+639A(0);U+639A(0); +U+639B(0);U+639B(0,9);U+6302(2,3,8,9),U+7F63(2,3,4,8,9) +U+639C(0);U+639C(0,9); +U+639D(0);U+639D(0,9); +U+639E(0);U+639E(0,9); +U+639F(0);U+639F(0,9); +U+63A0(0);U+63A0(5,9); +U+63A1(0);U+63A1(0,9);U+91C7(2,3,9) +U+63A2(0);U+63A2(5,9); +U+63A3(0);U+63A3(5,9); +U+63A4(0);U+63A4(0,9); +U+63A5(0);U+63A5(5,9); +U+63A6(0);U+63A6(0); +U+63A7(0);U+63A7(5,9); +U+63A8(0);U+63A8(5,9); +U+63A9(0);U+63A9(5,9); +U+63AA(0);U+63AA(5,9); +U+63AB(0);U+63AB(3,9); +U+63AC(0);U+63AC(5,9);U+530A(3,9) +U+63AD(0);U+63AD(5,9); +U+63AE(0);U+63AE(5,9); +U+63AF(0);U+63AF(0,9); +U+63B0(0);U+63B0(5,9); +U+63B1(0);U+63B1(0,9); +U+63B2(0);U+63ED(4,8,9);U+63ED(4,8,9) +U+63B3(0);U+64C4(1,3,8,9);U+64C4(1,3,8,9) +U+63B4(0);U+6451(1,3,8,9);U+6451(1,3,8,9) +U+63B5(0);U+63B5(0); +U+63B6(0);U+63B6(0); +U+63B7(0);U+64F2(1,3,8,9);U+64F2(1,3,8,9) +U+63B8(0);U+64A3(1,3,8,9);U+64A3(1,3,8,9) +U+63B9(0);U+63B9(4); +U+63BA(0);U+647B(1,3,8,9);U+647B(1,3,8,9) +U+63BC(0);U+645C(1,3,8,9);U+645C(1,3,8,9) +U+63BD(0);U+63BD(0,9);U+78B0(2,9),U+8E2B(2,3,9) +U+63BE(0);U+63BE(5,9); +U+63BF(0);U+63BF(0); +U+63C0(0);U+63C0(0,9);U+62E3(1,3,8) + +U+63C1(0);U+63C1(0); +U+63C2(0);U+63C2(0,9); +U+63C3(0);U+63C3(0,9); +U+63C4(0);U+63C4(5,9); +U+63C5(0);U+63C5(0,9);U+7814(3,9) +U+63C6(0);U+63C6(5,9);U+6951(3,9) +U+63C7(0);U+63C7(0,9); +U+63C8(0);U+63C8(0,9); +U+63C9(0);U+63C9(5,9); +U+63CA(0);U+63CA(3,9); +U+63CB(0);U+63CB(0,9); +U+63CC(0);U+63CC(0,9); +U+63CD(0);U+63CD(5,9); +U+63CE(0);U+63CE(5,9); +U+63CF(0);U+63CF(5,9); +U+63D0(0);U+63D0(5,9); +U+63D2(0);U+63D2(5,9);U+63F7(2,8) +U+63D3(0);U+63D3(0,9); +U+63D4(0);U+63D4(3); +U+63D5(0);U+63D5(0,9); +U+63D6(0);U+63D6(5,9); +U+63D7(0);U+63D7(0,9); +U+63D8(0);U+63D8(0,9); +U+63D9(0);U+63D9(0,9); +U+63DA(0);U+63DA(0,9);U+626C(1,3,8),U+98BA(2,9),U+98CF(1,3,4,8) +U+63DB(0);U+63DB(0,9);U+6362(4,8) +U+63DC(0);U+63DC(3,9); +U+63DD(0);U+63DD(0,9); +U+63DE(0);U+63DE(5); +U+63DF(0);U+63DF(0,9); +U+63E0(0);U+63E0(5,9); +U+63E1(0);U+63E1(5,9); +U+63E2(0);U+63E2(3); +U+63E3(0);U+63E3(5,9); +U+63E4(0);U+63E4(0,9); +U+63E5(0);U+63E5(0,9); +U+63E6(0);U+63E6(0); +U+63E7(0);U+63E7(0,9); +U+63E8(0);U+63E8(0,9); +U+63E9(0);U+63E9(5,9); +U+63EA(0);U+63EA(5,9);U+63EB(2,3,9) +U+63EB(0);U+63EB(0,9);U+63EA(2,3,9) +U+63EC(0);U+63EC(0); +U+63ED(0);U+63ED(5,9);U+63B2(4,8) +U+63EE(0);U+63EE(0,9);U+6325(1,3,8) +U+63EF(0);U+63EF(0,9);U+6404(4,8) +U+63F0(0);U+63F0(0,9); +U+63F1(0);U+63F1(3,9); +U+63F2(0);U+63F2(5,9); +U+63F3(0);U+63F3(0,9); +U+63F4(0);U+63F4(5,9);U+610B(3,9) +U+63F5(0);U+63F5(0,9); +U+63F6(0);U+63F6(5,9); +U+63F7(0);U+63D2(2,8,9);U+63D2(2,8,9) +U+63F8(0);U+63F8(5); +U+63F9(0);U+63F9(0,9);U+80CC(2,3,9),U+505D(0,2,3,9) +U+63FA(0);U+6416(8,9);U+6416(8,9),U+6447(4) +U+63FB(0);U+63FB(0); +U+63FC(0);U+63FC(0); +U+63FD(0);U+652C(1,3,8,9);U+652C(1,3,8,9) +U+63FE(0);U+6435(4,8,9);U+6435(4,8,9) +U+63FF(0);U+64B3(1,3,8,9);U+64B3(1,3,8,9) +U+6400(0);U+6519(1,3,8,9);U+6519(1,3,8,9) + +U+6401(0);U+64F1(1,3,8,9);U+64F1(1,3,8,9) +U+6402(0);U+645F(1,3,8,9);U+645F(1,3,8,9) +U+6403(0);U+7E3D(3,8,9);U+603B(3),U+7E3D(3,8,9),U+6374(3,4),U+6460(3,9),U+7DCF(3),U+7E02(3,4) + +U+6404(0);U+63EF(4,8,9);U+63EF(4,8,9) +U+6405(0);U+652A(1,3,8,9);U+6341(3,9),U+64B9(4),U+652A(1,3,8,9) +U+6406(0);U+6406(0,9);U+6784(4,9),U+69CB(2,3,8,9),U+5193(0,3,4,9) +U+6408(0);U+6408(0); +U+6409(0);U+6409(0,9);U+69B7(2,3,9) +U+640A(0);U+640A(0,9); +U+640B(0);U+640B(5,9);U+6260(3,8,9) +U+640C(0);U+640C(5,9); +U+640D(0);U+640D(0,9);U+635F(1,3,8) +U+640E(0);U+640E(0,9); +U+640F(0);U+640F(5,9); +U+6410(0);U+6410(5,9); +U+6411(0);U+6411(0); +U+6412(0);U+6412(4,9); +U+6413(0);U+6413(5,9); +U+6414(0);U+6414(5,9); +U+6415(0);U+6415(0,9); +U+6416(0);U+6416(0,9);U+63FA(8),U+6447(4,8) +U+6417(0);U+6417(0,9);U+6363(1,3,8),U+64E3(2,3,8,9) +U+6418(0);U+6418(0,9);U+652F(3,9) +U+6419(0);U+6419(0); +U+641A(0);U+641A(4,9); +U+641B(0);U+641B(5,9); +U+641C(0);U+641C(5,9);U+635C(4,8),U+9A2A(3,9) +U+641D(0);U+641D(0); +U+641E(0);U+641E(5,9); +U+641F(0);U+641F(0,9); +U+6420(0);U+6420(5,9); +U+6421(0);U+6421(5,9); +U+6422(0);U+6422(0,9); +U+6423(0);U+6423(0,9); +U+6424(0);U+6424(0,9);U+627C(2,3,9),U+6439(2,3,9) +U+6425(0);U+6425(3,9);U+6376(2,8,9) +U+6426(0);U+6426(5,9); +U+6427(0);U+6427(0,9);U+6247(4,9) +U+6428(0);U+6428(3,9);U+642D(3,8,9),U+6498(3,8,9) +U+6429(0);U+6429(0); +U+642A(0);U+642A(5,9); +U+642B(0);U+642B(0,9); +U+642C(0);U+642C(5,9); +U+642D(0);U+642D(5,9);U+6428(3,8,9),U+6498(3,9) +U+642E(0);U+642E(0,9); +U+642F(0);U+642F(0,9);U+638F(2,3,8,9) +U+6430(0);U+6430(3,9); +U+6431(0);U+6431(0); +U+6432(0);U+6432(3); +U+6433(0);U+6433(3,9); +U+6434(0);U+6434(5,9); +U+6435(0);U+6435(0,9);U+63FE(4,8) +U+6436(0);U+6436(0,9);U+62A2(1,3,8) +U+6437(0);U+6437(0,9); +U+6438(0);U+6438(0); +U+6439(0);U+6439(0,9);U+627C(3,9),U+6424(2,3,9) +U+643A(0);U+651C(2,3,8,9);U+651C(2,3,8,9) +U+643D(0);U+643D(5,9); +U+643E(0);U+643E(0,9);U+69A8(2,3,9),U+91A1(2,3,9) +U+643F(0);U+643F(5,9); +U+6440(0);U+6440(0,9);U+6342(3,9) +U+6441(0);U+6441(5,9); + +U+6443(0);U+6443(0,9);U+625B(2,3,8,9) +U+6444(0);U+651D(1,3,8,9);U+6315(3,9),U+651D(1,3,8,9) +U+6445(0);U+6504(1,3,8,9);U+6348(3,9),U+6504(1,3,8,9) +U+6446(0);U+64FA(1,3,8,9);U+64FA(1,3,8,9),U+896C(1,3,9) +U+6447(0);U+6416(4,8,9);U+63FA(4),U+6416(4,8,9) +U+6448(0);U+64EF(1,3,8,9);U+64EF(1,3,8,9) +U+644A(0);U+6524(1,3,8,9);U+6524(1,3,8,9) +U+644B(0);U+644B(0,9); +U+644C(0);U+644C(0); +U+644D(0);U+644D(0,9);U+7F29(4),U+7E2E(1,3,4,8,9) +U+644E(0);U+644E(0,9); +U+644F(0);U+644F(0); +U+6450(0);U+6450(0,9); +U+6451(0);U+6451(0,9);U+63B4(1,3,8) +U+6452(0);U+6452(5,9); +U+6453(0);U+6453(3,9); +U+6454(0);U+6454(5,9); +U+6455(0);U+6455(3); +U+6456(0);U+6456(0); +U+6457(0);U+6457(0); +U+6458(0);U+6458(5,9); +U+6459(0);U+6459(0,9); +U+645B(0);U+645B(3,9); +U+645C(0);U+645C(0,9);U+63BC(1,3,8) +U+645D(0);U+645D(0,9); +U+645E(0);U+645E(5,9); +U+645F(0);U+645F(0,9);U+6402(1,3,8) +U+6460(0);U+6460(0,9);U+603B(3),U+6374(3,4),U+6403(3),U+7DCF(3),U+7E02(3,4),U+7E3D(1,3,8,9) + +U+6461(0);U+6461(0,9); +U+6462(0);U+6462(0); +U+6463(0);U+6463(3); +U+6464(0);U+6464(0); +U+6465(0);U+6465(0,9); +U+6466(0);U+6466(0,9); +U+6467(0);U+6467(5,9); +U+6468(0);U+6468(0,9); +U+6469(0);U+6469(5,9); +U+646A(0);U+646A(0); +U+646B(0);U+646B(0,9); +U+646C(0);U+646C(0,9); +U+646D(0);U+646D(5,9);U+62D3(3,8,9) +U+646E(0);U+646E(0,9); +U+646F(0);U+646F(0,9);U+631A(1,3,8) +U+6470(0);U+6470(0,9); +U+6471(0);U+6471(0); +U+6472(0);U+6472(0,9); +U+6473(0);U+6473(0,9);U+62A0(1,3,8) +U+6474(0);U+6474(3,9); +U+6475(0);U+6475(0,9); +U+6476(0);U+6476(0,9);U+629F(1,3,8) +U+6477(0);U+6477(0,9); +U+6478(0);U+6478(5,9); +U+6479(0);U+6479(5,9); +U+647A(0);U+647A(0,9);U+6298(1,3,9) +U+647B(0);U+647B(0,9);U+63BA(1,3,8) +U+647C(0);U+647C(3);U+6333(3,9) +U+647D(0);U+647D(0,9); +U+647F(0);U+647F(0,9); +U+6480(0);U+6480(0); +U+6481(0);U+6481(0); +U+6482(0);U+6482(5,9); +U+6483(0);U+64CA(4,8,9);U+51FB(4),U+64CA(4,8,9) + +U+6484(0);U+6516(1,3,8,9);U+6516(1,3,8,9) +U+6485(0);U+6485(5,9);U+6398(3,8,9) +U+6487(0);U+6487(5,9); +U+6488(0);U+6488(0,9);U+635E(1,3,8) +U+6489(0);U+6489(0,9); +U+648A(0);U+648A(3,9); +U+648B(0);U+648B(0,9); +U+648C(0);U+648C(0,9); +U+648D(0);U+648D(3); +U+648E(0);U+648E(3); +U+648F(0);U+648F(0,9);U+6326(1,3,8) +U+6490(0);U+6490(0,9);U+6491(2,3,8),U+725A(2,3,4,8,9) +U+6491(0);U+6490(2,3,8,9);U+6490(2,3,8,9),U+725A(4,9) +U+6492(0);U+6492(5,9); +U+6493(0);U+6493(0,9);U+6320(1,3,8) +U+6494(0);U+6494(0); +U+6495(0);U+6495(5,9); +U+6496(0);U+6496(5,9); +U+6497(0);U+6497(3,9); +U+6498(0);U+6498(0,9);U+642D(3,9),U+6428(3,8,9) +U+6499(0);U+6499(5,9); +U+649A(0);U+649A(3,9);U+637B(4,9) +U+649B(0);U+649B(0); +U+649C(0);U+649C(0,9); +U+649D(0);U+649D(0,9); +U+649E(0);U+649E(5,9); +U+649F(0);U+649F(0,9);U+6322(1,3,8),U+8B51(1,3,4,8,9) +U+64A0(0);U+64A0(0,9); +U+64A2(0);U+64A2(0,9); +U+64A3(0);U+64A3(0,9);U+63B8(1,3,8) +U+64A4(0);U+64A4(5,9); +U+64A5(0);U+64A5(0,9);U+62E8(1,3,8) +U+64A6(0);U+64A6(0,9);U+626F(2,3,8,9) +U+64A7(0);U+64A7(0); +U+64A8(0);U+64A8(0); +U+64A9(0);U+64A9(5,9); +U+64AA(0);U+64AA(0); +U+64AB(0);U+64AB(0,9);U+629A(1,3,8),U+62CA(3,8,9) +U+64AC(0);U+64AC(5,9); +U+64AD(0);U+64AD(5,9); +U+64AE(0);U+64AE(5,9); +U+64B0(0);U+64B0(5,9),U+8B54(2,3,9);U+8B54(2,3,9) +U+64B1(0);U+64B1(0,9);U+692D(4),U+6955(3,4),U+6A62(1,3,4,8,9) +U+64B2(0);U+64B2(0,9);U+6251(1,3,8,9),U+6534(1,3,8) +U+64B3(0);U+64B3(0,9);U+63FF(1,3,8) +U+64B4(0);U+64B4(0); +U+64B5(0);U+6506(1,3,8,9);U+6506(1,3,8,9) +U+64B7(0);U+64F7(1,3,8,9);U+64F7(1,3,8,9) +U+64B8(0);U+64FC(4,8,9);U+64FC(4,8,9) +U+64B9(0);U+652A(4,8,9);U+6405(4),U+652A(4,8,9),U+6341(0,3,4,9) +U+64BA(0);U+651B(1,3,8,9);U+651B(1,3,8,9) +U+64BB(0);U+64BB(0,9);U+631E(1,3,8) +U+64BC(0);U+64BC(5,9); +U+64BD(0);U+64BD(0,9); +U+64BE(0);U+64BE(0,9);U+631D(1,3,8) +U+64BF(0);U+64BF(0,9);U+6361(1,3,8) +U+64C0(0);U+634D(8,9);U+625E(3,8,9),U+634D(8,9) +U+64C1(0);U+64C1(0,9);U+62E5(1,3,8) +U+64C2(0);U+64C2(5,9); +U+64C3(0);U+64C3(3,9); +U+64C4(0);U+64C4(0,9);U+63B3(1,3,8) +U+64C5(0);U+64C5(5,9); +U+64C6(0);U+64C6(3); + +U+64C7(0);U+64C7(0,9);U+629E(8),U+62E9(1,3,8) +U+64C9(0);U+64C9(3,9); +U+64CA(0);U+64CA(0,9);U+51FB(1,3,8),U+6483(4,8) +U+64CB(0);U+64CB(0,9);U+6321(1,3,8) +U+64CC(0);U+64CC(0); +U+64CD(0);U+64CD(5,9); +U+64CE(0);U+64CE(5,9); +U+64CF(0);U+64CF(0,9); +U+64D0(0);U+64D0(5,9); +U+64D1(0);U+64D1(0); +U+64D2(0);U+64D2(5,9); +U+64D3(0);U+64D3(0);U+39DF(1,3) +U+64D4(0);U+64D4(0,9);U+62C5(1,3,8) +U+64D6(0);U+64D6(0,9); +U+64D7(0);U+64D7(5,9); +U+64D8(0);U+64D8(5,9); +U+64D9(0);U+64D9(0,9); +U+64DA(0);U+64DA(0,9);U+62E0(3,8),U+636E(1,3,8,9) +U+64DB(0);U+64DB(3,9); +U+64DC(0);U+64DC(0); +U+64DD(0);U+64DD(0); +U+64DE(0);U+64FB(1,3,8,9);U+64FB(1,3,8,9) +U+64DF(0);U+64DF(0); +U+64E0(0);U+64E0(0,9);U+6324(1,3,8) +U+64E2(0);U+64E2(5,9); +U+64E3(0);U+64E3(3,9);U+6363(4),U+6417(2,3,8,9) +U+64E4(0);U+64E4(5,9); +U+64E6(0);U+64E6(5,9); +U+64E7(0);U+8209(2,3,8,9);U+4E3E(4),U+8209(2,3,8,9),U+6319(4) +U+64E8(0);U+64E8(0,9); +U+64E9(0);U+64E9(0,9); +U+64EA(0);U+64EA(3);U+64EB(3,9) +U+64EB(0);U+64EB(0,9);U+64EA(3) +U+64EC(0);U+64EC(0,9);U+5117(2,8,9),U+62DF(1,3,8) +U+64ED(0);U+64ED(0,9); +U+64EF(0);U+64EF(0,9);U+6448(1,3,8) +U+64F0(0);U+64F0(0,9);U+62E7(1,3,8) +U+64F1(0);U+64F1(0,9);U+6401(1,3,8) +U+64F2(0);U+64F2(0,9);U+63B7(1,3,8) +U+64F3(0);U+64F3(0,9); +U+64F4(0);U+64F4(0,9);U+6269(1,3,8),U+62E1(4,8) +U+64F6(0);U+64F6(0); +U+64F7(0);U+64F7(0,9);U+64B7(1,3,8) +U+64F8(0);U+64F8(0,9); +U+64FA(0);U+64FA(0,9);U+6446(1,3,8),U+896C(4,9) +U+64FB(0);U+64FB(0,9);U+64DE(1,3,8) +U+64FC(0);U+64FC(0,9);U+64B8(4,8) +U+64FD(0);U+64FD(3,9); +U+64FE(0);U+64FE(0,9);U+6270(1,3,8,9) +U+64FF(0);U+64FF(3,9); +U+6500(0);U+6500(5,9); +U+6501(0);U+6501(0,9); +U+6503(0);U+6503(3,9); +U+6504(0);U+6504(0,9);U+6445(1,3,8),U+6348(0,1,3,8,9) +U+6505(0);U+6522(3,8,9);U+6512(3),U+6522(3,8,9) +U+6506(0);U+6506(0,9);U+64B5(1,3,8) +U+6507(0);U+6507(3,9); +U+6508(0);U+6508(4); +U+6509(0);U+6509(5,9); +U+650B(0);U+650B(3); +U+650C(0);U+650C(0,9); +U+650D(0);U+650D(0,9); +U+650E(0);U+650E(0,9); + +U+650F(0);U+650F(0,9);U+62E2(1,3,8) +U+6510(0);U+6510(3,9); +U+6511(0);U+6511(0); +U+6512(0);U+6522(1,3,8,9);U+6505(3),U+6522(1,3,8,9) +U+6513(0);U+6513(0,9); +U+6514(0);U+6514(0,9);U+62E6(1,3,8) +U+6515(0);U+6515(3,9); +U+6516(0);U+6516(0,9);U+6484(1,3,8) +U+6517(0);U+6517(0,9); +U+6518(0);U+6518(5,9); +U+6519(0);U+6519(0,9);U+6400(1,3,8) +U+651A(0);U+651A(0); +U+651B(0);U+651B(0,9);U+64BA(1,3,8) +U+651C(0);U+651C(0,9);U+643A(2,3,8) +U+651D(0);U+651D(0,9);U+6444(1,3,8),U+6315(0,1,3,8,9) +U+651E(0);U+651E(3); +U+6520(0);U+6520(0,9); +U+6521(0);U+6521(0,9); +U+6522(0);U+6522(0,9);U+6505(3,8),U+6512(1,3,8) +U+6523(0);U+6523(0,9);U+631B(1,3,8) +U+6524(0);U+6524(0,9);U+644A(1,3,8) +U+6525(0);U+6525(5,9); +U+6526(0);U+6526(0,9); +U+6527(0);U+6527(0); +U+6529(0);U+6529(0,9); +U+652A(0);U+652A(0,9);U+6405(1,3,8),U+64B9(4,8),U+6341(0,1,3,8,9) +U+652B(0);U+652B(5,9); +U+652C(0);U+652C(0,9);U+63FD(1,3,8) +U+652D(0);U+652D(0,9); +U+652E(0);U+652E(5,9); +U+652F(0);U+652F(5,9);U+6418(3,9) +U+6530(0);U+6530(0); +U+6531(0);U+6531(3); +U+6532(0);U+6532(3,9); +U+6533(0);U+6533(0,9); +U+6534(0);U+6534(5);U+6251(3,9),U+64B2(1,3,8,9) +U+6535(0);U+6535(5); +U+6536(0);U+6536(5,9);U+53CE(3,8) +U+6537(0);U+6537(0,9);U+8003(2,3,8,9) +U+6538(0);U+6538(5,9);U+900C(3,9) +U+6539(0);U+6539(5,9); +U+653A(0);U+653A(0); +U+653B(0);U+653B(5,9); +U+653C(0);U+653C(0); +U+653D(0);U+653D(3,9); +U+653E(0);U+653E(5,9); +U+653F(0);U+653F(5,9); +U+6541(0);U+6541(0,9); +U+6543(0);U+6543(0,9); +U+6544(0);U+6544(0); +U+6545(0);U+6545(5,9); +U+6546(0);U+6546(0,9);U+5408(3,9),U+95A4(1,3,8,9) +U+6547(0);U+6547(0); +U+6548(0);U+6548(5,9),U+509A(2,3,9);U+4FF2(7,8),U+509A(2,3,9),U+52B9(2,3,8) +U+6549(0);U+6549(5,9); +U+654A(0);U+654A(0,9); +U+654B(0);U+654B(0); +U+654C(0);U+6575(1,3,8,9);U+6575(1,3,8,9) +U+654D(0);U+6558(3,8,9);U+53D9(2,3,8),U+6558(3,8,9) +U+654E(0);U+6559(3,8,9);U+6559(3,8,9) +U+654F(0);U+654F(5,9); +U+6550(0);U+6550(0); +U+6551(0);U+6551(5,9); + +U+6552(0);U+6552(0); +U+6553(0);U+6553(0,9);U+593A(3),U+596A(1,3,8,9) +U+6554(0);U+6554(3,9); +U+6555(0);U+6555(5,9); +U+6556(0);U+6556(5,9);U+969E(3,9) +U+6557(0);U+6557(0,9);U+8D25(1,3,8) +U+6558(0);U+6558(0,9);U+53D9(2),U+654D(3,8) +U+6559(0);U+6559(5,9);U+654E(3,8) +U+655B(0);U+6582(1,3,8,9);U+6582(1,3,8,9),U+6B5B(3,9) +U+655C(0);U+655C(3,9); +U+655D(0);U+655D(5,9); +U+655E(0);U+655E(5,9); +U+6560(0);U+656A(4,8,9);U+656A(4,8,9) +U+6561(0);U+6561(0); +U+6562(0);U+6562(5,9); +U+6563(0);U+6563(5,9); +U+6564(0);U+6564(0,9); +U+6565(0);U+6565(0,9); +U+6566(0);U+6566(5,9); +U+6567(0);U+6567(3,9); +U+6568(0);U+6568(0,9); +U+6569(0);U+6585(4,8);U+6585(4,8),U+6586(4) +U+656A(0);U+656A(0,9);U+6560(4,8) +U+656B(0);U+656B(5); +U+656C(0);U+656C(5,9); +U+656E(0);U+656E(0); +U+656F(0);U+656F(0,9);U+610D(4,9) +U+6570(0);U+6578(1,3,8,9);U+6578(1,3,8,9) +U+6571(0);U+6571(0); +U+6572(0);U+6572(5,9);U+6BC3(3,9) +U+6573(0);U+6573(0,9); +U+6574(0);U+6574(5,9); +U+6575(0);U+6575(0,9);U+654C(1,3,8) +U+6576(0);U+6576(0,9);U+9648(3),U+9673(1,3,8,9) +U+6577(0);U+6577(5,9);U+5C03(3,9) +U+6578(0);U+6578(0,9);U+6570(1,3,8) +U+6579(0);U+6579(0,9); +U+657A(0);U+657A(0,9);U+9A71(4),U+99C6(1,4),U+99C8(4),U+9A45(1,3,4,8,9) +U+657B(0);U+657B(0,9);U+5910(4,8) +U+657C(0);U+657C(0,9); +U+657E(0);U+657E(0); +U+657F(0);U+657F(0,9); +U+6580(0);U+6580(3,9); +U+6581(0);U+6581(3,9); +U+6582(0);U+6582(0,9);U+655B(1,3,8),U+6B5B(2,3,8,9) +U+6583(0);U+6583(0,9);U+6BD9(1,3,8) +U+6584(0);U+6584(3,9); +U+6585(0);U+6585(0);U+6569(4,8),U+6586(3,4,8) +U+6586(0);U+6585(3,4,8);U+6569(4),U+6585(3,4,8) +U+6587(0);U+6587(5,9); +U+6588(0);U+5B78(3,8,9);U+5B66(3),U+5B78(3,8,9) +U+6589(0);U+9F4A(3,8,9);U+9F4A(3,8,9),U+9F50(3),U+4E9D(0,3,8) +U+658B(0);U+9F4B(1,3,8,9);U+658E(4),U+9F4B(1,3,8,9) +U+658C(0);U+658C(5,9); +U+658D(0);U+89BA(3,8,9);U+89BA(3,8,9),U+89C9(3),U+899A(3,4,8) +U+658E(0);U+9F4B(4,8,9);U+658B(4),U+9F4B(4,8,9) +U+658F(0);U+658F(0); +U+6590(0);U+6590(5,9); +U+6591(0);U+6591(5,9); +U+6592(0);U+6592(3,9); +U+6593(0);U+6595(1,3,8,9);U+6595(1,3,8,9) +U+6594(0);U+6594(0,9);U+5EBE(3,9),U+659E(3,9) +U+6595(0);U+6595(0,9);U+6593(1,3,8) + +U+6596(0);U+6596(0,9);U+4EB9(4,9) +U+6597(0);U+6597(1,3,9),U+9B25(1,3,8,9);U+95D8(4),U+9B25(1,3,8,9),U+9B26(4),U+9B2A(4),U+9B2C(3),U+9B2D(4) + +U+6598(0);U+6598(0); +U+6599(0);U+6599(5,9); +U+659B(0);U+659B(5,9); +U+659C(0);U+659C(5,9); +U+659D(0);U+659D(3,9); +U+659E(0);U+659E(0,9);U+5EBE(3,9),U+6594(3,9) +U+659F(0);U+659F(5,9); +U+65A0(0);U+65A0(0,9); +U+65A1(0);U+65A1(5,9); +U+65A2(0);U+65A2(0,9); +U+65A3(0);U+65A3(0); +U+65A4(0);U+65A4(5,9);U+89D4(2,8,9),U+7B4B(2,3,8,9) +U+65A5(0);U+65A5(5,9); +U+65A6(0);U+65A6(0); +U+65A7(0);U+65A7(5,9); +U+65A8(0);U+65A8(0,9); +U+65A9(0);U+65AC(1,3,8,9);U+65AC(1,3,8,9) +U+65AA(0);U+65AA(0,9); +U+65AB(0);U+65AB(5,9); +U+65AC(0);U+65AC(0,9);U+65A9(1,3,8) +U+65AD(0);U+65B7(1,3,8,9);U+65B7(1,3,8,9) +U+65AE(0);U+65AE(3,9); +U+65AF(0);U+65AF(5,9); +U+65B0(0);U+65B0(5,9); +U+65B1(0);U+65B1(0); +U+65B2(0);U+65B2(4,9); +U+65B3(0);U+65B3(0,9); +U+65B4(0);U+65B4(0); +U+65B6(0);U+65B6(0,9); +U+65B7(0);U+65B7(0,9);U+65AD(1,3,8) +U+65B8(0);U+65B8(3,9); +U+65B9(0);U+65B9(5,9); +U+65BA(0);U+65BA(0); +U+65BB(0);U+65BB(3,9); +U+65BC(0);U+65BC(5,9);U+4E8E(4,8,9),U+6275(3) +U+65BD(0);U+65BD(5,9); +U+65BF(0);U+65BF(0,9); +U+65C0(0);U+65C0(0); +U+65C1(0);U+65C1(5,9); +U+65C2(0);U+65C2(0,9);U+65D7(2,9) +U+65C3(0);U+65C3(5,9); +U+65C4(0);U+65C4(5,9); +U+65C5(0);U+65C5(5,9);U+7963(3,9) +U+65C6(0);U+65C6(5,9); +U+65C7(0);U+65C7(0); +U+65CA(0);U+65CA(0); +U+65CB(0);U+65CB(1,3,9),U+93C7(1,3,4,9);U+93C7(1,3,4,9),U+955F(1,3,4,8) +U+65CC(0);U+65CC(5,9);U+65CD(3,9) +U+65CD(0);U+65CD(0,9);U+65CC(3,9) +U+65CE(0);U+65CE(5,9); +U+65CF(0);U+65CF(5,9); +U+65D0(0);U+65D0(0,9); +U+65D2(0);U+65D2(5,9); +U+65D3(0);U+65D3(0,9); +U+65D4(0);U+65D4(0); +U+65D5(0);U+65D5(0); +U+65D6(0);U+65D6(5,9); +U+65D7(0);U+65D7(5,9);U+65C2(2,9) +U+65DA(0);U+65DA(0,9);U+98D8(3),U+98C3(3,4),U+98C4(1,3,8,9) +U+65DB(0);U+65DB(4,9); + +U+65DD(0);U+65DD(0,9); +U+65DE(0);U+65DE(0,9); +U+65DF(0);U+65DF(0,9); +U+65E0(0);U+7121(1,3,8,9);U+7121(1,3,8,9) +U+65E1(0);U+65E1(0,9); +U+65E2(0);U+65E2(5,9);U+65E3(3,8) +U+65E3(0);U+65E2(3,8,9);U+65E2(3,8,9) +U+65E5(0);U+65E5(5,9); +U+65E6(0);U+65E6(5,9); +U+65E7(0);U+820A(1,3,8,9);U+820A(1,3,8,9) +U+65E8(0);U+65E8(5,9);U+6049(4,9) +U+65E9(0);U+65E9(5,9); +U+65EB(0);U+65EB(0); +U+65EC(0);U+65EC(5,9); +U+65ED(0);U+65ED(5,9);U+65EE(3,8,9) +U+65EE(0);U+65EE(5,9);U+65ED(3,8,9) +U+65EF(0);U+65EF(5,9); +U+65F0(0);U+65F0(5,9); +U+65F1(0);U+65F1(5,9); +U+65F2(0);U+65F2(0,9); +U+65F3(0);U+65F3(0,9); +U+65F4(0);U+65F4(3,9); +U+65F5(0);U+65F5(0,9); +U+65F6(0);U+6642(1,3,8,9);U+6642(1,3,8,9) +U+65F7(0);U+66E0(1,3,8,9);U+66E0(1,3,8,9) +U+65F8(0);U+6698(1,3,8,9);U+6698(1,3,8,9) +U+65FA(0);U+65FA(5,9); +U+65FB(0);U+65FB(3,9); +U+65FC(0);U+65FC(0,9); +U+65FD(0);U+65FD(0,9); +U+6600(0);U+6600(5,9); +U+6601(0);U+6601(0); +U+6602(0);U+6602(5,9); +U+6603(0);U+6603(5,9); +U+6604(0);U+6604(0,9);U+53CD(4,9) +U+6605(0);U+6605(0,9); +U+6606(0);U+6606(5,9),U+5D11(2,9);U+5D10(2),U+5D11(2,9),U+665C(3,9) +U+6607(0);U+6607(0,9);U+5347(2,3,8,9),U+965E(2,3,8,9) +U+6608(0);U+6608(0,9); +U+6609(0);U+6609(3,9); +U+660A(0);U+660A(5,9);U+6626(3,9) +U+660B(0);U+660B(0,9); +U+660C(0);U+660C(5,9); +U+660D(0);U+660D(0,9); +U+660E(0);U+660E(5,9); +U+660F(0);U+660F(5,9); +U+6610(0);U+6610(0,9); +U+6611(0);U+6611(0,9); +U+6612(0);U+6612(3,9); +U+6613(0);U+6613(5,9); +U+6614(0);U+6614(5,9); +U+6615(0);U+6615(5,9); +U+6616(0);U+6616(0); +U+6618(0);U+6618(0); +U+6619(0);U+66C7(1,3,8,9);U+66C7(1,3,8,9) +U+661A(0);U+614E(2,3,9);U+614E(2,3,9),U+613C(0,2,3,4,8),U+7718(2,3,4,8) +U+661B(0);U+661B(0); +U+661C(0);U+661C(0,9);U+967D(3,8,9),U+9633(3) +U+661D(0);U+661D(5,9); +U+661F(0);U+661F(5,9); +U+6620(0);U+6620(5,9);U+668E(2,3,8) +U+6621(0);U+6621(0,9); +U+6622(0);U+6622(3,9); + +U+6623(0);U+6623(0); +U+6624(0);U+6624(0,9); +U+6625(0);U+6625(5,9);U+8405(3,8) +U+6626(0);U+6626(0,9);U+660A(3,9) +U+6627(0);U+6627(5,9); +U+6628(0);U+6628(5,9); +U+6629(0);U+6629(0); +U+662A(0);U+662A(0); +U+662B(0);U+662B(3,9); +U+662D(0);U+662D(5,9); +U+662E(0);U+662E(0,9); +U+662F(0);U+662F(5,9);U+6630(2,3,8) +U+6630(0);U+662F(2,3,8,9);U+662F(2,3,8,9) +U+6631(0);U+6631(5,9); +U+6632(0);U+6632(4,9);U+66CA(4,9) +U+6633(0);U+6633(0,9); +U+6634(0);U+6634(5,9); +U+6635(0);U+6635(5,9);U+66B1(2,3,9) +U+6636(0);U+6636(5,9); +U+6639(0);U+6639(0,9); +U+663A(0);U+663A(0,9);U+70B3(3,9) +U+663C(0);U+665D(1,3,8,9);U+665D(1,3,8,9) +U+663D(0);U+66E8(1,3,8,9);U+66E8(1,3,8,9) +U+663E(0);U+986F(1,3,8,9);U+9855(4),U+986F(1,3,8,9) +U+6640(0);U+6640(0); +U+6641(0);U+6641(5,9); +U+6642(0);U+6642(0,9);U+65F6(1,3,8) +U+6643(0);U+6643(5,9);U+6644(3,8) +U+6644(0);U+6643(3,8,9);U+6643(3,8,9) +U+6645(0);U+6645(0,9); +U+6646(0);U+6646(0); +U+6647(0);U+6647(0,9); +U+6649(0);U+6649(0,9);U+664B(2,3,8) +U+664A(0);U+664A(0,9); +U+664B(0);U+6649(2,3,8,9);U+6649(2,3,8,9) +U+664C(0);U+664C(5,9); +U+664E(0);U+664E(0); +U+664F(0);U+664F(5,9); +U+6650(0);U+6650(0); +U+6651(0);U+6651(0,9); +U+6652(0);U+66EC(1,3,8,9);U+66EC(1,3,8,9) +U+6653(0);U+66C9(1,3,8,9);U+6681(4),U+66C9(1,3,8,9) +U+6654(0);U+66C4(1,3,8,9);U+66C4(1,3,8,9),U+66C5(3) +U+6655(0);U+6688(1,3,8,9);U+6688(1,3,8,9) +U+6656(0);U+6689(4,8,9);U+6689(4,8,9) +U+6657(0);U+6657(5); +U+6658(0);U+6658(0); +U+6659(0);U+6659(0,9); +U+665A(0);U+665A(5,9);U+6669(4,8) +U+665B(0);U+665B(0,9); +U+665C(0);U+665C(0,9);U+6606(3,9),U+5D10(0,2,3),U+5D11(2,3,8,9) +U+665D(0);U+665D(0,9);U+663C(1,3,8) +U+665E(0);U+665E(3,9); +U+665F(0);U+665F(5,9); +U+6661(0);U+6661(5,9); +U+6662(0);U+6662(3,9); +U+6664(0);U+6664(5,9); +U+6665(0);U+6665(0,9);U+7696(3,9) +U+6666(0);U+6666(5,9); +U+6668(0);U+6668(5,9); +U+6669(0);U+665A(4,8,9);U+665A(4,8,9) +U+666A(0);U+666A(0,9); +U+666B(0);U+666B(0); + +U+666C(0);U+666C(0,9); +U+666D(0);U+666D(0); +U+666E(0);U+666E(5,9); +U+666F(0);U+666F(5,9); +U+6670(0);U+6670(5,9); +U+6671(0);U+6671(0,9); +U+6672(0);U+6672(0,9); +U+6673(0);U+6673(0); +U+6674(0);U+6674(5,9); +U+6675(0);U+6675(0); +U+6676(0);U+6676(5,9); +U+6677(0);U+6677(5,9); +U+6678(0);U+6678(0,9); +U+6679(0);U+6679(0,9); +U+667A(0);U+667A(5,9); +U+667B(0);U+667B(0,9);U+6697(2,3,8,9),U+95C7(2,3,8,9) +U+667C(0);U+667C(0,9); +U+667D(0);U+667D(0); +U+667E(0);U+667E(5,9); +U+667F(0);U+667F(0); +U+6680(0);U+6680(0,9); +U+6681(0);U+66C9(4,8,9);U+6653(4),U+66C9(4,8,9) +U+6682(0);U+66AB(1,3,8,9);U+66AB(1,3,8,9),U+8E54(4,9) +U+6683(0);U+6683(0); +U+6684(0);U+6684(5,9); +U+6685(0);U+6685(0); +U+6686(0);U+6686(0,9); +U+6687(0);U+6687(5,9); +U+6688(0);U+6688(0,9);U+6655(1,3,8) +U+6689(0);U+6689(0,9);U+6656(4,8) +U+668A(0);U+668A(0,9); +U+668B(0);U+668B(3,9); +U+668C(0);U+668C(5,9); +U+668D(0);U+668D(0,9); +U+668E(0);U+6620(2,3,8,9);U+6620(2,3,8,9) +U+668F(0);U+668F(0); +U+6690(0);U+6690(0,9); +U+6691(0);U+6691(5,9); +U+6693(0);U+6693(0); +U+6694(0);U+6694(0,9); +U+6695(0);U+6695(0,9); +U+6696(0);U+6696(5,9),U+7156(2,3,8,9);U+7156(2,3,8,9) +U+6697(0);U+6697(5,9);U+667B(2,3,8,9),U+95C7(2,8,9) +U+6698(0);U+6698(0,9);U+65F8(1,3,8) +U+6699(0);U+6699(0,9); +U+669A(0);U+669A(0); +U+669B(0);U+669B(0); +U+669D(0);U+669D(5,9); +U+669F(0);U+669F(0,9); +U+66A0(0);U+66A0(0,9);U+7693(2,3,9),U+769C(2,3,9) +U+66A1(0);U+66A1(0,9); +U+66A2(0);U+66A2(0,9);U+7545(1,3,8) +U+66A3(0);U+66A3(0); +U+66A4(0);U+66A4(3); +U+66A5(0);U+66A5(0); +U+66A6(0);U+66C6(4,8,9);U+5386(4),U+66C6(4,8,9),U+53A4(4,9),U+6B74(2,3,4),U+6B77(1,3,4,8,9) + +U+66A7(0);U+66D6(1,3,8,9);U+66D6(1,3,8,9) +U+66A8(0);U+66A8(5,9);U+66C1(4,8),U+81EE(4,9),U+8507(4,9) +U+66A9(0);U+66A9(0,9); +U+66AA(0);U+66AA(0,9); +U+66AB(0);U+66AB(0,9);U+6682(1,3,8),U+8E54(1,3,4,8,9) +U+66AE(0);U+66AE(5,9); + +U+66AF(0);U+66AF(0,9); +U+66B0(0);U+66B0(0,9); +U+66B1(0);U+66B1(3,9);U+6635(2,3,9) +U+66B2(0);U+66B2(0,9); +U+66B3(0);U+66B3(0); +U+66B4(0);U+66B4(5,9);U+8663(3,9) +U+66B5(0);U+66B5(3,9); +U+66B6(0);U+66B6(0); +U+66B7(0);U+66B7(0,9); +U+66B8(0);U+66B8(0,9);U+4E86(7,9),U+77AD(1,3,4,7,8,9) +U+66B9(0);U+66B9(5,9); +U+66BA(0);U+66BA(0,9); +U+66BB(0);U+66BB(0,9); +U+66BC(0);U+66BC(0); +U+66BD(0);U+66BD(0,9); +U+66BE(0);U+66BE(5,9); +U+66BF(0);U+66BF(0); +U+66C0(0);U+66C0(0,9); +U+66C1(0);U+66A8(4,8,9);U+66A8(4,8,9),U+81EE(4,8,9),U+8507(4,8,9) +U+66C2(0);U+66C2(0); +U+66C3(0);U+66C3(0); +U+66C4(0);U+66C4(0,9);U+6654(1,3,8),U+66C5(3,8) +U+66C5(0);U+66C4(3,8,9);U+6654(3),U+66C4(3,8,9) +U+66C6(0);U+66C6(0,9);U+5386(1,3,8),U+66A6(4,8),U+6B77(3,4,9),U+53A4(1,3,4,8,9),U+6B74(1,2,3,8) + +U+66C7(0);U+66C7(0,9);U+6619(1,3,8) +U+66C8(0);U+66C8(3,9); +U+66C9(0);U+66C9(0,9);U+6653(1,3,8),U+6681(4,8) +U+66CA(0);U+66CA(0,9);U+6632(4,9) +U+66CB(0);U+66CB(0,9); +U+66CC(0);U+66CC(0,9);U+7167(3,9),U+70A4(2,3,8,9) +U+66CD(0);U+66CD(0); +U+66CE(0);U+66CE(0); +U+66CF(0);U+66CF(0,9);U+5411(4,9),U+56AE(1,3,4,8,9) +U+66D1(0);U+66D1(0); +U+66D2(0);U+66D2(4,9); +U+66D4(0);U+66D4(0); +U+66D5(0);U+66D5(0); +U+66D6(0);U+66D6(0,9);U+66A7(1,3,8) +U+66D8(0);U+66D8(0,9); +U+66D9(0);U+66D9(5,9); +U+66DA(0);U+66DA(0,9); +U+66DB(0);U+66DB(5,9); +U+66DC(0);U+66DC(5,9);U+71FF(3,9),U+8000(2,3,8,9) +U+66DD(0);U+66DD(5,9); +U+66DE(0);U+66DE(0,9); +U+66E0(0);U+66E0(0,9);U+65F7(1,3,8) +U+66E1(0);U+758A(3,8,9);U+53E0(2),U+758A(3,8,9),U+8FED(4,9),U+7589(2) +U+66E2(0);U+66E2(0); +U+66E3(0);U+66E3(0,9); +U+66E4(0);U+66E4(0,9); +U+66E5(0);U+66E5(0); +U+66E6(0);U+66E6(5,9); +U+66E7(0);U+66E7(0); +U+66E8(0);U+66E8(0,9);U+663D(1,3,8) +U+66E9(0);U+66E9(5,9); +U+66EA(0);U+66EA(0); +U+66EB(0);U+66EB(0,9); +U+66EC(0);U+66EC(0,9);U+6652(1,3,8,9) +U+66ED(0);U+66ED(0,9); +U+66EE(0);U+66EE(0,9); +U+66F0(0);U+66F0(5,9); +U+66F1(0);U+66F1(0); + +U+66F2(0);U+66F2(1,3,4,9),U+9EB4(4,9);U+9EAF(1,3),U+9EB4(4,9) +U+66F3(0);U+66F3(5,9);U+66F5(3,8) +U+66F4(0);U+66F4(5,9); +U+66F5(0);U+66F3(3,8,9);U+66F3(3,8,9) +U+66F6(0);U+66F6(0,9); +U+66F7(0);U+66F7(5,9); +U+66F8(0);U+66F8(0,9);U+4E66(1,3,8) +U+66F9(0);U+66F9(5,9);U+66FA(3,8) +U+66FA(0);U+66F9(3,8,9);U+66F9(3,8,9) +U+66FB(0);U+66FB(0); +U+66FC(0);U+66FC(5,9); +U+66FE(0);U+66FE(5,9); +U+66FF(0);U+66FF(5,9); +U+6700(0);U+6700(5,9); +U+6701(0);U+6701(0,9); +U+6703(0);U+6703(0,9);U+4F1A(1,3,8) +U+6704(0);U+6704(0,9); +U+6705(0);U+6705(0,9); +U+6706(0);U+6706(0); +U+6708(0);U+6708(5,9); +U+6709(0);U+6709(5,9); +U+670A(0);U+670A(5,9); +U+670B(0);U+670B(5,9); +U+670C(0);U+9812(3,8,9);U+9812(3,8,9),U+9881(7) +U+670D(0);U+670D(5,9); +U+670E(0);U+670E(0); +U+670F(0);U+670F(4,9);U+80D0(4,9) +U+6710(0);U+6710(5,9);U+80CA(4,8,9) +U+6711(0);U+6711(0); +U+6712(0);U+6712(3,9); +U+6713(0);U+6713(4,9);U+8101(4,9) +U+6714(0);U+6714(5,9); +U+6715(0);U+6715(5,9); +U+6716(0);U+6717(3,8,9);U+6717(3,8,9),U+70FA(3,8,9) +U+6717(0);U+6717(5,9);U+6716(3,8),U+70FA(3,9) +U+6718(0);U+6718(4,9);U+8127(4,8,9) +U+671A(0);U+671A(0); +U+671B(0);U+671B(5,9);U+6722(2,3,8,9) +U+671C(0);U+671C(0); +U+671D(0);U+671D(5,9); +U+671E(0);U+671F(2,3,8,9);U+671F(2,3,8,9) +U+671F(0);U+671F(5,9);U+671E(2,3,8) +U+6720(0);U+6720(0,9); +U+6721(0);U+6721(0,9); +U+6722(0);U+6722(0,9);U+671B(2,3,8,9) +U+6723(0);U+6723(4,9);U+81A7(4,9) +U+6725(0);U+6725(0); +U+6726(0);U+6726(5,9); +U+6727(0);U+6727(0,9);U+80E7(1,3,8) +U+6728(0);U+6728(5,9); +U+672A(0);U+672A(5,9); +U+672B(0);U+672B(5,9); +U+672C(0);U+672C(5,9);U+5932(3,8) +U+672D(0);U+672D(5,9);U+624E(3,9),U+5273(2,3),U+5284(2,3,9),U+7B9A(2,3,4),U+7D25(2,3,4),U+7D2E(2,3,4,8,9) + +U+672E(0);U+672E(0,9);U+672F(4),U+8853(1,3,4,8,9) +U+672F(0);U+8853(1,3,8,9);U+672E(4,9),U+8853(1,3,8,9) +U+6730(0);U+6730(0); +U+6731(0);U+6731(1,9),U+7843(1,4,9);U+7843(1,4,9) +U+6732(0);U+6732(0); +U+6733(0);U+6733(3,9); +U+6734(0);U+6734(1,3,9),U+6A38(1,3,8,9);U+6A38(1,3,8,9) + +U+6735(0);U+6735(5,9);U+6736(2,3,8) +U+6736(0);U+6735(2,3,8,9);U+6735(2,3,8,9) +U+6737(0);U+6737(0); +U+6738(0);U+6738(0,9); +U+6739(0);U+6739(0,9); +U+673A(0);U+6A5F(1,3,8,9);U+6A5F(1,3,8,9) +U+673B(0);U+673B(0,9);U+6A1B(3,9) +U+673C(0);U+673C(0,9);U+6787(3,9) +U+673D(0);U+673D(5,9); +U+673E(0);U+673E(3,9); +U+673F(0);U+673F(0,9);U+523A(3,9),U+523E(3,7,8) +U+6740(0);U+6BBA(1,3,8,9);U+6BBA(1,3,8,9),U+95B7(3,9) +U+6741(0);U+6741(0); +U+6742(0);U+96DC(1,3,8,9);U+96D1(3),U+96DC(1,3,8,9),U+96E5(3,9) +U+6743(0);U+6B0A(1,3,8,9);U+6A29(3),U+6B0A(1,3,8,9) +U+6744(0);U+6744(3); +U+6745(0);U+6745(3,9); +U+6746(0);U+6746(5,9),U+687F(2,3,9);U+687F(2,3,9) +U+6747(0);U+6747(0,9);U+572C(3,9) +U+6748(0);U+6748(5,9); +U+6749(0);U+6749(5,9); +U+674A(0);U+674A(0); +U+674B(0);U+674B(3,9); +U+674C(0);U+674C(5,9); +U+674D(0);U+674D(0,9);U+6893(3,9) +U+674E(0);U+674E(5,9); +U+674F(0);U+674F(5,9); +U+6750(0);U+6750(5,9); +U+6751(0);U+6751(5,9);U+90A8(2,3) +U+6752(0);U+6752(3); +U+6753(0);U+6753(5,9); +U+6754(0);U+6754(0); +U+6755(0);U+6755(0,9); +U+6756(0);U+6756(5,9); +U+6757(0);U+6757(0,9); +U+6758(0);U+6758(3); +U+6759(0);U+6759(3,9); +U+675A(0);U+675A(0,9); +U+675B(0);U+675B(0); +U+675C(0);U+675C(5,9); +U+675D(0);U+675D(4,9); +U+675E(0);U+675E(5,9); +U+675F(0);U+675F(5,9); +U+6760(0);U+6760(5,9),U+69D3(2,3,8,9);U+69D3(2,3,8,9) +U+6761(0);U+689D(1,3,8,9);U+689D(1,3,8,9) +U+6762(0);U+6762(0); +U+6763(0);U+6763(0); +U+6764(0);U+6764(0); +U+6765(0);U+4F86(1,3,8,9);U+4F86(1,3,8,9) +U+6766(0);U+6766(0); +U+6768(0);U+694A(1,3,8,9);U+694A(1,3,8,9) +U+6769(0);U+69AA(4,8,9);U+69AA(4,8,9) +U+676A(0);U+676A(5,9); +U+676B(0);U+676B(0); +U+676C(0);U+676C(0,9); +U+676D(0);U+676D(5,9); +U+676E(0);U+676E(4); +U+676F(0);U+676F(5,9);U+686E(2,3,8,9),U+76C3(2,3,8,9) +U+6770(0);U+6770(3,9),U+5091(2,3,8,9);U+5091(2,3,8,9) +U+6771(0);U+6771(0,9);U+4E1C(1,3,8) +U+6772(0);U+6772(5,9); +U+6773(0);U+6773(5,9); +U+6774(0);U+6774(3,9); + +U+6775(0);U+6775(5,9); +U+6776(0);U+6776(3,9); +U+6777(0);U+6777(5,9); +U+6778(0);U+6778(0,9);U+6BB3(3,9) +U+6779(0);U+6779(0,9); +U+677A(0);U+677A(0,9); +U+677B(0);U+677B(0,9); +U+677C(0);U+677C(5,9); +U+677D(0);U+677D(3,9); +U+677E(0);U+677E(1,3,9),U+9B06(1,3,4,8,9);U+6780(3,8),U+9B06(1,3,4,8,9) +U+677F(0);U+677F(1,3,9),U+95C6(1,3,8,9);U+95C6(1,3,8,9) +U+6780(0);U+677E(3,8,9);U+677E(3,8,9),U+9B06(1,3,4,8,9) +U+6781(0);U+6781(1,3,9),U+6975(1,3,8,9);U+6975(1,3,8,9) +U+6782(0);U+6782(0); +U+6783(0);U+6783(0,9); +U+6784(0);U+6784(1,3,9),U+69CB(1,3,8,9);U+5193(3,9),U+6406(4,9),U+69CB(1,3,8,9) +U+6785(0);U+6785(0,9); +U+6786(0);U+6786(0,9); +U+6787(0);U+6787(5,9);U+673C(3,9) +U+6789(0);U+6789(5,9); +U+678A(0);U+678A(0); +U+678B(0);U+678B(5,9); +U+678C(0);U+678C(0,9); +U+678D(0);U+678D(0,9); +U+678E(0);U+678E(0,9); +U+678F(0);U+6960(2,3,8,9);U+6960(2,3,8,9) +U+6790(0);U+6790(5,9); +U+6791(0);U+6791(3,9); +U+6792(0);U+6792(0,9); +U+6793(0);U+6793(3,9); +U+6794(0);U+6794(0,9); +U+6795(0);U+6795(5,9); +U+6797(0);U+6797(5,9); +U+6798(0);U+6798(5,9); +U+6799(0);U+6799(0,9);U+8F6D(3),U+8EDB(1,3,8,9),U+8EF6(3,9) +U+679A(0);U+679A(5,9); +U+679B(0);U+679B(0); +U+679C(0);U+679C(5,9);U+83D3(2,3) +U+679D(0);U+679D(5,9); +U+679E(0);U+6A05(1,3,8,9);U+6A05(1,3,8,9) +U+679F(0);U+679F(0,9); +U+67A0(0);U+67A0(0); +U+67A1(0);U+67A1(0); +U+67A2(0);U+6A1E(1,3,8,9);U+6A1E(1,3,8,9) +U+67A3(0);U+6806(4);U+6806(4),U+68D7(1,3,8,9) +U+67A4(0);U+67A4(0); +U+67A5(0);U+6AEA(1,3,8,9);U+6AEA(1,3,8,9) +U+67A6(0);U+67A6(0); +U+67A7(0);U+6898(1,3,8);U+6898(1,3,8) +U+67A8(0);U+68D6(1,3,8,9);U+68D6(1,3,8,9) +U+67AA(0);U+69CD(1,3,8,9);U+69CD(1,3,8,9) +U+67AB(0);U+6953(1,3,8,9);U+6953(1,3,8,9) +U+67AC(0);U+67AC(0); +U+67AD(0);U+689F(1,3,8,9);U+689F(1,3,8,9),U+9DCD(3,9) +U+67AE(0);U+67AE(0,9);U+6939(3,9) +U+67AF(0);U+67AF(5,9); +U+67B0(0);U+67B0(5,9);U+6A98(3) +U+67B1(0);U+67B1(3); +U+67B2(0);U+67B2(3,9); +U+67B3(0);U+67B3(5,9); +U+67B4(0);U+67B4(0,9);U+62D0(4,8,9) +U+67B5(0);U+67B5(5,9); +U+67B6(0);U+67B6(5,9); + +U+67B7(0);U+67B7(5,9);U+801E(3,9) +U+67B8(0);U+67B8(5,9); +U+67B9(0);U+67B9(0,9); +U+67BA(0);U+67BA(0,9); +U+67BB(0);U+67BB(3,9); +U+67BC(0);U+67BC(3); +U+67BE(0);U+67FF(7,8,9);U+67FF(7,8,9) +U+67C0(0);U+67C0(0,9); +U+67C1(0);U+67C1(5,9);U+8235(3,8,9) +U+67C2(0);U+67C2(3,9); +U+67C3(0);U+67C3(5,9); +U+67C4(0);U+67C4(5,9); +U+67C5(0);U+67C5(3,9); +U+67C6(0);U+67C6(0,9); +U+67C7(0);U+67C7(0); +U+67C8(0);U+67C8(0,9); +U+67C9(0);U+67C9(0,9); +U+67CA(0);U+67CA(0,9); +U+67CB(0);U+67CB(0,9); +U+67CC(0);U+67CC(3,9); +U+67CD(0);U+67CD(3,9); +U+67CE(0);U+67CE(3,9); +U+67CF(0);U+67CF(5,9);U+6822(2,3,8) +U+67D0(0);U+67D0(5,9); +U+67D1(0);U+67D1(5,9); +U+67D2(0);U+67D2(5,9);U+6F06(3,8,9),U+687C(3,8,9) +U+67D3(0);U+67D3(5,9); +U+67D4(0);U+67D4(5,9); +U+67D6(0);U+67D6(0); +U+67D8(0);U+67D8(5,9); +U+67D9(0);U+67D9(5,9); +U+67DA(0);U+67DA(5,9); +U+67DB(0);U+67DB(0,9); +U+67DC(0);U+67DC(1,3,9),U+6AC3(1,3,8,9);U+6AC3(1,3,8,9) +U+67DD(0);U+67DD(5,9); +U+67DE(0);U+67DE(5,9); +U+67DF(0);U+67DF(0,9); +U+67E0(0);U+6AB8(1,3,8,9);U+6AB8(1,3,8,9) +U+67E1(0);U+67E1(0); +U+67E2(0);U+67E2(5,9); +U+67E3(0);U+67E3(0,9); +U+67E4(0);U+67E4(0,9); +U+67E5(0);U+67E5(5,9);U+67FB(2,8),U+6942(3,8,9) +U+67E6(0);U+67E6(0,9); +U+67E7(0);U+67E7(0,9); +U+67E8(0);U+67E8(0); +U+67E9(0);U+67E9(5,9);U+67FE(3,8) +U+67EA(0);U+67EA(0,9); +U+67EB(0);U+67EB(3,9); +U+67EC(0);U+67EC(5,9); +U+67ED(0);U+67ED(0,9); +U+67EE(0);U+67EE(0,9); +U+67EF(0);U+67EF(5,9); +U+67F0(0);U+67F0(5,9);U+5948(3,8,9) +U+67F1(0);U+67F1(5,9);U+782B(3,9) +U+67F2(0);U+67F2(3,9); +U+67F3(0);U+67F3(5,9); +U+67F4(0);U+67F4(5,9);U+7961(3,9) +U+67F5(0);U+67F5(0,9);U+6805(2,3,8) +U+67F6(0);U+67F6(0,9); +U+67F7(0);U+67F7(3,9); +U+67F8(0);U+67F8(0,9); +U+67FA(0);U+67FA(3,9); + +U+67FB(0);U+67E5(2,8,9);U+67E5(2,8,9),U+6942(2,3,8,9) +U+67FC(0);U+67FC(0,9); +U+67FD(0);U+6A89(1,3,8,9);U+6A89(1,3,8,9) +U+67FE(0);U+67E9(3,8,9);U+67E9(3,8,9) +U+67FF(0);U+67FF(5,9);U+67BE(7,8) +U+6800(0);U+6894(2,3,8,9);U+6894(2,3,8,9) +U+6802(0);U+6802(0); +U+6803(0);U+6803(0); +U+6804(0);U+69AE(8,9);U+69AE(8,9),U+8363(7) +U+6805(0);U+67F5(2,3,8,9);U+67F5(2,3,8,9) +U+6806(0);U+6806(4);U+67A3(1,3,4),U+68D7(1,3,9) +U+6807(0);U+6A19(1,3,8,9);U+5882(3,9),U+6A19(1,3,8,9) +U+6808(0);U+68E7(1,3,8,9);U+68E7(1,3,8,9),U+8F4F(3,9) +U+6809(0);U+6ADB(1,3,8,9);U+6ADB(1,3,8,9) +U+680A(0);U+6AF3(1,3,8,9);U+6AF3(1,3,8,9) +U+680B(0);U+68DF(1,3,8,9);U+68DF(1,3,8,9) +U+680C(0);U+6AE8(1,3,8,9);U+6AE8(1,3,8,9) +U+680D(0);U+680D(0); +U+680E(0);U+6ADF(1,3,8,9);U+6ADF(1,3,8,9) +U+680F(0);U+6B04(1,3,8,9);U+6B04(1,3,8,9),U+6B17(3,9) +U+6810(0);U+6810(0); +U+6811(0);U+6A39(1,3,8,9);U+5C0C(3,9),U+6A39(1,3,8,9) +U+6812(0);U+6812(0,9); +U+6813(0);U+6813(5,9); +U+6814(0);U+6814(0,9);U+5951(3,9) +U+6816(0);U+6816(3,9),U+68F2(2,3,8,9);U+68F2(2,3,8,9) +U+6817(0);U+6817(5,9),U+6144(2,9);U+6144(2,9) +U+6818(0);U+6818(0,9); +U+6819(0);U+6819(0); +U+681A(0);U+681A(0,9); +U+681B(0);U+681B(0); +U+681C(0);U+681C(0,9); +U+681D(0);U+681D(5,9); +U+681F(0);U+681F(0,9); +U+6820(0);U+6820(3,9); +U+6821(0);U+6821(5,9);U+630D(3,9) +U+6822(0);U+67CF(2,3,8,9);U+67CF(2,3,8,9) +U+6823(0);U+6823(0); +U+6824(0);U+6824(0); +U+6825(0);U+6825(0,9); +U+6826(0);U+6826(0,9); +U+6828(0);U+6828(0,9); +U+6829(0);U+6829(5,9); +U+682A(0);U+682A(5,9); +U+682B(0);U+682B(0,9); +U+682C(0);U+682C(0); +U+682D(0);U+682D(3,9); +U+682E(0);U+682E(0,9); +U+682F(0);U+682F(0,9); +U+6831(0);U+6831(0,9); +U+6832(0);U+6832(5,9); +U+6833(0);U+6833(5,9); +U+6834(0);U+6834(0,9); +U+6835(0);U+6835(0,9); +U+6836(0);U+6836(0); +U+6837(0);U+6A23(1,3,8,9);U+69D8(4),U+6A23(1,3,8,9) +U+6838(0);U+6838(5,9);U+69C5(4,8),U+8988(2,3,8,9) +U+6839(0);U+6839(5,9); +U+683A(0);U+683A(0,9); +U+683B(0);U+683B(3,9); +U+683C(0);U+683C(5,9); +U+683D(0);U+683D(5,9); +U+683E(0);U+6B12(1,3,8,9);U+6B12(1,3,8,9) + +U+683F(0);U+683F(0); +U+6840(0);U+6840(5,9);U+69A4(3,9) +U+6841(0);U+6841(5,9);U+822A(3,8,9) +U+6842(0);U+6842(5,9); +U+6843(0);U+6843(5,9); +U+6844(0);U+6844(5,9); +U+6845(0);U+6845(5,9); +U+6846(0);U+6846(5,9); +U+6847(0);U+6847(0); +U+6848(0);U+6848(5,9); +U+6849(0);U+6849(5,9); +U+684A(0);U+684A(5); +U+684B(0);U+684B(0,9); +U+684C(0);U+684C(5,9);U+68F9(3,8,9),U+6AC2(2,3,8,9) +U+684D(0);U+684D(0,9); +U+684E(0);U+684E(5,9); +U+684F(0);U+684F(0,9); +U+6850(0);U+6850(5,9); +U+6851(0);U+6851(5,9);U+6852(3,8) +U+6852(0);U+6851(3,8,9);U+6851(3,8,9) +U+6853(0);U+6853(5,9); +U+6854(0);U+6854(5,9); +U+6855(0);U+6855(5); +U+6856(0);U+6856(0); +U+6857(0);U+6857(0); +U+685B(0);U+685B(0); +U+685D(0);U+685D(0); +U+6860(0);U+690F(4,8,9);U+690F(4,8,9) +U+6861(0);U+6A48(1,3,8,9);U+6A48(1,3,8,9) +U+6862(0);U+6968(1,3,8,9);U+6968(1,3,8,9) +U+6863(0);U+6A94(1,3,8,9);U+6A94(1,3,8,9) +U+6864(0);U+69BF(1,3,8,9);U+69BF(1,3,8,9) +U+6865(0);U+6A4B(1,3,8,9);U+6A4B(1,3,8,9),U+6A47(1,3,8,9),U+97BD(1,3,8),U+9792(1,3,8) + +U+6866(0);U+6A3A(1,3,8,9);U+6A3A(1,3,8,9) +U+6867(0);U+6A9C(1,3,8,9);U+6A9C(1,3,8,9) +U+6868(0);U+69F3(1,3,8,9);U+69F3(1,3,8,9) +U+6869(0);U+6A01(1,3,8,9);U+6A01(1,3,8,9),U+8E56(4,9) +U+686A(0);U+6A33(4,8);U+6A33(4,8) +U+686B(0);U+686B(5,9); +U+686C(0);U+686C(0); +U+686D(0);U+686D(3,9); +U+686E(0);U+686E(0,9);U+676F(2,3,8,9),U+76C3(2,3,8,9) +U+686F(0);U+686F(0,9); +U+6870(0);U+6870(0); +U+6871(0);U+6871(0,9); +U+6872(0);U+6872(0,9); +U+6873(0);U+6873(0); +U+6874(0);U+6874(5,9);U+6CED(3,9) +U+6875(0);U+6875(0,9); +U+6876(0);U+6876(5,9); +U+6877(0);U+6877(5,9); +U+6878(0);U+6878(3,9); +U+6879(0);U+6879(0,9);U+6994(3,4,9) +U+687B(0);U+687B(0,9); +U+687C(0);U+687C(0,9);U+6F06(3,9),U+67D2(3,5,8,9) +U+687D(0);U+687D(0,9); +U+687E(0);U+687E(0,9); +U+687F(0);U+687F(0,9);U+6746(2,3,9) +U+6880(0);U+6880(0,9); +U+6881(0);U+6881(5,9),U+6A11(2,3,9);U+6A11(2,3,9) +U+6882(0);U+6882(0,9); +U+6883(0);U+6883(5,9); + +U+6884(0);U+6884(0); +U+6885(0);U+6885(5,9);U+6973(2,3,8) +U+6886(0);U+6886(5,9); +U+6887(0);U+6887(0,9); +U+6888(0);U+6888(0); +U+6889(0);U+6889(0,9); +U+688A(0);U+688A(0,9); +U+688B(0);U+688B(3,9); +U+688C(0);U+688C(0,9); +U+688D(0);U+688D(0); +U+688E(0);U+688E(0); +U+688F(0);U+688F(5,9); +U+6890(0);U+6890(0,9); +U+6891(0);U+6891(0,9); +U+6892(0);U+6892(0,9); +U+6893(0);U+6893(5,9);U+674D(3,9) +U+6894(0);U+6894(0,9);U+6800(2,3,8) +U+6896(0);U+6896(0,9); +U+6897(0);U+6897(5,9); +U+6898(0);U+6898(0);U+67A7(1,3,8) +U+689A(0);U+689A(0); +U+689B(0);U+689B(0,9); +U+689C(0);U+689C(0,9); +U+689D(0);U+689D(0,9);U+6761(1,3,8) +U+689E(0);U+689E(0); +U+689F(0);U+689F(0,9);U+67AD(1,3,8),U+9DCD(1,3,8,9) +U+68A0(0);U+68A0(3,9); +U+68A1(0);U+68A1(3,9); +U+68A2(0);U+68A2(5,9); +U+68A3(0);U+68A3(3,9); +U+68A4(0);U+68A4(3,9); +U+68A6(0);U+5922(1,3,8,9);U+5922(1,3,8,9) +U+68A7(0);U+68A7(5,9); +U+68A8(0);U+68A8(5,9); +U+68A9(0);U+68A9(0,9); +U+68AA(0);U+68AA(0,9);U+8C46(3,9),U+8373(2,3,9) +U+68AB(0);U+68AB(0,9); +U+68AC(0);U+68AC(0,9); +U+68AD(0);U+68AD(5,9); +U+68AE(0);U+68AE(3,9); +U+68AF(0);U+68AF(5,9); +U+68B0(0);U+68B0(5,9); +U+68B1(0);U+68B1(3,9); +U+68B2(0);U+68B2(0,9);U+68C1(4,8) +U+68B3(0);U+68B3(5,9); +U+68B4(0);U+68B4(0,9); +U+68B5(0);U+68B5(5,9); +U+68B6(0);U+68B6(0); +U+68B7(0);U+68B7(0); +U+68B9(0);U+6AB3(3,8,9);U+69DF(3),U+6AB3(3,8,9) +U+68BB(0);U+68BB(0); +U+68BC(0);U+6AAE(4,8,9);U+6AAE(4,8,9) +U+68BD(0);U+68BD(0); +U+68BE(0);U+68F6(4,8,9);U+68F6(4,8,9) +U+68BF(0);U+69E4(4,8,9);U+69E4(4,8,9) +U+68C0(0);U+6AA2(1,3,4,8,9);U+691C(4),U+6AA2(1,3,4,8,9) +U+68C1(0);U+68B2(4,8,9);U+68B2(4,8,9) +U+68C2(0);U+6B1E(1,3,8,9);U+6B1E(1,3,8,9) +U+68C4(0);U+68C4(0,9);U+5F03(2,3,8) +U+68C6(0);U+68C6(0,9); +U+68C7(0);U+68C7(0,9); +U+68C8(0);U+68C8(0,9); +U+68C9(0);U+68C9(5,9); + +U+68CA(0);U+68CB(2,3,8,9);U+68CB(2,3,8,9),U+7881(2,3,8,9) +U+68CB(0);U+68CB(5,9);U+68CA(2,3,8),U+7881(2,3,8,9) +U+68CC(0);U+68CC(0,9); +U+68CD(0);U+68CD(5,9); +U+68CE(0);U+68CE(0,9); +U+68CF(0);U+68CF(0); +U+68D0(0);U+68D0(0,9); +U+68D1(0);U+68D1(0,9); +U+68D2(0);U+68D2(5,9); +U+68D3(0);U+68D3(0,9); +U+68D4(0);U+68D4(0,9); +U+68D5(0);U+68D5(5,9);U+6936(2,3,8) +U+68D6(0);U+68D6(0,9);U+67A8(1,3,8) +U+68D7(0);U+68D7(0,9);U+67A3(1,3,8),U+6806(4) +U+68D8(0);U+68D8(5,9); +U+68DA(0);U+68DA(5,9); +U+68DB(0);U+68DB(0); +U+68DC(0);U+68DC(0,9); +U+68DD(0);U+68DD(0,9); +U+68DE(0);U+68DE(0,9); +U+68DF(0);U+68DF(0,9);U+680B(1,3,8) +U+68E0(0);U+68E0(5,9); +U+68E1(0);U+68E1(0,9);U+3B4E(1,3) +U+68E3(0);U+68E3(5,9); +U+68E4(0);U+68E4(0,9); +U+68E6(0);U+68E6(0,9); +U+68E7(0);U+68E7(0,9);U+6808(1,3,8),U+8F4F(1,3,8,9) +U+68E8(0);U+68E8(0,9);U+7DAE(4,9) +U+68E9(0);U+68E9(0,9); +U+68EA(0);U+68EA(0,9); +U+68EB(0);U+68EB(0,9); +U+68EC(0);U+68EC(3,9); +U+68ED(0);U+68ED(0); +U+68EE(0);U+68EE(5,9); +U+68EF(0);U+68EF(3,9); +U+68F0(0);U+68F0(5,9);U+7BA0(2,3,9) +U+68F1(0);U+68F1(5,9),U+7A1C(2,3,9);U+7A1C(2,3,9) +U+68F2(0);U+68F2(0,9);U+6816(2,3,8,9) +U+68F3(0);U+68F3(0,9); +U+68F4(0);U+68F4(0,9); +U+68F5(0);U+68F5(5,9); +U+68F6(0);U+68F6(0,9);U+68BE(4,8) +U+68F7(0);U+68F7(0,9); +U+68F8(0);U+68F8(0,9); +U+68F9(0);U+68F9(5,9),U+6AC2(2,3,8,9);U+684C(3,8,9),U+6AC2(2,3,8,9) +U+68FA(0);U+68FA(5,9); +U+68FB(0);U+68FB(0,9); +U+68FC(0);U+68FC(5,9); +U+68FD(0);U+68FD(0,9); +U+68FE(0);U+68FE(0); +U+68FF(0);U+68FF(0); +U+6901(0);U+69E8(2,3,8,9);U+69E8(2,3,8,9) +U+6902(0);U+6902(0); +U+6903(0);U+6903(0); +U+6904(0);U+6904(0,9); +U+6905(0);U+6905(5,9); +U+6906(0);U+6906(0,9); +U+6907(0);U+6907(0,9); +U+6908(0);U+6908(0,9); +U+690A(0);U+690A(0,9); +U+690B(0);U+690B(5,9); +U+690C(0);U+690C(0,9); +U+690D(0);U+690D(5,9); + +U+690E(0);U+690E(5,9); +U+690F(0);U+690F(0,9);U+6860(4,8) +U+6910(0);U+6910(5,9); +U+6911(0);U+6911(0,9); +U+6912(0);U+6912(5,9); +U+6913(0);U+6913(0,9); +U+6914(0);U+6914(0,9); +U+6915(0);U+6915(0,9); +U+6916(0);U+6916(0); +U+6917(0);U+6917(0,9);U+7887(2,3,9) +U+6918(0);U+695A(3,8,9);U+695A(3,8,9),U+6A9A(3,8,9) +U+6919(0);U+6919(0); +U+691A(0);U+691A(0); +U+691B(0);U+691B(0); +U+691C(0);U+6AA2(4,8,9);U+68C0(4),U+6AA2(4,8,9) +U+691D(0);U+69FC(4,8,9);U+69FC(4,8,9),U+89C4(4),U+898F(2,4,8,9) +U+691E(0);U+691E(0); +U+691F(0);U+6ADD(1,3,8,9);U+6ADD(1,3,8,9) +U+6920(0);U+69E7(1,3,8,9);U+69E7(1,3,8,9) +U+6921(0);U+6921(0); +U+6922(0);U+6922(0); +U+6923(0);U+6923(0); +U+6924(0);U+6B0F(1,3,8,9);U+6B0F(1,3,8,9) +U+6925(0);U+6925(0,9); +U+6926(0);U+6926(0); +U+6927(0);U+6927(0); +U+6928(0);U+6928(0); +U+6929(0);U+6929(0); +U+692A(0);U+692A(0,9); +U+692B(0);U+6A3F(4,8,9);U+6A3F(4,8,9) +U+692C(0);U+692C(0); +U+692D(0);U+6A62(1,3,8,9);U+64B1(4,9),U+6955(3),U+6A62(1,3,8,9) +U+692E(0);U+692E(4); +U+692F(0);U+692F(0,9); +U+6930(0);U+6930(5,9); +U+6931(0);U+6931(0); +U+6932(0);U+6932(0,9); +U+6933(0);U+6933(0,9); +U+6934(0);U+6934(5,9);U+846E(3,9) +U+6935(0);U+6935(0,9); +U+6936(0);U+68D5(2,3,8,9);U+68D5(2,3,8,9) +U+6937(0);U+6937(0,9); +U+6938(0);U+6938(3,9); +U+6939(0);U+6939(5,9);U+67AE(3,9) +U+693A(0);U+693A(0); +U+693B(0);U+693B(0,9); +U+693C(0);U+693C(0,9); +U+693D(0);U+693D(5,9); +U+693F(0);U+693F(5,9); +U+6940(0);U+6940(0,9); +U+6941(0);U+6941(0,9); +U+6942(0);U+6942(5,9);U+67E5(3,8,9),U+67FB(2,3,8) +U+6943(0);U+6943(0); +U+6944(0);U+6944(0,9); +U+6945(0);U+6945(0,9); +U+6946(0);U+6946(0); +U+6947(0);U+6947(0); +U+6948(0);U+6948(3,9); +U+6949(0);U+6949(0,9); +U+694A(0);U+694A(0,9);U+6768(1,3,8) +U+694B(0);U+694B(0,9); +U+694C(0);U+694C(0,9); +U+694E(0);U+694E(3,9); + +U+694F(0);U+694F(0,9); +U+6950(0);U+6950(0); +U+6951(0);U+6951(0,9);U+63C6(3,9) +U+6952(0);U+6952(0,9); +U+6953(0);U+6953(0,9);U+67AB(1,3,8) +U+6954(0);U+6954(5,9); +U+6955(0);U+6A62(3,8,9);U+692D(3),U+6A62(3,8,9),U+64B1(0,3,4,9) +U+6956(0);U+6956(0,9); +U+6957(0);U+6957(5,9); +U+6958(0);U+6958(3,9); +U+6959(0);U+6959(3,9); +U+695A(0);U+695A(5,9);U+6918(3,8),U+6A9A(3,9) +U+695B(0);U+695B(0,9); +U+695C(0);U+695C(0,9); +U+695D(0);U+695D(5,9); +U+695E(0);U+695E(5,9); +U+695F(0);U+695F(0,9); +U+6960(0);U+6960(5,9);U+678F(2,3,8) +U+6961(0);U+6986(4,8,9);U+6986(4,8,9) +U+6962(0);U+6962(0,9); +U+6963(0);U+6963(5,9); +U+6964(0);U+6964(3); +U+6965(0);U+6965(0,9); +U+6966(0);U+6966(5,9); +U+6967(0);U+6967(0); +U+6968(0);U+6968(0,9);U+6862(1,3,8) +U+6969(0);U+6969(0,9); +U+696A(0);U+696A(3,9); +U+696B(0);U+696B(5,9); +U+696C(0);U+696C(3,9); +U+696D(0);U+696D(0,9);U+4E1A(1,3,8) +U+696E(0);U+696E(5,9); +U+696F(0);U+696F(0,9); +U+6970(0);U+6970(0,9); +U+6971(0);U+6971(5,9); +U+6972(0);U+6972(0); +U+6973(0);U+6885(2,3,8,9);U+6885(2,3,8,9) +U+6974(0);U+6974(0,9); +U+6975(0);U+6975(0,9);U+6781(1,3,8,9) +U+6976(0);U+6976(0,9); +U+6977(0);U+6977(5,9); +U+6978(0);U+6978(5,9); +U+6979(0);U+6979(5,9); +U+697A(0);U+697A(0,9); +U+697B(0);U+697B(0,9); +U+697C(0);U+6A13(1,3,8,9);U+6A13(1,3,8,9) +U+697D(0);U+6A02(3,8,9);U+4E50(3),U+6A02(3,8,9) +U+697E(0);U+697E(0); +U+697F(0);U+697F(0); +U+6980(0);U+6980(5); +U+6981(0);U+6981(0); +U+6982(0);U+6982(5,9);U+69EA(4,8) +U+6983(0);U+6983(0,9); +U+6984(0);U+6B16(1,3,8,9);U+6B16(1,3,8,9) +U+6985(0);U+6985(0);U+69B2(4,8) +U+6986(0);U+6986(5,9);U+6961(4,8) +U+6987(0);U+6AEC(1,3,8,9);U+6AEC(1,3,8,9),U+85FD(3,9) +U+6988(0);U+6ADA(1,3,8,9);U+6ADA(1,3,8,9) +U+6989(0);U+6AF8(1,3,8,9);U+6AF8(1,3,8,9) +U+698A(0);U+698A(0); +U+698B(0);U+698B(0); +U+698C(0);U+698C(0); +U+698D(0);U+698D(5,9); + +U+698E(0);U+698E(0,9);U+69DA(3),U+6A9F(1,3,8,9) +U+698F(0);U+698F(0); +U+6990(0);U+6990(0,9); +U+6991(0);U+6991(0,9); +U+6992(0);U+6992(0); +U+6993(0);U+6993(3,9); +U+6994(0);U+6994(5,9);U+6879(3,4,9) +U+6995(0);U+6995(5,9); +U+6996(0);U+6996(0,9); +U+6997(0);U+6997(0,9); +U+6998(0);U+77E9(2,3,8,9);U+77E9(2,3,8,9) +U+6999(0);U+6999(0,9); +U+699A(0);U+699A(0,9); +U+699B(0);U+699B(5,9);U+6A3C(3,9),U+7349(4,9) +U+699C(0);U+699C(5,9);U+7253(3,9) +U+699D(0);U+6A27(4,9);U+6A27(4,9),U+8531(3,9) +U+699E(0);U+699E(0,9); +U+69A0(0);U+69A0(0,9); +U+69A1(0);U+69A1(0,9);U+7D20(3,9) +U+69A3(0);U+69A3(0,9); +U+69A4(0);U+69A4(0,9);U+6840(3,9) +U+69A5(0);U+69A5(0,9); +U+69A6(0);U+69A6(3,9);U+5E72(4,9),U+5E79(2,3,9),U+4E7E(1,3,4,8,9),U+4E81(1,2,3,4,8),U+6F27(1,3,4,8,9) +U+69A7(0);U+69A7(5,9); +U+69A8(0);U+69A8(5,9);U+643E(2,3,9),U+91A1(3,9) +U+69A9(0);U+69A9(0,9); +U+69AA(0);U+69AA(0,9);U+6769(4,8) +U+69AB(0);U+69AB(5,9); +U+69AC(0);U+69AC(3,9); +U+69AD(0);U+69AD(5,9); +U+69AE(0);U+69AE(0,9);U+6804(8),U+8363(1,3,8) +U+69AF(0);U+69AF(0,9); +U+69B0(0);U+69B0(0,9); +U+69B1(0);U+69B1(5,9); +U+69B2(0);U+69B2(0);U+6985(4,8) +U+69B3(0);U+69B3(0,9); +U+69B4(0);U+69B4(5,9); +U+69B5(0);U+69B5(0,9); +U+69B6(0);U+69B6(0,9); +U+69B7(0);U+69B7(5,9);U+6409(2,3,9) +U+69B8(0);U+69B8(0); +U+69B9(0);U+69B9(0,9); +U+69BA(0);U+69BA(0); +U+69BB(0);U+69BB(5,9); +U+69BC(0);U+69BC(3,9); +U+69BD(0);U+69BD(0,9); +U+69BE(0);U+69BE(0,9); +U+69BF(0);U+69BF(0,9);U+6864(1,3,8) +U+69C1(0);U+69C1(5,9); +U+69C2(0);U+69C2(0,9); +U+69C3(0);U+69C3(3,9); +U+69C4(0);U+69C4(0,9); +U+69C5(0);U+6838(4,8,9);U+6838(4,8,9),U+8988(2,3,4,8,9) +U+69C6(0);U+69C6(0,9); +U+69C7(0);U+69D9(4,8,9);U+69D9(4,8,9) +U+69C8(0);U+69C8(4); +U+69C9(0);U+69C9(0,9); +U+69CA(0);U+69CA(5,9); +U+69CB(0);U+69CB(0,9);U+6406(2,3,8,9),U+6784(1,3,8,9),U+5193(0,1,3,8,9) +U+69CC(0);U+69CC(5,9); +U+69CD(0);U+69CD(0,9);U+67AA(1,3,8) +U+69CE(0);U+69CE(5,9); + +U+69CF(0);U+69CF(0,9); +U+69D0(0);U+69D0(5,9); +U+69D3(0);U+69D3(0,9);U+6760(2,3,8,9) +U+69D4(0);U+69D4(5,9); +U+69D8(0);U+6A23(4,8,9);U+6837(4),U+6A23(4,8,9) +U+69D9(0);U+69D9(4,9);U+69C7(4,8) +U+69DA(0);U+6A9F(1,3,8,9);U+698E(3,9),U+6A9F(1,3,8,9) +U+69DB(0);U+6ABB(1,3,8,9);U+6ABB(1,3,8,9),U+8F5E(3,9) +U+69DC(0);U+6A87(3,8,9);U+6A87(3,8,9) +U+69DD(0);U+69DD(0); +U+69DE(0);U+69DE(0); +U+69DF(0);U+6AB3(1,3,8,9);U+68B9(3),U+6AB3(1,3,8,9) +U+69E0(0);U+6AE7(1,3,8,9);U+6AE7(1,3,8,9) +U+69E1(0);U+69E1(0); +U+69E2(0);U+69E2(0,9); +U+69E3(0);U+69E3(0); +U+69E4(0);U+69E4(0,9);U+68BF(4,8) +U+69E5(0);U+69E5(3,9);U+6A85(3,9) +U+69E6(0);U+69E6(0,9); +U+69E7(0);U+69E7(0,9);U+6920(1,3,8) +U+69E8(0);U+69E8(0,9);U+6901(2,3,8) +U+69E9(0);U+69E9(0); +U+69EA(0);U+6982(4,8,9);U+6982(4,8,9) +U+69EB(0);U+69EB(0,9); +U+69EC(0);U+69EC(0,9); +U+69ED(0);U+69ED(5,9); +U+69EE(0);U+69EE(0,9); +U+69EF(0);U+69EF(0); +U+69F0(0);U+69F0(0); +U+69F1(0);U+69F1(3,9); +U+69F2(0);U+69F2(5,9); +U+69F3(0);U+69F3(0,9);U+6868(1,3,8) +U+69F4(0);U+69F4(0,9); +U+69F5(0);U+69F5(3); +U+69F6(0);U+69F6(0,9); +U+69F7(0);U+69F7(4,9); +U+69F8(0);U+69F8(3,9); +U+69FA(0);U+69FA(0); +U+69FB(0);U+69FB(0,9); +U+69FC(0);U+69FC(0,9);U+691D(4,8),U+898F(2,9),U+89C4(4) +U+69FD(0);U+69FD(5,9); +U+69FE(0);U+69FE(0,9); +U+69FF(0);U+69FF(5,9); +U+6A00(0);U+6A00(0,9); +U+6A01(0);U+6A01(0,9);U+6869(1,3,8),U+8E56(1,3,4,8,9) +U+6A02(0);U+6A02(0,9);U+4E50(1,3,8),U+697D(3,8) +U+6A04(0);U+6A04(0,9); +U+6A05(0);U+6A05(0,9);U+679E(1,3,8) +U+6A06(0);U+6A06(0,9); +U+6A07(0);U+6A07(0,9); +U+6A08(0);U+6A08(0,9); +U+6A09(0);U+6A09(0,9); +U+6A0A(0);U+6A0A(5,9); +U+6A0B(0);U+6A0B(0); +U+6A0D(0);U+6A0D(0,9); +U+6A0E(0);U+6A0E(0); +U+6A0F(0);U+6A0F(4,9); +U+6A10(0);U+6AD3(2,3,8,9);U+6A79(3),U+6AD3(2,3,8,9),U+8263(3,7,9),U+826A(2,3) +U+6A11(0);U+6A11(0,9);U+6881(2,3,9) +U+6A12(0);U+6A12(0); +U+6A13(0);U+6A13(0,9);U+697C(1,3,8) +U+6A14(0);U+6A14(0,9); +U+6A15(0);U+6A15(0,9); + +U+6A16(0);U+6A16(0,9); +U+6A17(0);U+6A17(5,9); +U+6A18(0);U+6A18(5,9);U+6A55(3,9) +U+6A19(0);U+6A19(0,9);U+6807(1,3,8),U+5882(0,1,3,8,9) +U+6A1A(0);U+6A1A(0); +U+6A1B(0);U+6A1B(3,9);U+673B(3,9) +U+6A1D(0);U+6A1D(3,9); +U+6A1E(0);U+6A1E(0,9);U+67A2(1,3,8) +U+6A1F(0);U+6A1F(5,9); +U+6A20(0);U+6A20(3,9); +U+6A21(0);U+6A21(5,9); +U+6A22(0);U+6A22(0); +U+6A23(0);U+6A23(0,9);U+6837(1,3,8),U+69D8(4,8) +U+6A25(0);U+6A25(0,9); +U+6A26(0);U+6A26(0,9); +U+6A27(0);U+6A27(0,9);U+699D(4),U+8531(3,4,9) +U+6A28(0);U+6A28(5,9); +U+6A29(0);U+6B0A(3,8,9);U+6743(3),U+6B0A(3,8,9) +U+6A2A(0);U+6A6B(4,8,9);U+6A6B(4,8,9) +U+6A2B(0);U+6A2B(0); +U+6A2C(0);U+6A2C(0); +U+6A2D(0);U+6A2D(0); +U+6A2E(0);U+6A2E(0); +U+6A2F(0);U+6AA3(1,3,8,9);U+6AA3(1,3,8,9) +U+6A30(0);U+6A30(0); +U+6A31(0);U+6AFB(1,3,8,9);U+6AFB(1,3,8,9) +U+6A32(0);U+6A32(0,9); +U+6A33(0);U+6A33(0);U+686A(4,8) +U+6A34(0);U+6A34(0,9); +U+6A35(0);U+6A35(5,9); +U+6A36(0);U+6A36(0); +U+6A38(0);U+6A38(0,9);U+6734(1,3,8,9) +U+6A39(0);U+6A39(0,9);U+6811(1,3,8),U+5C0C(0,1,3,8,9) +U+6A3A(0);U+6A3A(0,9);U+6866(1,3,8) +U+6A3B(0);U+6A3B(0,9); +U+6A3C(0);U+6A3C(0,9);U+699B(3,9),U+7349(3,4,9) +U+6A3D(0);U+6A3D(5,9);U+58AB(3,8,9),U+7F47(2,3,8) +U+6A3E(0);U+6A3E(5,9); +U+6A3F(0);U+6A3F(0,9);U+692B(4,8) +U+6A40(0);U+6A40(0,9); +U+6A41(0);U+6A41(3,9); +U+6A42(0);U+6A42(0); +U+6A43(0);U+6A43(3); +U+6A44(0);U+6A44(5,9); +U+6A45(0);U+6A45(0); +U+6A46(0);U+6A46(0,9); +U+6A47(0);U+6A47(5,9);U+6A4B(3,9),U+6865(1,3,8),U+97BD(1,3,8),U+9792(1,3,8) +U+6A48(0);U+6A48(0,9);U+6861(1,3,8) +U+6A49(0);U+6A49(0,9); +U+6A4B(0);U+6A4B(0,9);U+6865(1,3,8),U+6A47(3,9),U+97BD(3),U+9792(1,3,8) +U+6A4C(0);U+6A4C(0); +U+6A4D(0);U+6A4D(0,9); +U+6A4E(0);U+6A4E(0,9); +U+6A4F(0);U+6A4F(0,9); +U+6A50(0);U+6A50(5,9); +U+6A51(0);U+6A51(0,9); +U+6A52(0);U+6A52(0); +U+6A54(0);U+6A54(0,9); +U+6A55(0);U+6A55(0,9);U+6A18(3,9) +U+6A56(0);U+6A56(0,9); +U+6A57(0);U+6A57(0); +U+6A58(0);U+6A58(5,9); +U+6A59(0);U+6A59(5,9); + +U+6A5A(0);U+6A5A(3,9); +U+6A5B(0);U+6A5B(5,9); +U+6A5D(0);U+6A5D(0,9); +U+6A5E(0);U+6A5E(3,9); +U+6A5F(0);U+6A5F(0,9);U+673A(1,3,8,9) +U+6A60(0);U+6A60(0,9); +U+6A61(0);U+6A61(5,9); +U+6A62(0);U+6A62(0,9);U+692D(1,3,8),U+6955(3,8),U+64B1(0,1,3,4,8,9) +U+6A63(0);U+6A63(0); +U+6A64(0);U+6A64(0,9);U+854A(2,3,9),U+854B(2,3,8),U+8602(2,3,8) +U+6A65(0);U+6AEB(3,9);U+6AEB(3,9) +U+6A66(0);U+6A66(0,9); +U+6A67(0);U+6A67(3,9); +U+6A68(0);U+6A68(0,9); +U+6A69(0);U+6A69(0,9); +U+6A6A(0);U+6A6A(4,9); +U+6A6B(0);U+6A6B(0,9);U+6A2A(4,8) +U+6A6C(0);U+6A6C(0); +U+6A6D(0);U+6A6D(0,9); +U+6A6F(0);U+6A6F(0,9); +U+6A71(0);U+6AE5(2,3,8,9);U+6AE5(2,3,8,9) +U+6A72(0);U+6A72(0); +U+6A73(0);U+6A73(0); +U+6A74(0);U+6A74(0); +U+6A75(0);U+6A75(0); +U+6A76(0);U+6A76(0,9); +U+6A77(0);U+6A77(0); +U+6A78(0);U+6A78(0); +U+6A79(0);U+6AD3(1,3,8,9);U+6A10(3),U+6AD3(1,3,8,9),U+8263(7,9),U+826A(2,3) +U+6A7A(0);U+6A7A(0); +U+6A7B(0);U+6A7B(0); +U+6A7C(0);U+6ADE(1,3,8,9);U+6ADE(1,3,8,9) +U+6A7D(0);U+6A7D(0); +U+6A7E(0);U+6A7E(0,9); +U+6A7F(0);U+6A7F(0,9); +U+6A80(0);U+6A80(5,9); +U+6A81(0);U+6A81(0,9);U+6AA9(4,8) +U+6A82(0);U+6A82(0); +U+6A83(0);U+6A83(0,9);U+6AFD(3),U+6ABC(3,8) +U+6A84(0);U+6A84(5,9); +U+6A85(0);U+6A85(0,9);U+69E5(3,9) +U+6A87(0);U+6A87(0,9);U+69DC(3,8) +U+6A88(0);U+6A88(0); +U+6A89(0);U+6A89(0,9);U+67FD(1,3,8) +U+6A8B(0);U+6A8B(3); +U+6A8C(0);U+6A8C(0,9); +U+6A8D(0);U+6A8D(0,9); +U+6A8E(0);U+6A8E(5,9); +U+6A90(0);U+6A90(5,9),U+7C37(2,3,9);U+7C37(2,3,9) +U+6A91(0);U+6A91(5,9); +U+6A92(0);U+6A92(3,9); +U+6A93(0);U+6A93(0,9); +U+6A94(0);U+6A94(0,9);U+6863(1,3,8) +U+6A95(0);U+6A95(0,9); +U+6A96(0);U+6A96(0,9); +U+6A97(0);U+6A97(5,9);U+8617(4,9) +U+6A98(0);U+6A98(0);U+67B0(3,9) +U+6A9A(0);U+6A9A(0,9);U+695A(3,9),U+6918(0,3,8) +U+6A9B(0);U+6A9B(0,9); +U+6A9C(0);U+6A9C(0,9);U+6867(1,3,8) +U+6A9E(0);U+6A9E(0,9); +U+6A9F(0);U+6A9F(0,9);U+69DA(1,3,8),U+698E(0,1,3,8,9) +U+6AA0(0);U+6AA0(5,9); + +U+6AA1(0);U+6AA1(0,9); +U+6AA2(0);U+6AA2(0,9);U+68C0(1,3,8),U+691C(4,8) +U+6AA3(0);U+6AA3(0,9);U+6A2F(1,3,8) +U+6AA4(0);U+6AA4(0,9); +U+6AA5(0);U+6AA5(0,9);U+8223(3),U+8264(3,4,8,9) +U+6AA6(0);U+6AA6(0,9); +U+6AA7(0);U+6AA7(0); +U+6AA8(0);U+6AA8(0,9); +U+6AA9(0);U+6A81(4,8,9);U+6A81(4,8,9) +U+6AAB(0);U+6AAB(5); +U+6AAC(0);U+6AAC(5,9); +U+6AAD(0);U+6AAD(0,9); +U+6AAE(0);U+6AAE(0,9);U+68BC(4,8) +U+6AAF(0);U+6AAF(0,9);U+53F0(1,3,9),U+7C49(1,3,4,9),U+81FA(1,3,4,8,9),U+98B1(1,3,4,8,9) + +U+6AB0(0);U+6AB0(0); +U+6AB2(0);U+6AB2(0); +U+6AB3(0);U+6AB3(0,9);U+68B9(3,8),U+69DF(1,3,8) +U+6AB4(0);U+6AB4(0,9); +U+6AB5(0);U+6AB5(0); +U+6AB6(0);U+6AB6(0,9); +U+6AB7(0);U+6AB7(3,9); +U+6AB8(0);U+6AB8(0,9);U+67E0(1,3,8) +U+6AB9(0);U+6AB9(0,9); +U+6ABA(0);U+6ABA(0,9); +U+6ABB(0);U+6ABB(0,9);U+69DB(1,3,8),U+8F5E(1,3,8,9) +U+6ABC(0);U+6ABC(3);U+6AFD(3,8),U+6A83(0,3,8,9) +U+6ABD(0);U+6ABD(0,9); +U+6ABF(0);U+6ABF(0); +U+6AC1(0);U+6AC1(0); +U+6AC2(0);U+6AC2(0,9);U+68F9(2,3,8,9),U+684C(2,3,5,8,9) +U+6AC3(0);U+6AC3(0,9);U+67DC(1,3,8,9) +U+6AC5(0);U+6AC5(0,9); +U+6AC6(0);U+6AC6(0,9);U+9B41(3,9) +U+6AC7(0);U+6AC7(0,9); +U+6ACA(0);U+6ACA(0); +U+6ACB(0);U+6ACB(0,9); +U+6ACC(0);U+6ACC(0,9);U+8030(3,9) +U+6ACD(0);U+6ACD(3,9); +U+6ACE(0);U+6ACE(3); +U+6ACF(0);U+6ACF(3,9); +U+6AD0(0);U+6AD0(0,9);U+863D(3) +U+6AD1(0);U+6AD1(0,9); +U+6AD2(0);U+6AD2(0); +U+6AD3(0);U+6AD3(0,9);U+6A10(2,3,8),U+6A79(1,3,8),U+8263(2,3,8,9),U+826A(2,3,8) +U+6AD4(0);U+6AD4(0); +U+6AD5(0);U+6AD5(0); +U+6AD6(0);U+6AD6(0); +U+6AD7(0);U+6AD7(0); +U+6AD9(0);U+6AD9(3,9); +U+6ADA(0);U+6ADA(0,9);U+6988(1,3,8) +U+6ADB(0);U+6ADB(0,9);U+6809(1,3,8) +U+6ADC(0);U+6ADC(0,9); +U+6ADD(0);U+6ADD(0,9);U+691F(1,3,8) +U+6ADE(0);U+6ADE(0,9);U+6A7C(1,3,8) +U+6ADF(0);U+6ADF(0,9);U+680E(1,3,8) +U+6AE0(0);U+6AE0(0,9); +U+6AE1(0);U+6AE1(3,9); +U+6AE2(0);U+6AE2(0); +U+6AE3(0);U+6AE3(0); +U+6AE4(0);U+6AE4(0); +U+6AE5(0);U+6AE5(0,9);U+6A71(2,3,8) +U+6AE6(0);U+6AE6(0); + +U+6AE7(0);U+6AE7(0,9);U+69E0(1,3,8) +U+6AE8(0);U+6AE8(0,9);U+680C(1,3,8) +U+6AEA(0);U+6AEA(0,9);U+67A5(1,3,8) +U+6AEB(0);U+6AEB(0,9);U+6A65(3) +U+6AEC(0);U+6AEC(0,9);U+6987(1,3,8),U+85FD(1,3,8,9) +U+6AED(0);U+6AED(0); +U+6AEE(0);U+6AEE(0,9); +U+6AEF(0);U+6AEF(0,9); +U+6AF0(0);U+6AF0(0,9); +U+6AF1(0);U+6AF1(0,9);U+8616(4) +U+6AF2(0);U+6AF2(0); +U+6AF3(0);U+6AF3(0,9);U+680A(1,3,8) +U+6AF4(0);U+6AF4(0); +U+6AF5(0);U+6AF5(0); +U+6AF6(0);U+6AF6(0); +U+6AF7(0);U+6AF7(0); +U+6AF8(0);U+6AF8(0,9);U+6989(1,3,8) +U+6AF9(0);U+6AF9(0,9); +U+6AFA(0);U+6AFA(3,9); +U+6AFB(0);U+6AFB(0,9);U+6A31(1,3,8) +U+6AFC(0);U+6AFC(0,9); +U+6AFD(0);U+6A83(3,9);U+6A83(3,9),U+6ABC(3,8) +U+6AFE(0);U+6AFE(0); +U+6AFF(0);U+6AFF(0); +U+6B00(0);U+6B00(0,9); +U+6B01(0);U+6B01(0); +U+6B02(0);U+6B02(3,9); +U+6B03(0);U+6B03(0,9); +U+6B04(0);U+6B04(0,9);U+680F(1,3,8),U+6B17(1,3,8,9) +U+6B05(0);U+6B05(0); +U+6B06(0);U+6B06(0); +U+6B07(0);U+6B07(3); +U+6B08(0);U+6B08(0,9); +U+6B09(0);U+6B09(0,9);U+4E1B(3),U+53E2(1,3,4,8,9),U+85C2(3,9) +U+6B0A(0);U+6B0A(0,9);U+6743(1,3,8),U+6A29(3,8) +U+6B0B(0);U+6B0B(0,9); +U+6B0C(0);U+6B0C(0); +U+6B0D(0);U+6B0D(0); +U+6B0F(0);U+6B0F(0,9);U+6924(1,3,8) +U+6B10(0);U+6B10(3,9); +U+6B11(0);U+6B11(3,9); +U+6B12(0);U+6B12(0,9);U+683E(1,3,8) +U+6B13(0);U+6B13(0,9); +U+6B14(0);U+6B14(0); +U+6B15(0);U+6B15(0); +U+6B16(0);U+6B16(0,9);U+6984(1,3,8) +U+6B17(0);U+6B17(0,9);U+680F(3),U+6B04(1,3,8,9) +U+6B18(0);U+6B18(0,9); +U+6B19(0);U+6B19(0,9); +U+6B1A(0);U+6B1A(3,9); +U+6B1C(0);U+6B1C(0); +U+6B1D(0);U+9B31(2,3,8,9);U+90C1(2,3,9),U+9B31(2,3,8,9),U+9B30(2,3,4) +U+6B1E(0);U+6B1E(0,9);U+68C2(1,3,8) +U+6B1F(0);U+6B1F(0); +U+6B20(0);U+6B20(5,9); +U+6B21(0);U+6B21(5,9); +U+6B22(0);U+6B61(1,3,8,9);U+61FD(4,9),U+6B53(3),U+6B61(1,3,8,9),U+8B99(4,9),U+9A69(4,9) + +U+6B23(0);U+6B23(5,9); +U+6B24(0);U+6B5F(1,3,8,9);U+6B5F(1,3,8,9) +U+6B25(0);U+6B25(0,9); +U+6B26(0);U+6B26(0); +U+6B27(0);U+6B50(1,3,8,9);U+6B50(1,3,8,9) + +U+6B28(0);U+6B28(0,9); +U+6B29(0);U+6B29(0); +U+6B2A(0);U+6B2A(0); +U+6B2B(0);U+6B2B(0); +U+6B2C(0);U+6B2C(0,9); +U+6B2D(0);U+6B2D(0,9); +U+6B2F(0);U+6B2F(3,9); +U+6B30(0);U+6B30(0); +U+6B31(0);U+6B31(0,9); +U+6B32(0);U+6B32(5,9),U+617E(2,8,9);U+617E(2,8,9) +U+6B33(0);U+6B33(0,9);U+559F(3,9),U+5633(3,9) +U+6B34(0);U+6B34(0,9); +U+6B36(0);U+6B36(0,9);U+55FD(3,9) +U+6B37(0);U+6B37(5,9); +U+6B38(0);U+6B38(4,9);U+8A92(4,9),U+8BF6(1,3,4,8) +U+6B39(0);U+6B39(5,9); +U+6B3A(0);U+6B3A(5,9); +U+6B3B(0);U+6B3B(4,9); +U+6B3C(0);U+6B3C(0,9); +U+6B3D(0);U+6B3D(0,9);U+94A6(1,3,8) +U+6B3E(0);U+6B3E(5,9); +U+6B3F(0);U+6B3F(3,9); +U+6B41(0);U+6B41(0,9); +U+6B42(0);U+6B42(0,9); +U+6B43(0);U+6B43(5,9); +U+6B44(0);U+6B44(0); +U+6B45(0);U+6B45(0,9); +U+6B46(0);U+6B46(5,9); +U+6B47(0);U+6B47(5,9); +U+6B48(0);U+6B48(0,9); +U+6B49(0);U+6B49(5,9); +U+6B4A(0);U+6B4A(3,9); +U+6B4B(0);U+6B4B(0,9); +U+6B4C(0);U+6B4C(5,9); +U+6B4D(0);U+6B4D(3,9); +U+6B4E(0);U+6B4E(0,9);U+53F9(4),U+5606(1,3,4,8,9) +U+6B4F(0);U+6B4F(0); +U+6B50(0);U+6B50(0,9);U+6B27(1,3,8) +U+6B51(0);U+6B51(0,9); +U+6B52(0);U+6B52(0); +U+6B53(0);U+6B61(3,8,9);U+6B22(3),U+6B61(3,8,9),U+61FD(0,3,4,9),U+8B99(3,4,9),U+9A69(3,4,9) + +U+6B54(0);U+6B54(4,9); +U+6B55(0);U+6B55(0,9);U+55B7(3),U+5674(1,3,8,9) +U+6B56(0);U+6B56(0,9); +U+6B59(0);U+6B59(5,9); +U+6B5A(0);U+6B5A(0); +U+6B5B(0);U+6B5B(0,9);U+655B(3),U+6582(2,3,8,9) +U+6B5C(0);U+6B5C(0,9); +U+6B5E(0);U+6B5E(0,9); +U+6B5F(0);U+6B5F(0,9);U+6B24(1,3,8) +U+6B60(0);U+6B60(4,9); +U+6B61(0);U+6B61(0,9);U+61FD(2,3,8,9),U+6B22(1,3,8),U+6B53(3,8),U+8B99(2,8,9),U+9A69(2,8,9) + +U+6B62(0);U+6B62(5,9); +U+6B63(0);U+6B63(5,9); +U+6B64(0);U+6B64(5,9); +U+6B65(0);U+6B65(5,9);U+6B69(4,8) +U+6B66(0);U+6B66(5,9); +U+6B67(0);U+6B67(5,9);U+5C90(3,8,9) +U+6B69(0);U+6B65(4,8,9);U+6B65(4,8,9) +U+6B6A(0);U+6B6A(5,9); +U+6B6B(0);U+6B6B(0); + +U+6B6D(0);U+6B6D(0,9); +U+6B6F(0);U+9F52(3,8,9);U+9F52(3,8,9),U+9F7F(3) +U+6B70(0);U+6B70(0); +U+6B72(0);U+6B72(0,9);U+4E97(3,8),U+5C81(1,3,8),U+6B73(4,8) +U+6B73(0);U+6B72(4,8,9);U+4E97(7),U+5C81(4),U+6B72(4,8,9) +U+6B74(0);U+6B77(2,3,8,9);U+5386(2,3),U+6B77(2,3,8,9),U+53A4(2,3,4,9),U+66A6(2,3,4),U+66C6(1,2,3,8,9) +U+6B76(0);U+6B76(0,9); +U+6B77(0);U+6B77(0,9);U+5386(1,3,8),U+66C6(3,4,9),U+6B74(2,3,8),U+53A4(1,3,4,8,9),U+66A6(1,3,4,8) + +U+6B78(0);U+6B78(0,9);U+5E30(3,8),U+5F52(1,3,8),U+7688(3,8,9) +U+6B79(0);U+6B79(5,9);U+6B7A(3,8) +U+6B7A(0);U+6B79(3,8,9);U+6B79(3,8,9) +U+6B7B(0);U+6B7B(5,9); +U+6B7C(0);U+6BB2(1,3,8,9);U+6BB2(1,3,8,9) +U+6B7E(0);U+6B7E(4,9); +U+6B7F(0);U+6B7F(0,9);U+6B81(4,8) +U+6B80(0);U+6B80(0,9);U+592D(2,3,8,9) +U+6B81(0);U+6B7F(4,8,9);U+6B7F(4,8,9) +U+6B82(0);U+6B82(5,9); +U+6B83(0);U+6B83(5,9); +U+6B84(0);U+6B84(5,9); +U+6B85(0);U+6B85(0); +U+6B86(0);U+6B86(5,9); +U+6B87(0);U+6BA4(1,3,8,9);U+6BA4(1,3,8,9) +U+6B88(0);U+6B88(0,9); +U+6B89(0);U+6B89(5,9); +U+6B8A(0);U+6B8A(5,9); +U+6B8B(0);U+6B98(1,3,8,9);U+6B98(1,3,8,9) +U+6B8C(0);U+6B8C(0,9); +U+6B8D(0);U+6B8D(5,9); +U+6B8E(0);U+6B8E(0,9); +U+6B8F(0);U+6B8F(0,9); +U+6B90(0);U+6B90(0); +U+6B91(0);U+6B91(0,9); +U+6B92(0);U+6B9E(1,3,8,9);U+6B9E(1,3,8,9) +U+6B93(0);U+6BAE(1,3,8,9);U+6BAE(1,3,8,9) +U+6B94(0);U+6B94(0,9); +U+6B95(0);U+6B95(0,9);U+8E23(3,9) +U+6B96(0);U+6B96(5,9); +U+6B97(0);U+6B97(3,9); +U+6B98(0);U+6B98(0,9);U+6B8B(1,3,8) +U+6B99(0);U+6B99(0,9); +U+6B9A(0);U+6BAB(1,3,8,9);U+6BAB(1,3,8,9) +U+6B9B(0);U+6B9B(5,9); +U+6B9C(0);U+6B9C(0); +U+6B9D(0);U+6B9D(0); +U+6B9E(0);U+6B9E(0,9);U+6B92(1,3,8) +U+6B9F(0);U+6B9F(0,9); +U+6BA0(0);U+6BA0(0,9);U+81ED(3,9) +U+6BA1(0);U+6BAF(1,3,8,9);U+6BAF(1,3,8,9) +U+6BA2(0);U+6BA2(0,9); +U+6BA3(0);U+6BA3(0,9); +U+6BA4(0);U+6BA4(0,9);U+6B87(1,3,8) +U+6BA5(0);U+6BA5(0,9); +U+6BA6(0);U+6BA6(0,9); +U+6BA7(0);U+6BA7(0,9); +U+6BA8(0);U+6BA8(0);U+3C6E(1,3) +U+6BA9(0);U+6BA9(0); +U+6BAA(0);U+6BAA(5,9); +U+6BAB(0);U+6BAB(0,9);U+6B9A(1,3,8) +U+6BAC(0);U+6BAC(3); +U+6BAD(0);U+6BAD(0,9);U+50F5(2,3,9) + +U+6BAE(0);U+6BAE(0,9);U+6B93(1,3,8) +U+6BAF(0);U+6BAF(0,9);U+6BA1(1,3,8) +U+6BB0(0);U+6BB0(0,9); +U+6BB2(0);U+6BB2(0,9);U+6B7C(1,3,8) +U+6BB3(0);U+6BB3(5,9);U+6778(3,9) +U+6BB4(0);U+6BC6(1,3,8,9);U+6BC6(1,3,8,9) +U+6BB5(0);U+6BB5(5,9); +U+6BB6(0);U+6BB6(0,9); +U+6BB7(0);U+6BB7(5,9),U+6147(2,3,9);U+6147(2,3,9) +U+6BB9(0);U+6BB9(0); +U+6BBA(0);U+6BBA(0,9);U+6740(1,3,8),U+95B7(1,3,8,9) +U+6BBB(0);U+6BBC(3,8,9);U+58F3(1,3,8),U+6BBC(3,8,9) +U+6BBC(0);U+6BBC(0,9);U+58F3(4,8),U+6BBB(3,8) +U+6BBD(0);U+6BBD(0,9); +U+6BBE(0);U+6BBE(0); +U+6BBF(0);U+6BBF(5,9); +U+6BC0(0);U+6BC0(0,9);U+6BC1(4,8),U+8B6D(2,3,4,8,9) +U+6BC1(0);U+6BC0(4,8,9);U+6BC0(4,8,9),U+8B6D(2,3,9) +U+6BC2(0);U+8F42(1,3,8,9);U+8F42(1,3,8,9),U+8EF2(1,3,8),U+8F71(1,3,4,8) +U+6BC3(0);U+6BC3(0,9);U+6572(3,9) +U+6BC4(0);U+6BC4(0,9); +U+6BC5(0);U+6BC5(5,9); +U+6BC6(0);U+6BC6(0,9);U+6BB4(1,3,8) +U+6BC7(0);U+6BC7(0,9); +U+6BC8(0);U+6BC8(3,9); +U+6BC9(0);U+6BC9(0,9);U+533B(3),U+91AB(1,3,8,9) +U+6BCA(0);U+6BCA(0,9); +U+6BCB(0);U+6BCB(5,9); +U+6BCC(0);U+6BCC(0,9); +U+6BCD(0);U+6BCD(5,9); +U+6BCE(0);U+6BCF(4,8,9);U+6BCF(4,8,9) +U+6BCF(0);U+6BCF(5,9);U+6BCE(4,8) +U+6BD0(0);U+6BD0(0,9); +U+6BD1(0);U+6BD1(0); +U+6BD2(0);U+6BD2(5,9); +U+6BD3(0);U+6BD3(5,9); +U+6BD4(0);U+6BD4(5,9); +U+6BD5(0);U+7562(1,3,8,9);U+7562(1,3,8,9),U+7F7C(3,9),U+93CE(3,9) +U+6BD6(0);U+6BD6(5,9); +U+6BD7(0);U+6BD7(5,9);U+6BD8(2,3,8,9) +U+6BD8(0);U+6BD8(0,9);U+6BD7(2,3,8,9) +U+6BD9(0);U+6583(1,3,8,9);U+6583(1,3,8,9) +U+6BDA(0);U+6BDA(0,9); +U+6BDB(0);U+6BDB(5,9); +U+6BDC(0);U+6BDC(0); +U+6BDD(0);U+6BDD(0); +U+6BDE(0);U+6BDE(3,9); +U+6BDF(0);U+6BDF(0); +U+6BE0(0);U+6BE0(0,9);U+8888(3,9) +U+6BE1(0);U+6C08(1,3,8,9);U+6C08(1,3,8,9) +U+6BE2(0);U+6BE2(0,9); +U+6BE3(0);U+6BE3(0,9); +U+6BE4(0);U+6BE4(0,9);U+6BFB(3,9) +U+6BE5(0);U+6BE5(0); +U+6BE6(0);U+6BE6(0,9); +U+6BE7(0);U+6BE7(0,9);U+7ED2(2),U+7D68(1,2,3,8,9),U+7FA2(2,9) +U+6BE8(0);U+6BE8(0,9); +U+6BEA(0);U+6BEA(5); +U+6BEB(0);U+6BEB(5,9); +U+6BEC(0);U+6BEC(3,9);U+7403(2,3,8,9) +U+6BED(0);U+6BED(0); +U+6BEE(0);U+6BEE(0); +U+6BEF(0);U+6BEF(5,9); + +U+6BF0(0);U+6BF0(0,9); +U+6BF2(0);U+6BF2(0,9); +U+6BF3(0);U+6BF3(5,9); +U+6BF5(0);U+6BFF(1,3,8,9);U+6BFF(1,3,8,9) +U+6BF6(0);U+6BF6(0); +U+6BF7(0);U+6BF7(0,9); +U+6BF8(0);U+6BF8(0,9); +U+6BF9(0);U+6BF9(5,9); +U+6BFB(0);U+6BFB(3,9);U+6BE4(3,9) +U+6BFC(0);U+6BFC(0,9); +U+6BFD(0);U+6BFD(5,9); +U+6BFE(0);U+6BFE(0,9); +U+6BFF(0);U+6BFF(0,9);U+6BF5(1,3,8) +U+6C00(0);U+6C00(0,9); +U+6C01(0);U+6C01(0,9); +U+6C02(0);U+6C02(0,9);U+7266(2,3),U+729B(2,3,8,9),U+9AE6(2,3,9) +U+6C03(0);U+6C03(0,9); +U+6C04(0);U+6C04(0,9); +U+6C05(0);U+6C05(5,9); +U+6C06(0);U+6C06(5,9); +U+6C07(0);U+6C0C(1,3,8,9);U+6C0C(1,3,8,9) +U+6C08(0);U+6C08(0,9);U+6BE1(1,3,8) +U+6C09(0);U+6C09(0,9); +U+6C0B(0);U+6C0B(0,9); +U+6C0C(0);U+6C0C(0,9);U+6C07(1,3,8) +U+6C0D(0);U+6C0D(5,9); +U+6C0E(0);U+6C0E(0); +U+6C0F(0);U+6C0F(5,9); +U+6C10(0);U+6C10(5,9); +U+6C11(0);U+6C11(5,9); +U+6C12(0);U+6C12(0); +U+6C13(0);U+6C13(5,9);U+753F(4,9) +U+6C14(0);U+6C23(1,3,8,9);U+6C23(1,3,8,9) +U+6C15(0);U+6C15(5,9); +U+6C16(0);U+6C16(5,9); +U+6C18(0);U+6C18(5,9); +U+6C19(0);U+6C19(5,9); +U+6C1A(0);U+6C1A(5,9); +U+6C1B(0);U+6C1B(5,9);U+96F0(2,3,9) +U+6C1D(0);U+6C1D(0,9); +U+6C1E(0);U+6C1E(0); +U+6C1F(0);U+6C1F(5,9); +U+6C20(0);U+6C20(0,9); +U+6C21(0);U+6C21(5,9); +U+6C22(0);U+6C2B(1,3,8,9);U+6C2B(1,3,8,9) +U+6C23(0);U+6C23(0,9);U+6C14(1,3,8,9) +U+6C24(0);U+6C24(5,9); +U+6C25(0);U+6C25(0,9); +U+6C26(0);U+6C26(5,9); +U+6C27(0);U+6C27(5,9); +U+6C28(0);U+6C28(5,9); +U+6C29(0);U+6C2C(1,3,8,9);U+6C2C(1,3,8,9) +U+6C2A(0);U+6C2A(5,9); +U+6C2B(0);U+6C2B(0,9);U+6C22(1,3,8) +U+6C2C(0);U+6C2C(0,9);U+6C29(1,3,8) +U+6C2E(0);U+6C2E(5,9); +U+6C2F(0);U+6C2F(5,9); +U+6C30(0);U+6C30(5,9); +U+6C31(0);U+6C31(0); +U+6C32(0);U+6C33(4,8,9);U+6C33(4,8,9) +U+6C33(0);U+6C33(0,9);U+6C32(4,8) +U+6C34(0);U+6C34(5,9); +U+6C35(0);U+6C35(5); + +U+6C36(0);U+6C36(0,9); +U+6C37(0);U+51B0(2,3,8,9);U+51B0(2,3,8,9) +U+6C38(0);U+6C38(5,9); +U+6C3A(0);U+6C3A(0); +U+6C3B(0);U+6C3B(0,9); +U+6C3D(0);U+6C3D(5); +U+6C3E(0);U+6C3E(3,9);U+6C4E(3,9),U+6CDB(2,3,8,9) +U+6C3F(0);U+6C3F(3,9); +U+6C40(0);U+6C40(5,9); +U+6C41(0);U+6C41(5,9); +U+6C42(0);U+6C42(5,9); +U+6C43(0);U+6C43(0,9); +U+6C44(0);U+6C44(0); +U+6C46(0);U+6C46(5,9); +U+6C47(0);U+532F(1,3,8,9),U+5F59(1,3,8,9);U+532F(1,3,8,9),U+5F59(1,3,8,9),U+5F5A(4),U+6ED9(4) +U+6C48(0);U+6C48(0); +U+6C49(0);U+6F22(1,3,8,9);U+6F22(1,3,8,9) +U+6C4A(0);U+6C4A(5,9); +U+6C4B(0);U+6C4B(0,9); +U+6C4C(0);U+6C4C(0,9); +U+6C4D(0);U+6C4D(0,9); +U+6C4E(0);U+6C4E(0,9);U+6C3E(3,9),U+6CDB(2,3,8,9) +U+6C4F(0);U+6C4F(0,9);U+6C70(3,9),U+6E99(3,9) +U+6C50(0);U+6C50(5,9); +U+6C51(0);U+6C51(0); +U+6C52(0);U+6C52(0,9);U+832B(3,9) +U+6C53(0);U+6C53(0); +U+6C54(0);U+6C54(5,9); +U+6C55(0);U+6C55(5,9); +U+6C56(0);U+6C56(0); +U+6C57(0);U+6C57(5,9); +U+6C58(0);U+6C58(0); +U+6C59(0);U+6C59(0,9);U+6C5A(3,8),U+6C61(2,3,8,9) +U+6C5A(0);U+6C61(2,9);U+6C59(3,8,9),U+6C61(2,9) +U+6C5B(0);U+6C5B(5,9); +U+6C5C(0);U+6C5C(5,9);U+6D0D(4,9) +U+6C5D(0);U+6C5D(5,9); +U+6C5E(0);U+6C5E(5,9); +U+6C5F(0);U+6C5F(5,9); +U+6C60(0);U+6C60(5,9); +U+6C61(0);U+6C61(5,9),U+6C59(2,3,8,9);U+6C59(2,3,8,9),U+6C5A(2) +U+6C62(0);U+6C62(0); +U+6C63(0);U+6C63(0); +U+6C64(0);U+6E6F(1,3,8,9);U+6E6F(1,3,8,9) +U+6C65(0);U+6C65(0,9); +U+6C66(0);U+6C66(0,9); +U+6C67(0);U+6C67(0,9); +U+6C68(0);U+6C68(5,9); +U+6C69(0);U+6C69(5,9); +U+6C6A(0);U+6C6A(5,9);U+7007(3,9) +U+6C6B(0);U+6C6B(0,9); +U+6C6D(0);U+6C6D(0,9); +U+6C6F(0);U+6C6F(0,9); +U+6C70(0);U+6C70(5,9);U+6C4F(3,9),U+6E99(3,9) +U+6C71(0);U+6C71(0,9); +U+6C72(0);U+6C72(5,9); +U+6C73(0);U+6C73(0,9); +U+6C74(0);U+6C74(5,9); +U+6C75(0);U+6C75(0); +U+6C76(0);U+6C76(5,9); +U+6C77(0);U+6C77(0); +U+6C78(0);U+6C78(3,9);U+6DD3(3,9) + +U+6C79(0);U+6D36(2,3,8,9);U+6D36(2,3,8,9) +U+6C7A(0);U+6C7A(0,9);U+51B3(2,3,8) +U+6C7B(0);U+6C7B(0,9);U+6D52(3),U+6EF8(1,3,8,9) +U+6C7C(0);U+6C7C(0); +U+6C7D(0);U+6C7D(5,9);U+6ECA(3,9) +U+6C7E(0);U+6C7E(5,9); +U+6C7F(0);U+6C7F(3); +U+6C80(0);U+6C80(0,9); +U+6C81(0);U+6C81(5,9); +U+6C82(0);U+6C82(5,9); +U+6C83(0);U+6C83(5,9); +U+6C84(0);U+6C84(0,9); +U+6C85(0);U+6C85(5,9); +U+6C86(0);U+6C86(5,9); +U+6C87(0);U+6C87(3,9); +U+6C88(0);U+6C88(1,9),U+700B(1,3,8,9);U+6C89(3,9),U+6E16(4),U+700B(1,3,8,9) +U+6C89(0);U+6C89(5,9);U+6C88(3,9),U+6E16(3,4),U+700B(1,3,8,9) +U+6C8A(0);U+6C8A(0,9); +U+6C8B(0);U+6C8B(0,9); +U+6C8C(0);U+6C8C(5,9); +U+6C8D(0);U+6C8D(3,9);U+51B1(3,8,9) +U+6C8E(0);U+6C8E(0,9); +U+6C8F(0);U+6C8F(5,9); +U+6C90(0);U+6C90(5,9); +U+6C91(0);U+6C91(0); +U+6C92(0);U+6C92(0,9);U+6CA1(3,8) +U+6C93(0);U+6C93(5,9); +U+6C94(0);U+6C94(5,9); +U+6C95(0);U+6C95(0,9); +U+6C96(0);U+6C96(0,9);U+51B2(3,4,8),U+76C5(3,8,9),U+885D(3,4,9),U+794C(3,4,8,9),U+8876(3,4,8,9) + +U+6C97(0);U+6C97(0); +U+6C98(0);U+6C98(0,9); +U+6C99(0);U+6C99(5,9); +U+6C9A(0);U+6C9A(3,9); +U+6C9B(0);U+6C9B(5,9);U+4F02(3,9) +U+6C9C(0);U+6C9C(3,9); +U+6C9D(0);U+6C9D(0,9); +U+6C9E(0);U+6C9E(0); +U+6C9F(0);U+6E9D(1,3,8,9);U+6E9D(1,3,8,9) +U+6CA1(0);U+6C92(3,8,9);U+6C92(3,8,9) +U+6CA2(0);U+6FA4(4,8,9);U+6CFD(4),U+6FA4(4,8,9) +U+6CA3(0);U+7043(1,3,8,9);U+7043(1,3,8,9) +U+6CA4(0);U+6F1A(1,3,8,9);U+6F1A(1,3,8,9) +U+6CA5(0);U+701D(1,3,8,9);U+701D(1,3,8,9) +U+6CA6(0);U+6DEA(1,3,8,9);U+6DEA(1,3,8,9) +U+6CA7(0);U+6EC4(1,3,8,9);U+6EC4(1,3,8,9) +U+6CA8(0);U+6E22(1,3,8,9);U+6E22(1,3,8,9) +U+6CA9(0);U+6E88(4,9);U+6E88(4,9),U+6F59(1,3,8) +U+6CAA(0);U+6EEC(1,3,8,9);U+6EEC(1,3,8,9) +U+6CAB(0);U+6CAB(5,9); +U+6CAC(0);U+6CAC(3,9); +U+6CAD(0);U+6CAD(5,9); +U+6CAE(0);U+6CAE(5,9); +U+6CAF(0);U+6CAF(0); +U+6CB0(0);U+6CB0(0,9); +U+6CB1(0);U+6CB1(5,9);U+6CB2(3,8) +U+6CB2(0);U+6CB1(3,8,9);U+6CB1(3,8,9) +U+6CB3(0);U+6CB3(5,9); +U+6CB4(0);U+6CB4(3,9); +U+6CB5(0);U+6FD4(4,8,9);U+6FD4(4,8,9) +U+6CB6(0);U+6CB6(0,9); +U+6CB7(0);U+6CB7(0,9); + +U+6CB8(0);U+6CB8(5,9); +U+6CB9(0);U+6CB9(5,9); +U+6CBA(0);U+6CBA(0,9); +U+6CBB(0);U+6CBB(5,9); +U+6CBC(0);U+6CBC(5,9); +U+6CBD(0);U+6CBD(5,9); +U+6CBE(0);U+6CBE(5,9),U+9711(2,3,9);U+9711(2,3,9) +U+6CBF(0);U+6CBF(5,9); +U+6CC0(0);U+6CC0(0,9); +U+6CC1(0);U+6CC1(0,9);U+51B5(2,4,8) +U+6CC2(0);U+6CC2(0,9); +U+6CC3(0);U+6CC3(0,9); +U+6CC4(0);U+6CC4(5,9),U+6D29(2,3,8,9);U+6D29(2,3,8,9),U+6E2B(3,8,9) +U+6CC5(0);U+6CC5(5,9); +U+6CC6(0);U+6CC6(3,9); +U+6CC7(0);U+6CC7(0,9); +U+6CC8(0);U+6CC8(0); +U+6CC9(0);U+6CC9(5,9); +U+6CCA(0);U+6CCA(5,9);U+6FFC(3,8,9),U+6CFA(1,3,8) +U+6CCB(0);U+6CCB(0); +U+6CCC(0);U+6CCC(5,9); +U+6CCD(0);U+6CCD(0,9); +U+6CCE(0);U+6CCE(0); +U+6CCF(0);U+6CCF(0,9); +U+6CD0(0);U+6CD0(5,9); +U+6CD1(0);U+6CD1(0,9); +U+6CD2(0);U+6CD2(0,9);U+6D3E(4,9) +U+6CD3(0);U+6CD3(5,9); +U+6CD4(0);U+6CD4(5,9); +U+6CD5(0);U+6CD5(5,9); +U+6CD6(0);U+6CD6(5,9); +U+6CD7(0);U+6CD7(5,9); +U+6CD9(0);U+6CD9(0,9); +U+6CDA(0);U+6CDA(0,9); +U+6CDB(0);U+6CDB(5,9),U+6C3E(2,3,8,9),U+6C4E(2,3,8,9);U+6C3E(2,3,8,9),U+6C4E(2,3,8,9) + +U+6CDC(0);U+6CDC(0,9); +U+6CDD(0);U+6CDD(0,9);U+6EAF(3,4,8,9),U+9061(3) +U+6CDE(0);U+6CDE(1,3,9),U+6FD8(1,3,8,9);U+6FD8(1,3,8,9) +U+6CDF(0);U+6CDF(0); +U+6CE0(0);U+6CE0(5,9);U+6FAA(3,9) +U+6CE1(0);U+6CE1(5,9); +U+6CE2(0);U+6CE2(5,9); +U+6CE3(0);U+6CE3(5,9); +U+6CE4(0);U+6CE4(0); +U+6CE5(0);U+6CE5(5,9); +U+6CE6(0);U+6CE6(3);U+6DD7(3,9) +U+6CE7(0);U+6CE7(0,9); +U+6CE8(0);U+6CE8(5,9),U+8A3B(2,3,8,9);U+8A3B(2,3,8,9) +U+6CE9(0);U+6CE9(0,9); +U+6CEA(0);U+6DDA(2,3,8,9);U+6D99(4),U+6DDA(2,3,8,9) +U+6CEB(0);U+6CEB(5,9); +U+6CEC(0);U+6CEC(0,9); +U+6CED(0);U+6CED(0,9);U+6874(3,9) +U+6CEE(0);U+6CEE(5,9); +U+6CEF(0);U+6CEF(5,9); +U+6CF0(0);U+6CF0(5,9); +U+6CF1(0);U+6CF1(5,9); +U+6CF2(0);U+6CF2(0,9); +U+6CF3(0);U+6CF3(5,9); +U+6CF5(0);U+6CF5(5,9); +U+6CF6(0);U+6FA9(4,8,9);U+6FA9(4,8,9) +U+6CF7(0);U+7027(1,3,8,9);U+7027(1,3,8,9) + +U+6CF8(0);U+7018(1,3,8,9);U+7018(1,3,8,9) +U+6CF9(0);U+6CF9(0,9); +U+6CFA(0);U+6FFC(1,3,8,9);U+6FFC(1,3,8,9),U+6CCA(1,3,5,8,9) +U+6CFB(0);U+7009(1,3,8,9);U+7009(1,3,8,9) +U+6CFC(0);U+6F51(1,3,8,9);U+6F51(1,3,8,9) +U+6CFD(0);U+6FA4(1,3,8,9);U+6CA2(4),U+6FA4(1,3,8,9) +U+6CFE(0);U+6D87(1,3,8,9);U+6D87(1,3,8,9) +U+6CFF(0);U+6CFF(0); +U+6D00(0);U+6D00(0,9);U+76D8(3),U+76E4(1,3,8,9) +U+6D01(0);U+6D01(1,3,9),U+6F54(1,3,8,9);U+6D2F(2,3,9),U+6F54(1,3,8,9) +U+6D03(0);U+6D03(0,9); +U+6D04(0);U+6D04(5,9); +U+6D05(0);U+6D05(0); +U+6D06(0);U+6D06(0); +U+6D07(0);U+6D07(5,9); +U+6D08(0);U+6D08(0,9); +U+6D09(0);U+6D09(0,9); +U+6D0A(0);U+6D0A(0,9); +U+6D0B(0);U+6D0B(5,9); +U+6D0C(0);U+6D0C(5,9);U+51BD(3,8,9) +U+6D0D(0);U+6D0D(0,9);U+6C5C(4,9) +U+6D0E(0);U+6D0E(5,9); +U+6D0F(0);U+6D0F(3,9); +U+6D10(0);U+6D10(0,9); +U+6D11(0);U+6D11(3,9); +U+6D12(0);U+7051(1,3,8,9);U+7051(1,3,8,9) +U+6D13(0);U+6D13(0); +U+6D14(0);U+6D14(0); +U+6D15(0);U+6D15(0); +U+6D16(0);U+6D16(0,9); +U+6D17(0);U+6D17(5,9); +U+6D18(0);U+6D18(0,9); +U+6D19(0);U+6D19(5,9); +U+6D1A(0);U+6D1A(5,9); +U+6D1B(0);U+6D1B(5,9); +U+6D1D(0);U+6D1D(0,9); +U+6D1E(0);U+6D1E(5,9); +U+6D1F(0);U+6D1F(0,9); +U+6D20(0);U+6D20(0,9); +U+6D21(0);U+6D21(0); +U+6D22(0);U+6D22(0,9);U+4F0A(3,9) +U+6D23(0);U+6D23(0); +U+6D25(0);U+6D25(5,9); +U+6D26(0);U+6D26(4); +U+6D27(0);U+6D27(5,9); +U+6D28(0);U+6D28(0,9); +U+6D29(0);U+6D29(0,9);U+6CC4(2,3,8,9),U+6E2B(2,3,8,9) +U+6D2A(0);U+6D2A(5,9); +U+6D2B(0);U+6D2B(5,9); +U+6D2C(0);U+6D2C(0,9); +U+6D2D(0);U+6D2D(0,9); +U+6D2E(0);U+6D2E(5,9); +U+6D2F(0);U+6D2F(0,9);U+6D01(2,3,9),U+6F54(1,2,3,8,9) +U+6D30(0);U+6D30(0,9); +U+6D31(0);U+6D31(5,9); +U+6D32(0);U+6D32(5,9); +U+6D33(0);U+6D33(5,9); +U+6D34(0);U+6D34(0,9); +U+6D35(0);U+6D35(5,9); +U+6D36(0);U+6D36(0,9);U+6C79(2,3,8) +U+6D37(0);U+6D37(0,9); +U+6D38(0);U+6D38(3,9); +U+6D39(0);U+6D39(5,9); + +U+6D3A(0);U+6D3A(0,9); +U+6D3B(0);U+6D3B(5,9); +U+6D3C(0);U+6D3C(1,3,9),U+7AAA(1,3,8,9);U+6F25(3,9),U+7AAA(1,3,8,9) +U+6D3D(0);U+6D3D(5,9);U+51BE(3,9) +U+6D3E(0);U+6D3E(5,9);U+6CD2(4,9) +U+6D3F(0);U+6D3F(3,9); +U+6D40(0);U+6D40(0,9); +U+6D41(0);U+6D41(5,9); +U+6D42(0);U+6D42(0,9); +U+6D43(0);U+6D79(1,3,8,9);U+6D79(1,3,8,9) +U+6D44(0);U+6DE8(8,9);U+51C0(2,4),U+6DE8(8,9),U+51C8(2,4,8,9) +U+6D45(0);U+6DFA(1,3,8,9);U+6DFA(1,3,8,9) +U+6D46(0);U+6F3F(1,3,8,9);U+6F3F(1,3,8,9) +U+6D47(0);U+6F86(1,3,8,9);U+6F86(1,3,8,9) +U+6D48(0);U+6E5E(1,3,8,9);U+6E5E(1,3,8,9) +U+6D49(0);U+6EAE(1,3,8,9);U+6EAE(1,3,8,9) +U+6D4A(0);U+6FC1(1,3,8,9);U+6FC1(1,3,8,9) +U+6D4B(0);U+6E2C(1,3,8,9);U+6E2C(1,3,8,9) +U+6D4C(0);U+6D4C(0); +U+6D4D(0);U+6FAE(1,3,8,9);U+6FAE(1,3,8,9) +U+6D4E(0);U+6FDF(1,3,8,9);U+6E08(3),U+6FDF(1,3,8,9) +U+6D4F(0);U+700F(1,3,8,9);U+56A0(4),U+700F(1,3,8,9) +U+6D50(0);U+6EFB(1,3,8,9);U+6EFB(1,3,8,9) +U+6D51(0);U+6E3E(1,3,8,9);U+6E3E(1,3,8,9) +U+6D52(0);U+6EF8(1,3,8,9);U+6C7B(3,9),U+6EF8(1,3,8,9) +U+6D53(0);U+6FC3(1,3,8,9);U+6FC3(1,3,8,9) +U+6D54(0);U+6F6F(1,3,8,9);U+6F6F(1,3,8,9) +U+6D55(0);U+6FDC(1,3,8,9);U+6FDC(1,3,8,9) +U+6D56(0);U+6D56(0); +U+6D57(0);U+6D57(0); +U+6D58(0);U+6D58(0,9); +U+6D59(0);U+6D59(5,9);U+6DDB(2,3,9) +U+6D5A(0);U+6FEC(2,8,9);U+6FEC(2,8,9) +U+6D5B(0);U+6D5B(3); +U+6D5C(0);U+6FF1(3,8,9);U+6FF1(3,8,9),U+6EE8(1,3,8) +U+6D5D(0);U+6D5D(0); +U+6D5E(0);U+6D5E(5,9); +U+6D5F(0);U+6D5F(0,9); +U+6D60(0);U+6D60(5,9); +U+6D61(0);U+6D61(0,9); +U+6D62(0);U+6D62(0,9); +U+6D63(0);U+6D63(5,9);U+6FA3(2,3,9) +U+6D64(0);U+6D64(3,9); +U+6D65(0);U+6D65(3,9); +U+6D66(0);U+6D66(5,9); +U+6D67(0);U+6D67(0,9); +U+6D68(0);U+6D68(0,9); +U+6D69(0);U+6D69(5,9);U+6F94(3,8,9) +U+6D6A(0);U+6D6A(5,9); +U+6D6B(0);U+6D6B(0); +U+6D6C(0);U+6D6C(0,9); +U+6D6D(0);U+6D6D(0,9); +U+6D6E(0);U+6D6E(5,9); +U+6D6F(0);U+6D6F(5,9); +U+6D70(0);U+6D70(0,9); +U+6D72(0);U+6D72(0); +U+6D73(0);U+6D73(0); +U+6D74(0);U+6D74(5,9); +U+6D75(0);U+6D75(0,9); +U+6D76(0);U+6D76(0,9); +U+6D77(0);U+6D77(5,9); +U+6D78(0);U+6D78(5,9); +U+6D79(0);U+6D79(0,9);U+6D43(1,3,8) + +U+6D7A(0);U+6D7A(0,9); +U+6D7B(0);U+6D7B(0,9); +U+6D7C(0);U+6D7C(5,9); +U+6D7D(0);U+6D7D(3,9); +U+6D7E(0);U+6D7E(3,9); +U+6D7F(0);U+6D7F(0,9); +U+6D80(0);U+6D80(0,9); +U+6D82(0);U+6D82(1,3,9),U+5857(1,3,4,8,9);U+51C3(3),U+5857(1,3,4,8,9) +U+6D83(0);U+6D83(0,9); +U+6D84(0);U+6D84(0,9); +U+6D85(0);U+6D85(5,9); +U+6D86(0);U+6D86(0,9); +U+6D87(0);U+6D87(0,9);U+6CFE(1,3,8) +U+6D88(0);U+6D88(5,9); +U+6D89(0);U+6D89(5,9);U+6E09(4,8) +U+6D8A(0);U+6D8A(0,9); +U+6D8B(0);U+6D8B(0,9); +U+6D8C(0);U+6D8C(5,9),U+6E67(2,3,8,9);U+6E67(2,3,8,9) +U+6D8D(0);U+6D8D(0,9); +U+6D8E(0);U+6D8E(5,9); +U+6D8F(0);U+6D8F(0); +U+6D90(0);U+6D90(0,9); +U+6D91(0);U+6D91(5,9); +U+6D92(0);U+6D92(3,9); +U+6D93(0);U+6D93(5,9); +U+6D94(0);U+6D94(5,9); +U+6D95(0);U+6D95(5,9); +U+6D97(0);U+6D97(0,9);U+6D9A(4,8) +U+6D98(0);U+6D98(0,9); +U+6D99(0);U+6DDA(4,8,9);U+6CEA(4),U+6DDA(4,8,9) +U+6D9A(0);U+6D97(4,8,9);U+6D97(4,8,9) +U+6D9B(0);U+6FE4(1,3,8,9);U+6FE4(1,3,8,9) +U+6D9D(0);U+6F87(1,3,8,9);U+6F87(1,3,8,9) +U+6D9E(0);U+6DF6(1,3,8,9);U+6DF6(1,3,8,9) +U+6D9F(0);U+6F23(1,3,8,9);U+6F23(1,3,8,9) +U+6DA0(0);U+6F7F(1,3,8,9);U+6F7F(1,3,8,9) +U+6DA1(0);U+6E26(1,3,8,9);U+6E26(1,3,8,9),U+6FC4(3,9) +U+6DA2(0);U+6EB3(1,3,8,9);U+6EB3(1,3,8,9) +U+6DA3(0);U+6E19(4,8,9);U+6E19(4,8,9) +U+6DA4(0);U+6ECC(1,3,8,9);U+6ECC(1,3,8,9) +U+6DA5(0);U+6DA5(0); +U+6DA6(0);U+6F64(1,3,8,9);U+6F64(1,3,8,9) +U+6DA7(0);U+6F97(1,3,8,9);U+6F97(1,3,8,9) +U+6DA8(0);U+6F32(1,3,8,9);U+6F32(1,3,8,9) +U+6DA9(0);U+6F80(1,3,8,9);U+6E0B(4),U+6F80(1,3,8,9),U+6F81(3),U+6FC7(2,9),U+7012(3) +U+6DAA(0);U+6DAA(5,9); +U+6DAB(0);U+6DAB(5,9); +U+6DAC(0);U+6DAC(0,9); +U+6DAD(0);U+6DAD(0); +U+6DAE(0);U+6DAE(5,9); +U+6DAF(0);U+6DAF(5,9); +U+6DB2(0);U+6DB2(5,9); +U+6DB3(0);U+6DB3(0,9); +U+6DB4(0);U+6DB4(0,9); +U+6DB5(0);U+6DB5(5,9); +U+6DB7(0);U+6DB7(0,9); +U+6DB8(0);U+6DB8(5,9); +U+6DB9(0);U+6DB9(0); +U+6DBA(0);U+6DBA(0,9); +U+6DBB(0);U+6DBB(0,9); +U+6DBC(0);U+6DBC(0,9);U+51C9(2,3,8) +U+6DBD(0);U+6DBD(4,9); +U+6DBE(0);U+6DBE(0,9); + +U+6DBF(0);U+6DBF(5,9); +U+6DC0(0);U+6DC0(1,3,9),U+6FB1(1,3,8,9);U+6FB1(1,3,8,9) +U+6DC1(0);U+6DC1(0); +U+6DC2(0);U+6DC2(0,9); +U+6DC3(0);U+6DC3(0); +U+6DC4(0);U+6DC4(5,9); +U+6DC5(0);U+6DC5(5,9); +U+6DC6(0);U+6DC6(5,9); +U+6DC7(0);U+6DC7(5,9); +U+6DC8(0);U+6DC8(0,9); +U+6DC9(0);U+6DC9(0,9); +U+6DCA(0);U+6DCA(0,9); +U+6DCB(0);U+6DCB(5,9);U+75F3(2,3,9),U+9EBB(2,3,4,9),U+75F2(0,2,3,4,5,9),U+8534(2,3,4,5) + +U+6DCC(0);U+6DCC(5,9); +U+6DCD(0);U+6DCD(0,9); +U+6DCE(0);U+6DCE(0); +U+6DCF(0);U+6DCF(0,9); +U+6DD0(0);U+6DD0(0,9); +U+6DD1(0);U+6DD1(5,9); +U+6DD2(0);U+6DD2(0,9);U+51C4(2,3,8,9),U+60BD(2,3,8,9) +U+6DD3(0);U+6DD3(0,9);U+6C78(3,9) +U+6DD4(0);U+6DD4(0,9); +U+6DD5(0);U+6DD5(0,9); +U+6DD6(0);U+6DD6(5,9); +U+6DD7(0);U+6DD7(0,9);U+6CE6(3) +U+6DD8(0);U+6DD8(5,9); +U+6DD9(0);U+6DD9(5,9); +U+6DDA(0);U+6DDA(0,9);U+6CEA(2,3,8),U+6D99(4,8) +U+6DDB(0);U+6DDB(0,9);U+6D59(2,3,9) +U+6DDC(0);U+6DDC(0,9); +U+6DDD(0);U+6DDD(5,9); +U+6DDE(0);U+6DDE(5,9); +U+6DDF(0);U+6DDF(0,9); +U+6DE0(0);U+6DE0(5,9); +U+6DE1(0);U+6DE1(5,9);U+6FB9(4,8,9) +U+6DE2(0);U+6DE2(0,9); +U+6DE3(0);U+6DE3(0,9);U+502A(3,9) +U+6DE4(0);U+6DE4(5,9); +U+6DE5(0);U+6DE5(0,9);U+6E0C(4,8) +U+6DE6(0);U+6DE6(5,9); +U+6DE7(0);U+6DE7(0); +U+6DE8(0);U+6DE8(0,9);U+51C0(4,8),U+6D44(8),U+51C8(3,4,8,9) +U+6DE9(0);U+6DE9(0,9);U+51CC(3,9) +U+6DEA(0);U+6DEA(0,9);U+6CA6(1,3,8) +U+6DEB(0);U+6DEB(5,9);U+5A6C(2,3,8,9) +U+6DEC(0);U+6DEC(5,9); +U+6DED(0);U+6DED(0,9); +U+6DEE(0);U+6DEE(5,9); +U+6DEF(0);U+6DEF(0,9); +U+6DF0(0);U+6DF0(0,9); +U+6DF1(0);U+6DF1(5,9); +U+6DF2(0);U+6DF2(0,9); +U+6DF3(0);U+6DF3(5,9); +U+6DF4(0);U+6DF4(0,9); +U+6DF5(0);U+6DF5(0,9);U+6E0A(1,3,8),U+6E15(4,8),U+7041(1,3,4,8,9) +U+6DF6(0);U+6DF6(0,9);U+6D9E(1,3,8) +U+6DF7(0);U+6DF7(5,9); +U+6DF8(0);U+6E05(4,8,9);U+6E05(4,8,9),U+51CA(0,4,8,9) +U+6DF9(0);U+6DF9(5,9); +U+6DFA(0);U+6DFA(0,9);U+6D45(1,3,8) +U+6DFB(0);U+6DFB(5,9); +U+6DFC(0);U+6DFC(5,9); + +U+6DFD(0);U+6DFD(0,9); +U+6E00(0);U+6E00(0,9); +U+6E03(0);U+6E03(0,9); +U+6E04(0);U+6E04(0); +U+6E05(0);U+6E05(5,9);U+51CA(4,9),U+6DF8(4,8) +U+6E07(0);U+6E34(3,8,9);U+6E34(3,8,9) +U+6E08(0);U+6FDF(3,8,9);U+6D4E(3),U+6FDF(3,8,9) +U+6E09(0);U+6D89(4,8,9);U+6D89(4,8,9) +U+6E0A(0);U+6DF5(1,3,8,9);U+6DF5(1,3,8,9),U+6E15(4),U+7041(3,4,9) +U+6E0B(0);U+6F80(4,8,9);U+6DA9(4),U+6F80(4,8,9),U+6F81(3,4),U+6FC7(2,4,9),U+7012(3,4) + +U+6E0C(0);U+6DE5(4,8,9);U+6DE5(4,8,9) +U+6E0D(0);U+6F2C(1,3,8,9);U+6F2C(1,3,8,9) +U+6E0E(0);U+7006(1,3,8,9);U+7006(1,3,8,9) +U+6E0F(0);U+6E0F(0); +U+6E10(0);U+6F38(1,3,8,9);U+5DC9(4,9),U+6F38(1,3,8,9) +U+6E11(0);U+6FA0(1,3,8,9);U+6FA0(1,3,8,9) +U+6E14(0);U+6F01(1,3,8,9);U+6F01(1,3,8,9) +U+6E15(0);U+6DF5(4,8,9);U+6DF5(4,8,9),U+6E0A(4),U+7041(1,3,4,8,9) +U+6E16(0);U+700B(4,8,9);U+6C88(4,9),U+700B(4,8,9),U+6C89(3,4,9) +U+6E17(0);U+6EF2(1,3,8,9);U+6EF2(1,3,8,9) +U+6E19(0);U+6E19(0,9);U+6DA3(4,8) +U+6E1A(0);U+6E1A(5,9); +U+6E1B(0);U+6E1B(0,9);U+51CF(2,3,8) +U+6E1C(0);U+6E1C(3,9); +U+6E1D(0);U+6E1D(5,9); +U+6E1E(0);U+6E1E(0); +U+6E1F(0);U+6E1F(0,9); +U+6E20(0);U+6E20(5,9); +U+6E21(0);U+6E21(5,9); +U+6E22(0);U+6E22(0,9);U+6CA8(1,3,8) +U+6E23(0);U+6E23(5,9); +U+6E24(0);U+6E24(5,9);U+90E3(3,9) +U+6E25(0);U+6E25(5,9); +U+6E26(0);U+6E26(0,9);U+6DA1(1,3,8),U+6FC4(1,3,8,9) +U+6E27(0);U+6E27(0,9); +U+6E28(0);U+6E28(0,9); +U+6E29(0);U+6EAB(3,8,9);U+6EAB(3,8,9) +U+6E2B(0);U+6E2B(5,9);U+6CC4(3,8,9),U+6D29(2,3,8,9) +U+6E2C(0);U+6E2C(0,9);U+6D4B(1,3,8) +U+6E2D(0);U+6E2D(5,9); +U+6E2E(0);U+6E2E(0,9);U+83CF(3,9) +U+6E2F(0);U+6E2F(5,9); +U+6E30(0);U+6E30(3,9); +U+6E31(0);U+6E31(0,9); +U+6E32(0);U+6E32(5,9); +U+6E33(0);U+6E33(0,9); +U+6E34(0);U+6E34(5,9);U+6E07(3,8) +U+6E35(0);U+6E35(0,9); +U+6E36(0);U+6E36(0,9); +U+6E37(0);U+6E37(0); +U+6E38(0);U+6E38(5,9),U+904A(2,3,8,9);U+9030(3,8),U+904A(2,3,8,9) +U+6E39(0);U+6E39(0,9); +U+6E3A(0);U+6E3A(5,9); +U+6E3B(0);U+6E3B(0,9); +U+6E3C(0);U+6E3C(0,9); +U+6E3D(0);U+6E3D(0,9); +U+6E3E(0);U+6E3E(0,9);U+6D51(1,3,8) +U+6E3F(0);U+6E3F(0,9); +U+6E40(0);U+6E40(0,9); +U+6E41(0);U+6E41(0,9); +U+6E42(0);U+6E42(0); +U+6E43(0);U+6E43(5,9); + +U+6E44(0);U+6E44(5,9); +U+6E45(0);U+6E45(0,9); +U+6E46(0);U+6E46(3,9);U+6E47(3,9) +U+6E47(0);U+6E47(0,9);U+6E46(3,9) +U+6E48(0);U+6E48(0); +U+6E49(0);U+6E49(0,9); +U+6E4A(0);U+6E4A(0,9);U+51D1(2,3) +U+6E4B(0);U+6E4B(0,9); +U+6E4D(0);U+6E4D(5,9); +U+6E4E(0);U+6E4E(5,9); +U+6E4F(0);U+6E4F(0); +U+6E50(0);U+6E50(0); +U+6E51(0);U+6E51(0,9); +U+6E52(0);U+6E52(0,9); +U+6E53(0);U+6E53(5,9); +U+6E54(0);U+6E54(5,9); +U+6E55(0);U+6E55(0,9); +U+6E56(0);U+6E56(5,9); +U+6E57(0);U+6E57(0); +U+6E58(0);U+6E58(5,9); +U+6E59(0);U+6E59(0); +U+6E5A(0);U+6E5A(0,9); +U+6E5B(0);U+6E5B(5,9); +U+6E5C(0);U+6E5C(0,9); +U+6E5D(0);U+6E5D(0,9); +U+6E5E(0);U+6E5E(0,9);U+6D48(1,3,8) +U+6E5F(0);U+6E5F(5,9); +U+6E60(0);U+6E60(0,9); +U+6E61(0);U+6E61(0,9); +U+6E62(0);U+6E62(0,9); +U+6E63(0);U+6E63(0,9); +U+6E64(0);U+6E64(0,9); +U+6E65(0);U+6E65(0,9); +U+6E66(0);U+6E66(0,9); +U+6E67(0);U+6E67(0,9);U+6D8C(2,3,8,9) +U+6E68(0);U+6E68(0,9); +U+6E69(0);U+6E69(0,9); +U+6E6A(0);U+6E6A(0); +U+6E6B(0);U+6E6B(5,9); +U+6E6D(0);U+6E6D(0); +U+6E6E(0);U+6E6E(5,9); +U+6E6F(0);U+6E6F(0,9);U+6C64(1,3,8) +U+6E70(0);U+6E70(3); +U+6E71(0);U+6E71(0,9); +U+6E72(0);U+6E72(0,9); +U+6E73(0);U+6E73(0,9); +U+6E74(0);U+6E74(4,9); +U+6E75(0);U+6E75(0); +U+6E77(0);U+6E77(0,9); +U+6E78(0);U+6E78(0,9); +U+6E79(0);U+6E79(0,9); +U+6E7E(0);U+7063(1,3,8,9);U+7063(1,3,8,9) +U+6E7F(0);U+6FD5(1,3,8,9);U+6EBC(4,8,9),U+6FD5(1,3,8,9) +U+6E80(0);U+6EFF(4,8,9);U+6EE1(4),U+6EFF(4,8,9) +U+6E81(0);U+6FDA(4,8);U+6FDA(4,8) +U+6E82(0);U+6E82(0); +U+6E83(0);U+6F70(1,3,8,9);U+6F70(1,3,8,9) +U+6E84(0);U+6E84(0); +U+6E85(0);U+6FFA(1,3,8,9);U+6FFA(1,3,8,9) +U+6E86(0);U+6F35(4,8,9);U+6F35(4,8,9) +U+6E87(0);U+6F0A(1,3,8,9);U+6F0A(1,3,8,9) +U+6E88(0);U+6E88(0,9);U+6CA9(4),U+6F59(4,8) +U+6E89(0);U+6E89(5,9);U+6F11(4,8) + +U+6E8A(0);U+6E8A(0); +U+6E8D(0);U+6E8D(0,9); +U+6E8E(0);U+6E8E(0,9); +U+6E8F(0);U+6E8F(5,9); +U+6E90(0);U+6E90(5,9);U+53B5(3,8) +U+6E91(0);U+6E91(0); +U+6E92(0);U+6E92(0,9); +U+6E93(0);U+6E93(3,9); +U+6E94(0);U+6E94(0,9); +U+6E96(0);U+6E96(0,9);U+51C6(1,3,8,9),U+51D6(3,8) +U+6E97(0);U+6E97(0,9); +U+6E98(0);U+6E98(5,9); +U+6E99(0);U+6E99(0,9);U+6C70(3,9),U+6C4F(0,3,9) +U+6E9A(0);U+6E9A(0); +U+6E9B(0);U+6E9B(0,9); +U+6E9C(0);U+6E9C(5,9);U+6F91(3,8) +U+6E9D(0);U+6E9D(0,9);U+6C9F(1,3,8) +U+6E9E(0);U+6E9E(0,9); +U+6E9F(0);U+6E9F(5,9); +U+6EA0(0);U+6EA0(3,9); +U+6EA1(0);U+6EA1(0,9); +U+6EA2(0);U+6EA2(5,9); +U+6EA3(0);U+6EA3(0,9); +U+6EA4(0);U+6EA4(0,9); +U+6EA5(0);U+6EA5(5,9); +U+6EA6(0);U+6EA6(3,9);U+973A(3,9) +U+6EA7(0);U+6EA7(5,9); +U+6EA8(0);U+6EA8(0); +U+6EA9(0);U+6EA9(0); +U+6EAA(0);U+6EAA(5,9);U+8C3F(2,3,9) +U+6EAB(0);U+6EAB(0,9);U+6E29(3,8) +U+6EAC(0);U+6EAC(0); +U+6EAD(0);U+6EAD(0); +U+6EAE(0);U+6EAE(0,9);U+6D49(1,3,8) +U+6EAF(0);U+6EAF(5,9);U+6CDD(3,4,8,9),U+9061(2,3,8) +U+6EB0(0);U+6EB0(0,9); +U+6EB1(0);U+6EB1(5,9);U+6F67(3,9) +U+6EB2(0);U+6EB2(5,9); +U+6EB3(0);U+6EB3(0,9);U+6DA2(1,3,8) +U+6EB4(0);U+6EB4(5,9); +U+6EB5(0);U+6EB5(0); +U+6EB6(0);U+6EB6(5,9); +U+6EB7(0);U+6EB7(5,9); +U+6EB8(0);U+6EB8(0); +U+6EB9(0);U+6EB9(0,9); +U+6EBA(0);U+6EBA(5,9);U+5C3F(3,8,9) +U+6EBB(0);U+6EBB(5); +U+6EBC(0);U+6EBC(0,9);U+6E7F(4,8),U+6FD5(2,3,8,9) +U+6EBD(0);U+6EBD(5,9); +U+6EBE(0);U+6EBE(0,9); +U+6EBF(0);U+6EBF(0,9); +U+6EC0(0);U+6EC0(3,9); +U+6EC1(0);U+6EC1(5,9); +U+6EC2(0);U+6EC2(5,9); +U+6EC3(0);U+6EC3(0,9); +U+6EC4(0);U+6EC4(0,9);U+6CA7(1,3,8) +U+6EC5(0);U+6EC5(0,9);U+706D(1,3,8) +U+6EC6(0);U+6EC6(0,9); +U+6EC7(0);U+6EC7(5,9); +U+6EC8(0);U+6EC8(3,9); +U+6EC9(0);U+6EC9(3,9); +U+6ECA(0);U+6ECA(0,9);U+6C7D(3,9) +U+6ECB(0);U+6ECB(5,9); + +U+6ECC(0);U+6ECC(0,9);U+6DA4(1,3,8) +U+6ECD(0);U+6ECD(0,9); +U+6ECE(0);U+6ECE(0,9);U+8365(1,3,8) +U+6ECF(0);U+6ECF(5,9); +U+6ED0(0);U+6ED0(0,9); +U+6ED1(0);U+6ED1(5,9);U+78C6(3,8) +U+6ED2(0);U+6ED2(0,9); +U+6ED3(0);U+6ED3(5,9); +U+6ED4(0);U+6ED4(5,9); +U+6ED5(0);U+6ED5(5,9); +U+6ED6(0);U+6ED6(0,9); +U+6ED7(0);U+6F77(1,3,8,9);U+6F77(1,3,8,9) +U+6ED8(0);U+6ED8(0,9); +U+6ED9(0);U+6ED9(4);U+532F(0,9),U+5F59(4,9),U+6C47(1,3,8),U+5F5A(4,8) +U+6EDA(0);U+6EFE(4,8,9);U+6EFE(4,8,9) +U+6EDC(0);U+6EDC(0,9); +U+6EDE(0);U+6EEF(1,3,8,9);U+6EEF(1,3,8,9) +U+6EDF(0);U+7069(4,9);U+7054(4,8),U+7067(1,3,8),U+7069(4,9) +U+6EE0(0);U+7044(1,3,8,9);U+7044(1,3,8,9) +U+6EE1(0);U+6EFF(1,3,8,9);U+6E80(4),U+6EFF(1,3,8,9) +U+6EE2(0);U+7005(4,8,9);U+7005(4,8,9) +U+6EE4(0);U+6FFE(1,3,8,9);U+6FFE(1,3,8,9) +U+6EE5(0);U+6FEB(1,3,8,9);U+6FEB(1,3,8,9) +U+6EE6(0);U+7064(1,3,8,9);U+7064(1,3,8,9) +U+6EE7(0);U+6EE7(0); +U+6EE8(0);U+6FF1(1,3,8,9);U+6FF1(1,3,8,9),U+6D5C(1,3,5,8) +U+6EE9(0);U+7058(1,3,8,9);U+7058(1,3,8,9) +U+6EEA(0);U+6FA6(1,3,8,9);U+6FA6(1,3,8,9) +U+6EEB(0);U+6EEB(4,9);U+6F43(4,9) +U+6EEC(0);U+6EEC(0,9);U+6CAA(1,3,8) +U+6EED(0);U+6EED(0,9); +U+6EEE(0);U+6EEE(3,9); +U+6EEF(0);U+6EEF(0,9);U+6EDE(1,3,8) +U+6EF0(0);U+6EF0(0); +U+6EF1(0);U+6EF1(0,9); +U+6EF2(0);U+6EF2(0,9);U+6E17(1,3,8) +U+6EF3(0);U+6EF3(0); +U+6EF4(0);U+6EF4(5,9); +U+6EF5(0);U+6EF5(0,9); +U+6EF6(0);U+6EF6(0,9); +U+6EF7(0);U+6EF7(0,9);U+5364(1,3,8),U+9E75(4,9) +U+6EF8(0);U+6EF8(0,9);U+6D52(1,3,8),U+6C7B(0,1,3,8,9) +U+6EF9(0);U+6EF9(5,9); +U+6EFA(0);U+6EFA(0); +U+6EFB(0);U+6EFB(0,9);U+6D50(1,3,8) +U+6EFC(0);U+6EFC(0,9); +U+6EFD(0);U+6EFD(0,9); +U+6EFE(0);U+6EFE(0,9);U+6EDA(4,8) +U+6EFF(0);U+6EFF(0,9);U+6E80(4,8),U+6EE1(1,3,8) +U+6F00(0);U+6F00(0,9); +U+6F01(0);U+6F01(0,9);U+6E14(1,3,8) +U+6F02(0);U+6F02(5,9); +U+6F03(0);U+6F03(0,9); +U+6F05(0);U+6F05(0,9);U+5DE2(3,9),U+5DE3(3,8) +U+6F06(0);U+6F06(5,9);U+67D2(3,8,9),U+687C(3,9) +U+6F07(0);U+6F07(0,9); +U+6F08(0);U+6F08(0,9); +U+6F09(0);U+6F09(5,9); +U+6F0A(0);U+6F0A(0,9);U+6E87(1,3,8) +U+6F0C(0);U+6F0C(0); +U+6F0D(0);U+6F0D(0,9); +U+6F0E(0);U+6F0E(0,9);U+6F68(3),U+6F40(3,8,9) +U+6F0F(0);U+6F0F(5,9); + +U+6F10(0);U+6F10(0); +U+6F11(0);U+6E89(4,8,9);U+6E89(4,8,9) +U+6F12(0);U+6F12(0,9); +U+6F13(0);U+6F13(1,3,9),U+7055(1,3,4,8,9);U+7055(1,3,4,8,9) +U+6F14(0);U+6F14(5,9); +U+6F15(0);U+6F15(5,9); +U+6F16(0);U+6F16(0); +U+6F17(0);U+6F17(0); +U+6F18(0);U+6F18(3,9); +U+6F19(0);U+6F19(0,9); +U+6F1A(0);U+6F1A(0,9);U+6CA4(1,3,8) +U+6F1B(0);U+6F1B(0); +U+6F1C(0);U+6F1C(0,9); +U+6F1D(0);U+6F1D(0); +U+6F1E(0);U+6F1E(0,9); +U+6F1F(0);U+6F1F(0,9); +U+6F20(0);U+6F20(5,9); +U+6F21(0);U+6F21(0,9); +U+6F22(0);U+6F22(0,9);U+6C49(1,3,8) +U+6F23(0);U+6F23(0,9);U+6D9F(1,3,8) +U+6F24(0);U+6F24(5); +U+6F25(0);U+6F25(0,9);U+6D3C(3,9),U+7AAA(1,3,8,9) +U+6F26(0);U+6F26(0,9); +U+6F27(0);U+6F27(0,9);U+4E7E(3,9),U+4E81(2,3,8),U+5E72(1,3,8,9),U+5E79(1,3,4,8,9),U+69A6(1,3,4,8,9) + +U+6F28(0);U+6F28(3); +U+6F29(0);U+6F29(5,9); +U+6F2A(0);U+6F2A(5,9); +U+6F2B(0);U+6F2B(5,9);U+6FAB(3,9) +U+6F2C(0);U+6F2C(0,9);U+6E0D(1,3,8) +U+6F2D(0);U+6F2D(5,9); +U+6F2E(0);U+6F2E(0,9); +U+6F2F(0);U+6F2F(5,9); +U+6F30(0);U+6F30(0,9); +U+6F31(0);U+6F31(5,9);U+6F44(2,3,8) +U+6F32(0);U+6F32(0,9);U+6DA8(1,3,8) +U+6F33(0);U+6F33(5,9); +U+6F34(0);U+6F34(3); +U+6F35(0);U+6F35(0,9);U+6E86(4,8) +U+6F36(0);U+6F36(5,9); +U+6F37(0);U+6F37(0,9); +U+6F38(0);U+6F38(0,9);U+6E10(1,3,8),U+5DC9(0,1,3,4,8,9) +U+6F39(0);U+6F39(0,9); +U+6F3A(0);U+6F3A(0,9); +U+6F3B(0);U+6F3B(0,9); +U+6F3C(0);U+6F3C(0,9); +U+6F3D(0);U+6F3D(0); +U+6F3E(0);U+6F3E(5,9);U+7001(3,8,9) +U+6F3F(0);U+6F3F(0,9);U+6D46(1,3,8) +U+6F40(0);U+6F40(0,9);U+6F68(8),U+6F0E(0,3,8,9) +U+6F41(0);U+6F41(0,9);U+988D(1,3,8) +U+6F43(0);U+6F43(0,9);U+6EEB(4,9) +U+6F44(0);U+6F31(2,3,8,9);U+6F31(2,3,8,9) +U+6F45(0);U+704C(3,8,9);U+704C(3,8,9) +U+6F46(0);U+7020(4,8,9);U+7020(4,8,9) +U+6F47(0);U+701F(1,3,8,9);U+701F(1,3,8,9) +U+6F49(0);U+6F49(0); +U+6F4B(0);U+7032(1,3,8,9);U+7032(1,3,8,9) +U+6F4C(0);U+6F4C(0); +U+6F4D(0);U+6FF0(1,3,8,9);U+6FF0(1,3,8,9) +U+6F4E(0);U+6F4E(0,9); +U+6F4F(0);U+6F4F(0,9); +U+6F50(0);U+6F50(0,9); + +U+6F51(0);U+6F51(0,9);U+6CFC(1,3,8) +U+6F52(0);U+6F52(0,9);U+8361(3),U+76EA(3,4,9),U+8569(1,3,8,9),U+862F(3) +U+6F53(0);U+6F53(0,9); +U+6F54(0);U+6F54(0,9);U+6D01(1,3,8,9),U+6D2F(1,2,3,8,9) +U+6F55(0);U+6F55(0,9); +U+6F56(0);U+6F56(0); +U+6F57(0);U+6F57(0,9); +U+6F58(0);U+6F58(5,9); +U+6F59(0);U+6E88(4,8,9);U+6CA9(1,3,8),U+6E88(4,8,9) +U+6F5A(0);U+6F5A(0,9); +U+6F5B(0);U+6F5B(0,9);U+6F5C(2,3,8),U+6FF3(3,8) +U+6F5C(0);U+6F5B(2,3,8,9);U+6F5B(2,3,8,9),U+6FF3(3) +U+6F5D(0);U+6F5D(0,9); +U+6F5E(0);U+6F5E(5,9); +U+6F5F(0);U+6F5F(0,9);U+6F99(7,8) +U+6F60(0);U+6F60(3,9); +U+6F61(0);U+6F61(0,9); +U+6F62(0);U+6F62(5,9); +U+6F63(0);U+6F63(3,9); +U+6F64(0);U+6F64(0,9);U+6DA6(1,3,8) +U+6F65(0);U+6F65(0); +U+6F66(0);U+6F66(5,9); +U+6F67(0);U+6F67(0,9);U+6EB1(3,9) +U+6F68(0);U+6F40(8,9);U+6F0E(3,9),U+6F40(8,9) +U+6F69(0);U+6F69(0,9); +U+6F6A(0);U+6F6A(0,9); +U+6F6B(0);U+6F6B(0,9); +U+6F6C(0);U+6F6C(0,9); +U+6F6D(0);U+6F6D(5,9); +U+6F6E(0);U+6F6E(5,9); +U+6F6F(0);U+6F6F(0,9);U+6D54(1,3,8) +U+6F70(0);U+6F70(0,9);U+6E83(1,3,8) +U+6F71(0);U+6F71(0); +U+6F72(0);U+6F72(5,9); +U+6F73(0);U+6F73(0,9); +U+6F74(0);U+7026(3,9);U+7026(3,9) +U+6F75(0);U+6F75(0); +U+6F76(0);U+6F76(0,9); +U+6F77(0);U+6F77(0,9);U+6ED7(1,3,8) +U+6F78(0);U+6F78(5,9); +U+6F7A(0);U+6F7A(5,9); +U+6F7B(0);U+6F7B(0,9); +U+6F7C(0);U+6F7C(5,9); +U+6F7D(0);U+6F7D(0,9); +U+6F7E(0);U+6F7E(0,9); +U+6F7F(0);U+6F7F(0,9);U+6DA0(1,3,8) +U+6F80(0);U+6F80(0,9);U+6DA9(1,3,8),U+6E0B(4,8),U+6F81(2,3,8),U+6FC7(2,8,9),U+7012(3,8) + +U+6F81(0);U+6F80(2,3,8,9);U+6DA9(3),U+6F80(2,3,8,9),U+6E0B(3,4),U+6FC7(2,3,9),U+7012(3) + +U+6F82(0);U+6F82(0,9);U+6F84(2,3,8,9) +U+6F83(0);U+6F83(0); +U+6F84(0);U+6F84(5,9);U+6F82(2,3,8,9) +U+6F85(0);U+6F85(0,9); +U+6F86(0);U+6F86(0,9);U+6D47(1,3,8) +U+6F87(0);U+6F87(0,9);U+6D9D(1,3,8) +U+6F88(0);U+6F88(5,9); +U+6F89(0);U+6F89(5,9); +U+6F8A(0);U+6F8A(0); +U+6F8B(0);U+6F8B(0,9); +U+6F8C(0);U+6F8C(5,9); +U+6F8D(0);U+6F8D(5,9); +U+6F8E(0);U+6F8E(5,9); + +U+6F8F(0);U+6F8F(0); +U+6F90(0);U+6F90(0,9); +U+6F91(0);U+6E9C(3,8,9);U+6E9C(3,8,9) +U+6F92(0);U+6F92(0,9); +U+6F93(0);U+6F93(0,9); +U+6F94(0);U+6F94(0,9);U+6D69(3,8,9) +U+6F95(0);U+6F95(0,9); +U+6F96(0);U+6F96(0,9); +U+6F97(0);U+6F97(0,9);U+6DA7(1,3,8) +U+6F99(0);U+6F5F(7,8,9);U+6F5F(7,8,9) +U+6F9B(0);U+7002(4,8);U+7002(4,8) +U+6F9C(0);U+703E(1,3,8,9);U+703E(1,3,8,9) +U+6F9D(0);U+6F9D(0); +U+6F9E(0);U+6F9E(0,9); +U+6FA0(0);U+6FA0(0,9);U+6E11(1,3,8) +U+6FA1(0);U+6FA1(5,9); +U+6FA2(0);U+6FA2(0,9); +U+6FA3(0);U+6FA3(0,9);U+6D63(2,3,9) +U+6FA4(0);U+6FA4(0,9);U+6CA2(4,8),U+6CFD(1,3,8) +U+6FA5(0);U+6FA5(0,9); +U+6FA6(0);U+6FA6(0,9);U+6EEA(1,3,8) +U+6FA7(0);U+6FA7(5,9); +U+6FA8(0);U+6FA8(0,9); +U+6FA9(0);U+6FA9(0,9);U+6CF6(4,8) +U+6FAA(0);U+6FAA(0,9);U+6CE0(3,9) +U+6FAB(0);U+6FAB(0,9);U+6F2B(3,9) +U+6FAC(0);U+6FAC(0,9); +U+6FAD(0);U+6FAD(0,9); +U+6FAE(0);U+6FAE(0,9);U+6D4D(1,3,8) +U+6FAF(0);U+6FAF(0,9); +U+6FB0(0);U+6FB0(0,9); +U+6FB1(0);U+6FB1(0,9);U+6DC0(1,3,8,9) +U+6FB2(0);U+6FB2(0,9); +U+6FB3(0);U+6FB3(5,9); +U+6FB4(0);U+6FB4(0,9); +U+6FB5(0);U+6FB5(0); +U+6FB6(0);U+6FB6(5,9); +U+6FB8(0);U+6FB8(0,9); +U+6FB9(0);U+6FB9(5,9);U+6DE1(4,8,9) +U+6FBA(0);U+6FBA(0,9); +U+6FBB(0);U+6FBB(0); +U+6FBC(0);U+6FBC(0,9); +U+6FBD(0);U+6FBD(0,9); +U+6FBE(0);U+6FBE(0);U+3CE0(1,3) +U+6FBF(0);U+6FBF(0,9); +U+6FC0(0);U+6FC0(5,9); +U+6FC1(0);U+6FC1(0,9);U+6D4A(1,3,8) +U+6FC2(0);U+6FC2(5,9); +U+6FC3(0);U+6FC3(0,9);U+6D53(1,3,8) +U+6FC4(0);U+6FC4(0,9);U+6DA1(3),U+6E26(1,3,8,9) +U+6FC6(0);U+6FC6(3,9); +U+6FC7(0);U+6FC7(0,9);U+6DA9(2),U+6F80(2,8,9),U+7012(8),U+6E0B(2,4),U+6F81(2,3) +U+6FC8(0);U+6FC8(3,9); +U+6FC9(0);U+6FC9(5,9); +U+6FCA(0);U+6FCA(3,9); +U+6FCB(0);U+6FCB(0,9); +U+6FCC(0);U+6FCC(0,9); +U+6FCD(0);U+6FCD(0,9); +U+6FCE(0);U+6FCE(0,9); +U+6FCF(0);U+6FCF(0,9); +U+6FD1(0);U+7028(1,3,8,9);U+7028(1,3,8,9),U+702C(3) +U+6FD2(0);U+7015(1,3,8,9);U+7015(1,3,8,9) +U+6FD4(0);U+6FD4(0,9);U+6CB5(4,8) + +U+6FD5(0);U+6FD5(0,9);U+6E7F(1,3,8),U+6EBC(2,3,8,9) +U+6FD6(0);U+6FD6(0); +U+6FD7(0);U+6FD7(0); +U+6FD8(0);U+6FD8(0,9);U+6CDE(1,3,8,9) +U+6FD9(0);U+6FD9(0); +U+6FDA(0);U+6FDA(0);U+6E81(4,8) +U+6FDB(0);U+6FDB(0,9);U+8499(1,3,9),U+61DE(0,1,3,4,8,9),U+77C7(1,3,4,8,9) +U+6FDC(0);U+6FDC(0,9);U+6D55(1,3,8) +U+6FDD(0);U+6FDD(0,9); +U+6FDE(0);U+6FDE(5,9); +U+6FDF(0);U+6FDF(0,9);U+6D4E(1,3,8),U+6E08(3,8) +U+6FE0(0);U+6FE0(5,9); +U+6FE1(0);U+6FE1(5,9); +U+6FE2(0);U+6FE2(0,9); +U+6FE3(0);U+6FE3(0,9); +U+6FE4(0);U+6FE4(0,9);U+6D9B(1,3,8) +U+6FE5(0);U+6FE5(3); +U+6FE6(0);U+6FE6(3,9); +U+6FE7(0);U+6FE7(0,9); +U+6FE8(0);U+6FE8(0,9); +U+6FE9(0);U+6FE9(4,9); +U+6FEA(0);U+6FEA(0); +U+6FEB(0);U+6FEB(0,9);U+6EE5(1,3,8) +U+6FEC(0);U+6FEC(0,9);U+6D5A(2,8,9) +U+6FED(0);U+6FED(0,9); +U+6FEE(0);U+6FEE(5,9); +U+6FEF(0);U+6FEF(5,9); +U+6FF0(0);U+6FF0(0,9);U+6F4D(1,3,8) +U+6FF1(0);U+6FF1(0,9);U+6D5C(3,8),U+6EE8(1,3,8) +U+6FF2(0);U+6FF2(0,9); +U+6FF3(0);U+6F5B(3,8,9);U+6F5B(3,8,9),U+6F5C(3) +U+6FF4(0);U+6FF4(3,9); +U+6FF6(0);U+95CA(2,3,8,9);U+95CA(2,3,8,9),U+9614(4) +U+6FF7(0);U+6FF7(0,9); +U+6FF8(0);U+6FF8(0); +U+6FF9(0);U+6FF9(0); +U+6FFA(0);U+6FFA(0,9);U+6E85(1,3,8) +U+6FFB(0);U+6FFB(0,9);U+7022(3,9) +U+6FFC(0);U+6FFC(0,9);U+6CCA(3,8,9),U+6CFA(1,3,8) +U+6FFE(0);U+6FFE(0,9);U+6EE4(1,3,8) +U+6FFF(0);U+6FFF(3,9); +U+7000(0);U+7000(0,9); +U+7001(0);U+7001(0,9);U+6F3E(3,8,9) +U+7002(0);U+7002(0);U+6F9B(4,8) +U+7003(0);U+7003(0); +U+7004(0);U+7004(0,9); +U+7005(0);U+7005(0,9);U+6EE2(4,8) +U+7006(0);U+7006(0,9);U+6E0E(1,3,8) +U+7007(0);U+7007(0,9);U+6C6A(3,9) +U+7008(0);U+7008(0); +U+7009(0);U+7009(0,9);U+6CFB(1,3,8) +U+700A(0);U+700A(0,9); +U+700B(0);U+700B(0,9);U+6C88(1,8,9),U+6E16(4,8),U+6C89(1,3,8,9) +U+700C(0);U+700C(0,9); +U+700D(0);U+700D(0,9); +U+700E(0);U+700E(0,9); +U+700F(0);U+700F(0,9);U+56A0(4,8),U+6D4F(1,3,8) +U+7011(0);U+7011(5,9); +U+7012(0);U+6FC7(8,9);U+6DA9(3),U+6F80(3,8,9),U+6FC7(8,9),U+6E0B(3,4),U+6F81(3) +U+7014(0);U+7014(0,9); +U+7015(0);U+7015(0,9);U+6FD2(1,3,8) +U+7016(0);U+7016(0,9); +U+7017(0);U+7017(0,9); + +U+7018(0);U+7018(0,9);U+6CF8(1,3,8) +U+7019(0);U+7019(0,9); +U+701A(0);U+701A(5,9); +U+701B(0);U+701B(5,9); +U+701C(0);U+701C(0,9); +U+701D(0);U+701D(0,9);U+6CA5(1,3,8) +U+701F(0);U+701F(0,9);U+6F47(1,3,8) +U+7020(0);U+7020(0,9);U+6F46(4,8) +U+7021(0);U+7021(0,9); +U+7022(0);U+7022(3,9);U+6FFB(3,9) +U+7023(0);U+7023(5,9); +U+7024(0);U+7024(0,9); +U+7025(0);U+7025(0); +U+7026(0);U+7026(0,9);U+6F74(3) +U+7027(0);U+7027(0,9);U+6CF7(1,3,8) +U+7028(0);U+7028(0,9);U+6FD1(1,3,8),U+702C(3,8) +U+7029(0);U+7029(0,9); +U+702A(0);U+702A(0,9); +U+702B(0);U+702B(0,9); +U+702C(0);U+7028(3,8,9);U+6FD1(3),U+7028(3,8,9) +U+702D(0);U+702D(0); +U+702E(0);U+702E(0); +U+702F(0);U+702F(3,9); +U+7030(0);U+7030(0,9);U+5F25(1,3),U+5F4C(4,8,9),U+519E(1,3,7,9) +U+7031(0);U+7031(0,9); +U+7032(0);U+7032(0,9);U+6F4B(1,3,8) +U+7033(0);U+7033(3,9); +U+7034(0);U+7034(0,9); +U+7035(0);U+7035(5,9); +U+7036(0);U+7036(3); +U+7037(0);U+7037(0,9); +U+7038(0);U+7038(3,9); +U+7039(0);U+7039(5,9); +U+703A(0);U+703A(0,9); +U+703B(0);U+703B(0,9); +U+703C(0);U+703C(0,9); +U+703D(0);U+703D(0); +U+703E(0);U+703E(0,9);U+6F9C(1,3,8) +U+703F(0);U+703F(0,9); +U+7040(0);U+7040(0,9); +U+7041(0);U+7041(0,9);U+6E0A(3,4),U+6DF5(0,1,3,4,8,9),U+6E15(1,3,4,8) +U+7042(0);U+7042(0,9); +U+7043(0);U+7043(0,9);U+6CA3(1,3,8) +U+7044(0);U+7044(0,9);U+6EE0(1,3,8) +U+7045(0);U+7045(3,9); +U+7046(0);U+7046(0,9); +U+7048(0);U+7048(0,9); +U+7049(0);U+7049(3,9); +U+704A(0);U+704A(0,9); +U+704C(0);U+704C(5,9);U+6F45(3,8) +U+704D(0);U+704D(0); +U+704F(0);U+705D(1,3,8,9);U+705D(1,3,8,9) +U+7050(0);U+7050(0); +U+7051(0);U+7051(0,9);U+6D12(1,3,8,9) +U+7052(0);U+7052(3,9); +U+7053(0);U+7053(3); +U+7054(0);U+7069(3,8,9);U+6EDF(4,8),U+7067(4,8),U+7069(3,8,9) +U+7055(0);U+7055(0,9);U+6F13(1,3,8,9) +U+7056(0);U+7056(0,9); +U+7057(0);U+7057(0,9); +U+7058(0);U+7058(0,9);U+6EE9(1,3,8) +U+7059(0);U+7059(0); +U+705A(0);U+705A(0,9); + +U+705B(0);U+705B(0,9);U+9610(3),U+95E1(1,3,8,9) +U+705C(0);U+705C(0); +U+705D(0);U+705D(0,9);U+704F(1,3,8) +U+705E(0);U+705E(5,9); +U+705F(0);U+705F(0,9); +U+7060(0);U+7060(0,9); +U+7061(0);U+7061(3,9); +U+7062(0);U+7062(0,9); +U+7063(0);U+7063(0,9);U+6E7E(1,3,8) +U+7064(0);U+7064(0,9);U+6EE6(1,3,8) +U+7065(0);U+7065(0,9); +U+7066(0);U+7066(0,9); +U+7067(0);U+7069(3,4,9);U+6EDF(1,3,8),U+7054(4,8),U+7069(3,4,9) +U+7068(0);U+7068(0,9);U+8D63(2),U+8D1B(1,2,3,8,9) +U+7069(0);U+7069(0,9);U+6EDF(4),U+7054(3,8),U+7067(3,4) +U+706A(0);U+706A(0,9); +U+706B(0);U+706B(5,9); +U+706C(0);U+706C(5); +U+706D(0);U+6EC5(1,3,8,9);U+6EC5(1,3,8,9) +U+706E(0);U+5149(3,8,9);U+5149(3,8,9),U+709A(3,8,9),U+70E1(3,8,9) +U+706F(0);U+71C8(1,3,8,9);U+71C8(1,3,8,9) +U+7070(0);U+7070(5,9); +U+7071(0);U+7071(3,9); +U+7074(0);U+7074(0,9);U+70D8(3,9) +U+7075(0);U+9748(1,3,8,9);U+970A(3),U+9748(1,3,8,9) +U+7076(0);U+7076(1,3,9);U+7AC8(1,3,8) +U+7077(0);U+7077(0); +U+7078(0);U+7078(5,9); +U+7079(0);U+7079(0); +U+707A(0);U+707A(3,9); +U+707C(0);U+707C(5,9); +U+707D(0);U+707D(0,9);U+707E(2,3,8),U+70D6(4,8) +U+707E(0);U+707D(2,3,8,9);U+707D(2,3,8,9),U+70D6(2) +U+707F(0);U+71E6(1,3,8,9);U+71E6(1,3,8,9) +U+7080(0);U+716C(1,3,8,9);U+716C(1,3,8,9) +U+7082(0);U+7082(0,9); +U+7083(0);U+7083(0,9);U+711A(3,9) +U+7084(0);U+7084(0,9); +U+7085(0);U+7085(5,9);U+7094(3,9) +U+7086(0);U+7086(0,9); +U+7087(0);U+7087(0); +U+7088(0);U+7088(0); +U+7089(0);U+7210(1,3,8,9);U+7210(1,3,8,9),U+946A(4,9) +U+708A(0);U+708A(5,9); +U+708B(0);U+708B(0); +U+708C(0);U+708C(0); +U+708E(0);U+708E(5,9); +U+708F(0);U+708F(0); +U+7090(0);U+7090(0); +U+7091(0);U+7091(0,9); +U+7092(0);U+7092(5,9); +U+7093(0);U+7093(0,9); +U+7094(0);U+7094(5,9);U+7085(3,9) +U+7095(0);U+7095(5,9);U+531F(2,3,9) +U+7096(0);U+71C9(3,8,9);U+71C9(3,8,9) +U+7098(0);U+7098(0,9); +U+7099(0);U+7099(5,9); +U+709A(0);U+709A(0,9);U+5149(3,9),U+706E(3,8),U+70E1(3,9) +U+709C(0);U+7152(1,3,8,9);U+7152(1,3,8,9) +U+709D(0);U+7197(1,3,8,9);U+7197(1,3,8,9) +U+709E(0);U+709E(0); +U+709F(0);U+709F(0,9); +U+70A0(0);U+70A0(0); + +U+70A1(0);U+70A1(0,9); +U+70A2(0);U+70A2(0); +U+70A3(0);U+70A3(0); +U+70A4(0);U+70A4(0,9);U+7167(2,3,8,9),U+66CC(0,2,3,8,9) +U+70A5(0);U+70A5(0); +U+70A6(0);U+70A6(0); +U+70A7(0);U+70A7(0); +U+70A8(0);U+70A8(0); +U+70A9(0);U+70A9(0,9); +U+70AB(0);U+70AB(5,9); +U+70AC(0);U+70AC(5,9); +U+70AD(0);U+70AD(5,9); +U+70AE(0);U+70AE(5,9);U+70B0(3,8,9),U+7832(2,3,8,9),U+792E(2,3,8) +U+70AF(0);U+70AF(5,9);U+70F1(2,3,8) +U+70B0(0);U+70B0(0,9);U+70AE(3,8,9),U+7832(2,3,8,9),U+792E(2,3,8) +U+70B1(0);U+70B1(5,9); +U+70B3(0);U+70B3(5,9);U+663A(3,9) +U+70B4(0);U+70B4(0,9); +U+70B5(0);U+70B5(0,9); +U+70B7(0);U+70B7(5,9); +U+70B8(0);U+70B8(5,9); +U+70B9(0);U+9EDE(1,3,8,9);U+594C(4),U+9EDE(1,3,8,9) +U+70BA(0);U+70BA(0,9);U+4E3A(3,8),U+7232(3,8) +U+70BB(0);U+70BB(5); +U+70BC(0);U+7149(1,3,8,9);U+7149(1,3,8,9),U+934A(4,9) +U+70BD(0);U+71BE(1,3,8,9);U+71BE(1,3,8,9) +U+70BE(0);U+70BE(0,9); +U+70BF(0);U+70BF(0); +U+70C0(0);U+70C0(5); +U+70C1(0);U+720D(1,3,8,9);U+720D(1,3,8,9) +U+70C2(0);U+721B(1,3,8,9);U+71D7(3),U+721B(1,3,8,9) +U+70C3(0);U+70F4(1,3,8,9);U+70F4(1,3,8,9) +U+70C4(0);U+70C4(3); +U+70C5(0);U+70C5(0,9); +U+70C6(0);U+70C6(0,9); +U+70C7(0);U+70C7(0,9); +U+70C8(0);U+70C8(5,9); +U+70C9(0);U+7165(4,8,9);U+7115(3),U+7165(4,8,9) +U+70CA(0);U+70CA(5,9); +U+70CB(0);U+70CB(0,9); +U+70CC(0);U+70CC(0); +U+70CD(0);U+70CD(0,9); +U+70CE(0);U+70CE(0,9); +U+70CF(0);U+70CF(0,9);U+4E4C(1,3,8) +U+70D0(0);U+70D0(0); +U+70D1(0);U+70D1(0,9); +U+70D2(0);U+70D2(0,9); +U+70D3(0);U+70D3(0,9); +U+70D4(0);U+70D4(3,9); +U+70D6(0);U+707D(4,8,9);U+707D(4,8,9),U+707E(2) +U+70D7(0);U+70D7(3,9); +U+70D8(0);U+70D8(5,9);U+7074(3,9) +U+70D9(0);U+70D9(5,9); +U+70DA(0);U+70DA(0,9); +U+70DB(0);U+71ED(1,3,8,9);U+71ED(1,3,8,9) +U+70DC(0);U+70DC(0,9); +U+70DD(0);U+70DD(0,9); +U+70DE(0);U+70DE(0,9); +U+70DF(0);U+7159(2,3,8,9);U+7159(2,3,8,9),U+83F8(2,9) +U+70E0(0);U+70E0(0,9); +U+70E1(0);U+70E1(0,9);U+5149(3,9),U+706E(3,8),U+709A(3,9) +U+70E2(0);U+70E2(0,9); +U+70E3(0);U+70E3(0); + +U+70E4(0);U+70E4(5,9); +U+70E5(0);U+70E5(0); +U+70E6(0);U+7169(1,3,8,9);U+7169(1,3,8,9) +U+70E7(0);U+71D2(1,3,8,9);U+71D2(1,3,8,9) +U+70E8(0);U+71C1(1,3,8,9);U+71C1(1,3,8,9) +U+70E9(0);U+71F4(1,3,8,9);U+71F4(1,3,8,9) +U+70EA(0);U+70EA(0); +U+70EB(0);U+71D9(1,3,8,9);U+71D9(1,3,8,9) +U+70EC(0);U+71FC(1,3,8,9);U+7161(3,9),U+71FC(1,3,8,9) +U+70ED(0);U+71B1(1,3,8,9);U+71B1(1,3,8,9) +U+70EE(0);U+70EE(0); +U+70EF(0);U+70EF(5,9); +U+70F0(0);U+70F0(0,9); +U+70F1(0);U+70AF(2,3,8,9);U+70AF(2,3,8,9) +U+70F2(0);U+70F2(3); +U+70F3(0);U+70F3(0,9); +U+70F4(0);U+70F4(0,9);U+70C3(1,3,8) +U+70F5(0);U+70F5(0); +U+70F6(0);U+70F6(0,9); +U+70F7(0);U+70F7(5,9); +U+70F8(0);U+70F8(0,9); +U+70F9(0);U+70F9(5,9); +U+70FA(0);U+70FA(0,9);U+6717(3,9),U+6716(0,3,8) +U+70FB(0);U+70FB(0,9); +U+70FC(0);U+70FC(0,9); +U+70FD(0);U+70FD(5,9); +U+70FF(0);U+70FF(0,9); +U+7100(0);U+7100(0,9); +U+7101(0);U+7101(0); +U+7102(0);U+7102(0,9); +U+7103(0);U+7103(0); +U+7104(0);U+7104(0,9); +U+7105(0);U+7105(0); +U+7106(0);U+7106(0,9); +U+7107(0);U+7107(0); +U+7109(0);U+7109(5,9); +U+710A(0);U+710A(5,9);U+91EC(2,3,9),U+92B2(2,9) +U+710B(0);U+710B(0,9); +U+710C(0);U+710C(3,9);U+71C7(3,9) +U+710D(0);U+710D(0,9); +U+710E(0);U+710E(0,9); +U+710F(0);U+710F(0); +U+7110(0);U+7110(5,9); +U+7111(0);U+7111(0); +U+7112(0);U+7112(0); +U+7113(0);U+7113(5,9); +U+7115(0);U+7165(4,8,9);U+70C9(3),U+7165(4,8,9) +U+7116(0);U+71DC(1,3,8,9);U+71DC(1,3,8,9) +U+7117(0);U+7117(0,9); +U+7118(0);U+71FE(1,3,8,9);U+71FE(1,3,8,9) +U+7119(0);U+7119(5,9); +U+711A(0);U+711A(5,9);U+7083(3,9) +U+711B(0);U+711B(0,9); +U+711C(0);U+711C(0,9); +U+711D(0);U+711D(0); +U+711E(0);U+711E(0,9); +U+711F(0);U+711F(0,9); +U+7120(0);U+7120(3,9); +U+7121(0);U+7121(0,9);U+65E0(1,3,8) +U+7122(0);U+7122(0,9); +U+7123(0);U+7123(0,9); +U+7125(0);U+7125(0,9); +U+7126(0);U+7126(5,9); + +U+7127(0);U+7127(0); +U+7128(0);U+7128(0,9); +U+7129(0);U+7129(0); +U+712A(0);U+712A(3); +U+712B(0);U+712B(0); +U+712C(0);U+712C(0); +U+712D(0);U+7162(3,4,8,9);U+7162(3,4,8,9),U+8315(1,3,4,8),U+60F8(0,1,3,4,8,9) +U+712E(0);U+712E(3,9); +U+712F(0);U+712F(5,9); +U+7130(0);U+7130(5,9);U+71C4(2,3,9) +U+7131(0);U+7131(5,9); +U+7132(0);U+7132(3,9); +U+7135(0);U+7135(0); +U+7136(0);U+7136(5,9); +U+7137(0);U+7137(0); +U+7138(0);U+7138(4); +U+7139(0);U+7139(0); +U+713A(0);U+713A(0,9); +U+713B(0);U+713B(0); +U+713D(0);U+713D(0); +U+713E(0);U+713E(0); +U+713F(0);U+713F(0); +U+7140(0);U+7140(0); +U+7141(0);U+7141(0,9); +U+7142(0);U+7142(0,9); +U+7143(0);U+7143(0,9); +U+7144(0);U+7144(0,9); +U+7145(0);U+935B(3,8,9);U+935B(3,8,9),U+953B(1,3,8) +U+7146(0);U+7146(0,9); +U+7147(0);U+7147(4,9); +U+7148(0);U+7148(0); +U+7149(0);U+7149(0,9);U+70BC(1,3,8),U+934A(1,3,4,8,9) +U+714A(0);U+714A(5); +U+714B(0);U+714B(0,9); +U+714C(0);U+714C(5,9); +U+714D(0);U+714D(0,9); +U+714E(0);U+714E(5,9); +U+714F(0);U+714F(0); +U+7150(0);U+7150(0,9); +U+7151(0);U+716E(2,3,8,9);U+716E(2,3,8,9) +U+7152(0);U+7152(0,9);U+709C(1,3,8) +U+7153(0);U+7153(0,9); +U+7154(0);U+7154(3,9); +U+7156(0);U+7156(4,9);U+6696(2,3,8,9) +U+7158(0);U+7158(0,9); +U+7159(0);U+7159(0,9);U+70DF(2,3,8),U+83F8(4,8,9) +U+715A(0);U+715A(3,9);U+71DB(3,9) +U+715B(0);U+715B(0); +U+715C(0);U+715C(5,9); +U+715D(0);U+715D(0,9); +U+715E(0);U+715E(5,9); +U+715F(0);U+715F(0,9); +U+7160(0);U+7160(3,9); +U+7161(0);U+7161(0,9);U+70EC(3),U+71FC(1,3,8,9) +U+7162(0);U+7162(0,9);U+712D(3,4,8),U+8315(1,3,8),U+60F8(0,1,3,4,8,9) +U+7163(0);U+7163(3,9); +U+7164(0);U+7164(5,9); +U+7165(0);U+7165(0,9);U+70C9(4,8),U+7115(4,8) +U+7166(0);U+7166(5,9); +U+7167(0);U+7167(5,9);U+66CC(3,9),U+70A4(2,3,8,9) +U+7168(0);U+7168(5,9);U+71F0(3,9) +U+7169(0);U+7169(0,9);U+70E6(1,3,8) +U+716A(0);U+716A(0,9); + +U+716C(0);U+716C(0,9);U+7080(1,3,8) +U+716E(0);U+716E(5,9);U+7151(2,3,8) +U+716F(0);U+716F(0); +U+7170(0);U+7170(0,9);U+71E5(3,9) +U+7171(0);U+7171(3); +U+7172(0);U+7172(5,9); +U+7173(0);U+7173(5); +U+7174(0);U+7185(4,9);U+7185(4,9) +U+7175(0);U+7175(0); +U+7176(0);U+7176(0); +U+7177(0);U+7177(0); +U+7178(0);U+7178(5,9); +U+7179(0);U+7179(0); +U+717A(0);U+717A(5); +U+717B(0);U+717B(0,9); +U+717C(0);U+717C(0); +U+717D(0);U+717D(5,9); +U+717E(0);U+717E(0); +U+717F(0);U+717F(0); +U+7180(0);U+7180(0,9); +U+7181(0);U+7181(0,9); +U+7182(0);U+7182(0,9); +U+7183(0);U+7183(0); +U+7184(0);U+7184(5,9); +U+7185(0);U+7185(0,9);U+7174(4) +U+7186(0);U+7186(0,9); +U+7187(0);U+7187(3,9); +U+7188(0);U+7199(2,8,9);U+7199(2,8,9) +U+7189(0);U+7189(0,9); +U+718A(0);U+718A(5,9); +U+718B(0);U+718B(0); +U+718C(0);U+718C(0); +U+718E(0);U+718E(0); +U+718F(0);U+71FB(2,3,8,9);U+71FB(2,3,8,9) +U+7190(0);U+7190(0,9); +U+7191(0);U+7191(3); +U+7192(0);U+7192(0,9);U+8367(1,3,8) +U+7193(0);U+7193(0); +U+7194(0);U+7194(5,9);U+9394(2,8,9),U+9555(2,4,8) +U+7195(0);U+7195(0); +U+7197(0);U+7197(0,9);U+709D(1,3,8) +U+7198(0);U+7198(5); +U+7199(0);U+7199(5,9);U+7188(2,8) +U+719A(0);U+719A(0,9); +U+719B(0);U+719B(0,9); +U+719C(0);U+719C(3,9); +U+719D(0);U+719D(0,9); +U+719E(0);U+719E(0,9); +U+719F(0);U+719F(5,9); +U+71A0(0);U+71A0(5,9); +U+71A1(0);U+71A1(0,9); +U+71A2(0);U+71A2(0); +U+71A3(0);U+71A3(0); +U+71A4(0);U+71A4(0,9); +U+71A5(0);U+71A5(0,9); +U+71A7(0);U+71A7(0,9); +U+71A8(0);U+71A8(5,9); +U+71A9(0);U+71A9(0,9); +U+71AA(0);U+71AA(0,9); +U+71AC(0);U+71AC(5,9); +U+71AD(0);U+71AD(0); +U+71AE(0);U+71AE(0); +U+71AF(0);U+71AF(0,9); + +U+71B0(0);U+71B0(0,9); +U+71B1(0);U+71B1(0,9);U+70ED(1,3,8) +U+71B2(0);U+71B2(0,9);U+988E(4,8) +U+71B3(0);U+71B3(5,9); +U+71B4(0);U+71B4(0); +U+71B5(0);U+71B5(5,9); +U+71B7(0);U+71B7(0); +U+71B8(0);U+71B8(0,9); +U+71B9(0);U+71B9(5,9);U+71BA(3,8) +U+71BA(0);U+71B9(3,8,9);U+71B9(3,8,9) +U+71BB(0);U+71BB(0); +U+71BC(0);U+71BC(0,9); +U+71BD(0);U+71BD(0,9); +U+71BE(0);U+71BE(0,9);U+70BD(1,3,8) +U+71BF(0);U+71BF(0,9); +U+71C0(0);U+71C0(0,9); +U+71C1(0);U+71C1(0,9);U+70E8(1,3,8) +U+71C2(0);U+71C2(3,9); +U+71C3(0);U+71C3(5,9); +U+71C4(0);U+71C4(0,9);U+7130(2,3,9) +U+71C5(0);U+71C5(0,9); +U+71C6(0);U+71C6(0,9); +U+71C7(0);U+71C7(0,9);U+710C(3,9) +U+71C8(0);U+71C8(0,9);U+706F(1,3,8) +U+71C9(0);U+71C9(0,9);U+7096(3,8,9) +U+71CA(0);U+71CA(0,9); +U+71CB(0);U+71CB(0,9); +U+71CD(0);U+71CD(0); +U+71CE(0);U+71CE(5,9); +U+71CF(0);U+71CF(0,9); +U+71D0(0);U+71D0(4,9);U+78F7(2,9) +U+71D1(0);U+71D1(0); +U+71D2(0);U+71D2(0,9);U+70E7(1,3,8) +U+71D4(0);U+71D4(5,9); +U+71D5(0);U+71D5(5,9);U+89FE(3,9),U+9DF0(2,3,8,9) +U+71D6(0);U+71D6(3,9); +U+71D7(0);U+721B(3,8,9);U+70C2(3),U+721B(3,8,9) +U+71D8(0);U+71D8(0,9); +U+71D9(0);U+71D9(0,9);U+70EB(1,3,8) +U+71DA(0);U+71DA(0,9); +U+71DB(0);U+71DB(0,9);U+715A(3,9) +U+71DC(0);U+71DC(0,9);U+7116(1,3,8) +U+71DD(0);U+71DD(0); +U+71DE(0);U+71DE(0); +U+71DF(0);U+71DF(0,9);U+55B6(4,8),U+8425(1,3,8) +U+71E0(0);U+71E0(5,9); +U+71E1(0);U+71E1(3,9); +U+71E2(0);U+71E2(0,9); +U+71E3(0);U+71E3(0);U+71F7(4,8) +U+71E4(0);U+71E4(0,9); +U+71E5(0);U+71E5(5,9);U+7170(3,9) +U+71E6(0);U+71E6(0,9);U+707F(1,3,8) +U+71E7(0);U+71E7(5,9); +U+71E8(0);U+71E8(0,9);U+7214(3,9) +U+71E9(0);U+71E9(0); +U+71EA(0);U+71EA(0); +U+71EB(0);U+71EB(0); +U+71EC(0);U+71EC(0,9); +U+71ED(0);U+71ED(0,9);U+70DB(1,3,8) +U+71EE(0);U+71EE(5,9); +U+71EF(0);U+71EF(0);U+7227(3,9) +U+71F0(0);U+71F0(0,9);U+7168(3,9) +U+71F1(0);U+71F1(0,9); + +U+71F2(0);U+71F2(0,9); +U+71F4(0);U+71F4(0,9);U+70E9(1,3,8) +U+71F5(0);U+71F5(0); +U+71F6(0);U+71F6(0); +U+71F7(0);U+71E3(4,8);U+71E3(4,8) +U+71F8(0);U+71F8(0,9); +U+71F9(0);U+71F9(5,9); +U+71FB(0);U+71FB(0,9);U+718F(2,3,8,9) +U+71FC(0);U+71FC(0,9);U+70EC(1,3,8),U+7161(1,3,8,9) +U+71FD(0);U+71FD(0,9); +U+71FE(0);U+71FE(0,9);U+7118(1,3,8) +U+71FF(0);U+71FF(0,9);U+66DC(3,9),U+8000(2,3,8,9) +U+7201(0);U+7201(4,9);U+7226(4,9) +U+7202(0);U+7202(0,9); +U+7203(0);U+7203(0,9); +U+7204(0);U+7204(0); +U+7205(0);U+7205(0,9); +U+7206(0);U+7206(5,9); +U+7207(0);U+7207(3,9); +U+7208(0);U+7208(0); +U+7209(0);U+7209(0); +U+720A(0);U+720A(0,9); +U+720C(0);U+720C(3,9); +U+720D(0);U+720D(0,9);U+70C1(1,3,8) +U+720E(0);U+720E(0); +U+720F(0);U+720F(0); +U+7210(0);U+7210(0,9);U+7089(1,3,8),U+946A(1,3,4,8,9) +U+7212(0);U+7212(3); +U+7213(0);U+7213(0,9); +U+7214(0);U+7214(3,9);U+71E8(3,9) +U+7216(0);U+7216(0); +U+7218(0);U+7218(0); +U+7219(0);U+7219(0,9); +U+721A(0);U+721A(3,9); +U+721B(0);U+721B(0,9);U+70C2(1,3,8),U+71D7(3,8) +U+721C(0);U+721C(0); +U+721D(0);U+721D(5,9); +U+721E(0);U+721E(3,9); +U+721F(0);U+721F(0,9); +U+7221(0);U+7221(0); +U+7222(0);U+7222(0,9);U+7CDC(3,9) +U+7223(0);U+7223(0,9); +U+7226(0);U+7226(0,9);U+7201(4,9) +U+7227(0);U+7227(0,9);U+71EF(3) +U+7228(0);U+7228(5,9); +U+7229(0);U+7229(0,9); +U+722A(0);U+722A(5,9); +U+722B(0);U+722B(0); +U+722C(0);U+722C(5,9); +U+722D(0);U+722D(0,9);U+4E89(3,4,8) +U+722E(0);U+722E(0); +U+7230(0);U+7230(5,9); +U+7231(0);U+611B(1,3,8,9);U+611B(1,3,8,9) +U+7232(0);U+70BA(3,8,9);U+4E3A(1,3,8),U+70BA(3,8,9) +U+7233(0);U+7233(0); +U+7235(0);U+7235(5,9); +U+7236(0);U+7236(5,9); +U+7237(0);U+723A(1,3,8,9);U+723A(1,3,8,9) +U+7238(0);U+7238(5,9); +U+7239(0);U+7239(5,9); +U+723A(0);U+723A(0,9);U+7237(1,3,8) +U+723B(0);U+723B(5,9); +U+723C(0);U+4FCE(3,8,9);U+4FCE(3,8,9) + +U+723D(0);U+723D(5,9);U+6161(3,9) +U+723E(0);U+723E(0,9);U+5C12(2,3,8,9),U+5C13(3,8),U+5C14(1,3,8) +U+723F(0);U+723F(5,9);U+4E2C(8) +U+7240(0);U+5E8A(2,3,8,9);U+5E8A(2,3,8,9) +U+7241(0);U+7241(3,9); +U+7242(0);U+7242(3,9); +U+7243(0);U+7243(0); +U+7244(0);U+7244(0,9); +U+7246(0);U+7246(0,9);U+5899(4,8),U+58BB(2,3,8,9) +U+7247(0);U+7247(5,9); +U+7248(0);U+7248(5,9); +U+7249(0);U+7249(3,9); +U+724A(0);U+724A(0,9); +U+724B(0);U+724B(0,9);U+7B3A(2,3),U+7B8B(2,3,8,9) +U+724C(0);U+724C(5,9); +U+724D(0);U+7258(1,3,8,9);U+7258(1,3,8,9) +U+724F(0);U+724F(0,9); +U+7251(0);U+7251(0); +U+7252(0);U+7252(5,9); +U+7253(0);U+7253(0,9);U+699C(3,9) +U+7254(0);U+7254(0); +U+7256(0);U+7256(5,9); +U+7257(0);U+7257(0); +U+7258(0);U+7258(0,9);U+724D(1,3,8) +U+7259(0);U+7259(5,9); +U+725A(0);U+725A(0,9);U+6491(4),U+6490(0,2,3,4,8,9) +U+725B(0);U+725B(5,9); +U+725C(0);U+725C(0); +U+725D(0);U+725D(5,9); +U+725E(0);U+725E(0,9); +U+725F(0);U+725F(5,9); +U+7260(0);U+7260(0,9);U+5B83(2,3,8,9) +U+7261(0);U+7261(5,9); +U+7262(0);U+7262(5,9); +U+7263(0);U+7263(0,9); +U+7264(0);U+7264(0); +U+7265(0);U+7265(0); +U+7266(0);U+729B(2,3,8,9);U+6C02(2,3,9),U+729B(2,3,8,9),U+9AE6(3,9) +U+7267(0);U+7267(5,9); +U+7268(0);U+7268(0); +U+7269(0);U+7269(5,9); +U+726A(0);U+726A(0,9); +U+726B(0);U+726B(0); +U+726C(0);U+726C(0,9); +U+726D(0);U+726D(0); +U+726E(0);U+726E(5,9); +U+726F(0);U+726F(5,9); +U+7270(0);U+7270(0,9); +U+7271(0);U+7271(0); +U+7272(0);U+7272(5,9); +U+7273(0);U+7273(0,9); +U+7274(0);U+7274(0,9);U+62B5(2,3,9),U+7F9D(3,8,9),U+89DD(4,8,9),U+627A(2,3,8,9) +U+7275(0);U+727D(1,3,8,9);U+727D(1,3,8,9) +U+7276(0);U+7276(0,9); +U+7277(0);U+7277(0,9); +U+7278(0);U+7278(0,9); +U+7279(0);U+7279(5,9); +U+727A(0);U+72A7(1,3,8,9);U+72A7(1,3,8,9) +U+727B(0);U+727B(0,9); +U+727C(0);U+727C(0,9); +U+727D(0);U+727D(0,9);U+7275(1,3,8) +U+727E(0);U+727E(5,9); +U+727F(0);U+727F(5,9); + +U+7280(0);U+7280(5,9); +U+7281(0);U+7281(5,9);U+7282(2,3,8) +U+7282(0);U+7281(2,3,8,9);U+7281(2,3,8,9) +U+7283(0);U+7283(0); +U+7284(0);U+7284(5,9); +U+7285(0);U+7285(3,9); +U+7286(0);U+7286(0,9); +U+7287(0);U+5954(2,3,8,9);U+5954(2,3,8,9),U+9029(2,3,8) +U+7288(0);U+7288(0,9); +U+7289(0);U+7289(0,9); +U+728A(0);U+72A2(1,3,8,9);U+72A2(1,3,8,9) +U+728B(0);U+728B(5,9); +U+728C(0);U+728C(0,9); +U+728D(0);U+728D(5,9); +U+728E(0);U+728E(0,9); +U+728F(0);U+728F(5); +U+7290(0);U+7290(0,9); +U+7291(0);U+7291(0,9); +U+7292(0);U+7292(5,9); +U+7293(0);U+7293(0,9); +U+7294(0);U+7294(0); +U+7295(0);U+7295(0,9); +U+7296(0);U+7296(0,9);U+8366(1,3,8) +U+7297(0);U+7297(0,9); +U+7298(0);U+7298(0,9); +U+7299(0);U+7299(0); +U+729A(0);U+729A(0,9); +U+729B(0);U+729B(0,9);U+7266(2,3,8),U+6C02(0,2,3,8,9),U+9AE6(2,3,8,9) +U+729C(0);U+729C(0); +U+729D(0);U+729D(0,9); +U+729E(0);U+729E(0,9); +U+729F(0);U+729F(5); +U+72A1(0);U+72A1(0,9); +U+72A2(0);U+72A2(0,9);U+728A(1,3,8) +U+72A3(0);U+72A3(0,9); +U+72A4(0);U+72A4(0,9); +U+72A5(0);U+72A5(0,9); +U+72A6(0);U+72A6(0,9); +U+72A7(0);U+72A7(0,9);U+727A(1,3,8) +U+72A8(0);U+72A8(3,9); +U+72A9(0);U+72A9(0,9); +U+72AA(0);U+72AA(3,9); +U+72AC(0);U+72AC(5,9); +U+72AD(0);U+72AD(5); +U+72AE(0);U+72AE(0,9); +U+72AF(0);U+72AF(5,9); +U+72B0(0);U+72B0(5,9); +U+72B1(0);U+72B1(0); +U+72B2(0);U+8C7A(3,8,9);U+8C7A(3,8,9) +U+72B3(0);U+72B3(0); +U+72B4(0);U+72B4(5,9); +U+72B5(0);U+72B5(0,9); +U+72B6(0);U+72C0(1,3,4,8,9);U+72C0(1,3,4,8,9) +U+72B7(0);U+7377(1,3,8,9);U+7377(1,3,8,9) +U+72B8(0);U+7341(1,3,8);U+7341(1,3,8) +U+72B9(0);U+7336(1,3,8,9);U+7336(1,3,8,9) +U+72BA(0);U+72BA(0,9); +U+72BB(0);U+72BB(0); +U+72BC(0);U+72BC(0); +U+72BD(0);U+72BD(0,9); +U+72BF(0);U+72BF(0,9); +U+72C0(0);U+72C0(0,9);U+72B6(1,3,8) +U+72C1(0);U+72C1(5,9); + +U+72C2(0);U+72C2(5,9);U+72C5(3,9) +U+72C3(0);U+72C3(5,9); +U+72C4(0);U+72C4(5,9); +U+72C5(0);U+72C5(0,9);U+72C2(3,9) +U+72C6(0);U+72C6(0,9);U+4EF2(3,9) +U+72C7(0);U+72C7(0); +U+72C8(0);U+72FD(1,3,8,9);U+72FD(1,3,8,9) +U+72C9(0);U+72C9(0,9); +U+72CA(0);U+72CA(0,9); +U+72CB(0);U+72CB(3,9); +U+72CC(0);U+72CC(0,9); +U+72CD(0);U+72CD(5); +U+72CE(0);U+72CE(5,9); +U+72CF(0);U+72CF(0); +U+72D0(0);U+72D0(5,9); +U+72D1(0);U+72D1(0,9); +U+72D2(0);U+72D2(5,9); +U+72D3(0);U+72D3(0); +U+72D4(0);U+72D4(0,9); +U+72D5(0);U+72D5(0); +U+72D6(0);U+72D6(3,9); +U+72D7(0);U+72D7(5,9); +U+72D8(0);U+72D8(0,9); +U+72D9(0);U+72D9(5,9); +U+72DA(0);U+72DA(0,9); +U+72DB(0);U+72DB(0); +U+72DC(0);U+72DC(0,9); +U+72DD(0);U+736E(4,8,9);U+736E(4,8,9) +U+72DE(0);U+7370(1,3,8,9);U+7370(1,3,8,9) +U+72DF(0);U+72DF(0,9); +U+72E0(0);U+72E0(5,9); +U+72E1(0);U+72E1(5,9); +U+72E2(0);U+8C89(3,8,9);U+8C89(3,8,9) +U+72E3(0);U+72E3(0,9); +U+72E4(0);U+72E4(0,9); +U+72E5(0);U+72E5(4); +U+72E6(0);U+72E6(0,9); +U+72E7(0);U+72E7(0); +U+72E8(0);U+72E8(5,9); +U+72E9(0);U+72E9(5,9); +U+72EA(0);U+72EA(0,9); +U+72EB(0);U+72EB(0,9);U+4F6C(3,9) +U+72EC(0);U+7368(1,3,8,9);U+7368(1,3,8,9) +U+72ED(0);U+72F9(1,3,8,9);U+72F9(1,3,8,9) +U+72EE(0);U+7345(1,3,8,9);U+7345(1,3,8,9) +U+72EF(0);U+736A(1,3,8,9);U+736A(1,3,8,9),U+733E(1,3,8,9) +U+72F0(0);U+7319(4,8,9);U+7319(4,8,9) +U+72F1(0);U+7344(1,3,8,9);U+7344(1,3,8,9) +U+72F2(0);U+733B(1,3,8,9);U+733B(1,3,8,9) +U+72F3(0);U+72F3(5,9); +U+72F4(0);U+72F4(5,9); +U+72F5(0);U+72F5(0); +U+72F6(0);U+72F6(0,9); +U+72F7(0);U+72F7(5,9);U+7367(2,9) +U+72F8(0);U+72F8(5,9),U+8C8D(2,3,8,9);U+8C8D(2,3,8,9) +U+72F9(0);U+72F9(0,9);U+72ED(1,3,8) +U+72FA(0);U+72FA(5,9); +U+72FB(0);U+72FB(5,9); +U+72FC(0);U+72FC(5,9); +U+72FD(0);U+72FD(0,9);U+72C8(1,3,8) +U+72FE(0);U+72FE(3,9); +U+72FF(0);U+72FF(0,9); +U+7300(0);U+7300(0,9); + +U+7301(0);U+7301(5,9); +U+7303(0);U+736B(1,3,8,9);U+736B(1,3,8,9),U+7381(3,9) +U+7304(0);U+7304(0); +U+7305(0);U+7305(0); +U+7306(0);U+7306(0); +U+7307(0);U+7307(0,9); +U+7308(0);U+7308(3,9); +U+7309(0);U+7309(0); +U+730A(0);U+730A(5,9); +U+730B(0);U+730B(4,9); +U+730C(0);U+730C(0,9); +U+730D(0);U+730D(0); +U+730E(0);U+7375(1,3,8,9);U+7375(1,3,8,9) +U+730F(0);U+730F(0,9); +U+7311(0);U+7311(0,9); +U+7312(0);U+7312(0,9);U+538C(3),U+53AD(1,3,8,9) +U+7313(0);U+7313(5,9); +U+7314(0);U+7314(0); +U+7315(0);U+737C(1,3,8,9);U+737C(1,3,8,9) +U+7316(0);U+7316(5,9); +U+7317(0);U+7317(5,9); +U+7318(0);U+7318(0,9); +U+7319(0);U+7319(0,9);U+72F0(4,8) +U+731A(0);U+731A(0); +U+731B(0);U+731B(5,9); +U+731C(0);U+731C(5,9); +U+731D(0);U+731D(5,9); +U+731E(0);U+731E(5,9); +U+7320(0);U+7320(0); +U+7321(0);U+7380(1,3,8,9);U+7380(1,3,8,9) +U+7322(0);U+7322(5,9); +U+7323(0);U+7323(0,9); +U+7324(0);U+7324(0); +U+7325(0);U+7325(5,9); +U+7326(0);U+7326(0,9); +U+7327(0);U+7327(0,9); +U+7329(0);U+7329(5,9); +U+732A(0);U+8C6C(2,3,8,9);U+8C6C(2,3,8,9) +U+732B(0);U+8C93(2,3,9);U+8C93(2,3,9) +U+732C(0);U+732C(5);U+875F(2,3,9) +U+732D(0);U+732D(0,9); +U+732E(0);U+737B(1,3,8,9);U+737B(1,3,8,9) +U+7330(0);U+7330(3,9); +U+7331(0);U+7331(5,9); +U+7332(0);U+7332(3,9); +U+7333(0);U+7333(0,9); +U+7334(0);U+7334(5,9); +U+7335(0);U+7335(3,9); +U+7336(0);U+7336(0,9);U+72B9(1,3,8) +U+7337(0);U+7337(5,9); +U+7338(0);U+7338(5); +U+7339(0);U+7339(5); +U+733A(0);U+733A(0,9); +U+733B(0);U+733B(0,9);U+72F2(1,3,8) +U+733C(0);U+733C(0,9); +U+733D(0);U+733D(0); +U+733E(0);U+733E(5,9);U+736A(3,8,9),U+72EF(1,3,8) +U+733F(0);U+733F(5,9);U+876F(2,3,9) +U+7340(0);U+7340(0,9); +U+7341(0);U+7341(0);U+72B8(1,3,8) +U+7342(0);U+7342(0,9); +U+7343(0);U+7343(0,9);U+5446(2,3,8,9),U+9A03(4,9) +U+7344(0);U+7344(0,9);U+72F1(1,3,8) + +U+7345(0);U+7345(0,9);U+72EE(1,3,8) +U+7346(0);U+7346(4); +U+7347(0);U+7347(0); +U+7348(0);U+7348(0); +U+7349(0);U+7349(0,9);U+699B(4,9),U+6A3C(3,4,9) +U+734A(0);U+734A(0,9); +U+734B(0);U+734B(0); +U+734C(0);U+734C(0,9); +U+734D(0);U+734D(5,9); +U+734E(0);U+734E(0,9);U+5956(4),U+5968(8),U+596C(2,8) +U+7350(0);U+7350(5,9); +U+7351(0);U+7351(3,9); +U+7352(0);U+7352(5,9); +U+7354(0);U+7354(0); +U+7355(0);U+7355(0); +U+7356(0);U+7356(0); +U+7357(0);U+7357(5,9); +U+7358(0);U+7358(0,9); +U+7359(0);U+7359(3,9); +U+735A(0);U+735A(0,9); +U+735B(0);U+735B(0,9); +U+735C(0);U+735C(3); +U+735D(0);U+735D(3,9); +U+735E(0);U+735E(0,9);U+50EE(3,9) +U+735F(0);U+735F(0,9); +U+7360(0);U+7360(5,9); +U+7361(0);U+7361(0,9); +U+7362(0);U+7362(0,9); +U+7364(0);U+7364(0); +U+7365(0);U+7365(0,9); +U+7366(0);U+7366(0,9); +U+7367(0);U+7367(0,9);U+72F7(2,9) +U+7368(0);U+7368(0,9);U+72EC(1,3,8) +U+7369(0);U+7369(0,9); +U+736A(0);U+736A(0,9);U+72EF(1,3,8),U+733E(3,8,9) +U+736B(0);U+736B(0,9);U+7303(1,3,8),U+7381(1,3,8,9) +U+736C(0);U+736C(5,9); +U+736D(0);U+737A(1,3,8,9);U+737A(1,3,8,9) +U+736E(0);U+736E(0,9);U+72DD(4,8) +U+736F(0);U+736F(5,9); +U+7370(0);U+7370(0,9);U+72DE(1,3,8) +U+7371(0);U+7371(0); +U+7372(0);U+7372(0,9);U+83B7(1,3,8),U+7A6B(1,3,8,9) +U+7373(0);U+7373(0,9); +U+7374(0);U+7374(0); +U+7375(0);U+7375(0,9);U+730E(1,3,8) +U+7376(0);U+7376(4,9); +U+7377(0);U+7377(0,9);U+72B7(1,3,8) +U+7378(0);U+7378(0,9);U+517D(1,3,8) +U+7379(0);U+7379(3); +U+737A(0);U+737A(0,9);U+736D(1,3,8) +U+737B(0);U+737B(0,9);U+732E(1,3,8) +U+737C(0);U+737C(0,9);U+7315(1,3,8) +U+737D(0);U+737D(0,9); +U+737E(0);U+737E(5,9); +U+737F(0);U+737F(0,9); +U+7380(0);U+7380(0,9);U+7321(1,3,8) +U+7381(0);U+7381(0,9);U+7303(3),U+736B(1,3,8,9) +U+7382(0);U+7382(0,9); +U+7383(0);U+7383(3,9);U+8C9C(3,9) +U+7384(0);U+7384(5,9); +U+7385(0);U+7385(0,9);U+5999(2,3,8,9) +U+7386(0);U+7386(3,9);U+5179(7),U+8332(3,8,9) + +U+7387(0);U+7387(5,9); +U+7388(0);U+7388(0,9); +U+7389(0);U+7389(5,9); +U+738A(0);U+738A(3,9); +U+738B(0);U+738B(5,9); +U+738C(0);U+738C(0); +U+738D(0);U+738D(0); +U+738E(0);U+738E(5,9); +U+738F(0);U+738F(0); +U+7390(0);U+7390(0); +U+7391(0);U+74A3(1,3,8,9);U+74A3(1,3,8,9) +U+7392(0);U+7392(3,9); +U+7393(0);U+7393(0,9); +U+7394(0);U+7394(0,9); +U+7395(0);U+7395(3,9); +U+7396(0);U+7396(5,9); +U+7397(0);U+7397(0,9); +U+7398(0);U+7398(0); +U+7399(0);U+74B5(4,8,9);U+74B5(4,8,9) +U+739A(0);U+7452(4,8,9);U+7452(4,8,9),U+7497(4,9) +U+739B(0);U+746A(1,3,8,9);U+746A(1,3,8,9) +U+739D(0);U+739D(0,9); +U+739E(0);U+739E(3); +U+739F(0);U+739F(5,9);U+73C9(3,8),U+741D(3,8,9) +U+73A0(0);U+73A0(3,9); +U+73A1(0);U+73A1(4,9); +U+73A2(0);U+73A2(5,9); +U+73A3(0);U+73A3(0); +U+73A4(0);U+73A4(0,9); +U+73A5(0);U+73A5(0,9); +U+73A6(0);U+73A6(3,9); +U+73A7(0);U+73A7(0); +U+73A8(0);U+73A8(3,9); +U+73A9(0);U+73A9(5,9); +U+73AA(0);U+73AA(0); +U+73AB(0);U+73AB(5,9); +U+73AC(0);U+73AC(0,9); +U+73AD(0);U+73AD(3,9); +U+73AE(0);U+744B(1,3,8,9);U+744B(1,3,8,9) +U+73AF(0);U+74B0(1,3,8,9);U+74B0(1,3,8,9) +U+73B0(0);U+73FE(1,3,8,9);U+73FE(1,3,8,9) +U+73B1(0);U+7472(1,3,8,9);U+7472(1,3,8,9) +U+73B2(0);U+73B2(5,9); +U+73B3(0);U+73B3(5,9);U+8773(3,9) +U+73B4(0);U+73B4(0,9); +U+73B5(0);U+73B5(0,9); +U+73B6(0);U+73B6(0,9); +U+73B7(0);U+73B7(5,9); +U+73B8(0);U+73B8(0,9); +U+73B9(0);U+73B9(0,9); +U+73BA(0);U+74BD(1,3,8,9);U+74BD(1,3,8,9) +U+73BB(0);U+73BB(5,9); +U+73BC(0);U+73BC(3,9); +U+73BD(0);U+73BD(0); +U+73BE(0);U+73BE(0,9); +U+73BF(0);U+73BF(0,9); +U+73C0(0);U+73C0(5,9); +U+73C2(0);U+73C2(5,9); +U+73C3(0);U+73C3(0,9); +U+73C4(0);U+73C4(0); +U+73C5(0);U+73C5(0,9); +U+73C6(0);U+73C6(0,9); +U+73C7(0);U+73C7(0,9); + +U+73C8(0);U+73C8(5,9); +U+73C9(0);U+73C9(5);U+739F(3,8,9),U+741D(3,9) +U+73CA(0);U+73CA(5,9); +U+73CB(0);U+73CB(0,9); +U+73CC(0);U+73CC(0,9); +U+73CD(0);U+73CD(5,9);U+73CE(2,3,8) +U+73CE(0);U+73CD(2,3,8,9);U+73CD(2,3,8,9) +U+73CF(0);U+73CF(5); +U+73D0(0);U+73D0(5); +U+73D1(0);U+74CF(1,3,8,9);U+74CF(1,3,8,9) +U+73D2(0);U+73D2(0,9); +U+73D3(0);U+73D3(3,9); +U+73D4(0);U+73D4(0,9); +U+73D5(0);U+73D5(3); +U+73D6(0);U+73D6(0,9); +U+73D7(0);U+73D7(0,9); +U+73D8(0);U+73D8(0,9); +U+73D9(0);U+73D9(5,9); +U+73DA(0);U+73DA(0,9); +U+73DB(0);U+73DB(0,9); +U+73DC(0);U+73DC(0,9); +U+73DD(0);U+73DD(0,9); +U+73DE(0);U+73DE(5,9); +U+73DF(0);U+73DF(0); +U+73E0(0);U+73E0(5,9); +U+73E2(0);U+73E2(0); +U+73E3(0);U+73E3(0,9); +U+73E5(0);U+73E5(5,9); +U+73E6(0);U+73E6(0); +U+73E7(0);U+73E7(5,9); +U+73E8(0);U+73E8(0,9); +U+73E9(0);U+73E9(5,9); +U+73EA(0);U+73EA(0,9);U+572D(3,9) +U+73EB(0);U+73EB(0,9); +U+73EC(0);U+73EC(0); +U+73ED(0);U+73ED(5,9); +U+73EE(0);U+73EE(0,9);U+4F69(4,9) +U+73EF(0);U+73EF(0); +U+73F0(0);U+74AB(4,8,9);U+74AB(4,8,9) +U+73F1(0);U+73F1(0); +U+73F2(0);U+743F(1,3,8,9);U+743F(1,3,8,9) +U+73F4(0);U+73F4(0,9); +U+73F5(0);U+73F5(0,9); +U+73F6(0);U+73F6(0,9);U+7445(3,8) +U+73F7(0);U+73F7(3); +U+73F8(0);U+73F8(0,9); +U+73F9(0);U+73F9(0); +U+73FA(0);U+73FA(0,9); +U+73FC(0);U+73FC(0,9); +U+73FD(0);U+73FD(3,9); +U+73FE(0);U+73FE(0,9);U+73B0(1,3,8) +U+73FF(0);U+73FF(0,9); +U+7400(0);U+7400(4,9); +U+7401(0);U+7401(0,9);U+7487(3,9),U+74BF(2,3,9) +U+7402(0);U+7402(0); +U+7403(0);U+7403(5,9);U+6BEC(2,3,8,9) +U+7404(0);U+7404(3,9); +U+7405(0);U+7405(5,9),U+746F(2,8,9);U+746F(2,8,9) +U+7406(0);U+7406(5,9); +U+7407(0);U+7407(0,9); +U+7408(0);U+7408(3,9); +U+7409(0);U+7409(5,9); +U+740A(0);U+740A(5,9); + +U+740B(0);U+740B(0,9); +U+740C(0);U+740C(0,9);U+9675(4,9) +U+740D(0);U+740D(0,9);U+7483(2,3,9) +U+740E(0);U+74A1(1,3,8,9);U+74A1(1,3,8,9) +U+740F(0);U+7489(1,3,8,9);U+7489(1,3,8,9) +U+7410(0);U+7463(1,3,8,9);U+7463(1,3,8,9) +U+7411(0);U+7411(0); +U+7412(0);U+7412(0); +U+7413(0);U+7413(0); +U+7414(0);U+7414(0); +U+7415(0);U+7415(0); +U+7416(0);U+7416(0,9);U+76CF(4),U+76DE(1,3,4,8,9),U+9186(4,9) +U+7417(0);U+7417(0); +U+7419(0);U+7419(0); +U+741A(0);U+741A(5,9); +U+741B(0);U+741B(5,9);U+8CDD(3,9) +U+741C(0);U+741C(0); +U+741D(0);U+741D(0,9);U+73C9(3),U+739F(3,5,8,9) +U+741E(0);U+741E(0); +U+741F(0);U+741F(0); +U+7420(0);U+7420(0,9); +U+7421(0);U+7421(0,9); +U+7422(0);U+7422(5,9); +U+7423(0);U+7423(0,9); +U+7424(0);U+7424(3,9); +U+7425(0);U+7425(5,9); +U+7426(0);U+7426(5,9); +U+7427(0);U+7427(0); +U+7428(0);U+7428(5,9); +U+7429(0);U+7429(0,9); +U+742A(0);U+742A(5,9); +U+742B(0);U+742B(3,9); +U+742C(0);U+742C(5,9); +U+742D(0);U+742D(0,9); +U+742E(0);U+742E(5,9); +U+742F(0);U+742F(3,9); +U+7430(0);U+7430(5,9); +U+7431(0);U+7431(0,9);U+96D5(2,3,8,9),U+5F6B(2,3,8,9),U+9D70(2,3,8,9) +U+7432(0);U+7432(3,9); +U+7433(0);U+7433(5,9); +U+7434(0);U+7434(5,9); +U+7435(0);U+7435(5,9); +U+7436(0);U+7436(5,9); +U+7437(0);U+7437(0); +U+7438(0);U+7438(0); +U+743A(0);U+743A(4,9); +U+743B(0);U+743B(0); +U+743C(0);U+74CA(1,3,8,9);U+749A(3,9),U+74CA(1,3,8,9) +U+743D(0);U+743D(0); +U+743F(0);U+743F(0,9);U+73F2(1,3,8) +U+7440(0);U+7440(0,9); +U+7441(0);U+7441(5,9); +U+7442(0);U+7442(0,9); +U+7443(0);U+7443(0); +U+7444(0);U+7444(3,9); +U+7445(0);U+73F6(3,8,9);U+73F6(3,8,9) +U+7446(0);U+7446(0,9); +U+7448(0);U+7448(3); +U+744A(0);U+744A(0,9); +U+744B(0);U+744B(0,9);U+73AE(1,3,8) +U+744C(0);U+744C(0); +U+744D(0);U+744D(0,9); +U+744E(0);U+744E(0,9); + +U+744F(0);U+744F(0,9); +U+7450(0);U+7450(0,9); +U+7451(0);U+7451(0,9); +U+7452(0);U+7452(0,9);U+739A(4,8),U+7497(4,8,9) +U+7453(0);U+7453(0); +U+7454(0);U+7454(0,9); +U+7455(0);U+7455(5,9); +U+7456(0);U+7456(0); +U+7457(0);U+7457(5,9); +U+7459(0);U+7459(5,9);U+78AF(3,8) +U+745A(0);U+745A(5,9); +U+745B(0);U+745B(5,9); +U+745C(0);U+745C(5,9); +U+745D(0);U+745D(0); +U+745E(0);U+745E(5,9); +U+745F(0);U+745F(5,9); +U+7461(0);U+7461(0); +U+7462(0);U+7462(0,9); +U+7463(0);U+7463(0,9);U+7410(1,3,8) +U+7464(0);U+7464(0,9);U+7476(4,8) +U+7465(0);U+7465(0); +U+7466(0);U+7466(0); +U+7467(0);U+7467(0,9); +U+7468(0);U+7468(0); +U+7469(0);U+7469(0,9);U+83B9(1,3,8) +U+746A(0);U+746A(0,9);U+739B(1,3,8) +U+746B(0);U+746B(0); +U+746C(0);U+746C(3); +U+746D(0);U+746D(5,9); +U+746E(0);U+746E(0,9); +U+746F(0);U+746F(0,9);U+7405(2,8,9) +U+7470(0);U+7470(5,9); +U+7471(0);U+7471(4,9); +U+7472(0);U+7472(0,9);U+73B1(1,3,8) +U+7473(0);U+7473(3,9); +U+7474(0);U+7474(0); +U+7475(0);U+7475(0,9); +U+7476(0);U+7464(4,8,9);U+7464(4,8,9) +U+7477(0);U+74A6(1,3,8,9);U+74A6(1,3,8,9) +U+7478(0);U+74B8(4,8,9);U+74B8(4,8,9) +U+7479(0);U+7479(0,9); +U+747A(0);U+747A(0); +U+747C(0);U+747C(0,9); +U+747D(0);U+747D(0,9); +U+747E(0);U+747E(5,9); +U+747F(0);U+747F(3,9); +U+7480(0);U+7480(5,9); +U+7481(0);U+7481(5,9); +U+7482(0);U+7482(0); +U+7483(0);U+7483(5,9);U+740D(2,3,9) +U+7485(0);U+7485(0,9); +U+7486(0);U+7486(0,9); +U+7487(0);U+7487(5,9),U+74BF(2,3,9);U+7401(3,9),U+74BF(2,3,9) +U+7488(0);U+7488(0,9); +U+7489(0);U+7489(0,9);U+740F(1,3,8) +U+748A(0);U+748A(3,9); +U+748B(0);U+748B(5,9); +U+748C(0);U+748C(0); +U+748D(0);U+748D(0); +U+748E(0);U+74D4(1,3,8,9);U+74D4(1,3,8,9) +U+748F(0);U+748F(0); +U+7490(0);U+7490(5,9); +U+7491(0);U+7491(0); + +U+7492(0);U+7492(0,9); +U+7493(0);U+7493(3); +U+7494(0);U+7494(0,9); +U+7495(0);U+7495(0,9); +U+7497(0);U+7497(0,9);U+739A(4),U+7452(4,8,9) +U+7498(0);U+7498(0,9); +U+7499(0);U+7499(0); +U+749A(0);U+749A(0,9);U+743C(3),U+74CA(1,3,8,9) +U+749B(0);U+749B(0); +U+749C(0);U+749C(5,9); +U+749E(0);U+749E(5,9); +U+749F(0);U+749F(3,9); +U+74A0(0);U+74A0(0,9); +U+74A1(0);U+74A1(0,9);U+740E(1,3,8) +U+74A3(0);U+74A3(0,9);U+7391(1,3,8) +U+74A4(0);U+74A4(0); +U+74A5(0);U+74A5(0,9); +U+74A6(0);U+74A6(0,9);U+7477(1,3,8) +U+74A7(0);U+74A7(5,9); +U+74A8(0);U+74A8(5,9); +U+74A9(0);U+74A9(5,9); +U+74AA(0);U+74AA(3,9); +U+74AB(0);U+74AB(0,9);U+73F0(4,8) +U+74AC(0);U+74AC(0); +U+74AD(0);U+74AD(0,9); +U+74AE(0);U+74AE(0); +U+74AF(0);U+74AF(0,9); +U+74B0(0);U+74B0(0,9);U+73AF(1,3,8) +U+74B1(0);U+74B1(3,9); +U+74B2(0);U+74B2(0,9); +U+74B3(0);U+74B3(0); +U+74B4(0);U+74B4(0); +U+74B5(0);U+74B5(0,9);U+7399(4,8) +U+74B6(0);U+74B6(0,9); +U+74B7(0);U+74B7(3,9); +U+74B8(0);U+74B8(0,9);U+7478(4,8) +U+74B9(0);U+74B9(0); +U+74BA(0);U+74BA(5,9); +U+74BB(0);U+74BB(0,9); +U+74BC(0);U+74BC(0); +U+74BD(0);U+74BD(0,9);U+73BA(1,3,8) +U+74BE(0);U+74BE(0,9); +U+74BF(0);U+74BF(3,9);U+7487(2,3,9),U+7401(0,2,3,9) +U+74C0(0);U+74C0(0,9); +U+74C1(0);U+74C1(0,9); +U+74C2(0);U+74C2(0,9); +U+74C3(0);U+74C3(0,9); +U+74C4(0);U+74C4(0); +U+74C5(0);U+74C5(3,9); +U+74C6(0);U+74C6(0); +U+74CA(0);U+74CA(0,9);U+743C(1,3,8),U+749A(1,3,8,9) +U+74CB(0);U+74CB(0,9); +U+74CD(0);U+74CD(0); +U+74CE(0);U+74CE(0); +U+74CF(0);U+74CF(0,9);U+73D1(1,3,8) +U+74D0(0);U+74D0(0); +U+74D1(0);U+74D1(0); +U+74D2(0);U+74DA(1,3,8,9);U+74DA(1,3,8,9) +U+74D3(0);U+74D3(0); +U+74D4(0);U+74D4(0,9);U+748E(1,3,8) +U+74D5(0);U+74D5(0,9); +U+74D6(0);U+74D6(0,9); +U+74D7(0);U+74D7(0,9); + +U+74D8(0);U+74D8(0,9); +U+74D9(0);U+74D9(0,9); +U+74DA(0);U+74DA(0,9);U+74D2(1,3,8) +U+74DB(0);U+74DB(0,9); +U+74DC(0);U+74DC(5,9); +U+74DD(0);U+74DD(3,9); +U+74DE(0);U+74DE(5,9); +U+74DF(0);U+74DF(0,9); +U+74E0(0);U+74E0(5,9); +U+74E1(0);U+74E1(0,9);U+6267(3),U+57F7(0,1,3,8,9) +U+74E2(0);U+74E2(5,9); +U+74E3(0);U+74E3(5,9); +U+74E4(0);U+74E4(5,9); +U+74E5(0);U+74E5(0,9); +U+74E6(0);U+74E6(5,9); +U+74E7(0);U+74E7(0); +U+74E8(0);U+74E8(0,9); +U+74E9(0);U+74E9(0,9); +U+74EA(0);U+74EA(0); +U+74EC(0);U+74EC(0,9); +U+74ED(0);U+74ED(0); +U+74EE(0);U+7515(2,4,9);U+7515(2,4,9),U+7F4B(2,3,9) +U+74EF(0);U+750C(1,3,8,9);U+750C(1,3,8,9) +U+74F0(0);U+74F0(0); +U+74F1(0);U+74F1(0); +U+74F2(0);U+74F2(0); +U+74F3(0);U+74F3(0); +U+74F4(0);U+74F4(5,9); +U+74F5(0);U+74F5(3,9); +U+74F6(0);U+74F6(5,9);U+7501(3,8),U+7F3E(2,8,9) +U+74F7(0);U+74F7(5,9);U+7506(3,8) +U+74F8(0);U+74F8(0); +U+74F9(0);U+74F9(0); +U+74FA(0);U+74FA(0); +U+74FB(0);U+74FB(0,9); +U+74FC(0);U+74FC(0); +U+74FD(0);U+74FD(0,9); +U+74FE(0);U+74FE(0,9); +U+74FF(0);U+74FF(5,9); +U+7500(0);U+7500(0,9); +U+7501(0);U+74F6(3,8,9);U+74F6(3,8,9),U+7F3E(2,3,8,9) +U+7502(0);U+7502(0,9); +U+7503(0);U+7503(0,9); +U+7504(0);U+7504(5,9); +U+7505(0);U+7505(0); +U+7506(0);U+74F7(3,8,9);U+74F7(3,8,9) +U+7507(0);U+7507(0,9);U+7F42(3),U+7516(2,3,9),U+7F43(3,9),U+7F4C(1,3,8,9) +U+7508(0);U+7508(0,9); +U+7509(0);U+7509(0); +U+750A(0);U+750A(0); +U+750B(0);U+750B(0,9); +U+750C(0);U+750C(0,9);U+74EF(1,3,8) +U+750D(0);U+750D(5,9); +U+750F(0);U+750F(5,9); +U+7510(0);U+7510(0,9); +U+7511(0);U+7511(5,9); +U+7512(0);U+7512(3,9); +U+7513(0);U+7513(5,9); +U+7514(0);U+7514(3,9); +U+7515(0);U+7515(0,9);U+74EE(2,4,9),U+7F4B(2,3,4,9) +U+7516(0);U+7516(0,9);U+7F42(2,3),U+7507(0,2,3,9),U+7F43(2,3,9),U+7F4C(1,2,3,8,9) +U+7517(0);U+7517(0,9); +U+7518(0);U+7518(5,9); + +U+7519(0);U+7519(5); +U+751A(0);U+751A(5,9); +U+751B(0);U+751C(3,8,9);U+751C(3,8,9) +U+751C(0);U+751C(5,9);U+751B(3,8) +U+751D(0);U+751D(0,9); +U+751E(0);U+5617(2,3,8,9);U+5617(2,3,8,9),U+5C1D(4),U+5690(1,2,3,4,8,9) +U+751F(0);U+751F(5,9); +U+7521(0);U+7521(0,9); +U+7522(0);U+7522(0,9);U+4EA7(4,8),U+7523(8) +U+7523(0);U+7522(8,9);U+4EA7(1,3,8),U+7522(8,9) +U+7524(0);U+7524(0); +U+7525(0);U+7525(5,9); +U+7526(0);U+7526(0,9);U+82CF(4),U+56CC(0,1,3,4,9),U+8607(1,3,4,8,9),U+8613(1,3,4) +U+7527(0);U+7527(0); +U+7528(0);U+7528(5,9); +U+7529(0);U+7529(5,9); +U+752A(0);U+752A(0,9); +U+752B(0);U+752B(5,9); +U+752C(0);U+752C(5,9); +U+752D(0);U+752D(5,9); +U+752E(0);U+752E(0,9); +U+752F(0);U+752F(5,9); +U+7530(0);U+7530(5,9); +U+7531(0);U+7531(5,9); +U+7532(0);U+7532(5,9); +U+7533(0);U+7533(5,9); +U+7535(0);U+96FB(1,3,8,9);U+96FB(1,3,8,9) +U+7536(0);U+7536(0); +U+7537(0);U+7537(5,9); +U+7538(0);U+7538(5,9); +U+7539(0);U+7539(3,9); +U+753A(0);U+753A(5,9);U+5722(4,9) +U+753B(0);U+756B(1,3,8,9);U+756B(1,3,8,9),U+7575(3) +U+753C(0);U+753C(0); +U+753D(0);U+753D(0,9);U+754E(3,9) +U+753E(0);U+753E(5,9); +U+753F(0);U+753F(0,9);U+6C13(4,9) +U+7540(0);U+7540(5,9); +U+7542(0);U+7542(0); +U+7543(0);U+7543(0); +U+7544(0);U+7559(4,8,9);U+7559(4,8,9) +U+7545(0);U+66A2(1,3,8,9);U+66A2(1,3,8,9) +U+7546(0);U+755D(2,3,8,9);U+4EA9(4),U+755D(2,3,8,9),U+756E(4) +U+7547(0);U+7547(0,9); +U+7548(0);U+7548(5,9); +U+7549(0);U+7549(0); +U+754B(0);U+754B(5,9); +U+754C(0);U+754C(5,9);U+583A(3,8),U+754D(3,8) +U+754D(0);U+754C(3,8,9);U+754C(3,8,9),U+583A(0,3,8) +U+754E(0);U+754E(5,9);U+753D(3,9) +U+754F(0);U+754F(5,9);U+6104(4,9) +U+7550(0);U+7550(0); +U+7551(0);U+7551(0); +U+7553(0);U+7553(0); +U+7554(0);U+7554(5,9); +U+7556(0);U+7556(0); +U+7557(0);U+7557(0); +U+7558(0);U+7558(0); +U+7559(0);U+7559(5,9);U+7544(4,8) +U+755A(0);U+755A(5,9); +U+755B(0);U+755B(5,9); +U+755C(0);U+755C(5,9); +U+755D(0);U+755D(0,9);U+4EA9(1,3,8),U+7546(2,3,8),U+756E(2,3,8) + +U+755F(0);U+755F(0,9); +U+7560(0);U+7560(0); +U+7562(0);U+7562(0,9);U+6BD5(1,3,8),U+7F7C(1,3,8,9),U+93CE(1,3,8,9) +U+7563(0);U+7563(0,9);U+7B54(3,9),U+8345(3,4,8,9) +U+7564(0);U+7564(0,9); +U+7565(0);U+7565(5,9);U+7567(2,8) +U+7566(0);U+7566(5,9); +U+7567(0);U+7565(2,8,9);U+7565(2,8,9) +U+7568(0);U+7568(0); +U+7569(0);U+7569(0); +U+756A(0);U+756A(5,9);U+8E6F(3,8,9),U+7C75(3,8,9) +U+756B(0);U+756B(0,9);U+753B(1,3,8),U+7575(3,8) +U+756C(0);U+756C(4,9);U+756D(3,8),U+7572(4,8) +U+756D(0);U+756C(3,8,9);U+756C(3,8,9),U+7572(7) +U+756E(0);U+755D(2,3,8,9);U+4EA9(4),U+755D(2,3,8,9),U+7546(4) +U+756F(0);U+756F(0,9); +U+7570(0);U+7570(0,9);U+5F02(2,3,8,9) +U+7572(0);U+756C(4,8,9);U+756C(4,8,9),U+756D(7) +U+7574(0);U+7587(1,3,8,9);U+7587(1,3,8,9) +U+7575(0);U+756B(3,8,9);U+753B(3),U+756B(3,8,9) +U+7576(0);U+7576(0,9);U+5679(3,4,9),U+5F53(1,3,8) +U+7577(0);U+7577(0,9); +U+7578(0);U+7578(5,9); +U+7579(0);U+7579(5,9); +U+757C(0);U+757C(0); +U+757D(0);U+757D(0,9);U+7583(3),U+58A5(0,3,9) +U+757E(0);U+757E(0,9); +U+757F(0);U+757F(5,9); +U+7580(0);U+7580(0,9); +U+7581(0);U+7581(0); +U+7582(0);U+7582(0); +U+7583(0);U+7583(5);U+58A5(3,9),U+757D(3,9) +U+7584(0);U+7584(0,9); +U+7586(0);U+7586(5,9); +U+7587(0);U+7587(0,9);U+7574(1,3,8) +U+7588(0);U+7588(0); +U+7589(0);U+758A(3,8,9);U+53E0(2,3),U+758A(3,8,9),U+66E1(2),U+8FED(2,4,9) +U+758A(0);U+758A(0,9);U+53E0(2,3,8),U+66E1(3,8),U+7589(3,8),U+8FED(3,4,8,9) +U+758B(0);U+758B(5,9);U+5339(2,3,8,9) +U+758C(0);U+758C(0,9); +U+758D(0);U+758D(0); +U+758F(0);U+758F(5,9);U+8E08(4,8) +U+7590(0);U+7590(0,9); +U+7591(0);U+7591(5,9); +U+7592(0);U+7592(5); +U+7593(0);U+7593(0); +U+7594(0);U+7594(5,9); +U+7595(0);U+7595(0,9); +U+7596(0);U+7664(1,3,8,9);U+7664(1,3,8,9) +U+7597(0);U+7642(1,3,8,9);U+7642(1,3,8,9) +U+7598(0);U+7598(0,9);U+809B(2,3,9) +U+7599(0);U+7599(5,9); +U+759A(0);U+759A(5,9); +U+759B(0);U+759B(0); +U+759C(0);U+759C(0); +U+759D(0);U+759D(5,9); +U+759E(0);U+759E(0); +U+759F(0);U+7627(1,3,8,9);U+7627(1,3,8,9) +U+75A0(0);U+7658(1,3,8,9);U+7658(1,3,8,9) +U+75A1(0);U+760D(1,3,8,9);U+760D(1,3,8,9) +U+75A2(0);U+75A2(3,9); +U+75A3(0);U+75A3(5,9); +U+75A4(0);U+75A4(5,9); + +U+75A5(0);U+75A5(5,9); +U+75A6(0);U+75A6(0); +U+75A7(0);U+75A7(0,9); +U+75A8(0);U+75A8(0); +U+75AA(0);U+75AA(0,9);U+75F9(3,9),U+75FA(2,3,9) +U+75AB(0);U+75AB(5,9); +U+75AC(0);U+7667(1,3,8);U+7667(1,3,8) +U+75AD(0);U+7632(4,8,9);U+7632(4,8,9) +U+75AE(0);U+7621(1,3,8,9);U+7621(1,3,8,9) +U+75AF(0);U+760B(1,3,8,9);U+760B(1,3,8,9) +U+75B0(0);U+75B0(5,9); +U+75B1(0);U+75B1(5),U+76B0(2,9);U+76B0(2,9) +U+75B2(0);U+75B2(5,9); +U+75B3(0);U+75B3(5,9); +U+75B4(0);U+75B4(5); +U+75B5(0);U+75B5(5,9); +U+75B6(0);U+75B6(0,9); +U+75B8(0);U+75B8(5,9); +U+75B9(0);U+75B9(5,9); +U+75BA(0);U+75BA(0,9); +U+75BB(0);U+75BB(0,9); +U+75BC(0);U+75BC(5,9); +U+75BD(0);U+75BD(5,9); +U+75BE(0);U+75BE(5,9); +U+75BF(0);U+75BF(0,9);U+75F1(2,9) +U+75C0(0);U+75C0(0,9); +U+75C1(0);U+75C1(0,9); +U+75C2(0);U+75C2(5,9); +U+75C3(0);U+75C3(5); +U+75C4(0);U+75C4(5,9); +U+75C5(0);U+75C5(5,9); +U+75C6(0);U+75C6(0); +U+75C7(0);U+75C7(1,3,9),U+7665(1,3,4,8,9);U+7665(1,3,4,8,9) +U+75C8(0);U+7670(1,3,8,9);U+7670(1,3,8,9) +U+75C9(0);U+75D9(1,3,8,9);U+75D9(1,3,8,9) +U+75CA(0);U+75CA(5,9); +U+75CB(0);U+75CB(0,9); +U+75CC(0);U+75CC(0,9);U+606B(3,9) +U+75CD(0);U+75CD(5,9); +U+75CE(0);U+75CE(0,9); +U+75CF(0);U+75CF(0,9); +U+75D0(0);U+75D0(0,9);U+86D4(2,3,9),U+8698(2,3,9),U+8716(2,3,8) +U+75D1(0);U+75D1(0,9); +U+75D2(0);U+7662(1,3,8,9);U+7662(1,3,8,9) +U+75D3(0);U+75D3(0); +U+75D4(0);U+75D4(5,9); +U+75D5(0);U+75D5(5,9); +U+75D6(0);U+555E(4,9);U+54D1(7),U+5516(7),U+555E(4,9),U+7602(4,8) +U+75D7(0);U+75D7(0,9); +U+75D8(0);U+75D8(5,9); +U+75D9(0);U+75D9(0,9);U+75C9(1,3,8) +U+75DA(0);U+75DA(0,9); +U+75DB(0);U+75DB(5,9); +U+75DD(0);U+75DD(0,9); +U+75DE(0);U+75DE(5,9); +U+75DF(0);U+75DF(0,9); +U+75E0(0);U+75E0(0,9); +U+75E1(0);U+75E1(0,9); +U+75E2(0);U+75E2(5,9);U+9B01(4,9) +U+75E3(0);U+75E3(5,9); +U+75E4(0);U+75E4(5,9); +U+75E5(0);U+75E5(0); +U+75E6(0);U+75E6(5,9); + +U+75E7(0);U+75E7(5,9); +U+75E8(0);U+7646(1,3,8,9);U+7646(1,3,8,9) +U+75EA(0);U+7613(4,8,9);U+7613(4,8,9) +U+75EB(0);U+7647(1,3,8,9);U+7647(1,3,8,9) +U+75EC(0);U+75EC(0); +U+75ED(0);U+75ED(0,9); +U+75EF(0);U+75EF(0,9); +U+75F0(0);U+75F0(5,9); +U+75F1(0);U+75F1(5,9);U+75BF(2,9) +U+75F2(0);U+75F2(0,9);U+9EBB(3,9),U+75F3(3,4,9),U+8534(2,3),U+6DCB(2,3,4,5,9) +U+75F3(0);U+75F3(0,9);U+6DCB(2,3,9),U+9EBB(4,9),U+75F2(0,3,4,9),U+8534(2,3,4) +U+75F4(0);U+75F4(5,9),U+7661(2,3,8,9);U+7661(2,3,8,9) +U+75F5(0);U+75F5(0,9);U+60B8(3,4,9) +U+75F6(0);U+75F6(0,9); +U+75F7(0);U+75F7(0,9); +U+75F8(0);U+75F8(0,9); +U+75F9(0);U+75F9(5,9);U+75AA(3,9),U+75FA(2,9) +U+75FA(0);U+75FA(0,9);U+75F9(2,9),U+75AA(0,2,3,9) +U+75FB(0);U+75FB(0,9); +U+75FC(0);U+75FC(5,9); +U+75FD(0);U+75FD(0,9); +U+75FE(0);U+75FE(0,9); +U+75FF(0);U+75FF(5,9); +U+7600(0);U+7600(5,9); +U+7601(0);U+7601(5,9); +U+7602(0);U+555E(3,9);U+54D1(7),U+5516(7),U+555E(3,9),U+75D6(4,8) +U+7603(0);U+7603(5,9); +U+7604(0);U+7604(0); +U+7605(0);U+7649(1,3,8,9);U+7649(1,3,8,9) +U+7606(0);U+762E(1,3);U+762E(1,3) +U+7607(0);U+7607(0); +U+7608(0);U+7608(0,9); +U+7609(0);U+7609(0,9);U+6108(2,3,9),U+7652(2,3,8,9) +U+760A(0);U+760A(5,9); +U+760B(0);U+760B(0,9);U+75AF(1,3,8) +U+760C(0);U+760C(5,9);U+9B0E(4,9) +U+760D(0);U+760D(0,9);U+75A1(1,3,8) +U+760E(0);U+760E(0); +U+760F(0);U+760F(0,9); +U+7610(0);U+7610(5,9); +U+7611(0);U+7611(0,9);U+8717(4),U+8778(1,3,4,8,9) +U+7612(0);U+7612(0); +U+7613(0);U+7613(0,9);U+75EA(4,8) +U+7614(0);U+7614(0,9);U+82E6(3,9) +U+7615(0);U+7615(5,9); +U+7616(0);U+7616(0,9);U+5591(2,9),U+567E(2,3,9) +U+7617(0);U+761E(1,3,8,9);U+761E(1,3,8,9) +U+7618(0);U+763A(3,8,9);U+763A(3,8,9),U+763B(1,3,8) +U+7619(0);U+7619(5,9); +U+761A(0);U+761A(3,9); +U+761B(0);U+761B(5,9); +U+761C(0);U+761C(0,9); +U+761D(0);U+761D(3,9); +U+761E(0);U+761E(0,9);U+7617(1,3,8) +U+761F(0);U+761F(5,9); +U+7620(0);U+7620(5,9);U+818C(3,9) +U+7621(0);U+7621(0,9);U+75AE(1,3,8) +U+7622(0);U+7622(5,9); +U+7623(0);U+7623(0,9);U+574F(4,9),U+576F(4,9),U+58CA(4),U+58DE(1,3,4,8,9) +U+7624(0);U+7624(5,9); +U+7625(0);U+7625(5,9); +U+7626(0);U+7626(5,9); +U+7627(0);U+7627(0,9);U+759F(1,3,8) + +U+7628(0);U+7628(0,9);U+766B(3),U+7672(1,3,8,9) +U+7629(0);U+7629(5,9); +U+762A(0);U+765F(1,3,8,9);U+765F(1,3,8,9) +U+762B(0);U+7671(1,3,8,9);U+7671(1,3,8,9) +U+762D(0);U+762D(5,9); +U+762E(0);U+762E(0);U+7606(1,3) +U+762F(0);U+762F(0,9); +U+7630(0);U+7630(5,9); +U+7631(0);U+7631(0,9); +U+7632(0);U+7632(0,9);U+75AD(4,8) +U+7633(0);U+7633(5,9); +U+7634(0);U+7634(5,9); +U+7635(0);U+7635(5,9); +U+7636(0);U+7636(0); +U+7637(0);U+7637(0); +U+7638(0);U+7638(5,9); +U+7639(0);U+7639(0); +U+763A(0);U+763A(0,9);U+7618(3,8),U+763B(3) +U+763B(0);U+763A(3,9);U+7618(1,3,8),U+763A(3,9) +U+763C(0);U+763C(5,9); +U+763D(0);U+763D(0,9);U+52E4(3,9),U+61C3(2,3,8,9) +U+763E(0);U+766E(1,3,8,9);U+766E(1,3,8,9) +U+763F(0);U+766D(1,3,8,9);U+766D(1,3,8,9) +U+7640(0);U+7640(5); +U+7641(0);U+7641(0); +U+7642(0);U+7642(0,9);U+7597(1,3,8) +U+7643(0);U+7643(5,9); +U+7646(0);U+7646(0,9);U+75E8(1,3,8) +U+7647(0);U+7647(0,9);U+75EB(1,3,8) +U+7648(0);U+7648(0,9);U+5E9F(2),U+5EC3(2,4),U+5EE2(1,2,3,8,9) +U+7649(0);U+7649(0,9);U+7605(1,3,8) +U+764A(0);U+764A(0); +U+764B(0);U+764B(0); +U+764C(0);U+764C(5,9); +U+764D(0);U+764D(5); +U+764F(0);U+764F(0); +U+7650(0);U+7650(0,9); +U+7652(0);U+7652(0,9);U+6108(2,8,9),U+7609(2,3,8,9) +U+7653(0);U+7653(0,9); +U+7654(0);U+7654(5); +U+7656(0);U+7656(5,9); +U+7657(0);U+7657(0,9); +U+7658(0);U+7658(0,9);U+75A0(1,3,8) +U+7659(0);U+7659(0,9); +U+765A(0);U+765A(0,9); +U+765B(0);U+765B(0);U+765D(4,8) +U+765C(0);U+765C(5,9); +U+765D(0);U+765B(4,8);U+765B(4,8) +U+765E(0);U+7669(1,3,8,9);U+7669(1,3,8,9) +U+765F(0);U+765F(0,9);U+762A(1,3,8) +U+7660(0);U+7660(0,9); +U+7661(0);U+7661(0,9);U+75F4(2,3,8,9) +U+7662(0);U+7662(0,9);U+75D2(1,3,8,9) +U+7663(0);U+766C(1,3,8,9);U+766C(1,3,8,9) +U+7664(0);U+7664(0,9);U+7596(1,3,8) +U+7665(0);U+7665(0,9);U+75C7(1,3,8,9) +U+7666(0);U+7666(0); +U+7667(0);U+7667(0);U+75AC(1,3,8) +U+7668(0);U+970D(7,8,9);U+970D(7,8,9) +U+7669(0);U+7669(0,9);U+765E(1,3,8) +U+766A(0);U+766A(0,9); +U+766B(0);U+7672(1,3,8,9);U+7628(3,9),U+7672(1,3,8,9) +U+766C(0);U+766C(0,9);U+7663(1,3,8) + +U+766D(0);U+766D(0,9);U+763F(1,3,8) +U+766E(0);U+766E(0,9);U+763E(1,3,8) +U+766F(0);U+766F(5); +U+7670(0);U+7670(0,9);U+75C8(1,3,8) +U+7671(0);U+7671(0,9);U+762B(1,3,8) +U+7672(0);U+7672(0,9);U+766B(1,3,8),U+7628(0,1,3,8,9) +U+7674(0);U+7674(0); +U+7675(0);U+7675(0,9); +U+7676(0);U+7676(0); +U+7677(0);U+7677(0); +U+7678(0);U+7678(5,9); +U+7679(0);U+7679(3,9); +U+767B(0);U+767B(5,9);U+8C4B(4,9) +U+767C(0);U+767C(0,9);U+53D1(1,3,8),U+5F42(4,8),U+9AEA(1,3,4,8),U+9AEE(1,3,8,9) +U+767D(0);U+767D(5,9); +U+767E(0);U+767E(5,9); +U+767F(0);U+767F(0,9); +U+7680(0);U+7680(0); +U+7681(0);U+7681(0,9);U+7682(2,8,9) +U+7682(0);U+7682(5,9);U+7681(2,8,9) +U+7683(0);U+8C8C(3,8,9);U+8C8C(3,8,9) +U+7684(0);U+7684(5,9); +U+7685(0);U+7685(0); +U+7686(0);U+7686(5,9); +U+7687(0);U+7687(5,9); +U+7688(0);U+7688(5,9);U+6B78(3,8,9),U+5E30(0,3,8),U+5F52(3,8) +U+7689(0);U+7689(0,9); +U+768A(0);U+768A(0,9); +U+768B(0);U+768B(5,9);U+7690(2,3,8) +U+768C(0);U+768C(0); +U+768E(0);U+768E(5,9);U+76A6(3,9) +U+768F(0);U+768F(0,9); +U+7690(0);U+768B(2,3,8,9);U+768B(2,3,8,9) +U+7691(0);U+769A(1,3,8,9);U+769A(1,3,8,9) +U+7692(0);U+7692(0,9); +U+7693(0);U+7693(5,9);U+66A0(2,3,9),U+769C(2,3,9) +U+7694(0);U+7694(0); +U+7695(0);U+7695(0,9); +U+7696(0);U+7696(5,9);U+6665(3,9) +U+7697(0);U+7697(0); +U+7698(0);U+7698(0); +U+7699(0);U+7699(5,9); +U+769A(0);U+769A(0,9);U+7691(1,3,8) +U+769B(0);U+769B(0,9); +U+769C(0);U+769C(0,9);U+7693(2,3,9),U+66A0(0,2,3,9) +U+769D(0);U+769D(0,9); +U+769E(0);U+769E(3,9); +U+769F(0);U+769F(0); +U+76A0(0);U+76A0(0); +U+76A3(0);U+76A3(0); +U+76A4(0);U+76A4(5,9); +U+76A6(0);U+76A6(0,9);U+768E(3,9) +U+76A7(0);U+76A7(0); +U+76A9(0);U+76A9(0); +U+76AA(0);U+76AA(0,9); +U+76AB(0);U+76AB(0,9); +U+76AC(0);U+76AC(0); +U+76AD(0);U+76AD(0,9); +U+76AE(0);U+76AE(5,9); +U+76AF(0);U+76AF(0,9); +U+76B0(0);U+76B0(0,9);U+75B1(2) +U+76B1(0);U+76BA(1,3,8,9);U+76BA(1,3,8,9) +U+76B2(0);U+76B8(1,3,8,9);U+76B8(1,3,8,9) + +U+76B4(0);U+76B4(5,9); +U+76B5(0);U+76B5(0,9); +U+76B7(0);U+9F13(2,3,8,9);U+9F13(2,3,8,9),U+76BC(2,3,7,8) +U+76B8(0);U+76B8(0,9);U+76B2(1,3,8) +U+76BA(0);U+76BA(0,9);U+76B1(1,3,8) +U+76BB(0);U+76BB(4,9); +U+76BC(0);U+9F13(7,8,9);U+9F13(7,8,9),U+76B7(0,2,3,7,8) +U+76BD(0);U+76BD(0,9); +U+76BE(0);U+76BE(0,9); +U+76BF(0);U+76BF(5,9); +U+76C0(0);U+76C0(0); +U+76C2(0);U+76C2(5,9); +U+76C3(0);U+76C3(0,9);U+676F(2,3,8,9),U+686E(2,3,8,9) +U+76C4(0);U+76C4(0,9); +U+76C5(0);U+76C5(5,9);U+6C96(3,8,9),U+51B2(1,3,4,8),U+794C(3,4,8,9),U+885D(1,3,4,8,9),U+8876(3,4,8,9) + +U+76C6(0);U+76C6(5,9); +U+76C7(0);U+76CD(2,8,9);U+76CD(2,8,9) +U+76C8(0);U+76C8(5,9); +U+76C9(0);U+76C9(0,9); +U+76CA(0);U+76CA(5,9); +U+76CD(0);U+76CD(5,9);U+76C7(2,8) +U+76CE(0);U+76CE(5,9); +U+76CF(0);U+76DE(1,3,8,9);U+7416(4,9),U+76DE(1,3,8,9),U+9186(4,9) +U+76D0(0);U+9E7D(1,3,8,9);U+5869(3),U+9E7D(1,3,8,9) +U+76D1(0);U+76E3(1,3,8,9);U+76E3(1,3,8,9) +U+76D2(0);U+76D2(5,9); +U+76D3(0);U+76D3(0,9); +U+76D4(0);U+76D4(5,9); +U+76D5(0);U+76D5(0); +U+76D6(0);U+84CB(1,3,8,9);U+8462(3),U+84CB(1,3,8,9) +U+76D7(0);U+76DC(3,8,9);U+76DC(3,8,9) +U+76D8(0);U+76E4(1,3,8,9);U+6D00(3,9),U+76E4(1,3,8,9) +U+76DA(0);U+76DA(0,9); +U+76DB(0);U+76DB(5,9); +U+76DC(0);U+76DC(0,9);U+76D7(3,8) +U+76DD(0);U+76DD(0,9); +U+76DE(0);U+76DE(0,9);U+76CF(1,3,8),U+7416(0,1,3,4,8,9),U+9186(1,3,4,8,9) +U+76DF(0);U+76DF(5,9); +U+76E0(0);U+76E0(0); +U+76E1(0);U+76E1(0,9);U+5118(4,9),U+5C3D(1,3,8) +U+76E2(0);U+76E2(0); +U+76E3(0);U+76E3(0,9);U+76D1(1,3,8) +U+76E4(0);U+76E4(0,9);U+76D8(1,3,8),U+6D00(0,1,3,8,9) +U+76E5(0);U+76E5(5,9); +U+76E6(0);U+76E6(3,9); +U+76E7(0);U+76E7(0,9);U+5362(1,3,8) +U+76E8(0);U+76E8(0); +U+76E9(0);U+76E9(0,9); +U+76EA(0);U+76EA(3,9);U+8361(4),U+8569(2,3,9),U+6F52(0,3,4,9),U+862F(3,4) +U+76EC(0);U+76EC(0,9); +U+76ED(0);U+76ED(0,9);U+623E(4,9),U+623B(0,4,8) +U+76EE(0);U+76EE(5,9); +U+76EF(0);U+76EF(5,9); +U+76F0(0);U+76F0(0,9); +U+76F1(0);U+76F1(5,9); +U+76F2(0);U+76F2(5,9);U+76F3(3,9) +U+76F3(0);U+76F3(0,9);U+76F2(3,9) +U+76F4(0);U+76F4(5,9); +U+76F5(0);U+76F5(0,9); +U+76F6(0);U+76F6(0); +U+76F7(0);U+76F7(0,9); +U+76F8(0);U+76F8(5,9); + +U+76F9(0);U+76F9(5,9); +U+76FA(0);U+76FA(0,9); +U+76FB(0);U+76FB(0,9); +U+76FC(0);U+76FC(5,9); +U+76FD(0);U+76FD(0); +U+76FE(0);U+76FE(5,9); +U+76FF(0);U+76FF(3); +U+7701(0);U+7701(5,9); +U+7703(0);U+7703(0,9); +U+7704(0);U+7704(5,9); +U+7705(0);U+7705(0,9); +U+7706(0);U+7706(3); +U+7707(0);U+7707(5,9); +U+7708(0);U+7708(5,9); +U+7709(0);U+7709(5,9); +U+770A(0);U+770A(3,9); +U+770B(0);U+770B(5,9); +U+770C(0);U+770C(0); +U+770D(0);U+7798(1,3,8);U+7798(1,3,8) +U+770F(0);U+770F(0); +U+7710(0);U+7710(0,9); +U+7711(0);U+7711(0,9); +U+7712(0);U+7712(3,9); +U+7713(0);U+7713(0,9); +U+7714(0);U+7714(0); +U+7715(0);U+7715(0,9); +U+7716(0);U+7716(0); +U+7717(0);U+7717(0); +U+7718(0);U+614E(3,9);U+614E(3,9),U+613C(0,3,4,8),U+661A(2,3,4,8) +U+7719(0);U+7719(5,9); +U+771A(0);U+771A(5,9); +U+771B(0);U+771B(0,9); +U+771C(0);U+771C(0); +U+771D(0);U+771D(0,9); +U+771E(0);U+771F(3,8,9);U+771F(3,8,9) +U+771F(0);U+771F(5,9);U+771E(3,8) +U+7720(0);U+7720(5,9); +U+7722(0);U+7722(5,9); +U+7723(0);U+7723(3,9); +U+7725(0);U+7725(3,9); +U+7726(0);U+7726(5); +U+7727(0);U+7727(0,9); +U+7728(0);U+7728(5,9); +U+7729(0);U+7729(5,9); +U+772A(0);U+772A(0); +U+772C(0);U+77D3(4,8,9);U+77D3(4,8,9) +U+772D(0);U+772D(5,9); +U+772E(0);U+772E(0); +U+772F(0);U+772F(5,9);U+7787(2,3,9) +U+7730(0);U+7730(0); +U+7731(0);U+7731(0,9); +U+7732(0);U+7732(0,9); +U+7733(0);U+7733(0,9); +U+7734(0);U+7734(3,9); +U+7735(0);U+7735(5,9); +U+7736(0);U+7736(5,9); +U+7737(0);U+7737(5,9);U+7760(2,3,9) +U+7738(0);U+7738(5,9); +U+7739(0);U+7739(0,9); +U+773A(0);U+773A(5,9);U+899C(2,3,9) +U+773B(0);U+773B(0,9); +U+773C(0);U+773C(5,9); + +U+773D(0);U+773D(3,9); +U+773E(0);U+773E(0,9);U+4F17(4),U+8846(2,8) +U+7740(0);U+8457(4,8,9);U+8457(4,8,9) +U+7741(0);U+775C(4,8,9);U+775C(4,8,9) +U+7743(0);U+7743(5); +U+7744(0);U+7744(0,9); +U+7745(0);U+7745(0,9); +U+7746(0);U+7746(0,9); +U+7747(0);U+7747(5,9); +U+7748(0);U+7748(0); +U+7749(0);U+7749(0); +U+774A(0);U+774A(0,9); +U+774B(0);U+774B(0,9); +U+774C(0);U+774C(0,9); +U+774D(0);U+774D(0,9); +U+774E(0);U+774E(3,9); +U+774F(0);U+774F(0,9);U+56F0(1,8,9) +U+7750(0);U+775E(1,3,8,9);U+775E(1,3,8,9) +U+7751(0);U+77BC(1,3,8,9);U+77BC(1,3,8,9) +U+7752(0);U+7752(0,9); +U+7753(0);U+7753(0); +U+7754(0);U+7754(0,9); +U+7755(0);U+7755(0,9); +U+7756(0);U+7756(0,9); +U+7757(0);U+7757(0); +U+7758(0);U+7758(0); +U+7759(0);U+7759(0,9); +U+775A(0);U+775A(5,9); +U+775B(0);U+775B(5,9); +U+775C(0);U+775C(0,9);U+7741(4,8) +U+775D(0);U+775D(0); +U+775E(0);U+775E(0,9);U+7750(1,3,8) +U+775F(0);U+775F(3,9); +U+7760(0);U+7760(0,9);U+7737(2,3,9) +U+7761(0);U+7761(5,9); +U+7762(0);U+7762(5,9); +U+7763(0);U+7763(5,9); +U+7765(0);U+7765(5,9); +U+7766(0);U+7766(5,9); +U+7767(0);U+7767(0,9); +U+7768(0);U+7768(5,9); +U+7769(0);U+7769(0,9); +U+776A(0);U+776A(4,9);U+777E(3,4,9) +U+776B(0);U+776B(5,9); +U+776C(0);U+776C(5,9); +U+776D(0);U+776D(0,9); +U+776E(0);U+776E(0,9); +U+776F(0);U+776F(0,9); +U+7770(0);U+7770(0); +U+7771(0);U+7771(0); +U+7772(0);U+7772(0); +U+7773(0);U+7773(0); +U+7774(0);U+7774(0); +U+7775(0);U+7775(0); +U+7776(0);U+7776(0); +U+7777(0);U+7777(0); +U+7778(0);U+7778(0); +U+7779(0);U+7779(5,9); +U+777A(0);U+777A(0); +U+777B(0);U+777B(0); +U+777C(0);U+777C(3,9); +U+777D(0);U+777D(5,9); +U+777E(0);U+777E(5,9);U+776A(3,4,9) + +U+777F(0);U+777F(5,9);U+53E1(2,3,8,9) +U+7780(0);U+7780(5,9); +U+7781(0);U+7781(3,9); +U+7782(0);U+7782(3,9); +U+7783(0);U+7783(0,9); +U+7784(0);U+7784(5,9); +U+7785(0);U+7785(5,9);U+5062(7,9) +U+7786(0);U+77B6(4,8,9);U+77B6(4,8,9) +U+7787(0);U+7787(0,9);U+772F(2,3,9) +U+7788(0);U+7788(0,9); +U+7789(0);U+7789(0,9); +U+778A(0);U+778A(0); +U+778B(0);U+778B(0,9); +U+778C(0);U+778C(5,9); +U+778D(0);U+778D(5,9); +U+778E(0);U+778E(5,9); +U+778F(0);U+778F(3,9); +U+7790(0);U+7790(0); +U+7791(0);U+7791(5,9); +U+7792(0);U+779E(1,3,8,9);U+779E(1,3,8,9) +U+7793(0);U+7793(0); +U+7794(0);U+7794(0); +U+7795(0);U+7795(0,9); +U+7797(0);U+7797(0,9); +U+7798(0);U+7798(0);U+770D(1,3,8) +U+7799(0);U+7799(0,9); +U+779A(0);U+779A(0,9);U+77AC(3,9) +U+779B(0);U+779B(0,9); +U+779C(0);U+779C(0,9);U+4056(1,3) +U+779D(0);U+779D(0,9); +U+779E(0);U+779E(0,9);U+7792(1,3,8) +U+779F(0);U+779F(5,9); +U+77A0(0);U+77A0(5,9); +U+77A1(0);U+77A1(0,9); +U+77A2(0);U+77A2(5,9); +U+77A3(0);U+77A3(0,9); +U+77A5(0);U+77A5(5,9);U+8995(3,9) +U+77A6(0);U+77A6(0); +U+77A7(0);U+77A7(5,9); +U+77A8(0);U+77A8(0,9); +U+77A9(0);U+77DA(1,3,8,9);U+77DA(1,3,8,9) +U+77AA(0);U+77AA(5,9); +U+77AB(0);U+77AB(0,9); +U+77AC(0);U+77AC(5,9);U+779A(3,9) +U+77AD(0);U+77AD(0,9);U+4E86(1,3,8,9),U+66B8(1,3,4,7,8,9) +U+77AE(0);U+77AE(0); +U+77AF(0);U+77AF(3); +U+77B0(0);U+77B0(5,9);U+77D9(2,3,9) +U+77B1(0);U+77B1(0,9); +U+77B2(0);U+77B2(0,9); +U+77B3(0);U+77B3(5,9); +U+77B4(0);U+77B4(0,9); +U+77B5(0);U+77B5(5,9); +U+77B6(0);U+77B6(0,9);U+7786(4,8) +U+77B7(0);U+77B7(0,9); +U+77B8(0);U+77B8(0); +U+77B9(0);U+77B9(0); +U+77BA(0);U+77BA(0,9); +U+77BB(0);U+77BB(5,9); +U+77BC(0);U+77BC(0,9);U+7751(1,3,8) +U+77BD(0);U+77BD(5,9); +U+77BF(0);U+77BF(5,9); +U+77C0(0);U+77C0(0); + +U+77C2(0);U+77C2(0,9); +U+77C3(0);U+77C3(0); +U+77C4(0);U+77C4(0,9); +U+77C5(0);U+77C5(0); +U+77C6(0);U+77C6(0); +U+77C7(0);U+77C7(0,9);U+8499(1,8,9),U+61DE(0,1,4,8,9),U+6FDB(1,3,4,8,9) +U+77C8(0);U+77CF(8,9);U+77CF(8,9) +U+77C9(0);U+77C9(0,9); +U+77CA(0);U+77CA(0,9); +U+77CB(0);U+77CB(0); +U+77CC(0);U+77CC(0,9); +U+77CD(0);U+77CD(5,9); +U+77CE(0);U+77CE(0,9); +U+77CF(0);U+77CF(0,9);U+77C8(8) +U+77D0(0);U+77D0(0,9); +U+77D1(0);U+77D1(3); +U+77D3(0);U+77D3(0,9);U+772C(4,8) +U+77D4(0);U+77D4(0,9); +U+77D5(0);U+77D5(0,9); +U+77D6(0);U+77D6(0); +U+77D7(0);U+77D7(5,9); +U+77D8(0);U+77D8(0,9); +U+77D9(0);U+77D9(0,9);U+77B0(2,3,9) +U+77DA(0);U+77DA(0,9);U+77A9(1,3,8) +U+77DB(0);U+77DB(5,9); +U+77DC(0);U+77DC(5,9); +U+77DE(0);U+77DE(3,9); +U+77DF(0);U+77DF(4);U+9399(4,9) +U+77E0(0);U+77E0(0,9); +U+77E1(0);U+77E1(0); +U+77E2(0);U+77E2(5,9);U+7B36(3,8) +U+77E3(0);U+77E3(5,9); +U+77E5(0);U+77E5(5,9); +U+77E7(0);U+77E7(5,9); +U+77E8(0);U+77E8(0,9); +U+77E9(0);U+77E9(5,9);U+6998(2,3,8) +U+77EA(0);U+77EA(0); +U+77EB(0);U+77EF(1,3,8,9);U+77EF(1,3,8,9) +U+77EC(0);U+77EC(5,9);U+9073(3,9) +U+77ED(0);U+77ED(5,9); +U+77EE(0);U+77EE(5,9); +U+77EF(0);U+77EF(0,9);U+77EB(1,3,8) +U+77F0(0);U+77F0(0,9); +U+77F1(0);U+77F1(0,9); +U+77F2(0);U+77F2(3,9); +U+77F3(0);U+77F3(5,9); +U+77F6(0);U+78EF(1,3,8,9);U+78EF(1,3,8,9) +U+77F7(0);U+77F7(0,9); +U+77F8(0);U+77F8(5,9); +U+77F9(0);U+77F9(0,9); +U+77FA(0);U+77FA(0,9); +U+77FB(0);U+77FB(0,9); +U+77FC(0);U+77FC(0,9); +U+77FD(0);U+77FD(5,9); +U+77FE(0);U+792C(1,3,8,9);U+792C(1,3,8,9) +U+77FF(0);U+7926(1,3,8,9);U+7926(1,3,8,9),U+945B(4) +U+7800(0);U+78AD(1,3,8,9);U+78AD(1,3,8,9) +U+7801(0);U+78BC(1,3,8,9);U+78BC(1,3,8,9) +U+7802(0);U+7802(5,9); +U+7803(0);U+7803(0,9); +U+7804(0);U+7804(0); +U+7805(0);U+7805(3,9); +U+7806(0);U+7806(0,9); + +U+7808(0);U+7808(0); +U+7809(0);U+7809(5,9); +U+780A(0);U+780A(0); +U+780B(0);U+780B(0); +U+780C(0);U+780C(5,9); +U+780D(0);U+780D(5,9); +U+780E(0);U+780E(0,9); +U+780F(0);U+780F(0,9); +U+7810(0);U+7810(0,9); +U+7811(0);U+7811(5,9); +U+7812(0);U+7812(5,9); +U+7813(0);U+7813(0,9); +U+7814(0);U+7814(5,9);U+63C5(3,9) +U+7815(0);U+788E(3,8,9);U+788E(3,8,9) +U+7816(0);U+78DA(1,3,8,9);U+78DA(1,3,8,9) +U+7817(0);U+7868(1,3,8,9);U+7868(1,3,8,9) +U+7818(0);U+7818(5); +U+7819(0);U+7819(0); +U+781A(0);U+786F(1,3,8,9);U+786F(1,3,8,9) +U+781B(0);U+781B(0); +U+781C(0);U+78B8(1,3,8);U+78B8(1,3,8) +U+781D(0);U+781D(5,9); +U+781E(0);U+781E(0); +U+781F(0);U+781F(5,9); +U+7820(0);U+7820(4,9); +U+7821(0);U+7821(0,9); +U+7822(0);U+7822(0,9); +U+7823(0);U+7823(5,9);U+78A2(3,9) +U+7825(0);U+7825(5,9); +U+7826(0);U+7826(5,9); +U+7827(0);U+7827(5,9);U+78AA(2,3,8,9) +U+7828(0);U+7828(3,9); +U+7829(0);U+7829(5,9); +U+782A(0);U+782A(0,9); +U+782B(0);U+782B(0,9);U+67F1(3,9) +U+782C(0);U+782C(5,9); +U+782D(0);U+782D(5,9); +U+782E(0);U+782E(0,9); +U+782F(0);U+782F(3,9); +U+7830(0);U+7830(5,9); +U+7831(0);U+7831(0,9); +U+7832(0);U+7832(4,9);U+70AE(2,3,8,9),U+792E(3,4),U+70B0(2,3,8,9) +U+7833(0);U+7833(0,9); +U+7834(0);U+7834(5,9); +U+7835(0);U+7835(0,9); +U+7837(0);U+7837(5,9); +U+7838(0);U+7838(5,9); +U+7839(0);U+7839(5); +U+783A(0);U+792A(1,3,8,9);U+792A(1,3,8,9) +U+783B(0);U+7931(1,3,8,9);U+7931(1,3,8,9),U+9468(3,9) +U+783C(0);U+783C(5); +U+783D(0);U+783D(0); +U+783E(0);U+792B(1,3,8,9);U+792B(1,3,8,9) +U+7840(0);U+790E(1,3,8,9);U+790E(1,3,8,9) +U+7841(0);U+785C(4,8,9);U+785C(4,8,9) +U+7843(0);U+7843(0,9);U+6731(1,9) +U+7844(0);U+7844(0); +U+7845(0);U+7845(5,9); +U+7847(0);U+7847(5); +U+7848(0);U+7848(3,9); +U+7849(0);U+7849(0,9); +U+784A(0);U+784A(3,9); +U+784C(0);U+784C(5,9); + +U+784D(0);U+784D(0,9); +U+784E(0);U+784E(5,9); +U+7850(0);U+7850(5,9); +U+7851(0);U+7851(0); +U+7852(0);U+7852(5,9); +U+7853(0);U+7853(0); +U+7854(0);U+7854(0); +U+7855(0);U+78A9(1,3,8,9);U+78A9(1,3,8,9) +U+7856(0);U+7864(1,3,8,9);U+7864(1,3,8,9) +U+7857(0);U+78FD(1,3,8,9);U+78FD(1,3,8,9) +U+7858(0);U+7858(0); +U+7859(0);U+78D1(1,3,8,9);U+78A8(4,9),U+78D1(1,3,8,9) +U+785A(0);U+7904(1,3,8,9);U+7904(1,3,8,9) +U+785B(0);U+785B(0); +U+785C(0);U+785C(0,9);U+7841(4,8) +U+785D(0);U+785D(5,9); +U+785E(0);U+785E(0,9); +U+785F(0);U+785F(0); +U+7860(0);U+7860(0,9); +U+7861(0);U+7861(0); +U+7862(0);U+7862(0,9); +U+7863(0);U+7863(0); +U+7864(0);U+7864(0,9);U+7856(1,3,8) +U+7865(0);U+7865(0,9);U+868C(4,9) +U+7866(0);U+7866(0); +U+7867(0);U+7867(0); +U+7868(0);U+7868(0,9);U+7817(1,3,8) +U+7869(0);U+7869(0,9); +U+786A(0);U+786A(5,9); +U+786B(0);U+786B(5,9); +U+786C(0);U+786C(5,9);U+5CFA(3,8) +U+786D(0);U+786D(5,9); +U+786E(0);U+78BA(1,3,8,9);U+5859(4,9),U+78BA(1,3,8,9),U+78BB(4,9),U+792D(3,9) +U+786F(0);U+786F(0,9);U+781A(1,3,8) +U+7870(0);U+7870(0,9); +U+7871(0);U+7871(0,9); +U+7872(0);U+7872(0); +U+7873(0);U+7873(0); +U+7874(0);U+7874(0); +U+7875(0);U+78E0(4,8,9);U+78E0(4,8,9) +U+7877(0);U+9E7C(1,3,4,8,9);U+7906(4),U+96AA(3,4,9),U+9E7C(1,3,4,8,9),U+9669(3,4),U+78B1(1,3,4,8) + +U+7878(0);U+7878(0); +U+7879(0);U+7879(0,9); +U+787A(0);U+787A(0); +U+787B(0);U+787B(0,9); +U+787C(0);U+787C(5,9); +U+787D(0);U+787D(0); +U+787E(0);U+787E(3,9); +U+787F(0);U+787F(0,9); +U+7880(0);U+7880(0,9); +U+7881(0);U+7881(0,9);U+68CB(2,3,8,9),U+68CA(0,2,3,8) +U+7882(0);U+7882(0); +U+7883(0);U+7883(0,9); +U+7884(0);U+7884(0,9); +U+7885(0);U+7885(0,9); +U+7886(0);U+7886(0,9); +U+7887(0);U+7887(5,9);U+6917(2,3,9) +U+7889(0);U+7889(5,9); +U+788A(0);U+788A(0); +U+788B(0);U+788B(0); +U+788C(0);U+788C(5,9);U+78DF(2,3,9) +U+788D(0);U+7919(1,3,8,9);U+7919(1,3,8,9) + +U+788E(0);U+788E(5,9);U+7815(3,8) +U+788F(0);U+788F(0,9); +U+7890(0);U+7890(0); +U+7891(0);U+7891(5,9); +U+7892(0);U+7892(0); +U+7893(0);U+7893(5,9); +U+7894(0);U+7894(0,9); +U+7895(0);U+7895(3,9);U+57FC(3,9),U+5D0E(7,8,9) +U+7896(0);U+7896(0,9); +U+7897(0);U+7897(5,9);U+92FA(3,9) +U+7898(0);U+7898(5,9); +U+7899(0);U+7899(0,9); +U+789A(0);U+789A(5,9); +U+789B(0);U+78E7(1,3,8,9);U+78E7(1,3,8,9) +U+789C(0);U+78E3(1,3,8,9);U+78E3(1,3,8,9) +U+789D(0);U+789D(3);U+791D(3,9) +U+789E(0);U+789E(0,9);U+5CA9(3,9),U+55A6(0,3,4,9),U+5D52(2,3,4,9),U+58E7(3,4,9),U+5DCC(3,4),U+5DD6(2,3,4,8,9),U+7939(3,4,9) + +U+789F(0);U+789F(5,9); +U+78A0(0);U+78A0(0,9); +U+78A1(0);U+78A1(5,9); +U+78A2(0);U+78A2(0,9);U+7823(3,9) +U+78A3(0);U+78A3(5,9); +U+78A4(0);U+78A4(0,9); +U+78A5(0);U+78A5(5,9); +U+78A6(0);U+78A6(0); +U+78A7(0);U+78A7(5,9); +U+78A8(0);U+78A8(0,9);U+7859(4),U+78D1(1,3,4,8,9) +U+78A9(0);U+78A9(0,9);U+7855(1,3,8) +U+78AA(0);U+78AA(0,9);U+7827(2,3,8,9) +U+78AB(0);U+78AB(0,9); +U+78AC(0);U+78AC(0,9); +U+78AD(0);U+78AD(0,9);U+7800(1,3,8) +U+78AE(0);U+78AE(0); +U+78AF(0);U+7459(3,8,9);U+7459(3,8,9) +U+78B0(0);U+78B0(5,9);U+63BD(2,9),U+8E2B(2,3,9) +U+78B1(0);U+9E7C(3,4,8,9);U+9E7C(3,4,8,9),U+7877(1,3,4,8),U+7906(1,3,4,8),U+96AA(1,3,4,8,9),U+9669(1,3,4,8) + +U+78B2(0);U+78B2(5,9); +U+78B3(0);U+78B3(5,9); +U+78B4(0);U+78B4(5,9); +U+78B5(0);U+78B5(0); +U+78B6(0);U+78B6(0); +U+78B7(0);U+78B7(0); +U+78B8(0);U+78B8(0);U+781C(1,3,8) +U+78B9(0);U+78B9(5); +U+78BA(0);U+78BA(0,9);U+786E(1,3,8,9),U+5859(0,1,3,4,8,9),U+78BB(1,3,4,8,9),U+792D(1,3,4,8,9) + +U+78BB(0);U+78BB(0,9);U+786E(4,9),U+5859(0,4,9),U+78BA(1,3,4,8,9),U+792D(3,4,9) +U+78BC(0);U+78BC(0,9);U+7801(1,3,8) +U+78BD(0);U+78BD(0); +U+78BE(0);U+78BE(5,9); +U+78BF(0);U+78BF(0); +U+78C0(0);U+78C0(0); +U+78C1(0);U+78C1(5,9); +U+78C3(0);U+78C3(0,9); +U+78C4(0);U+78C4(0,9); +U+78C5(0);U+78C5(5,9); +U+78C6(0);U+6ED1(3,8,9);U+6ED1(3,8,9) +U+78C8(0);U+78C8(0,9); +U+78C9(0);U+78C9(5,9); +U+78CA(0);U+78CA(5,9);U+78E5(3,9) +U+78CB(0);U+78CB(5,9); + +U+78CC(0);U+78CC(0,9); +U+78CD(0);U+78CD(0,9); +U+78CE(0);U+78CE(0,9); +U+78CF(0);U+78CF(0,9); +U+78D0(0);U+78D0(5,9); +U+78D1(0);U+78D1(0,9);U+7859(1,3,8),U+78A8(1,3,4,8,9) +U+78D3(0);U+78D3(0); +U+78D4(0);U+78D4(5,9); +U+78D5(0);U+78D5(5,9); +U+78D6(0);U+78D6(0); +U+78D7(0);U+78D7(0); +U+78D8(0);U+78D8(0); +U+78D9(0);U+78D9(5); +U+78DA(0);U+78DA(0,9);U+7816(1,3,8) +U+78DB(0);U+78DB(0,9); +U+78DC(0);U+78DC(0); +U+78DD(0);U+78DD(3,9); +U+78DE(0);U+78DE(0,9); +U+78DF(0);U+78DF(0,9);U+788C(2,3,9) +U+78E0(0);U+78E0(0,9);U+7875(4,8) +U+78E1(0);U+78E1(3,9); +U+78E2(0);U+78E2(3,9); +U+78E3(0);U+78E3(0,9);U+789C(1,3,8) +U+78E4(0);U+78E4(0); +U+78E5(0);U+78E5(0,9);U+78CA(3,9) +U+78E6(0);U+78E6(0); +U+78E7(0);U+78E7(0,9);U+789B(1,3,8) +U+78E8(0);U+78E8(5,9); +U+78E9(0);U+78E9(0,9); +U+78EA(0);U+78EA(0,9); +U+78EB(0);U+78EB(0); +U+78EC(0);U+78EC(5,9); +U+78ED(0);U+78ED(0,9); +U+78EE(0);U+78EE(0); +U+78EF(0);U+78EF(0,9);U+77F6(1,3,8) +U+78F1(0);U+78F1(0); +U+78F2(0);U+78F2(5,9); +U+78F3(0);U+78F3(0,9); +U+78F4(0);U+78F4(5,9); +U+78F5(0);U+78F5(4); +U+78F6(0);U+78F6(0); +U+78F7(0);U+78F7(5,9);U+71D0(2,9) +U+78F9(0);U+78F9(0,9); +U+78FA(0);U+78FA(5,9); +U+78FB(0);U+78FB(3,9); +U+78FC(0);U+78FC(0,9); +U+78FD(0);U+78FD(0,9);U+7857(1,3,8) +U+78FE(0);U+78FE(0,9); +U+78FF(0);U+78FF(0,9); +U+7901(0);U+7901(5,9); +U+7902(0);U+7902(0,9); +U+7903(0);U+7903(0); +U+7904(0);U+7904(0,9);U+785A(1,3,8) +U+7905(0);U+7905(5,9); +U+7906(0);U+96AA(3,8,9);U+9669(3),U+7877(7),U+96AA(3,8,9),U+9E7C(1,3,4,8,9),U+78B1(1,3,4,8) + +U+7907(0);U+7907(0); +U+7909(0);U+7909(3,9); +U+790A(0);U+790A(0); +U+790B(0);U+790B(0); +U+790C(0);U+790C(0,9); +U+790E(0);U+790E(0,9);U+7840(1,3,8) +U+790F(0);U+790F(0); + +U+7910(0);U+7910(3,9); +U+7911(0);U+7911(0,9); +U+7912(0);U+7912(3,9); +U+7913(0);U+7913(5,9); +U+7914(0);U+7914(4,9); +U+7916(0);U+7916(0); +U+7917(0);U+7917(0,9); +U+7918(0);U+7918(3); +U+7919(0);U+7919(0,9);U+788D(1,3,8) +U+791A(0);U+791A(0); +U+791B(0);U+791B(0,9); +U+791C(0);U+791C(0,9); +U+791D(0);U+791D(0,9);U+789D(3) +U+791E(0);U+791E(5,9); +U+7921(0);U+7921(0,9); +U+7922(0);U+7922(0); +U+7923(0);U+7923(0,9); +U+7924(0);U+7924(5,9);U+7938(3,9) +U+7925(0);U+7925(0,9); +U+7926(0);U+7926(0,9);U+77FF(1,3,8),U+945B(3,8) +U+7927(0);U+7927(3,9); +U+7928(0);U+7928(0,9); +U+7929(0);U+7929(3,9); +U+792A(0);U+792A(0,9);U+783A(1,3,8) +U+792B(0);U+792B(0,9);U+783E(1,3,8) +U+792C(0);U+792C(0,9);U+77FE(1,3,8) +U+792D(0);U+792D(0,9);U+786E(3,9),U+5859(0,3,4,9),U+78BA(1,3,4,8,9),U+78BB(3,4,9) +U+792E(0);U+7832(3,4,9);U+70AE(2,3,8,9),U+7832(3,4,9),U+70B0(2,3,8,9) +U+792F(0);U+792F(0,9); +U+7930(0);U+7930(0); +U+7931(0);U+7931(0,9);U+783B(1,3,8),U+9468(1,3,8,9) +U+7933(0);U+7933(0); +U+7934(0);U+7934(5); +U+7935(0);U+7935(0,9); +U+7937(0);U+7937(0); +U+7938(0);U+7938(0,9);U+7924(3,9) +U+7939(0);U+7939(0,9);U+5CA9(3,9),U+55A6(0,3,4,9),U+5D52(2,3,4,9),U+58E7(3,4,9),U+5DCC(3,4),U+5DD6(2,3,4,8,9),U+789E(3,4,9) + +U+793A(0);U+793A(5,9); +U+793B(0);U+793B(5); +U+793C(0);U+79AE(1,3,8,9);U+79AE(1,3,8,9) +U+793D(0);U+793D(0,9); +U+793E(0);U+793E(5,9); +U+793F(0);U+793F(3,9);U+79B4(3,9) +U+7940(0);U+7940(5,9); +U+7941(0);U+7941(5,9); +U+7942(0);U+7942(0,9); +U+7943(0);U+79A1(4,8,9);U+79A1(4,8,9) +U+7944(0);U+7944(0,9); +U+7945(0);U+7945(0,9);U+5996(3,9),U+8A1E(3,9) +U+7946(0);U+7946(5,9); +U+7947(0);U+7947(3,9);U+79D6(2,3,9) +U+7948(0);U+7948(5,9); +U+7949(0);U+7949(5,9); +U+794A(0);U+794A(0,9); +U+794B(0);U+794B(0,9); +U+794C(0);U+794C(0,9);U+51B2(3),U+6C96(3,4,8,9),U+885D(1,3,4,8,9),U+8876(3,4,9),U+76C5(3,4,8,9) + +U+794D(0);U+794D(0); +U+794E(0);U+7995(1,3,8,9);U+7995(1,3,8,9) +U+794F(0);U+794F(0,9); +U+7950(0);U+7950(3,9); +U+7951(0);U+7951(0,9); + +U+7952(0);U+7952(0,9); +U+7953(0);U+7953(5,9); +U+7954(0);U+7954(0,9); +U+7955(0);U+7955(0,9);U+79D8(2,3,8,9) +U+7956(0);U+7956(5,9); +U+7957(0);U+7957(5,9); +U+7958(0);U+7B97(3,8,9);U+7B97(3,8,9),U+7B6D(3,8,9) +U+795A(0);U+795A(5,9); +U+795B(0);U+795B(5,9); +U+795C(0);U+795C(5,9); +U+795D(0);U+795D(5,9);U+7969(3,9) +U+795E(0);U+795E(5,9); +U+795F(0);U+795F(5,9); +U+7960(0);U+7960(5,9); +U+7961(0);U+7961(0,9);U+67F4(3,9) +U+7962(0);U+79B0(1,3,8,9);U+79B0(1,3,8,9) +U+7963(0);U+7963(0,9);U+65C5(3,9) +U+7964(0);U+7964(0,9); +U+7965(0);U+7965(5,9); +U+7966(0);U+7966(4); +U+7967(0);U+7967(5,9); +U+7968(0);U+7968(5,9); +U+7969(0);U+7969(0,9);U+795D(3,9) +U+796A(0);U+796A(0,9); +U+796B(0);U+796B(0,9); +U+796D(0);U+796D(5,9); +U+796F(0);U+798E(1,3,8,9);U+798E(1,3,8,9) +U+7970(0);U+7970(3,9); +U+7971(0);U+7971(0); +U+7972(0);U+7972(0,9); +U+7973(0);U+7973(0,9); +U+7974(0);U+7974(0,9); +U+7977(0);U+79B1(1,3,8,9);U+79B1(1,3,8,9) +U+7978(0);U+798D(1,3,8,9);U+798D(1,3,8,9) +U+7979(0);U+7979(0,9); +U+797A(0);U+797A(5,9);U+79A5(3,8) +U+797B(0);U+797B(0); +U+797C(0);U+797C(3,9); +U+797D(0);U+797D(0,9); +U+797E(0);U+797E(0); +U+797F(0);U+797F(0,9);U+7984(4,8) +U+7980(0);U+7A1F(2,3,8,9);U+7A1F(2,3,8,9),U+5EE9(0,2,3,8,9),U+5EEA(2,3,8) +U+7981(0);U+7981(5,9); +U+7982(0);U+7982(0,9); +U+7983(0);U+7983(0); +U+7984(0);U+797F(4,8,9);U+797F(4,8,9) +U+7985(0);U+79AA(1,3,8,9);U+79AA(1,3,8,9) +U+7988(0);U+7988(0,9); +U+7989(0);U+7989(0); +U+798A(0);U+798A(5,9); +U+798B(0);U+798B(0,9); +U+798C(0);U+798C(0); +U+798D(0);U+798D(0,9);U+7978(1,3,8) +U+798E(0);U+798E(0,9);U+796F(1,3,8) +U+798F(0);U+798F(5,9); +U+7990(0);U+7990(0,9); +U+7991(0);U+7991(0); +U+7992(0);U+7992(0,9); +U+7993(0);U+7993(0,9); +U+7994(0);U+7994(3,9); +U+7995(0);U+7995(0,9);U+794E(1,3,8) +U+7996(0);U+7996(0,9); + +U+7997(0);U+7997(0,9); +U+7998(0);U+7998(3,9); +U+7999(0);U+7999(0); +U+799A(0);U+799A(5,9); +U+799B(0);U+799B(0,9); +U+799C(0);U+799C(0,9); +U+799F(0);U+799F(0); +U+79A0(0);U+79A0(0,9); +U+79A1(0);U+79A1(0,9);U+7943(4,8) +U+79A2(0);U+79A2(0,9); +U+79A3(0);U+79A3(0); +U+79A4(0);U+79A4(0,9); +U+79A5(0);U+797A(3,8,9);U+797A(3,8,9) +U+79A6(0);U+79A6(0,9);U+5FA1(1,3,8,9) +U+79A7(0);U+79A7(5,9); +U+79A8(0);U+79A8(0,9); +U+79AA(0);U+79AA(0,9);U+7985(1,3,8) +U+79AB(0);U+79AB(0,9); +U+79AC(0);U+79AC(0,9); +U+79AD(0);U+79AD(0,9); +U+79AE(0);U+79AE(0,9);U+793C(1,3,8) +U+79AF(0);U+79AF(0); +U+79B0(0);U+79B0(0,9);U+7962(1,3,8) +U+79B1(0);U+79B1(0,9);U+7977(1,3,8) +U+79B2(0);U+79B2(0,9); +U+79B3(0);U+79B3(5,9); +U+79B4(0);U+79B4(0,9);U+793F(3,9) +U+79B5(0);U+79B5(0); +U+79B6(0);U+79B6(0,9); +U+79B7(0);U+79B7(3,9); +U+79B8(0);U+79B8(0,9);U+8E42(3,9) +U+79B9(0);U+79B9(5,9); +U+79BA(0);U+79BA(5,9); +U+79BB(0);U+96E2(1,3,8,9);U+96E2(1,3,8,9) +U+79BD(0);U+79BD(5,9); +U+79BE(0);U+79BE(5,9); +U+79BF(0);U+79BF(0,9);U+79C3(4,8) +U+79C0(0);U+79C0(5,9); +U+79C1(0);U+79C1(5,9);U+53B6(3,8) +U+79C2(0);U+79C2(0); +U+79C3(0);U+79BF(4,8,9);U+79BF(4,8,9) +U+79C5(0);U+79C5(3,9); +U+79C6(0);U+7A08(2,3,9);U+7A08(2,3,9) +U+79C8(0);U+79C8(0,9);U+7C7C(2,3,8) +U+79C9(0);U+79C9(5,9); +U+79CA(0);U+5E74(2,3,9);U+5E74(2,3,9) +U+79CB(0);U+79CB(1,3,9),U+97A6(1,3,4,9);U+7A50(7,8),U+97A6(1,3,4,9),U+9F9D(7,8) +U+79CD(0);U+7A2E(1,3,8,9);U+7A2E(1,3,8,9) +U+79CE(0);U+79CE(0,9); +U+79CF(0);U+79CF(3,9);U+8017(3,8,9) +U+79D0(0);U+8018(3,8,9);U+8018(3,8,9) +U+79D1(0);U+79D1(5,9); +U+79D2(0);U+79D2(5,9); +U+79D3(0);U+79D3(0); +U+79D5(0);U+79D5(5,9); +U+79D6(0);U+79D6(0,9);U+7947(2,3,9) +U+79D8(0);U+79D8(5,9),U+7955(2,3,8,9);U+7955(2,3,8,9) +U+79D9(0);U+79D9(0); +U+79DA(0);U+79DA(0); +U+79DB(0);U+79DB(0); +U+79DC(0);U+79DC(0,9); +U+79DD(0);U+79DD(0,9); +U+79DE(0);U+79DE(0,9); + +U+79DF(0);U+79DF(5,9); +U+79E0(0);U+79E0(0,9); +U+79E1(0);U+79E1(0); +U+79E2(0);U+79E2(0); +U+79E3(0);U+79E3(5,9); +U+79E4(0);U+79E4(5,9); +U+79E5(0);U+79E5(0); +U+79E6(0);U+79E6(5,9); +U+79E7(0);U+79E7(5,9); +U+79E8(0);U+79E8(0); +U+79E9(0);U+79E9(5,9); +U+79EA(0);U+79EA(0,9); +U+79EB(0);U+79EB(5,9); +U+79EC(0);U+79EC(0,9); +U+79ED(0);U+79ED(5,9); +U+79EE(0);U+79EE(0,9); +U+79EF(0);U+7A4D(1,3,8,9);U+7A4D(1,3,8,9) +U+79F0(0);U+7A31(1,3,8,9);U+5041(3,9),U+7A31(1,3,8,9) +U+79F1(0);U+79F1(0); +U+79F2(0);U+79F2(0); +U+79F3(0);U+79F3(0); +U+79F4(0);U+79F4(0); +U+79F5(0);U+79F5(0); +U+79F6(0);U+79F6(0,9);U+7CA2(3,9) +U+79F7(0);U+79F7(0,9); +U+79F8(0);U+79F8(5,9);U+7A2D(2),U+9782(4,9) +U+79F9(0);U+79F9(0); +U+79FA(0);U+79FA(0,9); +U+79FB(0);U+79FB(5,9);U+8FFB(2,3,9) +U+79FC(0);U+79FC(0); +U+79FD(0);U+7A62(1,3,8,9);U+7A62(1,3,8,9),U+8589(3,9) +U+79FE(0);U+7A60(4,8,9);U+7A60(4,8,9) +U+79FF(0);U+79FF(0); +U+7A00(0);U+7A00(5,9);U+5E0C(3,8,9) +U+7A02(0);U+7A02(5,9); +U+7A03(0);U+7A03(5,9); +U+7A04(0);U+7A04(0,9); +U+7A05(0);U+7A05(0,9);U+7A0E(4,8) +U+7A06(0);U+7A06(5); +U+7A08(0);U+7A08(0,9);U+79C6(2,3) +U+7A0A(0);U+7A0A(4,9); +U+7A0B(0);U+7A0B(5,9); +U+7A0C(0);U+7A0C(3,9); +U+7A0D(0);U+7A0D(5,9);U+8571(4,9) +U+7A0E(0);U+7A05(4,8,9);U+7A05(4,8,9) +U+7A0F(0);U+7A0F(0); +U+7A10(0);U+7A10(3,9); +U+7A11(0);U+7A11(3,9);U+7A4B(3,9) +U+7A12(0);U+7A12(0,9); +U+7A13(0);U+7A13(0,9); +U+7A14(0);U+7A14(5,9); +U+7A15(0);U+7A15(0,9); +U+7A16(0);U+7A16(0); +U+7A17(0);U+7A17(5,9);U+7CBA(2,9) +U+7A18(0);U+7A18(0,9); +U+7A19(0);U+7A19(0,9); +U+7A1A(0);U+7A1A(5,9);U+7A49(2,3,8) +U+7A1B(0);U+7A1B(3,9); +U+7A1C(0);U+7A1C(0,9);U+68F1(2,3,9) +U+7A1D(0);U+7A1D(0); +U+7A1E(0);U+7A1E(5,9); +U+7A1F(0);U+7A1F(0,9);U+5EE9(3,8,9),U+7980(2,3,8),U+5EEA(3,8) +U+7A20(0);U+7A20(5,9); + +U+7A21(0);U+7A21(0); +U+7A22(0);U+7A22(3,9); +U+7A23(0);U+7A4C(1,3,8,9);U+7A4C(1,3,8,9) +U+7A24(0);U+7A24(0); +U+7A25(0);U+7A25(0); +U+7A26(0);U+7A26(0,9); +U+7A27(0);U+7A27(0); +U+7A28(0);U+7A28(0,9); +U+7A29(0);U+7A29(0); +U+7A2A(0);U+7A2A(0); +U+7A2B(0);U+7A2B(0,9); +U+7A2D(0);U+79F8(2,9);U+79F8(2,9),U+9782(2,4,9) +U+7A2E(0);U+7A2E(0,9);U+79CD(1,3,8,9) +U+7A2F(0);U+7A2F(3,9); +U+7A30(0);U+7A30(0,9);U+7CC8(3,9) +U+7A31(0);U+7A31(0,9);U+79F0(1,3,8),U+5041(0,1,3,8,9) +U+7A32(0);U+7A3B(3,8,9);U+7A3B(3,8,9) +U+7A33(0);U+7A69(1,3,8,9);U+7A69(1,3,8,9) +U+7A34(0);U+7A34(0); +U+7A35(0);U+7A35(0); +U+7A37(0);U+7A37(5,9); +U+7A39(0);U+7A39(5,9); +U+7A3B(0);U+7A3B(5,9);U+7A32(3,8) +U+7A3C(0);U+7A3C(5,9); +U+7A3D(0);U+7A3D(5,9);U+4E69(3,8,9) +U+7A3E(0);U+7A3F(2,3,8,9);U+7A3F(2,3,8,9) +U+7A3F(0);U+7A3F(5,9);U+7A3E(2,3,8) +U+7A40(0);U+7A40(0,9);U+8C37(1,3,8,9) +U+7A41(0);U+7A41(0); +U+7A42(0);U+7A57(3,8,9);U+7A57(3,8,9),U+7A5F(3,8,9) +U+7A43(0);U+7A43(0); +U+7A44(0);U+7A44(0,9); +U+7A45(0);U+7CE0(2,3,8,9);U+7CE0(2,3,8,9) +U+7A46(0);U+7A46(5,9); +U+7A47(0);U+7A47(0,9);U+415F(1,3) +U+7A48(0);U+7A48(0,9); +U+7A49(0);U+7A1A(2,3,8,9);U+7A1A(2,3,8,9) +U+7A4A(0);U+7A4A(3,9); +U+7A4B(0);U+7A4B(0,9);U+7A11(3,9) +U+7A4C(0);U+7A4C(0,9);U+7A23(1,3,8) +U+7A4D(0);U+7A4D(0,9);U+79EF(1,3,8) +U+7A4E(0);U+7A4E(0,9);U+9834(2,8),U+9895(8),U+9896(1,3,8) +U+7A50(0);U+79CB(7,8,9);U+79CB(7,8,9),U+9F9D(4),U+97A6(1,3,4,7,8,9) +U+7A51(0);U+7A61(1,3,8,9);U+7A61(1,3,8,9) +U+7A52(0);U+7A52(0); +U+7A53(0);U+7A53(0); +U+7A54(0);U+7A54(0,9); +U+7A55(0);U+7A55(0); +U+7A56(0);U+7A56(0,9); +U+7A57(0);U+7A57(5,9);U+7A42(3,8),U+7A5F(3,9) +U+7A58(0);U+7A58(0,9); +U+7A59(0);U+7A59(0); +U+7A5A(0);U+7A5A(0,9); +U+7A5B(0);U+7A5B(3,9); +U+7A5C(0);U+7A5C(0,9); +U+7A5D(0);U+7A5D(0); +U+7A5E(0);U+7A6D(4,8,9);U+7A6D(4,8,9) +U+7A5F(0);U+7A5F(0,9);U+7A57(3,9),U+7A42(0,3,8) +U+7A60(0);U+7A60(0,9);U+79FE(4,8) +U+7A61(0);U+7A61(0,9);U+7A51(1,3,8) +U+7A62(0);U+7A62(0,9);U+79FD(1,3,8),U+8589(1,3,8,9) +U+7A65(0);U+7A65(3); +U+7A66(0);U+7A66(0); + +U+7A67(0);U+7A67(0,9); +U+7A68(0);U+7A68(0,9);U+9893(4),U+9839(4,8,9),U+983D(1,3,4,8) +U+7A69(0);U+7A69(0,9);U+7A33(1,3,8) +U+7A6B(0);U+7A6B(0,9);U+83B7(1,3,8),U+7372(0,1,3,8,9) +U+7A6C(0);U+7A6C(0,9); +U+7A6D(0);U+7A6D(0,9);U+7A5E(4,8) +U+7A6E(0);U+7A6E(0,9); +U+7A70(0);U+7A70(5,9); +U+7A71(0);U+7A71(0,9); +U+7A72(0);U+7A72(0); +U+7A73(0);U+7A73(0); +U+7A74(0);U+7A74(5,9);U+5CA4(4,9) +U+7A75(0);U+7A75(0,9);U+6316(3,9) +U+7A76(0);U+7A76(5,9); +U+7A77(0);U+7AAE(1,3,8,9);U+7AAE(1,3,8,9) +U+7A78(0);U+7A78(5,9); +U+7A79(0);U+7A79(5,9); +U+7A7A(0);U+7A7A(5,9); +U+7A7B(0);U+7A7B(0,9);U+5B87(3,9) +U+7A7C(0);U+7A7C(0); +U+7A7D(0);U+9631(2,3,8,9);U+9631(2,3,8,9) +U+7A7E(0);U+7A7E(4,9); +U+7A7F(0);U+7A7F(5,9); +U+7A80(0);U+7A80(5,9); +U+7A81(0);U+7A81(5,9); +U+7A83(0);U+7ACA(1,3,8,9);U+7ACA(1,3,8,9) +U+7A84(0);U+7A84(5,9); +U+7A85(0);U+7A85(3,9); +U+7A86(0);U+7A86(5,9); +U+7A87(0);U+7A87(0,9); +U+7A88(0);U+7A88(5,9); +U+7A89(0);U+7A89(3,9); +U+7A8A(0);U+7A8A(3,9); +U+7A8B(0);U+7A8B(0,9); +U+7A8C(0);U+7A8C(0,9); +U+7A8D(0);U+7AC5(1,3,8,9);U+7AC5(1,3,8,9) +U+7A8E(0);U+7AB5(1,3,8,9);U+7AB5(1,3,8,9) +U+7A8F(0);U+7A8F(0,9); +U+7A90(0);U+7A90(0,9); +U+7A91(0);U+7AAF(2,3,8,9);U+7AAF(2,3,8,9),U+7AB0(2,4) +U+7A92(0);U+7A92(5,9); +U+7A93(0);U+7A97(2,3,8,9);U+7A97(2,3,8,9) +U+7A94(0);U+7A94(3,9); +U+7A95(0);U+7A95(5,9); +U+7A96(0);U+7A96(5,9); +U+7A97(0);U+7A97(5,9);U+7A93(2,3,8) +U+7A98(0);U+7A98(5,9); +U+7A99(0);U+7A99(0,9); +U+7A9C(0);U+7AC4(1,3,8,9);U+7AC4(1,3,8,9) +U+7A9D(0);U+7AA9(1,3,8,9);U+7AA9(1,3,8,9) +U+7A9E(0);U+7A9E(0,9); +U+7A9F(0);U+7A9F(5,9); +U+7AA0(0);U+7AA0(5,9); +U+7AA1(0);U+7AA1(0); +U+7AA2(0);U+7AA2(0,9); +U+7AA3(0);U+7AA3(0,9); +U+7AA4(0);U+7AA4(0); +U+7AA5(0);U+7ABA(1,3,8,9);U+7ABA(1,3,8,9),U+95DA(2,3,9) +U+7AA6(0);U+7AC7(1,3,8,9);U+7AC7(1,3,8,9) +U+7AA7(0);U+7AA7(0); +U+7AA8(0);U+7AA8(5,9);U+5837(3,9) +U+7AA9(0);U+7AA9(0,9);U+7A9D(1,3,8) +U+7AAA(0);U+7AAA(0,9);U+6D3C(1,3,8,9),U+6F25(1,3,8,9) + +U+7AAB(0);U+7AAB(0,9); +U+7AAC(0);U+7AAC(5,9); +U+7AAD(0);U+7AB6(1,3,8,9);U+5BE0(4,9),U+7AB6(1,3,8,9) +U+7AAE(0);U+7AAE(0,9);U+7A77(1,3,8) +U+7AAF(0);U+7AAF(0,9);U+7A91(2,3,8),U+7AB0(4,8) +U+7AB0(0);U+7AAF(4,8,9);U+7A91(2,4),U+7AAF(4,8,9) +U+7AB1(0);U+7AB1(0,9); +U+7AB2(0);U+7AB2(0,9); +U+7AB3(0);U+7AB3(5,9); +U+7AB4(0);U+7AB4(0,9); +U+7AB5(0);U+7AB5(0,9);U+7A8E(1,3,8) +U+7AB6(0);U+7AB6(0,9);U+7AAD(1,3,8),U+5BE0(0,1,3,4,8,9) +U+7AB7(0);U+7AB7(0,9); +U+7AB8(0);U+7AB8(0,9); +U+7ABA(0);U+7ABA(0,9);U+7AA5(1,3,8),U+95DA(1,2,3,8,9) +U+7ABE(0);U+7ABE(4,9); +U+7ABF(0);U+7ABF(5,9); +U+7AC0(0);U+7AC0(3,9);U+8D6A(7),U+8D6C(1,3,7,8,9) +U+7AC1(0);U+7AC1(0,9); +U+7AC4(0);U+7AC4(0,9);U+7A9C(1,3,8) +U+7AC5(0);U+7AC5(0,9);U+7A8D(1,3,8) +U+7AC7(0);U+7AC7(0,9);U+7AA6(1,3,8) +U+7AC8(0);U+7076(1,3,8,9);U+7076(1,3,8,9) +U+7AC9(0);U+7AC9(0); +U+7ACA(0);U+7ACA(0,9);U+7A83(1,3,8) +U+7ACB(0);U+7ACB(5,9); +U+7ACC(0);U+7ACC(0); +U+7ACD(0);U+7ACD(0); +U+7ACE(0);U+7ACE(0); +U+7ACF(0);U+7ACF(0); +U+7AD0(0);U+7AD0(0); +U+7AD1(0);U+7AD1(3,9);U+7AE4(3,9) +U+7AD2(0);U+5947(3,8,9);U+5947(3,8,9) +U+7AD3(0);U+7AD3(0); +U+7AD4(0);U+7AD4(0); +U+7AD5(0);U+7AD5(0); +U+7AD6(0);U+8C4E(4,8,9);U+7AEA(1,3,8),U+8C4E(4,8,9) +U+7AD8(0);U+7AD8(0,9); +U+7AD9(0);U+7AD9(5,9); +U+7ADB(0);U+7ADB(0); +U+7ADC(0);U+9F8D(3,8,9);U+9F8D(3,8,9),U+9F99(3),U+9F92(3,9) +U+7ADD(0);U+4E26(3,8,9);U+4E26(3,8,9),U+5E76(2,9),U+4F75(3,8,9),U+5002(3,8),U+5E77(2,3,4,8) + +U+7ADE(0);U+7AF6(1,3,8,9);U+7AF6(1,3,8,9),U+7AF8(3) +U+7ADF(0);U+7ADF(5,9); +U+7AE0(0);U+7AE0(5,9);U+9067(3,9) +U+7AE1(0);U+7AE1(0); +U+7AE2(0);U+4FDF(2,8,9);U+4FDF(2,8,9) +U+7AE3(0);U+7AE3(5,9); +U+7AE4(0);U+7AE4(0,9);U+7AD1(3,9) +U+7AE5(0);U+7AE5(5,9); +U+7AE6(0);U+7AE6(5,9); +U+7AE7(0);U+7AE7(0); +U+7AE8(0);U+7AE8(0); +U+7AEA(0);U+8C4E(2,3,8,9);U+7AD6(1,3,8),U+8C4E(2,3,8,9) +U+7AEB(0);U+7AEB(0,9); +U+7AEC(0);U+7AEC(0); +U+7AED(0);U+7AED(5,9); +U+7AEE(0);U+7AEE(0,9); +U+7AEF(0);U+7AEF(5,9);U+8011(3,9) +U+7AF0(0);U+7AF0(0); +U+7AF1(0);U+7AF1(0); +U+7AF2(0);U+7AF2(0); + +U+7AF3(0);U+7AF3(0); +U+7AF4(0);U+7AF4(0); +U+7AF6(0);U+7AF6(0,9);U+7ADE(1,3,8),U+7AF8(3,8) +U+7AF7(0);U+7AF7(3,9); +U+7AF8(0);U+7AF6(3,8,9);U+7ADE(3),U+7AF6(3,8,9) +U+7AF9(0);U+7AF9(5,9); +U+7AFA(0);U+7AFA(5,9);U+7B01(3,9) +U+7AFB(0);U+7AFB(0,9); +U+7AFD(0);U+7AFD(5,9); +U+7AFE(0);U+7BEA(3,8,9);U+7BEA(3,8,9),U+7B8E(3,8,9) +U+7AFF(0);U+7AFF(5,9); +U+7B00(0);U+7B00(0,9);U+8292(3,9) +U+7B01(0);U+7B01(0,9);U+7AFA(3,9) +U+7B02(0);U+7B02(0); +U+7B03(0);U+7BE4(1,3,8,9);U+7BE4(1,3,8,9) +U+7B04(0);U+7B04(5,9); +U+7B05(0);U+7B05(0,9);U+7B4A(3,9) +U+7B06(0);U+7B06(5,9);U+5DF4(3,8,9) +U+7B08(0);U+7B08(5,9); +U+7B09(0);U+7B09(0,9); +U+7B0A(0);U+7B0A(5,9); +U+7B0B(0);U+7B4D(2,3,8,9);U+7B4D(2,3,8,9) +U+7B0C(0);U+7B0C(0); +U+7B0D(0);U+7B0D(0); +U+7B0E(0);U+7B0E(0,9); +U+7B0F(0);U+7B0F(5,9); +U+7B10(0);U+7B10(0,9); +U+7B11(0);U+7B11(5,9);U+54B2(2,8) +U+7B12(0);U+7B12(0,9); +U+7B13(0);U+7B13(0,9); +U+7B14(0);U+7B46(1,3,8,9);U+7B46(1,3,8,9) +U+7B15(0);U+7B67(1,3,8,9);U+7B67(1,3,8,9) +U+7B16(0);U+7B16(0); +U+7B17(0);U+7B17(0); +U+7B18(0);U+7B18(0,9); +U+7B19(0);U+7B19(5,9); +U+7B1A(0);U+7B1A(0,9); +U+7B1B(0);U+7B1B(5,9);U+7BF4(3,9) +U+7B1C(0);U+7B1C(0); +U+7B1D(0);U+7B1D(3,9); +U+7B1E(0);U+7B1E(5,9); +U+7B20(0);U+7B20(5,9); +U+7B21(0);U+7B21(0); +U+7B22(0);U+7B22(0,9); +U+7B23(0);U+7B23(0,9); +U+7B24(0);U+7B24(5,9); +U+7B25(0);U+7B25(5,9); +U+7B26(0);U+7B26(5,9); +U+7B28(0);U+7B28(5,9); +U+7B2A(0);U+7B2A(5,9); +U+7B2B(0);U+7B2B(5,9); +U+7B2C(0);U+7B2C(5,9); +U+7B2D(0);U+7B2D(0,9); +U+7B2E(0);U+7B2E(5,9);U+7B70(3,4,9) +U+7B2F(0);U+7B2F(0,9); +U+7B30(0);U+7B30(0,9); +U+7B31(0);U+7B31(5,9); +U+7B32(0);U+7B32(3,9); +U+7B33(0);U+7B33(5,9); +U+7B34(0);U+7B34(0,9); +U+7B35(0);U+7B35(0,9); +U+7B36(0);U+77E2(3,8,9);U+77E2(3,8,9) +U+7B37(0);U+7B37(0); + +U+7B38(0);U+7B38(5,9); +U+7B39(0);U+7B39(0); +U+7B3A(0);U+7B8B(1,3,8,9);U+724B(2,3,9),U+7B8B(1,3,8,9) +U+7B3B(0);U+7B3B(0,9);U+7B47(3,8,9) +U+7B3C(0);U+7C60(1,3,8,9);U+7BED(4),U+7C60(1,3,8,9) +U+7B3D(0);U+7B3D(0); +U+7B3E(0);U+7C69(1,3,8,9);U+7C69(1,3,8,9) +U+7B3F(0);U+7B3F(0); +U+7B40(0);U+7B40(3,9); +U+7B41(0);U+7B41(0); +U+7B43(0);U+7B43(0); +U+7B44(0);U+7B44(0,9); +U+7B45(0);U+7B45(5,9); +U+7B46(0);U+7B46(0,9);U+7B14(1,3,8) +U+7B47(0);U+7B47(5,9);U+7B3B(3,8,9) +U+7B48(0);U+7B48(0,9); +U+7B49(0);U+7B49(5,9); +U+7B4A(0);U+7B4A(3,9);U+7B05(3,9) +U+7B4B(0);U+7B4B(5,9);U+89D4(3,8,9),U+65A4(2,3,5,8,9) +U+7B4C(0);U+7B4C(5,9); +U+7B4D(0);U+7B4D(0,9);U+7B0B(2,3,8) +U+7B4E(0);U+7B4E(0,9); +U+7B4F(0);U+7B4F(5,9); +U+7B50(0);U+7B50(5,9); +U+7B51(0);U+7B51(1,3,9),U+7BC9(1,3,8,9);U+7BC9(1,3,8,9) +U+7B52(0);U+7B52(5,9);U+7B69(2,3,9) +U+7B54(0);U+7B54(5,9);U+7563(3,9),U+8345(4,8,9) +U+7B55(0);U+7B55(0); +U+7B56(0);U+7B56(5,9);U+7B5E(2,8),U+7B74(2,3,9) +U+7B57(0);U+7B57(0); +U+7B58(0);U+7B58(5,9);U+7C06(4,9) +U+7B59(0);U+7B59(0); +U+7B5A(0);U+7BF3(1,3,8,9);U+7BF3(1,3,8,9) +U+7B5B(0);U+7BE9(1,3,8,9);U+7BE9(1,3,8,9) +U+7B5C(0);U+7C39(4,8,9);U+7C39(4,8,9) +U+7B5D(0);U+7B8F(4,8,9);U+7B8F(4,8,9) +U+7B5E(0);U+7B56(2,8,9);U+7B56(2,8,9),U+7B74(2,3,8,9) +U+7B5F(0);U+7B5F(0); +U+7B60(0);U+7B60(5,9); +U+7B61(0);U+7B61(0,9); +U+7B62(0);U+7B62(5); +U+7B63(0);U+7B63(0,9);U+7BF1(3,9),U+7C6C(1,3,8,9) +U+7B64(0);U+7B64(0,9); +U+7B65(0);U+7B65(3,9); +U+7B66(0);U+7B66(0,9);U+7BA1(2,3,9) +U+7B67(0);U+7B67(0,9);U+7B15(1,3,8) +U+7B68(0);U+7B68(0); +U+7B69(0);U+7B69(0,9);U+7B52(2,3,9) +U+7B6A(0);U+7B6A(0); +U+7B6B(0);U+7B6B(0); +U+7B6C(0);U+7B6C(0); +U+7B6D(0);U+7B6D(0,9);U+7B97(3,9),U+7958(0,3,8) +U+7B6E(0);U+7B6E(5,9); +U+7B70(0);U+7B70(0,9);U+7B2E(3,4,9) +U+7B71(0);U+7B71(5,9);U+7BE0(4,8,9),U+7B7F(4,8) +U+7B72(0);U+7B72(5,9); +U+7B73(0);U+7B73(0,9); +U+7B74(0);U+7B74(0,9);U+7B56(2,3,9),U+7B5E(2,3,8) +U+7B75(0);U+7B75(5,9); +U+7B76(0);U+7B76(0,9); +U+7B77(0);U+7B77(5,9); +U+7B78(0);U+7B78(0,9); +U+7B79(0);U+7C4C(1,3,8,9);U+7C4C(1,3,8,9) + +U+7B7B(0);U+7B7B(5); +U+7B7C(0);U+7BD4(4,8,9);U+7BD4(4,8,9) +U+7B7D(0);U+7B7D(0); +U+7B7E(0);U+7C3D(1,3,8,9),U+7C64(1,3,8,9);U+7C3D(1,3,8,9),U+7C56(4),U+7C64(1,3,8,9) +U+7B7F(0);U+7BE0(4,8,9);U+7BE0(4,8,9),U+7B71(4,5,8,9) +U+7B80(0);U+7C21(1,3,8,9);U+7C21(1,3,8,9) +U+7B81(0);U+7B81(0); +U+7B82(0);U+7B82(0,9); +U+7B83(0);U+7B83(0); +U+7B84(0);U+7B84(0,9); +U+7B85(0);U+7B85(5,9); +U+7B87(0);U+7B87(0,9);U+4E2A(4),U+500B(2,3,8,9) +U+7B88(0);U+7B88(0,9); +U+7B89(0);U+7B89(0); +U+7B8A(0);U+7B8A(0,9); +U+7B8B(0);U+7B8B(0,9);U+724B(2,3,8,9),U+7B3A(1,3,8) +U+7B8C(0);U+7B8C(0,9); +U+7B8D(0);U+7B8D(5,9); +U+7B8E(0);U+7B8E(0,9);U+7BEA(3,9),U+7AFE(0,3,8) +U+7B8F(0);U+7B8F(0,9);U+7B5D(4,8) +U+7B90(0);U+7B90(5,9); +U+7B91(0);U+7B91(0,9); +U+7B93(0);U+7C59(1,3,8,9);U+7C59(1,3,8,9) +U+7B94(0);U+7B94(5,9); +U+7B95(0);U+7B95(5,9); +U+7B96(0);U+7B96(0,9); +U+7B97(0);U+7B97(5,9);U+7958(3,8),U+7B6D(3,9) +U+7B98(0);U+7B98(0,9); +U+7B99(0);U+7B99(3,9); +U+7B9A(0);U+5284(4,9);U+624E(4,9),U+5284(4,9),U+5273(0,4),U+672D(2,3,4,9),U+7D25(2,4),U+7D2E(2,4,8,9) + +U+7B9B(0);U+7B9B(3,9); +U+7B9C(0);U+7B9C(5,9); +U+7B9D(0);U+7B9D(5,9);U+9257(3,8,9),U+94B3(1,3,8),U+62D1(0,1,3,4,8,9) +U+7B9E(0);U+7B9E(0); +U+7B9F(0);U+7B9F(0); +U+7BA0(0);U+7BA0(3,9);U+68F0(2,3,9) +U+7BA1(0);U+7BA1(5,9);U+7B66(2,3,9) +U+7BA2(0);U+7BA2(5); +U+7BA4(0);U+7BA4(0,9); +U+7BA6(0);U+7C00(1,3,8,9);U+7C00(1,3,8,9) +U+7BA7(0);U+7BCB(1,3,8,9);U+7BCB(1,3,8,9) +U+7BA8(0);U+7C5C(1,3,8,9);U+7C5C(1,3,8,9) +U+7BA9(0);U+7C6E(1,3,8,9);U+7C6E(1,3,8,9) +U+7BAA(0);U+7C1E(1,3,8,9);U+7C1E(1,3,8,9) +U+7BAB(0);U+7C2B(1,3,8,9);U+7C2B(1,3,8,9),U+7C18(4) +U+7BAC(0);U+7BAC(5,9);U+7BDB(2,3,8,9) +U+7BAD(0);U+7BAD(5,9); +U+7BAE(0);U+7BAE(0); +U+7BAF(0);U+7BAF(0,9); +U+7BB1(0);U+7BB1(5,9); +U+7BB3(0);U+7BB3(3);U+7C08(3,8) +U+7BB4(0);U+7BB4(5,9); +U+7BB5(0);U+7BB5(0,9); +U+7BB6(0);U+7BB6(0); +U+7BB7(0);U+7BB7(0,9); +U+7BB8(0);U+7BB8(5,9); +U+7BB9(0);U+7BB9(0,9); +U+7BBA(0);U+7BBA(0); +U+7BBB(0);U+7BBB(0); +U+7BBC(0);U+7BBC(0); +U+7BBD(0);U+7BBD(0); +U+7BBE(0);U+7BBE(0,9); + +U+7BBF(0);U+7BBF(0); +U+7BC0(0);U+7BC0(0,9);U+8282(1,3,8) +U+7BC1(0);U+7BC1(5,9); +U+7BC2(0);U+7BC2(0); +U+7BC3(0);U+7BC3(0); +U+7BC4(0);U+7BC4(0,9);U+8303(1,3,8,9) +U+7BC5(0);U+7BC5(3); +U+7BC6(0);U+7BC6(5,9); +U+7BC7(0);U+7BC7(5,9); +U+7BC8(0);U+7BC8(0); +U+7BC9(0);U+7BC9(0,9);U+7B51(1,3,8,9) +U+7BCA(0);U+7BCA(3,9); +U+7BCB(0);U+7BCB(0,9);U+7BA7(1,3,8) +U+7BCC(0);U+7BCC(5,9); +U+7BCD(0);U+7BCD(0); +U+7BCE(0);U+7BCE(0,9); +U+7BD0(0);U+7BD0(0); +U+7BD1(0);U+7C23(1,3,8,9);U+7C23(1,3,8,9) +U+7BD2(0);U+7BD2(0); +U+7BD3(0);U+7C0D(1,3,8,9);U+7C0D(1,3,8,9) +U+7BD4(0);U+7BD4(0,9);U+7B7C(4,8) +U+7BD5(0);U+7BD5(0,9); +U+7BD6(0);U+7BD6(0); +U+7BD7(0);U+7BD7(0); +U+7BD8(0);U+7BD8(3,9); +U+7BD9(0);U+7BD9(5,9); +U+7BDA(0);U+7BDA(5,9); +U+7BDB(0);U+7BDB(0,9);U+7BAC(2,3,8,9) +U+7BDC(0);U+7BDC(0,9); +U+7BDD(0);U+7BDD(5,9);U+7C3C(3,9) +U+7BDE(0);U+7BDE(0,9); +U+7BDF(0);U+7BDF(0,9); +U+7BE0(0);U+7BE0(0,9);U+7B71(4,8,9),U+7B7F(4,8) +U+7BE1(0);U+7BE1(5,9);U+7C12(2,8) +U+7BE2(0);U+7BE2(0,9); +U+7BE3(0);U+7BE3(0,9); +U+7BE4(0);U+7BE4(0,9);U+7B03(1,3,8) +U+7BE5(0);U+7BE5(5,9); +U+7BE6(0);U+7BE6(5,9); +U+7BE7(0);U+7BE7(0,9); +U+7BE8(0);U+7BE8(0,9); +U+7BE9(0);U+7BE9(0,9);U+7B5B(1,3,8) +U+7BEA(0);U+7BEA(5,9);U+7AFE(3,8),U+7B8E(3,9) +U+7BEB(0);U+7BEB(0,9); +U+7BEC(0);U+7BEC(0); +U+7BED(0);U+7C60(4,8,9);U+7B3C(4),U+7C60(4,8,9) +U+7BEE(0);U+7C43(1,3,8,9);U+7C43(1,3,8,9) +U+7BEF(0);U+7C5B(4,8,9);U+7C5B(4,8,9) +U+7BF0(0);U+7BF0(0,9); +U+7BF1(0);U+7C6C(1,3,8,9);U+7B63(3,9),U+7C6C(1,3,8,9) +U+7BF2(0);U+7BF2(0,9);U+5F57(3,8,9) +U+7BF3(0);U+7BF3(0,9);U+7B5A(1,3,8) +U+7BF4(0);U+7BF4(0,9);U+7B1B(3,9) +U+7BF5(0);U+7BF5(0); +U+7BF6(0);U+7BF6(0); +U+7BF7(0);U+7BF7(5,9); +U+7BF8(0);U+7BF8(3,9); +U+7BF9(0);U+7BF9(0,9); +U+7BFB(0);U+7BFB(0,9); +U+7BFC(0);U+7BFC(5); +U+7BFD(0);U+7BFD(0,9);U+7C5E(4) +U+7BFE(0);U+7BFE(5,9); +U+7BFF(0);U+7BFF(0,9); + +U+7C00(0);U+7C00(0,9);U+7BA6(1,3,8) +U+7C01(0);U+7C01(0,9); +U+7C02(0);U+7C02(0,9); +U+7C03(0);U+7C03(0,9); +U+7C04(0);U+7C04(3); +U+7C05(0);U+7C05(0,9); +U+7C06(0);U+7C06(0,9);U+7B58(4,9) +U+7C07(0);U+7C07(5,9); +U+7C08(0);U+7BB3(3,8);U+7BB3(3,8) +U+7C09(0);U+7C09(0,9); +U+7C0A(0);U+7C0A(0,9); +U+7C0B(0);U+7C0B(5,9); +U+7C0C(0);U+7C0C(5,9); +U+7C0D(0);U+7C0D(0,9);U+7BD3(1,3,8) +U+7C0E(0);U+7C0E(4,9); +U+7C0F(0);U+7C0F(5,9); +U+7C10(0);U+7C10(0,9); +U+7C11(0);U+7C11(0,9);U+84D1(2,8,9) +U+7C12(0);U+7BE1(2,8,9);U+7BE1(2,8,9) +U+7C13(0);U+7C13(0); +U+7C15(0);U+7C15(0); +U+7C16(0);U+7C6A(1,3,8,9);U+7C6A(1,3,8,9) +U+7C17(0);U+7C17(0); +U+7C18(0);U+7C2B(4,8,9);U+7C2B(4,8,9),U+7BAB(4) +U+7C19(0);U+7C19(0,9); +U+7C1A(0);U+7C1A(0); +U+7C1C(0);U+7C1C(3,9); +U+7C1D(0);U+7C1D(0,9); +U+7C1E(0);U+7C1E(0,9);U+7BAA(1,3,8) +U+7C1F(0);U+7C1F(5,9); +U+7C20(0);U+7C20(3,9); +U+7C21(0);U+7C21(0,9);U+7B80(1,3,8) +U+7C22(0);U+7C22(0,9); +U+7C23(0);U+7C23(0,9);U+7BD1(1,3,8) +U+7C24(0);U+7C24(0); +U+7C25(0);U+7C25(0,9); +U+7C26(0);U+7C26(5,9); +U+7C27(0);U+7C27(5,9); +U+7C28(0);U+7C28(3,9); +U+7C29(0);U+7C29(0,9); +U+7C2A(0);U+7C2A(5,9); +U+7C2B(0);U+7C2B(0,9);U+7BAB(1,3,8),U+7C18(4,8) +U+7C2C(0);U+7C2C(3,9); +U+7C2D(0);U+7C2D(0,9); +U+7C30(0);U+7C30(0,9); +U+7C31(0);U+7C31(0); +U+7C32(0);U+7C32(0); +U+7C33(0);U+7C33(0,9); +U+7C34(0);U+7C34(0); +U+7C35(0);U+7C35(4); +U+7C36(0);U+7C36(0); +U+7C37(0);U+7C37(0,9);U+6A90(2,3,9) +U+7C38(0);U+7C38(5,9); +U+7C39(0);U+7C39(0,9);U+7B5C(4,8) +U+7C3A(0);U+7C3A(3); +U+7C3B(0);U+7C3B(0,9); +U+7C3C(0);U+7C3C(0,9);U+7BDD(3,9) +U+7C3D(0);U+7C3D(0,9);U+7B7E(1,3,8),U+7C64(3,4,9),U+7C56(1,3,4,8) +U+7C3E(0);U+7C3E(0,9);U+5E18(1,3,8,9) +U+7C3F(0);U+7C3F(5,9); +U+7C40(0);U+7C40(5,9); +U+7C41(0);U+7C5F(1,3,8,9);U+7C5F(1,3,8,9) +U+7C42(0);U+7C42(0); + +U+7C43(0);U+7C43(0,9);U+7BEE(1,3,8) +U+7C44(0);U+7C44(0); +U+7C45(0);U+7C45(0,9); +U+7C46(0);U+7C46(3); +U+7C47(0);U+7C47(0,9); +U+7C48(0);U+7C48(0,9); +U+7C49(0);U+7C49(0,9);U+53F0(4,9),U+6AAF(1,3,4,9),U+81FA(1,3,4,8,9),U+98B1(1,3,4,8,9) + +U+7C4A(0);U+7C4A(0,9); +U+7C4B(0);U+7C4B(0); +U+7C4C(0);U+7C4C(0,9);U+7B79(1,3,8) +U+7C4D(0);U+7C4D(5,9); +U+7C4E(0);U+7C4E(0); +U+7C50(0);U+7C50(3,9);U+7C58(3,8),U+85E4(2,3,9) +U+7C51(0);U+7C51(0); +U+7C53(0);U+7C53(0,9);U+85E9(3,9) +U+7C54(0);U+7C54(3,9);U+85EA(3,8,9),U+85AE(1,3,8) +U+7C56(0);U+7C64(8,9);U+7B7E(4),U+7C64(8,9),U+7C3D(1,3,4,8,9) +U+7C57(0);U+7C57(0,9); +U+7C58(0);U+7C50(3,8,9);U+7C50(3,8,9),U+85E4(7,9) +U+7C59(0);U+7C59(0,9);U+7B93(1,3,8) +U+7C5A(0);U+7C5A(3,9); +U+7C5B(0);U+7C5B(0,9);U+7BEF(4,8) +U+7C5C(0);U+7C5C(0,9);U+7BA8(1,3,8) +U+7C5E(0);U+7C5E(4);U+7BFD(4,9) +U+7C5F(0);U+7C5F(0,9);U+7C41(1,3,8) +U+7C60(0);U+7C60(0,9);U+7B3C(1,3,8),U+7BED(4,8) +U+7C61(0);U+7C61(0); +U+7C62(0);U+7C62(4); +U+7C63(0);U+7C63(0,9); +U+7C64(0);U+7C64(0,9);U+7C3D(3,4,9),U+7B7E(1,3,8),U+7C56(8) +U+7C65(0);U+7C65(0,9); +U+7C66(0);U+7C66(0,9); +U+7C67(0);U+7C67(0,9); +U+7C68(0);U+7C68(0); +U+7C69(0);U+7C69(0,9);U+7B3E(1,3,8) +U+7C6A(0);U+7C6A(0,9);U+7C16(1,3,8) +U+7C6B(0);U+7C6B(0,9); +U+7C6C(0);U+7C6C(0,9);U+7BF1(1,3,8,9),U+7B63(0,1,3,8,9) +U+7C6D(0);U+7C6D(0); +U+7C6E(0);U+7C6E(0,9);U+7BA9(1,3,8) +U+7C6F(0);U+7C6F(3,9); +U+7C70(0);U+7C70(4); +U+7C71(0);U+7C71(3); +U+7C72(0);U+7C72(0,9);U+5401(1,3,8,9) +U+7C73(0);U+7C73(5,9); +U+7C74(0);U+7CF4(1,3,8,9);U+7CF4(1,3,8,9) +U+7C75(0);U+7C75(0,9);U+8E6F(3,9),U+756A(3,5,8,9) +U+7C77(0);U+7C77(0); +U+7C78(0);U+7C78(3,9); +U+7C79(0);U+7C79(0,9); +U+7C7A(0);U+7C7A(3,9); +U+7C7B(0);U+985E(1,3,8,9);U+985E(1,3,8,9) +U+7C7C(0);U+79C8(2,3,8,9);U+79C8(2,3,8,9) +U+7C7D(0);U+7C7D(5,9); +U+7C7E(0);U+7C7E(0); +U+7C7F(0);U+7C7F(0,9); +U+7C80(0);U+7C80(0,9); +U+7C81(0);U+7C81(0,9); +U+7C82(0);U+7C82(0); +U+7C84(0);U+7C84(0,9); +U+7C85(0);U+7C85(0,9); +U+7C86(0);U+7C86(0); + +U+7C88(0);U+7C88(0,9);U+7CC5(3,9) +U+7C89(0);U+7C89(5,9); +U+7C8A(0);U+7C8A(0,9); +U+7C8B(0);U+7CB9(3,8,9);U+7CB9(3,8,9) +U+7C8C(0);U+7C8C(0,9); +U+7C8D(0);U+7C8D(0,9); +U+7C8E(0);U+7C8E(0); +U+7C8F(0);U+7C8F(0); +U+7C90(0);U+7C90(0); +U+7C91(0);U+7C91(5,9); +U+7C92(0);U+7C92(5,9); +U+7C94(0);U+7C94(0,9); +U+7C95(0);U+7C95(5,9); +U+7C96(0);U+7C96(0,9); +U+7C97(0);U+7C97(5,9);U+850D(3,9),U+89D5(2,3,9),U+9E81(4,8),U+9E84(3,8),U+9E86(3,9),U+9EA4(2,3,9) +U+7C98(0);U+7C98(5,9); +U+7C99(0);U+7C99(0); +U+7C9B(0);U+8085(3,8,9);U+8083(3),U+8085(3,8,9) +U+7C9C(0);U+7CF6(1,3,8,9);U+7CF6(1,3,8,9) +U+7C9D(0);U+7CF2(1,3,8,9);U+7CF2(1,3,8,9) +U+7C9E(0);U+7C9E(5,9); +U+7C9F(0);U+7C9F(5,9); +U+7CA0(0);U+7CA0(0); +U+7CA1(0);U+7CA1(0,9); +U+7CA2(0);U+7CA2(5,9);U+79F6(3,9) +U+7CA3(0);U+7CA3(0,9); +U+7CA4(0);U+7CB5(4,8,9);U+7CB5(4,8,9) +U+7CA5(0);U+7CA5(5,9);U+9B3B(3,8,9) +U+7CA6(0);U+7CA6(0); +U+7CA7(0);U+7CA7(4,9); +U+7CA8(0);U+7CA8(0,9); +U+7CA9(0);U+7CA9(0); +U+7CAA(0);U+7CDE(1,3,8,9);U+7CDE(1,3,8,9) +U+7CAD(0);U+7CAD(0); +U+7CAE(0);U+7CE7(1,3,4,8,9);U+7CE7(1,3,4,8,9) +U+7CAF(0);U+7CAF(0,9); +U+7CB0(0);U+7CB0(0); +U+7CB1(0);U+7CB1(5,9); +U+7CB2(0);U+7CB2(5,9); +U+7CB3(0);U+7CB3(5,9); +U+7CB4(0);U+7CB4(0,9); +U+7CB5(0);U+7CB5(0,9);U+7CA4(4,8) +U+7CB6(0);U+7CB6(0); +U+7CB7(0);U+7CB7(0); +U+7CB8(0);U+7CB8(0); +U+7CB9(0);U+7CB9(5,9);U+7C8B(3,8) +U+7CBA(0);U+7CBA(0,9);U+7A17(2,9) +U+7CBB(0);U+7CBB(0,9); +U+7CBC(0);U+7CBC(5,9); +U+7CBD(0);U+7CBD(5,9);U+7CC9(2,3),U+7CED(7,8) +U+7CBE(0);U+7CBE(5,9); +U+7CBF(0);U+7CBF(0,9); +U+7CC0(0);U+7CC0(0); +U+7CC1(0);U+7CDD(1,3,8,9);U+7CDD(1,3,8,9) +U+7CC2(0);U+7CC2(4); +U+7CC3(0);U+7CC3(0); +U+7CC4(0);U+7CC4(0); +U+7CC5(0);U+7CC5(5,9);U+7C88(3,9) +U+7CC6(0);U+7CC6(0); +U+7CC7(0);U+7CC7(5);U+9931(2,3,9) +U+7CC8(0);U+7CC8(5,9);U+7A30(3,9) +U+7CC9(0);U+7CBD(2,3,9);U+7CBD(2,3,9),U+7CED(2,3,7,8) + +U+7CCA(0);U+7CCA(5,9);U+992C(2,3,9) +U+7CCB(0);U+7CCB(0,9); +U+7CCC(0);U+7CCC(5,9); +U+7CCD(0);U+7CCD(5);U+9908(2,9) +U+7CCE(0);U+7CCE(0,9); +U+7CCF(0);U+7CCF(0); +U+7CD0(0);U+7CD0(0,9); +U+7CD1(0);U+7CD1(0,9); +U+7CD2(0);U+7CD2(0,9); +U+7CD4(0);U+7CD4(0,9); +U+7CD5(0);U+7CD5(5,9); +U+7CD6(0);U+7CD6(5,9);U+9939(2,3,8) +U+7CD7(0);U+7CD7(5,9); +U+7CD8(0);U+7CD8(0); +U+7CD9(0);U+7CD9(5,9); +U+7CDC(0);U+7CDC(5,9);U+7222(3,9) +U+7CDD(0);U+7CDD(0,9);U+7CC1(1,3,8) +U+7CDE(0);U+7CDE(0,9);U+7CAA(1,3,8) +U+7CDF(0);U+7CDF(5,9);U+8E67(2,9) +U+7CE0(0);U+7CE0(5,9);U+7A45(2,3,8) +U+7CE2(0);U+7CE2(0,9); +U+7CE4(0);U+7CE4(0);U+994A(3),U+9993(3,8) +U+7CE7(0);U+7CE7(0,9);U+7CAE(1,3,8) +U+7CE8(0);U+7CE8(5,9); +U+7CE9(0);U+7CE9(0); +U+7CEA(0);U+7CEA(0,9); +U+7CEB(0);U+7CEB(0); +U+7CEC(0);U+7CEC(0,9); +U+7CED(0);U+7CBD(7,8,9);U+7CBD(7,8,9),U+7CC9(2,3,7,8) +U+7CEE(0);U+7CEE(0,9); +U+7CEF(0);U+7CEF(5,9); +U+7CF0(0);U+7CF0(0,9);U+56E2(1,3),U+5718(4,9),U+56E3(1,3,4) +U+7CF1(0);U+7CF1(0,9);U+7CF5(4) +U+7CF2(0);U+7CF2(0,9);U+7C9D(1,3,8) +U+7CF3(0);U+7CF3(0); +U+7CF4(0);U+7CF4(0,9);U+7C74(1,3,8) +U+7CF5(0);U+7CF5(4);U+7CF1(4,9) +U+7CF6(0);U+7CF6(0,9);U+7C9C(1,3,8) +U+7CF7(0);U+7CF7(0,9); +U+7CF8(0);U+7CF8(5,9);U+7CF9(8),U+7D72(3,8,9),U+7E9F(8),U+4E1D(1,3,8) +U+7CF9(0);U+7CF8(8,9);U+7CF8(8,9),U+7E9F(4,8),U+7D72(3,8,9),U+4E1D(1,3,8) +U+7CFA(0);U+7CFE(2,3,8,9);U+7CFE(2,3,8,9),U+7EA0(4) +U+7CFB(0);U+7CFB(1,3,9),U+4FC2(1,3,4,8,9),U+7E6B(1,3,4,8,9);U+4FC2(1,3,4,8,9),U+7E6B(1,3,4,8,9) + +U+7CFD(0);U+7CFD(0,9); +U+7CFE(0);U+7CFE(0,9);U+7CFA(2,3,8),U+7EA0(1,3,8) +U+7D00(0);U+7D00(0,9);U+7EAA(1,3,8) +U+7D01(0);U+7D01(0,9);U+8869(4,9) +U+7D02(0);U+7D02(0,9);U+7EA3(1,3,8) +U+7D03(0);U+7D03(0,9); +U+7D04(0);U+7D04(0,9);U+7EA6(1,3,8) +U+7D05(0);U+7D05(0,9);U+7EA2(1,3,8) +U+7D06(0);U+7D06(0,9);U+7EA1(1,3,8) +U+7D07(0);U+7D07(0,9);U+7EA5(1,3,8) +U+7D08(0);U+7D08(0,9);U+7EA8(1,3,8) +U+7D09(0);U+7D09(0,9);U+7EAB(1,3,8) +U+7D0A(0);U+7D0A(5,9); +U+7D0B(0);U+7D0B(0,9);U+7EB9(1,3,8) +U+7D0C(0);U+7D0C(0,9); +U+7D0D(0);U+7D0D(0,9);U+7EB3(1,3,8) +U+7D0E(0);U+7D0E(0,9); +U+7D0F(0);U+7D0F(0,9); + +U+7D10(0);U+7D10(0,9);U+7EBD(1,3,8) +U+7D11(0);U+7D11(0,9); +U+7D12(0);U+7D12(0,9); +U+7D13(0);U+7D13(0,9);U+7EBE(1,3,8) +U+7D14(0);U+7D14(0,9);U+7EAF(1,3,8) +U+7D15(0);U+7D15(0,9);U+7EB0(1,3,8) +U+7D16(0);U+7D16(0,9);U+7EBC(1,3,8),U+7D7C(1,3,8,9) +U+7D17(0);U+7D17(0,9);U+7EB1(1,3,8) +U+7D18(0);U+7D18(0,9);U+7EAE(4,8) +U+7D19(0);U+7D19(0,9);U+5E0B(2,3,8),U+7EB8(1,3,8) +U+7D1A(0);U+7D1A(0,9);U+7EA7(1,3,8) +U+7D1B(0);U+7D1B(0,9);U+7EB7(1,3,8) +U+7D1C(0);U+7D1C(0,9);U+7EAD(1,3,8) +U+7D1D(0);U+7D1D(0,9);U+7EB4(1,3,8) +U+7D1E(0);U+7D1E(0,9); +U+7D1F(0);U+7D1F(0,9); +U+7D20(0);U+7D20(5,9);U+69A1(3,9) +U+7D21(0);U+7D21(0,9);U+7EBA(1,3,8) +U+7D22(0);U+7D22(5,9); +U+7D24(0);U+7D24(0); +U+7D25(0);U+7D2E(3,8,9);U+624E(2,9),U+7D2E(3,8,9),U+5273(0,2,4),U+5284(2,4,9),U+672D(2,3,4,9),U+7B9A(2,4) + +U+7D26(0);U+7D26(0); +U+7D27(0);U+7DCA(1,3,8,9);U+7DCA(1,3,8,9) +U+7D28(0);U+7D28(0,9); +U+7D29(0);U+7D29(0,9); +U+7D2B(0);U+7D2B(5,9); +U+7D2C(0);U+7D2C(0,9);U+4337(1,3),U+7EF8(4),U+7DA2(1,3,4,8,9) +U+7D2E(0);U+7D2E(0,9);U+624E(2,8,9),U+7D25(3,8),U+5273(0,2,4,8),U+5284(2,4,8,9),U+672D(2,3,4,8,9),U+7B9A(2,4,8) + +U+7D2F(0);U+7D2F(1,3,9),U+7E8D(1,3,8,9);U+7D6B(3,9),U+7E8D(1,3,8,9) +U+7D30(0);U+7D30(0,9);U+7EC6(1,3,8) +U+7D31(0);U+7D31(0,9);U+7EC2(1,3,8) +U+7D32(0);U+7D32(0,9);U+7D4F(2,8,9),U+7EC1(1,3,8) +U+7D33(0);U+7D33(0,9);U+7EC5(1,3,8) +U+7D34(0);U+7D34(0); +U+7D35(0);U+7D35(0,9);U+7EBB(4,8) +U+7D36(0);U+7D36(0,9); +U+7D37(0);U+7D37(0); +U+7D38(0);U+7D38(0,9); +U+7D39(0);U+7D39(0,9);U+7ECD(1,3,8) +U+7D3A(0);U+7D3A(0,9);U+7EC0(1,3,8) +U+7D3B(0);U+7D3B(0,9); +U+7D3C(0);U+7D3C(0,9);U+7ECB(1,3,8),U+7D8D(1,3,8,9) +U+7D3D(0);U+7D3D(0,9); +U+7D3E(0);U+7D3E(0,9); +U+7D3F(0);U+7D3F(0,9);U+7ED0(1,3,8) +U+7D40(0);U+7D40(0,9);U+7ECC(1,3,8) +U+7D41(0);U+7D41(0,9); +U+7D42(0);U+7D42(0,9);U+7EC8(1,3,8) +U+7D43(0);U+7D43(0,9);U+5F26(2,8,9) +U+7D44(0);U+7D44(0,9);U+7EC4(1,3,8) +U+7D45(0);U+7D45(3,9); +U+7D46(0);U+7D46(0,9);U+7ECA(1,3,8) +U+7D47(0);U+7D47(3,9); +U+7D49(0);U+7D49(0); +U+7D4A(0);U+7D4A(0,9); +U+7D4B(0);U+7E8A(4,8,9);U+7E8A(4,8,9),U+7EA9(4),U+7D56(3,4,8,9) +U+7D4C(0);U+7D93(4,8,9);U+7D93(4,8,9),U+7ECF(4) +U+7D4E(0);U+7D4E(0,9);U+7ED7(1,3,8) +U+7D4F(0);U+7D4F(0,9);U+7D32(2,8,9),U+7EC1(2,3) +U+7D50(0);U+7D50(0,9);U+7ED3(1,3,8) +U+7D51(0);U+7D51(0,9); + +U+7D52(0);U+7D52(0,9); +U+7D53(0);U+7D53(0,9); +U+7D54(0);U+7D54(0,9); +U+7D55(0);U+7D55(0,9);U+7D76(8),U+7EDD(4,8) +U+7D56(0);U+7D56(0,9);U+7E8A(3,8,9),U+7EA9(3),U+7D4B(0,3,4,8) +U+7D57(0);U+7D57(0); +U+7D58(0);U+7D58(0,9); +U+7D59(0);U+7D59(4); +U+7D5B(0);U+7D5B(0,9);U+7EE6(4),U+7E1A(4,9),U+7E27(1,3,4,8) +U+7D5C(0);U+7D5C(3,9); +U+7D5D(0);U+7D5D(0);U+7ED4(1,3,8) +U+7D5E(0);U+7D5E(0,9);U+7EDE(1,3,8) +U+7D5F(0);U+7D5F(0,9); +U+7D60(0);U+7D60(0); +U+7D61(0);U+7D61(0,9);U+7EDC(1,3,8) +U+7D62(0);U+7D62(0,9);U+7EDA(1,3,8) +U+7D63(0);U+7D63(0,9); +U+7D65(0);U+7D65(0); +U+7D66(0);U+7D66(0,9);U+7ED9(1,3,8) +U+7D67(0);U+7D67(0,9); +U+7D68(0);U+7D68(0,9);U+7ED2(1,3,8),U+6BE7(0,1,2,3,8,9),U+7FA2(1,2,3,8,9) +U+7D69(0);U+7D69(0,9); +U+7D6A(0);U+7D6A(0,9); +U+7D6B(0);U+7D6B(0,9);U+7D2F(3,9),U+7E8D(1,3,8,9) +U+7D6C(0);U+7D6C(0); +U+7D6D(0);U+7D6D(3,9); +U+7D6E(0);U+7D6E(5,9); +U+7D6F(0);U+7D6F(0,9); +U+7D70(0);U+7D70(0,9);U+7ED6(1,3,8) +U+7D71(0);U+7D71(0,9);U+7EDF(1,3,8) +U+7D72(0);U+7D72(0,9);U+4E1D(1,3,8),U+7CF8(3,8,9),U+7CF9(3,8),U+7E9F(3,8) +U+7D73(0);U+7D73(0,9);U+7EDB(1,3,8) +U+7D74(0);U+7D74(0); +U+7D75(0);U+7E6A(4,8,9);U+7E6A(4,8,9),U+7ED8(4),U+7E62(3,4,8,9),U+7F0B(0,3,4,8) +U+7D76(0);U+7D55(8,9);U+7D55(8,9),U+7EDD(1,3,8) +U+7D77(0);U+7E36(1,3,8,9);U+7E36(1,3,8,9),U+99BD(3,9) +U+7D79(0);U+7D79(0,9);U+7EE2(1,3,8) +U+7D7A(0);U+7D7A(0,9); +U+7D7B(0);U+7D7B(0,9); +U+7D7C(0);U+7D7C(0,9);U+7EBC(3),U+7D16(0,1,3,8,9) +U+7D7D(0);U+7D7D(0,9); +U+7D7E(0);U+7D7E(0); +U+7D7F(0);U+7D7F(0,9); +U+7D80(0);U+7D80(0,9); +U+7D81(0);U+7D81(0,9);U+7ED1(1,3,8) +U+7D83(0);U+7D83(0,9);U+7EE1(1,3,8) +U+7D84(0);U+7D84(0,9); +U+7D85(0);U+7D85(0,9); +U+7D86(0);U+7D86(0,9);U+7EE0(1,3,8) +U+7D87(0);U+7D87(0); +U+7D88(0);U+7D88(0,9);U+7EE8(1,3,8) +U+7D89(0);U+7E61(2,3,8,9);U+7E61(2,3,8,9),U+7EE3(1,3,8),U+7E4D(2,3,8) +U+7D8A(0);U+7D8A(0); +U+7D8B(0);U+7D8B(0); +U+7D8C(0);U+7D8C(0,9);U+7EE4(4,8) +U+7D8D(0);U+7D8D(0,9);U+7ECB(3),U+7D3C(0,1,3,8,9) +U+7D8E(0);U+7D8E(0,9); +U+7D8F(0);U+7D8F(0,9);U+7EE5(1,3,8),U+7DCC(1,3,4,8,9) +U+7D90(0);U+7D90(0); +U+7D91(0);U+7D91(0,9);U+6346(2,3,8,9) +U+7D92(0);U+7D92(0,9); +U+7D93(0);U+7D93(0,9);U+7D4C(4,8),U+7ECF(1,3,8) +U+7D94(0);U+7D94(0,9); + +U+7D96(0);U+7D96(0,9); +U+7D97(0);U+7D97(0); +U+7D99(0);U+7E7C(3,8,9);U+7E7C(3,8,9),U+7EE7(3) +U+7D9B(0);U+7D9B(0); +U+7D9C(0);U+7D9C(0,9);U+7EFC(1,3,8) +U+7D9D(0);U+7D9D(0,9); +U+7D9E(0);U+7D9E(0,9);U+7F0D(4,8) +U+7D9F(0);U+7D9F(0,9); +U+7DA0(0);U+7DA0(0,9);U+7DD1(8),U+7EFF(4,8) +U+7DA1(0);U+7DA1(0,9); +U+7DA2(0);U+7DA2(0,9);U+7EF8(1,3,8),U+4337(1,3,4,8),U+7D2C(0,1,3,4,8,9) +U+7DA3(0);U+7DA3(0,9);U+7EFB(1,3,8) +U+7DA5(0);U+7DA5(3); +U+7DA6(0);U+7DA6(5,9); +U+7DA7(0);U+7DA7(0,9); +U+7DA9(0);U+7DA9(0,9); +U+7DAA(0);U+7DAA(0,9); +U+7DAB(0);U+7DDA(2,3,8,9);U+7DDA(2,3,8,9),U+7EBF(1,3,8),U+7F10(2,3,4,8) +U+7DAC(0);U+7DAC(0,9);U+7EF6(1,3,8) +U+7DAD(0);U+7DAD(0,9);U+7EF4(1,3,8) +U+7DAE(0);U+7DAE(5,9);U+68E8(4,9) +U+7DAF(0);U+7DAF(0,9);U+7EF9(4,8) +U+7DB0(0);U+7DB0(0,9);U+7EFE(1,3,8) +U+7DB1(0);U+7DB1(0,9);U+7EB2(1,3,8) +U+7DB2(0);U+7DB2(0,9);U+7F51(1,3,8,9) +U+7DB3(0);U+7E43(2,3,8,9);U+7E43(2,3,8,9),U+7EF7(1,3,8) +U+7DB4(0);U+7DB4(0,9);U+7F00(1,3,8) +U+7DB5(0);U+7DB5(0,9);U+5F69(2,9) +U+7DB6(0);U+7DB6(0); +U+7DB7(0);U+7DB7(3,9); +U+7DB8(0);U+7DB8(0,9);U+7EB6(1,3,8) +U+7DB9(0);U+7DB9(0,9);U+7EFA(1,3,8) +U+7DBA(0);U+7DBA(0,9);U+7EEE(1,3,8) +U+7DBB(0);U+7DBB(0,9);U+7EFD(1,3,8) +U+7DBC(0);U+7DBC(0,9); +U+7DBD(0);U+7DBD(0,9);U+7EF0(1,3,8) +U+7DBE(0);U+7DBE(0,9);U+7EEB(1,3,8) +U+7DBF(0);U+7DBF(0,9);U+7EF5(1,3,8) +U+7DC0(0);U+7DC0(3,9); +U+7DC1(0);U+7DC1(0,9); +U+7DC2(0);U+7DC2(0,9); +U+7DC3(0);U+7DC3(0); +U+7DC4(0);U+7DC4(0,9);U+7EF2(1,3,8) +U+7DC5(0);U+7DC5(0,9); +U+7DC6(0);U+7DC6(0,9); +U+7DC7(0);U+7DC7(0,9);U+7F01(1,3,8) +U+7DC8(0);U+7DC8(0); +U+7DC9(0);U+7DC9(0,9); +U+7DCA(0);U+7DCA(0,9);U+7D27(1,3,8) +U+7DCB(0);U+7DCB(0,9);U+7EEF(1,3,8) +U+7DCC(0);U+7DCC(0,9);U+7EE5(4),U+7D8F(0,1,3,4,8,9) +U+7DCE(0);U+7DCE(0,9); +U+7DCF(0);U+7E3D(3,8,9);U+603B(3),U+7E3D(3,8,9),U+6374(3,4),U+6403(3),U+6460(3,9),U+7E02(3,4) + +U+7DD0(0);U+7E41(2,8,9);U+7E41(2,8,9) +U+7DD1(0);U+7DA0(8,9);U+7DA0(8,9),U+7EFF(1,3,8) +U+7DD2(0);U+7DD2(0,9);U+7DD6(4,8),U+7EEA(1,3,8) +U+7DD4(0);U+7DD4(0);U+7EF1(4,8) +U+7DD5(0);U+7DD5(0); +U+7DD6(0);U+7DD2(4,8,9);U+7DD2(4,8,9),U+7EEA(4) +U+7DD7(0);U+7DD7(0,9);U+7F03(1,3,8) +U+7DD8(0);U+7DD8(0,9);U+7F04(1,3,8) +U+7DD9(0);U+7DD9(0,9);U+7F02(1,3,8) + +U+7DDA(0);U+7DDA(0,9);U+7DAB(2,3,8),U+7EBF(4,8),U+7F10(4,8) +U+7DDB(0);U+7DDB(0,9); +U+7DDD(0);U+7DDD(0,9);U+7F09(1,3,8) +U+7DDE(0);U+7DDE(0,9);U+7F0E(1,3,8) +U+7DDF(0);U+7DDF(0,9);U+91CD(3,9) +U+7DE0(0);U+7DE0(0,9);U+7F14(1,3,8) +U+7DE1(0);U+7DE1(0,9);U+7F17(1,3,8) +U+7DE2(0);U+7DE2(0); +U+7DE3(0);U+7DE3(0,9);U+7E01(4,8),U+7F18(1,3,8) +U+7DE6(0);U+7DE6(0,9);U+7F0C(1,3,8) +U+7DE7(0);U+7DE7(0,9); +U+7DE8(0);U+7DE8(0,9);U+7F16(1,3,8) +U+7DE9(0);U+7DE9(0,9);U+7F13(1,3,8) +U+7DEA(0);U+7DEA(0,9);U+7E06(3) +U+7DEC(0);U+7DEC(0,9);U+7F05(1,3,8) +U+7DED(0);U+7DED(0); +U+7DEE(0);U+7DEE(0,9); +U+7DEF(0);U+7DEF(0,9);U+7EAC(1,3,8) +U+7DF0(0);U+7DF0(0,9); +U+7DF1(0);U+7DF1(0,9);U+7F11(1,3,8) +U+7DF2(0);U+7DF2(0,9);U+7F08(1,3,8) +U+7DF3(0);U+7DF3(0,9); +U+7DF4(0);U+7DF4(0,9);U+7EC3(1,3,8) +U+7DF5(0);U+7DF5(0); +U+7DF6(0);U+7DF6(0,9);U+7F0F(4,8) +U+7DF7(0);U+7DF7(0,9);U+886E(3),U+889E(3,8,9) +U+7DF8(0);U+7DF8(0); +U+7DF9(0);U+7DF9(0,9);U+7F07(1,3,8) +U+7DFA(0);U+7DFA(0,9); +U+7DFB(0);U+7DFB(0,9);U+81F4(1,3,8,9) +U+7DFC(0);U+7E15(3,8,9);U+7E15(3,8,9),U+7F0A(1,3),U+891E(1,3,4,9) +U+7E00(0);U+7E00(0); +U+7E01(0);U+7DE3(4,8,9);U+7DE3(4,8,9),U+7F18(4) +U+7E02(0);U+7E3D(4,8,9);U+603B(4),U+7E3D(4,8,9),U+6374(4),U+6403(3,4),U+6460(3,4,9),U+7DCF(3,4) +U+7E03(0);U+7E03(0,9);U+80E5(3,9) +U+7E04(0);U+7E69(3,8,9);U+7E69(3,8,9),U+7EF3(3) +U+7E05(0);U+7E05(0); +U+7E06(0);U+7DEA(3,9);U+7DEA(3,9) +U+7E07(0);U+7E07(0); +U+7E08(0);U+7E08(0,9);U+8426(1,3,8) +U+7E09(0);U+7E09(0,9);U+7F19(1,3,8) +U+7E0A(0);U+7E0A(0,9);U+7F22(1,3,8) +U+7E0B(0);U+7E0B(0,9);U+7F12(1,3,8) +U+7E0C(0);U+7E0C(0,9); +U+7E0D(0);U+7E0D(0,9);U+5E2E(3),U+5E47(3,4),U+5E5A(3),U+5E6B(1,3,4,8,9),U+97A4(3,4,9) + +U+7E0E(0);U+7E0E(0,9); +U+7E0F(0);U+7E0F(0,9); +U+7E10(0);U+7E10(0,9);U+7EC9(1,3,8) +U+7E11(0);U+7E11(0,9);U+7F23(1,3,8) +U+7E12(0);U+7E12(0,9); +U+7E13(0);U+7E13(0,9); +U+7E14(0);U+7E14(0,9); +U+7E15(0);U+7E15(0,9);U+7DFC(3,8),U+7F0A(4,8),U+891E(1,3,4,8,9) +U+7E16(0);U+7E16(0,9); +U+7E17(0);U+7E17(0,9);U+7F1E(1,3,8) +U+7E19(0);U+7E19(0); +U+7E1A(0);U+7E1A(0,9);U+7EE6(2,4),U+7D5B(0,4,9),U+7E27(1,3,4,8) +U+7E1B(0);U+7E1B(0,9);U+7F1A(1,3,8) +U+7E1C(0);U+7E1C(0,9); +U+7E1D(0);U+7E1D(0,9);U+7F1C(1,3,8) +U+7E1E(0);U+7E1E(0,9);U+7F1F(1,3,8) + +U+7E1F(0);U+7E1F(0,9);U+7F1B(1,3,8) +U+7E20(0);U+7E20(0,9); +U+7E21(0);U+7E21(0,9); +U+7E22(0);U+7E22(0,9); +U+7E23(0);U+7E23(0,9);U+53BF(1,3,8) +U+7E24(0);U+7E24(0,9); +U+7E25(0);U+7E25(0,9); +U+7E26(0);U+7E31(3,8,9);U+7E31(3,8,9),U+7EB5(3) +U+7E27(0);U+7E27(0);U+7EE6(1,3,8),U+7D5B(0,1,3,4,8,9),U+7E1A(1,3,4,8,9) +U+7E28(0);U+7E28(0); +U+7E29(0);U+7E29(0,9); +U+7E2A(0);U+7E2A(3,9); +U+7E2B(0);U+7E2B(0,9);U+7F1D(1,3,8) +U+7E2C(0);U+7E2C(3); +U+7E2D(0);U+7E2D(0,9);U+7F21(1,3,8),U+8935(1,3,8,9) +U+7E2E(0);U+7E2E(0,9);U+7F29(1,3,8),U+644D(0,1,3,4,8,9) +U+7E2F(0);U+7E2F(0,9); +U+7E30(0);U+7E30(0,9); +U+7E31(0);U+7E31(0,9);U+7E26(3,8),U+7EB5(1,3,8) +U+7E32(0);U+7E32(0,9);U+7F27(1,3,8) +U+7E33(0);U+7E33(0,9); +U+7E34(0);U+7E34(0,9);U+7EA4(1,3,8),U+5B45(0,1,3,8,9),U+7E8E(1,3,8),U+7E96(1,3,8,9) +U+7E35(0);U+7E35(0,9);U+7F26(1,3,8) +U+7E36(0);U+7E36(0,9);U+7D77(1,3,8),U+99BD(1,3,8,9) +U+7E37(0);U+7E37(0,9);U+7F15(1,3,8) +U+7E38(0);U+7E38(0,9); +U+7E39(0);U+7E39(0,9);U+7F25(1,3,8) +U+7E3A(0);U+7E3A(0,9); +U+7E3B(0);U+7E3B(5,9); +U+7E3C(0);U+7E3C(0,9); +U+7E3D(0);U+7E3D(0,9);U+603B(1,3,8),U+6374(4,8),U+6403(3,8),U+7DCF(3,8),U+7E02(4,8),U+6460(1,3,8,9) +U+7E3E(0);U+7E3E(0,9);U+7EE9(1,3,8),U+52E3(0,1,3,4,8,9) +U+7E3F(0);U+7E3F(3,9); +U+7E40(0);U+7E40(0,9); +U+7E41(0);U+7E41(5,9);U+7DD0(2,8) +U+7E42(0);U+7E42(0,9); +U+7E43(0);U+7E43(0,9);U+7DB3(2,3,8),U+7EF7(4,8) +U+7E44(0);U+7E44(0,9); +U+7E45(0);U+7E45(0,9);U+7F2B(1,3,8) +U+7E46(0);U+7E46(0,9);U+7F2A(1,3,8) +U+7E47(0);U+7E47(5,9); +U+7E48(0);U+7E48(0,9);U+7E66(4,8) +U+7E49(0);U+7E49(0,9); +U+7E4C(0);U+7E4C(0,9); +U+7E4D(0);U+7E61(8,9);U+7E61(8,9),U+7EE3(4),U+7D89(0,2,3,8) +U+7E4E(0);U+7E4E(0); +U+7E4F(0);U+7E4F(0); +U+7E50(0);U+7E50(0,9); +U+7E51(0);U+7E51(4,9); +U+7E52(0);U+7E52(0,9);U+7F2F(1,3,8) +U+7E53(0);U+7E53(0,9); +U+7E54(0);U+7E54(0,9);U+7EC7(1,3,8) +U+7E55(0);U+7E55(0,9);U+7F2E(1,3,8) +U+7E56(0);U+7E56(0,9);U+4F1E(4),U+5098(1,3,4,8,9) +U+7E57(0);U+7E57(0,9); +U+7E58(0);U+7E58(0,9); +U+7E59(0);U+7E59(0,9);U+7FFB(2,3,8,9),U+98DC(2,3,8) +U+7E5A(0);U+7E5A(0,9);U+7F2D(1,3,8) +U+7E5C(0);U+7E5C(0,9); +U+7E5D(0);U+7E5D(0); +U+7E5E(0);U+7E5E(0,9);U+7ED5(1,3,8),U+9076(1,3,4,8,9) +U+7E5F(0);U+7E5F(0,9); + +U+7E60(0);U+7E60(3,9); +U+7E61(0);U+7E61(0,9);U+7D89(2,3,8),U+7E4D(8),U+7EE3(4,8) +U+7E62(0);U+7E62(0,9);U+7E6A(3,8,9),U+7F0B(4,8),U+7D75(0,3,4,8),U+7ED8(3,4,8) +U+7E63(0);U+7E63(0,9); +U+7E65(0);U+7E65(0); +U+7E66(0);U+7E48(4,8,9);U+7E48(4,8,9) +U+7E67(0);U+7E67(0); +U+7E68(0);U+7E68(0,9); +U+7E69(0);U+7E69(0,9);U+7E04(3,8),U+7EF3(1,3,8) +U+7E6A(0);U+7E6A(0,9);U+7D75(4,8),U+7E62(3,8,9),U+7ED8(1,3,8),U+7F0B(3,4,8) +U+7E6B(0);U+7E6B(0,9);U+7CFB(1,3,8,9),U+4FC2(0,1,3,4,8,9) +U+7E6C(0);U+7E6C(0); +U+7E6D(0);U+7E6D(0,9);U+8327(1,3,8,9) +U+7E6E(0);U+7E6E(0);U+7F30(1,3,8),U+97C1(1,3,4,8,9) +U+7E6F(0);U+7E6F(0,9);U+7F33(1,3,8) +U+7E70(0);U+7E70(0,9);U+7F32(1,3,8) +U+7E71(0);U+7E71(0); +U+7E72(0);U+7E72(0,9); +U+7E73(0);U+7E73(0,9);U+7F34(1,3,8) +U+7E74(0);U+7E74(0,9); +U+7E75(0);U+7E75(0,9); +U+7E76(0);U+7E76(0,9); +U+7E77(0);U+7E77(0,9); +U+7E78(0);U+7E78(0,9); +U+7E79(0);U+7E79(0,9);U+7ECE(1,3,8) +U+7E7A(0);U+7E7A(0,9); +U+7E7B(0);U+7E7B(0,9); +U+7E7C(0);U+7E7C(0,9);U+7D99(3,8),U+7EE7(1,3,8) +U+7E7D(0);U+7E7D(0,9);U+7F24(1,3,8) +U+7E7E(0);U+7E7E(0,9);U+7F31(1,3,8) +U+7E7F(0);U+8964(3,8,9);U+8934(3),U+8964(3,8,9) +U+7E80(0);U+7E80(3,9); +U+7E81(0);U+7E81(0,9); +U+7E82(0);U+7E82(5,9); +U+7E83(0);U+7E83(0); +U+7E84(0);U+7E84(0); +U+7E85(0);U+7E85(0); +U+7E86(0);U+7E86(0,9); +U+7E87(0);U+7E87(0,9);U+98A3(4,8) +U+7E88(0);U+7E88(0,9);U+7F2C(1,3,8) +U+7E89(0);U+7E98(3,8,9);U+7E98(3,8,9),U+7F35(3) +U+7E8A(0);U+7E8A(0,9);U+7D4B(4,8),U+7D56(3,8,9),U+7EA9(1,3,8) +U+7E8B(0);U+7E8B(0,9); +U+7E8C(0);U+7E8C(0,9);U+7EED(1,3,8) +U+7E8D(0);U+7E8D(0,9);U+7D2F(1,3,8,9),U+7D6B(1,3,8,9) +U+7E8E(0);U+7E96(3,8,9);U+7E96(3,8,9),U+7EA4(3),U+5B45(0,3,9),U+7E34(1,3,8,9) +U+7E8F(0);U+7E8F(0,9);U+7E92(3,8),U+7F20(1,3,8) +U+7E90(0);U+7E90(0); +U+7E91(0);U+7E91(0,9); +U+7E92(0);U+7E8F(3,8,9);U+7E8F(3,8,9),U+7F20(3) +U+7E93(0);U+7E93(0,9);U+7F28(1,3,8) +U+7E94(0);U+7E94(0,9);U+624D(1,3,9) +U+7E95(0);U+7E95(0,9); +U+7E96(0);U+7E96(0,9);U+7E8E(3,8),U+7EA4(1,3,8),U+5B45(0,1,3,8,9),U+7E34(1,3,8,9) +U+7E97(0);U+7E97(0,9); +U+7E98(0);U+7E98(0,9);U+7E89(3,8),U+7F35(1,3,8) +U+7E99(0);U+7E99(0,9); +U+7E9A(0);U+7E9A(0,9); +U+7E9B(0);U+7E9B(5,9);U+7FE2(3,9) +U+7E9C(0);U+7E9C(0,9);U+7F06(1,3,8) +U+7E9E(0);U+7E9E(0); +U+7E9F(0);U+7CF8(8,9);U+7CF8(8,9),U+7CF9(4,8),U+7D72(3,8,9),U+4E1D(1,3,8) +U+7EA0(0);U+7CFE(1,3,8,9);U+7CFA(4),U+7CFE(1,3,8,9) + +U+7EA1(0);U+7D06(1,3,8,9);U+7D06(1,3,8,9) +U+7EA2(0);U+7D05(1,3,8,9);U+7D05(1,3,8,9) +U+7EA3(0);U+7D02(1,3,8,9);U+7D02(1,3,8,9) +U+7EA4(0);U+7E96(1,3,8,9);U+5B45(3,9),U+7E34(1,3,8,9),U+7E8E(3),U+7E96(1,3,8,9) +U+7EA5(0);U+7D07(1,3,8,9);U+7D07(1,3,8,9) +U+7EA6(0);U+7D04(1,3,8,9);U+7D04(1,3,8,9) +U+7EA7(0);U+7D1A(1,3,8,9);U+7D1A(1,3,8,9) +U+7EA8(0);U+7D08(1,3,8,9);U+7D08(1,3,8,9) +U+7EA9(0);U+7E8A(1,3,8,9);U+7D4B(4),U+7D56(3,9),U+7E8A(1,3,8,9) +U+7EAA(0);U+7D00(1,3,8,9);U+7D00(1,3,8,9) +U+7EAB(0);U+7D09(1,3,8,9);U+7D09(1,3,8,9) +U+7EAC(0);U+7DEF(1,3,8,9);U+7DEF(1,3,8,9) +U+7EAD(0);U+7D1C(1,3,8,9);U+7D1C(1,3,8,9) +U+7EAE(0);U+7D18(4,8,9);U+7D18(4,8,9) +U+7EAF(0);U+7D14(1,3,8,9);U+7D14(1,3,8,9) +U+7EB0(0);U+7D15(1,3,8,9);U+7D15(1,3,8,9) +U+7EB1(0);U+7D17(1,3,8,9);U+7D17(1,3,8,9) +U+7EB2(0);U+7DB1(1,3,8,9);U+7DB1(1,3,8,9) +U+7EB3(0);U+7D0D(1,3,8,9);U+7D0D(1,3,8,9) +U+7EB4(0);U+7D1D(1,3,8,9);U+7D1D(1,3,8,9) +U+7EB5(0);U+7E31(1,3,8,9);U+7E26(3),U+7E31(1,3,8,9) +U+7EB6(0);U+7DB8(1,3,8,9);U+7DB8(1,3,8,9) +U+7EB7(0);U+7D1B(1,3,8,9);U+7D1B(1,3,8,9) +U+7EB8(0);U+7D19(1,3,8,9);U+5E0B(4),U+7D19(1,3,8,9) +U+7EB9(0);U+7D0B(1,3,8,9);U+7D0B(1,3,8,9) +U+7EBA(0);U+7D21(1,3,8,9);U+7D21(1,3,8,9) +U+7EBB(0);U+7D35(4,8,9);U+7D35(4,8,9) +U+7EBC(0);U+7D16(1,3,8,9);U+7D16(1,3,8,9),U+7D7C(3,9) +U+7EBD(0);U+7D10(1,3,8,9);U+7D10(1,3,8,9) +U+7EBE(0);U+7D13(1,3,8,9);U+7D13(1,3,8,9) +U+7EBF(0);U+7DDA(4,8,9);U+7DAB(1,3,8),U+7DDA(4,8,9),U+7F10(4) +U+7EC0(0);U+7D3A(1,3,8,9);U+7D3A(1,3,8,9) +U+7EC1(0);U+7D32(1,3,8,9);U+7D32(1,3,8,9),U+7D4F(2,3,9) +U+7EC2(0);U+7D31(1,3,8,9);U+7D31(1,3,8,9) +U+7EC3(0);U+7DF4(1,3,8,9);U+7DF4(1,3,8,9) +U+7EC4(0);U+7D44(1,3,8,9);U+7D44(1,3,8,9) +U+7EC5(0);U+7D33(1,3,8,9);U+7D33(1,3,8,9) +U+7EC6(0);U+7D30(1,3,8,9);U+7D30(1,3,8,9) +U+7EC7(0);U+7E54(1,3,8,9);U+7E54(1,3,8,9) +U+7EC8(0);U+7D42(1,3,8,9);U+7D42(1,3,8,9) +U+7EC9(0);U+7E10(1,3,8,9);U+7E10(1,3,8,9) +U+7ECA(0);U+7D46(1,3,8,9);U+7D46(1,3,8,9) +U+7ECB(0);U+7D3C(1,3,8,9);U+7D3C(1,3,8,9),U+7D8D(3,9) +U+7ECC(0);U+7D40(1,3,8,9);U+7D40(1,3,8,9) +U+7ECD(0);U+7D39(1,3,8,9);U+7D39(1,3,8,9) +U+7ECE(0);U+7E79(1,3,8,9);U+7E79(1,3,8,9) +U+7ECF(0);U+7D93(1,3,8,9);U+7D4C(4),U+7D93(1,3,8,9) +U+7ED0(0);U+7D3F(1,3,8,9);U+7D3F(1,3,8,9) +U+7ED1(0);U+7D81(1,3,8,9);U+7D81(1,3,8,9) +U+7ED2(0);U+7D68(1,3,8,9);U+6BE7(2,9),U+7D68(1,3,8,9),U+7FA2(2,9) +U+7ED3(0);U+7D50(1,3,8,9);U+7D50(1,3,8,9) +U+7ED4(0);U+7D5D(1,3,8);U+7D5D(1,3,8) +U+7ED5(0);U+7E5E(1,3,8,9);U+7E5E(1,3,8,9),U+9076(4,9) +U+7ED6(0);U+7D70(1,3,8,9);U+7D70(1,3,8,9) +U+7ED7(0);U+7D4E(1,3,8,9);U+7D4E(1,3,8,9) +U+7ED8(0);U+7E6A(1,3,8,9);U+7D75(4),U+7E6A(1,3,8,9),U+7E62(3,4,8,9),U+7F0B(3,4,8) +U+7ED9(0);U+7D66(1,3,8,9);U+7D66(1,3,8,9) +U+7EDA(0);U+7D62(1,3,8,9);U+7D62(1,3,8,9) +U+7EDB(0);U+7D73(1,3,8,9);U+7D73(1,3,8,9) +U+7EDC(0);U+7D61(1,3,8,9);U+7D61(1,3,8,9) +U+7EDD(0);U+7D55(4,8,9);U+7D55(4,8,9),U+7D76(1,3,8) +U+7EDE(0);U+7D5E(1,3,8,9);U+7D5E(1,3,8,9) +U+7EDF(0);U+7D71(1,3,8,9);U+7D71(1,3,8,9) + +U+7EE0(0);U+7D86(1,3,8,9);U+7D86(1,3,8,9) +U+7EE1(0);U+7D83(1,3,8,9);U+7D83(1,3,8,9) +U+7EE2(0);U+7D79(1,3,8,9);U+7D79(1,3,8,9) +U+7EE3(0);U+7E61(4,8,9);U+7D89(1,3,8),U+7E4D(4),U+7E61(4,8,9) +U+7EE4(0);U+7D8C(4,8,9);U+7D8C(4,8,9) +U+7EE5(0);U+7D8F(1,3,8,9);U+7D8F(1,3,8,9),U+7DCC(4,9) +U+7EE6(0);U+7E27(1,3,8);U+7D5B(4,9),U+7E1A(4,9),U+7E27(1,3,8) +U+7EE7(0);U+7E7C(1,3,8,9);U+7D99(3),U+7E7C(1,3,8,9) +U+7EE8(0);U+7D88(1,3,8,9);U+7D88(1,3,8,9) +U+7EE9(0);U+7E3E(1,3,8,9);U+52E3(4,9),U+7E3E(1,3,8,9) +U+7EEA(0);U+7DD2(1,3,8,9);U+7DD2(1,3,8,9),U+7DD6(4) +U+7EEB(0);U+7DBE(1,3,8,9);U+7DBE(1,3,8,9) +U+7EEC(0);U+7EEC(4); +U+7EED(0);U+7E8C(1,3,8,9);U+7E8C(1,3,8,9) +U+7EEE(0);U+7DBA(1,3,8,9);U+7DBA(1,3,8,9) +U+7EEF(0);U+7DCB(1,3,8,9);U+7DCB(1,3,8,9) +U+7EF0(0);U+7DBD(1,3,8,9);U+7DBD(1,3,8,9) +U+7EF1(0);U+7DD4(4,8);U+7DD4(4,8) +U+7EF2(0);U+7DC4(1,3,8,9);U+7DC4(1,3,8,9) +U+7EF3(0);U+7E69(1,3,8,9);U+7E04(3),U+7E69(1,3,8,9) +U+7EF4(0);U+7DAD(1,3,8,9);U+7DAD(1,3,8,9) +U+7EF5(0);U+7DBF(1,3,8,9);U+7DBF(1,3,8,9) +U+7EF6(0);U+7DAC(1,3,8,9);U+7DAC(1,3,8,9) +U+7EF7(0);U+7E43(4,8,9);U+7DB3(1,3,8),U+7E43(4,8,9) +U+7EF8(0);U+7DA2(1,3,8,9);U+7D2C(4,9),U+7DA2(1,3,8,9),U+4337(1,3,4) +U+7EF9(0);U+7DAF(4,8,9);U+7DAF(4,8,9) +U+7EFA(0);U+7DB9(1,3,8,9);U+7DB9(1,3,8,9) +U+7EFB(0);U+7DA3(1,3,8,9);U+7DA3(1,3,8,9) +U+7EFC(0);U+7D9C(1,3,8,9);U+7D9C(1,3,8,9) +U+7EFD(0);U+7DBB(1,3,8,9);U+7DBB(1,3,8,9) +U+7EFE(0);U+7DB0(1,3,8,9);U+7DB0(1,3,8,9) +U+7EFF(0);U+7DA0(4,8,9);U+7DA0(4,8,9),U+7DD1(1,3,8) +U+7F00(0);U+7DB4(1,3,8,9);U+7DB4(1,3,8,9) +U+7F01(0);U+7DC7(1,3,8,9);U+7DC7(1,3,8,9) +U+7F02(0);U+7DD9(1,3,8,9);U+7DD9(1,3,8,9) +U+7F03(0);U+7DD7(1,3,8,9);U+7DD7(1,3,8,9) +U+7F04(0);U+7DD8(1,3,8,9);U+7DD8(1,3,8,9) +U+7F05(0);U+7DEC(1,3,8,9);U+7DEC(1,3,8,9) +U+7F06(0);U+7E9C(1,3,8,9);U+7E9C(1,3,8,9) +U+7F07(0);U+7DF9(1,3,8,9);U+7DF9(1,3,8,9) +U+7F08(0);U+7DF2(1,3,8,9);U+7DF2(1,3,8,9) +U+7F09(0);U+7DDD(1,3,8,9);U+7DDD(1,3,8,9) +U+7F0A(0);U+7E15(4,8,9);U+7DFC(1,3),U+7E15(4,8,9),U+891E(4,9) +U+7F0B(0);U+7E62(4,8,9);U+7E62(4,8,9),U+7E6A(3,4,8,9),U+7D75(0,3,4,8),U+7ED8(3,4,8) +U+7F0C(0);U+7DE6(1,3,8,9);U+7DE6(1,3,8,9) +U+7F0D(0);U+7D9E(4,8,9);U+7D9E(4,8,9) +U+7F0E(0);U+7DDE(1,3,8,9);U+7DDE(1,3,8,9) +U+7F0F(0);U+7DF6(4,8,9);U+7DF6(4,8,9) +U+7F10(0);U+7DDA(4,8,9);U+7DDA(4,8,9),U+7EBF(4),U+7DAB(0,2,3,4,8) +U+7F11(0);U+7DF1(1,3,8,9);U+7DF1(1,3,8,9) +U+7F12(0);U+7E0B(1,3,8,9);U+7E0B(1,3,8,9) +U+7F13(0);U+7DE9(1,3,8,9);U+7DE9(1,3,8,9) +U+7F14(0);U+7DE0(1,3,8,9);U+7DE0(1,3,8,9) +U+7F15(0);U+7E37(1,3,8,9);U+7E37(1,3,8,9) +U+7F16(0);U+7DE8(1,3,8,9);U+7DE8(1,3,8,9) +U+7F17(0);U+7DE1(1,3,8,9);U+7DE1(1,3,8,9) +U+7F18(0);U+7DE3(1,3,8,9);U+7DE3(1,3,8,9),U+7E01(4) +U+7F19(0);U+7E09(1,3,8,9);U+7E09(1,3,8,9) +U+7F1A(0);U+7E1B(1,3,8,9);U+7E1B(1,3,8,9) +U+7F1B(0);U+7E1F(1,3,8,9);U+7E1F(1,3,8,9) +U+7F1C(0);U+7E1D(1,3,8,9);U+7E1D(1,3,8,9) +U+7F1D(0);U+7E2B(1,3,8,9);U+7E2B(1,3,8,9) +U+7F1E(0);U+7E17(1,3,8,9);U+7E17(1,3,8,9) + +U+7F1F(0);U+7E1E(1,3,8,9);U+7E1E(1,3,8,9) +U+7F20(0);U+7E8F(1,3,8,9);U+7E8F(1,3,8,9),U+7E92(3) +U+7F21(0);U+7E2D(1,3,8,9);U+8935(3,9),U+7E2D(1,3,8,9) +U+7F22(0);U+7E0A(1,3,8,9);U+7E0A(1,3,8,9) +U+7F23(0);U+7E11(1,3,8,9);U+7E11(1,3,8,9) +U+7F24(0);U+7E7D(1,3,8,9);U+7E7D(1,3,8,9) +U+7F25(0);U+7E39(1,3,8,9);U+7E39(1,3,8,9) +U+7F26(0);U+7E35(1,3,8,9);U+7E35(1,3,8,9) +U+7F27(0);U+7E32(1,3,8,9);U+7E32(1,3,8,9) +U+7F28(0);U+7E93(1,3,8,9);U+7E93(1,3,8,9) +U+7F29(0);U+7E2E(1,3,8,9);U+644D(4,9),U+7E2E(1,3,8,9) +U+7F2A(0);U+7E46(1,3,8,9);U+7E46(1,3,8,9) +U+7F2B(0);U+7E45(1,3,8,9);U+7E45(1,3,8,9) +U+7F2C(0);U+7E88(1,3,8,9);U+7E88(1,3,8,9) +U+7F2D(0);U+7E5A(1,3,8,9);U+7E5A(1,3,8,9) +U+7F2E(0);U+7E55(1,3,8,9);U+7E55(1,3,8,9) +U+7F2F(0);U+7E52(1,3,8,9);U+7E52(1,3,8,9) +U+7F30(0);U+7E6E(1,3,8);U+7E6E(1,3,8),U+97C1(4,9) +U+7F31(0);U+7E7E(1,3,8,9);U+7E7E(1,3,8,9) +U+7F32(0);U+7E70(1,3,8,9);U+7E70(1,3,8,9) +U+7F33(0);U+7E6F(1,3,8,9);U+7E6F(1,3,8,9) +U+7F34(0);U+7E73(1,3,8,9);U+7E73(1,3,8,9) +U+7F35(0);U+7E98(1,3,8,9);U+7E89(3),U+7E98(1,3,8,9) +U+7F36(0);U+7F36(5,9); +U+7F37(0);U+5378(3,8,9);U+5378(3,8,9) +U+7F38(0);U+7F38(5,9);U+5808(3,9) +U+7F39(0);U+7F39(4,9); +U+7F3A(0);U+7F3A(5,9); +U+7F3D(0);U+7F3D(0,9);U+9262(2,3,8),U+94B5(4,8) +U+7F3E(0);U+7F3E(0,9);U+74F6(2,8,9),U+7501(2,3,8) +U+7F3F(0);U+7F3F(3,9); +U+7F40(0);U+7F40(0); +U+7F42(0);U+7F4C(1,3,8,9);U+7507(3,9),U+7516(2,3,9),U+7F43(3,9),U+7F4C(1,3,8,9) +U+7F43(0);U+7F43(0,9);U+7F42(3),U+7507(0,3,9),U+7516(2,3,9),U+7F4C(1,3,8,9) +U+7F44(0);U+7F44(5,9); +U+7F45(0);U+7F45(5,9);U+93EC(4,9) +U+7F47(0);U+7F47(0);U+6A3D(2,3,8,9),U+58AB(0,2,3,8,9) +U+7F48(0);U+7F48(0,9);U+575B(4),U+58C7(1,3,4,8,9),U+7F4E(1,3,4) +U+7F49(0);U+7F49(0); +U+7F4A(0);U+7F4A(0,9); +U+7F4B(0);U+7F4B(0,9);U+74EE(2,3,9),U+7515(2,3,4,9) +U+7F4C(0);U+7F4C(0,9);U+7F42(1,3,8),U+7507(0,1,3,8,9),U+7516(1,2,3,8,9),U+7F43(1,3,8,9) + +U+7F4D(0);U+7F4D(3,9); +U+7F4E(0);U+58C7(4,9);U+575B(1,3),U+58C7(4,9),U+7F48(1,3,4,9) +U+7F4F(0);U+7F4F(0,9);U+5786(3),U+58DA(1,3,8,9) +U+7F50(0);U+7F50(5,9);U+9475(2,3,8,9) +U+7F51(0);U+7DB2(1,3,8,9);U+7DB2(1,3,8,9) +U+7F52(0);U+7F52(0); +U+7F53(0);U+7F53(0); +U+7F54(0);U+7F54(5,9); +U+7F55(0);U+7F55(5,9); +U+7F56(0);U+7F56(0); +U+7F57(0);U+7F85(1,3,8,9);U+7F85(1,3,8,9) +U+7F58(0);U+7F58(5,9);U+7F66(3,8,9) +U+7F5A(0);U+7F70(1,3,8,9);U+7F70(1,3,8,9),U+7F78(4) +U+7F5B(0);U+7F5B(0,9); +U+7F5C(0);U+7F5C(0,9); +U+7F5D(0);U+7F5D(0,9); +U+7F5E(0);U+7F5E(0,9); +U+7F5F(0);U+7F5F(5,9); +U+7F60(0);U+7F60(0,9); +U+7F61(0);U+7F61(5,9); + +U+7F62(0);U+7F77(1,3,8,9);U+7F77(1,3,8,9) +U+7F63(0);U+7F63(0,9);U+6302(4,9),U+639B(2,3,4,8,9) +U+7F64(0);U+7F64(0); +U+7F65(0);U+7F65(3,9);U+7F82(3,8) +U+7F66(0);U+7F66(3,9);U+7F58(3,8,9) +U+7F67(0);U+7F67(3,9); +U+7F68(0);U+7F68(5,9); +U+7F69(0);U+7F69(5,9); +U+7F6A(0);U+7F6A(5,9);U+8FA0(2,8) +U+7F6B(0);U+7F6B(0,9); +U+7F6C(0);U+7F6C(3,9); +U+7F6D(0);U+7F6D(0,9); +U+7F6E(0);U+7F6E(5,9);U+5BD8(2,8,9) +U+7F6F(0);U+7F6F(0); +U+7F70(0);U+7F70(0,9);U+7F5A(1,3,8),U+7F78(2,3,8) +U+7F71(0);U+7F71(5); +U+7F72(0);U+7F72(5,9); +U+7F73(0);U+7F73(0,9); +U+7F74(0);U+7F86(1,3,8,9);U+7F86(1,3,8,9) +U+7F75(0);U+7F75(0,9);U+99E1(2,3,8),U+9A82(4,8),U+508C(0,4,8,9) +U+7F76(0);U+7F76(4,9);U+7F80(4,8) +U+7F77(0);U+7F77(0,9);U+7F62(1,3,8) +U+7F78(0);U+7F70(2,3,8,9);U+7F5A(4),U+7F70(2,3,8,9) +U+7F79(0);U+7F79(5,9); +U+7F7A(0);U+7F7A(3,9); +U+7F7B(0);U+7F7B(0,9); +U+7F7C(0);U+7F7C(0,9);U+6BD5(3),U+7562(1,3,8,9),U+93CE(3,9) +U+7F7D(0);U+7F7D(0,9); +U+7F7E(0);U+7F7E(5,9); +U+7F7F(0);U+7F7F(0,9); +U+7F80(0);U+7F76(4,8,9);U+7F76(4,8,9) +U+7F81(0);U+7F88(1,3,8,9);U+7F87(4,9),U+7F88(1,3,8,9),U+8989(3),U+898A(2,3) +U+7F82(0);U+7F65(3,8,9);U+7F65(3,8,9) +U+7F83(0);U+7F83(0,9);U+51AA(3,8,9),U+5E42(7) +U+7F85(0);U+7F85(0,9);U+7F57(1,3,8) +U+7F86(0);U+7F86(0,9);U+7F74(1,3,8) +U+7F87(0);U+7F87(0,9);U+7F81(4),U+7F88(4,8,9),U+8989(8),U+898A(2,3,4) +U+7F88(0);U+7F88(0,9);U+7F81(1,3,8),U+7F87(4,8,9),U+8989(3,8),U+898A(2,3,8) +U+7F89(0);U+7F89(0,9); +U+7F8A(0);U+7F8A(5,9); +U+7F8B(0);U+7F8B(0,9);U+8288(4,8) +U+7F8C(0);U+7F8C(5,9); +U+7F8D(0);U+7F8D(3,9); +U+7F8E(0);U+7F8E(5,9);U+5ABA(3,9) +U+7F8F(0);U+7F8F(0); +U+7F91(0);U+7F91(3,9); +U+7F92(0);U+7F92(0,9); +U+7F93(0);U+7F93(3); +U+7F94(0);U+7F94(5,9); +U+7F95(0);U+7F95(0,9); +U+7F96(0);U+7F96(0,9); +U+7F98(0);U+7F98(0); +U+7F9A(0);U+7F9A(5,9); +U+7F9B(0);U+7F9B(0,9);U+4E49(3),U+7FA9(1,3,8,9) +U+7F9C(0);U+7F9C(0,9); +U+7F9D(0);U+7F9D(5,9);U+7274(3,8,9),U+627A(2,3,8,9),U+62B5(2,3,5,8,9),U+89DD(2,3,8,9) + +U+7F9E(0);U+7F9E(5,9); +U+7F9F(0);U+7FA5(1,3,8,9);U+7FA5(1,3,8,9) +U+7FA0(0);U+7FA0(0,9); +U+7FA1(0);U+7FA1(5,9);U+7FA8(3,4,8,9) +U+7FA2(0);U+7FA2(0,9);U+7ED2(2),U+6BE7(0,2,9),U+7D68(1,2,3,8,9) +U+7FA3(0);U+7FA4(2,3,8,9);U+7FA4(2,3,8,9) + +U+7FA4(0);U+7FA4(5,9);U+7FA3(2,3,8) +U+7FA5(0);U+7FA5(0,9);U+7F9F(1,3,8) +U+7FA6(0);U+7FA6(0,9); +U+7FA7(0);U+7FA7(5,9); +U+7FA8(0);U+7FA8(0,9);U+7FA1(3,4,8,9) +U+7FA9(0);U+7FA9(0,9);U+4E49(1,3,8),U+7F9B(1,3,8,9) +U+7FAA(0);U+7FAA(0); +U+7FAB(0);U+7FAB(3); +U+7FAC(0);U+7FAC(3,9); +U+7FAD(0);U+7FAD(0,9); +U+7FAE(0);U+7FB9(4,8,9);U+7FB9(4,8,9) +U+7FAF(0);U+7FAF(5,9); +U+7FB0(0);U+7FB0(5,9); +U+7FB1(0);U+7FB1(3,9); +U+7FB2(0);U+7FB2(5,9); +U+7FB3(0);U+7FB3(0,9); +U+7FB5(0);U+7FB5(0,9); +U+7FB6(0);U+7FB6(0,9);U+81BB(2,3,9) +U+7FB7(0);U+7FB7(0,9); +U+7FB8(0);U+7FB8(5,9); +U+7FB9(0);U+7FB9(5,9);U+7FAE(4,8) +U+7FBA(0);U+7FBA(0,9); +U+7FBB(0);U+7FBB(0,9); +U+7FBC(0);U+7FBC(5,9); +U+7FBD(0);U+7FBD(5,9); +U+7FBE(0);U+7FBE(0,9); +U+7FBF(0);U+7FBF(5,9); +U+7FC0(0);U+7FC0(0,9); +U+7FC1(0);U+7FC1(5,9); +U+7FC2(0);U+7FC2(0,9); +U+7FC3(0);U+7FC3(3,9); +U+7FC4(0);U+7FC5(2,3,8,9);U+7FC5(2,3,8,9),U+7FE8(2,3,8,9) +U+7FC5(0);U+7FC5(5,9);U+7FC4(2,3,8),U+7FE8(3,9) +U+7FC6(0);U+7FE0(3,8,9);U+7FE0(3,8,9) +U+7FC7(0);U+7FC7(0,9); +U+7FC8(0);U+7FC8(0); +U+7FC9(0);U+7FC9(0,9); +U+7FCA(0);U+7FCA(5,9); +U+7FCB(0);U+7FCB(0,9); +U+7FCC(0);U+7FCC(5,9); +U+7FCD(0);U+7FCD(0,9); +U+7FCE(0);U+7FCE(5,9); +U+7FCF(0);U+7FCF(0,9); +U+7FD0(0);U+7FD0(0,9); +U+7FD1(0);U+7FD1(0,9); +U+7FD2(0);U+7FD2(0,9);U+4E60(1,3,8) +U+7FD3(0);U+7FD3(0); +U+7FD4(0);U+7FD4(5,9); +U+7FD5(0);U+7FD5(5,9); +U+7FD7(0);U+7FD7(0,9); +U+7FD8(0);U+7FF9(1,3,8,9);U+7FF9(1,3,8,9) +U+7FD9(0);U+7FFD(4,8,9);U+7FFD(4,8,9) +U+7FDA(0);U+7FEC(1,3,8,9);U+7FEC(1,3,8,9) +U+7FDB(0);U+7FDB(0,9); +U+7FDC(0);U+7FDC(0,9); +U+7FDE(0);U+7FDE(0,9); +U+7FDF(0);U+7FDF(5,9); +U+7FE0(0);U+7FE0(5,9);U+7FC6(3,8) +U+7FE1(0);U+7FE1(5,9); +U+7FE2(0);U+7FE2(0,9);U+7E9B(3,9) +U+7FE3(0);U+7FE3(3,9); +U+7FE5(0);U+7FE5(5,9); +U+7FE6(0);U+7FE6(5,9); + +U+7FE7(0);U+7FE7(0); +U+7FE8(0);U+7FE8(0,9);U+7FC5(3,9),U+7FC4(0,2,3,8) +U+7FE9(0);U+7FE9(5,9); +U+7FEA(0);U+7FEA(0,9); +U+7FEB(0);U+7FEB(3,9); +U+7FEC(0);U+7FEC(0,9);U+7FDA(1,3,8) +U+7FED(0);U+7FED(4,9);U+7FF5(4,9) +U+7FEE(0);U+7FEE(5,9); +U+7FEF(0);U+7FEF(0,9); +U+7FF0(0);U+7FF0(5,9);U+9DBE(3,9) +U+7FF1(0);U+7FF1(5,9);U+7FF6(4,8),U+7FFA(2,3,8) +U+7FF2(0);U+7FF2(0,9); +U+7FF3(0);U+7FF3(5,9); +U+7FF4(0);U+7FF4(0,9); +U+7FF5(0);U+7FF5(0,9);U+7FED(4,9) +U+7FF6(0);U+7FF1(4,8,9);U+7FF1(4,8,9),U+7FFA(4) +U+7FF7(0);U+7FF7(0,9); +U+7FF8(0);U+7FF8(0,9); +U+7FF9(0);U+7FF9(0,9);U+7FD8(1,3,8) +U+7FFA(0);U+7FF1(2,3,8,9);U+7FF1(2,3,8,9),U+7FF6(4) +U+7FFB(0);U+7FFB(5,9);U+7E59(2,3,8,9),U+98DC(2,3,8) +U+7FFC(0);U+7FFC(5,9); +U+7FFD(0);U+7FFD(0,9);U+7FD9(4,8) +U+7FFE(0);U+7FFE(0,9); +U+7FFF(0);U+7FFF(0,9); +U+8000(0);U+8000(5,9);U+71FF(2,3,8,9),U+66DC(2,3,5,8,9) +U+8001(0);U+8001(5,9);U+8002(8) +U+8002(0);U+8001(8,9);U+8001(8,9) +U+8003(0);U+8003(5,9);U+6537(2,3,8,9) +U+8004(0);U+8004(5,9); +U+8005(0);U+8005(5,9); +U+8006(0);U+8006(5,9); +U+8007(0);U+8007(3,9);U+8008(3,8),U+8009(3) +U+8008(0);U+8007(3,8,9);U+8007(3,8,9),U+8009(3,8) +U+8009(0);U+8007(3,9);U+8007(3,9),U+8008(3,8) +U+800B(0);U+800B(5,9); +U+800C(0);U+800C(5,9); +U+800D(0);U+800D(5,9); +U+800E(0);U+800E(0,9); +U+800F(0);U+800F(3,9); +U+8010(0);U+8010(5,9); +U+8011(0);U+8011(0,9);U+7AEF(3,9) +U+8012(0);U+8012(5,9); +U+8013(0);U+8013(0); +U+8014(0);U+8014(5,9); +U+8015(0);U+8015(5,9); +U+8016(0);U+8016(5,9); +U+8017(0);U+8017(5,9);U+79CF(3,8,9) +U+8018(0);U+8018(5,9);U+79D0(3,8) +U+8019(0);U+8019(5,9); +U+801A(0);U+801A(0); +U+801B(0);U+801B(0,9); +U+801C(0);U+801C(5,9); +U+801D(0);U+801D(0);U+521E(3,9) +U+801E(0);U+801E(0,9);U+67B7(3,9) +U+801F(0);U+801F(0,9); +U+8020(0);U+8020(5); +U+8021(0);U+8021(0,9);U+92E4(2,3,8,9),U+9504(4) +U+8022(0);U+802E(1,3,8);U+802E(1,3,8) +U+8023(0);U+8023(0); +U+8024(0);U+8024(0,9);U+501F(3,9),U+85C9(3,8,9) +U+8025(0);U+8025(5); +U+8026(0);U+8026(5,9); + +U+8027(0);U+802C(1,3,8,9);U+802C(1,3,8,9) +U+8028(0);U+8028(5,9); +U+8029(0);U+8029(5,9); +U+802A(0);U+802A(5,9); +U+802B(0);U+802B(0); +U+802C(0);U+802C(0,9);U+8027(1,3,8) +U+802D(0);U+802D(0); +U+802E(0);U+802E(0);U+8022(1,3,8) +U+8030(0);U+8030(3,9);U+6ACC(3,9) +U+8031(0);U+8031(5); +U+8032(0);U+8032(0); +U+8033(0);U+8033(5,9); +U+8034(0);U+8034(0,9); +U+8035(0);U+8035(5,9); +U+8036(0);U+8036(5,9); +U+8037(0);U+8037(5,9); +U+8038(0);U+8073(1,3,8,9);U+8073(1,3,8,9) +U+8039(0);U+8039(0,9); +U+803A(0);U+803A(0); +U+803B(0);U+6065(2,3,8,9);U+6065(2,3,8,9) +U+803D(0);U+803D(5,9);U+8EAD(2,3,8) +U+803E(0);U+803E(0,9); +U+803F(0);U+803F(5,9); +U+8041(0);U+8041(0); +U+8042(0);U+8076(1,3,8,9);U+8076(1,3,8,9) +U+8043(0);U+8043(5,9); +U+8044(0);U+8044(0); +U+8045(0);U+8045(0); +U+8046(0);U+8046(5,9); +U+8047(0);U+8047(0,9); +U+8048(0);U+8048(0,9); +U+8049(0);U+8049(0); +U+804A(0);U+804A(5,9); +U+804B(0);U+807E(1,3,8,9);U+807E(1,3,8,9) +U+804C(0);U+8077(1,3,8,9);U+8077(1,3,8,9) +U+804D(0);U+8079(1,3,8,9);U+8079(1,3,8,9) +U+804E(0);U+804E(0); +U+804F(0);U+804F(0,9); +U+8050(0);U+8050(0,9); +U+8051(0);U+8051(0,9); +U+8052(0);U+8052(5,9); +U+8053(0);U+8053(0); +U+8054(0);U+806F(1,3,8,9);U+8068(4),U+806B(3),U+806E(3),U+806F(1,3,8,9) +U+8055(0);U+8055(0); +U+8056(0);U+8056(0,9);U+5723(1,3,8,9),U+57A9(3,8),U+580A(1,3,8,9) +U+8057(0);U+8057(0); +U+8058(0);U+8058(5,9); +U+8059(0);U+8059(0); +U+805A(0);U+805A(5,9); +U+805B(0);U+805B(0); +U+805C(0);U+805C(0,9); +U+805D(0);U+805D(0,9);U+9998(4,9) +U+805E(0);U+805E(0,9);U+95FB(1,3,8) +U+805F(0);U+5A7F(7,8,9);U+5A7F(7,8,9) +U+8060(0);U+8060(0); +U+8061(0);U+8070(3,8,9);U+806A(3),U+8070(3,8,9) +U+8062(0);U+8062(0); +U+8063(0);U+8063(0); +U+8064(0);U+8064(0,9); +U+8065(0);U+8065(0); +U+8067(0);U+8067(0,9); +U+8068(0);U+806F(4,8,9);U+8054(4),U+806F(4,8,9),U+806B(3,4),U+806E(3,4) +U+8069(0);U+8075(1,3,8,9);U+8075(1,3,8,9) + +U+806A(0);U+8070(1,3,4,8,9);U+8061(3),U+8070(1,3,4,8,9) +U+806B(0);U+806F(3,8,9);U+8054(3),U+806F(3,8,9),U+8068(3,4),U+806E(3) +U+806C(0);U+806C(0,9); +U+806D(0);U+806D(0); +U+806E(0);U+806F(3,8,9);U+8054(3),U+806F(3,8,9),U+8068(3,4),U+806B(3) +U+806F(0);U+806F(0,9);U+8054(1,3,8),U+8068(4,8),U+806B(3,8),U+806E(3,8) +U+8070(0);U+8070(0,9);U+8061(3,8),U+806A(1,3,8) +U+8071(0);U+8071(5,9); +U+8072(0);U+8072(0,9);U+58F0(1,3,8) +U+8073(0);U+8073(0,9);U+8038(1,3,8) +U+8074(0);U+807D(3,8,9);U+542C(3,9),U+807D(3,8,9),U+807C(3) +U+8075(0);U+8075(0,9);U+8069(1,3,8) +U+8076(0);U+8076(0,9);U+8042(1,3,8) +U+8077(0);U+8077(0,9);U+804C(1,3,8) +U+8078(0);U+8078(0,9); +U+8079(0);U+8079(0,9);U+804D(1,3,8) +U+807A(0);U+807A(0); +U+807B(0);U+807B(0); +U+807C(0);U+807D(3,8,9);U+542C(3,9),U+807D(3,8,9),U+8074(3) +U+807D(0);U+807D(0,9);U+542C(1,3,8,9),U+8074(3,8),U+807C(3,8) +U+807E(0);U+807E(0,9);U+804B(1,3,8) +U+807F(0);U+807F(5,9);U+8080(8) +U+8080(0);U+807F(8,9);U+807F(8,9) +U+8081(0);U+8081(0); +U+8082(0);U+8082(0,9); +U+8083(0);U+8085(1,3,8,9);U+7C9B(3),U+8085(1,3,8,9) +U+8084(0);U+8084(5,9); +U+8085(0);U+8085(0,9);U+7C9B(3,8),U+8083(1,3,8) +U+8086(0);U+8086(5,9);U+56DB(3,8,9) +U+8087(0);U+8087(5,9); +U+8089(0);U+8089(5,9);U+5B8D(4,8) +U+808A(0);U+808A(0,9);U+81C6(3,9) +U+808B(0);U+808B(5,9); +U+808C(0);U+808C(5,9); +U+808D(0);U+808D(0); +U+808F(0);U+808F(0,9); +U+8090(0);U+8090(0,9);U+80F3(2,8,9) +U+8091(0);U+8091(0); +U+8092(0);U+8092(0,9); +U+8093(0);U+8093(5,9); +U+8095(0);U+8095(0,9);U+97E7(3),U+976D(3,4),U+97CC(1,3,4,8,9) +U+8096(0);U+8096(5,9); +U+8097(0);U+8097(0); +U+8098(0);U+8098(5,9); +U+8099(0);U+8099(0,9); +U+809A(0);U+809A(5,9); +U+809B(0);U+809B(5,9);U+7598(2,3,9) +U+809C(0);U+809C(5,9); +U+809D(0);U+809D(5,9); +U+809E(0);U+809E(0); +U+809F(0);U+809F(5); +U+80A0(0);U+8178(1,3,8,9);U+8178(1,3,8,9),U+8193(4) +U+80A1(0);U+80A1(5,9); +U+80A2(0);U+80A2(5,9);U+80D1(3,9) +U+80A3(0);U+80A3(0,9);U+51FD(3,9),U+51FE(3,8) +U+80A4(0);U+819A(1,3,8,9);U+819A(1,3,8,9) +U+80A5(0);U+80A5(5,9); +U+80A9(0);U+80A9(5,9); +U+80AA(0);U+80AA(5,9); +U+80AB(0);U+80AB(5,9); +U+80AD(0);U+80AD(5,9); +U+80AE(0);U+9AAF(1,3,4,8,9);U+9AAF(1,3,4,8,9) +U+80AF(0);U+80AF(5,9);U+80BB(3,8) + +U+80B0(0);U+80B0(0); +U+80B1(0);U+80B1(5,9); +U+80B2(0);U+80B2(5,9); +U+80B4(0);U+80B4(5,9),U+991A(2,3,9);U+991A(2,3,9) +U+80B5(0);U+80B5(0,9); +U+80B6(0);U+80B6(0); +U+80B7(0);U+80B7(5); +U+80B8(0);U+80B8(3,9); +U+80BA(0);U+80BA(5,9);U+80C7(3,9) +U+80BB(0);U+80AF(3,8,9);U+80AF(3,8,9) +U+80BC(0);U+80BC(5); +U+80BD(0);U+80BD(5); +U+80BE(0);U+814E(1,3,8,9);U+814E(1,3,8,9) +U+80BF(0);U+816B(1,3,8,9);U+816B(1,3,8,9) +U+80C0(0);U+8139(1,3,8,9);U+8139(1,3,8,9) +U+80C1(0);U+8105(1,3,8,9);U+8105(1,3,8,9),U+8107(4) +U+80C2(0);U+80C2(5,9); +U+80C3(0);U+80C3(5,9); +U+80C4(0);U+80C4(5,9);U+5191(4,8,9) +U+80C5(0);U+80C5(0,9); +U+80C6(0);U+81BD(1,3,8,9);U+81BD(1,3,8,9) +U+80C7(0);U+80C7(0,9);U+80BA(3,9) +U+80C8(0);U+80C8(0,9); +U+80C9(0);U+80C9(0,9); +U+80CA(0);U+80CA(0,9);U+6710(4,8,9) +U+80CB(0);U+80CB(0); +U+80CC(0);U+80CC(5,9);U+505D(3,9),U+63F9(2,3,9) +U+80CD(0);U+80CD(5,9); +U+80CE(0);U+80CE(5,9); +U+80CF(0);U+80CF(0,9); +U+80D0(0);U+80D0(0,9);U+670F(4,9) +U+80D1(0);U+80D1(0,9);U+80A2(3,9) +U+80D2(0);U+80D2(0); +U+80D3(0);U+80D3(0); +U+80D4(0);U+80D4(0,9); +U+80D5(0);U+80D5(0,9); +U+80D6(0);U+80D6(5,9); +U+80D7(0);U+80D7(5,9); +U+80D8(0);U+80D8(0,9); +U+80D9(0);U+80D9(5,9); +U+80DA(0);U+80DA(5,9); +U+80DB(0);U+80DB(5,9); +U+80DC(0);U+80DC(1,3,9),U+52DD(1,3,4,8,9);U+52DD(1,3,4,8,9) +U+80DD(0);U+80DD(5,9); +U+80DE(0);U+80DE(5,9); +U+80E0(0);U+80E0(3,9); +U+80E1(0);U+80E1(1,3,9),U+9B0D(1,3,4,8,9);U+885A(2,9),U+9B0D(1,3,4,8,9) +U+80E2(0);U+80E2(0); +U+80E3(0);U+80E3(3,9); +U+80E4(0);U+80E4(5,9); +U+80E5(0);U+80E5(5,9);U+7E03(3,9) +U+80E6(0);U+80E6(0,9); +U+80E7(0);U+6727(1,3,8,9);U+6727(1,3,8,9) +U+80E8(0);U+8156(1,3,8);U+8156(1,3,8) +U+80E9(0);U+80E9(5); +U+80EA(0);U+81DA(1,3,8,9);U+81DA(1,3,8,9) +U+80EB(0);U+811B(1,3,8,9);U+811B(1,3,8,9) +U+80EC(0);U+80EC(5); +U+80ED(0);U+80ED(5,9);U+81D9(2,3,8,9) +U+80EE(0);U+80EE(3); +U+80EF(0);U+80EF(5,9);U+9ABB(3,9) +U+80F0(0);U+80F0(5,9); +U+80F1(0);U+80F1(5,9); + +U+80F2(0);U+80F2(5,9); +U+80F3(0);U+80F3(5,9);U+8090(2,8,9) +U+80F4(0);U+80F4(5,9); +U+80F5(0);U+80F5(3,9); +U+80F6(0);U+81A0(1,3,8,9);U+81A0(1,3,8,9) +U+80F7(0);U+80F8(2,3,8,9);U+80F8(2,3,8,9) +U+80F8(0);U+80F8(5,9);U+80F7(2,3,8) +U+80F9(0);U+80F9(3,9); +U+80FA(0);U+80FA(5,9); +U+80FB(0);U+80FB(0,9); +U+80FC(0);U+80FC(5,9);U+8141(3,8) +U+80FD(0);U+80FD(5,9); +U+80FE(0);U+80FE(0,9); +U+80FF(0);U+80FF(0); +U+8100(0);U+8100(0,9); +U+8101(0);U+8101(0,9);U+6713(4,9) +U+8102(0);U+8102(5,9); +U+8105(0);U+8105(0,9);U+80C1(1,3,8),U+8107(2,3,8) +U+8106(0);U+8106(5,9);U+81AC(3,9) +U+8107(0);U+8105(2,3,8,9);U+80C1(4),U+8105(2,3,8,9) +U+8108(0);U+8108(0,9);U+8109(2,3,4,8) +U+8109(0);U+8108(2,3,4,8,9);U+8108(2,3,4,8,9) +U+810A(0);U+810A(5,9); +U+810B(0);U+810B(0); +U+810C(0);U+810C(0); +U+810D(0);U+81BE(1,3,8,9);U+81BE(1,3,8,9) +U+810E(0);U+810E(5); +U+810F(0);U+81DF(1,3,8,9),U+9AD2(1,3,8,9);U+81DF(1,3,8,9),U+9AD2(1,3,8,9) +U+8110(0);U+81CD(1,3,8,9);U+81CD(1,3,8,9) +U+8111(0);U+8166(1,3,8,9);U+8166(1,3,8,9) +U+8112(0);U+8112(5); +U+8113(0);U+81BF(1,3,8,9);U+81BF(1,3,8,9) +U+8114(0);U+81E0(1,3,8,9);U+81E0(1,3,8,9) +U+8115(0);U+8115(0,9); +U+8116(0);U+8116(5,9); +U+8118(0);U+8118(5,9); +U+8119(0);U+8119(0,9); +U+811A(0);U+8173(2,3,8,9);U+8173(2,3,8,9) +U+811B(0);U+811B(0,9);U+80EB(1,3,8) +U+811C(0);U+811C(0); +U+811D(0);U+811D(0,9); +U+811E(0);U+811E(5,9); +U+811F(0);U+811F(0,9); +U+8120(0);U+8120(0); +U+8121(0);U+8121(3,9); +U+8122(0);U+8122(3,9); +U+8123(0);U+8123(0,9);U+5507(3,8,9) +U+8124(0);U+8124(0,9); +U+8125(0);U+8125(0,9); +U+8126(0);U+8126(0); +U+8127(0);U+8127(0,9);U+6718(4,8,9) +U+8128(0);U+8128(0); +U+8129(0);U+8129(3,9);U+4FEE(2,3,9) +U+812A(0);U+812A(0); +U+812B(0);U+812B(0,9);U+8131(4,8) +U+812C(0);U+812C(5,9); +U+812D(0);U+812D(0,9); +U+812E(0);U+812E(0); +U+812F(0);U+812F(5,9); +U+8130(0);U+8130(0,9); +U+8131(0);U+812B(4,8,9);U+812B(4,8,9) +U+8132(0);U+8132(5); +U+8136(0);U+8161(1,3,8,9);U+8161(1,3,8,9) + +U+8137(0);U+8137(0); +U+8138(0);U+81C9(1,3,8,9);U+81C9(1,3,8,9) +U+8139(0);U+8139(0,9);U+80C0(1,3,8) +U+813A(0);U+813A(0,9); +U+813B(0);U+813B(0); +U+813C(0);U+813C(0); +U+813D(0);U+813D(0,9); +U+813E(0);U+813E(5,9); +U+813F(0);U+813F(0); +U+8140(0);U+8140(0); +U+8141(0);U+80FC(3,8,9);U+80FC(3,8,9) +U+8142(0);U+8142(0); +U+8143(0);U+8143(0,9); +U+8144(0);U+8144(0,9); +U+8145(0);U+8145(0); +U+8146(0);U+8146(5,9);U+500E(3,9) +U+8147(0);U+8147(0,9); +U+8148(0);U+8148(5); +U+8149(0);U+8149(0); +U+814A(0);U+81D8(1,3,8,9);U+81C8(4),U+81D8(1,3,8,9) +U+814B(0);U+814B(5,9); +U+814C(0);U+9183(2,9);U+9183(2,9) +U+814D(0);U+814D(0,9); +U+814E(0);U+814E(0,9);U+80BE(1,3,8) +U+814F(0);U+814F(0,9); +U+8150(0);U+8150(5,9); +U+8151(0);U+8151(5,9); +U+8152(0);U+8152(3,9); +U+8153(0);U+8153(5,9); +U+8154(0);U+8154(5,9); +U+8155(0);U+8155(5,9); +U+8156(0);U+8156(0);U+80E8(1,3,8) +U+8157(0);U+8157(0); +U+8158(0);U+8195(1,3,8,9);U+8195(1,3,8,9) +U+8159(0);U+8159(5); +U+815A(0);U+815A(5); +U+815B(0);U+815B(0,9); +U+815C(0);U+815C(0,9); +U+815D(0);U+815D(3); +U+815E(0);U+815E(3,9); +U+8160(0);U+8160(5,9);U+50B6(4,9) +U+8161(0);U+8161(0,9);U+8136(1,3,8) +U+8162(0);U+8162(0,9); +U+8163(0);U+8163(0); +U+8164(0);U+8164(0,9); +U+8165(0);U+8165(5,9); +U+8166(0);U+8166(0,9);U+8111(1,3,8) +U+8167(0);U+8167(5,9); +U+8168(0);U+8168(0); +U+8169(0);U+8169(5,9); +U+816A(0);U+816A(0); +U+816B(0);U+816B(0,9);U+80BF(1,3,8) +U+816C(0);U+816C(0); +U+816D(0);U+9F76(2,3,9);U+9F76(2,3,9) +U+816E(0);U+816E(5,9); +U+816F(0);U+816F(3,9); +U+8170(0);U+8170(5,9); +U+8171(0);U+8171(5,9); +U+8172(0);U+8172(0,9); +U+8173(0);U+8173(0,9);U+811A(2,3,8) +U+8174(0);U+8174(5,9); +U+8175(0);U+8175(0); +U+8176(0);U+8176(3,9); + +U+8177(0);U+8177(0,9); +U+8178(0);U+8178(0,9);U+80A0(1,3,8),U+8193(2,3,8) +U+8179(0);U+8179(5,9); +U+817A(0);U+817A(5,9); +U+817B(0);U+81A9(1,3,8,9);U+81A9(1,3,8,9) +U+817C(0);U+817C(5); +U+817D(0);U+8183(4,8,9);U+8183(4,8,9) +U+817E(0);U+9A30(1,3,8,9);U+9A30(1,3,8,9) +U+817F(0);U+817F(5,9); +U+8180(0);U+8180(5,9); +U+8181(0);U+8181(0); +U+8182(0);U+8182(5,9); +U+8183(0);U+8183(0,9);U+817D(4,8) +U+8185(0);U+8185(0); +U+8186(0);U+8186(0,9);U+55C9(3,9) +U+8187(0);U+8187(0,9); +U+8188(0);U+8188(5,9); +U+8189(0);U+8189(0,9); +U+818A(0);U+818A(5,9); +U+818B(0);U+818B(0,9); +U+818C(0);U+818C(0,9);U+7620(3,9) +U+818D(0);U+818D(3,9); +U+818E(0);U+818E(0); +U+818F(0);U+818F(5,9); +U+8191(0);U+81CF(1,3,8,9);U+81CF(1,3,8,9),U+9AD5(1,3,8,9),U+9ACC(1,3,8) +U+8192(0);U+8192(0); +U+8193(0);U+8178(2,3,8,9);U+80A0(4),U+8178(2,3,8,9) +U+8194(0);U+8194(0); +U+8195(0);U+8195(0,9);U+8158(1,3,8) +U+8197(0);U+8197(0,9); +U+8198(0);U+8198(5,9);U+81D5(2,3,8,9) +U+8199(0);U+8199(0,9); +U+819A(0);U+819A(0,9);U+80A4(1,3,8) +U+819B(0);U+819B(5,9); +U+819C(0);U+819C(5,9); +U+819D(0);U+819D(5,9); +U+819E(0);U+819E(0,9);U+43DD(1,3) +U+819F(0);U+819F(0,9); +U+81A0(0);U+81A0(0,9);U+80F6(1,3,8) +U+81A1(0);U+81A1(0); +U+81A2(0);U+81A2(0,9); +U+81A3(0);U+81A3(5,9); +U+81A4(0);U+81A4(0); +U+81A5(0);U+81A5(0); +U+81A6(0);U+81A6(5,9); +U+81A7(0);U+81A7(0,9);U+6723(4,9) +U+81A8(0);U+81A8(5,9); +U+81A9(0);U+81A9(0,9);U+817B(1,3,8) +U+81AA(0);U+81AA(5); +U+81AB(0);U+81AB(0,9); +U+81AC(0);U+81AC(0,9);U+8106(3,9) +U+81AD(0);U+81AD(0); +U+81AE(0);U+81AE(0,9); +U+81AF(0);U+81AF(0); +U+81B0(0);U+81B0(0,9); +U+81B1(0);U+81B1(0,9); +U+81B2(0);U+81B2(0,9); +U+81B3(0);U+81B3(5,9); +U+81B4(0);U+81B4(0,9); +U+81B5(0);U+81B5(4,9); +U+81B6(0);U+81B6(0); +U+81B7(0);U+81B7(0,9); +U+81B8(0);U+9AD3(3,8,9);U+9AD3(3,8,9),U+9AC4(3,8) + +U+81B9(0);U+81B9(0,9); +U+81BA(0);U+81BA(5,9); +U+81BB(0);U+81BB(5,9),U+7FB6(2,3,9);U+7FB6(2,3,9) +U+81BC(0);U+81BC(0,9); +U+81BD(0);U+81BD(0,9);U+80C6(1,3,8) +U+81BE(0);U+81BE(0,9);U+810D(1,3,8) +U+81BF(0);U+81BF(0,9);U+8113(1,3,8) +U+81C0(0);U+81C0(5,9); +U+81C1(0);U+81C1(5); +U+81C2(0);U+81C2(5,9); +U+81C3(0);U+81C3(5,9); +U+81C4(0);U+81C4(0,9); +U+81C5(0);U+81C5(0,9); +U+81C6(0);U+81C6(5,9);U+808A(3,9) +U+81C7(0);U+81C7(0,9); +U+81C8(0);U+814A(4,9);U+814A(4,9),U+81D8(2,3,8,9) +U+81C9(0);U+81C9(0,9);U+8138(1,3,8) +U+81CA(0);U+81CA(5,9); +U+81CC(0);U+81CC(5,9); +U+81CD(0);U+81CD(0,9);U+8110(1,3,8) +U+81CE(0);U+81CE(3); +U+81CF(0);U+81CF(0,9);U+8191(1,3,8),U+9AD5(3,8,9),U+9ACC(1,3,8) +U+81D0(0);U+81D0(0,9); +U+81D1(0);U+81D1(0,9); +U+81D2(0);U+81D2(0,9); +U+81D4(0);U+81D4(0); +U+81D5(0);U+81D5(0,9);U+8198(2,3,8,9) +U+81D6(0);U+81D6(0); +U+81D7(0);U+81D7(3,9); +U+81D8(0);U+81D8(0,9);U+814A(1,3,8,9),U+81C8(2,3,8) +U+81D9(0);U+81D9(0,9);U+80ED(2,3,8,9) +U+81DA(0);U+81DA(0,9);U+80EA(1,3,8) +U+81DB(0);U+81DB(0,9); +U+81DC(0);U+81E2(1,3,8,9);U+81E2(1,3,8,9) +U+81DD(0);U+81DD(0,9);U+88F8(2,3,9) +U+81DE(0);U+81DE(3,9); +U+81DF(0);U+81DF(0,9);U+810F(1,3,8),U+9AD2(1,3,8,9) +U+81E0(0);U+81E0(0,9);U+8114(1,3,8) +U+81E1(0);U+81E1(0,9); +U+81E2(0);U+81E2(0,9);U+81DC(1,3,8) +U+81E3(0);U+81E3(5,9); +U+81E5(0);U+81E5(0,9);U+5367(3,4,8) +U+81E6(0);U+81E6(0,9); +U+81E7(0);U+81E7(5,9); +U+81E8(0);U+81E8(0,9);U+4E34(1,3,8) +U+81E9(0);U+81E9(0,9); +U+81EA(0);U+81EA(5,9); +U+81EB(0);U+81EB(0); +U+81EC(0);U+81EC(5,9); +U+81ED(0);U+81ED(5,9);U+6BA0(3,9) +U+81EE(0);U+81EE(0,9);U+66A8(4,9),U+66C1(4,8),U+8507(4,9) +U+81F1(0);U+81F1(0); +U+81F2(0);U+81F2(0,9); +U+81F3(0);U+81F3(5,9); +U+81F4(0);U+81F4(1,3,9),U+7DFB(1,3,4,8,9);U+7DFB(1,3,4,8,9) +U+81F5(0);U+81F5(0); +U+81F6(0);U+81F6(0); +U+81F7(0);U+81F7(0,9); +U+81F8(0);U+81F8(0,9); +U+81F9(0);U+81F9(0,9); +U+81FA(0);U+81FA(0,9);U+53F0(1,3,8,9),U+6AAF(1,3,4,8,9),U+7C49(1,3,4,8,9),U+98B1(1,3,4,8,9) + +U+81FB(0);U+81FB(5,9); + +U+81FC(0);U+81FC(5,9); +U+81FD(0);U+81FD(0); +U+81FE(0);U+81FE(5,9); +U+81FF(0);U+81FF(0,9);U+9538(4),U+9364(1,3,4,8,9) +U+8200(0);U+8200(5,9);U+62AD(4,9) +U+8201(0);U+8201(5,9); +U+8202(0);U+8202(5,9); +U+8203(0);U+8204(3,4,8,9);U+8204(3,4,8,9) +U+8204(0);U+8204(5,9);U+8203(3,4,8) +U+8205(0);U+8205(5,9); +U+8206(0);U+8F3F(1,3,8,9);U+8F3F(1,3,8,9),U+8F5D(3,9) +U+8207(0);U+8207(0,9);U+4E0E(1,3,8,9) +U+8208(0);U+8208(0,9);U+5174(1,3,8) +U+8209(0);U+8209(0,9);U+4E3E(1,3,8),U+6319(4,8),U+64E7(2,3,8) +U+820A(0);U+820A(0,9);U+65E7(1,3,8) +U+820B(0);U+820B(4,9); +U+820C(0);U+820C(5,9); +U+820D(0);U+820D(1,3,9),U+6368(1,3,4,8,9);U+6368(1,3,4,8,9),U+820E(4,8) +U+820E(0);U+820D(4,8,9);U+820D(4,8,9),U+6368(0,1,3,4,8,9) +U+820F(0);U+820F(0); +U+8210(0);U+8210(5,9); +U+8211(0);U+8211(4,9); +U+8212(0);U+8212(5,9); +U+8214(0);U+8214(5,9); +U+8215(0);U+8215(0,9); +U+8216(0);U+8216(0,9);U+92EA(2,3,8,9),U+94FA(4) +U+8218(0);U+9928(2,3,8,9);U+9928(2,3,8,9),U+9986(4) +U+8219(0);U+8219(0); +U+821A(0);U+821A(0); +U+821B(0);U+821B(5,9); +U+821C(0);U+821C(5,9); +U+821D(0);U+821D(4,9); +U+821E(0);U+821E(5,9); +U+821F(0);U+821F(5,9); +U+8220(0);U+8220(0,9); +U+8221(0);U+8221(5,9);U+8239(3,8,9),U+8229(2,3,8) +U+8222(0);U+8222(5,9); +U+8223(0);U+8264(4,8,9);U+6AA5(3,9),U+8264(4,8,9) +U+8225(0);U+8225(0,9); +U+8226(0);U+8226(0); +U+8227(0);U+8227(4); +U+8228(0);U+8228(5,9); +U+8229(0);U+8239(2,3,8,9);U+8239(2,3,8,9),U+8221(2,3,5,8,9) +U+822A(0);U+822A(5,9);U+6841(3,8,9) +U+822B(0);U+822B(5,9); +U+822C(0);U+822C(5,9); +U+822D(0);U+822D(5); +U+822F(0);U+822F(5,9); +U+8230(0);U+8266(1,3,8,9);U+8266(1,3,8,9) +U+8231(0);U+8259(1,3,8,9);U+8259(1,3,8,9) +U+8232(0);U+8232(0,9); +U+8233(0);U+8233(5,9); +U+8234(0);U+8234(5,9); +U+8235(0);U+8235(5,9);U+67C1(3,8,9) +U+8236(0);U+8236(5,9);U+824A(3,8) +U+8237(0);U+8237(5,9); +U+8238(0);U+8238(5,9); +U+8239(0);U+8239(5,9);U+8221(3,8,9),U+8229(2,3,8) +U+823A(0);U+823A(0,9); +U+823B(0);U+826B(1,3,8,9);U+826B(1,3,8,9) +U+823C(0);U+823C(0,9); +U+823D(0);U+823D(0,9); +U+823E(0);U+823E(5); + +U+823F(0);U+823F(0,9); +U+8240(0);U+8240(0,9); +U+8242(0);U+8242(0,9); +U+8243(0);U+8243(0); +U+8244(0);U+8244(5,9); +U+8245(0);U+8245(0,9); +U+8246(0);U+8246(0); +U+8247(0);U+8247(5,9); +U+8248(0);U+8248(0); +U+8249(0);U+8249(5,9); +U+824A(0);U+8236(3,8,9);U+8236(3,8,9) +U+824B(0);U+824B(5,9); +U+824C(0);U+824C(0); +U+824D(0);U+824D(0); +U+824E(0);U+824E(3,9); +U+824F(0);U+824F(5,9); +U+8250(0);U+8250(0,9);U+5C4A(3),U+5C46(0,2,3,8,9) +U+8251(0);U+8251(0,9); +U+8252(0);U+8252(0,9); +U+8253(0);U+8253(0,9); +U+8254(0);U+8254(0); +U+8255(0);U+8255(0,9); +U+8256(0);U+8256(0,9); +U+8257(0);U+8257(3,9); +U+8258(0);U+8258(5,9); +U+8259(0);U+8259(0,9);U+8231(1,3,8) +U+825A(0);U+825A(5,9); +U+825B(0);U+825B(0,9); +U+825C(0);U+825C(0,9); +U+825D(0);U+825D(0); +U+825E(0);U+825E(0,9); +U+825F(0);U+825F(5,9); +U+8260(0);U+8260(0); +U+8261(0);U+8261(0,9); +U+8263(0);U+8263(4,9);U+6A79(7),U+6AD3(2,3,8,9),U+826A(4),U+6A10(0,3,7) +U+8264(0);U+8264(0,9);U+8223(4,8),U+6AA5(0,3,4,8,9) +U+8266(0);U+8266(0,9);U+8230(1,3,8) +U+8267(0);U+8267(0); +U+8268(0);U+8268(5,9); +U+8269(0);U+8269(0,9); +U+826A(0);U+826A(0);U+6A79(2,3),U+6AD3(2,3,8,9),U+8263(4,9),U+6A10(0,2,3) +U+826B(0);U+826B(0,9);U+823B(1,3,8) +U+826C(0);U+826C(0,9); +U+826D(0);U+826D(0,9); +U+826E(0);U+826E(5,9); +U+826F(0);U+826F(5,9); +U+8270(0);U+8271(1,3,8,9);U+8271(1,3,8,9) +U+8271(0);U+8271(0,9);U+8270(1,3,8) +U+8272(0);U+8272(5,9); +U+8273(0);U+8277(1,3,8,9);U+8276(4),U+8277(1,3,8,9),U+8C54(4,8,9) +U+8274(0);U+8274(5,9); +U+8275(0);U+8275(0,9); +U+8276(0);U+8277(8,9);U+8273(4),U+8277(8,9),U+8C54(4,8,9) +U+8277(0);U+8277(0,9);U+8273(1,3,8),U+8276(8),U+8C54(2,3,8,9) +U+8278(0);U+8278(0,9);U+8349(2,3,9),U+9A32(2,3,4,9) +U+8279(0);U+8279(5); +U+827A(0);U+85DD(1,3,8,9);U+84FA(3,9),U+517F(4),U+85DD(1,3,8,9) +U+827B(0);U+827B(0); +U+827C(0);U+827C(0,9); +U+827D(0);U+827D(5,9); +U+827E(0);U+827E(5,9); +U+827F(0);U+827F(5,9); +U+8280(0);U+8280(0,9);U+82D5(3,9) + +U+8281(0);U+8281(0); +U+8282(0);U+7BC0(1,3,8,9);U+7BC0(1,3,8,9) +U+8283(0);U+8283(3,9); +U+8284(0);U+8284(5,9); +U+8285(0);U+8285(0,9); +U+8286(0);U+8286(0); +U+8287(0);U+8287(0); +U+8288(0);U+7F8B(4,8,9);U+7F8B(4,8,9) +U+8289(0);U+8289(0); +U+828A(0);U+828A(5,9); +U+828B(0);U+828B(5,9); +U+828D(0);U+828D(5,9); +U+828E(0);U+828E(5,9); +U+828F(0);U+828F(5,9); +U+8290(0);U+8290(3,9); +U+8291(0);U+8291(5,9); +U+8292(0);U+8292(5,9);U+7B00(3,9) +U+8293(0);U+8293(0,9); +U+8294(0);U+8294(0,9); +U+8295(0);U+8295(0); +U+8296(0);U+8296(0); +U+8297(0);U+858C(1,3,8,9);U+858C(1,3,8,9) +U+8298(0);U+8298(5,9); +U+8299(0);U+8299(5,9); +U+829A(0);U+829A(0,9); +U+829B(0);U+829B(3,9); +U+829C(0);U+856A(1,3,8,9);U+856A(1,3,8,9) +U+829D(0);U+829D(5,9); +U+829E(0);U+829E(0,9); +U+829F(0);U+829F(5,9); +U+82A0(0);U+82A0(0,9); +U+82A1(0);U+82A1(5,9); +U+82A2(0);U+82A2(0,9); +U+82A3(0);U+82A3(0,9); +U+82A4(0);U+82A4(5,9); +U+82A5(0);U+82A5(5,9); +U+82A6(0);U+8606(1,3,8,9);U+8606(1,3,8,9) +U+82A7(0);U+82A7(3,9); +U+82A8(0);U+82A8(5,9); +U+82A9(0);U+82A9(5,9); +U+82AA(0);U+82AA(5); +U+82AB(0);U+82AB(5,9); +U+82AC(0);U+82AC(5,9); +U+82AD(0);U+82AD(5,9); +U+82AE(0);U+82AE(5,9); +U+82AF(0);U+82AF(5,9); +U+82B0(0);U+82B0(5,9); +U+82B1(0);U+82B1(5,9);U+8624(2,3,9) +U+82B3(0);U+82B3(5,9); +U+82B4(0);U+82B4(5,9); +U+82B5(0);U+82B5(0,9); +U+82B6(0);U+82B6(0,9);U+82DF(3,9) +U+82B7(0);U+82B7(5,9); +U+82B8(0);U+82B8(1,3,9),U+8553(1,3,8,9);U+8553(1,3,8,9) +U+82B9(0);U+82B9(5,9); +U+82BA(0);U+82BA(0,9); +U+82BB(0);U+82BB(0,9);U+520D(1,3,8) +U+82BC(0);U+82BC(0,9); +U+82BD(0);U+82BD(5,9); +U+82BE(0);U+82BE(5,9); +U+82BF(0);U+82BF(4); +U+82C0(0);U+82C0(0,9); +U+82C1(0);U+84EF(1,3,8,9);U+84EF(1,3,8,9) + +U+82C2(0);U+82C2(0,9); +U+82C3(0);U+82C3(0,9); +U+82C4(0);U+82C4(5); +U+82C5(0);U+5208(3,8,9);U+5208(3,8,9) +U+82C6(0);U+82C6(0); +U+82C7(0);U+8466(1,3,8,9);U+8466(1,3,8,9) +U+82C8(0);U+85F6(1,3,8,9);U+85F6(1,3,8,9) +U+82C9(0);U+82C9(0); +U+82CA(0);U+82CA(5); +U+82CB(0);U+83A7(1,3,8,9);U+83A7(1,3,8,9) +U+82CC(0);U+8407(4,8,9);U+8407(4,8,9) +U+82CD(0);U+84BC(1,3,8,9);U+84BC(1,3,8,9) +U+82CE(0);U+82E7(4,8,9);U+82E7(4,8,9) +U+82CF(0);U+7526(4,9),U+8607(1,3,8,9);U+56CC(1,3,9),U+7526(4,9),U+8607(1,3,8,9),U+8613(4) + +U+82D0(0);U+82D0(0); +U+82D1(0);U+82D1(5,9); +U+82D2(0);U+82D2(5,9); +U+82D3(0);U+82D3(5,9); +U+82D4(0);U+82D4(5,9); +U+82D5(0);U+82D5(5,9);U+8280(3,9) +U+82D6(0);U+82D6(0,9); +U+82D7(0);U+82D7(5,9); +U+82D8(0);U+82D8(5); +U+82D9(0);U+82D9(0,9); +U+82DA(0);U+82DA(0); +U+82DB(0);U+82DB(5,9); +U+82DC(0);U+82DC(5,9); +U+82DD(0);U+82DD(0); +U+82DE(0);U+82DE(5,9); +U+82DF(0);U+82DF(5,9);U+82B6(3,9) +U+82E0(0);U+82E0(5,9); +U+82E1(0);U+82E1(5,9); +U+82E3(0);U+82E3(5,9); +U+82E4(0);U+82E4(5,9); +U+82E5(0);U+82E5(5,9); +U+82E6(0);U+82E6(5,9);U+7614(3,9) +U+82E7(0);U+82E7(0,9);U+82CE(4,8) +U+82E8(0);U+82E8(0,9); +U+82E9(0);U+82E9(0); +U+82EA(0);U+82EA(0,9); +U+82EB(0);U+82EB(5,9); +U+82EC(0);U+82EC(0,9); +U+82ED(0);U+82ED(0,9); +U+82EE(0);U+82EE(0); +U+82EF(0);U+82EF(5,9); +U+82F0(0);U+82F0(0,9); +U+82F1(0);U+82F1(5,9);U+5040(3,9) +U+82F2(0);U+82F2(0,9); +U+82F3(0);U+82F3(0,9); +U+82F4(0);U+82F4(5,9); +U+82F5(0);U+82F5(0,9); +U+82F6(0);U+82F6(4,9); +U+82F7(0);U+82F7(5); +U+82F8(0);U+82F8(0); +U+82F9(0);U+860B(1,3,8,9);U+860B(1,3,8,9) +U+82FA(0);U+82FA(0,9); +U+82FB(0);U+82FB(5,9); +U+82FD(0);U+83F0(3,8,9);U+83F0(3,8,9),U+83C7(3,4,8,9) +U+82FE(0);U+82FE(3,9); +U+82FF(0);U+83CB(3,8,9);U+83CB(3,8,9) +U+8300(0);U+8300(0,9); +U+8301(0);U+8301(5,9); + +U+8302(0);U+8302(5,9); +U+8303(0);U+8303(1,3,9),U+7BC4(1,3,4,8,9);U+7BC4(1,3,4,8,9) +U+8304(0);U+8304(5,9); +U+8305(0);U+8305(5,9);U+8306(4,8,9) +U+8306(0);U+8306(5,9);U+8305(4,8,9) +U+8307(0);U+8307(5,9); +U+8308(0);U+8308(5,9); +U+8309(0);U+8309(5,9); +U+830B(0);U+830B(0); +U+830C(0);U+830C(5,9); +U+830D(0);U+830D(0,9); +U+830E(0);U+8396(1,3,8,9);U+8396(1,3,8,9) +U+830F(0);U+8622(1,3,8,9);U+8622(1,3,8,9) +U+8311(0);U+8526(1,3,8,9);U+8526(1,3,8,9) +U+8312(0);U+8312(0); +U+8313(0);U+8313(0); +U+8314(0);U+584B(1,3,8,9);U+584B(1,3,8,9) +U+8315(0);U+7162(1,3,8,9);U+60F8(4,9),U+7162(1,3,8,9),U+712D(1,3,4,8) +U+8316(0);U+8316(0,9); +U+8317(0);U+8317(5,9); +U+8318(0);U+8354(2,3,8,9);U+8354(2,3,8,9) +U+8319(0);U+8319(0,9); +U+831A(0);U+831A(5); +U+831B(0);U+831B(5,9); +U+831C(0);U+831C(5,9); +U+831D(0);U+831D(0); +U+831E(0);U+831E(0,9); +U+831F(0);U+831F(0); +U+8320(0);U+8320(0,9); +U+8321(0);U+8321(0); +U+8322(0);U+8322(0,9); +U+8323(0);U+8323(0); +U+8324(0);U+8324(0,9); +U+8325(0);U+8325(0,9); +U+8326(0);U+8326(0,9); +U+8327(0);U+7E6D(1,3,8,9);U+7E6D(1,3,8,9) +U+8328(0);U+8328(5,9); +U+8329(0);U+8329(0,9); +U+832A(0);U+832A(0,9); +U+832B(0);U+832B(5,9);U+6C52(3,9) +U+832C(0);U+832C(5,9); +U+832D(0);U+832D(5,9); +U+832E(0);U+832E(0); +U+832F(0);U+832F(5,9); +U+8331(0);U+8331(5,9); +U+8332(0);U+8332(0,9);U+5179(3,4,8),U+7386(3,8,9) +U+8333(0);U+8333(5,9); +U+8334(0);U+8334(5,9); +U+8335(0);U+8335(5,9); +U+8336(0);U+8336(5,9); +U+8337(0);U+8337(4,9); +U+8338(0);U+8338(5,9); +U+8339(0);U+8339(5,9); +U+833A(0);U+833A(5,9); +U+833B(0);U+833B(0,9);U+83BD(4,9) +U+833C(0);U+833C(5,9); +U+833D(0);U+833D(0); +U+833E(0);U+833E(0); +U+833F(0);U+833F(0,9); +U+8340(0);U+8340(5,9); +U+8341(0);U+8341(0,9); +U+8342(0);U+8342(3,9); +U+8343(0);U+8343(5,9); + +U+8344(0);U+8344(0,9); +U+8345(0);U+8345(0,9);U+7B54(4,8,9),U+7563(0,3,4,8,9) +U+8346(0);U+834A(4,8,9);U+834A(4,8,9) +U+8347(0);U+8347(5,9);U+8395(3,9) +U+8348(0);U+8348(0,9); +U+8349(0);U+8349(5,9);U+8278(2,3,9),U+9A32(4,9) +U+834A(0);U+834A(0,9);U+8346(4,8) +U+834B(0);U+834B(0,9); +U+834C(0);U+834C(0,9); +U+834D(0);U+834D(0,9); +U+834E(0);U+834E(3,9); +U+834F(0);U+834F(5,9); +U+8350(0);U+8350(1,3,9);U+85A6(1,3,8,9) +U+8351(0);U+8351(5,9); +U+8352(0);U+8352(5,9); +U+8353(0);U+8353(0,9); +U+8354(0);U+8354(5,9);U+8318(2,3,8) +U+8356(0);U+8356(0,9); +U+8357(0);U+8357(0); +U+8358(0);U+838A(4,8,9);U+5E84(4,9),U+838A(4,8,9) +U+8359(0);U+8598(4,8,9);U+8598(4,8,9) +U+835A(0);U+83A2(1,3,8,9);U+83A2(1,3,8,9) +U+835B(0);U+8558(1,3,8,9);U+8558(1,3,8,9) +U+835C(0);U+84FD(1,3,8,9);U+84FD(1,3,8,9) +U+835D(0);U+8434(4,8,9);U+8434(4,8,9) +U+835E(0);U+854E(1,3,8,9);U+854E(1,3,8,9) +U+835F(0);U+8588(1,3,8,9);U+8588(1,3,8,9) +U+8360(0);U+85BA(1,3,8,9);U+8415(3),U+85BA(1,3,8,9) +U+8361(0);U+8569(1,3,8,9);U+6F52(3,9),U+76EA(4,9),U+8569(1,3,8,9),U+862F(3) +U+8362(0);U+8362(0); +U+8363(0);U+69AE(1,3,8,9);U+6804(7),U+69AE(1,3,8,9) +U+8364(0);U+8477(1,3,8,9);U+8477(1,3,8,9),U+8512(3,9) +U+8365(0);U+6ECE(1,3,8,9);U+6ECE(1,3,8,9) +U+8366(0);U+7296(1,3,8,9);U+7296(1,3,8,9) +U+8367(0);U+7192(1,3,8,9);U+7192(1,3,8,9) +U+8368(0);U+8541(1,3,8,9);U+8541(1,3,8,9) +U+8369(0);U+85CE(1,3,8,9);U+85CE(1,3,8,9) +U+836A(0);U+84C0(1,3,8,9);U+84C0(1,3,8,9) +U+836B(0);U+852D(1,3,8,9);U+5ED5(4,9),U+852D(1,3,8,9) +U+836C(0);U+8552(1,3,8);U+8552(1,3,8) +U+836D(0);U+8452(1,3,8,9);U+8452(1,3,8,9) +U+836E(0);U+8464(1,3,8);U+8464(1,3,8) +U+836F(0);U+85E5(1,3,8,9);U+846F(4,9),U+85AC(4),U+85E5(1,3,8,9) +U+8370(0);U+8370(0); +U+8371(0);U+8371(0); +U+8372(0);U+8372(0); +U+8373(0);U+8373(0,9);U+8C46(2,9),U+68AA(0,2,3,9) +U+8374(0);U+8374(0,9); +U+8375(0);U+8375(0,9); +U+8376(0);U+8376(3,9); +U+8377(0);U+8377(5,9); +U+8378(0);U+8378(5,9);U+8467(4,9) +U+8379(0);U+8379(0); +U+837A(0);U+837A(0,9); +U+837B(0);U+837B(5,9);U+85E1(3,9) +U+837C(0);U+837C(5,9); +U+837D(0);U+837D(5,9);U+840E(3,8,9) +U+837E(0);U+837E(0,9); +U+837F(0);U+837F(0,9); +U+8380(0);U+8380(0); +U+8381(0);U+8381(0,9); +U+8382(0);U+8382(0); +U+8383(0);U+8383(0,9); + +U+8384(0);U+8384(0); +U+8385(0);U+849E(2,3,8,9);U+849E(2,3,8,9) +U+8386(0);U+8386(5,9); +U+8387(0);U+8387(0,9); +U+8388(0);U+8388(0,9); +U+8389(0);U+8389(5,9); +U+838A(0);U+838A(0,9);U+5E84(1,3,8,9),U+8358(4,8) +U+838B(0);U+838B(3,9); +U+838C(0);U+838C(0,9); +U+838D(0);U+838D(3,9); +U+838E(0);U+838E(5,9); +U+838F(0);U+838F(0,9); +U+8390(0);U+8390(0,9); +U+8391(0);U+8391(0); +U+8392(0);U+8392(5,9); +U+8393(0);U+8393(5,9); +U+8394(0);U+8394(0,9); +U+8395(0);U+8395(0,9);U+8347(3,9) +U+8396(0);U+8396(0,9);U+830E(1,3,8) +U+8397(0);U+8397(0,9); +U+8398(0);U+8398(5,9); +U+8399(0);U+8399(0,9); +U+839A(0);U+839A(3,9); +U+839B(0);U+839B(5,9); +U+839C(0);U+839C(5); +U+839D(0);U+839D(0,9); +U+839E(0);U+839E(5,9); +U+83A0(0);U+83A0(5,9); +U+83A1(0);U+83A1(0); +U+83A2(0);U+83A2(0,9);U+835A(1,3,8) +U+83A3(0);U+83A3(0,9); +U+83A4(0);U+83A4(0,9); +U+83A5(0);U+83A5(0,9); +U+83A6(0);U+83A6(0,9); +U+83A7(0);U+83A7(0,9);U+82CB(1,3,8) +U+83A8(0);U+83A8(5,9); +U+83A9(0);U+83A9(5,9); +U+83AA(0);U+83AA(5,9); +U+83AB(0);U+83AB(5,9); +U+83AC(0);U+83AC(3); +U+83AD(0);U+83AD(0); +U+83AE(0);U+83AE(0,9); +U+83AF(0);U+83AF(0,9); +U+83B0(0);U+83B0(5,9); +U+83B1(0);U+840A(1,3,8,9);U+840A(1,3,8,9),U+90F2(3,9) +U+83B2(0);U+84EE(1,3,8,9);U+84EE(1,3,8,9) +U+83B3(0);U+8494(1,3,8,9);U+8494(1,3,8,9) +U+83B4(0);U+8435(1,3,8,9);U+8435(1,3,8,9) +U+83B6(0);U+859F(4,8,9);U+859F(4,8,9) +U+83B7(0);U+7372(1,3,8,9),U+7A6B(1,3,8,9);U+7372(1,3,8,9),U+7A6B(1,3,8,9) +U+83B8(0);U+8555(1,3,8,9);U+8555(1,3,8,9) +U+83B9(0);U+7469(1,3,8,9);U+7469(1,3,8,9) +U+83BA(0);U+9DAF(1,3,8,9);U+9DAF(1,3,8,9) +U+83BB(0);U+83BB(0); +U+83BC(0);U+84F4(2,9);U+84F4(2,9),U+8493(1,3,8) +U+83BD(0);U+83BD(5,9);U+833B(4,9) +U+83BF(0);U+83BF(0,9); +U+83C0(0);U+83C0(5,9); +U+83C1(0);U+83C1(5,9); +U+83C2(0);U+83C2(3,9); +U+83C3(0);U+83C3(0,9); +U+83C4(0);U+83C4(0,9); +U+83C5(0);U+83C5(5,9);U+844C(3,9) + +U+83C6(0);U+83C6(0,9); +U+83C7(0);U+83C7(5,9);U+83F0(3,4,9),U+82FD(0,3,4,8) +U+83C8(0);U+83C8(0,9); +U+83C9(0);U+83C9(0,9); +U+83CA(0);U+83CA(5,9);U+861C(4,9) +U+83CB(0);U+83CB(3,9);U+82FF(3,8) +U+83CC(0);U+83CC(5,9); +U+83CD(0);U+83CD(0); +U+83CE(0);U+83CE(0,9); +U+83CF(0);U+83CF(5,9);U+6E2E(3,9) +U+83D0(0);U+83D0(0); +U+83D1(0);U+83D1(3,9); +U+83D2(0);U+83D2(0); +U+83D3(0);U+83D3(0);U+679C(2,3,9) +U+83D4(0);U+83D4(5,9);U+8514(4,8,9),U+535C(1,3,4,8,9) +U+83D5(0);U+83D5(0,9); +U+83D6(0);U+83D6(5,9); +U+83D7(0);U+83D7(0,9); +U+83D8(0);U+83D8(5,9); +U+83D9(0);U+83D9(0,9); +U+83DA(0);U+83DA(0); +U+83DB(0);U+83DB(0,9); +U+83DC(0);U+83DC(5,9); +U+83DD(0);U+83DD(5,9); +U+83DE(0);U+83DE(0,9);U+9ECE(3,9) +U+83DF(0);U+83DF(5,9); +U+83E0(0);U+83E0(5,9); +U+83E1(0);U+83E1(5,9); +U+83E2(0);U+83E2(3,9); +U+83E3(0);U+83E3(0,9); +U+83E4(0);U+83E4(0,9); +U+83E5(0);U+83E5(5,9); +U+83E7(0);U+83E7(0,9); +U+83E8(0);U+83E8(0,9); +U+83E9(0);U+83E9(5,9); +U+83EA(0);U+83EA(5,9); +U+83EB(0);U+83EB(0,9);U+5807(4,8,9),U+84F3(3,4,8,9) +U+83EC(0);U+83EC(0,9); +U+83EE(0);U+83EE(0,9); +U+83EF(0);U+83EF(0,9);U+534E(1,3,8),U+5D0B(3,8,9) +U+83F0(0);U+83F0(5,9);U+82FD(3,8),U+83C7(3,4,9) +U+83F1(0);U+83F1(5,9);U+8506(2,3,9) +U+83F2(0);U+83F2(5,9); +U+83F3(0);U+83F3(0,9); +U+83F4(0);U+83F4(3,9);U+5EB5(2,3,8,9) +U+83F5(0);U+83F5(0,9); +U+83F6(0);U+83F6(0,9); +U+83F7(0);U+5E1A(3,8,9);U+5E1A(3,8,9) +U+83F8(0);U+83F8(5,9);U+70DF(2),U+7159(4,8,9) +U+83F9(0);U+83F9(5,9);U+8445(3,9) +U+83FA(0);U+83FA(0,9); +U+83FB(0);U+83FB(0,9); +U+83FC(0);U+83FC(0,9); +U+83FD(0);U+83FD(5,9); +U+83FE(0);U+83FE(0,9); +U+83FF(0);U+83FF(3,9); +U+8400(0);U+8400(0); +U+8401(0);U+8401(5,9); +U+8402(0);U+8402(0); +U+8403(0);U+8403(5,9); +U+8404(0);U+8404(5,9); +U+8405(0);U+6625(3,8,9);U+6625(3,8,9) +U+8406(0);U+8406(5,9); + +U+8407(0);U+8407(0,9);U+82CC(4,8) +U+8408(0);U+8408(3); +U+8409(0);U+8409(0,9); +U+840A(0);U+840A(0,9);U+83B1(1,3,8),U+90F2(1,3,8,9) +U+840B(0);U+840B(5,9); +U+840C(0);U+840C(5,9);U+8544(4,9) +U+840D(0);U+840D(5,9); +U+840E(0);U+840E(5,9);U+837D(3,8,9) +U+840F(0);U+840F(5,9); +U+8410(0);U+8410(0,9); +U+8411(0);U+8411(5,9); +U+8412(0);U+8412(0,9); +U+8413(0);U+8413(3,9); +U+8415(0);U+85BA(3,8,9);U+8360(3),U+85BA(3,8,9) +U+8418(0);U+8418(5); +U+8419(0);U+8419(0); +U+841A(0);U+8600(1,3,8,9);U+8600(1,3,8,9) +U+841B(0);U+841B(0,9); +U+841C(0);U+841C(5); +U+841D(0);U+863F(1,3,8,9);U+863F(1,3,8,9) +U+841E(0);U+841E(0); +U+8421(0);U+8421(0); +U+8422(0);U+8422(0); +U+8423(0);U+8423(0,9); +U+8424(0);U+87A2(1,3,8,9);U+87A2(1,3,8,9) +U+8425(0);U+71DF(1,3,8,9);U+55B6(4),U+71DF(1,3,8,9) +U+8426(0);U+7E08(1,3,8,9);U+7E08(1,3,8,9) +U+8427(0);U+856D(1,3,8,9);U+856D(1,3,8,9) +U+8428(0);U+85A9(1,3,8,9);U+85A9(1,3,8,9) +U+8429(0);U+8429(0,9); +U+842A(0);U+842A(0); +U+842B(0);U+842B(0,9); +U+842C(0);U+842C(0,9);U+4E07(1,3,8,9) +U+842D(0);U+842D(0,9); +U+842E(0);U+842E(0); +U+842F(0);U+842F(0,9); +U+8430(0);U+8430(0,9); +U+8431(0);U+8431(5,9);U+8432(2,9) +U+8432(0);U+8432(0,9);U+8431(2,9) +U+8433(0);U+8433(0,9); +U+8434(0);U+8434(0,9);U+835D(4,8) +U+8435(0);U+8435(0,9);U+83B4(1,3,8) +U+8436(0);U+8436(0,9); +U+8437(0);U+8437(0,9); +U+8438(0);U+8438(5,9); +U+8439(0);U+8439(0,9); +U+843A(0);U+843A(0,9); +U+843B(0);U+843B(0,9); +U+843C(0);U+843C(5,9);U+855A(2,3,8) +U+843D(0);U+843D(5,9); +U+843E(0);U+843E(0); +U+843F(0);U+843F(0,9); +U+8440(0);U+8440(0,9); +U+8441(0);U+8441(0); +U+8442(0);U+8442(0,9); +U+8443(0);U+8443(0,9); +U+8444(0);U+8444(0,9); +U+8445(0);U+8445(0,9);U+83F9(3,9) +U+8446(0);U+8446(5,9); +U+8447(0);U+8447(0,9); +U+8448(0);U+8448(0); +U+8449(0);U+8449(0,9);U+53F6(1,3,8) +U+844A(0);U+844A(0); + +U+844B(0);U+844B(3,9); +U+844C(0);U+844C(0,9);U+83C5(3,9) +U+844D(0);U+844D(0,9); +U+844E(0);U+844E(0,9); +U+844F(0);U+844F(0); +U+8450(0);U+8450(0,9); +U+8451(0);U+8451(5,9); +U+8452(0);U+8452(0,9);U+836D(1,3,8) +U+8453(0);U+8453(0); +U+8454(0);U+8454(0,9); +U+8455(0);U+8455(0); +U+8456(0);U+8456(0,9); +U+8457(0);U+8457(5,9);U+7740(4,8) +U+8459(0);U+8459(5,9); +U+845A(0);U+845A(5,9); +U+845B(0);U+845B(5,9); +U+845C(0);U+845C(5); +U+845D(0);U+845D(0,9); +U+845E(0);U+845E(0,9); +U+845F(0);U+845F(0,9); +U+8460(0);U+8460(0,9);U+53C2(4),U+53C1(4,5),U+53C3(4,8,9),U+84E1(4),U+53C4(3,4) +U+8461(0);U+8461(5,9); +U+8462(0);U+84CB(3,8,9);U+76D6(3),U+84CB(3,8,9) +U+8463(0);U+8463(5,9);U+856B(3,9) +U+8464(0);U+8464(0);U+836E(1,3,8) +U+8465(0);U+8465(0,9); +U+8466(0);U+8466(0,9);U+82C7(1,3,8) +U+8467(0);U+8467(0,9);U+8378(4,9) +U+8468(0);U+8468(0,9); +U+8469(0);U+8469(5,9); +U+846A(0);U+846A(0); +U+846B(0);U+846B(5,9); +U+846C(0);U+846C(5,9);U+585F(2,3,8) +U+846D(0);U+846D(5,9); +U+846E(0);U+846E(0,9);U+6934(3,9) +U+846F(0);U+846F(0,9);U+836F(4),U+85AC(4),U+85E5(1,3,4,8,9) +U+8470(0);U+8470(3,9); +U+8471(0);U+8525(2,3,9);U+8525(2,3,9) +U+8472(0);U+8472(0); +U+8473(0);U+8473(5,9); +U+8474(0);U+8474(0,9); +U+8475(0);U+8475(5,9); +U+8476(0);U+8476(5,9); +U+8477(0);U+8477(0,9);U+8364(1,3,8),U+8512(1,3,8,9) +U+8478(0);U+8478(5,9); +U+8479(0);U+8479(0,9); +U+847A(0);U+847A(5,9); +U+847B(0);U+847B(0); +U+847C(0);U+847C(0); +U+847D(0);U+847D(0,9); +U+847E(0);U+847E(0,9); +U+847F(0);U+847F(0); +U+8480(0);U+8480(0); +U+8481(0);U+8481(0); +U+8482(0);U+8482(5,9); +U+8484(0);U+8484(0); +U+8485(0);U+8485(0); +U+8486(0);U+8486(0,9); +U+8487(0);U+8546(1,3,8,9);U+8546(1,3,8,9) +U+8488(0);U+8488(5); +U+8489(0);U+8562(1,3,8,9);U+8562(1,3,8,9) +U+848A(0);U+848A(0); +U+848B(0);U+8523(1,3,4,8,9);U+8523(1,3,4,8,9) + +U+848C(0);U+851E(1,3,8,9);U+851E(1,3,8,9) +U+848D(0);U+848D(0,9);U+853F(4,8) +U+848E(0);U+848E(5,9); +U+848F(0);U+848F(0,9); +U+8490(0);U+8490(3,9); +U+8491(0);U+8491(0,9); +U+8492(0);U+8492(0); +U+8493(0);U+84F4(2,8,9);U+84F4(2,8,9),U+83BC(1,3,8) +U+8494(0);U+8494(0,9);U+83B3(1,3,8) +U+8496(0);U+8496(0); +U+8497(0);U+8497(5,9); +U+8498(0);U+8498(0,9); +U+8499(0);U+8499(1,3,9),U+61DE(1,4,8,9),U+6FDB(1,3,4,9),U+77C7(1,4,8,9);U+61DE(1,4,8,9),U+6FDB(1,3,4,9),U+77C7(1,4,8,9) + +U+849A(0);U+849A(0,9); +U+849B(0);U+849B(0,9); +U+849C(0);U+849C(5,9); +U+849D(0);U+849D(0,9); +U+849E(0);U+849E(0,9);U+8385(2,3,8) +U+849F(0);U+849F(0,9); +U+84A0(0);U+84A0(0,9); +U+84A1(0);U+84A1(5,9); +U+84A2(0);U+84A2(0,9); +U+84A3(0);U+84A3(0); +U+84A4(0);U+84A4(0,9); +U+84A5(0);U+84A5(0); +U+84A6(0);U+84A6(3); +U+84A7(0);U+84A7(0,9); +U+84A8(0);U+84A8(3,9); +U+84A9(0);U+84A9(0,9); +U+84AA(0);U+84AA(0,9); +U+84AB(0);U+84AB(0,9); +U+84AC(0);U+84AC(0,9); +U+84AE(0);U+84AE(0,9); +U+84AF(0);U+84AF(5,9); +U+84B0(0);U+84B0(0,9); +U+84B1(0);U+84B1(0,9); +U+84B2(0);U+84B2(5,9); +U+84B3(0);U+84B3(0); +U+84B4(0);U+84B4(5,9); +U+84B5(0);U+84B5(0); +U+84B6(0);U+84B6(0,9); +U+84B8(0);U+84B8(5,9); +U+84B9(0);U+84B9(5,9); +U+84BA(0);U+84BA(5,9); +U+84BB(0);U+84BB(0,9); +U+84BC(0);U+84BC(0,9);U+82CD(1,3,8) +U+84BD(0);U+84BD(5); +U+84BE(0);U+84BE(0); +U+84BF(0);U+84BF(5,9); +U+84C0(0);U+84C0(0,9);U+836A(1,3,8) +U+84C1(0);U+84C1(5,9); +U+84C2(0);U+84C2(0,9); +U+84C4(0);U+84C4(5,9); +U+84C5(0);U+84C5(0,9); +U+84C6(0);U+84C6(0,9);U+5E2D(2,3,8,9),U+5ED7(2,3,4,8,9) +U+84C7(0);U+84C7(0,9); +U+84C8(0);U+84C8(3); +U+84C9(0);U+84C9(5,9); +U+84CA(0);U+84CA(5,9); +U+84CB(0);U+84CB(0,9);U+8462(3,8),U+76D6(1,3,8) +U+84CC(0);U+84CC(0,9); +U+84CD(0);U+84CD(5,9); + +U+84CE(0);U+84CE(0,9); +U+84CF(0);U+84CF(0,9); +U+84D0(0);U+84D0(5,9); +U+84D1(0);U+7C11(2,8,9);U+7C11(2,8,9) +U+84D2(0);U+84D2(0,9); +U+84D3(0);U+84D3(5,9); +U+84D4(0);U+84D4(0,9); +U+84D5(0);U+84D5(3); +U+84D6(0);U+84D6(5,9); +U+84D7(0);U+84D7(0,9); +U+84D8(0);U+8509(3,4,9);U+8509(3,4,9) +U+84D9(0);U+84D9(0); +U+84DB(0);U+84DB(0,9); +U+84DC(0);U+84DC(0); +U+84DD(0);U+85CD(1,3,8,9);U+85CD(1,3,8,9) +U+84DE(0);U+84DE(0); +U+84DF(0);U+858A(1,3,8,9);U+858A(1,3,8,9) +U+84E0(0);U+863A(4,8,9);U+863A(4,8,9) +U+84E1(0);U+53C3(2,3,8,9);U+53C2(4),U+53C3(2,3,8,9),U+53C1(4,5),U+53C4(3,4),U+8460(4,9) + +U+84E2(0);U+84E2(0); +U+84E3(0);U+8577(1,3,8,9);U+8577(1,3,8,9) +U+84E4(0);U+84E4(0); +U+84E5(0);U+93A3(4,8,9);U+93A3(4,8,9) +U+84E6(0);U+9A40(1,3,8,9);U+9A40(1,3,8,9) +U+84E7(0);U+84E7(3,9); +U+84E8(0);U+84E8(4,9); +U+84E9(0);U+84E9(0,9); +U+84EA(0);U+84EA(0,9); +U+84EB(0);U+84EB(0,9); +U+84EC(0);U+84EC(5,9); +U+84EE(0);U+84EE(0,9);U+83B2(1,3,8) +U+84EF(0);U+84EF(0,9);U+82C1(1,3,8) +U+84F0(0);U+84F0(5,9); +U+84F1(0);U+84F1(0,9); +U+84F2(0);U+84F2(0,9); +U+84F3(0);U+84F3(0,9);U+5807(3,9),U+83EB(3,4,8,9) +U+84F4(0);U+84F4(0,9);U+83BC(2),U+8493(2,8) +U+84F5(0);U+84F5(0); +U+84F6(0);U+84F6(0,9); +U+84F7(0);U+84F7(0,9); +U+84F8(0);U+84F8(0); +U+84F9(0);U+84F9(0,9); +U+84FA(0);U+84FA(0,9);U+827A(3),U+517F(0,3,4),U+85DD(3,4,8,9) +U+84FB(0);U+84FB(0,9); +U+84FC(0);U+84FC(5,9); +U+84FD(0);U+84FD(0,9);U+835C(1,3,8) +U+84FE(0);U+84FE(0,9); +U+84FF(0);U+84FF(5,9); +U+8500(0);U+8500(0,9); +U+8501(0);U+8501(0); +U+8502(0);U+8502(0,9); +U+8503(0);U+8503(0); +U+8504(0);U+8504(0); +U+8506(0);U+8506(0,9);U+83F1(2,3,9) +U+8507(0);U+8507(0,9);U+66A8(4,9),U+66C1(4,8),U+81EE(4,9) +U+8508(0);U+8508(0,9); +U+8509(0);U+8509(0,9);U+84D8(3,4) +U+850A(0);U+850A(0,9); +U+850B(0);U+850B(0,9); +U+850C(0);U+850C(5,9); +U+850D(0);U+850D(0,9);U+7C97(3,9),U+89D5(2,3,9),U+9E81(3,4,8),U+9E84(3,8),U+9E86(3,9),U+9EA4(2,3,9) + + +U+850E(0);U+850E(0,9); +U+850F(0);U+850F(0,9); +U+8511(0);U+8511(1,3,9);U+858E(3,9),U+884A(1,3,4,9) +U+8512(0);U+8512(0,9);U+8364(3),U+8477(1,3,8,9) +U+8513(0);U+8513(5,9); +U+8514(0);U+8514(0,9);U+535C(1,3,8,9),U+83D4(4,8,9) +U+8515(0);U+8515(4,9); +U+8516(0);U+8516(0,9); +U+8517(0);U+8517(5,9); +U+8518(0);U+8518(0,9); +U+8519(0);U+8519(0,9); +U+851A(0);U+851A(5,9); +U+851B(0);U+851B(0); +U+851C(0);U+851C(0,9); +U+851D(0);U+851D(0,9); +U+851E(0);U+851E(0,9);U+848C(1,3,8) +U+851F(0);U+851F(5,9); +U+8520(0);U+8520(0,9); +U+8521(0);U+8521(5,9); +U+8522(0);U+8522(0); +U+8523(0);U+8523(0,9);U+848B(1,3,8) +U+8524(0);U+8524(3,9); +U+8525(0);U+8525(0,9);U+8471(2,3) +U+8526(0);U+8526(0,9);U+8311(1,3,8) +U+8527(0);U+8527(3,9); +U+8528(0);U+8528(0,9); +U+8529(0);U+8529(0,9); +U+852A(0);U+852A(0,9); +U+852B(0);U+852B(5,9); +U+852C(0);U+852C(5,9); +U+852D(0);U+852D(0,9);U+836B(1,3,8),U+5ED5(0,1,3,4,8,9) +U+852E(0);U+852E(0,9);U+5E3C(4),U+5E57(1,3,4,8,9) +U+852F(0);U+852F(0,9); +U+8530(0);U+8530(0,9); +U+8531(0);U+8531(0,9);U+699D(3),U+6A27(3,4,9) +U+8534(0);U+9EBB(2,3,9);U+9EBB(2,3,9),U+75F2(0,2,3,9),U+75F3(2,3,4,9),U+6DCB(2,3,4,5,9) + +U+8535(0);U+85CF(3,8,9);U+85CF(3,8,9) +U+8536(0);U+8536(0); +U+8537(0);U+8594(1,3,8,9);U+8594(1,3,8,9) +U+8538(0);U+8538(5); +U+8539(0);U+861E(1,3,8,9);U+861E(1,3,8,9) +U+853A(0);U+85FA(1,3,8,9);U+85FA(1,3,8,9) +U+853B(0);U+853B(5,9); +U+853C(0);U+85F9(1,3,8,9);U+85F9(1,3,8,9),U+8B6A(3,9) +U+853D(0);U+853D(5,9); +U+853E(0);U+853E(0,9);U+85DC(2,9) +U+853F(0);U+848D(4,8,9);U+848D(4,8,9) +U+8540(0);U+8540(0,9); +U+8541(0);U+8541(0,9);U+8368(1,3,8) +U+8542(0);U+8542(0); +U+8543(0);U+8543(5,9); +U+8544(0);U+8544(0,9);U+840C(4,9) +U+8545(0);U+8545(0,9);U+85D5(3,9) +U+8546(0);U+8546(0,9);U+8487(1,3,8) +U+8547(0);U+8547(0,9); +U+8548(0);U+8548(5,9); +U+8549(0);U+8549(5,9); +U+854A(0);U+854A(5,9);U+6A64(2,3,9),U+854B(2,3,8),U+8602(2,3,8) +U+854B(0);U+854A(2,3,8,9);U+854A(2,3,8,9),U+6A64(0,2,3,8,9),U+8602(2,3,8) +U+854D(0);U+854D(0,9); +U+854E(0);U+854E(0,9);U+835E(1,3,8) +U+854F(0);U+85F8(3,9);U+85F8(3,9) + +U+8551(0);U+8551(0,9); +U+8552(0);U+8552(0);U+836C(1,3,8) +U+8553(0);U+8553(0,9);U+82B8(1,3,8,9) +U+8554(0);U+8554(0,9); +U+8555(0);U+8555(0,9);U+83B8(1,3,8) +U+8556(0);U+8556(5,9); +U+8557(0);U+8557(0,9); +U+8558(0);U+8558(0,9);U+835B(1,3,8) +U+8559(0);U+8559(5,9); +U+855A(0);U+843C(2,3,8,9);U+843C(2,3,8,9) +U+855B(0);U+855B(3,9); +U+855C(0);U+855C(3); +U+855D(0);U+855D(0,9); +U+855E(0);U+855E(5,9); +U+855F(0);U+855F(0); +U+8560(0);U+8560(0,9); +U+8561(0);U+8561(0,9); +U+8562(0);U+8562(0,9);U+8489(1,3,8) +U+8563(0);U+8563(3,9); +U+8564(0);U+8564(5,9); +U+8565(0);U+8565(0,9); +U+8566(0);U+8566(0,9); +U+8567(0);U+8567(0,9); +U+8568(0);U+8568(5,9); +U+8569(0);U+8569(0,9);U+76EA(2,3,9),U+8361(1,3,8),U+862F(3),U+6F52(0,1,3,8,9) +U+856A(0);U+856A(0,9);U+829C(1,3,8) +U+856B(0);U+856B(0,9);U+8463(3,9) +U+856C(0);U+856C(0,9); +U+856D(0);U+856D(0,9);U+8427(1,3,8) +U+856E(0);U+856E(0,9); +U+856F(0);U+856F(0); +U+8570(0);U+8580(4,8,9);U+8580(4,8,9) +U+8571(0);U+8571(0,9);U+7A0D(4,9) +U+8572(0);U+8604(1,3,8,9);U+8604(1,3,8,9) +U+8573(0);U+8573(0); +U+8574(0);U+860A(4,8,9);U+85F4(1,3,8),U+860A(4,8,9) +U+8575(0);U+8575(4,9);U+859E(4,9) +U+8576(0);U+8576(0,9); +U+8577(0);U+8577(0,9);U+84E3(1,3,8) +U+8578(0);U+8578(3,9); +U+8579(0);U+8579(5,9); +U+857A(0);U+857A(5,9); +U+857B(0);U+857B(5,9); +U+857C(0);U+857C(0,9); +U+857D(0);U+857D(0); +U+857E(0);U+857E(5,9); +U+8580(0);U+8580(0,9);U+8570(4,8) +U+8581(0);U+8581(0,9); +U+8582(0);U+8582(0,9); +U+8583(0);U+8583(0,9); +U+8584(0);U+8584(5,9); +U+8585(0);U+8585(5,9); +U+8586(0);U+8586(0,9); +U+8587(0);U+8587(5,9); +U+8588(0);U+8588(0,9);U+835F(1,3,8) +U+8589(0);U+8589(0,9);U+79FD(3),U+7A62(1,3,8,9) +U+858A(0);U+858A(0,9);U+84DF(1,3,8) +U+858B(0);U+858B(0,9); +U+858C(0);U+858C(0,9);U+8297(1,3,8) +U+858D(0);U+858D(0,9); +U+858E(0);U+858E(0,9);U+8511(3,9),U+884A(1,3,4,9) +U+858F(0);U+858F(5,9); +U+8590(0);U+8590(0,9); + +U+8591(0);U+8591(0,9);U+59DC(1,3,8,9) +U+8592(0);U+8592(0); +U+8594(0);U+8594(0,9);U+8537(1,3,8) +U+8595(0);U+8595(0,9); +U+8596(0);U+8596(3,9); +U+8598(0);U+8598(0,9);U+8359(4,8) +U+8599(0);U+8599(0,9);U+5243(2,9) +U+859A(0);U+859A(0,9); +U+859B(0);U+859B(5,9); +U+859C(0);U+859C(5,9); +U+859D(0);U+859D(0,9); +U+859E(0);U+859E(0,9);U+8575(4,9) +U+859F(0);U+859F(0,9);U+83B6(4,8) +U+85A0(0);U+85A0(0,9); +U+85A1(0);U+85A1(0,9); +U+85A2(0);U+85A2(0,9); +U+85A3(0);U+85A3(0,9); +U+85A4(0);U+85A4(5,9); +U+85A5(0);U+85A5(0); +U+85A6(0);U+85A6(0,9);U+8350(1,3,8,9) +U+85A7(0);U+85A7(0,9); +U+85A8(0);U+85A8(5,9); +U+85A9(0);U+85A9(0,9);U+8428(1,3,8) +U+85AA(0);U+85AA(5,9); +U+85AB(0);U+85B0(4,8,9);U+85B0(4,8,9) +U+85AC(0);U+85E5(4,8,9);U+836F(4),U+85E5(4,8,9),U+846F(4,9) +U+85AD(0);U+85AD(0); +U+85AE(0);U+85EA(1,3,8,9);U+85EA(1,3,8,9),U+7C54(1,3,8,9) +U+85AF(0);U+85AF(5,9);U+85F7(2,9) +U+85B0(0);U+85B0(5,9);U+85AB(4,8) +U+85B1(0);U+85B1(0,9); +U+85B3(0);U+85B3(0,9); +U+85B4(0);U+85B4(0,9); +U+85B5(0);U+85B5(0,9); +U+85B6(0);U+85B6(0,9); +U+85B7(0);U+85B7(5,9); +U+85B8(0);U+85B8(0,9); +U+85B9(0);U+85B9(5,9); +U+85BA(0);U+85BA(0,9);U+8360(1,3,8),U+8415(3,8) +U+85BC(0);U+85BC(0); +U+85BD(0);U+85BD(0,9); +U+85BE(0);U+85BE(3,9); +U+85BF(0);U+85BF(0,9); +U+85C0(0);U+85C0(0,9); +U+85C1(0);U+85C1(5); +U+85C2(0);U+85C2(0,9);U+4E1B(3),U+53E2(1,3,4,8,9),U+6B09(3,9) +U+85C3(0);U+85C3(3,9); +U+85C4(0);U+85C4(0,9); +U+85C5(0);U+85C5(0,9); +U+85C6(0);U+85C6(0,9); +U+85C7(0);U+85C7(0,9); +U+85C8(0);U+85C8(0,9); +U+85C9(0);U+85C9(0,9);U+501F(1,3,8,9),U+8024(3,8,9) +U+85CA(0);U+85CA(3); +U+85CB(0);U+85CB(0,9); +U+85CD(0);U+85CD(0,9);U+84DD(1,3,8) +U+85CE(0);U+85CE(0,9);U+8369(1,3,8) +U+85CF(0);U+85CF(5,9);U+8535(3,8) +U+85D0(0);U+85D0(5,9); +U+85D1(0);U+85D1(0,9); +U+85D2(0);U+85D2(0,9); +U+85D3(0);U+861A(1,3,8,9);U+861A(1,3,8,9) +U+85D4(0);U+85D4(0); + +U+85D5(0);U+85D5(5,9);U+8545(3,9) +U+85D6(0);U+85D6(0); +U+85D7(0);U+85D7(0,9); +U+85D8(0);U+85D8(0,9); +U+85D9(0);U+85D9(0,9); +U+85DA(0);U+85DA(0,9); +U+85DB(0);U+85DB(0); +U+85DC(0);U+85DC(5,9);U+853E(2,9) +U+85DD(0);U+85DD(0,9);U+517F(4,8),U+827A(1,3,8),U+84FA(3,4,8,9) +U+85DE(0);U+85DE(0,9); +U+85DF(0);U+85DF(4,9); +U+85E0(0);U+85E0(0); +U+85E1(0);U+85E1(0,9);U+837B(3,9) +U+85E2(0);U+85E2(0,9); +U+85E3(0);U+85E3(0,9); +U+85E4(0);U+85E4(5,9),U+7C50(2,3,9);U+7C50(2,3,9),U+7C58(7) +U+85E5(0);U+85E5(0,9);U+836F(1,3,8),U+85AC(4,8),U+846F(1,3,4,8,9) +U+85E6(0);U+85E6(0,9); +U+85E7(0);U+85E7(0); +U+85E8(0);U+85E8(3,9); +U+85E9(0);U+85E9(5,9);U+7C53(3,9) +U+85EA(0);U+85EA(0,9);U+7C54(3,8,9),U+85AE(1,3,8) +U+85EB(0);U+85EB(0,9); +U+85EC(0);U+85EC(0,9); +U+85ED(0);U+85ED(0,9);U+44D6(1,3) +U+85EF(0);U+85EF(0,9); +U+85F0(0);U+85F0(0,9); +U+85F1(0);U+85F1(0,9); +U+85F2(0);U+85F2(0,9); +U+85F4(0);U+860A(4,8,9);U+8574(1,3,8),U+860A(4,8,9) +U+85F5(0);U+85F5(0); +U+85F6(0);U+85F6(0,9);U+82C8(1,3,8) +U+85F7(0);U+85F7(0,9);U+85AF(2,9) +U+85F8(0);U+85F8(0,9);U+854F(3) +U+85F9(0);U+85F9(0,9);U+853C(1,3,8),U+8B6A(1,3,8,9) +U+85FA(0);U+85FA(0,9);U+853A(1,3,8) +U+85FB(0);U+85FB(5,9); +U+85FD(0);U+85FD(0,9);U+6987(3),U+6AEC(1,3,8,9) +U+85FE(0);U+85FE(0,9); +U+85FF(0);U+85FF(5,9); +U+8600(0);U+8600(0,9);U+841A(1,3,8) +U+8601(0);U+8601(0,9); +U+8602(0);U+854A(2,3,8,9);U+854A(2,3,8,9),U+6A64(0,2,3,8,9),U+854B(2,3,8) +U+8604(0);U+8604(0,9);U+8572(1,3,8) +U+8605(0);U+8605(5,9); +U+8606(0);U+8606(0,9);U+82A6(1,3,8) +U+8607(0);U+8607(0,9);U+56CC(4,8,9),U+82CF(1,3,8),U+8613(2,8),U+7526(1,3,4,8,9) +U+8608(0);U+8608(0); +U+8609(0);U+8609(0,9); +U+860A(0);U+860A(0,9);U+8574(4,8),U+85F4(4,8) +U+860B(0);U+860B(0,9);U+82F9(1,3,8,9) +U+860C(0);U+860C(0,9); +U+860F(0);U+860F(0);U+8614(7,8) +U+8611(0);U+8611(5,9); +U+8612(0);U+8612(0); +U+8613(0);U+8607(2,8,9);U+82CF(4),U+8607(2,8,9),U+56CC(0,1,3,4,9),U+7526(1,3,4,9) +U+8614(0);U+860F(7,8);U+860F(7,8) +U+8616(0);U+8616(5);U+6AF1(4,9) +U+8617(0);U+8617(0,9);U+6A97(4,9) +U+8618(0);U+8618(0,9); +U+8619(0);U+8619(0,9); +U+861A(0);U+861A(0,9);U+85D3(1,3,8) +U+861B(0);U+861B(0,9); + +U+861C(0);U+861C(0,9);U+83CA(4,9) +U+861E(0);U+861E(0,9);U+8539(1,3,8) +U+861F(0);U+861F(0,9); +U+8620(0);U+8620(0,9); +U+8621(0);U+8621(0,9); +U+8622(0);U+8622(0,9);U+830F(1,3,8) +U+8623(0);U+8623(0,9); +U+8624(0);U+8624(0,9);U+82B1(2,3,9) +U+8625(0);U+8625(0,9); +U+8626(0);U+8626(0,9); +U+8627(0);U+8627(5,9); +U+8628(0);U+8628(0); +U+8629(0);U+8629(5,9); +U+862A(0);U+862A(0,9); +U+862B(0);U+862B(3); +U+862C(0);U+862C(0,9);U+867A(4,9) +U+862D(0);U+862D(0,9);U+5170(1,3,8) +U+862E(0);U+862E(0,9); +U+862F(0);U+8569(3,9);U+8361(3),U+8569(3,9),U+6F52(0,3,9),U+76EA(3,4,9) +U+8630(0);U+8630(0); +U+8631(0);U+8631(0,9); +U+8632(0);U+8632(0,9); +U+8633(0);U+8633(0,9); +U+8634(0);U+8634(0,9); +U+8635(0);U+8635(0,9); +U+8636(0);U+8636(0,9); +U+8638(0);U+8638(5,9); +U+8639(0);U+8639(0,9); +U+863A(0);U+863A(0,9);U+84E0(4,8) +U+863B(0);U+863B(0,9); +U+863C(0);U+863C(5,9); +U+863D(0);U+863D(3);U+6AD0(3,9) +U+863E(0);U+863E(0,9); +U+863F(0);U+863F(0,9);U+841D(1,3,8) +U+8640(0);U+8640(0,9);U+9F51(3),U+97F2(3),U+9F4F(1,3,8,9) +U+8641(0);U+8641(0); +U+8642(0);U+8642(0); +U+8643(0);U+8643(0,9); +U+8644(0);U+8644(0); +U+8645(0);U+8645(0); +U+8646(0);U+8646(3,9); +U+8647(0);U+8647(0,9); +U+8648(0);U+8648(0,9); +U+8649(0);U+8649(0); +U+864A(0);U+864A(0); +U+864B(0);U+864B(0,9); +U+864C(0);U+864C(0,9); +U+864D(0);U+864D(5,9); +U+864E(0);U+864E(5,9); +U+864F(0);U+865C(1,8,9);U+865C(1,8,9) +U+8650(0);U+8650(3,9); +U+8651(0);U+616E(1,3,8,9);U+616E(1,3,8,9) +U+8652(0);U+8652(4,9); +U+8653(0);U+8653(3,9); +U+8654(0);U+8654(5,9); +U+8655(0);U+8655(0,9);U+5904(1,3,8) +U+8656(0);U+8656(0,9);U+547C(2,3,8,9),U+5611(2,3,8),U+8B3C(2,3,8,9) +U+8658(0);U+8658(0); +U+8659(0);U+8659(0,9); +U+865A(0);U+865B(3,8,9);U+865B(3,8,9) +U+865B(0);U+865B(0,9);U+865A(3,8) +U+865C(0);U+865C(0,9);U+864F(1,8) +U+865D(0);U+865D(0); + +U+865E(0);U+865E(5,9); +U+865F(0);U+865F(0,9);U+53F7(1,3,8),U+8B79(1,3,8,9) +U+8660(0);U+8660(0); +U+8661(0);U+8661(3,9); +U+8662(0);U+8662(5,9); +U+8663(0);U+8663(0,9);U+66B4(3,9) +U+8664(0);U+8664(0,9); +U+8665(0);U+8665(4,9); +U+8666(0);U+8666(3); +U+8667(0);U+8667(0,9);U+4E8F(1,3,8) +U+8668(0);U+8668(0,9); +U+8669(0);U+8669(4,9); +U+866A(0);U+866A(0,9); +U+866B(0);U+87F2(1,3,8,9);U+87F2(1,3,8,9) +U+866C(0);U+866C(5);U+866F(2,3,9) +U+866D(0);U+866D(0,9); +U+866E(0);U+866E(1,3,9);U+87E3(1,3,8,9) +U+866F(0);U+866F(0,9);U+866C(2,3) +U+8670(0);U+8670(0,9); +U+8671(0);U+8768(2,3,8,9);U+8768(2,3,8,9) +U+8672(0);U+8672(0); +U+8673(0);U+8673(0,9); +U+8674(0);U+8674(0,9); +U+8676(0);U+8676(0); +U+8677(0);U+8677(0,9); +U+8678(0);U+8678(0); +U+8679(0);U+8679(5,9); +U+867A(0);U+867A(5,9);U+862C(4,9) +U+867B(0);U+867B(5,9); +U+867C(0);U+867C(5,9); +U+867D(0);U+96D6(1,3,8,9);U+96D6(1,3,8,9) +U+867E(0);U+8766(1,3,8,9);U+8766(1,3,8,9) +U+867F(0);U+8806(1,3,8,9);U+8806(1,3,8,9) +U+8680(0);U+8755(1,3,8,9);U+8755(1,3,8,9) +U+8681(0);U+87FB(1,3,8,9);U+8798(3,9),U+87FB(1,3,8,9) +U+8682(0);U+879E(1,3,8,9);U+879E(1,3,8,9) +U+8683(0);U+8801(4,8,9);U+8801(4,8,9) +U+8684(0);U+8684(0); +U+8685(0);U+8685(0,9); +U+8686(0);U+8686(0,9); +U+8687(0);U+8687(0,9); +U+8688(0);U+8688(0); +U+868A(0);U+868A(5,9);U+87A1(2,3,8),U+87C1(2,3,8) +U+868B(0);U+868B(5,9);U+8739(3,8) +U+868C(0);U+868C(5,9);U+7865(4,9) +U+868D(0);U+868D(5,9); +U+868E(0);U+868E(0,9); +U+868F(0);U+868F(3); +U+8690(0);U+8690(0,9); +U+8691(0);U+8691(0,9); +U+8693(0);U+8693(5,9); +U+8694(0);U+8694(0,9);U+86B3(4,9) +U+8695(0);U+8836(1,3,8,9);U+8836(1,3,8,9) +U+8696(0);U+8696(0,9); +U+8697(0);U+8697(0,9); +U+8698(0);U+8698(0,9);U+86D4(2,3,9),U+75D0(0,2,3,9),U+8716(2,3,8) +U+8699(0);U+8699(0,9); +U+869A(0);U+869A(0,9); +U+869B(0);U+869B(0); +U+869C(0);U+869C(5,9); +U+869D(0);U+8814(2,3,9);U+8814(2,3,9) +U+869E(0);U+869E(0,9); +U+869F(0);U+869F(0); + +U+86A1(0);U+86A1(4,9); +U+86A2(0);U+86A2(0,9); +U+86A3(0);U+86A3(5,9);U+8719(3,9) +U+86A4(0);U+86A4(5,9); +U+86A5(0);U+86A5(0,9); +U+86A7(0);U+86A7(5,9); +U+86A8(0);U+86A8(5,9); +U+86A9(0);U+86A9(5,9); +U+86AA(0);U+86AA(5,9); +U+86AB(0);U+86AB(0); +U+86AC(0);U+8706(1,3,8,9);U+8706(1,3,8,9) +U+86AD(0);U+86AD(0); +U+86AE(0);U+86AE(0); +U+86AF(0);U+86AF(5,9); +U+86B0(0);U+86B0(5,9); +U+86B1(0);U+86B1(5,9); +U+86B2(0);U+86B2(0); +U+86B3(0);U+86B3(4,9);U+8694(4,9) +U+86B4(0);U+86B4(5,9); +U+86B5(0);U+86B5(5,9); +U+86B6(0);U+86B6(5,9);U+9B7D(3,9) +U+86B7(0);U+86B7(0,9); +U+86B8(0);U+86B8(4,9); +U+86B9(0);U+86B9(0,9); +U+86BA(0);U+86BA(5,9); +U+86BB(0);U+86BB(0,9); +U+86BC(0);U+86BC(0,9); +U+86BD(0);U+86BD(0,9); +U+86BE(0);U+86BE(0,9); +U+86BF(0);U+86BF(0,9); +U+86C0(0);U+86C0(5,9); +U+86C1(0);U+86C1(3,9); +U+86C2(0);U+86C2(0,9); +U+86C3(0);U+86C3(0,9); +U+86C4(0);U+86C4(5,9);U+86CC(3,9) +U+86C5(0);U+86C5(0,9); +U+86C6(0);U+86C6(5,9); +U+86C7(0);U+86C7(5,9); +U+86C8(0);U+86C8(0,9); +U+86C9(0);U+86C9(5,9); +U+86CA(0);U+8831(1,3,8,9);U+8831(1,3,8,9) +U+86CB(0);U+86CB(5,9); +U+86CC(0);U+86CC(0,9);U+86C4(3,9) +U+86CE(0);U+8823(1,3,8,9);U+8823(1,3,8,9) +U+86CF(0);U+87F6(1,3,8,9);U+87F6(1,3,8,9) +U+86D0(0);U+86D0(5,9); +U+86D1(0);U+86D1(5,9); +U+86D2(0);U+86D2(0); +U+86D3(0);U+86D3(3,9); +U+86D4(0);U+86D4(5,9);U+75D0(2,3,9),U+8698(2,3,9),U+8716(2,8) +U+86D6(0);U+86D6(4,9); +U+86D7(0);U+86D7(0,9); +U+86D8(0);U+86D8(5,9); +U+86D9(0);U+86D9(5,9); +U+86DA(0);U+86DA(0,9); +U+86DB(0);U+86DB(5,9);U+9F04(3,8) +U+86DC(0);U+86DC(0,9); +U+86DD(0);U+86DD(0,9); +U+86DE(0);U+86DE(5,9); +U+86DF(0);U+86DF(5,9); +U+86E1(0);U+86E1(0); +U+86E2(0);U+86E2(0,9); +U+86E3(0);U+86E3(0,9); + +U+86E4(0);U+86E4(5,9); +U+86E5(0);U+86E5(0); +U+86E6(0);U+86E6(0,9); +U+86E8(0);U+86E8(0,9); +U+86E9(0);U+86E9(5,9);U+86EC(3,9) +U+86EA(0);U+86EA(0,9);U+9713(3,9),U+873A(2,3,8,9) +U+86EB(0);U+86EB(0,9); +U+86EC(0);U+86EC(0,9);U+86E9(3,9) +U+86ED(0);U+86ED(5,9); +U+86EE(0);U+883B(1,3,8,9);U+883B(1,3,8,9) +U+86EF(0);U+86EF(0); +U+86F0(0);U+87C4(1,3,8,9);U+87C4(1,3,8,9) +U+86F1(0);U+86FA(1,3,8,9);U+86FA(1,3,8,9) +U+86F2(0);U+87EF(1,3,8,9);U+87EF(1,3,8,9) +U+86F3(0);U+8784(1,3,8,9);U+8784(1,3,8,9) +U+86F4(0);U+8810(1,3,8,9);U+8810(1,3,8,9) +U+86F5(0);U+86F5(0,9); +U+86F6(0);U+86F6(0,9); +U+86F7(0);U+86F7(3,9); +U+86F8(0);U+86F8(5,9); +U+86F9(0);U+86F9(5,9); +U+86FA(0);U+86FA(0,9);U+86F1(1,3,8) +U+86FB(0);U+86FB(0,9);U+8715(4,8) +U+86FC(0);U+86FC(0); +U+86FE(0);U+86FE(5,9); +U+86FF(0);U+86FF(0); +U+8700(0);U+8700(5,9); +U+8701(0);U+8701(0,9); +U+8702(0);U+8702(5,9); +U+8703(0);U+8703(5,9);U+8704(3,9) +U+8704(0);U+8704(0,9);U+8703(3,9) +U+8705(0);U+8705(0,9); +U+8706(0);U+8706(0,9);U+86AC(1,3,8) +U+8707(0);U+8707(5,9); +U+8708(0);U+8708(5,9); +U+8709(0);U+8709(5,9); +U+870A(0);U+870A(5,9); +U+870B(0);U+870B(0,9);U+8782(2,3,4,9) +U+870C(0);U+870C(0,9); +U+870D(0);U+870D(5,9); +U+870E(0);U+870E(3,9); +U+870F(0);U+870F(0); +U+8710(0);U+8710(0); +U+8711(0);U+8711(0,9);U+8712(3,9) +U+8712(0);U+8712(5,9);U+8711(3,9) +U+8713(0);U+8713(5,9); +U+8714(0);U+8714(0); +U+8715(0);U+86FB(4,8,9);U+86FB(4,8,9) +U+8716(0);U+86D4(2,8,9);U+86D4(2,8,9),U+75D0(0,2,3,8,9),U+8698(2,3,8,9) +U+8717(0);U+8778(1,3,8,9);U+7611(4,9),U+8778(1,3,8,9) +U+8718(0);U+8718(5,9);U+9F05(3,8) +U+8719(0);U+8719(0,9);U+86A3(3,9) +U+871A(0);U+871A(5,9); +U+871B(0);U+871B(0,9); +U+871C(0);U+871C(5,9); +U+871E(0);U+871E(5,9); +U+871F(0);U+871F(0); +U+8720(0);U+8720(0,9); +U+8721(0);U+881F(1,3,8,9);U+881F(1,3,8,9) +U+8722(0);U+8722(5,9); +U+8723(0);U+8723(5,9); +U+8724(0);U+8724(0,9); +U+8725(0);U+8725(5,9); + +U+8726(0);U+8726(3,9); +U+8727(0);U+8727(0,9); +U+8728(0);U+8728(0,9);U+8776(2,3,9) +U+8729(0);U+8729(5,9); +U+872A(0);U+872A(0,9); +U+872B(0);U+872B(0); +U+872C(0);U+872C(3,9); +U+872D(0);U+872D(0,9); +U+872E(0);U+872E(5,9);U+9B4A(4,9) +U+8730(0);U+8730(0,9); +U+8731(0);U+8731(5,9); +U+8732(0);U+8732(0,9); +U+8733(0);U+8733(0,9); +U+8734(0);U+8734(5,9); +U+8735(0);U+8735(0,9); +U+8736(0);U+8736(0); +U+8737(0);U+8737(5,9);U+8E21(4,9) +U+8738(0);U+8738(0,9); +U+8739(0);U+868B(3,8,9);U+868B(3,8,9) +U+873A(0);U+873A(0,9);U+9713(2,3,8,9),U+86EA(0,2,3,8,9) +U+873B(0);U+873B(5,9); +U+873C(0);U+873C(3,9); +U+873E(0);U+873E(5,9); +U+873F(0);U+873F(5,9); +U+8740(0);U+8740(0,9); +U+8741(0);U+8741(0,9); +U+8742(0);U+8742(0,9); +U+8743(0);U+8743(4,9); +U+8744(0);U+8744(4); +U+8746(0);U+8746(0,9); +U+8747(0);U+8805(1,3,8,9);U+8805(1,3,8,9) +U+8748(0);U+87C8(1,3,8,9);U+87C8(1,3,8,9) +U+8749(0);U+87EC(1,3,8,9);U+87EC(1,3,8,9) +U+874A(0);U+874A(0); +U+874C(0);U+874C(5,9); +U+874D(0);U+874D(0,9); +U+874E(0);U+880D(2,3,9);U+880D(2,3,9) +U+874F(0);U+874F(0,9); +U+8750(0);U+8750(0,9); +U+8751(0);U+8751(0,9); +U+8752(0);U+8752(3,9); +U+8753(0);U+8753(5,9); +U+8754(0);U+8754(0,9); +U+8755(0);U+8755(0,9);U+8680(1,3,8) +U+8756(0);U+8756(0,9); +U+8757(0);U+8757(5,9); +U+8758(0);U+8758(0,9); +U+8759(0);U+8759(5,9); +U+875A(0);U+875A(0,9); +U+875B(0);U+875B(0,9); +U+875C(0);U+875C(0,9); +U+875D(0);U+875D(0,9); +U+875E(0);U+875E(0,9); +U+875F(0);U+875F(0,9);U+732C(2,3) +U+8760(0);U+8760(5,9); +U+8761(0);U+8761(0,9);U+8815(2,3,9) +U+8762(0);U+8762(0,9); +U+8763(0);U+8763(5,9); +U+8764(0);U+8764(5,9); +U+8765(0);U+8765(5,9); +U+8766(0);U+8766(0,9);U+867E(1,3,8) +U+8767(0);U+8767(0,9); +U+8768(0);U+8768(0,9);U+8671(2,3,8,9) + +U+8769(0);U+8769(0,9); +U+876A(0);U+876A(0,9); +U+876B(0);U+876B(0,9);U+8829(3,9) +U+876C(0);U+876C(0,9); +U+876D(0);U+876D(0,9); +U+876E(0);U+876E(5,9); +U+876F(0);U+876F(0,9);U+733F(2,3,9) +U+8770(0);U+8770(5); +U+8772(0);U+8772(0); +U+8773(0);U+8773(0,9);U+73B3(3,9) +U+8774(0);U+8774(5,9); +U+8775(0);U+8775(0,9); +U+8776(0);U+8776(5,9);U+8728(2,3,9) +U+8777(0);U+8777(3,9); +U+8778(0);U+8778(0,9);U+8717(1,3,8),U+7611(0,1,3,4,8,9) +U+8779(0);U+8779(0,9); +U+877A(0);U+877A(0,9); +U+877B(0);U+877B(5,9); +U+877C(0);U+87BB(1,3,8,9);U+87BB(1,3,8,9) +U+877D(0);U+877D(5); +U+877E(0);U+8811(1,3,8,9);U+8811(1,3,8,9) +U+8780(0);U+87BF(4,8,9);U+87BF(4,8,9) +U+8781(0);U+8781(0,9); +U+8782(0);U+8782(5,9);U+870B(2,3,4,9) +U+8783(0);U+8783(5,9); +U+8784(0);U+8784(0,9);U+86F3(1,3,8) +U+8785(0);U+8785(5,9); +U+8786(0);U+8786(0); +U+8787(0);U+8787(0,9); +U+8788(0);U+8788(5,9); +U+8789(0);U+8789(0,9); +U+878A(0);U+878A(3); +U+878B(0);U+878B(5); +U+878C(0);U+878C(0); +U+878D(0);U+878D(5,9); +U+878F(0);U+878F(0,9); +U+8790(0);U+8790(0,9); +U+8791(0);U+8791(0,9); +U+8792(0);U+8792(0,9); +U+8793(0);U+8793(5,9); +U+8794(0);U+8794(0,9); +U+8795(0);U+8795(0); +U+8796(0);U+8796(0,9); +U+8797(0);U+8797(5,9);U+87B3(4,8,9) +U+8798(0);U+8798(0,9);U+8681(3),U+87FB(1,3,8,9) +U+879A(0);U+879A(0,9); +U+879B(0);U+879B(0,9); +U+879C(0);U+879C(0,9); +U+879D(0);U+879D(0,9); +U+879E(0);U+879E(0,9);U+8682(1,3,8) +U+879F(0);U+879F(5,9); +U+87A0(0);U+87A0(0); +U+87A1(0);U+868A(2,3,8,9);U+868A(2,3,8,9),U+87C1(2,3,8) +U+87A2(0);U+87A2(0,9);U+8424(1,3,8) +U+87A3(0);U+87A3(0,9); +U+87A4(0);U+87A4(0,9);U+949F(3),U+9221(3,4),U+937E(1,3,8,9),U+9418(1,3,8,9),U+953A(0,1,3,4,8) + +U+87A5(0);U+87A5(0); +U+87A6(0);U+87A6(0); +U+87A7(0);U+87A7(0); +U+87A8(0);U+87CE(1,3,8);U+87CE(1,3,8) +U+87A9(0);U+87A9(0); +U+87AA(0);U+87AA(0,9); + +U+87AB(0);U+87AB(5,9); +U+87AC(0);U+87AC(5,9); +U+87AD(0);U+87AD(5,9); +U+87AE(0);U+87AE(3,9); +U+87AF(0);U+87AF(5,9); +U+87B0(0);U+87B0(0,9); +U+87B1(0);U+87B1(0); +U+87B2(0);U+87B2(0,9); +U+87B3(0);U+87B3(5,9);U+8797(4,8,9) +U+87B4(0);U+87B4(0,9); +U+87B5(0);U+87B5(5,9); +U+87B6(0);U+87B6(3,9); +U+87B7(0);U+87B7(3,9); +U+87B8(0);U+87B8(0,9); +U+87B9(0);U+87B9(0,9); +U+87BA(0);U+87BA(5,9); +U+87BB(0);U+87BB(0,9);U+877C(1,3,8) +U+87BC(0);U+87BC(0,9); +U+87BD(0);U+87BD(5,9); +U+87BE(0);U+87BE(0,9); +U+87BF(0);U+87BF(0,9);U+8780(4,8) +U+87C0(0);U+87C0(5,9); +U+87C1(0);U+868A(2,3,8,9);U+868A(2,3,8,9),U+87A1(2,3,8) +U+87C2(0);U+87C2(0,9); +U+87C3(0);U+87C3(0,9); +U+87C4(0);U+87C4(0,9);U+86F0(1,3,8) +U+87C5(0);U+87C5(0,9); +U+87C6(0);U+87C6(5,9);U+87C7(2,3,8) +U+87C7(0);U+87C6(2,3,8,9);U+87C6(2,3,8,9) +U+87C8(0);U+87C8(0,9);U+8748(1,3,8) +U+87C9(0);U+87C9(0,9); +U+87CA(0);U+87CA(5,9); +U+87CB(0);U+87CB(5,9); +U+87CC(0);U+87CC(0,9); +U+87CD(0);U+87CD(0); +U+87CE(0);U+87CE(0);U+87A8(1,3,8) +U+87CF(0);U+8828(1,3,8,9);U+8828(1,3,8,9) +U+87D0(0);U+87D0(0); +U+87D1(0);U+87D1(5,9); +U+87D2(0);U+87D2(5,9);U+880E(3,8) +U+87D3(0);U+87D3(5,9); +U+87D4(0);U+87D4(0,9); +U+87D5(0);U+87D5(0); +U+87D6(0);U+87D6(3); +U+87D7(0);U+87D7(3,9); +U+87D8(0);U+87D8(3,9); +U+87D9(0);U+87D9(0,9); +U+87DB(0);U+87DB(5,9); +U+87DC(0);U+87DC(0,9); +U+87DD(0);U+87DD(0,9); +U+87DE(0);U+87DE(0,9); +U+87DF(0);U+87DF(3,9); +U+87E0(0);U+87E0(5,9); +U+87E1(0);U+87E1(3,9); +U+87E2(0);U+87E2(0,9); +U+87E3(0);U+87E3(0,9);U+866E(1,3,8,9) +U+87E4(0);U+87E4(0,9); +U+87E5(0);U+87E5(5,9); +U+87E6(0);U+87E6(0,9); +U+87E7(0);U+87E7(0,9); +U+87E8(0);U+87E8(3,9); +U+87E9(0);U+87E9(0); +U+87EA(0);U+87EA(5,9); + +U+87EB(0);U+87EB(0,9); +U+87EC(0);U+87EC(0,9);U+8749(1,3,8) +U+87ED(0);U+87ED(0,9); +U+87EE(0);U+87EE(5); +U+87EF(0);U+87EF(0,9);U+86F2(1,3,8) +U+87F1(0);U+87F1(0); +U+87F2(0);U+87F2(0,9);U+866B(1,3,8,9) +U+87F3(0);U+87F3(0,9); +U+87F4(0);U+87F4(4,9); +U+87F5(0);U+87F5(0); +U+87F6(0);U+87F6(0,9);U+86CF(1,3,8) +U+87F7(0);U+87F7(0,9); +U+87F8(0);U+87F8(0); +U+87F9(0);U+87F9(5,9);U+880F(2,3,8) +U+87FA(0);U+87FA(3,9); +U+87FB(0);U+87FB(0,9);U+8681(1,3,8),U+8798(1,3,8,9) +U+87FC(0);U+87FC(0,9); +U+87FD(0);U+87FD(0); +U+87FE(0);U+87FE(5,9); +U+87FF(0);U+87FF(0,9); +U+8800(0);U+8800(0,9); +U+8801(0);U+8801(0,9);U+8683(4,8) +U+8802(0);U+8802(0,9); +U+8803(0);U+8803(5,9); +U+8804(0);U+8804(0); +U+8805(0);U+8805(0,9);U+8747(1,3,8) +U+8806(0);U+8806(0,9);U+867F(1,3,8) +U+8808(0);U+8808(0,9); +U+8809(0);U+8809(0,9); +U+880A(0);U+880A(5,9); +U+880B(0);U+880B(3,9); +U+880C(0);U+880C(0,9); +U+880D(0);U+880D(0,9);U+874E(2,3,9) +U+880E(0);U+87D2(3,8,9);U+87D2(3,8,9) +U+880F(0);U+87F9(2,3,8,9);U+87F9(2,3,8,9) +U+8810(0);U+8810(0,9);U+86F4(1,3,8) +U+8811(0);U+8811(0,9);U+877E(1,3,8) +U+8813(0);U+8813(5,9); +U+8814(0);U+8814(0,9);U+869D(2,3,9) +U+8815(0);U+8815(5,9);U+8761(2,3,9) +U+8816(0);U+8816(5,9); +U+8817(0);U+8817(0,9); +U+8818(0);U+8818(0); +U+8819(0);U+8819(0,9); +U+881A(0);U+881A(0); +U+881B(0);U+881B(5,9); +U+881C(0);U+881C(0,9); +U+881D(0);U+881D(0,9); +U+881E(0);U+881E(0); +U+881F(0);U+881F(0,9);U+8721(1,3,8,9) +U+8820(0);U+8820(0,9); +U+8821(0);U+8821(5,9); +U+8822(0);U+8822(5,9);U+60F7(2,3,8,9) +U+8823(0);U+8823(0,9);U+86CE(1,3,8) +U+8824(0);U+8824(0,9); +U+8825(0);U+8825(3,9); +U+8826(0);U+8826(0,9); +U+8827(0);U+8839(3,8,9);U+8839(3,8,9) +U+8828(0);U+8828(0,9);U+87CF(1,3,8) +U+8829(0);U+8829(3,9);U+876B(3,9) +U+882A(0);U+882A(0,9); +U+882B(0);U+882B(0,9);U+5299(3,9) +U+882C(0);U+882C(0,9); + +U+882E(0);U+882E(0,9); +U+882F(0);U+882F(4,9); +U+8830(0);U+8830(0,9); +U+8831(0);U+8831(0,9);U+86CA(1,3,8) +U+8832(0);U+8832(5,9); +U+8833(0);U+8833(0,9); +U+8834(0);U+8834(0); +U+8835(0);U+8835(3,9); +U+8836(0);U+8836(0,9);U+8695(1,3,8,9) +U+8837(0);U+8837(0,9);U+883C(4,9) +U+8838(0);U+8838(0,9); +U+8839(0);U+8839(5,9);U+8827(3,8) +U+883B(0);U+883B(0,9);U+86EE(1,3,8) +U+883C(0);U+883C(5,9);U+8837(4,9) +U+883D(0);U+883D(0,9); +U+883E(0);U+883E(0,9); +U+883F(0);U+883F(0,9); +U+8840(0);U+8840(5,9); +U+8841(0);U+8841(0,9); +U+8842(0);U+8844(2,3,8,9);U+8844(2,3,8,9) +U+8843(0);U+8843(3,9); +U+8844(0);U+8844(5,9);U+8842(2,3,8) +U+8845(0);U+91C1(1,3,8,9);U+91C1(1,3,8,9) +U+8846(0);U+773E(2,8,9);U+4F17(1,3,8),U+773E(2,8,9) +U+8848(0);U+8848(0,9); +U+8849(0);U+8849(0); +U+884A(0);U+884A(0,9);U+8511(1,3,9),U+858E(1,3,4,9) +U+884B(0);U+884B(0,9); +U+884C(0);U+884C(5,9); +U+884D(0);U+884D(5,9); +U+884E(0);U+884E(0,9); +U+884F(0);U+884F(0); +U+8850(0);U+8850(0); +U+8851(0);U+8851(0); +U+8852(0);U+8852(3,9); +U+8853(0);U+8853(0,9);U+672F(1,3,8),U+672E(0,1,3,4,8,9) +U+8854(0);U+929C(1,3,8,9);U+5563(4,9),U+929C(1,3,8,9) +U+8855(0);U+8855(0,9);U+540C(2,9),U+4EDD(2,3,5,8,9) +U+8856(0);U+8856(0,9);U+5F04(2,9) +U+8857(0);U+8857(5,9); +U+8859(0);U+8859(5,9); +U+885A(0);U+885A(0,9);U+80E1(2,9),U+9B0D(1,2,3,4,8,9) +U+885B(0);U+885B(0,9);U+536B(1,3,8),U+885E(3,8) +U+885D(0);U+885D(0,9);U+51B2(1,3,8),U+6C96(3,4,9),U+794C(1,3,4,8,9),U+8876(1,3,4,8,9),U+76C5(1,3,4,8,9) + +U+885E(0);U+885B(3,8,9);U+536B(3),U+885B(3,8,9) +U+8860(0);U+8860(0); +U+8861(0);U+8861(5,9); +U+8862(0);U+8862(5,9); +U+8863(0);U+8863(5,9); +U+8864(0);U+8864(5); +U+8865(0);U+88DC(1,3,8,9);U+88DC(1,3,8,9) +U+8866(0);U+8866(0); +U+8867(0);U+8867(0,9); +U+8868(0);U+8868(1,3,9),U+9336(1,3,9);U+9336(1,3,9) +U+8869(0);U+8869(5,9);U+7D01(4,9) +U+886A(0);U+886A(0,9);U+8898(4,9) +U+886B(0);U+886B(5,9); +U+886C(0);U+896F(1,3,8,9);U+896F(1,3,8,9) +U+886D(0);U+886D(0,9); +U+886E(0);U+889E(3,8,9);U+7DF7(3,9),U+889E(3,8,9) +U+886F(0);U+886F(0,9); +U+8870(0);U+8870(5,9); + +U+8871(0);U+8871(0,9); +U+8872(0);U+8872(5,9); +U+8873(0);U+8873(0); +U+8874(0);U+8874(0,9); +U+8875(0);U+8875(0,9); +U+8876(0);U+8876(0,9);U+51B2(4),U+6C96(3,4,8,9),U+794C(3,4,9),U+885D(1,3,4,8,9),U+76C5(3,4,8,9) + +U+8877(0);U+8877(5,9); +U+8878(0);U+8878(0); +U+8879(0);U+8879(0,9);U+53EA(1,8,9),U+96BB(1,3,4,8,9) +U+887B(0);U+887B(3); +U+887C(0);U+887C(0,9); +U+887D(0);U+887D(5,9); +U+887E(0);U+887E(5,9); +U+887F(0);U+887F(5,9); +U+8880(0);U+8880(0,9); +U+8881(0);U+8881(5,9); +U+8882(0);U+8882(5,9); +U+8883(0);U+8883(0,9); +U+8884(0);U+8956(1,3,8,9);U+8956(1,3,8,9) +U+8885(0);U+88CA(1,3,8,9);U+5ACB(7,9),U+5B1D(4,8,9),U+88CA(1,3,8,9),U+892D(3,9) +U+8886(0);U+8918(4,8,9);U+8918(4,8,9) +U+8887(0);U+8887(0); +U+8888(0);U+8888(5,9);U+6BE0(3,9) +U+8889(0);U+8889(3,9); +U+888A(0);U+888A(0); +U+888B(0);U+888B(5,9); +U+888C(0);U+888C(0,9);U+888D(3,9) +U+888D(0);U+888D(5,9);U+888C(3,9) +U+888E(0);U+888E(3,9); +U+888F(0);U+888F(0); +U+8890(0);U+8890(0); +U+8891(0);U+8891(0,9); +U+8892(0);U+8892(5,9);U+8962(2,3,9) +U+8893(0);U+8893(0,9); +U+8894(0);U+8894(0); +U+8895(0);U+8895(0,9); +U+8896(0);U+8896(5,9);U+890E(4,8,9) +U+8897(0);U+8897(3,9); +U+8898(0);U+8898(4,9);U+886A(4,9) +U+8899(0);U+8899(0,9); +U+889A(0);U+889A(0,9); +U+889B(0);U+889B(0,9); +U+889C(0);U+896A(1,3,4,8,9);U+896A(1,3,4,8,9),U+97C8(4),U+97E4(3,4) +U+889D(0);U+889D(0); +U+889E(0);U+889E(0,9);U+886E(3,8),U+7DF7(0,3,8,9) +U+889F(0);U+889F(0,9);U+5E19(2,3,9) +U+88A0(0);U+88A0(4); +U+88A1(0);U+88A1(4,9); +U+88A2(0);U+88A2(5,9); +U+88A3(0);U+88A3(3); +U+88A4(0);U+88A4(5,9); +U+88A5(0);U+88A5(0); +U+88A6(0);U+88A6(0); +U+88A7(0);U+88A7(0,9); +U+88A8(0);U+88A8(3,9); +U+88A9(0);U+88A9(0); +U+88AA(0);U+88AA(0,9); +U+88AB(0);U+88AB(5,9); +U+88AC(0);U+88AC(0,9);U+88D5(4,9) +U+88AD(0);U+8972(1,3,8,9);U+8972(1,3,8,9) +U+88AE(0);U+88AE(0); +U+88AF(0);U+894F(4,8,9);U+894F(4,8,9) + +U+88B0(0);U+88B0(0); +U+88B1(0);U+88B1(5,9); +U+88B2(0);U+88B2(4,9); +U+88B3(0);U+88B3(3); +U+88B4(0);U+88B4(0);U+8932(2,8,9),U+88E4(4) +U+88B6(0);U+88B6(0,9); +U+88B7(0);U+88B7(5,9); +U+88B8(0);U+88B8(0,9); +U+88B9(0);U+88B9(3,9); +U+88BA(0);U+88BA(0,9); +U+88BB(0);U+88BB(0); +U+88BC(0);U+88BC(5,9); +U+88BD(0);U+88BD(0,9); +U+88BE(0);U+88BE(0,9); +U+88BF(0);U+88BF(0); +U+88C0(0);U+88C0(0,9); +U+88C1(0);U+88C1(5,9); +U+88C2(0);U+88C2(5,9); +U+88C3(0);U+88C3(0); +U+88C4(0);U+88C4(0); +U+88C5(0);U+88DD(1,3,4,8,9);U+88DD(1,3,4,8,9) +U+88C6(0);U+8960(1,3,8,9);U+8960(1,3,8,9) +U+88C7(0);U+88C7(0); +U+88C8(0);U+890C(4,8,9);U+890C(4,8,9) +U+88C9(0);U+88C9(5,9); +U+88CA(0);U+88CA(0,9);U+5ACB(2,9),U+5B1D(2,8,9),U+8885(1,3,8),U+892D(2,3,7,9) +U+88CB(0);U+88CB(0,9); +U+88CC(0);U+88CC(0,9);U+5939(4),U+593E(1,3,4,8,9) +U+88CD(0);U+88CD(0,9); +U+88CE(0);U+88CE(5,9); +U+88CF(0);U+88CF(0,9);U+88E1(2,3,9),U+91CC(1,3,8,9) +U+88D0(0);U+88D0(0,9); +U+88D1(0);U+88D1(0); +U+88D2(0);U+88D2(5,9); +U+88D3(0);U+88D3(0); +U+88D4(0);U+88D4(5,9); +U+88D5(0);U+88D5(5,9);U+88AC(4,9) +U+88D6(0);U+88D6(0,9); +U+88D7(0);U+88D7(0,9); +U+88D8(0);U+88D8(5,9); +U+88D9(0);U+88D9(5,9);U+5E2C(2,3,8),U+88E0(2,3,8) +U+88DA(0);U+88DA(0,9); +U+88DB(0);U+88DB(0,9); +U+88DC(0);U+88DC(0,9);U+8865(1,3,8) +U+88DD(0);U+88DD(0,9);U+88C5(1,3,8) +U+88DE(0);U+88DE(0,9); +U+88DF(0);U+88DF(5,9); +U+88E0(0);U+88D9(2,3,8,9);U+88D9(2,3,8,9),U+5E2C(0,2,3,8) +U+88E1(0);U+88E1(0,9);U+88CF(2,3,9),U+91CC(4,9) +U+88E2(0);U+8933(1,3,8,9);U+8933(1,3,8,9) +U+88E3(0);U+895D(1,3,8,9);U+895D(1,3,8,9) +U+88E4(0);U+8932(1,3,8,9);U+8932(1,3,8,9),U+88B4(4) +U+88E5(0);U+8947(1,3,8);U+8947(1,3,8),U+8949(3,9) +U+88E7(0);U+88E7(0,9); +U+88E8(0);U+88E8(5,9); +U+88EA(0);U+88EA(0); +U+88EB(0);U+88EB(0,9); +U+88EC(0);U+88EC(0,9); +U+88EE(0);U+88EE(0,9); +U+88EF(0);U+88EF(0,9); +U+88F0(0);U+88F0(5,9); +U+88F1(0);U+88F1(5,9); +U+88F2(0);U+88F2(0,9); + +U+88F3(0);U+88F3(5,9); +U+88F4(0);U+88F4(5,9);U+88F5(3,8) +U+88F5(0);U+88F4(3,8,9);U+88F4(3,8,9) +U+88F6(0);U+88F6(0,9); +U+88F7(0);U+88F7(0,9); +U+88F8(0);U+88F8(5,9);U+81DD(2,3,9) +U+88F9(0);U+88F9(5,9);U+8901(3,9) +U+88FA(0);U+88FA(0,9); +U+88FB(0);U+88FB(0,9); +U+88FC(0);U+88FC(5,9); +U+88FD(0);U+88FD(0,9);U+5236(1,3,8,9) +U+88FE(0);U+88FE(5,9); +U+88FF(0);U+88FF(0); +U+8900(0);U+8900(4);U+5E3A(0) +U+8901(0);U+8901(0,9);U+88F9(3,9) +U+8902(0);U+8902(5,9); +U+8904(0);U+8904(0); +U+8905(0);U+8905(0,9); +U+8906(0);U+8906(0,9); +U+8907(0);U+8907(0,9);U+590D(1,3,9),U+5FA9(1,3,8,9),U+8986(1,3,8,9) +U+8908(0);U+8908(0); +U+8909(0);U+8909(0,9); +U+890A(0);U+890A(5,9);U+60FC(3,9) +U+890B(0);U+890B(0,9); +U+890C(0);U+890C(0,9);U+88C8(4,8) +U+890D(0);U+890D(0); +U+890E(0);U+890E(0,9);U+8896(4,8,9) +U+8910(0);U+8910(5,9); +U+8911(0);U+8911(3,9); +U+8912(0);U+8912(5,9);U+8943(2,3,8) +U+8913(0);U+8913(5,9); +U+8914(0);U+8914(0,9);U+526F(4,9) +U+8915(0);U+8915(0,9); +U+8916(0);U+8916(0,9); +U+8917(0);U+8917(0,9); +U+8918(0);U+8918(0,9);U+8886(4,8) +U+8919(0);U+8919(5,9); +U+891A(0);U+891A(5,9); +U+891B(0);U+8938(1,3,8,9);U+8938(1,3,8,9) +U+891C(0);U+891C(0); +U+891D(0);U+891D(0); +U+891E(0);U+891E(0,9);U+7F0A(4),U+7DFC(0,1,3,4),U+7E15(1,3,4,8,9) +U+891F(0);U+891F(0,9); +U+8920(0);U+8920(0); +U+8921(0);U+8921(5,9); +U+8922(0);U+8922(0,9);U+6000(3,9),U+61F7(1,3,8,9),U+61D0(3),U+8931(3,9) +U+8923(0);U+8923(0,9); +U+8925(0);U+8925(5,9); +U+8926(0);U+8926(0,9); +U+8927(0);U+8927(4,9); +U+8928(0);U+8928(0); +U+8929(0);U+8929(0,9); +U+892A(0);U+892A(5,9); +U+892B(0);U+892B(5,9); +U+892C(0);U+892C(0,9); +U+892D(0);U+892D(0,9);U+8885(3),U+5ACB(3,7,9),U+5B1D(3,7,8,9),U+88CA(2,3,7,9) +U+892E(0);U+892E(0,9); +U+892F(0);U+892F(0,9); +U+8930(0);U+8930(5,9); +U+8931(0);U+8931(0,9);U+6000(3,9),U+61F7(1,3,8,9),U+61D0(3),U+8922(3,9) +U+8932(0);U+8932(0,9);U+88B4(2,8),U+88E4(1,3,8) +U+8933(0);U+8933(0,9);U+88E2(1,3,8) +U+8934(0);U+8964(1,3,8,9);U+7E7F(3),U+8964(1,3,8,9) + +U+8935(0);U+8935(0,9);U+7F21(3),U+7E2D(0,1,3,8,9) +U+8936(0);U+8936(5,9); +U+8937(0);U+8937(0,9); +U+8938(0);U+8938(0,9);U+891B(1,3,8) +U+8939(0);U+8939(3); +U+893A(0);U+893A(0); +U+893B(0);U+893B(0,9);U+4EB5(1,3,8) +U+893C(0);U+893C(0,9); +U+893D(0);U+893D(0,9); +U+893E(0);U+893E(0,9); +U+893F(0);U+893F(0); +U+8940(0);U+8940(0); +U+8941(0);U+8941(4,9); +U+8942(0);U+8942(3,9); +U+8943(0);U+8912(2,3,8,9);U+8912(2,3,8,9) +U+8944(0);U+8944(5,9); +U+8945(0);U+8945(0); +U+8946(0);U+8946(3,9); +U+8947(0);U+8947(0);U+88E5(1,3,8),U+8949(1,3,8,9) +U+8948(0);U+8948(0); +U+8949(0);U+8949(0,9);U+88E5(3),U+8947(1,3,8) +U+894A(0);U+894A(0); +U+894B(0);U+894B(0,9); +U+894C(0);U+894C(0,9); +U+894E(0);U+894E(0); +U+894F(0);U+894F(0,9);U+88AF(4,8) +U+8950(0);U+8950(0,9); +U+8951(0);U+8951(0,9); +U+8952(0);U+8952(0,9); +U+8953(0);U+8953(0,9); +U+8954(0);U+8954(0); +U+8955(0);U+8974(4,8,9);U+5E71(3),U+8974(4,8,9) +U+8956(0);U+8956(0,9);U+8884(1,3,8) +U+8957(0);U+8957(3,9); +U+8958(0);U+8958(0,9); +U+8959(0);U+8959(0,9); +U+895A(0);U+895A(0,9); +U+895B(0);U+895B(0,9); +U+895C(0);U+895C(3,9); +U+895D(0);U+895D(0,9);U+88E3(1,3,8) +U+895E(0);U+895E(5,9); +U+895F(0);U+895F(5,9); +U+8960(0);U+8960(0,9);U+88C6(1,3,8) +U+8961(0);U+8961(3,9); +U+8962(0);U+8962(0,9);U+8892(2,3,9) +U+8963(0);U+8963(0,9); +U+8964(0);U+8964(0,9);U+8934(1,3,8),U+7E7F(3,8) +U+8966(0);U+8966(5,9); +U+8967(0);U+8967(0); +U+8968(0);U+8968(0); +U+8969(0);U+8969(0,9); +U+896A(0);U+896A(0,9);U+889C(1,3,8),U+97C8(2,8),U+97E4(2,8) +U+896B(0);U+896B(0,9); +U+896C(0);U+896C(0,9);U+6446(1,3),U+64FA(4,9) +U+896D(0);U+896D(3,9); +U+896E(0);U+896E(0,9); +U+896F(0);U+896F(0,9);U+886C(1,3,8) +U+8970(0);U+8970(0); +U+8971(0);U+8971(0,9); +U+8972(0);U+8972(0,9);U+88AD(1,3,8) +U+8973(0);U+8973(0,9); +U+8974(0);U+8974(0,9);U+5E71(3,8),U+8955(4,8) +U+8976(0);U+8976(0,9); + +U+8977(0);U+8977(0); +U+8978(0);U+8978(0); +U+8979(0);U+8979(0,9); +U+897A(0);U+897A(3,9); +U+897B(0);U+897B(5,9); +U+897C(0);U+897C(0,9); +U+897E(0);U+897E(0,9);U+8980(8) +U+897F(0);U+897F(5,9); +U+8980(0);U+897E(8,9);U+897E(8,9) +U+8981(0);U+8981(5,9); +U+8982(0);U+8982(0,9); +U+8983(0);U+8983(5,9); +U+8984(0);U+8984(0); +U+8985(0);U+8985(0,9); +U+8986(0);U+8986(5,9);U+5FA9(3,8,9),U+590D(1,3,8,9),U+8907(1,3,8,9) +U+8987(0);U+9738(2,3,8,9);U+9738(2,3,8,9) +U+8988(0);U+8988(3,9);U+6838(2,3,8,9),U+69C5(2,3,4,8) +U+8989(0);U+7F87(8,9);U+7F81(3),U+7F87(8,9),U+7F88(3,8,9),U+898A(2,3) +U+898A(0);U+7F88(2,3,8,9);U+7F81(2,3),U+7F88(2,3,8,9),U+7F87(2,3,4,9),U+8989(2,3) +U+898B(0);U+898B(0,9);U+89C1(1,3,8) +U+898C(0);U+89C0(3,8,9);U+89C0(3,8,9),U+89C2(3),U+89B3(3,8) +U+898E(0);U+898E(0);U+89C3(1,3,8) +U+898F(0);U+898F(0,9);U+69FC(2,9),U+89C4(1,3,8),U+691D(0,2,4,8) +U+8991(0);U+8991(0); +U+8992(0);U+8992(0); +U+8993(0);U+8993(0,9);U+89C5(1,3,8) +U+8995(0);U+8995(0,9);U+77A5(3,9) +U+8996(0);U+8996(0,9);U+89C6(1,3,8) +U+8997(0);U+8997(0,9); +U+8998(0);U+8998(0,9);U+89C7(1,3,8) +U+899A(0);U+89BA(4,8,9);U+89BA(4,8,9),U+89C9(4),U+658D(0,3,4,8) +U+899B(0);U+899B(0,9); +U+899C(0);U+899C(0,9);U+773A(2,3,9) +U+899D(0);U+899D(0,9);U+5EC9(4,9),U+4EB7(0,2,4,8) +U+899E(0);U+899E(0,9); +U+899F(0);U+899F(0,9); +U+89A0(0);U+89A0(0); +U+89A1(0);U+89A1(0,9);U+89CB(1,3,8) +U+89A2(0);U+89A2(0,9); +U+89A3(0);U+89A3(0,9); +U+89A4(0);U+89A4(0,9); +U+89A5(0);U+89A5(0);U+89CD(4,8) +U+89A6(0);U+89A6(0,9);U+89CE(1,3,8) +U+89A7(0);U+89BD(3,8,9);U+89BD(3,8,9),U+89C8(4) +U+89A8(0);U+89A8(0); +U+89AA(0);U+89AA(0,9);U+4EB2(1,3,8) +U+89AB(0);U+89AB(0); +U+89AC(0);U+89AC(0,9);U+89CA(1,3,8) +U+89AD(0);U+89AD(0,9); +U+89AE(0);U+89AE(0,9); +U+89AF(0);U+89AF(0,9);U+89CF(1,3,8) +U+89B1(0);U+89B1(0); +U+89B2(0);U+89B2(0,9);U+89D0(1,3,8) +U+89B3(0);U+89C0(3,8,9);U+89C0(3,8,9),U+89C2(3),U+898C(0,3,8) +U+89B5(0);U+89B5(3);U+89B8(3,8) +U+89B6(0);U+89B6(0,9); +U+89B7(0);U+89B7(0,9);U+89D1(1,3,8) +U+89B8(0);U+89B8(0);U+89B5(3,8) +U+89B9(0);U+89B9(3,9); +U+89BA(0);U+89BA(0,9);U+658D(3,8),U+899A(4,8),U+89C9(1,3,8) +U+89BD(0);U+89BD(0,9);U+89A7(3,8),U+89C8(1,3,8) +U+89BE(0);U+89BE(0,9); +U+89BF(0);U+89BF(0,9);U+89CC(1,3,8) + +U+89C0(0);U+89C0(0,9);U+898C(3,8),U+89B3(3,8),U+89C2(1,3,8) +U+89C1(0);U+898B(1,3,8,9);U+898B(1,3,8,9) +U+89C2(0);U+89C0(1,3,8,9);U+898C(3),U+89B3(3),U+89C0(1,3,8,9) +U+89C3(0);U+898E(1,3,8);U+898E(1,3,8) +U+89C4(0);U+898F(1,3,8,9);U+691D(4),U+69FC(4,9),U+898F(1,3,8,9) +U+89C5(0);U+8993(1,3,8,9);U+8993(1,3,8,9) +U+89C6(0);U+8996(1,3,8,9);U+8996(1,3,8,9) +U+89C7(0);U+8998(1,3,8,9);U+8998(1,3,8,9) +U+89C8(0);U+89BD(1,3,8,9);U+89A7(4),U+89BD(1,3,8,9) +U+89C9(0);U+89BA(1,3,8,9);U+658D(3),U+899A(4),U+89BA(1,3,8,9) +U+89CA(0);U+89AC(1,3,8,9);U+89AC(1,3,8,9) +U+89CB(0);U+89A1(1,3,8,9);U+89A1(1,3,8,9) +U+89CC(0);U+89BF(1,3,8,9);U+89BF(1,3,8,9) +U+89CD(0);U+89A5(4,8);U+89A5(4,8) +U+89CE(0);U+89A6(1,3,8,9);U+89A6(1,3,8,9) +U+89CF(0);U+89AF(1,3,8,9);U+89AF(1,3,8,9) +U+89D0(0);U+89B2(1,3,8,9);U+89B2(1,3,8,9) +U+89D1(0);U+89B7(1,3,8,9);U+89B7(1,3,8,9) +U+89D2(0);U+89D2(5,9); +U+89D3(0);U+89D3(3,9); +U+89D4(0);U+89D4(0,9);U+65A4(2,3,8,9),U+7B4B(3,8,9) +U+89D5(0);U+89D5(0,9);U+7C97(2,3,9),U+850D(2,3,9),U+9E81(2,3,4,8),U+9E84(2,3,8),U+9E86(2,3,9),U+9EA4(2,3,9) + +U+89D6(0);U+89D6(5,9); +U+89D7(0);U+89D7(0); +U+89D8(0);U+89D8(0); +U+89D9(0);U+89D9(0,9);U+4F0B(3,9) +U+89DA(0);U+89DA(5,9); +U+89DB(0);U+89DB(0,9); +U+89DC(0);U+89DC(5,9); +U+89DD(0);U+89DD(0,9);U+627A(3,9),U+62B5(2,9),U+7274(4,8,9),U+7F9D(2,3,8,9) +U+89DE(0);U+89F4(1,3,8,9);U+89F4(1,3,8,9) +U+89DF(0);U+89DF(0,9);U+9C91(1,3,4),U+9BAD(1,3,4,8,9) +U+89E0(0);U+89E0(0,9); +U+89E1(0);U+89E1(0,9); +U+89E2(0);U+89E2(3,9); +U+89E3(0);U+89E3(5,9);U+89E7(3,8) +U+89E4(0);U+89E4(0,9); +U+89E5(0);U+89E5(5,9); +U+89E6(0);U+89F8(1,3,8,9);U+89F8(1,3,8,9) +U+89E7(0);U+89E3(3,8,9);U+89E3(3,8,9) +U+89E8(0);U+89E8(0,9); +U+89E9(0);U+89E9(4,9); +U+89EA(0);U+89EA(0);U+89F2(3,9) +U+89EB(0);U+89EB(5,9); +U+89EC(0);U+89EC(0,9); +U+89ED(0);U+89ED(0,9); +U+89EF(0);U+89F6(4,8,9);U+89F6(4,8,9) +U+89F0(0);U+89F0(0,9); +U+89F1(0);U+89F1(0,9); +U+89F2(0);U+89F2(0,9);U+89EA(3) +U+89F3(0);U+89F3(5,9); +U+89F4(0);U+89F4(0,9);U+89DE(1,3,8) +U+89F6(0);U+89F6(0,9);U+89EF(4,8) +U+89F7(0);U+89F7(3,9); +U+89F8(0);U+89F8(0,9);U+89E6(1,3,8,9) +U+89FA(0);U+89FA(0,9); +U+89FB(0);U+89FB(0,9); +U+89FC(0);U+89FC(0,9); +U+89FE(0);U+89FE(0,9);U+71D5(3,9),U+9DF0(2,3,8,9) +U+89FF(0);U+89FF(3,9); +U+8A00(0);U+8A00(5,9);U+8A01(8),U+8BA0(8) +U+8A01(0);U+8A00(8,9);U+8A00(8,9),U+8BA0(4,8) + +U+8A02(0);U+8A02(0,9);U+8BA2(1,3,8) +U+8A03(0);U+8A03(0,9);U+8BA3(1,3,8) +U+8A04(0);U+8A04(3,9); +U+8A07(0);U+8A07(5,9); +U+8A08(0);U+8A08(0,9);U+8BA1(1,3,8) +U+8A09(0);U+8A09(0); +U+8A0A(0);U+8A0A(0,9);U+8BAF(1,3,8) +U+8A0B(0);U+8A0B(0); +U+8A0C(0);U+8A0C(0,9);U+8BA7(1,3,8) +U+8A0D(0);U+8A0D(0); +U+8A0E(0);U+8A0E(0,9);U+8BA8(1,3,8) +U+8A0F(0);U+8A0F(0,9); +U+8A10(0);U+8A10(0,9);U+8BA6(1,3,8) +U+8A11(0);U+8A11(0,9); +U+8A12(0);U+8A12(0,9);U+8BB1(4,8) +U+8A13(0);U+8A13(0,9);U+8BAD(1,3,8) +U+8A15(0);U+8A15(0,9);U+8BAA(1,3,8) +U+8A16(0);U+8A16(0,9);U+8BAB(1,3,8) +U+8A17(0);U+8A17(0,9);U+6258(2,4,9),U+8BAC(4,8) +U+8A18(0);U+8A18(0,9);U+8BB0(1,3,8) +U+8A1A(0);U+8ABE(4,8,9);U+8ABE(4,8,9) +U+8A1B(0);U+8A1B(0,9);U+8B4C(2,8),U+8BB9(1,3,8) +U+8A1C(0);U+8A1C(0); +U+8A1D(0);U+8A1D(0,9);U+8BB6(1,3,8) +U+8A1E(0);U+8A1E(0,9);U+5996(3,9),U+7945(3,9) +U+8A1F(0);U+8A1F(0,9);U+8BBC(1,3,8) +U+8A22(0);U+8A22(0,9);U+4723(1,3) +U+8A23(0);U+8A23(0,9);U+8BC0(1,3,8) +U+8A24(0);U+8A24(3); +U+8A25(0);U+8A25(0,9);U+8BB7(1,3,8) +U+8A26(0);U+8A26(0); +U+8A27(0);U+8A27(0,9);U+5C24(3,9) +U+8A28(0);U+8A28(0); +U+8A29(0);U+8A29(0);U+8BBB(1,3,8),U+54C5(0,1,3,8,9) +U+8A2A(0);U+8A2A(0,9);U+8BBF(1,3,8) +U+8A2C(0);U+8A2C(3,9); +U+8A2D(0);U+8A2D(0,9);U+8BBE(1,3,8) +U+8A2E(0);U+8A2E(0); +U+8A2F(0);U+8A2F(0); +U+8A30(0);U+8A30(0,9);U+8C06(4),U+8AC4(1,3,4,8,9) +U+8A31(0);U+8A31(0,9);U+8BB8(1,3,8),U+9126(1,3,8,9) +U+8A32(0);U+8A32(0); +U+8A34(0);U+8A34(0,9);U+8BC9(1,3,8),U+612C(2,3,8,9) +U+8A35(0);U+8A35(3); +U+8A36(0);U+8A36(0,9);U+5475(3,4,8,9),U+8BC3(1,3,8),U+55EC(3,4,8) +U+8A37(0);U+8A37(0); +U+8A38(0);U+8A38(0); +U+8A39(0);U+8A39(0,9); +U+8A3A(0);U+8A3A(0,9);U+8BCA(1,3,8) +U+8A3B(0);U+8A3B(0,9);U+6CE8(2,3,8,9) +U+8A3C(0);U+8A3C(0,9);U+8B49(3,8,9),U+8BC1(4) +U+8A3E(0);U+8A3E(5,9);U+8A3F(3,9) +U+8A3F(0);U+8A3F(0,9);U+8A3E(3,9) +U+8A40(0);U+8A40(3,9); +U+8A41(0);U+8A41(0,9);U+8BC2(1,3,8) +U+8A42(0);U+8A42(0); +U+8A43(0);U+8A43(0); +U+8A44(0);U+8A44(0,9); +U+8A45(0);U+8A45(0,9); +U+8A46(0);U+8A46(0,9);U+8BCB(1,3,8),U+5467(0,1,3,8,9) +U+8A47(0);U+8A47(0); +U+8A48(0);U+8A48(5,9); +U+8A49(0);U+8A49(3); + +U+8A4A(0);U+8A4A(0,9); +U+8A4C(0);U+8A4C(0,9); +U+8A4D(0);U+8A4D(0,9); +U+8A4E(0);U+8A4E(0,9);U+8BB5(1,3,8) +U+8A4F(0);U+8A4F(0,9); +U+8A50(0);U+8A50(0,9);U+8BC8(1,3,8) +U+8A51(0);U+8A51(3,9); +U+8A52(0);U+8A52(0,9);U+8BD2(1,3,8) +U+8A53(0);U+8A53(0); +U+8A54(0);U+8A54(0,9);U+8BCF(1,3,8) +U+8A55(0);U+8A55(0,9);U+8BC4(1,3,8) +U+8A56(0);U+8A56(0,9);U+8BD0(4,8) +U+8A57(0);U+8A57(0,9);U+8BC7(1,3,8) +U+8A58(0);U+8A58(0,9);U+8BCE(1,3,8) +U+8A59(0);U+8A59(0,9); +U+8A5A(0);U+8A5A(0); +U+8A5B(0);U+8A5B(0,9);U+8BC5(1,3,8),U+8B2F(1,3,8,9) +U+8A5C(0);U+8A5C(0); +U+8A5D(0);U+8A5D(0); +U+8A5E(0);U+8A5E(0,9);U+8BCD(1,3,8) +U+8A5F(0);U+8B8B(1,3,8,9);U+8B8B(1,3,8,9) +U+8A60(0);U+8A60(3,9);U+548F(2,3,8) +U+8A61(0);U+8A61(0,9);U+8BE9(1,3,8) +U+8A62(0);U+8A62(0,9);U+8BE2(1,3,8) +U+8A63(0);U+8A63(0,9);U+8BE3(1,3,8) +U+8A65(0);U+8A65(0); +U+8A66(0);U+8A66(0,9);U+8BD5(1,3,8) +U+8A67(0);U+5BDF(2,8,9);U+5BDF(2,8,9) +U+8A68(0);U+8A68(3,9); +U+8A69(0);U+8A69(0,9);U+8BD7(1,3,8) +U+8A6A(0);U+8A6A(0); +U+8A6B(0);U+8A6B(0,9);U+8BE7(1,3,8),U+4F98(0,1,3,8,9) +U+8A6C(0);U+8A6C(0,9);U+8BDF(1,3,8) +U+8A6D(0);U+8A6D(0,9);U+8BE1(1,3,8) +U+8A6E(0);U+8A6E(0,9);U+8BE0(1,3,8) +U+8A6F(0);U+8A6F(0); +U+8A70(0);U+8A70(0,9);U+8BD8(1,3,8) +U+8A71(0);U+8A71(0,9);U+8BDD(1,3,8),U+8AD9(1,3,8,9) +U+8A72(0);U+8A72(0,9);U+8BE5(1,3,8) +U+8A73(0);U+8A73(0,9);U+8BE6(1,3,8) +U+8A74(0);U+8A74(0,9); +U+8A75(0);U+8A75(0,9);U+8BDC(4,8) +U+8A76(0);U+8A76(0,9);U+916C(2,3,8,9),U+9167(2,3,8),U+91BB(2,3,8) +U+8A77(0);U+8A77(0,9); +U+8A79(0);U+8A79(5,9); +U+8A7A(0);U+8A7A(3,9); +U+8A7B(0);U+8A7B(0,9);U+54AF(3,8,9) +U+8A7C(0);U+8A7C(0,9);U+8BD9(1,3,8) +U+8A7E(0);U+8A7E(0); +U+8A7F(0);U+8A7F(0,9);U+8BD6(1,3,8) +U+8A80(0);U+8A80(0); +U+8A81(0);U+8A81(0,9); +U+8A82(0);U+8A82(0,9); +U+8A83(0);U+8A83(3,9); +U+8A84(0);U+8A84(0,9);U+8BD4(1,3,8) +U+8A85(0);U+8A85(0,9);U+8BDB(1,3,8) +U+8A86(0);U+8A86(0,9);U+8BD3(1,3,8) +U+8A87(0);U+8A87(0,9);U+5938(1,3,8,9) +U+8A89(0);U+8B7D(1,3,8,9);U+8B7D(1,3,8,9) +U+8A8A(0);U+8B04(1,3,8,9);U+8B04(1,3,8,9) +U+8A8B(0);U+8A8B(0,9);U+5FCC(3,9),U+8AC5(3,9) +U+8A8C(0);U+8A8C(0,9);U+5FD7(2,3,8,9) +U+8A8D(0);U+8A8D(0,9);U+8BA4(1,3,8) + +U+8A8E(0);U+8A8E(0); +U+8A8F(0);U+8A8F(0,9); +U+8A90(0);U+8A90(0); +U+8A91(0);U+8A91(0,9);U+8BF3(1,3,8) +U+8A92(0);U+8A92(0,9);U+6B38(4,9),U+8BF6(1,3,8) +U+8A93(0);U+8A93(5,9); +U+8A94(0);U+8A94(0); +U+8A95(0);U+8A95(0,9);U+8BDE(1,3,8) +U+8A96(0);U+8A96(0,9);U+6096(2,3,9) +U+8A97(0);U+8A97(0); +U+8A98(0);U+8A98(0,9);U+8BF1(1,3,8) +U+8A99(0);U+8A99(0,9); +U+8A9A(0);U+8A9A(0,9);U+8BEE(1,3,8) +U+8A9B(0);U+8A9B(0); +U+8A9C(0);U+8A9C(3); +U+8A9D(0);U+8A9D(0); +U+8A9E(0);U+8A9E(0,9);U+8BED(1,3,8) +U+8AA0(0);U+8AA0(0,9);U+8BDA(1,3,8) +U+8AA1(0);U+8AA1(0,9);U+8BEB(1,3,8) +U+8AA2(0);U+8AA2(0); +U+8AA3(0);U+8AA3(0,9);U+8BEC(1,3,8) +U+8AA4(0);U+8AA4(0,9);U+609E(3),U+60AE(4),U+8BEF(1,3,8) +U+8AA5(0);U+8AA5(0,9);U+8BF0(1,3,8) +U+8AA6(0);U+8AA6(0,9);U+8BF5(1,3,8) +U+8AA7(0);U+8AA7(0,9); +U+8AA8(0);U+8AA8(0,9);U+8BF2(1,3,8) +U+8AA9(0);U+8AA9(0); +U+8AAA(0);U+8AAA(0,9);U+8AAC(8),U+8BF4(4) +U+8AAB(0);U+8AAB(0,9);U+9707(3,9) +U+8AAC(0);U+8AAA(8,9);U+8AAA(8,9),U+8BF4(1,3,8) +U+8AAE(0);U+8AAE(0); +U+8AB0(0);U+8AB0(0,9);U+8C01(1,3,8) +U+8AB1(0);U+8AB1(0); +U+8AB2(0);U+8AB2(0,9);U+8BFE(1,3,8) +U+8AB3(0);U+8AB3(0); +U+8AB4(0);U+8AB4(0); +U+8AB5(0);U+8AB5(3); +U+8AB6(0);U+8AB6(0,9);U+8C07(1,3,8) +U+8AB8(0);U+8AB8(0,9); +U+8AB9(0);U+8AB9(0,9);U+8BFD(1,3,8) +U+8ABA(0);U+8ABA(0,9); +U+8ABB(0);U+8ABB(0,9); +U+8ABC(0);U+8ABC(0,9);U+8C0A(1,3,8) +U+8ABD(0);U+8ABD(0,9); +U+8ABE(0);U+8ABE(0,9);U+8A1A(4,8) +U+8ABF(0);U+8ABF(0,9);U+8C03(1,3,8) +U+8AC0(0);U+8AC0(3,9); +U+8AC1(0);U+8AC1(3); +U+8AC2(0);U+8AC2(0,9);U+8C04(1,3,8) +U+8AC3(0);U+8AC3(0,9); +U+8AC4(0);U+8AC4(0,9);U+8C06(1,3,8),U+8A30(0,1,3,4,8,9) +U+8AC5(0);U+8AC5(0,9);U+5FCC(3,9),U+8A8B(3,9) +U+8AC6(0);U+8AC6(0,9); +U+8AC7(0);U+8AC7(0,9);U+8C08(1,3,8) +U+8AC8(0);U+8AC8(3,9); +U+8AC9(0);U+8AC9(0,9);U+8BFF(1,3,8) +U+8ACA(0);U+8ACA(0); +U+8ACB(0);U+8ACB(0,9);U+8BF7(1,3,8) +U+8ACC(0);U+8AEB(4,8,9);U+8AEB(4,8,9),U+8C0F(4) +U+8ACD(0);U+8ACD(0,9);U+8BE4(1,3,8) +U+8ACE(0);U+8ACE(3); +U+8ACF(0);U+8ACF(0,9);U+8BF9(1,3,8) +U+8AD1(0);U+8AD1(0,9);U+8BFC(1,3,8) + +U+8AD2(0);U+8AD2(0,9);U+8C05(1,3,8) +U+8AD3(0);U+8AD3(0,9); +U+8AD4(0);U+8AD4(0,9); +U+8AD5(0);U+8AD5(3,9); +U+8AD6(0);U+8AD6(0,9);U+8BBA(1,3,8) +U+8AD7(0);U+8AD7(0,9);U+8C02(1,3,8) +U+8AD8(0);U+8AD8(0,9); +U+8AD9(0);U+8AD9(0,9);U+8BDD(3),U+8A71(0,1,3,8,9) +U+8ADA(0);U+8ADA(0); +U+8ADB(0);U+8ADB(0,9);U+8C00(1,3,8) +U+8ADC(0);U+8ADC(0,9);U+8C0D(1,3,8) +U+8ADD(0);U+8ADD(0,9);U+8C1E(1,3,8) +U+8ADE(0);U+8ADE(0,9);U+8C1D(1,3,8) +U+8ADF(0);U+8ADF(3,9); +U+8AE0(0);U+8AE0(0,9);U+55A7(2,3,8,9),U+5405(0,2,3,8) +U+8AE1(0);U+8AE1(0,9);U+8C25(4),U+8B1A(1,3,4,8,9) +U+8AE2(0);U+8AE2(0,9);U+8BE8(1,3,8),U+9850(1,3,8,9) +U+8AE3(0);U+8AE3(0); +U+8AE4(0);U+8AE4(0,9);U+8C14(1,3,8) +U+8AE5(0);U+8AE5(0); +U+8AE6(0);U+8AE6(0,9);U+8C1B(1,3,8) +U+8AE7(0);U+8AE7(0,9);U+8C10(1,3,8) +U+8AE8(0);U+8AE8(0,9); +U+8AE9(0);U+8B5C(3,8,9);U+8B5C(3,8,9),U+8C31(3) +U+8AEA(0);U+8AEA(0); +U+8AEB(0);U+8AEB(0,9);U+8ACC(4,8),U+8C0F(1,3,8) +U+8AED(0);U+8AED(0,9);U+8C15(1,3,8) +U+8AEE(0);U+8AEE(0,9);U+54A8(3,8,9),U+8C18(1,3,8) +U+8AEF(0);U+8AEF(0,9); +U+8AF0(0);U+8AF0(0,9); +U+8AF1(0);U+8AF1(0,9);U+8BB3(1,3,8) +U+8AF2(0);U+8AF2(0,9); +U+8AF3(0);U+8AF3(0,9);U+8C19(1,3,8) +U+8AF4(0);U+8AF4(0,9); +U+8AF5(0);U+8AF5(0,9);U+5583(3,9),U+5A1A(3,8) +U+8AF6(0);U+8AF6(0,9);U+8C0C(1,3,8) +U+8AF7(0);U+8AF7(0,9);U+8BBD(1,3,8) +U+8AF8(0);U+8AF8(0,9);U+8BF8(1,3,8) +U+8AF9(0);U+8AF9(0); +U+8AFA(0);U+8AFA(0,9);U+8C1A(1,3,8) +U+8AFB(0);U+8AFB(0,9); +U+8AFC(0);U+8AFC(0,9);U+8C16(1,3,8) +U+8AFD(0);U+8AFD(3); +U+8AFE(0);U+8AFE(0,9);U+8BFA(1,3,8) +U+8AFF(0);U+8AFF(0,9); +U+8B00(0);U+8B00(0,9);U+8C0B(1,3,8) +U+8B01(0);U+8B01(0,9);U+8C12(1,3,8) +U+8B02(0);U+8B02(0,9);U+8C13(1,3,8) +U+8B03(0);U+8B03(0); +U+8B04(0);U+8B04(0,9);U+8A8A(1,3,8) +U+8B05(0);U+8B05(0,9);U+8BCC(1,3,8) +U+8B06(0);U+8B06(0,9); +U+8B07(0);U+8B07(5,9); +U+8B08(0);U+8B08(0,9); +U+8B09(0);U+8B09(0); +U+8B0A(0);U+8B0A(0,9);U+8C0E(1,3,8) +U+8B0B(0);U+8B0B(3,9); +U+8B0D(0);U+8B0D(3,9); +U+8B0E(0);U+8B0E(0,9);U+8C1C(1,3,8) +U+8B0F(0);U+8B0F(0,9); +U+8B10(0);U+8B10(0,9);U+8C27(1,3,8) +U+8B11(0);U+8B11(0,9); +U+8B12(0);U+8B12(0,9); + +U+8B13(0);U+8B13(3,9); +U+8B14(0);U+8B14(0,9);U+8C11(1,3,8) +U+8B15(0);U+8B15(0,9);U+557C(3,9) +U+8B16(0);U+8B16(0,9);U+8C21(1,3,8) +U+8B17(0);U+8B17(0,9);U+8C24(1,3,8) +U+8B18(0);U+8B18(0,9); +U+8B19(0);U+8B19(0,9);U+8C26(1,3,8) +U+8B1A(0);U+8B1A(0,9);U+8C25(1,3,8),U+8AE1(0,1,3,4,8,9) +U+8B1B(0);U+8B1B(0,9);U+8BB2(1,3,8) +U+8B1C(0);U+8B1C(0,9); +U+8B1D(0);U+8B1D(0,9);U+8C22(1,3,8) +U+8B1E(0);U+8B1E(0,9); +U+8B1F(0);U+8B1F(0); +U+8B20(0);U+8B20(0,9);U+8B21(4,8),U+8C23(4,8) +U+8B21(0);U+8B20(4,8,9);U+8B20(4,8,9),U+8C23(1,3,8) +U+8B22(0);U+8B22(0,9); +U+8B23(0);U+8B23(3,9); +U+8B24(0);U+8B24(0,9); +U+8B25(0);U+8B25(0,9); +U+8B26(0);U+8B26(5,9); +U+8B27(0);U+8B27(0,9); +U+8B28(0);U+8B28(0,9);U+8C1F(1,3,8),U+8B55(1,3,8,9) +U+8B2A(0);U+8B2A(0,9);U+5546(3,9) +U+8B2B(0);U+8B2B(0,9);U+8C2A(1,3,8) +U+8B2C(0);U+8B2C(0,9);U+8C2C(1,3,8) +U+8B2D(0);U+8B7E(3,8,9);U+8B7E(3,8,9),U+8C2B(1,3,8) +U+8B2E(0);U+8B2E(0,9); +U+8B2F(0);U+8B2F(0,9);U+8BC5(3),U+8A5B(0,1,3,8,9) +U+8B30(0);U+8B30(0,9); +U+8B31(0);U+8B31(0,9); +U+8B33(0);U+8B33(0,9);U+8BB4(1,3,8) +U+8B34(0);U+8B34(0); +U+8B35(0);U+8B35(0,9); +U+8B36(0);U+8B36(0,9);U+5EB6(3,9),U+5EBB(2,3,8) +U+8B37(0);U+8B37(3,9); +U+8B39(0);U+8B39(0,9);U+8C28(1,3,8) +U+8B3A(0);U+8B3A(0,9); +U+8B3B(0);U+8B3B(3,9); +U+8B3C(0);U+8B3C(0,9);U+547C(2,3,8,9),U+5611(2,3,8),U+8656(2,3,8,9) +U+8B3D(0);U+8B3D(0,9); +U+8B3E(0);U+8B3E(0,9);U+8C29(1,3,8) +U+8B40(0);U+8B40(0,9); +U+8B41(0);U+8B41(3,9);U+54D7(4,8),U+5629(2,3,8,9) +U+8B42(0);U+8B42(0,9); +U+8B43(0);U+8B43(0); +U+8B44(0);U+8B44(0); +U+8B45(0);U+8B45(0,9); +U+8B46(0);U+8B46(0,9);U+563B(2,9) +U+8B47(0);U+8B47(0,9); +U+8B48(0);U+8B48(0,9);U+619D(3,9) +U+8B49(0);U+8B49(0,9);U+8A3C(3,8,9),U+8BC1(1,3,8) +U+8B4A(0);U+8B4A(0,9); +U+8B4B(0);U+8B4B(0,9);U+8C30(3),U+8B95(1,3,8,9) +U+8B4C(0);U+8A1B(2,8,9);U+8A1B(2,8,9),U+8BB9(4) +U+8B4D(0);U+8B4D(3);U+5E94(1,3),U+5FDC(4),U+61C9(1,3,8,9) +U+8B4E(0);U+8B4E(0,9);U+8C32(1,3,8),U+564A(0,1,3,8,9) +U+8B4F(0);U+8B4F(0,9);U+8BA5(1,3,8) +U+8B50(0);U+8B50(0,9);U+5642(3,9) +U+8B51(0);U+8B51(0,9);U+6322(4),U+649F(1,3,4,8,9) +U+8B52(0);U+8B52(0,9); +U+8B53(0);U+8B53(3,9); +U+8B54(0);U+8B54(0,9);U+64B0(2,3,9) +U+8B55(0);U+8B55(0,9);U+8C1F(3),U+8B28(0,1,3,8,9) + +U+8B56(0);U+8B56(0,9);U+8C2E(1,3,8) +U+8B57(0);U+8B57(0,9); +U+8B58(0);U+8B58(0,9);U+8BC6(1,3,8) +U+8B59(0);U+8B59(0,9);U+8C2F(1,3,8) +U+8B5A(0);U+8B5A(0,9);U+8C2D(1,3,8) +U+8B5B(0);U+8B5B(0); +U+8B5C(0);U+8B5C(0,9);U+8AE9(3,8),U+8C31(1,3,8) +U+8B5D(0);U+8B5D(3,9); +U+8B5E(0);U+8B5E(0); +U+8B5F(0);U+8B5F(3,9);U+566A(2,3,8,9) +U+8B60(0);U+8B60(0,9); +U+8B63(0);U+8B63(0,9); +U+8B64(0);U+8B64(0); +U+8B65(0);U+8B65(0,9); +U+8B66(0);U+8B66(5,9); +U+8B67(0);U+8B67(0,9); +U+8B68(0);U+8B68(0,9); +U+8B6A(0);U+8B6A(0,9);U+853C(3),U+85F9(1,3,8,9) +U+8B6B(0);U+8B6B(0,9);U+8C35(1,3,8) +U+8B6C(0);U+8B6C(5,9); +U+8B6D(0);U+8B6D(0,9);U+6BC1(2,3),U+6BC0(0,2,3,4,8,9) +U+8B6E(0);U+8B6E(3); +U+8B6F(0);U+8B6F(0,9);U+8BD1(1,3,8) +U+8B70(0);U+8B70(0,9);U+8BAE(1,3,8) +U+8B71(0);U+5584(3,8,9);U+5584(3,8,9) +U+8B73(0);U+8B73(0); +U+8B74(0);U+8B74(0,9);U+8C34(1,3,8) +U+8B76(0);U+8B76(0); +U+8B77(0);U+8B77(0,9);U+62A4(1,3,8) +U+8B78(0);U+8B78(0,9);U+8BEA(4,8) +U+8B79(0);U+8B79(0,9);U+53F7(3),U+865F(1,3,8,9) +U+8B7A(0);U+8B7A(0,9); +U+8B7B(0);U+8B7B(0,9);U+5624(3),U+56B6(1,3,8,9) +U+8B7D(0);U+8B7D(0,9);U+8A89(1,3,8) +U+8B7E(0);U+8B7E(0,9);U+8B2D(3,8),U+8C2B(4) +U+8B7F(0);U+8B7F(0,9);U+6167(3,9) +U+8B80(0);U+8B80(0,9);U+8BFB(1,3,8) +U+8B82(0);U+8B82(0,9); +U+8B83(0);U+8B9A(3,8,9);U+8B9A(3,8,9),U+8D5E(7),U+8D0A(2,3,8,9),U+8CDB(4,7) +U+8B84(0);U+8B84(0,9); +U+8B85(0);U+8B85(0,9);U+8C09(1,3,8) +U+8B86(0);U+8B86(0,9); +U+8B88(0);U+8B88(0,9); +U+8B89(0);U+8B89(0); +U+8B8A(0);U+8B8A(0,9);U+5909(3,8),U+53D8(1,3,8) +U+8B8B(0);U+8B8B(0,9);U+8A5F(1,3,8) +U+8B8C(0);U+8B8C(0,9);U+4729(1,3) +U+8B8E(0);U+8B8E(0,9);U+4EC7(3,8,9),U+8B90(3),U+96E0(1,3,8) +U+8B90(0);U+8B8E(3,9);U+4EC7(2,8,9),U+8B8E(3,9),U+96E0(7) +U+8B91(0);U+8B91(3); +U+8B92(0);U+8B92(0,9);U+8C17(1,3,8) +U+8B93(0);U+8B93(0,9);U+8BA9(1,3,8) +U+8B94(0);U+8B94(0,9); +U+8B95(0);U+8B95(0,9);U+8C30(1,3,8),U+8B4B(0,1,3,8,9) +U+8B96(0);U+8B96(0,9);U+8C36(1,3,8) +U+8B97(0);U+8B97(0); +U+8B98(0);U+8B98(3,9); +U+8B99(0);U+8B99(0,9);U+6B22(4),U+6B61(2,8,9),U+61FD(0,4,9),U+6B53(3,4),U+9A69(4,9) +U+8B9A(0);U+8B9A(3,9);U+8B83(3,8),U+8D0A(2,9),U+8D5E(4),U+8CDB(3,4,7,8) +U+8B9C(0);U+8B9C(0,9);U+8C20(1,3,8) +U+8B9D(0);U+8B9D(0); +U+8B9E(0);U+8B9E(0,9);U+8C33(1,3,8) +U+8B9F(0);U+8B9F(3,9); + +U+8BA0(0);U+8A00(8,9);U+8A00(8,9),U+8A01(4,8) +U+8BA1(0);U+8A08(1,3,8,9);U+8A08(1,3,8,9) +U+8BA2(0);U+8A02(1,3,8,9);U+8A02(1,3,8,9) +U+8BA3(0);U+8A03(1,3,8,9);U+8A03(1,3,8,9) +U+8BA4(0);U+8A8D(1,3,8,9);U+8A8D(1,3,8,9) +U+8BA5(0);U+8B4F(1,3,8,9);U+8B4F(1,3,8,9) +U+8BA6(0);U+8A10(1,3,8,9);U+8A10(1,3,8,9) +U+8BA7(0);U+8A0C(1,3,8,9);U+8A0C(1,3,8,9) +U+8BA8(0);U+8A0E(1,3,8,9);U+8A0E(1,3,8,9) +U+8BA9(0);U+8B93(1,3,8,9);U+8B93(1,3,8,9) +U+8BAA(0);U+8A15(1,3,8,9);U+8A15(1,3,8,9) +U+8BAB(0);U+8A16(1,3,8,9);U+8A16(1,3,8,9) +U+8BAC(0);U+8A17(4,8,9);U+6258(4,9),U+8A17(4,8,9) +U+8BAD(0);U+8A13(1,3,8,9);U+8A13(1,3,8,9) +U+8BAE(0);U+8B70(1,3,8,9);U+8B70(1,3,8,9) +U+8BAF(0);U+8A0A(1,3,8,9);U+8A0A(1,3,8,9) +U+8BB0(0);U+8A18(1,3,8,9);U+8A18(1,3,8,9) +U+8BB1(0);U+8A12(4,8,9);U+8A12(4,8,9) +U+8BB2(0);U+8B1B(1,3,8,9);U+8B1B(1,3,8,9) +U+8BB3(0);U+8AF1(1,3,8,9);U+8AF1(1,3,8,9) +U+8BB4(0);U+8B33(1,3,8,9);U+8B33(1,3,8,9) +U+8BB5(0);U+8A4E(1,3,8,9);U+8A4E(1,3,8,9) +U+8BB6(0);U+8A1D(1,3,8,9);U+8A1D(1,3,8,9) +U+8BB7(0);U+8A25(1,3,8,9);U+8A25(1,3,8,9) +U+8BB8(0);U+8A31(1,3,8,9);U+8A31(1,3,8,9),U+9126(3,9) +U+8BB9(0);U+8A1B(1,3,8,9);U+8A1B(1,3,8,9),U+8B4C(4) +U+8BBA(0);U+8AD6(1,3,8,9);U+8AD6(1,3,8,9) +U+8BBB(0);U+8A29(1,3,8);U+54C5(3,9),U+8A29(1,3,8) +U+8BBC(0);U+8A1F(1,3,8,9);U+8A1F(1,3,8,9) +U+8BBD(0);U+8AF7(1,3,8,9);U+8AF7(1,3,8,9) +U+8BBE(0);U+8A2D(1,3,8,9);U+8A2D(1,3,8,9) +U+8BBF(0);U+8A2A(1,3,8,9);U+8A2A(1,3,8,9) +U+8BC0(0);U+8A23(1,3,8,9);U+8A23(1,3,8,9) +U+8BC1(0);U+8B49(1,3,8,9);U+8A3C(4,9),U+8B49(1,3,8,9) +U+8BC2(0);U+8A41(1,3,8,9);U+8A41(1,3,8,9) +U+8BC3(0);U+8A36(1,3,8,9);U+8A36(1,3,8,9),U+5475(1,3,4,5,8,9),U+55EC(1,3,4,8) +U+8BC4(0);U+8A55(1,3,8,9);U+8A55(1,3,8,9) +U+8BC5(0);U+8A5B(1,3,8,9);U+8A5B(1,3,8,9),U+8B2F(3,9) +U+8BC6(0);U+8B58(1,3,8,9);U+8B58(1,3,8,9) +U+8BC7(0);U+8A57(1,3,8,9);U+8A57(1,3,8,9) +U+8BC8(0);U+8A50(1,3,8,9);U+8A50(1,3,8,9) +U+8BC9(0);U+8A34(1,3,8,9);U+612C(3,9),U+8A34(1,3,8,9) +U+8BCA(0);U+8A3A(1,3,8,9);U+8A3A(1,3,8,9) +U+8BCB(0);U+8A46(1,3,8,9);U+5467(3,9),U+8A46(1,3,8,9) +U+8BCC(0);U+8B05(1,3,8,9);U+8B05(1,3,8,9) +U+8BCD(0);U+8A5E(1,3,8,9);U+8A5E(1,3,8,9) +U+8BCE(0);U+8A58(1,3,8,9);U+8A58(1,3,8,9) +U+8BCF(0);U+8A54(1,3,8,9);U+8A54(1,3,8,9) +U+8BD0(0);U+8A56(4,8,9);U+8A56(4,8,9) +U+8BD1(0);U+8B6F(1,3,8,9);U+8B6F(1,3,8,9) +U+8BD2(0);U+8A52(1,3,8,9);U+8A52(1,3,8,9) +U+8BD3(0);U+8A86(1,3,8,9);U+8A86(1,3,8,9) +U+8BD4(0);U+8A84(1,3,8,9);U+8A84(1,3,8,9) +U+8BD5(0);U+8A66(1,3,8,9);U+8A66(1,3,8,9) +U+8BD6(0);U+8A7F(1,3,8,9);U+8A7F(1,3,8,9) +U+8BD7(0);U+8A69(1,3,8,9);U+8A69(1,3,8,9) +U+8BD8(0);U+8A70(1,3,8,9);U+8A70(1,3,8,9) +U+8BD9(0);U+8A7C(1,3,8,9);U+8A7C(1,3,8,9) +U+8BDA(0);U+8AA0(1,3,8,9);U+8AA0(1,3,8,9) +U+8BDB(0);U+8A85(1,3,8,9);U+8A85(1,3,8,9) +U+8BDC(0);U+8A75(4,8,9);U+8A75(4,8,9) +U+8BDD(0);U+8A71(1,3,8,9);U+8A71(1,3,8,9),U+8AD9(3,9) +U+8BDE(0);U+8A95(1,3,8,9);U+8A95(1,3,8,9) + +U+8BDF(0);U+8A6C(1,3,8,9);U+8A6C(1,3,8,9) +U+8BE0(0);U+8A6E(1,3,8,9);U+8A6E(1,3,8,9) +U+8BE1(0);U+8A6D(1,3,8,9);U+8A6D(1,3,8,9) +U+8BE2(0);U+8A62(1,3,8,9);U+8A62(1,3,8,9) +U+8BE3(0);U+8A63(1,3,8,9);U+8A63(1,3,8,9) +U+8BE4(0);U+8ACD(1,3,8,9);U+8ACD(1,3,8,9) +U+8BE5(0);U+8A72(1,3,8,9);U+8A72(1,3,8,9) +U+8BE6(0);U+8A73(1,3,8,9);U+8A73(1,3,8,9) +U+8BE7(0);U+8A6B(1,3,8,9);U+4F98(3,9),U+8A6B(1,3,8,9) +U+8BE8(0);U+8AE2(1,3,8,9);U+8AE2(1,3,8,9),U+9850(3,9) +U+8BE9(0);U+8A61(1,3,8,9);U+8A61(1,3,8,9) +U+8BEA(0);U+8B78(4,8,9);U+8B78(4,8,9) +U+8BEB(0);U+8AA1(1,3,8,9);U+8AA1(1,3,8,9) +U+8BEC(0);U+8AA3(1,3,8,9);U+8AA3(1,3,8,9) +U+8BED(0);U+8A9E(1,3,8,9);U+8A9E(1,3,8,9) +U+8BEE(0);U+8A9A(1,3,8,9);U+8A9A(1,3,8,9) +U+8BEF(0);U+8AA4(1,3,8,9);U+609E(3),U+60AE(4),U+8AA4(1,3,8,9) +U+8BF0(0);U+8AA5(1,3,8,9);U+8AA5(1,3,8,9) +U+8BF1(0);U+8A98(1,3,8,9);U+8A98(1,3,8,9) +U+8BF2(0);U+8AA8(1,3,8,9);U+8AA8(1,3,8,9) +U+8BF3(0);U+8A91(1,3,8,9);U+8A91(1,3,8,9) +U+8BF4(0);U+8AAA(4,9);U+8AAA(4,9),U+8AAC(1,3,8) +U+8BF5(0);U+8AA6(1,3,8,9);U+8AA6(1,3,8,9) +U+8BF6(0);U+8A92(1,3,8,9);U+8A92(1,3,8,9),U+6B38(1,3,4,8,9) +U+8BF7(0);U+8ACB(1,3,8,9);U+8ACB(1,3,8,9) +U+8BF8(0);U+8AF8(1,3,8,9);U+8AF8(1,3,8,9) +U+8BF9(0);U+8ACF(1,3,8,9);U+8ACF(1,3,8,9) +U+8BFA(0);U+8AFE(1,3,8,9);U+8AFE(1,3,8,9) +U+8BFB(0);U+8B80(1,3,8,9);U+8B80(1,3,8,9) +U+8BFC(0);U+8AD1(1,3,8,9);U+8AD1(1,3,8,9) +U+8BFD(0);U+8AB9(1,3,8,9);U+8AB9(1,3,8,9) +U+8BFE(0);U+8AB2(1,3,8,9);U+8AB2(1,3,8,9) +U+8BFF(0);U+8AC9(1,3,8,9);U+8AC9(1,3,8,9) +U+8C00(0);U+8ADB(1,3,8,9);U+8ADB(1,3,8,9) +U+8C01(0);U+8AB0(1,3,8,9);U+8AB0(1,3,8,9) +U+8C02(0);U+8AD7(1,3,8,9);U+8AD7(1,3,8,9) +U+8C03(0);U+8ABF(1,3,8,9);U+8ABF(1,3,8,9) +U+8C04(0);U+8AC2(1,3,8,9);U+8AC2(1,3,8,9) +U+8C05(0);U+8AD2(1,3,8,9);U+8AD2(1,3,8,9) +U+8C06(0);U+8AC4(1,3,8,9);U+8A30(4,9),U+8AC4(1,3,8,9) +U+8C07(0);U+8AB6(1,3,8,9);U+8AB6(1,3,8,9) +U+8C08(0);U+8AC7(1,3,8,9);U+8AC7(1,3,8,9) +U+8C09(0);U+8B85(1,3,8,9);U+8B85(1,3,8,9) +U+8C0A(0);U+8ABC(1,3,8,9);U+8ABC(1,3,8,9) +U+8C0B(0);U+8B00(1,3,8,9);U+8B00(1,3,8,9) +U+8C0C(0);U+8AF6(1,3,8,9);U+8AF6(1,3,8,9) +U+8C0D(0);U+8ADC(1,3,8,9);U+8ADC(1,3,8,9) +U+8C0E(0);U+8B0A(1,3,8,9);U+8B0A(1,3,8,9) +U+8C0F(0);U+8AEB(1,3,8,9);U+8ACC(4),U+8AEB(1,3,8,9) +U+8C10(0);U+8AE7(1,3,8,9);U+8AE7(1,3,8,9) +U+8C11(0);U+8B14(1,3,8,9);U+8B14(1,3,8,9) +U+8C12(0);U+8B01(1,3,8,9);U+8B01(1,3,8,9) +U+8C13(0);U+8B02(1,3,8,9);U+8B02(1,3,8,9) +U+8C14(0);U+8AE4(1,3,8,9);U+8AE4(1,3,8,9) +U+8C15(0);U+8AED(1,3,8,9);U+8AED(1,3,8,9) +U+8C16(0);U+8AFC(1,3,8,9);U+8AFC(1,3,8,9) +U+8C17(0);U+8B92(1,3,8,9);U+8B92(1,3,8,9) +U+8C18(0);U+8AEE(1,3,8,9);U+8AEE(1,3,8,9),U+54A8(1,3,5,8,9) +U+8C19(0);U+8AF3(1,3,8,9);U+8AF3(1,3,8,9) +U+8C1A(0);U+8AFA(1,3,8,9);U+8AFA(1,3,8,9) +U+8C1B(0);U+8AE6(1,3,8,9);U+8AE6(1,3,8,9) +U+8C1C(0);U+8B0E(1,3,8,9);U+8B0E(1,3,8,9) +U+8C1D(0);U+8ADE(1,3,8,9);U+8ADE(1,3,8,9) + +U+8C1E(0);U+8ADD(1,3,8,9);U+8ADD(1,3,8,9) +U+8C1F(0);U+8B28(1,3,8,9);U+8B28(1,3,8,9),U+8B55(3,9) +U+8C20(0);U+8B9C(1,3,8,9);U+8B9C(1,3,8,9) +U+8C21(0);U+8B16(1,3,8,9);U+8B16(1,3,8,9) +U+8C22(0);U+8B1D(1,3,8,9);U+8B1D(1,3,8,9) +U+8C23(0);U+8B20(4,8,9);U+8B20(4,8,9),U+8B21(1,3,8) +U+8C24(0);U+8B17(1,3,8,9);U+8B17(1,3,8,9) +U+8C25(0);U+8B1A(1,3,8,9);U+8AE1(4,9),U+8B1A(1,3,8,9) +U+8C26(0);U+8B19(1,3,8,9);U+8B19(1,3,8,9) +U+8C27(0);U+8B10(1,3,8,9);U+8B10(1,3,8,9) +U+8C28(0);U+8B39(1,3,8,9);U+8B39(1,3,8,9) +U+8C29(0);U+8B3E(1,3,8,9);U+8B3E(1,3,8,9) +U+8C2A(0);U+8B2B(1,3,8,9);U+8B2B(1,3,8,9) +U+8C2B(0);U+8B7E(4,9);U+8B2D(1,3,8),U+8B7E(4,9) +U+8C2C(0);U+8B2C(1,3,8,9);U+8B2C(1,3,8,9) +U+8C2D(0);U+8B5A(1,3,8,9);U+8B5A(1,3,8,9) +U+8C2E(0);U+8B56(1,3,8,9);U+8B56(1,3,8,9) +U+8C2F(0);U+8B59(1,3,8,9);U+8B59(1,3,8,9) +U+8C30(0);U+8B95(1,3,8,9);U+8B4B(3,9),U+8B95(1,3,8,9) +U+8C31(0);U+8B5C(1,3,8,9);U+8AE9(3),U+8B5C(1,3,8,9) +U+8C32(0);U+8B4E(1,3,8,9);U+564A(3,9),U+8B4E(1,3,8,9) +U+8C33(0);U+8B9E(1,3,8,9);U+8B9E(1,3,8,9) +U+8C34(0);U+8B74(1,3,8,9);U+8B74(1,3,8,9) +U+8C35(0);U+8B6B(1,3,8,9);U+8B6B(1,3,8,9) +U+8C36(0);U+8B96(1,3,8,9);U+8B96(1,3,8,9) +U+8C37(0);U+8C37(1,3,9),U+7A40(1,3,4,8,9);U+7A40(1,3,4,8,9) +U+8C39(0);U+8C39(0,9); +U+8C3A(0);U+8C3A(0); +U+8C3B(0);U+8C3B(0,9); +U+8C3C(0);U+8C3C(3,9); +U+8C3D(0);U+8C3D(0,9); +U+8C3E(0);U+8C3E(0,9); +U+8C3F(0);U+8C3F(0,9);U+6EAA(2,3,9) +U+8C41(0);U+8C41(5,9); +U+8C42(0);U+8C42(0,9); +U+8C43(0);U+8C43(0,9); +U+8C45(0);U+8C45(3,9); +U+8C46(0);U+8C46(5,9),U+8373(2,9);U+68AA(3,9),U+8373(2,9) +U+8C47(0);U+8C47(5,9); +U+8C48(0);U+8C48(0,9);U+5C82(1,3,8) +U+8C49(0);U+8C49(5,9); +U+8C4A(0);U+8C4A(0,9);U+4E30(3,9),U+8C50(3,8,9) +U+8C4B(0);U+8C4B(0,9);U+767B(4,9) +U+8C4C(0);U+8C4C(5,9); +U+8C4D(0);U+8C4D(0,9); +U+8C4E(0);U+8C4E(0,9);U+7AD6(4,8),U+7AEA(2,3,8) +U+8C4F(0);U+8C4F(0,9); +U+8C50(0);U+8C50(0,9);U+4E30(1,3,8,9),U+8C4A(3,8,9) +U+8C54(0);U+8C54(0,9);U+8273(4,8),U+8276(4,8),U+8277(2,3,8,9) +U+8C55(0);U+8C55(5,9); +U+8C56(0);U+8C56(0,9); +U+8C57(0);U+8C57(3,9);U+62FB(3,9) +U+8C59(0);U+8C59(0); +U+8C5A(0);U+8C5A(5,9); +U+8C5B(0);U+8C5B(0); +U+8C5C(0);U+8C5C(0,9);U+8C63(3,8) +U+8C5D(0);U+8C5D(0,9); +U+8C5E(0);U+8C5E(0); +U+8C5F(0);U+8C5F(0,9); +U+8C60(0);U+8C60(0); +U+8C61(0);U+8C61(5,9);U+50CF(3,8,9) +U+8C62(0);U+8C62(5,9); +U+8C63(0);U+8C5C(3,8,9);U+8C5C(3,8,9) + +U+8C64(0);U+8C64(3,9); +U+8C65(0);U+8C65(0,9); +U+8C66(0);U+8C66(0,9); +U+8C67(0);U+8C67(0); +U+8C68(0);U+8C68(3,9); +U+8C69(0);U+8C69(0,9); +U+8C6A(0);U+8C6A(5,9); +U+8C6B(0);U+8C6B(5,9); +U+8C6C(0);U+8C6C(0,9);U+732A(2,3,8) +U+8C6D(0);U+8C6D(3,9); +U+8C6E(0);U+8C76(1,3,9);U+8C76(1,3,9) +U+8C6F(0);U+8C6F(0,9); +U+8C70(0);U+8C70(0,9); +U+8C71(0);U+8C71(0,9); +U+8C72(0);U+8C72(3,9); +U+8C73(0);U+8C73(5,9); +U+8C75(0);U+8C75(0,9); +U+8C76(0);U+8C76(0,9);U+8C6E(1,3) +U+8C77(0);U+8C77(0,9); +U+8C78(0);U+8C78(5,9); +U+8C79(0);U+8C79(5,9); +U+8C7A(0);U+8C7A(5,9);U+72B2(3,8) +U+8C7B(0);U+8C7B(3,9); +U+8C7D(0);U+8C7D(0,9); +U+8C7E(0);U+8C7E(3); +U+8C80(0);U+8C80(3,9); +U+8C81(0);U+8C81(3,9); +U+8C82(0);U+8C82(5,9); +U+8C84(0);U+8C84(0,9); +U+8C85(0);U+8C85(5,9); +U+8C86(0);U+8C86(0,9); +U+8C88(0);U+8C88(4); +U+8C89(0);U+8C89(5,9);U+72E2(3,8) +U+8C8A(0);U+8C8A(5,9); +U+8C8C(0);U+8C8C(5,9);U+7683(3,8) +U+8C8D(0);U+8C8D(0,9);U+72F8(2,3,8,9) +U+8C8F(0);U+8C8F(0,9); +U+8C90(0);U+8C90(0,9); +U+8C91(0);U+8C91(0,9); +U+8C92(0);U+8C92(3,9); +U+8C93(0);U+8C93(0,9);U+732B(2,3) +U+8C94(0);U+8C94(5,9); +U+8C95(0);U+8C95(0,9); +U+8C96(0);U+8C96(0); +U+8C97(0);U+8C97(0,9); +U+8C98(0);U+8C98(5,9); +U+8C99(0);U+8C99(0,9); +U+8C9A(0);U+8C9A(0,9); +U+8C9C(0);U+8C9C(0,9);U+7383(3,9) +U+8C9D(0);U+8C9D(0,9);U+8D1D(1,3,8) +U+8C9E(0);U+8C9E(0,9);U+8D1E(1,3,8) +U+8C9F(0);U+8C9F(0);U+8D20(4,8) +U+8CA0(0);U+8CA0(0,9);U+8D1F(1,3,8) +U+8CA1(0);U+8CA1(0,9);U+8D22(1,3,8) +U+8CA2(0);U+8CA2(0,9);U+8D21(1,3,8) +U+8CA3(0);U+8CA3(3,9); +U+8CA4(0);U+8CA4(0,9); +U+8CA5(0);U+8CA5(0,9); +U+8CA7(0);U+8CA7(0,9);U+8D2B(1,3,8) +U+8CA8(0);U+8CA8(0,9);U+8D27(1,3,8) +U+8CA9(0);U+8CA9(0,9);U+8D29(1,3,8) +U+8CAA(0);U+8CAA(0,9);U+8D2A(1,3,8) +U+8CAB(0);U+8CAB(0,9);U+8D2F(1,3,8) + +U+8CAC(0);U+8CAC(0,9);U+8D23(1,3,8) +U+8CAD(0);U+8CEA(3,8,9);U+8CEA(3,8,9),U+8D28(3) +U+8CAE(0);U+8CB3(4,9);U+8CB3(4,9),U+8D30(4),U+4E8C(3,4,5,8,9),U+5F0D(3,4,8) +U+8CAF(0);U+8CAF(0,9);U+8D2E(1,3,8) +U+8CB0(0);U+8CB0(0,9);U+8D33(1,3,8) +U+8CB1(0);U+8CB1(0); +U+8CB2(0);U+8CB2(0,9);U+8D40(4,8) +U+8CB3(0);U+8CB3(0,9);U+4E8C(3,8,9),U+8CAE(4),U+8D30(1,3,8),U+5F0D(3,8) +U+8CB4(0);U+8CB4(0,9);U+8D35(1,3,8) +U+8CB5(0);U+8CB5(0,9); +U+8CB6(0);U+8CB6(0,9);U+8D2C(1,3,8) +U+8CB7(0);U+8CB7(0,9);U+4E70(1,3,8) +U+8CB8(0);U+8CB8(0,9);U+8D37(1,3,8) +U+8CB9(0);U+8CB9(0,9); +U+8CBA(0);U+8CBA(0,9);U+8D36(1,3,8) +U+8CBB(0);U+8CBB(0,9);U+8D39(1,3,8) +U+8CBC(0);U+8CBC(0,9);U+8D34(1,3,8) +U+8CBD(0);U+8CBD(0,9);U+8D3B(1,3,8) +U+8CBE(0);U+8CBE(0,9); +U+8CBF(0);U+8CBF(0,9);U+8D38(1,3,8) +U+8CC0(0);U+8CC0(0,9);U+8D3A(1,3,8) +U+8CC1(0);U+8CC1(0,9);U+8D32(1,3,8) +U+8CC2(0);U+8CC2(0,9);U+8D42(1,3,8) +U+8CC3(0);U+8CC3(0,9);U+8D41(1,3,8) +U+8CC4(0);U+8CC4(0,9);U+8D3F(1,3,8) +U+8CC5(0);U+8CC5(0,9);U+8D45(1,3,8),U+8CCC(1,3,8,9) +U+8CC6(0);U+8CC6(0); +U+8CC7(0);U+8CC7(0,9);U+8D44(1,3,8) +U+8CC8(0);U+8CC8(0,9);U+8D3E(1,3,8) +U+8CC9(0);U+6064(2,3,8,9);U+6064(2,3,8,9),U+5379(0,2,3,8,9) +U+8CCA(0);U+8CCA(0,9);U+621D(3,8),U+8D3C(1,3,8) +U+8CCC(0);U+8CCC(0,9);U+8D45(3),U+8CC5(0,1,3,8,9) +U+8CCE(0);U+8CCE(0); +U+8CCF(0);U+8CCF(0,9); +U+8CD0(0);U+8CD0(0); +U+8CD1(0);U+8CD1(0,9);U+8D48(1,3,8) +U+8CD2(0);U+8CD2(0,9);U+8D4A(1,8) +U+8CD3(0);U+8CD3(0,9);U+5BBE(1,3,8),U+8CD4(3,8) +U+8CD4(0);U+8CD3(3,8,9);U+5BBE(3),U+8CD3(3,8,9) +U+8CD5(0);U+8CD5(0,9);U+8D47(4,8) +U+8CD7(0);U+8CD7(0,9);U+4E32(4,9) +U+8CD9(0);U+8CD9(0,9);U+8D52(1,3,8) +U+8CDA(0);U+8CDA(0,9);U+8D49(1,3,8) +U+8CDB(0);U+8D0A(2,3,8,9);U+8D0A(2,3,8,9),U+8D5E(4),U+8B83(0,4,7),U+8B9A(3,4,7,8,9) +U+8CDC(0);U+8CDC(0,9);U+8D50(1,3,8) +U+8CDD(0);U+8CDD(0,9);U+741B(3,9) +U+8CDE(0);U+8CDE(0,9);U+8D4F(1,3,8) +U+8CDF(0);U+8CDF(0,9); +U+8CE0(0);U+8CE0(0,9);U+8D54(1,3,8) +U+8CE1(0);U+8CE1(0,9);U+8D53(1,3,8) +U+8CE2(0);U+8CE2(0,9);U+8D24(1,3,8) +U+8CE3(0);U+8CE3(0,9);U+5356(1,3,8),U+58F2(4,8) +U+8CE4(0);U+8CE4(0,9);U+8D31(1,3,8) +U+8CE5(0);U+8CE5(0,9); +U+8CE6(0);U+8CE6(0,9);U+8D4B(1,3,8) +U+8CE7(0);U+8CE7(0,9);U+8D55(1,3,8) +U+8CE8(0);U+8CE8(3,9); +U+8CEA(0);U+8CEA(0,9);U+8CAD(3,8),U+8D28(1,3,8) +U+8CEB(0);U+8CEB(0);U+8D4D(1,3,8),U+9F4E(1,3,8,9) +U+8CEC(0);U+8CEC(0,9);U+5E33(3,8,9),U+8D26(1,3,8),U+5E10(1,3,8) +U+8CED(0);U+8CED(0,9);U+8D4C(1,3,8) +U+8CEE(0);U+8CEE(0,9);U+8D46(3),U+8D10(1,3,8,9) +U+8CEF(0);U+8CEF(0); + +U+8CF0(0);U+8CF0(0,9); +U+8CF1(0);U+8CF1(0,9); +U+8CF2(0);U+8CF2(0); +U+8CF3(0);U+8CF3(0,9); +U+8CF4(0);U+8CF4(0,9);U+8D56(1,3,8),U+983C(2,3,8) +U+8CF5(0);U+8CF5(0,9);U+8D57(1,3,8) +U+8CF6(0);U+8CF6(0); +U+8CF8(0);U+8CF8(0,9);U+5269(2,3,8,9),U+5270(2,3,4,8) +U+8CF9(0);U+8CF9(0,9);U+9552(3),U+93B0(1,3,8,9) +U+8CFA(0);U+8CFA(0,9);U+8D5A(1,3,8) +U+8CFB(0);U+8CFB(0,9);U+8D59(1,3,8) +U+8CFC(0);U+8CFC(0,9);U+8D2D(1,3,8) +U+8CFD(0);U+8CFD(0,9);U+8D5B(1,3,8) +U+8CFE(0);U+8CFE(0,9);U+8D5C(1,3,8) +U+8CFF(0);U+8CFF(0); +U+8D00(0);U+8D00(0,9); +U+8D02(0);U+8D02(0,9); +U+8D03(0);U+8D03(0); +U+8D04(0);U+8D04(0,9);U+8D3D(1,3,8) +U+8D05(0);U+8D05(0,9);U+8D58(1,3,8) +U+8D06(0);U+8D06(3,9); +U+8D07(0);U+8D07(0,9);U+8D5F(4,8) +U+8D08(0);U+8D08(0,9);U+8D60(1,3,8) +U+8D09(0);U+8D09(0,9); +U+8D0A(0);U+8D0A(0,9);U+8B9A(2,9),U+8CDB(2,3,8),U+8D5E(1,3,8),U+8B83(0,2,3,8) +U+8D0B(0);U+8D17(2,3,8,9);U+8D17(2,3,8,9),U+8D5D(1,3,8) +U+8D0C(0);U+8D0C(0); +U+8D0D(0);U+8D0D(0,9);U+8D61(1,3,8) +U+8D0E(0);U+8D0E(0); +U+8D0F(0);U+8D0F(0,9);U+8D62(1,3,8) +U+8D10(0);U+8D10(0,9);U+8D46(1,3,8),U+8CEE(0,1,3,8,9) +U+8D13(0);U+8D13(0,9);U+8D1C(3,8),U+8D43(4,8) +U+8D14(0);U+8D14(0,9);U+8D51(4,8) +U+8D15(0);U+8D15(0,9); +U+8D16(0);U+8D16(0,9);U+8D4E(1,3,8) +U+8D17(0);U+8D17(0,9);U+8D0B(2,3,8),U+8D5D(4) +U+8D18(0);U+8D18(0); +U+8D19(0);U+8D19(0,9); +U+8D1A(0);U+8D1A(0); +U+8D1B(0);U+8D1B(0,9);U+8D63(1,3,8),U+7068(0,1,2,3,8,9) +U+8D1C(0);U+8D13(3,8,9);U+8D13(3,8,9),U+8D43(1,3,8) +U+8D1D(0);U+8C9D(1,3,8,9);U+8C9D(1,3,8,9) +U+8D1E(0);U+8C9E(1,3,8,9);U+8C9E(1,3,8,9) +U+8D1F(0);U+8CA0(1,3,8,9);U+8CA0(1,3,8,9) +U+8D20(0);U+8C9F(4,8);U+8C9F(4,8) +U+8D21(0);U+8CA2(1,3,8,9);U+8CA2(1,3,8,9) +U+8D22(0);U+8CA1(1,3,8,9);U+8CA1(1,3,8,9) +U+8D23(0);U+8CAC(1,3,8,9);U+8CAC(1,3,8,9) +U+8D24(0);U+8CE2(1,3,8,9);U+8CE2(1,3,8,9) +U+8D25(0);U+6557(1,3,8,9);U+6557(1,3,8,9) +U+8D26(0);U+8CEC(1,3,8,9);U+8CEC(1,3,8,9),U+5E10(1,3,8),U+5E33(0,1,3,8,9) +U+8D27(0);U+8CA8(1,3,8,9);U+8CA8(1,3,8,9) +U+8D28(0);U+8CEA(1,3,8,9);U+8CAD(3),U+8CEA(1,3,8,9) +U+8D29(0);U+8CA9(1,3,8,9);U+8CA9(1,3,8,9) +U+8D2A(0);U+8CAA(1,3,8,9);U+8CAA(1,3,8,9) +U+8D2B(0);U+8CA7(1,3,8,9);U+8CA7(1,3,8,9) +U+8D2C(0);U+8CB6(1,3,8,9);U+8CB6(1,3,8,9) +U+8D2D(0);U+8CFC(1,3,8,9);U+8CFC(1,3,8,9) +U+8D2E(0);U+8CAF(1,3,4,8,9);U+8CAF(1,3,4,8,9) +U+8D2F(0);U+8CAB(1,3,8,9);U+8CAB(1,3,8,9) +U+8D30(0);U+8CB3(1,3,8,9);U+8CAE(4),U+8CB3(1,3,8,9),U+4E8C(1,3,5,8,9),U+5F0D(1,3,8) +U+8D31(0);U+8CE4(1,3,8,9);U+8CE4(1,3,8,9) +U+8D32(0);U+8CC1(1,3,8,9);U+8CC1(1,3,8,9) + +U+8D33(0);U+8CB0(1,3,8,9);U+8CB0(1,3,8,9) +U+8D34(0);U+8CBC(1,3,8,9);U+8CBC(1,3,8,9) +U+8D35(0);U+8CB4(1,3,8,9);U+8CB4(1,3,8,9) +U+8D36(0);U+8CBA(1,3,8,9);U+8CBA(1,3,8,9) +U+8D37(0);U+8CB8(1,3,8,9);U+8CB8(1,3,8,9) +U+8D38(0);U+8CBF(1,3,8,9);U+8CBF(1,3,8,9) +U+8D39(0);U+8CBB(1,3,8,9);U+8CBB(1,3,8,9) +U+8D3A(0);U+8CC0(1,3,8,9);U+8CC0(1,3,8,9) +U+8D3B(0);U+8CBD(1,3,8,9);U+8CBD(1,3,8,9) +U+8D3C(0);U+8CCA(1,3,8,9);U+621D(3),U+8CCA(1,3,8,9) +U+8D3D(0);U+8D04(1,3,8,9);U+8D04(1,3,8,9) +U+8D3E(0);U+8CC8(1,3,8,9);U+8CC8(1,3,8,9) +U+8D3F(0);U+8CC4(1,3,8,9);U+8CC4(1,3,8,9) +U+8D40(0);U+8CB2(4,8,9);U+8CB2(4,8,9) +U+8D41(0);U+8CC3(1,3,8,9);U+8CC3(1,3,8,9) +U+8D42(0);U+8CC2(1,3,8,9);U+8CC2(1,3,8,9) +U+8D43(0);U+8D13(4,8,9);U+8D13(4,8,9),U+8D1C(1,3,8) +U+8D44(0);U+8CC7(1,3,8,9);U+8CC7(1,3,8,9) +U+8D45(0);U+8CC5(1,3,8,9);U+8CC5(1,3,8,9),U+8CCC(3,9) +U+8D46(0);U+8D10(1,3,8,9);U+8CEE(3,9),U+8D10(1,3,8,9) +U+8D47(0);U+8CD5(4,8,9);U+8CD5(4,8,9) +U+8D48(0);U+8CD1(1,3,8,9);U+8CD1(1,3,8,9) +U+8D49(0);U+8CDA(1,3,8,9);U+8CDA(1,3,8,9) +U+8D4A(0);U+8CD2(1,8,9);U+8CD2(1,8,9) +U+8D4B(0);U+8CE6(1,3,8,9);U+8CE6(1,3,8,9) +U+8D4C(0);U+8CED(1,3,8,9);U+8CED(1,3,8,9) +U+8D4D(0);U+8CEB(1,3,8);U+8CEB(1,3,8),U+9F4E(3,9) +U+8D4E(0);U+8D16(1,3,8,9);U+8D16(1,3,8,9) +U+8D4F(0);U+8CDE(1,3,8,9);U+8CDE(1,3,8,9) +U+8D50(0);U+8CDC(1,3,8,9);U+8CDC(1,3,8,9) +U+8D51(0);U+8D14(4,8,9);U+8D14(4,8,9) +U+8D52(0);U+8CD9(1,3,8,9);U+8CD9(1,3,8,9) +U+8D53(0);U+8CE1(1,3,8,9);U+8CE1(1,3,8,9) +U+8D54(0);U+8CE0(1,3,8,9);U+8CE0(1,3,8,9) +U+8D55(0);U+8CE7(1,3,8,9);U+8CE7(1,3,8,9) +U+8D56(0);U+8CF4(1,3,8,9);U+8CF4(1,3,8,9),U+983C(4) +U+8D57(0);U+8CF5(1,3,8,9);U+8CF5(1,3,8,9) +U+8D58(0);U+8D05(1,3,8,9);U+8D05(1,3,8,9) +U+8D59(0);U+8CFB(1,3,8,9);U+8CFB(1,3,8,9) +U+8D5A(0);U+8CFA(1,3,8,9);U+8CFA(1,3,8,9) +U+8D5B(0);U+8CFD(1,3,8,9);U+8CFD(1,3,8,9) +U+8D5C(0);U+8CFE(1,3,8,9);U+8CFE(1,3,8,9) +U+8D5D(0);U+8D17(4,9);U+8D0B(1,3,8),U+8D17(4,9) +U+8D5E(0);U+8D0A(1,3,8,9),U+8B9A(4,9);U+8B83(7),U+8B9A(4,9),U+8CDB(4),U+8D0A(1,3,8,9) + +U+8D5F(0);U+8D07(4,8,9);U+8D07(4,8,9) +U+8D60(0);U+8D08(1,3,8,9);U+8D08(1,3,8,9) +U+8D61(0);U+8D0D(1,3,8,9);U+8D0D(1,3,8,9) +U+8D62(0);U+8D0F(1,3,8,9);U+8D0F(1,3,8,9) +U+8D63(0);U+8D1B(1,3,8,9);U+7068(2,9),U+8D1B(1,3,8,9) +U+8D64(0);U+8D64(5,9); +U+8D65(0);U+8D65(0); +U+8D66(0);U+8D66(5,9); +U+8D67(0);U+8D67(5,9); +U+8D68(0);U+8D68(3,9); +U+8D69(0);U+8D69(0,9); +U+8D6A(0);U+8D6C(1,3,8,9);U+7AC0(7,9),U+8D6C(1,3,8,9) +U+8D6B(0);U+8D6B(5,9); +U+8D6C(0);U+8D6C(0,9);U+8D6A(1,3,8),U+7AC0(1,3,7,8,9) +U+8D6D(0);U+8D6D(5,9); +U+8D6E(0);U+8D6E(0,9);U+971E(3,9) +U+8D6F(0);U+8D6F(0,9); +U+8D70(0);U+8D70(5,9);U+8D71(3,8) + +U+8D71(0);U+8D70(3,8,9);U+8D70(3,8,9) +U+8D72(0);U+8D72(0,9); +U+8D73(0);U+8D73(5,9); +U+8D74(0);U+8D74(5,9); +U+8D75(0);U+8D99(1,3,8,9);U+8D99(1,3,8,9) +U+8D76(0);U+8D95(1,3,4,8,9);U+8D95(1,3,4,8,9) +U+8D77(0);U+8D77(5,9); +U+8D78(0);U+8D78(0,9); +U+8D79(0);U+8D79(0,9); +U+8D7A(0);U+8D7A(0); +U+8D7B(0);U+8D7B(0,9); +U+8D7D(0);U+8D7D(0,9); +U+8D7E(0);U+8D7E(0); +U+8D7F(0);U+8D7F(0); +U+8D80(0);U+8D80(0,9); +U+8D81(0);U+8D81(5,9);U+8D82(2,3,8) +U+8D82(0);U+8D81(2,3,8,9);U+8D81(2,3,8,9) +U+8D83(0);U+8D83(0); +U+8D84(0);U+8D84(5,9); +U+8D85(0);U+8D85(5,9); +U+8D86(0);U+8D86(3); +U+8D87(0);U+8D87(0); +U+8D88(0);U+8D88(0); +U+8D89(0);U+8D89(0,9); +U+8D8A(0);U+8D8A(5,9); +U+8D8B(0);U+8DA8(1,3,8,9);U+8D8D(3,9),U+8DA8(1,3,8,9) +U+8D8C(0);U+8D8C(0,9); +U+8D8D(0);U+8D8D(0,9);U+8D8B(3),U+8DA8(1,3,8,9) +U+8D8E(0);U+8D8E(0,9); +U+8D8F(0);U+8D8F(0,9); +U+8D90(0);U+8D90(0,9); +U+8D91(0);U+8D91(5,9); +U+8D92(0);U+8D92(0,9);U+8DF3(7,9) +U+8D93(0);U+8D93(0,9); +U+8D94(0);U+8D94(5,9); +U+8D95(0);U+8D95(0,9);U+8D76(1,3,8,9) +U+8D96(0);U+8D96(0,9); +U+8D97(0);U+8D97(0); +U+8D98(0);U+8D98(0); +U+8D99(0);U+8D99(0,9);U+8D75(1,3,8) +U+8D9A(0);U+8D9A(0); +U+8D9B(0);U+8D9B(3,9); +U+8D9C(0);U+8D9C(0,9); +U+8D9D(0);U+8D9D(0); +U+8D9E(0);U+8D9E(0); +U+8D9F(0);U+8D9F(5,9);U+8E5A(2,3,9) +U+8DA0(0);U+8DA0(3,9); +U+8DA1(0);U+8DA1(0,9); +U+8DA2(0);U+8DA2(0); +U+8DA3(0);U+8DA3(5,9); +U+8DA4(0);U+8DA4(0); +U+8DA5(0);U+8DA5(0,9); +U+8DA7(0);U+8DA7(0,9); +U+8DA8(0);U+8DA8(0,9);U+8D8B(1,3,8),U+8D8D(1,3,8,9) +U+8DA9(0);U+8DA9(0); +U+8DAA(0);U+8DAA(0,9); +U+8DAB(0);U+8DAB(3,9); +U+8DAC(0);U+8DAC(3,9); +U+8DAD(0);U+8DAD(0,9); +U+8DAE(0);U+8DAE(0,9);U+8E81(3,9) +U+8DAF(0);U+8DAF(0,9); +U+8DB0(0);U+8DB0(0); +U+8DB1(0);U+8DB2(1,3,8,9);U+8DB2(1,3,8,9) + +U+8DB2(0);U+8DB2(0,9);U+8DB1(1,3,8) +U+8DB3(0);U+8DB3(5,9); +U+8DB4(0);U+8DB4(5,9); +U+8DB5(0);U+8DB5(5,9); +U+8DB6(0);U+8DB6(0,9); +U+8DB7(0);U+8DB7(0,9); +U+8DB8(0);U+8E89(1,3,8,9);U+8E89(1,3,8,9) +U+8DB9(0);U+8DB9(0,9); +U+8DBA(0);U+8DBA(5,9); +U+8DBB(0);U+8DBB(0); +U+8DBC(0);U+8DBC(5,9); +U+8DBD(0);U+8DBD(0); +U+8DBE(0);U+8DBE(5,9); +U+8DBF(0);U+8DBF(5,9); +U+8DC1(0);U+8DC1(0,9); +U+8DC2(0);U+8DC2(3,9); +U+8DC3(0);U+8E8D(1,3,8,9);U+8E8D(1,3,8,9) +U+8DC4(0);U+8E4C(1,3,8,9);U+8E4C(1,3,8,9) +U+8DC5(0);U+8DC5(0,9); +U+8DC6(0);U+8DC6(5,9); +U+8DC7(0);U+8DC7(0,9); +U+8DC8(0);U+8DC8(0,9); +U+8DC9(0);U+8DC9(0); +U+8DCA(0);U+8DCA(0); +U+8DCB(0);U+8DCB(5,9); +U+8DCC(0);U+8DCC(5,9); +U+8DCD(0);U+8DCD(0,9); +U+8DCE(0);U+8DCE(5,9); +U+8DCF(0);U+8DCF(5,9); +U+8DD0(0);U+8DD0(0,9); +U+8DD1(0);U+8DD1(5,9); +U+8DD2(0);U+8DD2(0); +U+8DD3(0);U+8DD3(0,9); +U+8DD4(0);U+8DD4(3); +U+8DD5(0);U+8DD5(0,9); +U+8DD6(0);U+8DD6(5,9);U+8E60(2,3,4,9) +U+8DD7(0);U+8DD7(5,9); +U+8DD8(0);U+8DD8(0,9); +U+8DD9(0);U+8DD9(3,9); +U+8DDA(0);U+8DDA(5,9); +U+8DDB(0);U+8DDB(5,9); +U+8DDC(0);U+8DDC(0,9); +U+8DDD(0);U+8DDD(5,9); +U+8DDE(0);U+8E92(4,8,9);U+8E92(4,8,9) +U+8DDF(0);U+8DDF(5,9); +U+8DE0(0);U+8DE0(0,9); +U+8DE1(0);U+8DE1(0,9);U+8E5F(4,8,9),U+8FF9(2,3,8) +U+8DE2(0);U+8DE2(0,9); +U+8DE3(0);U+8DE3(5,9); +U+8DE4(0);U+8DE4(5,9); +U+8DE6(0);U+8DE6(3,9); +U+8DE7(0);U+8DE7(0,9); +U+8DE8(0);U+8DE8(5,9); +U+8DE9(0);U+8DE9(0,9); +U+8DEA(0);U+8DEA(5,9); +U+8DEB(0);U+8DEB(5,9); +U+8DEC(0);U+8DEC(5,9);U+8E5E(3,9) +U+8DED(0);U+8DED(0); +U+8DEE(0);U+8DEE(0,9); +U+8DEF(0);U+8DEF(5,9); +U+8DF0(0);U+8DF0(0,9); +U+8DF1(0);U+8DF1(0,9); +U+8DF2(0);U+8DF2(0,9); + +U+8DF3(0);U+8DF3(5,9);U+8D92(7,9) +U+8DF4(0);U+8DF4(0,9);U+8E29(2,3,9) +U+8DF5(0);U+8E10(1,3,8,9);U+8E10(1,3,8,9) +U+8DF6(0);U+8E82(4,8,9);U+8E82(4,8,9) +U+8DF7(0);U+8E7A(1,3,8,9);U+8E7A(1,3,8,9),U+8E7B(3,9) +U+8DF8(0);U+8E55(1,3,8,9);U+9A46(3,9),U+8E55(1,3,8,9) +U+8DF9(0);U+8E9A(1,3,8,9);U+8E9A(1,3,8,9) +U+8DFA(0);U+8DFA(5,9); +U+8DFB(0);U+8E8B(1,3,8,9);U+8E8B(1,3,8,9) +U+8DFC(0);U+8DFC(0,9);U+5C40(2,9),U+4FB7(0,2,9) +U+8DFD(0);U+8DFD(5,9); +U+8DFE(0);U+8DFE(0,9); +U+8DFF(0);U+8DFF(0,9); +U+8E00(0);U+8E00(0,9);U+9F8A(3),U+9F6A(1,3,8,9) +U+8E02(0);U+8E02(3,9);U+8E19(3,9) +U+8E03(0);U+8E03(0,9); +U+8E04(0);U+8E04(0,9); +U+8E05(0);U+8E05(5,9); +U+8E06(0);U+8E06(0,9); +U+8E07(0);U+8E07(0,9); +U+8E08(0);U+758F(4,8,9);U+758F(4,8,9) +U+8E09(0);U+8E09(5,9); +U+8E0A(0);U+8E0A(1,3,9),U+8E34(1,3,4,8,9);U+8E34(1,3,4,8,9) +U+8E0C(0);U+8E8A(1,3,8,9);U+8E8A(1,3,8,9) +U+8E0D(0);U+8E0D(0,9);U+9AB9(3,9) +U+8E0E(0);U+8E0E(0); +U+8E0F(0);U+8E0F(5,9); +U+8E10(0);U+8E10(0,9);U+8DF5(1,3,8) +U+8E11(0);U+8E11(0,9); +U+8E12(0);U+8E12(0,9); +U+8E13(0);U+8E13(0,9); +U+8E14(0);U+8E14(5,9); +U+8E15(0);U+8E15(0,9); +U+8E16(0);U+8E16(3,9); +U+8E17(0);U+8E17(0,9); +U+8E18(0);U+8E18(0,9); +U+8E19(0);U+8E19(0,9);U+8E02(3,9) +U+8E1A(0);U+8E1A(0,9); +U+8E1B(0);U+8E1B(0,9); +U+8E1C(0);U+8E1C(0,9); +U+8E1D(0);U+8E1D(5,9); +U+8E1E(0);U+8E1E(5,9); +U+8E1F(0);U+8E1F(5,9); +U+8E20(0);U+8E20(0,9); +U+8E21(0);U+8E21(0,9);U+8737(4,9) +U+8E22(0);U+8E22(5,9); +U+8E23(0);U+8E23(5,9);U+6B95(3,9) +U+8E24(0);U+8E24(0,9); +U+8E25(0);U+8E25(0,9); +U+8E26(0);U+8E26(0,9); +U+8E27(0);U+8E27(0,9); +U+8E28(0);U+8E64(3,8,9);U+8E2A(3),U+8E64(3,8,9) +U+8E29(0);U+8E29(5,9);U+8DF4(2,3,9) +U+8E2A(0);U+8E64(2,3,9);U+8E28(3),U+8E64(2,3,9) +U+8E2B(0);U+8E2B(0,9);U+78B0(2,3,9),U+63BD(0,2,3,9) +U+8E2C(0);U+8E93(1,3,8,9);U+8E93(1,3,8,9) +U+8E2D(0);U+8E2D(0); +U+8E2E(0);U+8E2E(5,9); +U+8E2F(0);U+8E91(1,3,8,9);U+8E91(1,3,8,9) +U+8E30(0);U+8E30(0,9);U+903E(2,9) +U+8E31(0);U+8E31(5,9); +U+8E33(0);U+8E33(3,9); +U+8E34(0);U+8E34(0,9);U+8E0A(1,3,8,9) + +U+8E35(0);U+8E35(5,9); +U+8E36(0);U+8E36(0,9); +U+8E37(0);U+8E37(0); +U+8E38(0);U+8E38(3,9); +U+8E39(0);U+8E39(5,9); +U+8E3A(0);U+8E3A(5); +U+8E3B(0);U+8E3B(0); +U+8E3C(0);U+8E3C(3,9); +U+8E3D(0);U+8E3D(5,9); +U+8E3E(0);U+8E3E(0,9); +U+8E3F(0);U+8E3F(0,9); +U+8E40(0);U+8E40(5,9); +U+8E41(0);U+8E41(5,9); +U+8E42(0);U+8E42(5,9);U+79B8(3,9) +U+8E43(0);U+8E43(0); +U+8E44(0);U+8E44(5,9); +U+8E45(0);U+8E45(0,9); +U+8E47(0);U+8E47(5,9); +U+8E48(0);U+8E48(5,9); +U+8E49(0);U+8E49(5,9); +U+8E4A(0);U+8E4A(5,9); +U+8E4B(0);U+8E4B(5,9); +U+8E4C(0);U+8E4C(0,9);U+8DC4(1,3,8) +U+8E4D(0);U+8E4D(0,9); +U+8E4E(0);U+8E4E(0,9); +U+8E50(0);U+8E50(0,9); +U+8E51(0);U+8EA1(1,3,8,9);U+8EA1(1,3,8,9) +U+8E52(0);U+8E63(1,3,8,9);U+8E63(1,3,8,9) +U+8E53(0);U+8E53(0,9); +U+8E54(0);U+8E54(0,9);U+6682(4),U+66AB(1,3,4,8,9) +U+8E55(0);U+8E55(0,9);U+8DF8(1,3,8),U+9A46(1,3,8,9) +U+8E56(0);U+8E56(0,9);U+6869(4),U+6A01(1,3,4,8,9) +U+8E57(0);U+8E57(0,9); +U+8E58(0);U+8E58(0); +U+8E59(0);U+8E59(5,9);U+9863(3,9) +U+8E5A(0);U+8E5A(0,9);U+8D9F(2,3,9) +U+8E5B(0);U+8E5B(0,9); +U+8E5C(0);U+8E5C(0,9); +U+8E5D(0);U+8E5D(0,9); +U+8E5E(0);U+8E5E(0,9);U+8DEC(3,9) +U+8E5F(0);U+8E5F(0,9);U+8DE1(4,8,9),U+8FF9(2,3) +U+8E60(0);U+8E60(0,9);U+8DD6(2,3,4,9) +U+8E61(0);U+8E61(3,9); +U+8E62(0);U+8E62(3,9); +U+8E63(0);U+8E63(0,9);U+8E52(1,3,8) +U+8E64(0);U+8E64(0,9);U+8E28(3,8),U+8E2A(2,3) +U+8E65(0);U+8E65(0,9); +U+8E66(0);U+8E66(5,9); +U+8E67(0);U+8E67(0,9);U+7CDF(2,9) +U+8E68(0);U+8E68(3); +U+8E69(0);U+8E69(5,9); +U+8E6A(0);U+8E6A(0,9); +U+8E6B(0);U+8E6B(0); +U+8E6C(0);U+8E6C(5,9); +U+8E6D(0);U+8E6D(5,9); +U+8E6F(0);U+8E6F(5,9);U+756A(3,8,9),U+7C75(3,9) +U+8E70(0);U+8E95(2,3,4,9);U+8E95(2,3,4,9) +U+8E71(0);U+8E71(4); +U+8E72(0);U+8E72(5,9);U+58FF(4,9) +U+8E73(0);U+8E73(0,9); +U+8E74(0);U+8E74(5,9); +U+8E76(0);U+8E76(5,9); +U+8E78(0);U+8E78(3,9); + +U+8E7A(0);U+8E7A(0,9);U+8DF7(1,3,8),U+8E7B(2,3,8,9) +U+8E7B(0);U+8E7B(0,9);U+8DF7(3),U+8E7A(2,3,8,9) +U+8E7C(0);U+8E7C(5,9); +U+8E7D(0);U+8E7D(0); +U+8E7E(0);U+8E7E(0); +U+8E7F(0);U+8EA5(1,3,8,9);U+8EA5(1,3,8,9) +U+8E80(0);U+8E80(0); +U+8E81(0);U+8E81(5,9);U+8DAE(3,9) +U+8E82(0);U+8E82(0,9);U+8DF6(4,8) +U+8E83(0);U+8E83(4); +U+8E84(0);U+8E84(3,9); +U+8E85(0);U+8E85(5,9); +U+8E86(0);U+8E86(0,9); +U+8E87(0);U+8E87(5,9); +U+8E88(0);U+8E88(0,9); +U+8E89(0);U+8E89(0,9);U+8DB8(1,3,8) +U+8E8A(0);U+8E8A(0,9);U+8E0C(1,3,8) +U+8E8B(0);U+8E8B(0,9);U+8DFB(1,3,8) +U+8E8C(0);U+8E8C(0,9); +U+8E8D(0);U+8E8D(0,9);U+8DC3(1,3,8) +U+8E8E(0);U+8E8E(0,9); +U+8E8F(0);U+8EAA(1,3,8,9);U+8EAA(1,3,8,9) +U+8E90(0);U+8E90(5,9); +U+8E91(0);U+8E91(0,9);U+8E2F(1,3,8) +U+8E92(0);U+8E92(0,9);U+8DDE(4,8) +U+8E93(0);U+8E93(0,9);U+8E2C(1,3,8) +U+8E94(0);U+8E94(5,9); +U+8E95(0);U+8E95(0,9);U+8E70(2,3,4) +U+8E96(0);U+8E96(0,9); +U+8E97(0);U+8E97(0,9); +U+8E98(0);U+8E98(0,9); +U+8E9A(0);U+8E9A(0,9);U+8DF9(1,3,8) +U+8E9C(0);U+8EA6(1,3,8,9);U+8EA6(1,3,8,9) +U+8E9D(0);U+8E9D(0,9); +U+8E9E(0);U+8E9E(5,9); +U+8E9F(0);U+8E9F(3,9); +U+8EA0(0);U+8EA0(0,9); +U+8EA1(0);U+8EA1(0,9);U+8E51(1,3,8) +U+8EA3(0);U+8EA3(3,9); +U+8EA4(0);U+8EA4(0,9); +U+8EA5(0);U+8EA5(0,9);U+8E7F(1,3,8) +U+8EA6(0);U+8EA6(0,9);U+8E9C(1,3,8) +U+8EA7(0);U+8EA7(3); +U+8EA8(0);U+8EA8(0,9); +U+8EA9(0);U+8EA9(0,9); +U+8EAA(0);U+8EAA(0,9);U+8E8F(1,3,8) +U+8EAB(0);U+8EAB(5,9); +U+8EAC(0);U+8EAC(5,9); +U+8EAD(0);U+803D(2,3,8,9);U+803D(2,3,8,9) +U+8EAE(0);U+8EAE(0); +U+8EAF(0);U+8EC0(1,3,8,9);U+8EC0(1,3,8,9) +U+8EB0(0);U+9AD4(3,8,9);U+4F53(3,9),U+9AD4(3,8,9),U+8EC6(3),U+9AB5(3) +U+8EB1(0);U+8EB2(3,4,8,9);U+8EB2(3,4,8,9) +U+8EB2(0);U+8EB2(5,9);U+8EB1(3,4,8) +U+8EB4(0);U+8EB4(0); +U+8EB5(0);U+8EB5(0); +U+8EB8(0);U+8EB8(0); +U+8EB9(0);U+8EB9(0); +U+8EBA(0);U+8EBA(5,9); +U+8EBB(0);U+8EBB(0); +U+8EBC(0);U+8EBC(0); +U+8EBD(0);U+8EBD(0,9); +U+8EBE(0);U+8EBE(0); + +U+8EBF(0);U+8EBF(0); +U+8EC0(0);U+8EC0(0,9);U+8EAF(1,3,8) +U+8EC2(0);U+8EC2(0,9); +U+8EC3(0);U+8EC3(0); +U+8EC5(0);U+8EC5(0); +U+8EC6(0);U+9AD4(3,8,9);U+4F53(3,9),U+9AD4(3,8,9),U+8EB0(3),U+9AB5(3) +U+8EC7(0);U+8EC7(0); +U+8EC8(0);U+8EC8(0); +U+8EC9(0);U+8EC9(0,9); +U+8ECA(0);U+8ECA(0,9);U+8F66(1,3,8) +U+8ECB(0);U+8ECB(0,9);U+8F67(1,3,8) +U+8ECC(0);U+8ECC(0,9);U+8F68(1,3,8) +U+8ECD(0);U+8ECD(0,9);U+519B(1,3,8) +U+8ECE(0);U+8ECE(5); +U+8ECF(0);U+8ECF(0,9); +U+8ED0(0);U+8ED0(0); +U+8ED1(0);U+8ED1(0,9);U+8F6A(4,8) +U+8ED2(0);U+8ED2(0,9);U+8F69(1,3,8) +U+8ED3(0);U+8ED3(0,9); +U+8ED4(0);U+8ED4(0,9);U+8F6B(1,3,8) +U+8ED5(0);U+8ED5(0); +U+8ED6(0);U+8ED6(4);U+8EE0(4,9) +U+8ED7(0);U+8ED7(0,9); +U+8ED8(0);U+8ED8(0,9); +U+8EDA(0);U+8EDA(0); +U+8EDB(0);U+8EDB(0,9);U+8F6D(1,8),U+6799(0,1,3,8,9),U+8EF6(1,3,8,9) +U+8EDC(0);U+8EDC(0,9); +U+8EDD(0);U+8EDD(0,9); +U+8EDE(0);U+8EDE(0,9); +U+8EDF(0);U+8EDF(0,9);U+8F6F(1,3,8) +U+8EE0(0);U+8EE0(0,9);U+8ED6(4) +U+8EE1(0);U+8EE1(0,9);U+9ED4(3,9) +U+8EE4(0);U+8EE4(0);U+8F77(1,3,8) +U+8EE5(0);U+8EE5(0,9); +U+8EE6(0);U+8EE6(0,9); +U+8EE7(0);U+8EE7(0,9); +U+8EE8(0);U+8EE8(3,9); +U+8EE9(0);U+8EE9(0,9); +U+8EEA(0);U+8EEA(0); +U+8EEB(0);U+8EEB(0,9);U+8F78(1,3,8) +U+8EEC(0);U+8EEC(3,9); +U+8EED(0);U+8EED(3); +U+8EEE(0);U+8EEE(0,9); +U+8EEF(0);U+8EEF(3,9); +U+8EF1(0);U+8EF1(0,9); +U+8EF2(0);U+8F42(9);U+8F42(9),U+8F71(1,3,8),U+6BC2(1,3,8) +U+8EF3(0);U+8EF3(0); +U+8EF4(0);U+8EF4(0,9); +U+8EF5(0);U+8EF5(0,9); +U+8EF6(0);U+8EF6(0,9);U+8F6D(3),U+6799(0,3,9),U+8EDB(1,3,8,9) +U+8EF7(0);U+8EF7(0,9); +U+8EF8(0);U+8EF8(0,9);U+8F74(1,3,8) +U+8EF9(0);U+8EF9(0,9);U+8F75(4,8) +U+8EFA(0);U+8EFA(0,9);U+8F7A(1,3,8) +U+8EFB(0);U+8EFB(0,9);U+8F72(1,3,8) +U+8EFC(0);U+8EFC(0,9);U+8F76(1,3,8) +U+8EFD(0);U+8F15(3,8,9);U+8F15(3,8,9),U+8F7B(3) +U+8EFE(0);U+8EFE(0,9);U+8F7C(1,3,8) +U+8EFF(0);U+8EFF(3,9);U+8F27(3,8) +U+8F00(0);U+8F00(3,9); +U+8F01(0);U+8F01(3,9); +U+8F02(0);U+8F02(0,9); +U+8F03(0);U+8F03(0,9);U+8F83(1,3,8) + +U+8F04(0);U+8F04(0); +U+8F05(0);U+8F05(0,9);U+8F82(1,3,8) +U+8F06(0);U+8F06(0,9); +U+8F07(0);U+8F07(0,9);U+8F81(4,8) +U+8F08(0);U+8F08(0,9);U+8F80(4,8) +U+8F09(0);U+8F09(0,9);U+8F7D(1,3,8) +U+8F0A(0);U+8F0A(0,9);U+8F7E(1,3,8) +U+8F0B(0);U+8F0B(0,9); +U+8F0D(0);U+8F0D(0,9); +U+8F0E(0);U+8F0E(0,9); +U+8F10(0);U+8F10(0,9); +U+8F11(0);U+8F11(0,9); +U+8F12(0);U+8F12(0,9);U+8F84(1,3,8) +U+8F13(0);U+8F13(0,9);U+633D(2,3,9) +U+8F14(0);U+8F14(0,9);U+8F85(1,3,8) +U+8F15(0);U+8F15(0,9);U+8EFD(3,8),U+8F7B(1,3,8) +U+8F16(0);U+8F16(0,9); +U+8F17(0);U+8F17(3,9); +U+8F18(0);U+8F18(0,9); +U+8F1A(0);U+8F1A(3,9); +U+8F1B(0);U+8F1B(0,9);U+8F86(1,3,8) +U+8F1C(0);U+8F1C(0,9);U+8F8E(1,3,8) +U+8F1D(0);U+8F1D(0,9);U+8F89(1,3,8) +U+8F1E(0);U+8F1E(0,9);U+8F8B(1,3,8) +U+8F1F(0);U+8F1F(0,9);U+8F8D(1,3,8) +U+8F20(0);U+8F20(3,9); +U+8F21(0);U+8F21(3); +U+8F22(0);U+8F22(0); +U+8F23(0);U+8F23(0,9); +U+8F24(0);U+8F24(0,9); +U+8F25(0);U+8F25(0,9);U+8F8A(1,3,8) +U+8F26(0);U+8F26(0,9);U+8F87(1,3,8) +U+8F27(0);U+8EFF(3,8,9);U+8EFF(3,8,9) +U+8F28(0);U+8F28(3); +U+8F29(0);U+8F29(0,9);U+8F88(1,3,8) +U+8F2A(0);U+8F2A(0,9);U+8F6E(1,3,8) +U+8F2B(0);U+8F2B(0); +U+8F2C(0);U+8F2C(0,9);U+8F8C(4,8) +U+8F2E(0);U+8F2E(0,9); +U+8F2F(0);U+8F2F(0,9);U+8F91(1,3,8) +U+8F30(0);U+8F30(0); +U+8F31(0);U+8F31(0); +U+8F32(0);U+8F32(3,9); +U+8F33(0);U+8F33(0,9);U+8F8F(1,3,8) +U+8F34(0);U+8F34(3,9); +U+8F35(0);U+8F35(4,9); +U+8F36(0);U+8F36(3,9); +U+8F37(0);U+8F37(0,9); +U+8F38(0);U+8F38(0,9);U+8F93(1,3,8) +U+8F39(0);U+8F39(0,9); +U+8F3B(0);U+8F3B(0,9);U+8F90(1,3,8) +U+8F3C(0);U+8F40(4,8,9);U+8F40(4,8,9),U+8F92(4) +U+8F3D(0);U+8F3D(0); +U+8F3E(0);U+8F3E(0,9);U+8F97(1,3,8) +U+8F3F(0);U+8F3F(0,9);U+8206(1,3,8),U+8F5D(1,3,8,9) +U+8F40(0);U+8F40(0,9);U+8F3C(4,8),U+8F92(4,8) +U+8F42(0);U+8F42(0,9);U+6BC2(1,3,8),U+8EF2(3),U+8F71(4) +U+8F43(0);U+8F43(0,9); +U+8F44(0);U+8F44(0,9);U+8F96(1,3,8) +U+8F45(0);U+8F45(0,9);U+8F95(1,3,8) +U+8F46(0);U+8F46(0,9);U+8F98(1,3,8) +U+8F47(0);U+8F47(0,9); +U+8F48(0);U+8F48(0,9); + +U+8F49(0);U+8F49(0,9);U+8F6C(1,3,8) +U+8F4A(0);U+8F4A(0); +U+8F4B(0);U+8F4B(0,9); +U+8F4C(0);U+8F4C(0); +U+8F4D(0);U+8F4D(0,9);U+8F99(1,3,8) +U+8F4E(0);U+8F4E(0,9);U+8F7F(1,3,8) +U+8F4F(0);U+8F4F(0,9);U+6808(3),U+68E7(1,3,8,9) +U+8F50(0);U+8F50(3,9); +U+8F51(0);U+8F51(0,9); +U+8F52(0);U+8F52(0,9); +U+8F53(0);U+8F53(0,9); +U+8F54(0);U+8F54(0,9);U+8F9A(1,3,8) +U+8F55(0);U+8F55(0,9); +U+8F56(0);U+8F56(0,9); +U+8F57(0);U+8F57(4,9); +U+8F58(0);U+8F58(0,9); +U+8F59(0);U+8F59(3,9); +U+8F5A(0);U+8F5A(0,9); +U+8F5B(0);U+8F5B(0,9); +U+8F5D(0);U+8F5D(0,9);U+8206(3),U+8F3F(1,3,8,9) +U+8F5E(0);U+8F5E(0,9);U+69DB(3),U+6ABB(1,3,8,9) +U+8F5F(0);U+8F5F(0,9);U+8F70(1,3,8) +U+8F60(0);U+8F60(0,9); +U+8F61(0);U+8F61(0,9);U+8F94(1,3,8) +U+8F62(0);U+8F62(0,9);U+8F79(1,3,8) +U+8F63(0);U+8F63(0,9); +U+8F64(0);U+8F64(0,9);U+8F73(1,3,8) +U+8F65(0);U+8F65(0); +U+8F66(0);U+8ECA(1,3,8,9);U+8ECA(1,3,8,9) +U+8F67(0);U+8ECB(1,3,8,9);U+8ECB(1,3,8,9) +U+8F68(0);U+8ECC(1,3,8,9);U+8ECC(1,3,8,9) +U+8F69(0);U+8ED2(1,3,8,9);U+8ED2(1,3,8,9) +U+8F6A(0);U+8ED1(4,8,9);U+8ED1(4,8,9) +U+8F6B(0);U+8ED4(1,3,8,9);U+8ED4(1,3,8,9) +U+8F6C(0);U+8F49(1,3,8,9);U+8F49(1,3,8,9) +U+8F6D(0);U+8EDB(1,8,9);U+6799(3,9),U+8EDB(1,8,9),U+8EF6(3,9) +U+8F6E(0);U+8F2A(1,3,8,9);U+8F2A(1,3,8,9) +U+8F6F(0);U+8EDF(1,3,8,9);U+8EDF(1,3,8,9) +U+8F70(0);U+8F5F(1,3,8,9);U+8F5F(1,3,8,9) +U+8F71(0);U+8F42(4,9);U+8EF2(1,3,8),U+8F42(4,9),U+6BC2(1,3,4,8) +U+8F72(0);U+8EFB(1,3,8,9);U+8EFB(1,3,8,9) +U+8F73(0);U+8F64(1,3,8,9);U+8F64(1,3,8,9) +U+8F74(0);U+8EF8(1,3,8,9);U+8EF8(1,3,8,9) +U+8F75(0);U+8EF9(4,8,9);U+8EF9(4,8,9) +U+8F76(0);U+8EFC(1,3,8,9);U+8EFC(1,3,8,9) +U+8F77(0);U+8EE4(1,3,8);U+8EE4(1,3,8) +U+8F78(0);U+8EEB(1,3,8,9);U+8EEB(1,3,8,9) +U+8F79(0);U+8F62(1,3,8,9);U+8F62(1,3,8,9) +U+8F7A(0);U+8EFA(1,3,8,9);U+8EFA(1,3,8,9) +U+8F7B(0);U+8F15(1,3,8,9);U+8EFD(3),U+8F15(1,3,8,9) +U+8F7C(0);U+8EFE(1,3,8,9);U+8EFE(1,3,8,9) +U+8F7D(0);U+8F09(1,3,8,9);U+8F09(1,3,8,9) +U+8F7E(0);U+8F0A(1,3,8,9);U+8F0A(1,3,8,9) +U+8F7F(0);U+8F4E(1,3,8,9);U+8F4E(1,3,8,9) +U+8F80(0);U+8F08(4,8,9);U+8F08(4,8,9) +U+8F81(0);U+8F07(4,8,9);U+8F07(4,8,9) +U+8F82(0);U+8F05(1,3,8,9);U+8F05(1,3,8,9) +U+8F83(0);U+8F03(1,3,8,9);U+8F03(1,3,8,9) +U+8F84(0);U+8F12(1,3,8,9);U+8F12(1,3,8,9) +U+8F85(0);U+8F14(1,3,8,9);U+8F14(1,3,8,9) +U+8F86(0);U+8F1B(1,3,8,9);U+8F1B(1,3,8,9) +U+8F87(0);U+8F26(1,3,8,9);U+8F26(1,3,8,9) + +U+8F88(0);U+8F29(1,3,8,9);U+8F29(1,3,8,9) +U+8F89(0);U+8F1D(1,3,8,9);U+8F1D(1,3,8,9) +U+8F8A(0);U+8F25(1,3,8,9);U+8F25(1,3,8,9) +U+8F8B(0);U+8F1E(1,3,8,9);U+8F1E(1,3,8,9) +U+8F8C(0);U+8F2C(4,8,9);U+8F2C(4,8,9) +U+8F8D(0);U+8F1F(1,3,8,9);U+8F1F(1,3,8,9) +U+8F8E(0);U+8F1C(1,3,8,9);U+8F1C(1,3,8,9) +U+8F8F(0);U+8F33(1,3,8,9);U+8F33(1,3,8,9) +U+8F90(0);U+8F3B(1,3,8,9);U+8F3B(1,3,8,9) +U+8F91(0);U+8F2F(1,3,8,9);U+8F2F(1,3,8,9) +U+8F92(0);U+8F40(4,8,9);U+8F3C(4),U+8F40(4,8,9) +U+8F93(0);U+8F38(1,3,8,9);U+8F38(1,3,8,9) +U+8F94(0);U+8F61(1,3,8,9);U+8F61(1,3,8,9) +U+8F95(0);U+8F45(1,3,8,9);U+8F45(1,3,8,9) +U+8F96(0);U+8F44(1,3,8,9);U+8F44(1,3,8,9) +U+8F97(0);U+8F3E(1,3,8,9);U+8F3E(1,3,8,9) +U+8F98(0);U+8F46(1,3,8,9);U+8F46(1,3,8,9) +U+8F99(0);U+8F4D(1,3,8,9);U+8F4D(1,3,8,9) +U+8F9A(0);U+8F54(1,3,8,9);U+8F54(1,3,8,9) +U+8F9B(0);U+8F9B(5,9); +U+8F9C(0);U+8F9C(5,9); +U+8F9E(0);U+8FAD(1,3,8,9);U+8FAD(1,3,8,9) +U+8F9F(0);U+8F9F(1,3,9),U+95E2(1,3,4,9);U+907F(3,8,9),U+95E2(1,3,4,9) +U+8FA0(0);U+7F6A(2,8,9);U+7F6A(2,8,9) +U+8FA1(0);U+8FA1(0); +U+8FA2(0);U+8FA3(2,8,9);U+8FA3(2,8,9) +U+8FA3(0);U+8FA3(5,9);U+8FA2(2,8) +U+8FA5(0);U+8FA5(0); +U+8FA6(0);U+8FA6(0,9);U+529E(1,3,8),U+8FA8(3,9),U+8FA7(3,8),U+91C6(3,4,9) +U+8FA7(0);U+8FA8(3,8,9);U+8FA8(3,8,9),U+529E(1,3,8),U+8FA6(0,3,8,9),U+91C6(3,4,8,9) +U+8FA8(0);U+8FA8(5,9);U+8FA6(3,9),U+8FA7(3,8),U+91C6(4,9),U+529E(1,3,8) +U+8FA9(0);U+8FAF(1,3,8,9);U+8FAF(1,3,8,9) +U+8FAA(0);U+8FAA(0); +U+8FAB(0);U+8FAE(1,3,8,9);U+8FAE(1,3,8,9) +U+8FAC(0);U+8FAC(3); +U+8FAD(0);U+8FAD(0,9);U+8F9E(1,3,8) +U+8FAE(0);U+8FAE(0,9);U+8FAB(1,3,8) +U+8FAF(0);U+8FAF(0,9);U+8FA9(1,3,8) +U+8FB0(0);U+8FB0(5,9); +U+8FB1(0);U+8FB1(5,9); +U+8FB2(0);U+8FB2(0,9);U+519C(1,3,8) +U+8FB4(0);U+8FB4(0,9); +U+8FB5(0);U+8FB5(4); +U+8FB6(0);U+8FB6(5); +U+8FB7(0);U+8FB7(0); +U+8FB8(0);U+8FB8(0); +U+8FB9(0);U+908A(1,3,8,9);U+9089(3),U+908A(1,3,8,9) +U+8FBB(0);U+8FBB(0); +U+8FBC(0);U+8FBC(0); +U+8FBD(0);U+907C(1,3,8,9);U+907C(1,3,8,9) +U+8FBE(0);U+9054(1,3,8,9);U+8FD6(4,9),U+9054(1,3,8,9) +U+8FBF(0);U+8FBF(0,9); +U+8FC0(0);U+8FC0(0); +U+8FC1(0);U+9077(1,3,8,9);U+9077(1,3,8,9) +U+8FC2(0);U+8FC2(5,9); +U+8FC4(0);U+8FC4(5,9); +U+8FC5(0);U+8FC5(5,9); +U+8FC6(0);U+8FC6(0,9);U+8FE4(3,4,9) +U+8FC7(0);U+904E(1,3,8,9);U+904E(1,3,8,9) +U+8FC8(0);U+9081(1,3,8,9);U+9081(1,3,8,9) +U+8FC9(0);U+8FC9(0,9); +U+8FCB(0);U+8FCB(0,9); +U+8FCC(0);U+8FCC(0); + +U+8FCD(0);U+8FCD(0,9); +U+8FCE(0);U+8FCE(5,9); +U+8FCF(0);U+8FCF(0); +U+8FD0(0);U+904B(1,3,8,9);U+904B(1,3,8,9) +U+8FD1(0);U+8FD1(5,9); +U+8FD2(0);U+8FD2(0,9); +U+8FD3(0);U+8FD3(5,9); +U+8FD4(0);U+8FD4(5,9); +U+8FD5(0);U+8FD5(5,9); +U+8FD6(0);U+8FD6(0,9);U+8FBE(4),U+9054(1,3,4,8,9) +U+8FD7(0);U+8FD7(0,9); +U+8FD8(0);U+9084(1,3,8,9);U+9084(1,3,8,9) +U+8FD9(0);U+9019(1,3,8,9);U+9019(1,3,8,9) +U+8FDA(0);U+8FDA(0); +U+8FDB(0);U+9032(1,3,8,9);U+9032(1,3,8,9) +U+8FDC(0);U+9060(1,3,8,9);U+903A(4),U+9060(1,3,8,9) +U+8FDD(0);U+9055(1,3,8,9);U+9055(1,3,8,9) +U+8FDE(0);U+9023(1,3,8,9);U+9023(1,3,8,9) +U+8FDF(0);U+9072(1,3,8,9);U+8FE1(3,9),U+9045(3),U+905F(3),U+9072(1,3,8,9) +U+8FE0(0);U+8FE0(0,9); +U+8FE1(0);U+8FE1(0,9);U+8FDF(3),U+9045(3),U+905F(3),U+9072(1,3,8,9) +U+8FE2(0);U+8FE2(5,9); +U+8FE3(0);U+8FE3(0,9); +U+8FE4(0);U+8FE4(5,9);U+8FC6(3,4,9) +U+8FE5(0);U+8FE5(5,9);U+9008(2,3,8) +U+8FE6(0);U+8FE6(5,9); +U+8FE8(0);U+8FE8(5,9);U+902E(3,8,9) +U+8FE9(0);U+9087(1,3,8,9);U+9087(1,3,8,9) +U+8FEA(0);U+8FEA(5,9);U+5EF8(3,8) +U+8FEB(0);U+8FEB(5,9); +U+8FEC(0);U+5F80(3,8,9);U+5F80(3,8,9),U+5F83(2,3,8) +U+8FED(0);U+8FED(5,9);U+66E1(4),U+758A(3,4,8,9),U+53E0(2,4,5),U+7589(2,4) +U+8FEE(0);U+8FEE(5,9); +U+8FEF(0);U+9003(3,8,9);U+9003(3,8,9) +U+8FF0(0);U+8FF0(5,9); +U+8FF1(0);U+8FF1(0); +U+8FF2(0);U+8FF2(0); +U+8FF3(0);U+9015(4,8,9);U+9015(4,8,9),U+5F84(1,3,4,8),U+5F91(1,3,4,8,9) +U+8FF4(0);U+8FF4(0,9);U+56DE(1,3,8,9),U+5EFB(2),U+5EFD(8),U+9025(2,3),U+56D8(0,1,3,4,8),U+56EC(1,3,4,8) + +U+8FF5(0);U+8FF5(0,9); +U+8FF6(0);U+8FF6(0,9); +U+8FF7(0);U+8FF7(5,9); +U+8FF8(0);U+8FF8(5,9); +U+8FF9(0);U+8DE1(2,3,8,9),U+8E5F(2,3,9);U+8DE1(2,3,8,9),U+8E5F(2,3,9) +U+8FFA(0);U+8FFA(0,9);U+4E43(2,8,9),U+5EFC(4) +U+8FFB(0);U+8FFB(0,9);U+79FB(2,3,9) +U+8FFC(0);U+8FFC(0,9); +U+8FFD(0);U+8FFD(5,9); +U+8FFE(0);U+8FFE(3,9); +U+8FFF(0);U+8FFF(0,9); +U+9000(0);U+9000(5,9); +U+9001(0);U+9001(5,9); +U+9002(0);U+9069(1,3,8,9);U+9069(1,3,8,9) +U+9003(0);U+9003(5,9);U+8FEF(3,8) +U+9004(0);U+9004(5,9); +U+9005(0);U+9005(5,9); +U+9006(0);U+9006(5,9); +U+9007(0);U+9007(0); +U+9008(0);U+8FE5(2,3,8,9);U+8FE5(2,3,8,9) +U+9009(0);U+9078(1,3,8,9);U+9078(1,3,8,9) +U+900A(0);U+905C(1,3,8,9);U+613B(3,9),U+905C(1,3,8,9) +U+900B(0);U+900B(5,9); + +U+900C(0);U+900C(0,9);U+6538(3,9) +U+900D(0);U+900D(5,9); +U+900F(0);U+900F(5,9); +U+9010(0);U+9010(5,9); +U+9011(0);U+9011(5,9); +U+9012(0);U+905E(1,3,8,9);U+9013(4),U+905E(1,3,8,9) +U+9013(0);U+905E(4,8,9);U+9012(4),U+905E(4,8,9) +U+9014(0);U+9014(5,9); +U+9015(0);U+9015(0,9);U+5F84(4),U+5F91(2,3,8,9),U+8FF3(4,8) +U+9016(0);U+9016(5,9); +U+9017(0);U+9017(5,9); +U+9018(0);U+9018(0); +U+9019(0);U+9019(0,9);U+8FD9(1,3,8) +U+901A(0);U+901A(5,9); +U+901B(0);U+901B(5,9); +U+901C(0);U+901C(3,9); +U+901D(0);U+901D(5,9); +U+901E(0);U+901E(5,9); +U+901F(0);U+901F(5,9); +U+9020(0);U+9020(5,9); +U+9021(0);U+9021(5,9); +U+9022(0);U+9022(5,9); +U+9023(0);U+9023(0,9);U+8FDE(1,3,8) +U+9024(0);U+9024(0,9); +U+9025(0);U+8FF4(2,3,9);U+56DE(4,8,9),U+5EFB(3),U+8FF4(2,3,9),U+56D8(0,3,4,8),U+56EC(3,4,8),U+5EFD(2,3,4,8) + +U+9026(0);U+9090(1,3,8,9);U+9090(1,3,8,9) +U+9027(0);U+9027(0); +U+9028(0);U+9028(0); +U+9029(0);U+5954(2,3,8,9);U+5954(2,3,8,9),U+7287(2,3,8) +U+902B(0);U+902B(0); +U+902D(0);U+902D(5,9); +U+902E(0);U+902E(5,9);U+8FE8(3,8,9) +U+902F(0);U+902F(5,9); +U+9030(0);U+904A(3,9);U+6E38(3,8,9),U+904A(3,9) +U+9031(0);U+9031(0,9);U+5468(2,3,9) +U+9032(0);U+9032(0,9);U+8FDB(1,3,8) +U+9033(0);U+9033(0); +U+9034(0);U+9034(3,9); +U+9035(0);U+9035(5,9); +U+9036(0);U+9036(5,9); +U+9038(0);U+9038(5,9);U+52AE(4,9) +U+903A(0);U+9060(4,8,9);U+8FDC(4),U+9060(4,8,9) +U+903B(0);U+908F(1,3,8,9);U+908F(1,3,8,9) +U+903C(0);U+903C(5,9); +U+903D(0);U+903D(0,9); +U+903E(0);U+903E(5,9);U+8E30(2,9) +U+903F(0);U+903F(0,9); +U+9041(0);U+9041(5,9);U+906F(2,3,9) +U+9042(0);U+9042(5,9); +U+9043(0);U+9043(0); +U+9044(0);U+9044(5,9); +U+9045(0);U+9072(3,8,9);U+8FDF(3),U+9072(3,8,9),U+8FE1(3,9),U+905F(3) +U+9047(0);U+9047(5,9); +U+9048(0);U+9048(0); +U+9049(0);U+9049(0,9);U+4FA6(4),U+5075(1,3,4,8,9) +U+904A(0);U+904A(0,9);U+6E38(2,3,8,9),U+9030(3) +U+904B(0);U+904B(0,9);U+8FD0(1,3,8) +U+904C(0);U+904C(3); +U+904D(0);U+904D(5,9);U+5FA7(2,3,8) +U+904E(0);U+904E(0,9);U+8FC7(1,3,8) +U+904F(0);U+904F(5,9); +U+9050(0);U+9050(5,9); + +U+9051(0);U+9051(5,9);U+5FA8(3,8,9) +U+9052(0);U+9052(5,9); +U+9053(0);U+9053(5,9); +U+9054(0);U+9054(0,9);U+8FBE(1,3,8),U+8FD6(1,3,4,8,9) +U+9055(0);U+9055(0,9);U+8FDD(1,3,8) +U+9056(0);U+9056(0); +U+9057(0);U+907A(1,3,8,9);U+907A(1,3,8,9) +U+9058(0);U+9058(5,9); +U+9059(0);U+9059(0,9);U+9065(4,8) +U+905A(0);U+905A(0); +U+905B(0);U+905B(5,9); +U+905C(0);U+905C(0,9);U+900A(1,3,8),U+613B(0,1,3,8,9) +U+905D(0);U+905D(0,9); +U+905E(0);U+905E(0,9);U+9012(1,3,8),U+9013(4,8) +U+905F(0);U+9072(3,8,9);U+8FDF(3),U+9072(3,8,9),U+8FE1(3,9),U+9045(3) +U+9060(0);U+9060(0,9);U+8FDC(1,3,8),U+903A(4,8) +U+9061(0);U+6EAF(2,3,8,9);U+6CDD(3,9),U+6EAF(2,3,8,9) +U+9062(0);U+9062(5,9); +U+9063(0);U+9063(5,9); +U+9064(0);U+9064(0); +U+9065(0);U+9059(4,8,9);U+9059(4,8,9) +U+9066(0);U+9066(0); +U+9067(0);U+9067(0,9);U+7AE0(3,9) +U+9068(0);U+9068(5,9); +U+9069(0);U+9069(0,9);U+9002(1,3,8,9) +U+906A(0);U+906A(0); +U+906B(0);U+906B(0,9); +U+906C(0);U+906C(4); +U+906D(0);U+906D(5,9); +U+906E(0);U+906E(5,9); +U+906F(0);U+906F(0,9);U+9041(2,3,9) +U+9070(0);U+9070(0,9); +U+9071(0);U+9071(0); +U+9072(0);U+9072(0,9);U+8FDF(1,3,8),U+9045(3,8),U+905F(3,8),U+8FE1(1,3,8,9) +U+9073(0);U+9073(0,9);U+77EC(3,9) +U+9074(0);U+9074(5,9); +U+9075(0);U+9075(5,9); +U+9076(0);U+9076(0,9);U+7ED5(4),U+7E5E(0,1,3,4,8,9) +U+9077(0);U+9077(0,9);U+8FC1(1,3,8) +U+9078(0);U+9078(0,9);U+9009(1,3,8) +U+9079(0);U+9079(0,9); +U+907A(0);U+907A(0,9);U+9057(1,3,8) +U+907B(0);U+907B(0,9); +U+907C(0);U+907C(0,9);U+8FBD(1,3,8) +U+907D(0);U+907D(5,9); +U+907E(0);U+907E(0,9); +U+907F(0);U+907F(5,9);U+8F9F(3,8,9),U+95E2(1,3,4,8,9) +U+9080(0);U+9080(5,9); +U+9081(0);U+9081(0,9);U+8FC8(1,3,8) +U+9082(0);U+9082(5,9); +U+9083(0);U+9083(5,9); +U+9084(0);U+9084(0,9);U+8FD8(1,3,8) +U+9085(0);U+9085(0,9); +U+9086(0);U+9086(0,9); +U+9087(0);U+9087(0,9);U+8FE9(1,3,8) +U+9088(0);U+9088(5,9); +U+9089(0);U+908A(3,8,9);U+8FB9(3),U+908A(3,8,9) +U+908A(0);U+908A(0,9);U+8FB9(1,3,8),U+9089(3,8) +U+908B(0);U+908B(5,9); +U+908C(0);U+908C(0); +U+908D(0);U+908D(0,9);U+539F(4,9) +U+908E(0);U+908E(0); +U+908F(0);U+908F(0,9);U+903B(1,3,8) + +U+9090(0);U+9090(0,9);U+9026(1,3,8) +U+9091(0);U+9091(5,9); +U+9092(0);U+9092(0); +U+9093(0);U+9127(1,3,8,9);U+9127(1,3,8,9) +U+9094(0);U+9094(0,9); +U+9095(0);U+9095(5,9); +U+9096(0);U+9096(0); +U+9097(0);U+9097(5,9); +U+9098(0);U+9098(0,9); +U+9099(0);U+9099(5,9); +U+909A(0);U+909A(0); +U+909B(0);U+909B(5,9); +U+909C(0);U+909C(0); +U+909D(0);U+913A(1,3,8,9);U+913A(1,3,8,9) +U+909E(0);U+909E(0,9); +U+909F(0);U+909F(0,9); +U+90A0(0);U+90A0(0,9); +U+90A1(0);U+90A1(5,9); +U+90A2(0);U+90A2(5,9);U+90C9(3,8) +U+90A3(0);U+90A3(5,9); +U+90A4(0);U+90A4(0); +U+90A5(0);U+90A5(0,9); +U+90A6(0);U+90A6(5,9); +U+90A7(0);U+90A7(0,9); +U+90A8(0);U+6751(2,3,9);U+6751(2,3,9) +U+90A9(0);U+90A9(0); +U+90AA(0);U+90AA(5,9); +U+90AC(0);U+9114(1,3,8,9);U+9114(1,3,8,9) +U+90AD(0);U+90AD(0); +U+90AE(0);U+90F5(1,3,8,9);U+90F5(1,3,8,9) +U+90AF(0);U+90AF(5,9); +U+90B0(0);U+90B0(5,9); +U+90B1(0);U+90B1(5,9); +U+90B2(0);U+90B2(0,9); +U+90B3(0);U+90B3(5,9); +U+90B4(0);U+90B4(5,9); +U+90B5(0);U+90B5(5,9); +U+90B6(0);U+90B6(5,9);U+9101(3,9) +U+90B7(0);U+90B7(0); +U+90B8(0);U+90B8(5,9); +U+90B9(0);U+9112(1,3,8,9);U+9112(1,3,8,9) +U+90BA(0);U+9134(1,3,8,9);U+9134(1,3,8,9) +U+90BB(0);U+9130(1,3,8,9);U+9130(1,3,8,9),U+96A3(4) +U+90BC(0);U+90BC(0); +U+90BD(0);U+90BD(3,9); +U+90BE(0);U+90BE(5,9); +U+90BF(0);U+90BF(0,9); +U+90C0(0);U+90C0(0); +U+90C1(0);U+90C1(1,3,9),U+9B31(1,3,8,9);U+6B1D(2,3),U+9B30(4),U+9B31(1,3,8,9) +U+90C2(0);U+90C2(0); +U+90C3(0);U+90C3(0,9); +U+90C4(0);U+9699(3,8,9);U+9699(3,8,9) +U+90C5(0);U+90C5(5,9); +U+90C6(0);U+90C6(0); +U+90C7(0);U+90C7(5,9); +U+90C8(0);U+90C8(0,9); +U+90C9(0);U+90A2(3,8,9);U+90A2(3,8,9) +U+90CA(0);U+90CA(5,9); +U+90CB(0);U+90CB(0,9); +U+90CE(0);U+90CE(5,9);U+90DE(4,8) +U+90CF(0);U+90DF(1,3,8,9);U+90DF(1,3,8,9) +U+90D0(0);U+9136(1,3,8,9);U+9136(1,3,8,9) +U+90D1(0);U+912D(1,3,8,9);U+912D(1,3,8,9) + +U+90D3(0);U+9106(1,3,8,9);U+9106(1,3,8,9) +U+90D4(0);U+90D4(0,9); +U+90D5(0);U+90D5(0,9); +U+90D6(0);U+90D6(0,9); +U+90D7(0);U+90D7(5,9); +U+90D8(0);U+90D8(0,9);U+5415(3),U+5442(3,4,8,9) +U+90D9(0);U+90D9(0,9); +U+90DA(0);U+90DA(0,9); +U+90DB(0);U+90DB(5,9); +U+90DC(0);U+90DC(5,9); +U+90DD(0);U+90DD(5,9); +U+90DE(0);U+90CE(4,8,9);U+90CE(4,8,9) +U+90DF(0);U+90DF(0,9);U+90CF(1,3,8) +U+90E0(0);U+90E0(0,9); +U+90E1(0);U+90E1(5,9); +U+90E2(0);U+90E2(5,9); +U+90E3(0);U+90E3(0,9);U+6E24(3,9) +U+90E4(0);U+90E4(0,9); +U+90E5(0);U+90E5(0,9); +U+90E6(0);U+9148(1,3,8,9);U+9148(1,3,8,9) +U+90E7(0);U+9116(1,3,8,9);U+9116(1,3,8,9) +U+90E8(0);U+90E8(5,9); +U+90E9(0);U+90E9(0,9); +U+90EA(0);U+90EA(0,9); +U+90EB(0);U+90EB(5,9); +U+90EC(0);U+90EC(0,9); +U+90ED(0);U+90ED(5,9);U+588E(3,9) +U+90EE(0);U+90EE(0); +U+90EF(0);U+90EF(5,9); +U+90F0(0);U+90F0(0,9);U+9139(3,9) +U+90F1(0);U+90F1(0,9); +U+90F2(0);U+90F2(0,9);U+83B1(3),U+840A(1,3,8,9) +U+90F3(0);U+90F3(3,9); +U+90F4(0);U+90F4(5,9); +U+90F5(0);U+90F5(0,9);U+90AE(1,3,8) +U+90F7(0);U+9109(3,8,9);U+4E61(3),U+9109(3,8,9),U+9115(3,4) +U+90F8(0);U+9132(1,3,8,9);U+9132(1,3,8,9) +U+90F9(0);U+90F9(0,9); +U+90FA(0);U+90FA(0,9); +U+90FB(0);U+90FB(0,9); +U+90FC(0);U+90FC(0,9); +U+90FD(0);U+90FD(5,9); +U+90FE(0);U+90FE(5,9); +U+90FF(0);U+90FF(0,9); +U+9100(0);U+9100(0,9); +U+9101(0);U+9101(0,9);U+90B6(3,9) +U+9102(0);U+9102(5,9); +U+9103(0);U+9103(0,9);U+4FDE(4,9),U+516A(3,4,8) +U+9104(0);U+9104(5,9); +U+9105(0);U+9105(0,9); +U+9106(0);U+9106(0,9);U+90D3(1,3,8) +U+9107(0);U+9107(0,9); +U+9108(0);U+9108(0,9); +U+9109(0);U+9109(0,9);U+4E61(1,3,8),U+90F7(3,8),U+9115(4,8) +U+910B(0);U+910B(3,9); +U+910C(0);U+910C(0); +U+910D(0);U+910D(0,9); +U+910E(0);U+910E(0,9); +U+910F(0);U+910F(0,9); +U+9110(0);U+9110(0,9); +U+9111(0);U+9111(0,9); +U+9112(0);U+9112(0,9);U+90B9(1,3,8) +U+9113(0);U+9113(0); + +U+9114(0);U+9114(0,9);U+90AC(1,3,8) +U+9115(0);U+9109(4,8,9);U+4E61(4),U+9109(4,8,9),U+90F7(3,4) +U+9116(0);U+9116(0,9);U+90E7(1,3,8) +U+9117(0);U+9117(0,9); +U+9118(0);U+9118(0,9); +U+9119(0);U+9119(5,9); +U+911A(0);U+911A(0,9); +U+911B(0);U+911B(0,9); +U+911C(0);U+911C(0,9); +U+911D(0);U+911D(0,9); +U+911E(0);U+911E(5,9); +U+911F(0);U+911F(0,9); +U+9120(0);U+9120(0,9); +U+9121(0);U+9121(0,9); +U+9122(0);U+9122(5,9); +U+9123(0);U+9123(5,9); +U+9124(0);U+9124(0,9); +U+9125(0);U+9125(0); +U+9126(0);U+9126(0,9);U+8BB8(3),U+8A31(0,1,3,8,9) +U+9127(0);U+9127(0,9);U+9093(1,3,8) +U+9128(0);U+9128(0,9); +U+9129(0);U+9129(0,9); +U+912A(0);U+912A(3,9); +U+912B(0);U+912B(0,9); +U+912C(0);U+912C(0,9); +U+912D(0);U+912D(0,9);U+90D1(1,3,8) +U+912E(0);U+912E(0,9); +U+912F(0);U+912F(5,9); +U+9130(0);U+9130(0,9);U+90BB(1,3,8),U+96A3(2,3,8) +U+9131(0);U+9131(5,9); +U+9132(0);U+9132(0,9);U+90F8(1,3,8) +U+9133(0);U+9133(0,9); +U+9134(0);U+9134(0,9);U+90BA(1,3,8) +U+9135(0);U+9135(0,9); +U+9136(0);U+9136(0,9);U+90D0(1,3,8) +U+9137(0);U+9146(3,8,9);U+9146(3,8,9) +U+9138(0);U+9138(0,9); +U+9139(0);U+9139(5,9);U+90F0(3,9) +U+913A(0);U+913A(0,9);U+909D(1,3,8) +U+913B(0);U+913B(0,9); +U+913E(0);U+913E(0,9); +U+913F(0);U+913F(0,9); +U+9140(0);U+9140(0,9); +U+9141(0);U+9141(0,9); +U+9142(0);U+9147(4,8,9);U+9147(4,8,9) +U+9143(0);U+9143(5,9); +U+9144(0);U+9144(0,9); +U+9145(0);U+9145(4,9); +U+9146(0);U+9146(5,9);U+9137(3,8) +U+9147(0);U+9147(0,9);U+9142(4,8) +U+9148(0);U+9148(0,9);U+90E6(1,3,8) +U+9149(0);U+9149(5,9);U+4E23(3,8) +U+914A(0);U+914A(5,9); +U+914B(0);U+914B(5,9); +U+914C(0);U+914C(5,9); +U+914D(0);U+914D(5,9); +U+914E(0);U+914E(5,9); +U+914F(0);U+914F(5,9); +U+9150(0);U+9150(5,9); +U+9151(0);U+9151(0); +U+9152(0);U+9152(5,9); +U+9153(0);U+9153(0,9); +U+9154(0);U+9189(3,8,9);U+9189(3,8,9) + +U+9155(0);U+9155(0,9); +U+9156(0);U+9156(0,9); +U+9157(0);U+9157(5,9); +U+9158(0);U+9158(3,9); +U+915A(0);U+915A(5,9); +U+915B(0);U+915B(0); +U+915C(0);U+915C(0); +U+915D(0);U+919E(4,8,9);U+9196(1,3,8),U+919E(4,8,9) +U+915E(0);U+915E(5); +U+915F(0);U+915F(0,9); +U+9160(0);U+9160(0,9); +U+9161(0);U+9161(5,9); +U+9162(0);U+9162(5,9);U+918B(3,8,9) +U+9163(0);U+9163(5,9); +U+9164(0);U+9164(5,9); +U+9165(0);U+9165(5,9); +U+9166(0);U+91B1(4,8,9);U+91B1(4,8,9) +U+9167(0);U+916C(2,3,8,9);U+916C(2,3,8,9),U+8A76(0,2,3,8,9),U+91BB(2,3,8) +U+9168(0);U+9168(0,9); +U+9169(0);U+9169(5,9); +U+916A(0);U+916A(5,9); +U+916B(0);U+916B(0); +U+916C(0);U+916C(5,9);U+8A76(2,3,8,9),U+9167(2,3,8),U+91BB(2,3,8) +U+916D(0);U+916D(0); +U+916E(0);U+916E(5,9); +U+916F(0);U+916F(5,9); +U+9170(0);U+9170(5); +U+9171(0);U+91AC(1,3,8,9);U+91AC(1,3,8,9) +U+9172(0);U+9172(5,9); +U+9173(0);U+9173(0,9); +U+9174(0);U+9174(5,9); +U+9175(0);U+9175(5,9); +U+9176(0);U+9176(5); +U+9177(0);U+9177(5,9); +U+9178(0);U+9178(5,9); +U+9179(0);U+9179(5,9); +U+917A(0);U+917A(3,9); +U+917C(0);U+917C(0); +U+917D(0);U+91C5(1,3,8,9);U+91C5(1,3,8,9) +U+917E(0);U+91C3(1,3,8,9);U+91C3(1,3,8,9) +U+917F(0);U+91C0(1,3,8,9);U+91C0(1,3,8,9) +U+9180(0);U+9180(0,9); +U+9181(0);U+9181(3,9); +U+9182(0);U+9182(0,9); +U+9183(0);U+9183(0,9);U+814C(2,9) +U+9184(0);U+9184(0,9); +U+9185(0);U+9185(5,9); +U+9186(0);U+9186(0,9);U+76CF(4),U+7416(0,4,9),U+76DE(1,3,4,8,9) +U+9187(0);U+9187(5,9); +U+9188(0);U+9188(0); +U+9189(0);U+9189(5,9);U+9154(3,8) +U+918A(0);U+918A(3,9); +U+918B(0);U+918B(5,9);U+9162(3,8,9) +U+918C(0);U+918C(5); +U+918D(0);U+918D(5,9); +U+918E(0);U+918E(0); +U+918F(0);U+918F(0,9); +U+9190(0);U+9190(5,9); +U+9191(0);U+9191(5,9); +U+9192(0);U+9192(5,9); +U+9193(0);U+9193(0,9); +U+9194(0);U+9194(0); +U+9196(0);U+919E(8,9);U+915D(1,3,8),U+919E(8,9) + +U+9199(0);U+9199(0,9); +U+919A(0);U+919A(5,9); +U+919B(0);U+919B(5,9); +U+919C(0);U+919C(0,9);U+4E11(1,3,8,9) +U+919D(0);U+919D(3,9); +U+919E(0);U+919E(0,9);U+915D(4,8),U+9196(8) +U+919F(0);U+919F(0,9); +U+91A0(0);U+91A0(0,9); +U+91A1(0);U+91A1(0,9);U+69A8(3,9),U+643E(0,2,3,9) +U+91A2(0);U+91A2(5,9); +U+91A3(0);U+91A3(5,9); +U+91A5(0);U+91A5(0,9); +U+91A6(0);U+91A6(0); +U+91A7(0);U+91A7(0,9); +U+91A8(0);U+91A8(3,9); +U+91AA(0);U+91AA(5,9); +U+91AB(0);U+91AB(0,9);U+533B(1,3,8),U+6BC9(1,3,8,9) +U+91AC(0);U+91AC(0,9);U+9171(1,3,8) +U+91AD(0);U+91AD(5,9); +U+91AE(0);U+91AE(5,9); +U+91AF(0);U+91AF(5,9); +U+91B0(0);U+91B0(0,9); +U+91B1(0);U+91B1(0,9);U+9166(4,8) +U+91B2(0);U+91B2(3,9); +U+91B3(0);U+91B3(0,9); +U+91B4(0);U+91B4(5,9); +U+91B5(0);U+91B5(5,9); +U+91B6(0);U+91B6(3); +U+91B7(0);U+91B7(0,9); +U+91B9(0);U+91B9(0,9); +U+91BA(0);U+91BA(5,9); +U+91BB(0);U+916C(2,3,8,9);U+916C(2,3,8,9),U+8A76(0,2,3,8,9),U+9167(2,3,8) +U+91BC(0);U+91BC(0,9);U+5BB4(2,3,9) +U+91BD(0);U+91BD(0,9); +U+91BE(0);U+91BE(3,9); +U+91C0(0);U+91C0(0,9);U+917F(1,3,8) +U+91C1(0);U+91C1(0,9);U+8845(1,3,8) +U+91C2(0);U+91C2(0,9); +U+91C3(0);U+91C3(0,9);U+917E(1,3,8) +U+91C5(0);U+91C5(0,9);U+917D(1,3,8) +U+91C6(0);U+91C6(0,9);U+8FA8(4,9),U+529E(1,3,4,8),U+8FA6(0,3,4,9),U+8FA7(3,4,8) +U+91C7(0);U+91C7(5,9),U+63A1(2,3,9);U+63A1(2,3,9) +U+91C9(0);U+91C9(5,9); +U+91CA(0);U+91CB(1,3,8,9);U+91CB(1,3,8,9) +U+91CB(0);U+91CB(0,9);U+91CA(1,3,8) +U+91CC(0);U+91CC(1,3,4,9),U+88CF(1,3,4,8,9),U+88E1(4,9);U+88CF(1,3,4,8,9),U+88E1(4,9) + +U+91CD(0);U+91CD(5,9);U+7DDF(3,9) +U+91CE(0);U+91CE(5,9);U+57DC(2,3,8,9) +U+91CF(0);U+91CF(5,9); +U+91D0(0);U+91D0(0,9);U+5398(2,3,8,9) +U+91D1(0);U+91D1(5,9);U+91D2(8),U+9485(8) +U+91D2(0);U+91D1(8,9);U+91D1(8,9),U+9485(4,8) +U+91D3(0);U+91D3(0,9);U+9486(1,3,8) +U+91D4(0);U+91D4(0,9);U+9487(1,3,8) +U+91D5(0);U+91D5(0,9);U+948C(1,3,8) +U+91D7(0);U+91D7(0,9);U+948A(1,3,8) +U+91D8(0);U+91D8(0,9);U+9489(1,3,8) +U+91D9(0);U+91D9(0,9);U+948B(1,3,8) +U+91DA(0);U+91DA(3,9); +U+91DB(0);U+91DB(0); +U+91DC(0);U+91DC(5,9); +U+91DD(0);U+91DD(0,9);U+9488(1,3,8) + +U+91DE(0);U+91DE(0); +U+91DF(0);U+91DF(0); +U+91E2(0);U+91E2(0,9); +U+91E3(0);U+91E3(0,9);U+9493(1,8),U+9B61(1,4,8,9) +U+91E4(0);U+91E4(0,9);U+9490(1,3,8) +U+91E5(0);U+91E5(0); +U+91E6(0);U+91E6(0,9);U+6263(2,9) +U+91E7(0);U+91E7(0,9);U+948F(1,3,8) +U+91E8(0);U+91E8(0,9); +U+91E9(0);U+91E9(0,9);U+9492(1,3,8) +U+91EA(0);U+91EA(0,9); +U+91EB(0);U+91EB(0,9); +U+91EC(0);U+91EC(0,9);U+710A(2,3,9),U+92B2(2,3,9) +U+91ED(0);U+91ED(0,9); +U+91EE(0);U+91EE(0,9); +U+91F0(0);U+91F0(0); +U+91F1(0);U+91F1(3,9); +U+91F2(0);U+91F2(0); +U+91F3(0);U+91F3(0,9); +U+91F4(0);U+91F4(0,9); +U+91F5(0);U+91F5(0,9);U+9497(1,3,8) +U+91F7(0);U+91F7(0,9);U+948D(1,3,8) +U+91F8(0);U+91F8(0,9); +U+91F9(0);U+91F9(0,9);U+9495(1,3,8) +U+91FA(0);U+91FA(0);U+948E(1,3,8) +U+91FB(0);U+91FB(0); +U+91FD(0);U+91FD(0,9); +U+91FE(0);U+91FE(0);U+497A(1,3) +U+91FF(0);U+91FF(3,9); +U+9200(0);U+9200(0,9);U+94AF(1,3,8) +U+9201(0);U+9201(0,9);U+94AB(1,3,8) +U+9202(0);U+9202(0,9); +U+9203(0);U+9203(0,9);U+9498(1,3,8) +U+9204(0);U+9204(0,9);U+94AD(1,3,8) +U+9205(0);U+9205(0,9);U+94A5(4),U+9470(1,3,4,8,9) +U+9206(0);U+9206(0,9);U+94C5(2),U+925B(1,2,3,8,9) +U+9207(0);U+9207(0,9); +U+9208(0);U+9208(0);U+949A(1,3,8) +U+9209(0);U+9209(0,9);U+94A0(1,3,8) +U+920A(0);U+920A(0,9); +U+920B(0);U+920B(0); +U+920C(0);U+920C(0,9); +U+920D(0);U+920D(0,9);U+949D(1,3,8) +U+920E(0);U+9264(2,3,8,9);U+9264(2,3,8,9),U+94A9(1,3,8) +U+920F(0);U+920F(0,9); +U+9210(0);U+9210(0,9);U+94A4(1,3,8) +U+9211(0);U+9211(0,9);U+94A3(4,8) +U+9212(0);U+9212(0,9);U+9491(4,8) +U+9214(0);U+9214(0,9);U+949E(1,3,8) +U+9215(0);U+9215(0,9);U+94AE(1,3,8) +U+9216(0);U+9216(0,9); +U+9217(0);U+9217(3,9); +U+9218(0);U+9218(0); +U+9219(0);U+9219(0,9); +U+921A(0);U+921A(3,9); +U+921B(0);U+921B(0); +U+921C(0);U+921C(0,9); +U+921D(0);U+921D(0); +U+921E(0);U+921E(0,9);U+94A7(1,3,8) +U+9220(0);U+9220(0); +U+9221(0);U+9418(4,9);U+9418(4,9),U+949F(4),U+87A4(0,3,4,9),U+937E(1,3,4,8,9),U+953A(1,3,4,8) + +U+9223(0);U+9223(0,9);U+9499(1,3,8) + +U+9224(0);U+9224(0,9); +U+9225(0);U+9225(0,9);U+94AC(1,3,8) +U+9226(0);U+9226(0,9);U+949B(1,3,8) +U+9227(0);U+9227(0,9);U+94AA(1,3,8) +U+9228(0);U+9228(0); +U+9229(0);U+9229(0); +U+922A(0);U+922A(0); +U+922B(0);U+922B(0); +U+922D(0);U+922D(0,9); +U+922E(0);U+922E(0,9);U+94CC(1,3,8) +U+922F(0);U+922F(0); +U+9230(0);U+9230(0,9);U+94C8(1,3,8) +U+9231(0);U+9231(0,9); +U+9232(0);U+9232(0,9); +U+9233(0);U+9233(0,9);U+94B6(1,3,8) +U+9234(0);U+9234(0,9);U+94C3(1,3,8) +U+9235(0);U+9235(0); +U+9236(0);U+9236(0,9); +U+9237(0);U+9237(0,9);U+94B4(1,3,8) +U+9238(0);U+9238(0,9);U+94B9(1,8) +U+9239(0);U+9239(0,9);U+94CD(1,3,8) +U+923A(0);U+923A(0,9);U+94B0(1,3,8) +U+923B(0);U+923B(0); +U+923C(0);U+923C(0); +U+923D(0);U+923D(0,9);U+94B8(4,8) +U+923E(0);U+923E(0,9);U+94C0(1,3,8) +U+923F(0);U+923F(0,9);U+94BF(1,3,8) +U+9240(0);U+9240(0,9);U+94BE(1,3,8) +U+9241(0);U+9241(0); +U+9242(0);U+9242(0); +U+9245(0);U+9245(0,9);U+5DE8(2,3,8,9),U+949C(4,8) +U+9246(0);U+9246(0,9);U+94BB(4),U+947D(1,3,4,8,9),U+9409(4,9) +U+9247(0);U+9247(4); +U+9248(0);U+9248(0,9);U+94CA(1,3,8) +U+9249(0);U+9249(0,9);U+94C9(1,3,8) +U+924A(0);U+924A(0,9); +U+924B(0);U+924B(0,9);U+94C7(4,8) +U+924C(0);U+924C(0,9);U+548C(3,9),U+9FA2(2,3,8,9) +U+924D(0);U+924D(0,9);U+94CB(1,3,8) +U+924E(0);U+924E(0,9); +U+924F(0);U+924F(0,9); +U+9250(0);U+9250(0,9); +U+9251(0);U+9251(0,9);U+94C2(1,3,8) +U+9252(0);U+9252(0,9); +U+9253(0);U+9253(0,9); +U+9254(0);U+9254(0,9); +U+9255(0);U+9255(0);U+94B7(1,3,8) +U+9256(0);U+9256(0,9); +U+9257(0);U+9257(0,9);U+7B9D(3,8,9),U+94B3(1,3,8),U+62D1(0,1,3,4,8,9) +U+9258(0);U+9258(0); +U+9259(0);U+9259(0); +U+925A(0);U+925A(0,9);U+94C6(1,3,8) +U+925B(0);U+925B(0,9);U+94C5(1,3,8),U+9206(0,1,2,3,8,9) +U+925C(0);U+925C(0); +U+925D(0);U+925D(0); +U+925E(0);U+925E(0,9);U+94BA(1,3,8) +U+925F(0);U+925F(3); +U+9260(0);U+9260(3,9); +U+9261(0);U+9261(0,9); +U+9262(0);U+7F3D(2,3,8,9);U+7F3D(2,3,8,9),U+94B5(1,3,8) +U+9263(0);U+9263(0,9); +U+9264(0);U+9264(0,9);U+920E(2,3,8),U+94A9(4,8) +U+9265(0);U+9265(3,9); + +U+9266(0);U+9266(0,9);U+94B2(1,3,8) +U+9267(0);U+9267(0,9); +U+9268(0);U+9268(4); +U+926B(0);U+926B(0); +U+926C(0);U+926C(0,9);U+94BC(1,3,8) +U+926D(0);U+926D(0,9);U+94BD(1,3,8) +U+926E(0);U+926E(0); +U+926F(0);U+926F(0,9); +U+9270(0);U+9270(0,9); +U+9272(0);U+9272(0,9); +U+9273(0);U+9273(0); +U+9274(0);U+9452(1,3,8,9);U+9451(4,9),U+9452(1,3,8,9) +U+9275(0);U+9275(0); +U+9276(0);U+9276(0,9);U+94CF(1,3,8) +U+9277(0);U+9277(0); +U+9278(0);U+9278(0,9);U+94F0(1,3,8) +U+9279(0);U+9279(0,9); +U+927A(0);U+927A(0,9);U+94D2(1,3,8) +U+927B(0);U+927B(0,9);U+94EC(1,3,8) +U+927C(0);U+927C(0,9); +U+927D(0);U+927D(0,9); +U+927E(0);U+927E(0,9); +U+927F(0);U+927F(0,9);U+94EA(1,3,8) +U+9280(0);U+9280(0,9);U+94F6(1,3,8) +U+9282(0);U+9282(0,9); +U+9283(0);U+9283(0,9);U+94F3(1,3,8) +U+9285(0);U+9285(0,9);U+94DC(1,3,8) +U+9286(0);U+9286(0,9); +U+9287(0);U+9287(0,9); +U+9288(0);U+9288(0,9); +U+9289(0);U+9289(0); +U+928A(0);U+928A(0,9); +U+928B(0);U+928B(3,9); +U+928C(0);U+928C(0,9); +U+928D(0);U+928D(0,9);U+94DA(4,8) +U+928E(0);U+928E(5,9); +U+928F(0);U+928F(0); +U+9290(0);U+9290(0); +U+9291(0);U+9291(0,9);U+94E3(1,3,8) +U+9292(0);U+9292(3); +U+9293(0);U+9293(0,9);U+94E8(1,3,8) +U+9294(0);U+9294(3,9); +U+9295(0);U+9295(0,9);U+9435(3,8,9),U+94C1(3) +U+9296(0);U+9296(0,9);U+94E2(1,3,8) +U+9297(0);U+9297(0,9); +U+9298(0);U+9298(0,9);U+94ED(1,3,8) +U+9299(0);U+9299(3,9); +U+929A(0);U+929A(0,9);U+94EB(1,3,8) +U+929B(0);U+929B(0,9);U+94E6(4,8) +U+929C(0);U+929C(0,9);U+8854(1,3,8),U+5563(0,1,3,4,8,9) +U+929D(0);U+929D(0,9); +U+929F(0);U+929F(0); +U+92A0(0);U+92A0(0,9);U+94D1(1,3,8) +U+92A1(0);U+92A1(0,9); +U+92A2(0);U+92A2(0,9); +U+92A3(0);U+92A3(0,9);U+94F7(1,3,8) +U+92A4(0);U+92A4(0,9); +U+92A5(0);U+92A5(0,9);U+94F1(1,3,8) +U+92A6(0);U+92A6(0,9);U+94DF(1,3,8) +U+92A7(0);U+92A7(0,9); +U+92A8(0);U+92A8(0,9);U+94F5(1,3,8) +U+92A9(0);U+92A9(0,9);U+94E5(1,3,8) +U+92AA(0);U+92AA(0,9);U+94D5(1,3,8) + +U+92AB(0);U+92AB(0,9);U+94EF(1,3,8) +U+92AC(0);U+92AC(0,9);U+94D0(1,3,8) +U+92AD(0);U+9322(3,8,9);U+9322(3,8,9),U+94B1(3) +U+92AE(0);U+947E(1,3,8,9);U+947E(1,3,8,9) +U+92AF(0);U+92AF(0); +U+92B0(0);U+92B0(0); +U+92B1(0);U+92B1(0);U+94DE(1,3,8) +U+92B2(0);U+92B2(0,9);U+710A(2,9),U+91EC(2,3,9) +U+92B3(0);U+92B3(0,9);U+92ED(8),U+9510(4,8) +U+92B4(0);U+92B4(0,9); +U+92B5(0);U+92B5(3,9); +U+92B6(0);U+92B6(3,9); +U+92B7(0);U+92B7(0,9);U+9500(1,3,8) +U+92B8(0);U+92B8(0); +U+92B9(0);U+92B9(0,9);U+93FD(2,3,8,9),U+9508(1,3,8) +U+92BA(0);U+92BA(0); +U+92BB(0);U+92BB(0,9);U+9511(1,3,8) +U+92BC(0);U+92BC(0,9);U+9509(1,3,8) +U+92BE(0);U+92BE(0); +U+92BF(0);U+92BF(0); +U+92C0(0);U+92C0(0,9); +U+92C1(0);U+92C1(0,9);U+94DD(1,3,8) +U+92C2(0);U+92C2(0,9); +U+92C3(0);U+92C3(0,9);U+9512(1,3,8) +U+92C4(0);U+92C4(0,9);U+933D(3,8) +U+92C5(0);U+92C5(0,9);U+950C(1,3,8) +U+92C6(0);U+92C6(0,9); +U+92C7(0);U+92C7(0,9);U+94A1(1,3,8) +U+92C8(0);U+92C8(5,9); +U+92C9(0);U+92C9(0,9); +U+92CA(0);U+92CA(0,9); +U+92CB(0);U+92CB(0,9); +U+92CC(0);U+92CC(0,9);U+94E4(1,3,8) +U+92CD(0);U+92CD(0,9); +U+92CE(0);U+92CE(0,9); +U+92CF(0);U+92CF(0,9);U+94D7(1,3,8) +U+92D0(0);U+92D0(0,9); +U+92D1(0);U+92D1(0,9); +U+92D2(0);U+92D2(0,9);U+950B(1,3,8) +U+92D3(0);U+92D3(0,9); +U+92D5(0);U+92D5(0,9); +U+92D6(0);U+92D6(0); +U+92D7(0);U+92D7(0,9); +U+92D8(0);U+92D8(0,9); +U+92D9(0);U+92D9(0,9);U+94FB(4,8) +U+92DA(0);U+92DA(0); +U+92DC(0);U+92DC(0); +U+92DD(0);U+92DD(0,9);U+950A(4,8) +U+92DE(0);U+92DE(3,9); +U+92DF(0);U+92DF(0,9);U+9513(1,3,8) +U+92E0(0);U+92E0(0,9); +U+92E1(0);U+92E1(0,9); +U+92E3(0);U+92E3(0);U+94D8(4,8) +U+92E4(0);U+92E4(0,9);U+8021(2,3,8,9),U+9504(1,3,8) +U+92E5(0);U+92E5(0);U+9503(1,3,8) +U+92E6(0);U+92E6(0,9);U+9514(1,3,8) +U+92E7(0);U+92E7(0,9); +U+92E8(0);U+92E8(0,9);U+9507(1,3,8) +U+92E9(0);U+92E9(0,9);U+94D3(1,3,8) +U+92EA(0);U+92EA(0,9);U+8216(2,3,8,9),U+94FA(1,3,8) +U+92EB(0);U+92EB(0); +U+92EC(0);U+92EC(0); +U+92ED(0);U+92B3(8,9);U+92B3(8,9),U+9510(1,3,8) + +U+92EE(0);U+92EE(0,9);U+94D6(4,8) +U+92EF(0);U+92EF(0,9);U+9506(1,3,8) +U+92F0(0);U+92F0(0,9);U+9502(1,3,8) +U+92F1(0);U+92F1(0,9);U+94FD(1,3,8) +U+92F2(0);U+92F2(0); +U+92F3(0);U+9444(4,8,9);U+9444(4,8,9),U+94F8(4) +U+92F4(0);U+92F4(0); +U+92F5(0);U+92F5(0); +U+92F6(0);U+92F6(0);U+950D(4,8) +U+92F7(0);U+92F7(0,9); +U+92F8(0);U+92F8(0,9);U+952F(1,3,8) +U+92F9(0);U+92F9(0,9); +U+92FA(0);U+92FA(0,9);U+7897(3,9) +U+92FB(0);U+92FB(0,9); +U+92FC(0);U+92FC(0,9);U+94A2(1,3,8) +U+92FD(0);U+92FD(0); +U+92FE(0);U+92FE(0,9); +U+92FF(0);U+92FF(3,9); +U+9300(0);U+9300(0,9); +U+9301(0);U+9301(0,9);U+951E(1,3,8) +U+9302(0);U+9302(0,9); +U+9303(0);U+9303(0); +U+9304(0);U+9304(0,9);U+5F55(4,8),U+9332(4,8),U+5F54(0,3,4,8,9) +U+9305(0);U+9305(0); +U+9306(0);U+9306(0,9);U+9516(4,8) +U+9307(0);U+9307(0);U+952B(1,3,8) +U+9308(0);U+9308(0,9);U+9529(4,8) +U+9309(0);U+9309(0,9); +U+930A(0);U+930A(0); +U+930B(0);U+930B(0,9);U+93F0(4),U+955A(4,8) +U+930C(0);U+930C(0,9); +U+930D(0);U+930D(0,9); +U+930E(0);U+930E(0,9); +U+930F(0);U+930F(0,9);U+94D4(4,8) +U+9310(0);U+9310(0,9);U+9525(1,3,8) +U+9311(0);U+9311(3); +U+9312(0);U+9312(0,9);U+9515(1,3,8) +U+9313(0);U+9313(0,9); +U+9314(0);U+9314(0,9); +U+9315(0);U+9315(0,9);U+951F(1,3,8) +U+9316(0);U+9316(0,9); +U+9317(0);U+9317(0); +U+9318(0);U+9318(0,9);U+9524(1,3,8),U+939A(1,2,3,8,9) +U+9319(0);U+9319(0,9);U+9531(1,3,8) +U+931A(0);U+931A(0,9);U+94EE(1,3,8) +U+931B(0);U+931B(0,9);U+951B(1,3,8) +U+931D(0);U+931D(0,9); +U+931E(0);U+931E(3,9); +U+931F(0);U+931F(0,9);U+952C(4,8) +U+9320(0);U+9320(0,9);U+952D(1,3,8) +U+9321(0);U+9321(0,9);U+951C(4,8) +U+9322(0);U+9322(0,9);U+92AD(3,8),U+94B1(1,3,8) +U+9323(0);U+9323(0,9); +U+9324(0);U+9324(0,9); +U+9325(0);U+9325(0,9); +U+9326(0);U+9326(0,9);U+9526(1,3,8) +U+9327(0);U+9327(0,9); +U+9328(0);U+9328(0,9);U+951A(1,3,8) +U+9329(0);U+9329(0,9);U+9520(4,8) +U+932A(0);U+932A(0,9); +U+932B(0);U+932B(0,9);U+9521(1,3,8) +U+932D(0);U+932D(3,9); +U+932E(0);U+932E(0,9);U+9522(1,3,8) + +U+932F(0);U+932F(0,9);U+9519(1,3,8) +U+9332(0);U+9304(4,8,9);U+5F55(1,3,8),U+9304(4,8,9),U+5F54(0,1,3,8,9) +U+9333(0);U+9333(0,9);U+9530(1,3,8) +U+9334(0);U+9334(0,9); +U+9335(0);U+9335(0,9); +U+9336(0);U+9336(0,9);U+8868(1,3,9) +U+9337(0);U+9337(0); +U+9338(0);U+9338(0,9);U+94FC(1,3,8) +U+9339(0);U+9339(0,9); +U+933A(0);U+933A(0); +U+933B(0);U+933B(0); +U+933C(0);U+933C(0,9);U+637A(4,9) +U+933D(0);U+92C4(3,8,9);U+92C4(3,8,9) +U+933E(0);U+93E8(1,3,8,9);U+93E8(1,3,8,9) +U+933F(0);U+933F(0); +U+9340(0);U+9340(0);U+951D(1,3,8) +U+9341(0);U+9341(0);U+9528(1,3,8) +U+9342(0);U+9342(0); +U+9343(0);U+9343(0);U+952A(4,8) +U+9344(0);U+9344(0); +U+9345(0);U+9345(0); +U+9346(0);U+9346(0,9);U+9494(1,3,8) +U+9347(0);U+9347(0,9);U+9534(1,3,8) +U+9348(0);U+9348(0);U+9533(4,8) +U+9349(0);U+9349(0,9); +U+934A(0);U+934A(0,9);U+70BC(4),U+7149(1,3,4,8,9) +U+934B(0);U+934B(0,9);U+9505(1,3,8) +U+934C(0);U+934C(0,9); +U+934D(0);U+934D(0,9);U+9540(1,3,8) +U+934E(0);U+934E(0,9); +U+934F(0);U+934F(0,9); +U+9350(0);U+9350(3,9); +U+9351(0);U+9351(3,9); +U+9352(0);U+9352(3,9); +U+9353(0);U+9353(0); +U+9354(0);U+9354(0,9);U+9537(1,3,8) +U+9355(0);U+9355(0,9); +U+9356(0);U+9356(0,9); +U+9357(0);U+9357(0,9); +U+9358(0);U+9358(0,9);U+94E1(1,3,8) +U+9359(0);U+9359(0,9); +U+935A(0);U+935A(0,9);U+9496(1,3),U+940A(1,3,9) +U+935B(0);U+935B(0,9);U+7145(3,8),U+953B(1,3,8) +U+935C(0);U+935C(0,9); +U+935D(0);U+935D(0); +U+935E(0);U+935E(0,9);U+94FF(3),U+93D7(1,3,8,9) +U+935F(0);U+935F(3); +U+9360(0);U+9360(0,9);U+953D(4,8) +U+9361(0);U+9361(0,9); +U+9363(0);U+9363(0,9); +U+9364(0);U+9364(0,9);U+9538(1,3,8),U+81FF(0,1,3,4,8,9) +U+9365(0);U+9365(0,9);U+9532(1,3,8),U+9411(1,3,8,9) +U+9366(0);U+9366(3); +U+9367(0);U+9367(0,9); +U+9369(0);U+9369(0);U+9518(1,3,8) +U+936A(0);U+936A(5,9); +U+936C(0);U+936C(0,9);U+9539(1,3,8) +U+936D(0);U+936D(0,9); +U+936E(0);U+936E(3); +U+9370(0);U+9370(0,9);U+953E(1,3,8) +U+9371(0);U+9371(3,9);U+9437(3,9) +U+9372(0);U+9372(3); +U+9374(0);U+9374(0); + +U+9375(0);U+9375(0,9);U+952E(1,3,8),U+9473(1,3,8,9) +U+9376(0);U+9376(0,9);U+9536(1,3,8) +U+9377(0);U+9377(0,9); +U+9379(0);U+9379(0,9); +U+937A(0);U+937A(0,9);U+9517(1,3,8) +U+937B(0);U+937B(0,9); +U+937C(0);U+937C(0,9); +U+937D(0);U+937D(0); +U+937E(0);U+937E(0,9);U+9418(3,8,9),U+949F(1,3,8),U+953A(4,8),U+87A4(0,1,3,8,9),U+9221(1,3,4,8) + +U+9380(0);U+9380(0,9); +U+9382(0);U+9382(0,9);U+9541(1,3,8) +U+9383(0);U+9383(0,9); +U+9384(0);U+9384(0);U+953F(1,3,8) +U+9385(0);U+9385(0); +U+9386(0);U+9386(0); +U+9387(0);U+9387(0);U+9545(1,3,8) +U+9388(0);U+9388(0,9); +U+9389(0);U+9389(0,9); +U+938A(0);U+938A(0,9);U+9551(1,3,8) +U+938C(0);U+938C(0,9);U+9570(2,3),U+5286(0,2,3),U+942E(2,3,8,9) +U+938D(0);U+938D(0,9); +U+938E(0);U+938E(0,9); +U+938F(0);U+938F(5,9); +U+9390(0);U+9390(0); +U+9391(0);U+9391(0,9); +U+9392(0);U+9392(3,9); +U+9393(0);U+9393(0); +U+9394(0);U+9394(0,9);U+7194(2,8,9),U+9555(4,8) +U+9395(0);U+9395(0,9); +U+9396(0);U+9396(0,9);U+93C1(3,8),U+9501(1,3,8) +U+9397(0);U+9397(0,9); +U+9398(0);U+9398(0,9);U+9549(1,3,8) +U+9399(0);U+9399(0,9);U+77DF(4) +U+939A(0);U+939A(0,9);U+9524(2),U+9318(0,1,2,3,8,9) +U+939B(0);U+939B(0,9);U+9548(4,8),U+93C4(4,8,9),U+946E(3,4,8,9) +U+939D(0);U+939D(0,9); +U+939E(0);U+939E(3,9); +U+939F(0);U+939F(0,9); +U+93A1(0);U+93A1(0,9);U+9543(1,3,8) +U+93A2(0);U+93A2(0,9);U+94A8(1,3,8) +U+93A3(0);U+93A3(4,9);U+84E5(4,8) +U+93A4(0);U+93A4(0,9); +U+93A5(0);U+93A5(0,9); +U+93A6(0);U+93A6(0,9);U+954F(1,3,8) +U+93A7(0);U+93A7(0,9);U+94E0(1,3,8) +U+93A8(0);U+93A8(0,9); +U+93A9(0);U+93A9(0,9);U+94E9(1,3,8) +U+93AA(0);U+93AA(0,9);U+953C(1,3,8) +U+93AC(0);U+93AC(0,9);U+9550(1,3,8) +U+93AD(0);U+93AE(3,8,9);U+93AE(3,8,9),U+9547(3) +U+93AE(0);U+93AE(0,9);U+93AD(3,8),U+9547(1,3,8) +U+93AF(0);U+93AF(0,9); +U+93B0(0);U+93B0(0,9);U+9552(1,3,8),U+8CF9(0,1,3,8,9) +U+93B1(0);U+93B1(0,9); +U+93B2(0);U+93B2(0,9);U+954B(4),U+9482(1,3,4,8,9) +U+93B3(0);U+93B3(0,9);U+954D(1,3,8) +U+93B4(0);U+93B4(0,9); +U+93B5(0);U+93B5(0,9);U+9553(1,3,8) +U+93B6(0);U+93B6(0); +U+93B7(0);U+93B7(0,9); +U+93B8(0);U+93B8(0);U+954C(1,3,8),U+942B(1,3,4,8,9) +U+93B9(0);U+93B9(0); + +U+93BA(0);U+93BA(0); +U+93BC(0);U+93BC(0); +U+93BD(0);U+93BD(0); +U+93BE(0);U+93BE(0); +U+93BF(0);U+93BF(0);U+954E(1,3,8) +U+93C0(0);U+93C0(0,9);U+942A(3,9) +U+93C1(0);U+9396(3,8,9);U+9396(3,8,9),U+9501(3) +U+93C2(0);U+93C2(0,9); +U+93C3(0);U+93C3(0,9);U+955E(1,3,8) +U+93C4(0);U+93C4(0,9);U+9548(4),U+939B(0,4,8,9),U+946E(3,4,8,9) +U+93C5(0);U+93C5(0); +U+93C6(0);U+93C6(0); +U+93C7(0);U+93C7(0,9);U+65CB(1,3,4,9),U+955F(4,8) +U+93C8(0);U+93C8(0,9);U+94FE(1,3,8) +U+93C9(0);U+93C9(3); +U+93CA(0);U+93CA(5,9); +U+93CB(0);U+93CB(0); +U+93CC(0);U+93CC(0,9);U+9546(4,8) +U+93CD(0);U+93CD(0,9);U+9559(4,8) +U+93CE(0);U+93CE(0,9);U+6BD5(3),U+7562(1,3,8,9),U+7F7C(3,9) +U+93CF(0);U+93CF(3,9); +U+93D0(0);U+93D0(0,9);U+9560(4,8) +U+93D1(0);U+93D1(0,9);U+955D(1,3,8) +U+93D2(0);U+93D2(0,9); +U+93D3(0);U+93D3(3); +U+93D4(0);U+93D4(0,9); +U+93D5(0);U+93D5(0,9); +U+93D6(0);U+93D6(5,9); +U+93D7(0);U+93D7(0,9);U+94FF(1,3,8),U+935E(0,1,3,8,9) +U+93D8(0);U+93D8(0,9);U+9535(1,3,8) +U+93D9(0);U+93D9(0,9); +U+93DA(0);U+93DA(3,9); +U+93DB(0);U+93DB(0); +U+93DC(0);U+93DC(0,9);U+9557(1,3,8) +U+93DD(0);U+93DD(0,9);U+9558(1,3,8) +U+93DE(0);U+93DE(0,9);U+955B(1,3,8) +U+93DF(0);U+93DF(0,9);U+5257(4,8),U+5277(2,3,8,9),U+94F2(1,3,8),U+522C(1,3,4,8) +U+93E1(0);U+93E1(0,9);U+955C(1,3,8) +U+93E2(0);U+93E2(0,9);U+9556(1,3,8) +U+93E3(0);U+93E3(0,9); +U+93E4(0);U+93E4(0,9);U+9542(1,3,8) +U+93E6(0);U+93E6(0,9); +U+93E7(0);U+93E7(0,9); +U+93E8(0);U+93E8(0,9);U+933E(1,3,8) +U+93E9(0);U+93E9(0); +U+93EA(0);U+93EA(0); +U+93EB(0);U+93EB(0); +U+93EC(0);U+93EC(0,9);U+7F45(4,9) +U+93ED(0);U+93ED(0); +U+93EE(0);U+93EE(0,9); +U+93EF(0);U+93EF(0); +U+93F0(0);U+930B(4,9);U+930B(4,9),U+955A(1,3) +U+93F1(0);U+93F1(0); +U+93F2(0);U+93F2(0); +U+93F4(0);U+93F4(0); +U+93F5(0);U+93F5(0,9);U+94E7(1,3,8) +U+93F6(0);U+93F6(3,9); +U+93F7(0);U+93F7(0,9);U+9564(1,3,8) +U+93F8(0);U+93F8(0,9); +U+93F9(0);U+93F9(0,9);U+956A(1,3,8) +U+93FA(0);U+93FA(0,9);U+497D(1,3) +U+93FB(0);U+93FB(0,9); +U+93FC(0);U+93FC(0,9); + +U+93FD(0);U+93FD(0,9);U+92B9(2,3,8,9),U+9508(4,8) +U+93FE(0);U+93FE(0,9); +U+93FF(0);U+93FF(0,9); +U+9400(0);U+9400(3,9);U+532E(7),U+5331(1,3,7,8,9) +U+9401(0);U+9401(3); +U+9403(0);U+9403(0,9);U+94D9(1,3,8) +U+9404(0);U+9404(0); +U+9405(0);U+9405(0); +U+9406(0);U+9406(4,9); +U+9407(0);U+9407(0,9); +U+9408(0);U+9408(0); +U+9409(0);U+9409(0,9);U+94BB(4),U+9246(0,4,9),U+947D(1,3,4,8,9) +U+940A(0);U+940A(0,9);U+9496(3),U+935A(0,1,3,9) +U+940B(0);U+940B(0,9);U+94F4(4,8) +U+940C(0);U+940C(0,9); +U+940D(0);U+940D(0,9); +U+940E(0);U+940E(3,9); +U+940F(0);U+940F(0,9); +U+9410(0);U+9410(0,9);U+9563(1,3,8) +U+9411(0);U+9411(0,9);U+9532(3),U+9365(0,1,3,8,9) +U+9412(0);U+9412(0,9);U+94F9(1,3,8) +U+9413(0);U+9413(0,9);U+9566(1,3,8) +U+9414(0);U+9414(0,9);U+9561(4,8) +U+9415(0);U+9415(3,9); +U+9416(0);U+9416(0,9); +U+9418(0);U+9418(0,9);U+9221(4),U+937E(3,8,9),U+949F(1,3,8),U+87A4(0,1,3,8,9),U+953A(1,3,4,8) + +U+9419(0);U+9419(0,9);U+956B(1,3,8) +U+941B(0);U+941B(0); +U+941D(0);U+941D(0);U+9562(1,3,8) +U+9420(0);U+9420(0,9);U+9568(1,3,8) +U+9422(0);U+9422(0); +U+9423(0);U+9423(0); +U+9425(0);U+9425(0);U+4985(1,3) +U+9426(0);U+9426(0);U+950E(1,3,8) +U+9427(0);U+9427(0);U+950F(1,3,8) +U+9428(0);U+9428(0,9);U+9544(1,3,8) +U+9429(0);U+9429(0,9); +U+942A(0);U+942A(3,9);U+93C0(3,9) +U+942B(0);U+942B(0,9);U+954C(4),U+93B8(0,1,3,4,8) +U+942C(0);U+942C(0,9); +U+942D(0);U+942D(0); +U+942E(0);U+942E(0,9);U+5286(3,8),U+9570(1,3,8),U+938C(2,3,8,9) +U+942F(0);U+942F(0);U+4983(1,3) +U+9430(0);U+9430(0,9); +U+9431(0);U+9431(0,9);U+5251(3),U+5263(3),U+528D(1,3,8,9),U+5292(3,4),U+5294(3) +U+9432(0);U+9432(0,9);U+956F(1,3,8) +U+9433(0);U+9433(0,9);U+956D(1,3,8) +U+9434(0);U+9434(3); +U+9435(0);U+9435(0,9);U+9295(3,8,9),U+94C1(1,3,8) +U+9436(0);U+9436(0,9);U+956E(1,3,8) +U+9437(0);U+9437(0,9);U+9371(3,9) +U+9438(0);U+9438(0,9);U+94CE(1,3,8) +U+9439(0);U+9439(3,9); +U+943A(0);U+943A(0,9);U+94DB(1,3,8) +U+943B(0);U+943B(0,9); +U+943C(0);U+943C(0,9); +U+943D(0);U+943D(0,9); +U+943E(0);U+943E(5); +U+943F(0);U+943F(0,9);U+9571(1,3,8) +U+9440(0);U+9440(0,9); +U+9441(0);U+9441(0); +U+9442(0);U+9442(0); + +U+9444(0);U+9444(0,9);U+92F3(4,8),U+94F8(1,3,8) +U+9445(0);U+9445(0,9); +U+9446(0);U+9446(0,9); +U+9447(0);U+9447(0,9); +U+9448(0);U+9448(3,9); +U+9449(0);U+9449(0,9); +U+944A(0);U+944A(0,9);U+956C(1,3,8) +U+944B(0);U+944B(0,9); +U+944C(0);U+944C(0,9);U+9554(1,3,8) +U+944D(0);U+944D(0); +U+944F(0);U+944F(0,9); +U+9450(0);U+9450(0,9); +U+9451(0);U+9451(0,9);U+9274(4),U+9452(2,3,8,9) +U+9452(0);U+9452(0,9);U+9274(1,3,8),U+9451(2,3,8,9) +U+9453(0);U+9453(0); +U+9454(0);U+9454(0);U+9572(1,3,8) +U+9455(0);U+9455(0,9);U+9527(1,3,8) +U+9456(0);U+9456(0); +U+9457(0);U+9457(3,9); +U+9458(0);U+9458(0); +U+9459(0);U+9459(0); +U+945B(0);U+7926(3,8,9);U+77FF(4),U+7926(3,8,9) +U+945C(0);U+945C(4); +U+945D(0);U+945D(0,9); +U+945E(0);U+945E(0,9);U+9574(1,3,8) +U+945F(0);U+945F(0); +U+9460(0);U+9460(0,9);U+94C4(1,3,8) +U+9461(0);U+9461(0); +U+9462(0);U+9462(3,9); +U+9463(0);U+9463(0,9);U+9573(1,3,8) +U+9464(0);U+9464(0,9);U+5228(2,3,9) +U+9465(0);U+9465(0);U+9565(1,3,8) +U+9466(0);U+9466(0); +U+9467(0);U+9467(0); +U+9468(0);U+9468(0,9);U+783B(3),U+7931(1,3,8,9) +U+9469(0);U+9469(0,9); +U+946A(0);U+946A(0,9);U+7089(4),U+7210(1,3,4,8,9) +U+946B(0);U+946B(5,9); +U+946D(0);U+946D(0,9);U+9567(1,3,8) +U+946E(0);U+946E(0,9);U+9548(3),U+939B(0,3,4,8,9),U+93C4(3,4,8,9) +U+946F(0);U+946F(0,9);U+5C16(4,9) +U+9470(0);U+9470(0,9);U+94A5(1,3,8),U+9205(0,1,3,4,8,9) +U+9471(0);U+9471(0,9);U+9575(4,8) +U+9472(0);U+9472(0,9);U+9576(1,3,8) +U+9473(0);U+9473(0,9);U+952E(3),U+9375(0,1,3,8,9) +U+9474(0);U+9474(0,9); +U+9475(0);U+9475(0,9);U+7F50(2,3,8,9) +U+9476(0);U+9476(0,9); +U+9477(0);U+9477(0,9);U+954A(1,3,8) +U+9478(0);U+9478(0,9); +U+9479(0);U+9479(0);U+9569(1,3,8) +U+947A(0);U+947A(0); +U+947C(0);U+947C(0,9);U+9523(1,3,8) +U+947D(0);U+947D(0,9);U+94BB(1,3,8),U+9246(0,1,3,4,8,9),U+9409(1,3,4,8,9) +U+947E(0);U+947E(0,9);U+92AE(1,3,8) +U+947F(0);U+947F(0,9);U+51FF(1,3,8) +U+9480(0);U+9480(0,9); +U+9481(0);U+9481(0,9);U+4986(1,3) +U+9482(0);U+9482(0,9);U+954B(1,3,8),U+93B2(0,1,3,4,8,9) +U+9483(0);U+9483(0,9); +U+9484(0);U+9484(0); +U+9485(0);U+91D1(8,9);U+91D1(8,9),U+91D2(4,8) +U+9486(0);U+91D3(1,3,8,9);U+91D3(1,3,8,9) + +U+9487(0);U+91D4(1,3,8,9);U+91D4(1,3,8,9) +U+9488(0);U+91DD(1,3,8,9);U+91DD(1,3,8,9) +U+9489(0);U+91D8(1,3,8,9);U+91D8(1,3,8,9) +U+948A(0);U+91D7(1,3,8,9);U+91D7(1,3,8,9) +U+948B(0);U+91D9(1,3,8,9);U+91D9(1,3,8,9) +U+948C(0);U+91D5(1,3,8,9);U+91D5(1,3,8,9) +U+948D(0);U+91F7(1,3,8,9);U+91F7(1,3,8,9) +U+948E(0);U+91FA(1,3,8);U+91FA(1,3,8) +U+948F(0);U+91E7(1,3,8,9);U+91E7(1,3,8,9) +U+9490(0);U+91E4(1,3,8,9);U+91E4(1,3,8,9) +U+9491(0);U+9212(4,8,9);U+9212(4,8,9) +U+9492(0);U+91E9(1,3,8,9);U+91E9(1,3,8,9) +U+9493(0);U+91E3(1,8,9);U+91E3(1,8,9),U+9B61(4,9) +U+9494(0);U+9346(1,3,8,9);U+9346(1,3,8,9) +U+9495(0);U+91F9(1,3,8,9);U+91F9(1,3,8,9) +U+9496(0);U+935A(1,3,9);U+935A(1,3,9),U+940A(3,9) +U+9497(0);U+91F5(1,3,8,9);U+91F5(1,3,8,9) +U+9498(0);U+9203(1,3,8,9);U+9203(1,3,8,9) +U+9499(0);U+9223(1,3,8,9);U+9223(1,3,8,9) +U+949A(0);U+9208(1,3,8);U+9208(1,3,8) +U+949B(0);U+9226(1,3,8,9);U+9226(1,3,8,9) +U+949C(0);U+9245(4,8,9);U+9245(4,8,9),U+5DE8(2,3,4,5,8,9) +U+949D(0);U+920D(1,3,8,9);U+920D(1,3,8,9) +U+949E(0);U+9214(1,3,8,9);U+9214(1,3,8,9) +U+949F(0);U+937E(1,3,8,9),U+9418(1,3,8,9);U+87A4(3,9),U+9221(4),U+937E(1,3,8,9),U+9418(1,3,8,9),U+953A(1,3,4,8) + +U+94A0(0);U+9209(1,3,8,9);U+9209(1,3,8,9) +U+94A1(0);U+92C7(1,3,8,9);U+92C7(1,3,8,9) +U+94A2(0);U+92FC(1,3,8,9);U+92FC(1,3,8,9) +U+94A3(0);U+9211(4,8,9);U+9211(4,8,9) +U+94A4(0);U+9210(1,3,8,9);U+9210(1,3,8,9) +U+94A5(0);U+9470(1,3,8,9);U+9205(4,9),U+9470(1,3,8,9) +U+94A6(0);U+6B3D(1,3,8,9);U+6B3D(1,3,8,9) +U+94A7(0);U+921E(1,3,8,9);U+921E(1,3,8,9) +U+94A8(0);U+93A2(1,3,8,9);U+93A2(1,3,8,9) +U+94A9(0);U+9264(4,8,9);U+920E(1,3,8),U+9264(4,8,9) +U+94AA(0);U+9227(1,3,8,9);U+9227(1,3,8,9) +U+94AB(0);U+9201(1,3,8,9);U+9201(1,3,8,9) +U+94AC(0);U+9225(1,3,8,9);U+9225(1,3,8,9) +U+94AD(0);U+9204(1,3,8,9);U+9204(1,3,8,9) +U+94AE(0);U+9215(1,3,8,9);U+9215(1,3,8,9) +U+94AF(0);U+9200(1,3,8,9);U+9200(1,3,8,9) +U+94B0(0);U+923A(1,3,8,9);U+923A(1,3,8,9) +U+94B1(0);U+9322(1,3,8,9);U+92AD(3),U+9322(1,3,8,9) +U+94B2(0);U+9266(1,3,8,9);U+9266(1,3,8,9) +U+94B3(0);U+9257(1,3,8,9);U+62D1(4,9),U+9257(1,3,8,9),U+7B9D(1,3,5,8,9) +U+94B4(0);U+9237(1,3,8,9);U+9237(1,3,8,9) +U+94B5(0);U+7F3D(4,8,9);U+7F3D(4,8,9),U+9262(1,3,8) +U+94B6(0);U+9233(1,3,8,9);U+9233(1,3,8,9) +U+94B7(0);U+9255(1,3,8);U+9255(1,3,8) +U+94B8(0);U+923D(4,8,9);U+923D(4,8,9) +U+94B9(0);U+9238(1,8,9);U+9238(1,8,9) +U+94BA(0);U+925E(1,3,8,9);U+925E(1,3,8,9) +U+94BB(0);U+947D(1,3,8,9);U+947D(1,3,8,9),U+9246(4,9),U+9409(4,9) +U+94BC(0);U+926C(1,3,8,9);U+926C(1,3,8,9) +U+94BD(0);U+926D(1,3,8,9);U+926D(1,3,8,9) +U+94BE(0);U+9240(1,3,8,9);U+9240(1,3,8,9) +U+94BF(0);U+923F(1,3,8,9);U+923F(1,3,8,9) +U+94C0(0);U+923E(1,3,8,9);U+923E(1,3,8,9) +U+94C1(0);U+9435(1,3,8,9);U+9295(3,9),U+9435(1,3,8,9) +U+94C2(0);U+9251(1,3,8,9);U+9251(1,3,8,9) +U+94C3(0);U+9234(1,3,8,9);U+9234(1,3,8,9) +U+94C4(0);U+9460(1,3,8,9);U+9460(1,3,8,9) + +U+94C5(0);U+925B(1,3,8,9);U+9206(2,9),U+925B(1,3,8,9) +U+94C6(0);U+925A(1,3,8,9);U+925A(1,3,8,9) +U+94C7(0);U+924B(4,8,9);U+924B(4,8,9) +U+94C8(0);U+9230(1,3,8,9);U+9230(1,3,8,9) +U+94C9(0);U+9249(1,3,8,9);U+9249(1,3,8,9) +U+94CA(0);U+9248(1,3,8,9);U+9248(1,3,8,9) +U+94CB(0);U+924D(1,3,8,9);U+924D(1,3,8,9) +U+94CC(0);U+922E(1,3,8,9);U+922E(1,3,8,9) +U+94CD(0);U+9239(1,3,8,9);U+9239(1,3,8,9) +U+94CE(0);U+9438(1,3,8,9);U+9438(1,3,8,9) +U+94CF(0);U+9276(1,3,8,9);U+9276(1,3,8,9) +U+94D0(0);U+92AC(1,3,8,9);U+92AC(1,3,8,9) +U+94D1(0);U+92A0(1,3,8,9);U+92A0(1,3,8,9) +U+94D2(0);U+927A(1,3,8,9);U+927A(1,3,8,9) +U+94D3(0);U+92E9(1,3,8,9);U+92E9(1,3,8,9) +U+94D4(0);U+930F(4,8,9);U+930F(4,8,9) +U+94D5(0);U+92AA(1,3,8,9);U+92AA(1,3,8,9) +U+94D6(0);U+92EE(4,8,9);U+92EE(4,8,9) +U+94D7(0);U+92CF(1,3,8,9);U+92CF(1,3,8,9) +U+94D8(0);U+92E3(4,8);U+92E3(4,8) +U+94D9(0);U+9403(1,3,8,9);U+9403(1,3,8,9) +U+94DA(0);U+928D(4,8,9);U+928D(4,8,9) +U+94DB(0);U+943A(1,3,8,9);U+943A(1,3,8,9) +U+94DC(0);U+9285(1,3,8,9);U+9285(1,3,8,9) +U+94DD(0);U+92C1(1,3,8,9);U+92C1(1,3,8,9) +U+94DE(0);U+92B1(1,3,8);U+92B1(1,3,8) +U+94DF(0);U+92A6(1,3,8,9);U+92A6(1,3,8,9) +U+94E0(0);U+93A7(1,3,8,9);U+93A7(1,3,8,9) +U+94E1(0);U+9358(1,3,8,9);U+9358(1,3,8,9) +U+94E2(0);U+9296(1,3,8,9);U+9296(1,3,8,9) +U+94E3(0);U+9291(1,3,8,9);U+9291(1,3,8,9) +U+94E4(0);U+92CC(1,3,8,9);U+92CC(1,3,8,9) +U+94E5(0);U+92A9(1,3,8,9);U+92A9(1,3,8,9) +U+94E6(0);U+929B(4,8,9);U+929B(4,8,9) +U+94E7(0);U+93F5(1,3,8,9);U+93F5(1,3,8,9) +U+94E8(0);U+9293(1,3,8,9);U+9293(1,3,8,9) +U+94E9(0);U+93A9(1,3,8,9);U+93A9(1,3,8,9) +U+94EA(0);U+927F(1,3,8,9);U+927F(1,3,8,9) +U+94EB(0);U+929A(1,3,8,9);U+929A(1,3,8,9) +U+94EC(0);U+927B(1,3,8,9);U+927B(1,3,8,9) +U+94ED(0);U+9298(1,3,8,9);U+9298(1,3,8,9) +U+94EE(0);U+931A(1,3,8,9);U+931A(1,3,8,9) +U+94EF(0);U+92AB(1,3,8,9);U+92AB(1,3,8,9) +U+94F0(0);U+9278(1,3,8,9);U+9278(1,3,8,9) +U+94F1(0);U+92A5(1,3,8,9);U+92A5(1,3,8,9) +U+94F2(0);U+93DF(1,3,8,9);U+5257(4),U+5277(4,9),U+93DF(1,3,8,9),U+522C(1,3,4,8) +U+94F3(0);U+9283(1,3,8,9);U+9283(1,3,8,9) +U+94F4(0);U+940B(4,8,9);U+940B(4,8,9) +U+94F5(0);U+92A8(1,3,8,9);U+92A8(1,3,8,9) +U+94F6(0);U+9280(1,3,8,9);U+9280(1,3,8,9) +U+94F7(0);U+92A3(1,3,8,9);U+92A3(1,3,8,9) +U+94F8(0);U+9444(1,3,8,9);U+92F3(4),U+9444(1,3,8,9) +U+94F9(0);U+9412(1,3,8,9);U+9412(1,3,8,9) +U+94FA(0);U+92EA(1,3,8,9),U+8216(4,9);U+8216(4,9),U+92EA(1,3,8,9) +U+94FB(0);U+92D9(4,8,9);U+92D9(4,8,9) +U+94FC(0);U+9338(1,3,8,9);U+9338(1,3,8,9) +U+94FD(0);U+92F1(1,3,8,9);U+92F1(1,3,8,9) +U+94FE(0);U+93C8(1,3,8,9);U+93C8(1,3,8,9) +U+94FF(0);U+93D7(1,3,8,9);U+935E(3,9),U+93D7(1,3,8,9) +U+9500(0);U+92B7(1,3,8,9);U+92B7(1,3,8,9) +U+9501(0);U+9396(1,3,8,9);U+9396(1,3,8,9),U+93C1(3) +U+9502(0);U+92F0(1,3,8,9);U+92F0(1,3,8,9) +U+9503(0);U+92E5(1,3,8);U+92E5(1,3,8) + +U+9504(0);U+92E4(1,3,8,9);U+8021(4,9),U+92E4(1,3,8,9) +U+9505(0);U+934B(1,3,8,9);U+934B(1,3,8,9) +U+9506(0);U+92EF(1,3,8,9);U+92EF(1,3,8,9) +U+9507(0);U+92E8(1,3,8,9);U+92E8(1,3,8,9) +U+9508(0);U+93FD(4,8,9);U+92B9(1,3,8,9),U+93FD(4,8,9) +U+9509(0);U+92BC(1,3,8,9);U+92BC(1,3,8,9) +U+950A(0);U+92DD(4,8,9);U+92DD(4,8,9) +U+950B(0);U+92D2(1,3,8,9);U+92D2(1,3,8,9) +U+950C(0);U+92C5(1,3,8,9);U+92C5(1,3,8,9) +U+950D(0);U+92F6(4,8);U+92F6(4,8) +U+950E(0);U+9426(1,3,8);U+9426(1,3,8) +U+950F(0);U+9427(1,3,8);U+9427(1,3,8) +U+9510(0);U+92B3(4,8,9);U+92B3(4,8,9),U+92ED(1,3,8) +U+9511(0);U+92BB(1,3,8,9);U+92BB(1,3,8,9) +U+9512(0);U+92C3(1,3,8,9);U+92C3(1,3,8,9) +U+9513(0);U+92DF(1,3,8,9);U+92DF(1,3,8,9) +U+9514(0);U+92E6(1,3,8,9);U+92E6(1,3,8,9) +U+9515(0);U+9312(1,3,8,9);U+9312(1,3,8,9) +U+9516(0);U+9306(4,8,9);U+9306(4,8,9) +U+9517(0);U+937A(1,3,8,9);U+937A(1,3,8,9) +U+9518(0);U+9369(1,3,8);U+9369(1,3,8) +U+9519(0);U+932F(1,3,8,9);U+932F(1,3,8,9) +U+951A(0);U+9328(1,3,8,9);U+9328(1,3,8,9) +U+951B(0);U+931B(1,3,8,9);U+931B(1,3,8,9) +U+951C(0);U+9321(4,8,9);U+9321(4,8,9) +U+951D(0);U+9340(1,3,8);U+9340(1,3,8) +U+951E(0);U+9301(1,3,8,9);U+9301(1,3,8,9) +U+951F(0);U+9315(1,3,8,9);U+9315(1,3,8,9) +U+9520(0);U+9329(4,8,9);U+9329(4,8,9) +U+9521(0);U+932B(1,3,8,9);U+932B(1,3,8,9) +U+9522(0);U+932E(1,3,8,9);U+932E(1,3,8,9) +U+9523(0);U+947C(1,3,8,9);U+947C(1,3,8,9) +U+9524(0);U+9318(1,3,8,9);U+9318(1,3,8,9),U+939A(2,9) +U+9525(0);U+9310(1,3,8,9);U+9310(1,3,8,9) +U+9526(0);U+9326(1,3,8,9);U+9326(1,3,8,9) +U+9527(0);U+9455(1,3,8,9);U+9455(1,3,8,9) +U+9528(0);U+9341(1,3,8);U+9341(1,3,8) +U+9529(0);U+9308(4,8,9);U+9308(4,8,9) +U+952A(0);U+9343(4,8);U+9343(4,8) +U+952B(0);U+9307(1,3,8);U+9307(1,3,8) +U+952C(0);U+931F(4,8,9);U+931F(4,8,9) +U+952D(0);U+9320(1,3,8,9);U+9320(1,3,8,9) +U+952E(0);U+9375(1,3,8,9);U+9375(1,3,8,9),U+9473(3,9) +U+952F(0);U+92F8(1,3,8,9);U+92F8(1,3,8,9) +U+9530(0);U+9333(1,3,8,9);U+9333(1,3,8,9) +U+9531(0);U+9319(1,3,8,9);U+9319(1,3,8,9) +U+9532(0);U+9365(1,3,8,9);U+9365(1,3,8,9),U+9411(3,9) +U+9533(0);U+9348(4,8);U+9348(4,8) +U+9534(0);U+9347(1,3,8,9);U+9347(1,3,8,9) +U+9535(0);U+93D8(1,3,8,9);U+93D8(1,3,8,9) +U+9536(0);U+9376(1,3,8,9);U+9376(1,3,8,9) +U+9537(0);U+9354(1,3,8,9);U+9354(1,3,8,9) +U+9538(0);U+9364(1,3,8,9);U+81FF(4,9),U+9364(1,3,8,9) +U+9539(0);U+936C(1,3,8,9);U+936C(1,3,8,9) +U+953A(0);U+937E(4,8,9);U+937E(4,8,9),U+9221(0,1,3,4,8),U+9418(1,3,4,8,9),U+949F(1,3,4,8),U+87A4(0,1,3,4,8,9) + +U+953B(0);U+935B(1,3,8,9);U+935B(1,3,8,9),U+7145(1,3,5,8) +U+953C(0);U+93AA(1,3,8,9);U+93AA(1,3,8,9) +U+953D(0);U+9360(4,8,9);U+9360(4,8,9) +U+953E(0);U+9370(1,3,8,9);U+9370(1,3,8,9) +U+953F(0);U+9384(1,3,8);U+9384(1,3,8) +U+9540(0);U+934D(1,3,8,9);U+934D(1,3,8,9) +U+9541(0);U+9382(1,3,8,9);U+9382(1,3,8,9) + +U+9542(0);U+93E4(1,3,8,9);U+93E4(1,3,8,9) +U+9543(0);U+93A1(1,3,8,9);U+93A1(1,3,8,9) +U+9544(0);U+9428(1,3,8,9);U+9428(1,3,8,9) +U+9545(0);U+9387(1,3,8);U+9387(1,3,8) +U+9546(0);U+93CC(4,8,9);U+93CC(4,8,9) +U+9547(0);U+93AE(1,3,8,9);U+93AD(3),U+93AE(1,3,8,9) +U+9548(0);U+939B(4,8,9);U+939B(4,8,9),U+93C4(4,9),U+946E(3,9) +U+9549(0);U+9398(1,3,8,9);U+9398(1,3,8,9) +U+954A(0);U+9477(1,3,8,9);U+9477(1,3,8,9) +U+954B(0);U+9482(1,3,8,9);U+93B2(4,9),U+9482(1,3,8,9) +U+954C(0);U+93B8(1,3,8);U+93B8(1,3,8),U+942B(4,9) +U+954D(0);U+93B3(1,3,8,9);U+93B3(1,3,8,9) +U+954E(0);U+93BF(1,3,8);U+93BF(1,3,8) +U+954F(0);U+93A6(1,3,8,9);U+93A6(1,3,8,9) +U+9550(0);U+93AC(1,3,8,9);U+93AC(1,3,8,9) +U+9551(0);U+938A(1,3,8,9);U+938A(1,3,8,9) +U+9552(0);U+93B0(1,3,8,9);U+8CF9(3,9),U+93B0(1,3,8,9) +U+9553(0);U+93B5(1,3,8,9);U+93B5(1,3,8,9) +U+9554(0);U+944C(1,3,8,9);U+944C(1,3,8,9) +U+9555(0);U+9394(4,8,9);U+9394(4,8,9),U+7194(2,4,5,8,9) +U+9556(0);U+93E2(1,3,8,9);U+93E2(1,3,8,9) +U+9557(0);U+93DC(1,3,8,9);U+93DC(1,3,8,9) +U+9558(0);U+93DD(1,3,8,9);U+93DD(1,3,8,9) +U+9559(0);U+93CD(4,8,9);U+93CD(4,8,9) +U+955A(0);U+930B(4,8,9);U+930B(4,8,9),U+93F0(1,3) +U+955B(0);U+93DE(1,3,8,9);U+93DE(1,3,8,9) +U+955C(0);U+93E1(1,3,8,9);U+93E1(1,3,8,9) +U+955D(0);U+93D1(1,3,8,9);U+93D1(1,3,8,9) +U+955E(0);U+93C3(1,3,8,9);U+93C3(1,3,8,9) +U+955F(0);U+93C7(4,8,9);U+93C7(4,8,9),U+65CB(1,3,4,8,9) +U+9560(0);U+93D0(4,8,9);U+93D0(4,8,9) +U+9561(0);U+9414(4,8,9);U+9414(4,8,9) +U+9562(0);U+941D(1,3,8);U+941D(1,3,8) +U+9563(0);U+9410(1,3,8,9);U+9410(1,3,8,9) +U+9564(0);U+93F7(1,3,8,9);U+93F7(1,3,8,9) +U+9565(0);U+9465(1,3,8);U+9465(1,3,8) +U+9566(0);U+9413(1,3,8,9);U+9413(1,3,8,9) +U+9567(0);U+946D(1,3,8,9);U+946D(1,3,8,9) +U+9568(0);U+9420(1,3,8,9);U+9420(1,3,8,9) +U+9569(0);U+9479(1,3,8);U+9479(1,3,8) +U+956A(0);U+93F9(1,3,8,9);U+93F9(1,3,8,9) +U+956B(0);U+9419(1,3,8,9);U+9419(1,3,8,9) +U+956C(0);U+944A(1,3,8,9);U+944A(1,3,8,9) +U+956D(0);U+9433(1,3,8,9);U+9433(1,3,8,9) +U+956E(0);U+9436(1,3,8,9);U+9436(1,3,8,9) +U+956F(0);U+9432(1,3,8,9);U+9432(1,3,8,9) +U+9570(0);U+942E(1,3,8,9);U+5286(3),U+938C(2,3,9),U+942E(1,3,8,9) +U+9571(0);U+943F(1,3,8,9);U+943F(1,3,8,9) +U+9572(0);U+9454(1,3,8);U+9454(1,3,8) +U+9573(0);U+9463(1,3,8,9);U+9463(1,3,8,9) +U+9574(0);U+945E(1,3,8,9);U+945E(1,3,8,9) +U+9575(0);U+9471(4,8,9);U+9471(4,8,9) +U+9576(0);U+9472(1,3,8,9);U+9472(1,3,8,9) +U+9577(0);U+9577(0,9);U+957F(1,3,8) +U+957A(0);U+957A(0,9); +U+957B(0);U+957B(0,9); +U+957C(0);U+957C(0,9); +U+957D(0);U+957D(0,9); +U+957F(0);U+9577(1,3,8,9);U+9577(1,3,8,9) +U+9580(0);U+9580(0,9);U+95E8(1,3,8) +U+9581(0);U+9581(0); +U+9582(0);U+9582(0,9);U+95E9(1,3,8) +U+9583(0);U+9583(0,9);U+95EA(1,3,8) + +U+9584(0);U+9584(0); +U+9586(0);U+9586(0,9);U+95EB(4,8),U+95BB(4,9),U+960E(1,3,4,8) +U+9587(0);U+9589(3,8,9);U+9589(3,8,9),U+95ED(3) +U+9588(0);U+9588(0,9);U+95EC(4,8) +U+9589(0);U+9589(0,9);U+9587(3,8),U+95ED(1,3,8) +U+958A(0);U+958A(0); +U+958B(0);U+958B(0,9);U+5F00(1,3,8) +U+958C(0);U+958C(0,9);U+95F6(4,8) +U+958D(0);U+958D(0,9); +U+958E(0);U+958E(0,9);U+95F3(4,8) +U+958F(0);U+958F(0,9);U+95F0(1,3,8) +U+9590(0);U+9590(0,9); +U+9591(0);U+9591(0,9);U+95F2(1,3,8) +U+9592(0);U+9592(0,9); +U+9593(0);U+9593(0,9);U+95F4(1,3,8) +U+9594(0);U+9594(0,9);U+95F5(1,3,8) +U+9595(0);U+9595(0); +U+9596(0);U+9596(0); +U+9598(0);U+9598(0,9);U+95F8(1,3,8) +U+9599(0);U+9B27(2,3,8,9);U+95F9(4),U+9B27(2,3,8,9) +U+959A(0);U+959A(0); +U+959B(0);U+959B(0,9); +U+959C(0);U+959C(3,9); +U+959D(0);U+959D(0); +U+959E(0);U+959E(0,9);U+5173(3),U+95A2(3),U+95D7(3),U+95DC(1,3,8,9) +U+959F(0);U+959F(0,9); +U+95A1(0);U+95A1(0,9);U+9602(1,3,8) +U+95A2(0);U+95DC(3,8,9);U+5173(3),U+95DC(3,8,9),U+959E(3,9),U+95D7(3) +U+95A3(0);U+95A3(0,9);U+9601(1,3,8) +U+95A4(0);U+95A4(0,9);U+5408(1,3,8,9),U+6546(1,3,8,9) +U+95A5(0);U+95A5(0,9);U+9600(1,3,8) +U+95A6(0);U+95A6(0); +U+95A7(0);U+9B28(3,9);U+54C4(2,8,9),U+9B28(3,9) +U+95A8(0);U+95A8(0,9);U+95FA(1,3,8) +U+95A9(0);U+95A9(0,9);U+95FD(1,3,8) +U+95AA(0);U+95AA(0); +U+95AB(0);U+95AB(0,9);U+9603(1,3,8) +U+95AC(0);U+95AC(0,9);U+9606(1,3,8) +U+95AD(0);U+95AD(0,9);U+95FE(1,3,8) +U+95AE(0);U+95AE(0,9); +U+95AF(0);U+95AF(0); +U+95B0(0);U+95B0(0,9); +U+95B1(0);U+95B1(0,9);U+95B2(8),U+9605(4,8) +U+95B2(0);U+95B1(8,9);U+95B1(8,9),U+9605(1,3,8) +U+95B5(0);U+95B5(0,9); +U+95B6(0);U+95B6(0,9);U+960A(1,3,8) +U+95B7(0);U+95B7(0,9);U+6740(3),U+6BBA(1,3,8,9) +U+95B9(0);U+95B9(0,9);U+9609(1,3,8) +U+95BA(0);U+95BA(0,9); +U+95BB(0);U+95BB(0,9);U+95EB(3,8),U+9586(4,9),U+960E(1,3,8) +U+95BC(0);U+95BC(0,9);U+960F(1,3,8) +U+95BD(0);U+95BD(0,9);U+960D(1,3,8) +U+95BE(0);U+95BE(0,9);U+9608(1,3,8) +U+95BF(0);U+95BF(0,9);U+960C(1,3,8) +U+95C0(0);U+95C0(0,9); +U+95C2(0);U+95C2(0); +U+95C3(0);U+95C3(0,9);U+9612(1,3,8) +U+95C4(0);U+95C4(0); +U+95C5(0);U+95C5(3,9); +U+95C6(0);U+95C6(0,9);U+677F(1,3,8,9) +U+95C7(0);U+95C7(0,9);U+6697(2,8,9),U+667B(0,2,3,8,9) +U+95C8(0);U+95C8(0,9);U+95F1(1,3,8) +U+95C9(0);U+95C9(0,9); + +U+95CA(0);U+95CA(0,9);U+6FF6(2,3,8),U+9614(1,3,8) +U+95CB(0);U+95CB(0,9);U+9615(1,3,8) +U+95CC(0);U+95CC(0,9);U+9611(1,3,8) +U+95CD(0);U+95CD(0,9);U+9607(4,8) +U+95CE(0);U+95CE(0); +U+95CF(0);U+95CF(0); +U+95D0(0);U+95D0(0,9);U+9617(1,3,8) +U+95D1(0);U+95D1(3,9); +U+95D2(0);U+95D2(0,9);U+9618(4,8) +U+95D3(0);U+95D3(0,9);U+95FF(1,3,8) +U+95D4(0);U+95D4(0,9);U+9616(1,3,8) +U+95D5(0);U+95D5(0,9);U+9619(1,3,8) +U+95D6(0);U+95D6(0,9);U+95EF(1,3,8) +U+95D7(0);U+95DC(3,8,9);U+5173(3),U+95DC(3,8,9),U+959E(3,9),U+95A2(3) +U+95D8(0);U+9B25(4,8,9);U+6597(4,9),U+9B25(4,8,9),U+9B2D(3),U+9B26(4),U+9B2A(4),U+9B2C(3,4) + +U+95DA(0);U+95DA(0,9);U+7AA5(2,3),U+7ABA(1,2,3,8,9) +U+95DB(0);U+95DB(0,9); +U+95DC(0);U+95DC(0,9);U+5173(1,3,8),U+95A2(3,8),U+95D7(3,8),U+959E(1,3,8,9) +U+95DE(0);U+95DE(0,9);U+961A(1,3,8),U+9B2B(1,3,8,9) +U+95DF(0);U+95DF(0,9); +U+95E0(0);U+95E0(0,9);U+9613(4,8) +U+95E1(0);U+95E1(0,9);U+9610(1,3,8),U+705B(0,1,3,8,9) +U+95E2(0);U+95E2(0,9);U+8F9F(1,3,9),U+907F(1,3,4,8,9) +U+95E3(0);U+95E3(0,9); +U+95E4(0);U+95E4(0,9);U+961B(4,8) +U+95E5(0);U+95E5(0,9);U+95FC(1,3,8) +U+95E6(0);U+95E6(0); +U+95E7(0);U+95E7(0); +U+95E8(0);U+9580(1,3,8,9);U+9580(1,3,8,9) +U+95E9(0);U+9582(1,3,8,9);U+9582(1,3,8,9) +U+95EA(0);U+9583(1,3,8,9);U+9583(1,3,8,9) +U+95EB(0);U+9586(4,8,9);U+9586(4,8,9),U+95BB(3,8,9),U+960E(1,3,4,8) +U+95EC(0);U+9588(4,8,9);U+9588(4,8,9) +U+95ED(0);U+9589(1,3,8,9);U+9587(3),U+9589(1,3,8,9) +U+95EE(0);U+554F(1,3,8,9);U+554F(1,3,8,9) +U+95EF(0);U+95D6(1,3,8,9);U+95D6(1,3,8,9) +U+95F0(0);U+958F(1,3,8,9);U+958F(1,3,8,9) +U+95F1(0);U+95C8(1,3,8,9);U+95C8(1,3,8,9) +U+95F2(0);U+9591(1,3,8,9);U+9591(1,3,8,9) +U+95F3(0);U+958E(4,8,9);U+958E(4,8,9) +U+95F4(0);U+9593(1,3,8,9);U+9593(1,3,8,9) +U+95F5(0);U+9594(1,3,8,9);U+9594(1,3,8,9) +U+95F6(0);U+958C(4,8,9);U+958C(4,8,9) +U+95F7(0);U+60B6(1,3,8,9);U+60B6(1,3,8,9) +U+95F8(0);U+9598(1,3,8,9);U+9598(1,3,8,9) +U+95F9(0);U+9B27(1,3,8,9);U+9599(4),U+9B27(1,3,8,9) +U+95FA(0);U+95A8(1,3,8,9);U+95A8(1,3,8,9) +U+95FB(0);U+805E(1,3,8,9);U+805E(1,3,8,9) +U+95FC(0);U+95E5(1,3,8,9);U+95E5(1,3,8,9) +U+95FD(0);U+95A9(1,3,8,9);U+95A9(1,3,8,9) +U+95FE(0);U+95AD(1,3,8,9);U+95AD(1,3,8,9) +U+95FF(0);U+95D3(1,3,8,9);U+95D3(1,3,8,9) +U+9600(0);U+95A5(1,3,8,9);U+95A5(1,3,8,9) +U+9601(0);U+95A3(1,3,8,9);U+95A3(1,3,8,9) +U+9602(0);U+95A1(1,3,8,9);U+95A1(1,3,8,9) +U+9603(0);U+95AB(1,3,8,9);U+95AB(1,3,8,9) +U+9604(0);U+9B2E(1,3,8,9);U+9B2E(1,3,8,9) +U+9605(0);U+95B1(4,8,9);U+95B1(4,8,9),U+95B2(1,3,8) +U+9606(0);U+95AC(1,3,8,9);U+95AC(1,3,8,9) +U+9607(0);U+95CD(4,8,9);U+95CD(4,8,9) +U+9608(0);U+95BE(1,3,8,9);U+95BE(1,3,8,9) +U+9609(0);U+95B9(1,3,8,9);U+95B9(1,3,8,9) + +U+960A(0);U+95B6(1,3,8,9);U+95B6(1,3,8,9) +U+960B(0);U+9B29(1,3,8,9);U+9B29(1,3,8,9) +U+960C(0);U+95BF(1,3,8,9);U+95BF(1,3,8,9) +U+960D(0);U+95BD(1,3,8,9);U+95BD(1,3,8,9) +U+960E(0);U+95BB(1,3,8,9);U+95BB(1,3,8,9),U+95EB(1,3,4,8),U+9586(0,1,3,4,8,9) +U+960F(0);U+95BC(1,3,8,9);U+95BC(1,3,8,9) +U+9610(0);U+95E1(1,3,8,9);U+705B(3,9),U+95E1(1,3,8,9) +U+9611(0);U+95CC(1,3,8,9);U+95CC(1,3,8,9) +U+9612(0);U+95C3(1,3,8,9);U+95C3(1,3,8,9) +U+9613(0);U+95E0(4,8,9);U+95E0(4,8,9) +U+9614(0);U+95CA(1,3,8,9);U+6FF6(4),U+95CA(1,3,8,9) +U+9615(0);U+95CB(1,3,8,9);U+95CB(1,3,8,9) +U+9616(0);U+95D4(1,3,8,9);U+95D4(1,3,8,9) +U+9617(0);U+95D0(1,3,8,9);U+95D0(1,3,8,9) +U+9618(0);U+95D2(4,8,9);U+95D2(4,8,9) +U+9619(0);U+95D5(1,3,8,9);U+95D5(1,3,8,9) +U+961A(0);U+95DE(1,3,8,9);U+95DE(1,3,8,9),U+9B2B(3,9) +U+961B(0);U+95E4(4,8,9);U+95E4(4,8,9) +U+961C(0);U+961C(5,9);U+5CCA(3,9),U+961D(3,8) +U+961D(0);U+961D(5);U+961C(3,8,9),U+5CCA(0,3,8,9) +U+961E(0);U+961E(0,9); +U+961F(0);U+968A(1,3,8,9);U+968A(1,3,8,9) +U+9620(0);U+9620(0,9); +U+9621(0);U+9621(5,9); +U+9622(0);U+9622(5,9); +U+9623(0);U+9623(0,9);U+5C79(3,9) +U+9624(0);U+9624(3,9); +U+9627(0);U+9627(0); +U+9628(0);U+9628(0,9);U+5384(2,8,9) +U+962A(0);U+962A(5,9);U+5742(3,8) +U+962B(0);U+962B(3); +U+962C(0);U+962C(0,9);U+5751(2,3,8,9) +U+962D(0);U+962D(0,9); +U+962E(0);U+962E(5,9); +U+962F(0);U+962F(0,9);U+5740(2,3,8,9) +U+9630(0);U+9630(0,9); +U+9631(0);U+9631(5,9);U+7A7D(2,3,8) +U+9632(0);U+9632(5,9); +U+9633(0);U+967D(1,3,8,9);U+967D(1,3,8,9),U+661C(3,9) +U+9634(0);U+9670(1,3,8,9);U+9670(1,3,8,9),U+9712(4,9),U+9720(4,9) +U+9635(0);U+9663(1,3,8,9);U+9663(1,3,8,9) +U+9636(0);U+968E(1,3,8,9);U+968E(1,3,8,9),U+5826(4) +U+9637(0);U+9637(0); +U+9638(0);U+9638(3); +U+9639(0);U+9639(0,9); +U+963A(0);U+963A(0,9); +U+963B(0);U+963B(5,9); +U+963C(0);U+963C(5,9); +U+963D(0);U+963D(5,9); +U+963F(0);U+963F(5,9); +U+9640(0);U+9640(5,9); +U+9641(0);U+9641(0); +U+9642(0);U+9642(5,9); +U+9643(0);U+9643(0,9); +U+9644(0);U+9644(5,9);U+577F(2,3) +U+9645(0);U+969B(1,3,8,9);U+969B(1,3,8,9) +U+9646(0);U+9678(1,3,8,9);U+5774(3,9),U+9678(1,3,8,9) +U+9647(0);U+96B4(1,3,8,9);U+96B4(1,3,8,9) +U+9648(0);U+9673(1,3,8,9);U+9673(1,3,8,9),U+6576(3,9) +U+9649(0);U+9658(1,3,8,9);U+9658(1,3,8,9) +U+964A(0);U+964A(3,9); +U+964B(0);U+964B(5,9); +U+964C(0);U+964C(5,9); + +U+964D(0);U+964D(5,9); +U+964E(0);U+964E(0,9); +U+964F(0);U+964F(0,9); +U+9650(0);U+9650(5,9); +U+9651(0);U+9651(3,9); +U+9652(0);U+9652(0); +U+9653(0);U+9653(0,9); +U+9654(0);U+9654(5,9);U+5793(3,8,9) +U+9655(0);U+965D(1,8,9);U+965D(1,8,9),U+965C(4,9) +U+9658(0);U+9658(0,9);U+9649(1,3,8) +U+9659(0);U+9659(0); +U+965A(0);U+965A(0); +U+965B(0);U+965B(5,9); +U+965C(0);U+965C(0,9);U+9655(4),U+965D(1,4,8,9) +U+965D(0);U+965D(0,9);U+9655(1,8),U+965C(1,4,8,9) +U+965E(0);U+965E(0,9);U+5347(2,3,8,9),U+6607(2,3,8,9) +U+965F(0);U+965F(5,9); +U+9660(0);U+9660(0); +U+9661(0);U+9661(5,9); +U+9662(0);U+9662(5,9); +U+9663(0);U+9663(0,9);U+9635(1,3,8) +U+9664(0);U+9664(5,9); +U+9666(0);U+9666(0); +U+9667(0);U+9689(3,4,8,9);U+9689(3,4,8,9) +U+9668(0);U+9695(1,3,8,9);U+9695(1,3,8,9) +U+9669(0);U+96AA(1,3,8,9);U+7906(3),U+96AA(1,3,8,9),U+7877(1,3,4),U+9E7C(1,3,4,8,9),U+78B1(1,3,4,8) +U+966A(0);U+966A(5,9); +U+966B(0);U+966B(0,9); +U+966C(0);U+966C(5,9); +U+966D(0);U+966D(3,9); +U+966E(0);U+966E(0); +U+966F(0);U+966F(3,9); +U+9670(0);U+9670(0,9);U+9634(1,3,8),U+9712(1,3,4,8,9),U+9720(1,3,4,8,9) +U+9671(0);U+9671(0,9);U+97A0(3,9) +U+9672(0);U+9672(5,9); +U+9673(0);U+9673(0,9);U+9648(1,3,8),U+6576(0,1,3,8,9) +U+9674(0);U+9674(5,9); +U+9675(0);U+9675(5,9);U+740C(4,9) +U+9676(0);U+9676(5,9);U+530B(4,9) +U+9677(0);U+9677(5,9); +U+9678(0);U+9678(0,9);U+9646(1,3,8),U+5774(0,1,3,8,9) +U+967C(0);U+967C(0,9); +U+967D(0);U+967D(0,9);U+661C(3,8,9),U+9633(1,3,8) +U+967E(0);U+967E(4,9); +U+9680(0);U+9680(0,9); +U+9683(0);U+9683(0,9); +U+9684(0);U+9684(0,9);U+5824(2,3,9) +U+9685(0);U+9685(5,9); +U+9686(0);U+9686(5,9); +U+9687(0);U+9687(0,9); +U+9688(0);U+9688(5,9); +U+9689(0);U+9689(3,9);U+9667(3,4,8) +U+968A(0);U+968A(0,9);U+961F(1,3,8) +U+968B(0);U+968B(5,9); +U+968D(0);U+968D(5,9); +U+968E(0);U+968E(0,9);U+5826(2,3,8),U+9636(1,3,8) +U+968F(0);U+96A8(1,3,8,9);U+96A8(1,3,8,9) +U+9690(0);U+96B1(1,3,8,9);U+96A0(3),U+96B1(1,3,8,9) +U+9691(0);U+9691(0,9); +U+9692(0);U+9692(0,9); +U+9693(0);U+9693(0,9);U+96B3(3,9) +U+9694(0);U+9694(5,9); + +U+9695(0);U+9695(0,9);U+9668(1,3,8) +U+9697(0);U+9697(5,9); +U+9698(0);U+9698(5,9); +U+9699(0);U+9699(5,9);U+90C4(3,8) +U+969B(0);U+969B(0,9);U+9645(1,3,8) +U+969C(0);U+969C(5,9);U+5887(3,9) +U+969E(0);U+969E(0,9);U+6556(3,9) +U+96A0(0);U+96B1(3,8,9);U+9690(3),U+96B1(3,8,9) +U+96A1(0);U+96A1(0,9); +U+96A2(0);U+96A2(0,9); +U+96A3(0);U+9130(2,3,8,9);U+90BB(4),U+9130(2,3,8,9) +U+96A4(0);U+96A4(3,9); +U+96A5(0);U+96A5(3); +U+96A6(0);U+96A6(0); +U+96A7(0);U+96A7(5,9); +U+96A8(0);U+96A8(0,9);U+968F(1,3,8) +U+96A9(0);U+96A9(0,9); +U+96AA(0);U+96AA(0,9);U+9669(1,3,8),U+7877(3,4),U+7906(3,8),U+9E7C(1,3,4,8,9),U+78B1(1,3,4,8) + +U+96AC(0);U+96AC(0,9); +U+96AD(0);U+96AD(0); +U+96AE(0);U+96AE(0,9); +U+96B0(0);U+96B0(5,9); +U+96B1(0);U+96B1(0,9);U+9690(1,3,8),U+96A0(3,8) +U+96B3(0);U+96B3(5,9);U+9693(3,9) +U+96B4(0);U+96B4(0,9);U+9647(1,3,8) +U+96B6(0);U+96B8(1,3,8,9);U+96B7(4),U+96B8(1,3,8,9) +U+96B7(0);U+96B8(2,3,8,9);U+96B6(4),U+96B8(2,3,8,9) +U+96B8(0);U+96B8(0,9);U+96B6(1,3,8),U+96B7(2,3,8) +U+96B9(0);U+96B9(5,9); +U+96BA(0);U+96BA(0); +U+96BB(0);U+96BB(0,9);U+53EA(1,3,8,9),U+8879(1,3,4,8,9) +U+96BC(0);U+96BC(5,9); +U+96BD(0);U+96CB(2,3,8,9);U+96CB(2,3,8,9) +U+96BE(0);U+96E3(1,3,8,9);U+96E3(1,3,8,9) +U+96BF(0);U+96BF(0,9);U+5F0B(3,9) +U+96C0(0);U+96C0(5,9); +U+96C1(0);U+96C1(5,9);U+9CEB(3,8),U+9D08(2,3,8,9) +U+96C2(0);U+96C2(3,9); +U+96C3(0);U+96C3(0,9); +U+96C4(0);U+96C4(5,9); +U+96C5(0);U+96C5(5,9); +U+96C6(0);U+96C6(5,9); +U+96C7(0);U+96C7(5,9),U+50F1(2,3,9);U+50F1(2,3,9) +U+96C8(0);U+96C8(0,9); +U+96C9(0);U+96C9(5,9);U+9D19(3,9) +U+96CA(0);U+96CA(3,9); +U+96CB(0);U+96CB(0,9);U+96BD(2,3,8) +U+96CC(0);U+96CC(5,9); +U+96CD(0);U+96CD(5,9);U+96DD(2,3,9) +U+96CE(0);U+96CE(5,9); +U+96CF(0);U+96DB(1,3,8,9);U+96DB(1,3,8,9),U+9DB5(3,9) +U+96D0(0);U+96D0(0); +U+96D1(0);U+96DC(3,8,9);U+6742(3),U+96DC(3,8,9),U+96E5(3,9) +U+96D2(0);U+96D2(5,9); +U+96D3(0);U+96D3(0,9); +U+96D4(0);U+96D4(0,9); +U+96D5(0);U+96D5(5,9);U+5F6B(2,8,9),U+7431(2,3,8,9),U+9D70(2,3,8,9) +U+96D6(0);U+96D6(0,9);U+867D(1,3,8) +U+96D7(0);U+96D7(0,9); +U+96D8(0);U+96D8(3,9); +U+96D9(0);U+96D9(0,9);U+53CC(1,3,8) +U+96DA(0);U+96DA(0,9); + +U+96DB(0);U+96DB(0,9);U+96CF(1,3,8),U+9DB5(1,3,8,9) +U+96DC(0);U+96DC(0,9);U+6742(1,3,8),U+96D1(3,8),U+96E5(1,3,8,9) +U+96DD(0);U+96DD(0,9);U+96CD(2,3,9) +U+96DE(0);U+96DE(0,9);U+9CEE(8),U+9DC4(2,3,4,8),U+9E21(4,8) +U+96DF(0);U+96DF(4,9); +U+96E0(0);U+8B8E(1,3,8,9);U+8B8E(1,3,8,9),U+8B90(7),U+4EC7(1,3,5,8,9) +U+96E1(0);U+96E1(0,9); +U+96E2(0);U+96E2(0,9);U+79BB(1,3,8,9) +U+96E3(0);U+96E3(0,9);U+96BE(1,3,8) +U+96E5(0);U+96E5(0,9);U+6742(3),U+96D1(3),U+96DC(1,3,8,9) +U+96E8(0);U+96E8(5,9); +U+96E9(0);U+96E9(5,9); +U+96EA(0);U+96EA(5,9); +U+96EB(0);U+96EB(0); +U+96EC(0);U+96EC(0); +U+96ED(0);U+96ED(0); +U+96EE(0);U+96EE(0); +U+96EF(0);U+96EF(5,9); +U+96F0(0);U+96F0(0,9);U+6C1B(2,3,9) +U+96F1(0);U+96F1(3,9); +U+96F2(0);U+96F2(0,9);U+4E91(1,3,8,9) +U+96F3(0);U+9742(1,3,8,9);U+9742(1,3,8,9) +U+96F4(0);U+96F4(0); +U+96F5(0);U+96F5(0,9); +U+96F6(0);U+96F6(5,9); +U+96F7(0);U+96F7(5,9); +U+96F8(0);U+96F8(0,9); +U+96F9(0);U+96F9(5,9); +U+96FA(0);U+96FA(0,9); +U+96FB(0);U+96FB(0,9);U+7535(1,3,8) +U+96FD(0);U+96FD(0,9); +U+96FE(0);U+9727(1,3,8,9);U+9727(1,3,8,9) +U+96FF(0);U+96FF(0,9); +U+9700(0);U+9700(5,9); +U+9701(0);U+973D(1,3,8,9);U+973D(1,3,8,9) +U+9702(0);U+9702(0,9); +U+9703(0);U+9703(0); +U+9704(0);U+9704(5,9); +U+9705(0);U+9705(0,9); +U+9706(0);U+9706(5,9); +U+9707(0);U+9707(5,9);U+8AAB(3,9) +U+9708(0);U+9708(5,9); +U+9709(0);U+9709(1,3,9),U+9EF4(1,3,4,9);U+9EF4(1,3,4,9) +U+970A(0);U+9748(3,8,9);U+7075(3),U+9748(3,8,9) +U+970B(0);U+970B(0,9); +U+970C(0);U+970C(0); +U+970D(0);U+970D(5,9);U+7668(7,8) +U+970E(0);U+970E(5,9); +U+970F(0);U+970F(5,9); +U+9710(0);U+9710(0,9); +U+9711(0);U+9711(0,9);U+6CBE(2,3,9) +U+9712(0);U+9712(0,9);U+9634(4),U+9670(1,3,4,8,9),U+9720(4,9) +U+9713(0);U+9713(5,9);U+86EA(3,9),U+873A(2,3,8,9) +U+9715(0);U+9715(0); +U+9716(0);U+9716(5,9); +U+9718(0);U+9718(0,9); +U+9719(0);U+9719(0,9); +U+971C(0);U+971C(5,9); +U+971D(0);U+971D(0,9); +U+971E(0);U+971E(5,9);U+8D6E(3,9) +U+971F(0);U+971F(0,9); +U+9720(0);U+9720(0,9);U+9634(4),U+9670(1,3,4,8,9),U+9712(4,9) +U+9721(0);U+9721(0); + +U+9722(0);U+9722(3,9); +U+9723(0);U+9723(0,9); +U+9724(0);U+9724(3,9); +U+9725(0);U+9725(0,9); +U+9726(0);U+9726(0,9); +U+9727(0);U+9727(0,9);U+96FE(1,3,8) +U+9728(0);U+9728(0,9); +U+9729(0);U+9729(0,9);U+5ED3(3,9) +U+972A(0);U+972A(5,9); +U+972B(0);U+972B(3,9); +U+972C(0);U+972C(0,9); +U+972D(0);U+9744(1,3,8,9);U+9744(1,3,8,9) +U+972E(0);U+972E(0,9); +U+972F(0);U+972F(0,9); +U+9730(0);U+9730(5,9); +U+9731(0);U+9731(0); +U+9732(0);U+9732(5,9); +U+9735(0);U+9735(0,9); +U+9736(0);U+9736(0); +U+9738(0);U+9738(5,9);U+8987(2,3,8) +U+9739(0);U+9739(5,9); +U+973A(0);U+973A(0,9);U+6EA6(3,9) +U+973B(0);U+973B(0); +U+973C(0);U+973C(0); +U+973D(0);U+973D(0,9);U+9701(1,3,8) +U+973E(0);U+973E(5,9); +U+973F(0);U+973F(3,9); +U+9742(0);U+9742(0,9);U+96F3(1,3,8) +U+9743(0);U+9743(0,9); +U+9744(0);U+9744(0,9);U+972D(1,3,8) +U+9745(0);U+9745(0); +U+9746(0);U+9746(0,9);U+53C7(1,3,8) +U+9747(0);U+9747(0,9); +U+9748(0);U+9748(0,9);U+970A(3,8),U+7075(1,3,8) +U+9749(0);U+9749(0,9);U+53C6(1,3,8) +U+974A(0);U+974A(0); +U+974B(0);U+974B(0,9); +U+974C(0);U+974C(0); +U+974E(0);U+974E(0); +U+974F(0);U+974F(0); +U+9750(0);U+9750(0); +U+9751(0);U+9752(4,8,9);U+9752(4,8,9) +U+9752(0);U+9752(5,9);U+9751(4,8) +U+9753(0);U+975A(1,3,8,9);U+975A(1,3,8,9) +U+9754(0);U+975D(4,8);U+975D(4,8) +U+9755(0);U+9755(0); +U+9756(0);U+9756(5,9); +U+9758(0);U+9758(0,9); +U+9759(0);U+975C(4,8,9);U+975C(4,8,9) +U+975A(0);U+975A(0,9);U+9753(1,3,8) +U+975B(0);U+975B(5,9); +U+975C(0);U+975C(0,9);U+9759(4,8) +U+975D(0);U+975D(0);U+9754(4,8) +U+975E(0);U+975E(5,9); +U+975F(0);U+975F(0); +U+9760(0);U+9760(5,9); +U+9761(0);U+9761(5,9); +U+9762(0);U+9762(1,3,9),U+9EB5(1,3,8,9);U+9EAA(4),U+9EB5(1,3,8,9) +U+9765(0);U+9768(1,3,8,9);U+9768(1,3,8,9) +U+9766(0);U+9766(0,9); +U+9767(0);U+9767(0); +U+9768(0);U+9768(0,9);U+9765(1,3,8) +U+9769(0);U+9769(5,9); + +U+976A(0);U+976A(0,9); +U+976B(0);U+976B(0); +U+976C(0);U+976C(0,9); +U+976D(0);U+97CC(2,3,8,9);U+97CC(2,3,8,9),U+97E7(4),U+8095(0,3,4,9) +U+976E(0);U+976E(0,9); +U+976F(0);U+976F(0); +U+9770(0);U+9770(0,9); +U+9772(0);U+9772(0,9); +U+9773(0);U+9773(5,9); +U+9774(0);U+9774(5,9); +U+9776(0);U+9776(5,9); +U+9777(0);U+9777(3,9); +U+9778(0);U+9778(4,9); +U+9779(0);U+9779(0); +U+977A(0);U+977A(0,9); +U+977B(0);U+977B(0,9);U+977C(4,9) +U+977C(0);U+977C(5,9);U+977B(4,9) +U+977D(0);U+977D(0,9); +U+977E(0);U+977E(0,9); +U+977F(0);U+977F(0,9); +U+9780(0);U+9780(0,9);U+9F17(3) +U+9781(0);U+9781(0,9); +U+9782(0);U+9782(0,9);U+79F8(4,9),U+7A2D(2,4) +U+9783(0);U+9783(0,9); +U+9784(0);U+9784(0,9); +U+9785(0);U+9785(5,9); +U+9786(0);U+9786(0); +U+9788(0);U+9788(0,9); +U+978A(0);U+978A(0,9); +U+978B(0);U+978B(5,9); +U+978C(0);U+978D(2,3,8,9);U+978D(2,3,8,9) +U+978D(0);U+978D(5,9);U+978C(2,3,8) +U+978E(0);U+978E(0,9); +U+978F(0);U+978F(0,9);U+5DE9(1,3,8) +U+9790(0);U+9790(0); +U+9791(0);U+97C3(1,3,8,9);U+97C3(1,3,8,9) +U+9792(0);U+97BD(1,3,8);U+97BD(1,3,8),U+6A47(1,3,5,8,9),U+6A4B(1,3,8,9),U+6865(1,3,8) + +U+9793(0);U+9793(0); +U+9794(0);U+9794(5,9); +U+9795(0);U+9795(0); +U+9796(0);U+9796(0); +U+9797(0);U+9797(0,9); +U+9798(0);U+9798(5,9); +U+9799(0);U+9799(0,9); +U+979A(0);U+979A(0,9); +U+979C(0);U+979C(0,9); +U+979D(0);U+979D(0,9); +U+979E(0);U+979E(3,9); +U+979F(0);U+979F(3); +U+97A0(0);U+97A0(5,9);U+9671(3,9) +U+97A1(0);U+97A1(0,9); +U+97A2(0);U+97A2(0,9); +U+97A3(0);U+97A3(5,9); +U+97A4(0);U+97A4(0,9);U+5E2E(4),U+5E47(4),U+5E5A(3,4),U+5E6B(1,3,4,8,9),U+7E0D(3,4,9) + +U+97A5(0);U+97A5(0,9); +U+97A6(0);U+97A6(0,9);U+79CB(1,3,9),U+7A50(1,3,4,7,8),U+9F9D(1,3,4,7,8) +U+97A7(0);U+97A7(3); +U+97A8(0);U+97A8(3,9); +U+97AA(0);U+97AA(0,9); +U+97AB(0);U+97AB(5,9); +U+97AC(0);U+97AC(0,9); + +U+97AD(0);U+97AD(5,9); +U+97AE(0);U+97AE(0,9); +U+97AF(0);U+97C9(1,3,8,9);U+97C9(1,3,8,9) +U+97B2(0);U+97B2(5); +U+97B3(0);U+97B3(0,9); +U+97B4(0);U+97B4(5); +U+97B6(0);U+97B6(0,9); +U+97B7(0);U+97B7(0,9); +U+97B8(0);U+97B8(0); +U+97B9(0);U+97B9(4,9); +U+97BA(0);U+97BA(0); +U+97BB(0);U+97BB(0,9); +U+97BC(0);U+97BC(0); +U+97BD(0);U+97BD(0);U+6A4B(3,9),U+9792(1,3,8),U+6865(1,3,8),U+6A47(1,3,8,9) +U+97BF(0);U+97BF(0,9); +U+97C1(0);U+97C1(0,9);U+7F30(4),U+7E6E(0,1,3,4,8) +U+97C2(0);U+97C2(0); +U+97C3(0);U+97C3(0,9);U+9791(1,3,8) +U+97C4(0);U+97C4(0,9); +U+97C5(0);U+97C5(0,9); +U+97C6(0);U+97C6(0,9);U+5343(1,3,9),U+4EDF(1,3,4,5,8,9) +U+97C7(0);U+97C7(3,9); +U+97C8(0);U+896A(2,8,9);U+889C(4),U+896A(2,8,9),U+97E4(3) +U+97C9(0);U+97C9(0,9);U+97AF(1,3,8) +U+97CA(0);U+97CA(0); +U+97CB(0);U+97CB(0,9);U+97E6(1,3,8) +U+97CC(0);U+97CC(0,9);U+976D(2,3,8),U+97E7(1,3,8),U+8095(0,1,3,4,8,9) +U+97CD(0);U+97CD(0,9);U+97E8(1,3,8) +U+97CE(0);U+97CE(4,9); +U+97CF(0);U+97CF(0,9); +U+97D0(0);U+97D0(0,9); +U+97D1(0);U+97D1(0); +U+97D3(0);U+97D3(0,9);U+97E9(1,3,8) +U+97D4(0);U+97D4(0,9); +U+97D5(0);U+97D5(0,9); +U+97D6(0);U+97D6(0,9); +U+97D7(0);U+97D7(3,9); +U+97D8(0);U+97D8(3,9); +U+97D9(0);U+97D9(0,9);U+97EA(1,3,8) +U+97DA(0);U+97DA(0); +U+97DB(0);U+97DB(3); +U+97DC(0);U+97DC(0,9);U+97EC(1,3,8) +U+97DD(0);U+97DD(3,9); +U+97DE(0);U+97DE(0,9);U+97EB(1,3,8) +U+97DF(0);U+97DF(0,9); +U+97E0(0);U+97E0(3); +U+97E1(0);U+97E1(0,9); +U+97E2(0);U+97E2(0); +U+97E3(0);U+97E3(3,9);U+97E5(3,9) +U+97E4(0);U+896A(2,8,9);U+889C(3,4),U+896A(2,8,9),U+97C8(3) +U+97E5(0);U+97E5(0,9);U+97E3(3,9) +U+97E6(0);U+97CB(1,3,8,9);U+97CB(1,3,8,9) +U+97E7(0);U+97CC(1,3,4,8,9);U+8095(3,9),U+976D(4),U+97CC(1,3,4,8,9) +U+97E8(0);U+97CD(1,3,8,9);U+97CD(1,3,8,9) +U+97E9(0);U+97D3(1,3,8,9);U+97D3(1,3,8,9) +U+97EA(0);U+97D9(1,3,8,9);U+97D9(1,3,8,9) +U+97EB(0);U+97DE(1,3,8,9);U+97DE(1,3,8,9) +U+97EC(0);U+97DC(1,3,8,9);U+97DC(1,3,8,9) +U+97ED(0);U+97ED(5,9);U+97EE(2,3,8) +U+97EE(0);U+97ED(2,3,8,9);U+97ED(2,3,8,9) +U+97EF(0);U+97EF(0); +U+97F0(0);U+97F0(0,9); +U+97F1(0);U+97F1(3,9); + +U+97F2(0);U+9F4F(3,8,9);U+9F4F(3,8,9),U+9F51(3),U+8640(0,3,9) +U+97F3(0);U+97F3(5,9); +U+97F4(0);U+97F4(0); +U+97F5(0);U+97FB(2,3,9);U+97FB(2,3,9) +U+97F6(0);U+97F6(5,9); +U+97F7(0);U+97F7(0); +U+97F8(0);U+97F8(3,9); +U+97F9(0);U+97F9(0,9); +U+97FA(0);U+97FA(0,9); +U+97FB(0);U+97FB(0,9);U+97F5(2,3) +U+97FD(0);U+97FD(0,9); +U+97FE(0);U+97FE(0,9); +U+97FF(0);U+97FF(0,9);U+54CD(1,3,8) +U+9800(0);U+9800(3,9); +U+9801(0);U+9801(0,9);U+9875(1,3,8) +U+9802(0);U+9802(0,9);U+9876(1,3,8) +U+9803(0);U+9803(0,9);U+9877(1,3,8) +U+9804(0);U+9804(0,9); +U+9805(0);U+9805(0,9);U+9879(1,3,8) +U+9806(0);U+9806(0,9);U+987A(1,3,8) +U+9807(0);U+9807(0,9);U+9878(1,3,8) +U+9808(0);U+9808(0,9);U+987B(1,3,8),U+9B1A(3,4,9) +U+9809(0);U+9824(3,8,9);U+9824(3,8,9),U+9890(3),U+984A(3,9) +U+980A(0);U+980A(0,9);U+987C(1,3,8) +U+980B(0);U+9867(3,8,9);U+9867(3,8,9),U+987E(3) +U+980C(0);U+980C(0,9);U+9882(1,3,8) +U+980D(0);U+980D(0,9); +U+980E(0);U+980E(0,9);U+9880(1,3,8) +U+980F(0);U+980F(0,9);U+9883(1,3,8) +U+9810(0);U+9810(0,9);U+9884(1,3,8) +U+9811(0);U+9811(0,9);U+987D(1,3,8) +U+9812(0);U+9812(0,9);U+670C(3,8),U+9881(1,3,8) +U+9813(0);U+9813(0,9);U+987F(1,3,8) +U+9814(0);U+9814(0); +U+9815(0);U+9815(0); +U+9816(0);U+9816(0,9); +U+9817(0);U+9817(0,9);U+9887(1,3,8) +U+9818(0);U+9818(0,9);U+9886(1,3,8) +U+9819(0);U+9819(0); +U+981A(0);U+9838(4,8,9);U+9838(4,8,9),U+9888(4),U+9D5B(3,4,9) +U+981B(0);U+981B(0,9); +U+981C(0);U+981C(0,9);U+988C(1,3,8) +U+981D(0);U+981D(0,9); +U+981E(0);U+981E(3,9);U+9F43(3,9) +U+9820(0);U+9820(0,9); +U+9821(0);U+9821(0,9);U+9889(1,3,8) +U+9822(0);U+9822(0); +U+9823(0);U+9823(0); +U+9824(0);U+9824(0,9);U+9809(3,8),U+9890(1,3,8),U+984A(3,8,9) +U+9826(0);U+9826(0,9);U+988F(1,3,8) +U+9827(0);U+9827(0,9); +U+9828(0);U+9828(0,9); +U+9829(0);U+9829(4,9); +U+982B(0);U+982B(0,9);U+4FEF(2,3,9),U+4FDB(0,2,3,9) +U+982D(0);U+982D(0,9);U+5934(1,3,8) +U+982E(0);U+982E(0);U+9892(4,8) +U+982F(0);U+982F(3,9); +U+9830(0);U+9830(0,9);U+988A(1,3,8) +U+9831(0);U+9831(0); +U+9832(0);U+9832(0,9);U+988B(1,3,8) +U+9834(0);U+7A4E(2,8,9);U+7A4E(2,8,9),U+9895(4,8),U+9896(4) +U+9835(0);U+9835(0,9); +U+9836(0);U+9836(0); + +U+9837(0);U+9837(0,9);U+9894(1,3,8) +U+9838(0);U+9838(0,9);U+981A(4,8),U+9888(1,3,8),U+9D5B(3,4,8,9) +U+9839(0);U+9839(0,9);U+983D(4,8),U+9893(4,8),U+7A68(0,4,8,9) +U+983B(0);U+983B(0,9);U+9891(1,3,8) +U+983C(0);U+8CF4(2,3,8,9);U+8CF4(2,3,8,9),U+8D56(4) +U+983D(0);U+9839(4,8,9);U+9839(4,8,9),U+9893(1,3,8),U+7A68(0,1,3,4,8,9) +U+983F(0);U+983F(4); +U+9840(0);U+9840(0); +U+9841(0);U+9841(0,9); +U+9843(0);U+9843(0,9); +U+9844(0);U+9844(0,9); +U+9845(0);U+9845(0,9); +U+9846(0);U+9846(0,9);U+9897(1,3,8) +U+9848(0);U+9848(0,9); +U+9849(0);U+9849(3,9); +U+984A(0);U+984A(0,9);U+9890(3),U+9809(0,3),U+9824(3,8,9) +U+984C(0);U+984C(0,9);U+9898(1,3,8) +U+984D(0);U+984D(0,9);U+989D(1,3,8) +U+984E(0);U+984E(0,9);U+989A(4,8) +U+984F(0);U+984F(0,9);U+9854(8),U+989C(4,8) +U+9850(0);U+9850(0,9);U+8BE8(3),U+8AE2(0,1,3,8,9) +U+9851(0);U+9851(0,9); +U+9852(0);U+9852(0,9);U+9899(1,3,8) +U+9853(0);U+9853(0,9);U+989B(1,3,8) +U+9854(0);U+984F(8,9);U+984F(8,9),U+989C(1,3,8) +U+9855(0);U+986F(4,8,9);U+663E(4),U+986F(4,8,9) +U+9857(0);U+9857(0,9); +U+9858(0);U+9858(0,9);U+613F(1,3,8,9) +U+9859(0);U+9859(0,9);U+98A1(1,3,8) +U+985A(0);U+985B(3,8,9);U+985B(3,8,9),U+98A0(3),U+508E(0,3,9) +U+985B(0);U+985B(0,9);U+985A(3,8),U+98A0(1,3,8),U+508E(0,1,3,8,9) +U+985C(0);U+985C(0,9); +U+985D(0);U+985D(0,9); +U+985E(0);U+985E(0,9);U+7C7B(1,3,8) +U+985F(0);U+985F(0,9); +U+9860(0);U+9860(0,9); +U+9861(0);U+9861(0); +U+9862(0);U+9862(0,9);U+989F(1,3,8) +U+9863(0);U+9863(0,9);U+8E59(3,9) +U+9864(0);U+9864(0,9); +U+9865(0);U+9865(0,9);U+98A2(1,3,8) +U+9867(0);U+9867(0,9);U+980B(3,8),U+987E(1,3,8) +U+9869(0);U+9869(3,9); +U+986A(0);U+986A(3,9); +U+986B(0);U+986B(0,9);U+98A4(1,3,8) +U+986C(0);U+986C(0);U+98A5(1,3,8) +U+986D(0);U+986D(0); +U+986E(0);U+986E(0); +U+986F(0);U+986F(0,9);U+663E(1,3,8),U+9855(4,8) +U+9870(0);U+9870(0,9);U+98A6(1,3,8) +U+9871(0);U+9871(0,9);U+9885(1,3,8) +U+9872(0);U+9872(0,9); +U+9873(0);U+9873(0,9);U+989E(1,3,8) +U+9874(0);U+9874(0,9);U+98A7(1,3,8) +U+9875(0);U+9801(1,3,8,9);U+9801(1,3,8,9) +U+9876(0);U+9802(1,3,8,9);U+9802(1,3,8,9) +U+9877(0);U+9803(1,3,8,9);U+9803(1,3,8,9) +U+9878(0);U+9807(1,3,8,9);U+9807(1,3,8,9) +U+9879(0);U+9805(1,3,8,9);U+9805(1,3,8,9) +U+987A(0);U+9806(1,3,8,9);U+9806(1,3,8,9) +U+987B(0);U+9808(1,3,8,9),U+9B1A(1,8,9);U+9808(1,3,8,9),U+9B1A(1,8,9) +U+987C(0);U+980A(1,3,8,9);U+980A(1,3,8,9) +U+987D(0);U+9811(1,3,8,9);U+9811(1,3,8,9) + +U+987E(0);U+9867(1,3,8,9);U+980B(3),U+9867(1,3,8,9) +U+987F(0);U+9813(1,3,8,9);U+9813(1,3,8,9) +U+9880(0);U+980E(1,3,8,9);U+980E(1,3,8,9) +U+9881(0);U+9812(1,3,8,9);U+670C(7),U+9812(1,3,8,9) +U+9882(0);U+980C(1,3,8,9);U+980C(1,3,8,9) +U+9883(0);U+980F(1,3,8,9);U+980F(1,3,8,9) +U+9884(0);U+9810(1,3,8,9);U+9810(1,3,8,9) +U+9885(0);U+9871(1,3,8,9);U+9871(1,3,8,9) +U+9886(0);U+9818(1,3,8,9);U+9818(1,3,8,9) +U+9887(0);U+9817(1,3,8,9);U+9817(1,3,8,9) +U+9888(0);U+9838(1,3,8,9);U+981A(4),U+9838(1,3,8,9),U+9D5B(3,9) +U+9889(0);U+9821(1,3,8,9);U+9821(1,3,8,9) +U+988A(0);U+9830(1,3,8,9);U+9830(1,3,8,9) +U+988B(0);U+9832(1,3,8,9);U+9832(1,3,8,9) +U+988C(0);U+981C(1,3,8,9);U+981C(1,3,8,9) +U+988D(0);U+6F41(1,3,8,9);U+6F41(1,3,8,9) +U+988E(0);U+71B2(4,8,9);U+71B2(4,8,9) +U+988F(0);U+9826(1,3,8,9);U+9826(1,3,8,9) +U+9890(0);U+9824(1,3,8,9);U+9809(3),U+9824(1,3,8,9),U+984A(3,9) +U+9891(0);U+983B(1,3,8,9);U+983B(1,3,8,9) +U+9892(0);U+982E(4,8);U+982E(4,8) +U+9893(0);U+9839(4,8,9);U+7A68(4,9),U+9839(4,8,9),U+983D(1,3,8) +U+9894(0);U+9837(1,3,8,9);U+9837(1,3,8,9) +U+9895(0);U+7A4E(8,9);U+7A4E(8,9),U+9834(4,8),U+9896(4) +U+9896(0);U+7A4E(1,3,8,9);U+7A4E(1,3,8,9),U+9834(4),U+9895(4) +U+9897(0);U+9846(1,3,8,9);U+9846(1,3,8,9) +U+9898(0);U+984C(1,3,8,9);U+984C(1,3,8,9) +U+9899(0);U+9852(1,3,8,9);U+9852(1,3,8,9) +U+989A(0);U+984E(4,8,9);U+984E(4,8,9) +U+989B(0);U+9853(1,3,8,9);U+9853(1,3,8,9) +U+989C(0);U+984F(4,8,9);U+984F(4,8,9),U+9854(1,3,8) +U+989D(0);U+984D(1,3,8,9);U+984D(1,3,8,9) +U+989E(0);U+9873(1,3,8,9);U+9873(1,3,8,9) +U+989F(0);U+9862(1,3,8,9);U+9862(1,3,8,9) +U+98A0(0);U+985B(1,3,8,9);U+508E(3,9),U+985B(1,3,8,9),U+985A(3) +U+98A1(0);U+9859(1,3,8,9);U+9859(1,3,8,9) +U+98A2(0);U+9865(1,3,8,9);U+9865(1,3,8,9) +U+98A3(0);U+7E87(4,8,9);U+7E87(4,8,9) +U+98A4(0);U+986B(1,3,8,9);U+986B(1,3,8,9) +U+98A5(0);U+986C(1,3,8);U+986C(1,3,8) +U+98A6(0);U+9870(1,3,8,9);U+9870(1,3,8,9) +U+98A7(0);U+9874(1,3,8,9);U+9874(1,3,8,9) +U+98A8(0);U+98A8(0,9);U+51E8(3,8),U+98CE(1,3,8),U+98CC(3,8,9) +U+98A9(0);U+98A9(0,9); +U+98AA(0);U+98AA(0); +U+98AB(0);U+98AB(0); +U+98AC(0);U+98AC(0,9); +U+98AD(0);U+98AD(0,9);U+98D0(4,8) +U+98AE(0);U+98AE(0,9);U+98D1(4,8) +U+98AF(0);U+98AF(0,9);U+98D2(1,3,8) +U+98B0(0);U+98B0(0); +U+98B1(0);U+98B1(0,9);U+53F0(1,3,8,9),U+6AAF(1,3,4,8,9),U+7C49(1,3,4,8,9),U+81FA(1,3,4,8,9) + +U+98B2(0);U+98B2(0,9); +U+98B3(0);U+98B3(0,9);U+522E(1,3,8,9),U+5280(1,3,4,8,9) +U+98B4(0);U+98B4(0); +U+98B5(0);U+98B5(0); +U+98B6(0);U+98B6(0,9);U+98D3(1,3,8) +U+98B8(0);U+98B8(0,9);U+98D4(1,3,8) +U+98B9(0);U+98B9(0); +U+98BA(0);U+98BA(0,9);U+626C(4),U+63DA(2,9),U+98CF(4,8) +U+98BB(0);U+98BB(0,9);U+98D6(4,8) +U+98BC(0);U+98BC(0,9);U+98D5(1,3,8) + +U+98BD(0);U+98BD(0,9); +U+98BE(0);U+98BE(0,9); +U+98BF(0);U+98BF(0,9); +U+98C0(0);U+98C0(0,9);U+98D7(1,3,8) +U+98C1(0);U+98C1(0,9); +U+98C2(0);U+98C2(3,9); +U+98C3(0);U+98C4(2,3,8,9);U+98C4(2,3,8,9),U+98D8(4),U+65DA(0,3,4,9) +U+98C4(0);U+98C4(0,9);U+98C3(2,3,8),U+98D8(1,3,8),U+65DA(0,1,3,8,9) +U+98C5(0);U+98C5(0); +U+98C6(0);U+98C6(0,9);U+98C8(3),U+98D9(1,3,8),U+98DA(4) +U+98C8(0);U+98C6(3,9);U+98C6(3,9),U+98DA(4,8),U+98D9(1,3,8) +U+98C9(0);U+98C9(0,9); +U+98CB(0);U+98CB(0,9); +U+98CC(0);U+98CC(0,9);U+98CE(3),U+51E8(0,3),U+98A8(3,8,9) +U+98CD(0);U+98CD(0); +U+98CE(0);U+98A8(1,3,8,9);U+51E8(3),U+98A8(1,3,8,9),U+98CC(3,9) +U+98CF(0);U+98BA(4,8,9);U+626C(4),U+98BA(4,8,9),U+63DA(1,3,4,8,9) +U+98D0(0);U+98AD(4,8,9);U+98AD(4,8,9) +U+98D1(0);U+98AE(4,8,9);U+98AE(4,8,9) +U+98D2(0);U+98AF(1,3,8,9);U+98AF(1,3,8,9) +U+98D3(0);U+98B6(1,3,8,9);U+98B6(1,3,8,9) +U+98D4(0);U+98B8(1,3,8,9);U+98B8(1,3,8,9) +U+98D5(0);U+98BC(1,3,8,9);U+98BC(1,3,8,9) +U+98D6(0);U+98BB(4,8,9);U+98BB(4,8,9) +U+98D7(0);U+98C0(1,3,8,9);U+98C0(1,3,8,9) +U+98D8(0);U+98C4(1,3,8,9);U+65DA(3,9),U+98C3(4),U+98C4(1,3,8,9) +U+98D9(0);U+98C6(1,3,8,9);U+98C6(1,3,8,9),U+98C8(1,3,8),U+98DA(1,3,4,8) +U+98DA(0);U+98C6(4,9);U+98C6(4,9),U+98C8(4,8),U+98D9(1,3,4,8) +U+98DB(0);U+98DB(0,9);U+98DE(1,3,8) +U+98DC(0);U+7FFB(2,3,8,9);U+7FFB(2,3,8,9),U+7E59(0,2,3,8,9) +U+98DD(0);U+98DD(0); +U+98DE(0);U+98DB(1,3,8,9);U+98DB(1,3,8,9) +U+98DF(0);U+98DF(5,9);U+98E0(8),U+9963(8) +U+98E0(0);U+98DF(8,9);U+98DF(8,9),U+9963(4,8) +U+98E2(0);U+98E2(0,9);U+9951(3,4,9),U+9965(1,8) +U+98E3(0);U+98E3(0,9);U+9964(4,8) +U+98E5(0);U+98E5(0,9);U+9966(1,3,8) +U+98E6(0);U+98E6(0); +U+98E7(0);U+98E7(5,9); +U+98E8(0);U+9957(1,3,8,9);U+9957(1,3,8,9) +U+98E9(0);U+98E9(0,9);U+9968(1,3,8) +U+98EA(0);U+98EA(0,9);U+9901(2,3,8),U+996A(1,3,8) +U+98EB(0);U+98EB(0,9);U+996B(1,3,8),U+9947(1,3,8,9) +U+98ED(0);U+98ED(0,9);U+996C(1,3,8) +U+98EF(0);U+98EF(0,9);U+98F0(3,8),U+996D(1,3,8) +U+98F0(0);U+98EF(3,8,9);U+98EF(3,8,9),U+996D(3) +U+98F2(0);U+98F2(0,9);U+996E(1,3,8) +U+98F3(0);U+98F3(0); +U+98F4(0);U+98F4(0,9);U+9974(1,3,8) +U+98F5(0);U+98F5(0); +U+98F6(0);U+98F6(0,9); +U+98F7(0);U+98F7(0); +U+98F9(0);U+98F9(0,9);U+9971(3),U+98FD(1,3,8,9) +U+98FA(0);U+98FA(3,9); +U+98FC(0);U+98FC(0,9);U+9972(1,3,8) +U+98FD(0);U+98FD(0,9);U+9971(1,3,8),U+98F9(0,1,3,8,9) +U+98FE(0);U+98FE(0,9);U+991D(3,8),U+9970(1,3,8) +U+98FF(0);U+98FF(0);U+9973(1,3) +U+9900(0);U+9900(3,9); +U+9901(0);U+98EA(2,3,8,9);U+98EA(2,3,8,9),U+996A(4) +U+9902(0);U+9902(0,9); +U+9903(0);U+9903(0,9);U+997A(1,3,8) +U+9904(0);U+9904(0);U+9978(1,3,8) + +U+9905(0);U+9905(0,9);U+9920(3,8),U+997C(1,3,8) +U+9906(0);U+9906(0); +U+9907(0);U+9907(0,9); +U+9908(0);U+9908(0,9);U+7CCD(2) +U+9909(0);U+9909(0,9);U+9977(1,3,8),U+995F(1,2,3,8,9) +U+990A(0);U+990A(0,9);U+517B(1,3,8) +U+990B(0);U+990B(0); +U+990C(0);U+990C(0,9);U+9975(1,3,8) +U+990D(0);U+995C(1,3,8,9);U+995C(1,3,8,9) +U+990E(0);U+990E(0);U+9979(1,3,8) +U+990F(0);U+990F(0);U+997B(1,3,8) +U+9910(0);U+9910(5,9);U+55B0(3,8) +U+9911(0);U+9911(0,9);U+997D(1,3,8) +U+9912(0);U+9912(0,9);U+9981(1,3,8) +U+9913(0);U+9913(0,9);U+997F(1,3,8) +U+9914(0);U+9914(3,9); +U+9915(0);U+9915(0,9);U+9982(4,8) +U+9916(0);U+9916(0,9);U+997E(4,8) +U+9917(0);U+9917(0,9); +U+9918(0);U+9918(0,9);U+4F59(1,3,8,9),U+9980(4,8) +U+991A(0);U+991A(0,9);U+80B4(2,3,9) +U+991B(0);U+991B(0,9);U+9984(1,3,8) +U+991C(0);U+991C(0);U+9983(1,3,8) +U+991D(0);U+98FE(3,8,9);U+98FE(3,8,9),U+9970(3) +U+991E(0);U+991E(0,9);U+996F(1,3,8) +U+991F(0);U+991F(3,9); +U+9920(0);U+9905(3,8,9);U+9905(3,8,9),U+997C(3) +U+9921(0);U+9921(0,9);U+9985(1,3,8) +U+9922(0);U+9922(0); +U+9923(0);U+9923(0); +U+9924(0);U+9924(0,9); +U+9925(0);U+9925(0,9); +U+9926(0);U+9926(0); +U+9927(0);U+9927(0,9); +U+9928(0);U+9928(0,9);U+8218(2,3,8),U+9986(1,3,8) +U+9929(0);U+9929(0,9); +U+992A(0);U+992A(0,9); +U+992B(0);U+992B(0,9); +U+992C(0);U+992C(0,9);U+7CCA(2,3,9) +U+992D(0);U+992D(0,9); +U+992E(0);U+992E(5,9); +U+992F(0);U+992F(0,9); +U+9930(0);U+9930(0,9); +U+9931(0);U+9931(0,9);U+7CC7(2,3) +U+9932(0);U+9932(0,9); +U+9933(0);U+9933(0,9);U+9967(1,3,8) +U+9934(0);U+9934(0); +U+9935(0);U+9935(0,9);U+5582(4,9) +U+9936(0);U+9936(0);U+9989(1,3) +U+9937(0);U+9937(0);U+9987(1,3,8) +U+9938(0);U+9938(0); +U+9939(0);U+7CD6(2,3,8,9);U+7CD6(2,3,8,9) +U+993A(0);U+993A(0,9);U+998E(1,3,8) +U+993C(0);U+993C(0,9);U+9969(1,3,8) +U+993D(0);U+993D(0,9);U+994B(2,3,8,9),U+9988(4,8) +U+993E(0);U+993E(0,9);U+998F(1,3,8) +U+993F(0);U+993F(0,9);U+998A(1,3,8) +U+9940(0);U+9940(0); +U+9941(0);U+9941(0,9);U+998C(4,8) +U+9942(0);U+9942(0); +U+9943(0);U+9943(0,9);U+998D(1,3,8) +U+9945(0);U+9945(0,9);U+9992(1,3,8) +U+9946(0);U+9946(0); + +U+9947(0);U+9947(0,9);U+996B(3),U+98EB(0,1,3,8,9) +U+9948(0);U+9948(0,9);U+9990(1,3,8) +U+9949(0);U+9949(0,9);U+9991(1,3,8) +U+994A(0);U+994A(0);U+7CE4(3),U+9993(1,3,8) +U+994B(0);U+994B(0,9);U+993D(2,3,8,9),U+9988(1,3,8) +U+994C(0);U+994C(0,9);U+9994(1,3,8) +U+994E(0);U+994E(3,9); +U+994F(0);U+994F(0); +U+9950(0);U+9950(0,9); +U+9951(0);U+9951(0,9);U+98E2(3,4,9),U+9965(1,3,8) +U+9952(0);U+9952(0,9);U+9976(1,3,8) +U+9953(0);U+9953(0,9); +U+9954(0);U+9954(5,9); +U+9955(0);U+9955(5,9); +U+9956(0);U+9956(0,9); +U+9957(0);U+9957(0,9);U+98E8(1,3,8) +U+9958(0);U+9958(3,9); +U+9959(0);U+9959(3,9); +U+995B(0);U+995B(0,9); +U+995C(0);U+995C(0,9);U+990D(1,3,8) +U+995E(0);U+995E(0,9);U+998B(1,3,8) +U+995F(0);U+995F(0,9);U+9977(2),U+9909(0,1,2,3,8,9) +U+9960(0);U+9960(0); +U+9961(0);U+9961(0,9); +U+9962(0);U+9962(0);U+9995(1,3,8) +U+9963(0);U+98DF(8,9);U+98DF(8,9),U+98E0(4,8) +U+9964(0);U+98E3(4,8,9);U+98E3(4,8,9) +U+9965(0);U+9951(1,3,8,9);U+98E2(1,8,9),U+9951(1,3,8,9) +U+9966(0);U+98E5(1,3,8,9);U+98E5(1,3,8,9) +U+9967(0);U+9933(1,3,8,9);U+9933(1,3,8,9) +U+9968(0);U+98E9(1,3,8,9);U+98E9(1,3,8,9) +U+9969(0);U+993C(1,3,8,9);U+993C(1,3,8,9) +U+996A(0);U+98EA(1,3,8,9);U+98EA(1,3,8,9),U+9901(4) +U+996B(0);U+98EB(1,3,8,9);U+98EB(1,3,8,9),U+9947(3,9) +U+996C(0);U+98ED(1,3,8,9);U+98ED(1,3,8,9) +U+996D(0);U+98EF(1,3,8,9);U+98EF(1,3,8,9),U+98F0(3) +U+996E(0);U+98F2(1,3,8,9);U+98F2(1,3,8,9) +U+996F(0);U+991E(1,3,8,9);U+991E(1,3,8,9) +U+9970(0);U+98FE(1,3,8,9);U+98FE(1,3,8,9),U+991D(3) +U+9971(0);U+98FD(1,3,8,9);U+98F9(3,9),U+98FD(1,3,8,9) +U+9972(0);U+98FC(1,3,8,9);U+98FC(1,3,8,9) +U+9973(0);U+98FF(1,3);U+98FF(1,3) +U+9974(0);U+98F4(1,3,8,9);U+98F4(1,3,8,9) +U+9975(0);U+990C(1,3,8,9);U+990C(1,3,8,9) +U+9976(0);U+9952(1,3,8,9);U+9952(1,3,8,9) +U+9977(0);U+9909(1,3,8,9);U+9909(1,3,8,9),U+995F(2,9) +U+9978(0);U+9904(1,3,8);U+9904(1,3,8) +U+9979(0);U+990E(1,3,8);U+990E(1,3,8) +U+997A(0);U+9903(1,3,8,9);U+9903(1,3,8,9) +U+997B(0);U+990F(1,3,8);U+990F(1,3,8) +U+997C(0);U+9905(1,3,8,9);U+9905(1,3,8,9),U+9920(3) +U+997D(0);U+9911(1,3,8,9);U+9911(1,3,8,9) +U+997E(0);U+9916(4,8,9);U+9916(4,8,9) +U+997F(0);U+9913(1,3,8,9);U+9913(1,3,8,9) +U+9980(0);U+9918(4,8,9);U+9918(4,8,9),U+4F59(1,3,4,8,9) +U+9981(0);U+9912(1,3,8,9);U+9912(1,3,8,9) +U+9982(0);U+9915(4,8,9);U+9915(4,8,9) +U+9983(0);U+991C(1,3,8);U+991C(1,3,8) +U+9984(0);U+991B(1,3,8,9);U+991B(1,3,8,9) +U+9985(0);U+9921(1,3,8,9);U+9921(1,3,8,9) +U+9986(0);U+9928(1,3,8,9);U+8218(4),U+9928(1,3,8,9) +U+9987(0);U+9937(1,3,8);U+9937(1,3,8) +U+9988(0);U+994B(1,3,8,9),U+993D(4,8,9);U+993D(4,8,9),U+994B(1,3,8,9) + +U+9989(0);U+9936(1,3);U+9936(1,3) +U+998A(0);U+993F(1,3,8,9);U+993F(1,3,8,9) +U+998B(0);U+995E(1,3,8,9);U+995E(1,3,8,9) +U+998C(0);U+9941(4,8,9);U+9941(4,8,9) +U+998D(0);U+9943(1,3,8,9);U+9943(1,3,8,9) +U+998E(0);U+993A(1,3,8,9);U+993A(1,3,8,9) +U+998F(0);U+993E(1,3,8,9);U+993E(1,3,8,9) +U+9990(0);U+9948(1,3,8,9);U+9948(1,3,8,9) +U+9991(0);U+9949(1,3,8,9);U+9949(1,3,8,9) +U+9992(0);U+9945(1,3,8,9);U+9945(1,3,8,9) +U+9993(0);U+994A(1,3,8);U+7CE4(3,8),U+994A(1,3,8) +U+9994(0);U+994C(1,3,8,9);U+994C(1,3,8,9) +U+9995(0);U+9962(1,3,8);U+9962(1,3,8) +U+9996(0);U+9996(5,9); +U+9997(0);U+9997(5,9); +U+9998(0);U+9998(5,9);U+805D(4,9) +U+9999(0);U+9999(5,9); +U+999A(0);U+999A(0); +U+999B(0);U+999B(0); +U+999C(0);U+999C(0,9); +U+999D(0);U+999D(0,9); +U+999E(0);U+999E(0,9); +U+999F(0);U+999F(0); +U+99A0(0);U+99A0(0); +U+99A1(0);U+99A1(0,9); +U+99A2(0);U+99A2(0); +U+99A3(0);U+99A3(0,9); +U+99A4(0);U+99A4(0); +U+99A5(0);U+99A5(5,9); +U+99A6(0);U+99A6(0,9); +U+99A7(0);U+99A7(0,9); +U+99A8(0);U+99A8(5,9);U+99AB(3,9) +U+99A9(0);U+99A9(0); +U+99AA(0);U+99AA(0); +U+99AB(0);U+99AB(0,9);U+99A8(3,9) +U+99AC(0);U+99AC(0,9);U+9A6C(1,3,8) +U+99AD(0);U+99AD(0,9);U+9A6D(1,3,8) +U+99AE(0);U+99AE(0,9);U+51AF(1,3,8) +U+99AF(0);U+99AF(0,9); +U+99B0(0);U+99B0(0,9); +U+99B1(0);U+99B1(0,9);U+99C4(3,8),U+9A6E(1,3,8) +U+99B2(0);U+99B2(3,9); +U+99B3(0);U+99B3(0,9);U+9A70(1,3,8) +U+99B4(0);U+99B4(0,9);U+9A6F(1,3,8) +U+99B5(0);U+99B5(0,9); +U+99B6(0);U+99B6(0); +U+99B7(0);U+99B7(0); +U+99B8(0);U+99B8(0); +U+99B9(0);U+99B9(0,9);U+9A72(4,8) +U+99BA(0);U+99BA(0,9); +U+99BB(0);U+99BB(0,9); +U+99BC(0);U+99BC(0); +U+99BD(0);U+99BD(0,9);U+7D77(3),U+7E36(1,3,8,9) +U+99BE(0);U+99BE(0); +U+99C0(0);U+99C0(0); +U+99C1(0);U+99C1(0,9);U+99EE(2,8,9),U+9A73(1,3,8) +U+99C2(0);U+99C2(3,9); +U+99C3(0);U+99C3(0,9); +U+99C4(0);U+99B1(3,8,9);U+99B1(3,8,9),U+9A6E(3) +U+99C6(0);U+9A45(3,8,9);U+9A45(3,8,9),U+9A71(1),U+657A(0,1,4,9),U+99C8(1,4) +U+99C7(0);U+99C7(0,9); +U+99C8(0);U+9A45(2,3,8,9);U+9A45(2,3,8,9),U+9A71(4),U+657A(0,4,9),U+99C6(1,4) +U+99C9(0);U+99C9(4,9); + +U+99CA(0);U+99CA(0); +U+99CB(0);U+99CB(0,9); +U+99CC(0);U+99CC(0,9); +U+99CD(0);U+99CD(0,9); +U+99CE(0);U+99CE(0,9); +U+99CF(0);U+99CF(0,9); +U+99D0(0);U+99D0(0,9);U+9A7B(1,3,8) +U+99D1(0);U+99D1(0,9);U+9A7D(1,3,8) +U+99D2(0);U+99D2(0,9);U+9A79(1,3,8) +U+99D3(0);U+99D3(0,9); +U+99D4(0);U+99D4(0,9);U+9A75(1,3,8) +U+99D5(0);U+99D5(0,9);U+9A7E(1,3,8) +U+99D6(0);U+99D6(0,9); +U+99D7(0);U+99D7(0,9); +U+99D8(0);U+99D8(0,9);U+9A80(1,3,8) +U+99D9(0);U+99D9(0,9);U+9A78(1,3,8) +U+99DA(0);U+99DA(0); +U+99DB(0);U+99DB(0,9);U+9A76(1,3,8) +U+99DC(0);U+99DC(0,9); +U+99DD(0);U+99DD(0,9);U+99DE(2,3,8),U+9A7C(1,3,8) +U+99DE(0);U+99DD(2,3,8,9);U+99DD(2,3,8,9),U+9A7C(4) +U+99DF(0);U+99DF(0,9);U+9A77(1,3,8) +U+99E1(0);U+7F75(2,3,8,9);U+7F75(2,3,8,9),U+9A82(1,3,8),U+508C(0,1,3,4,8,9) +U+99E2(0);U+99E2(0,9);U+9A08(3,8),U+9A88(1,3,8) +U+99E3(0);U+99E3(0,9); +U+99E4(0);U+99E4(0,9); +U+99E5(0);U+99E5(0,9); +U+99E7(0);U+99E7(3,9); +U+99E8(0);U+99E8(0); +U+99E9(0);U+99E9(3,9); +U+99EA(0);U+99EA(0,9); +U+99EC(0);U+99EC(0,9); +U+99ED(0);U+99ED(0,9);U+9A87(1,3,8),U+99F4(1,3,8,9) +U+99EE(0);U+99EE(0,9);U+99C1(2,8,9),U+9A73(4) +U+99EF(0);U+99EF(0); +U+99F0(0);U+99F0(0,9);U+9A83(4,8) +U+99F1(0);U+99F1(0,9);U+9A86(1,3,8) +U+99F2(0);U+99F2(0); +U+99F3(0);U+99F3(0); +U+99F4(0);U+99F4(0,9);U+9A87(3),U+99ED(0,1,3,8,9) +U+99F6(0);U+99F6(0,9); +U+99F7(0);U+99F7(3,9); +U+99F8(0);U+99F8(0,9);U+9A8E(1,3,8) +U+99F9(0);U+99F9(0,9); +U+99FA(0);U+99FA(0,9); +U+99FB(0);U+99FB(3,9); +U+99FC(0);U+99FC(0,9); +U+99FD(0);U+99FD(3,9); +U+99FE(0);U+99FE(0,9); +U+99FF(0);U+99FF(0,9);U+9A8F(1,3,8) +U+9A00(0);U+9A00(0); +U+9A01(0);U+9A01(0,9);U+9A8B(1,3,8) +U+9A02(0);U+9A02(0,9);U+9A8D(4,8) +U+9A03(0);U+9A03(0,9);U+5446(2,8,9),U+7343(4,9) +U+9A04(0);U+9A04(0,9); +U+9A05(0);U+9A05(0,9);U+9A93(1,3,8) +U+9A06(0);U+9A06(0,9); +U+9A07(0);U+9A07(0,9); +U+9A08(0);U+99E2(3,8,9);U+99E2(3,8,9),U+9A88(3) +U+9A09(0);U+9A09(0,9); +U+9A0A(0);U+9A0A(0,9); +U+9A0B(0);U+9A0B(0,9); +U+9A0C(0);U+9A0C(0);U+9A23(3,9),U+9A94(4),U+9B03(2,8,9) + +U+9A0D(0);U+9A0D(0,9);U+9A92(1,3,8) +U+9A0E(0);U+9A0E(0,9);U+9A91(1,3,8) +U+9A0F(0);U+9A0F(0,9);U+9A90(1,3,8),U+9A39(1,3,8,9) +U+9A11(0);U+9A11(0,9); +U+9A14(0);U+9A14(0,9); +U+9A15(0);U+9A15(0,9); +U+9A16(0);U+9A16(0,9);U+9A9B(1,3,8) +U+9A19(0);U+9A19(0,9);U+9A97(1,3,8) +U+9A1A(0);U+9A1A(0,9); +U+9A1B(0);U+9A1B(0,9); +U+9A1C(0);U+9A1C(0,9); +U+9A1D(0);U+9A1D(0,9); +U+9A1E(0);U+9A1E(4,9); +U+9A1F(0);U+9A1F(0); +U+9A20(0);U+9A20(0,9); +U+9A21(0);U+9A21(0); +U+9A22(0);U+9A22(0,9); +U+9A23(0);U+9A23(0,9);U+9A0C(3),U+9B03(2,3,8,9),U+9A94(3,4) +U+9A24(0);U+9A24(0,9);U+9A99(4,8) +U+9A25(0);U+9A25(0,9); +U+9A26(0);U+9A26(0); +U+9A27(0);U+9A27(0,9); +U+9A29(0);U+9A29(0,9); +U+9A2A(0);U+9A2A(0,9);U+641C(3,9),U+635C(0,3,4,8) +U+9A2B(0);U+9A2B(0,9);U+9A9E(1,3,8) +U+9A2C(0);U+9A2C(0,9); +U+9A2D(0);U+9A2D(0,9);U+9A98(1,3,8) +U+9A2E(0);U+9A2E(0,9);U+9A9D(1,3,8) +U+9A2F(0);U+9A2F(0); +U+9A30(0);U+9A30(0,9);U+817E(1,3,8) +U+9A31(0);U+9A31(0,9); +U+9A32(0);U+9A32(0,9);U+8349(4,9),U+8278(0,2,3,4,9) +U+9A33(0);U+9A33(0); +U+9A34(0);U+9A34(0,9); +U+9A35(0);U+9A35(0,9); +U+9A36(0);U+9A36(0,9);U+9A7A(1,3,8) +U+9A37(0);U+9A37(0,9);U+9A9A(1,3,8) +U+9A38(0);U+9A38(0,9);U+9A9F(1,3,8) +U+9A39(0);U+9A39(0,9);U+9A90(3),U+9A0F(0,1,3,8,9) +U+9A3A(0);U+9A3A(3,9);U+9A47(4,8) +U+9A3C(0);U+9A3C(0); +U+9A3D(0);U+9A3D(0,9); +U+9A3E(0);U+9A3E(0,9);U+9AA1(1,3,8) +U+9A3F(0);U+9A3F(0,9); +U+9A40(0);U+9A40(0,9);U+84E6(1,3,8) +U+9A41(0);U+9A41(0,9);U+9A9C(1,3,8) +U+9A42(0);U+9A42(0,9);U+9A96(1,3,8) +U+9A43(0);U+9A43(0,9);U+9AA0(1,3,8) +U+9A44(0);U+9A44(0,9);U+9AA2(1,3,8) +U+9A45(0);U+9A45(0,9);U+99C6(3,8),U+99C8(2,3,8),U+9A71(1,3,8),U+657A(0,1,3,4,8,9) +U+9A46(0);U+9A46(0,9);U+8DF8(3),U+8E55(1,3,8,9) +U+9A47(0);U+9A3A(4,8,9);U+9A3A(4,8,9) +U+9A48(0);U+9A48(0,9); +U+9A49(0);U+9A49(0,9); +U+9A4A(0);U+9A4A(0,9);U+9A85(1,3,8) +U+9A4B(0);U+9A4B(0); +U+9A4C(0);U+9A4C(0,9);U+9A95(4,8) +U+9A4D(0);U+9A4D(0,9);U+9A81(1,3,8) +U+9A4E(0);U+9A4E(0,9); +U+9A4F(0);U+9A4F(0,9);U+9AA3(4,8) +U+9A50(0);U+9A50(3,9); +U+9A52(0);U+9A52(0,9); +U+9A53(0);U+9A53(3,9); + +U+9A54(0);U+9A54(0,9); +U+9A55(0);U+9A55(0,9);U+9A84(1,3,8),U+618D(0,1,3,8,9) +U+9A56(0);U+9A56(0,9); +U+9A57(0);U+9A57(0,9);U+9A8C(1,3,8) +U+9A59(0);U+9A59(0,9); +U+9A5A(0);U+9A5A(0,9);U+60CA(1,3,8,9) +U+9A5B(0);U+9A5B(0,9);U+9A7F(1,3,8) +U+9A5C(0);U+9A5C(0); +U+9A5E(0);U+9A5E(0,9); +U+9A5F(0);U+9A5F(0,9);U+9AA4(1,3,8) +U+9A60(0);U+9A60(0,9); +U+9A61(0);U+9A61(0); +U+9A62(0);U+9A62(0,9);U+9A74(1,3,8) +U+9A64(0);U+9A64(0,9);U+9AA7(1,3,8) +U+9A65(0);U+9A65(0,9);U+9AA5(1,3,8) +U+9A66(0);U+9A66(0,9);U+9AA6(4,8) +U+9A67(0);U+9A67(0,9); +U+9A68(0);U+9A68(0,9); +U+9A69(0);U+9A69(0,9);U+6B22(4),U+6B61(2,8,9),U+61FD(0,4,9),U+6B53(3,4),U+8B99(4,9) +U+9A6A(0);U+9A6A(0,9);U+9A8A(1,3,8) +U+9A6B(0);U+9A6B(0,9);U+9A89(4,8) +U+9A6C(0);U+99AC(1,3,8,9);U+99AC(1,3,8,9) +U+9A6D(0);U+99AD(1,3,8,9);U+99AD(1,3,8,9) +U+9A6E(0);U+99B1(1,3,8,9);U+99B1(1,3,8,9),U+99C4(3) +U+9A6F(0);U+99B4(1,3,8,9);U+99B4(1,3,8,9) +U+9A70(0);U+99B3(1,3,8,9);U+99B3(1,3,8,9) +U+9A71(0);U+9A45(1,3,8,9);U+657A(4,9),U+99C6(1),U+99C8(4),U+9A45(1,3,8,9) +U+9A72(0);U+99B9(4,8,9);U+99B9(4,8,9) +U+9A73(0);U+99C1(1,3,8,9);U+99C1(1,3,8,9),U+99EE(4,9) +U+9A74(0);U+9A62(1,3,8,9);U+9A62(1,3,8,9) +U+9A75(0);U+99D4(1,3,8,9);U+99D4(1,3,8,9) +U+9A76(0);U+99DB(1,3,8,9);U+99DB(1,3,8,9) +U+9A77(0);U+99DF(1,3,8,9);U+99DF(1,3,8,9) +U+9A78(0);U+99D9(1,3,8,9);U+99D9(1,3,8,9) +U+9A79(0);U+99D2(1,3,8,9);U+99D2(1,3,8,9) +U+9A7A(0);U+9A36(1,3,8,9);U+9A36(1,3,8,9) +U+9A7B(0);U+99D0(1,3,8,9);U+99D0(1,3,8,9) +U+9A7C(0);U+99DD(1,3,8,9);U+99DE(4),U+99DD(1,3,8,9) +U+9A7D(0);U+99D1(1,3,8,9);U+99D1(1,3,8,9) +U+9A7E(0);U+99D5(1,3,8,9);U+99D5(1,3,8,9) +U+9A7F(0);U+9A5B(1,3,8,9);U+9A5B(1,3,8,9) +U+9A80(0);U+99D8(1,3,8,9);U+99D8(1,3,8,9) +U+9A81(0);U+9A4D(1,3,8,9);U+9A4D(1,3,8,9) +U+9A82(0);U+7F75(4,8,9);U+508C(4,9),U+7F75(4,8,9),U+99E1(1,3,8) +U+9A83(0);U+99F0(4,8,9);U+99F0(4,8,9) +U+9A84(0);U+9A55(1,3,8,9);U+618D(3,9),U+9A55(1,3,8,9) +U+9A85(0);U+9A4A(1,3,8,9);U+9A4A(1,3,8,9) +U+9A86(0);U+99F1(1,3,8,9);U+99F1(1,3,8,9) +U+9A87(0);U+99ED(1,3,8,9);U+99ED(1,3,8,9),U+99F4(3,9) +U+9A88(0);U+99E2(1,3,8,9);U+99E2(1,3,8,9),U+9A08(3) +U+9A89(0);U+9A6B(4,8,9);U+9A6B(4,8,9) +U+9A8A(0);U+9A6A(1,3,8,9);U+9A6A(1,3,8,9) +U+9A8B(0);U+9A01(1,3,8,9);U+9A01(1,3,8,9) +U+9A8C(0);U+9A57(1,3,8,9);U+9A57(1,3,8,9) +U+9A8D(0);U+9A02(4,8,9);U+9A02(4,8,9) +U+9A8E(0);U+99F8(1,3,8,9);U+99F8(1,3,8,9) +U+9A8F(0);U+99FF(1,3,8,9);U+99FF(1,3,8,9) +U+9A90(0);U+9A0F(1,3,8,9);U+9A0F(1,3,8,9),U+9A39(3,9) +U+9A91(0);U+9A0E(1,3,8,9);U+9A0E(1,3,8,9) +U+9A92(0);U+9A0D(1,3,8,9);U+9A0D(1,3,8,9) +U+9A93(0);U+9A05(1,3,8,9);U+9A05(1,3,8,9) +U+9A94(0);U+9A0C(4);U+9A0C(4),U+9B03(4,8,9),U+9A23(3,4,9) +U+9A95(0);U+9A4C(4,8,9);U+9A4C(4,8,9) + +U+9A96(0);U+9A42(1,3,8,9);U+9A42(1,3,8,9) +U+9A97(0);U+9A19(1,3,8,9);U+9A19(1,3,8,9) +U+9A98(0);U+9A2D(1,3,8,9);U+9A2D(1,3,8,9) +U+9A99(0);U+9A24(4,8,9);U+9A24(4,8,9) +U+9A9A(0);U+9A37(1,3,8,9);U+9A37(1,3,8,9) +U+9A9B(0);U+9A16(1,3,8,9);U+9A16(1,3,8,9) +U+9A9C(0);U+9A41(1,3,8,9);U+9A41(1,3,8,9) +U+9A9D(0);U+9A2E(1,3,8,9);U+9A2E(1,3,8,9) +U+9A9E(0);U+9A2B(1,3,8,9);U+9A2B(1,3,8,9) +U+9A9F(0);U+9A38(1,3,8,9);U+9A38(1,3,8,9) +U+9AA0(0);U+9A43(1,3,8,9);U+9A43(1,3,8,9) +U+9AA1(0);U+9A3E(1,3,8,9);U+9A3E(1,3,8,9) +U+9AA2(0);U+9A44(1,3,8,9);U+9A44(1,3,8,9) +U+9AA3(0);U+9A4F(4,8,9);U+9A4F(4,8,9) +U+9AA4(0);U+9A5F(1,3,8,9);U+9A5F(1,3,8,9) +U+9AA5(0);U+9A65(1,3,8,9);U+9A65(1,3,8,9) +U+9AA6(0);U+9A66(4,8,9);U+9A66(4,8,9) +U+9AA7(0);U+9A64(1,3,8,9);U+9A64(1,3,8,9) +U+9AA8(0);U+9AA8(5,9); +U+9AAA(0);U+9AAB(3,8,9);U+9AAB(3,8,9) +U+9AAB(0);U+9AAB(3,9);U+9AAA(3,8) +U+9AAC(0);U+9AAC(0); +U+9AAD(0);U+9AAD(0,9); +U+9AAE(0);U+9AAE(0); +U+9AAF(0);U+9AAF(0,9);U+80AE(1,3,8,9) +U+9AB0(0);U+9AB0(5,9); +U+9AB1(0);U+9AB1(5,9); +U+9AB2(0);U+9AB2(0); +U+9AB3(0);U+9AB3(0,9); +U+9AB4(0);U+9AB4(3,9);U+9ACA(3,9) +U+9AB5(0);U+9AD4(3,8,9);U+4F53(3,9),U+9AD4(3,8,9),U+8EB0(3),U+8EC6(3) +U+9AB6(0);U+9AB6(5); +U+9AB7(0);U+9AB7(5,9); +U+9AB8(0);U+9AB8(5,9); +U+9AB9(0);U+9AB9(3,9);U+8E0D(3,9) +U+9ABA(0);U+9ABA(5); +U+9ABB(0);U+9ABB(0,9);U+80EF(3,9) +U+9ABC(0);U+9ABC(5,9); +U+9ABE(0);U+9ABE(0,9);U+9CA0(2),U+9BC1(1,2,3,8,9) +U+9ABF(0);U+9ABF(0,9); +U+9AC0(0);U+9AC0(5,9); +U+9AC1(0);U+9AC1(5,9); +U+9AC2(0);U+9AC2(5,9); +U+9AC3(0);U+9AC3(0); +U+9AC4(0);U+9AD3(3,8,9);U+9AD3(3,8,9),U+81B8(0,3,8) +U+9AC5(0);U+9ACF(1,3,8,9);U+9ACF(1,3,8,9) +U+9AC6(0);U+9AC6(3,9); +U+9AC7(0);U+9AC7(3,9); +U+9AC9(0);U+9AC9(0); +U+9ACA(0);U+9ACA(0,9);U+9AB4(3,9) +U+9ACB(0);U+9AD6(1,3,8,9);U+9AD6(1,3,8,9) +U+9ACC(0);U+9AD5(1,3,8,9);U+9AD5(1,3,8,9),U+8191(1,3,8),U+81CF(0,1,3,8,9) +U+9ACD(0);U+9ACD(0,9); +U+9ACE(0);U+9ACE(0); +U+9ACF(0);U+9ACF(0,9);U+9AC5(1,3,8) +U+9AD0(0);U+9AD0(0,9); +U+9AD1(0);U+9AD1(5,9); +U+9AD2(0);U+9AD2(0,9);U+810F(1,3,8),U+81DF(1,3,8,9) +U+9AD3(0);U+9AD3(5,9);U+81B8(3,8),U+9AC4(3,8) +U+9AD4(0);U+9AD4(0,9);U+4F53(1,3,8,9),U+8EB0(3,8),U+8EC6(3,8),U+9AB5(3,8) +U+9AD5(0);U+9AD5(0,9);U+81CF(3,8,9),U+9ACC(1,3,8),U+8191(1,3,8) +U+9AD6(0);U+9AD6(0,9);U+9ACB(1,3,8) +U+9AD8(0);U+9AD8(5,9);U+9AD9(3,8) + +U+9AD9(0);U+9AD8(3,8,9);U+9AD8(3,8,9) +U+9ADA(0);U+9ADA(0); +U+9ADB(0);U+9ADB(0); +U+9ADC(0);U+9ADC(0,9); +U+9ADD(0);U+9ADD(0); +U+9ADE(0);U+9ADE(0); +U+9ADF(0);U+9ADF(5,9); +U+9AE1(0);U+9AE1(5,9); +U+9AE2(0);U+9AE2(4); +U+9AE3(0);U+9AE3(0,9);U+4EFF(2,3,8,9),U+5023(2,3,8,9),U+5F77(2,3,4,8,9) +U+9AE5(0);U+9AEF(2,3,8,9);U+9AEF(2,3,8,9) +U+9AE6(0);U+9AE6(5,9);U+7266(3),U+6C02(0,2,3,9),U+729B(2,3,8,9) +U+9AE7(0);U+9AE7(0,9); +U+9AEA(0);U+9AEE(4,8,9);U+53D1(4),U+9AEE(4,8,9),U+5F42(4),U+767C(1,3,4,8,9) +U+9AEB(0);U+9AEB(5,9); +U+9AEC(0);U+9AEC(0,9); +U+9AED(0);U+9AED(5,9); +U+9AEE(0);U+9AEE(0,9);U+53D1(1,3,8),U+9AEA(4,8),U+5F42(1,3,4,8),U+767C(1,3,8,9) +U+9AEF(0);U+9AEF(5,9);U+9AE5(2,3,8) +U+9AF1(0);U+9AF1(0,9); +U+9AF2(0);U+9AF2(0,9); +U+9AF3(0);U+9AF3(3,9); +U+9AF4(0);U+5F7F(8,9);U+4F5B(2,9),U+5F7F(8,9),U+4ECF(0,2,3,8) +U+9AF5(0);U+9AF5(0); +U+9AF6(0);U+9AF6(0,9); +U+9AF7(0);U+9AF7(0,9); +U+9AF8(0);U+9AF8(0); +U+9AF9(0);U+9AF9(5,9); +U+9AFA(0);U+9AFA(3,9);U+9B20(3,9) +U+9AFB(0);U+9AFB(5,9); +U+9AFC(0);U+9AFC(3,9); +U+9AFD(0);U+9AFD(0,9); +U+9AFE(0);U+9AFE(0,9); +U+9AFF(0);U+9AFF(0); +U+9B01(0);U+9B01(0,9);U+75E2(4,9) +U+9B03(0);U+9B03(5,9);U+9A0C(2,8),U+9A23(2,3,8,9),U+9A94(4,8) +U+9B04(0);U+9B04(3,9); +U+9B05(0);U+9B05(0,9); +U+9B06(0);U+9B06(0,9);U+677E(1,3,8,9),U+6780(1,3,4,8) +U+9B07(0);U+9B07(0); +U+9B08(0);U+9B08(5,9); +U+9B0A(0);U+9B0A(3,9); +U+9B0B(0);U+9B0B(0,9); +U+9B0C(0);U+9B0C(0,9); +U+9B0D(0);U+9B0D(0,9);U+80E1(1,3,8,9),U+885A(1,2,3,4,8,9) +U+9B0E(0);U+9B0E(0,9);U+760C(4,9) +U+9B0F(0);U+9B0F(5); +U+9B10(0);U+9B10(0,9); +U+9B11(0);U+9B11(0,9); +U+9B12(0);U+9B12(4,9); +U+9B13(0);U+9B22(1,3,8,9);U+9B22(1,3,8,9) +U+9B15(0);U+9B15(0,9); +U+9B16(0);U+9B16(0,9); +U+9B17(0);U+9B17(0,9); +U+9B18(0);U+9B18(0,9); +U+9B19(0);U+9B19(0,9); +U+9B1A(0);U+9B1A(0,9);U+9808(3,4,9),U+987B(1,8) +U+9B1C(0);U+9B1C(3); +U+9B1D(0);U+9B1D(4); +U+9B1E(0);U+9B1E(0,9); +U+9B1F(0);U+9B1F(5,9); +U+9B20(0);U+9B20(0,9);U+9AFA(3,9) +U+9B21(0);U+9B21(3); + +U+9B22(0);U+9B22(0,9);U+9B13(1,3,8) +U+9B23(0);U+9B23(5,9); +U+9B24(0);U+9B24(0,9); +U+9B25(0);U+9B25(0,9);U+6597(1,3,8,9),U+95D8(4,8),U+9B26(2,8),U+9B2A(2,8),U+9B2C(2,3,8),U+9B2D(4,8) + +U+9B26(0);U+9B25(2,8,9);U+6597(4,9),U+9B25(2,8,9),U+9B2C(4),U+9B2D(3),U+95D8(4),U+9B2A(4) + +U+9B27(0);U+9B27(0,9);U+9599(2,3,8),U+95F9(1,3,8) +U+9B28(0);U+9B28(0,9);U+54C4(2,3,8,9),U+95A7(3) +U+9B29(0);U+9B29(0,9);U+960B(1,3,8) +U+9B2A(0);U+9B25(2,8,9);U+6597(4,9),U+9B25(2,8,9),U+9B2C(4),U+9B2D(3),U+95D8(4),U+9B26(4) + +U+9B2B(0);U+9B2B(0,9);U+961A(3),U+95DE(0,1,3,8,9) +U+9B2C(0);U+9B25(2,3,8,9);U+6597(3,9),U+9B25(2,3,8,9),U+9B26(4),U+9B2A(4),U+9B2D(3),U+95D8(3,4) +U+9B2D(0);U+9B25(4,8,9);U+6597(4,9),U+95D8(3),U+9B25(4,8,9),U+9B26(3),U+9B2A(3),U+9B2C(3) + +U+9B2E(0);U+9B2E(0,9);U+9604(1,3,8) +U+9B2F(0);U+9B2F(5,9); +U+9B30(0);U+9B31(2,3,8,9);U+90C1(4,9),U+9B31(2,3,8,9),U+6B1D(0,2,3,4) +U+9B31(0);U+9B31(0,9);U+6B1D(2,3,8),U+90C1(1,3,8,9),U+9B30(2,3,8) +U+9B32(0);U+9B32(5,9); +U+9B33(0);U+9B33(0,9); +U+9B35(0);U+9B35(0,9); +U+9B36(0);U+9B39(4,8);U+9B39(4,8) +U+9B37(0);U+9B37(0,9); +U+9B38(0);U+9B38(0); +U+9B39(0);U+9B39(0);U+9B36(4,8) +U+9B3A(0);U+9B3A(0,9); +U+9B3B(0);U+9B3B(5,9);U+7CA5(3,8,9) +U+9B3C(0);U+9B3C(5,9); +U+9B3E(0);U+9B3E(0,9); +U+9B3F(0);U+9B3F(0,9); +U+9B41(0);U+9B41(5,9);U+6AC6(3,9) +U+9B42(0);U+9B42(5,9); +U+9B43(0);U+9B43(5,9); +U+9B44(0);U+9B44(5,9); +U+9B45(0);U+9B45(5,9); +U+9B46(0);U+9B46(0,9); +U+9B47(0);U+9B58(1,3,8,9);U+9B58(1,3,8,9) +U+9B48(0);U+9B48(5,9); +U+9B49(0);U+9B4E(1,3,8,9);U+9B4E(1,3,8,9) +U+9B4A(0);U+9B4A(0,9);U+872E(4,9) +U+9B4B(0);U+9B4B(0,9); +U+9B4C(0);U+9B4C(0,9); +U+9B4D(0);U+9B4D(5,9); +U+9B4E(0);U+9B4E(0,9);U+9B49(1,3,8) +U+9B4F(0);U+9B4F(5,9); +U+9B51(0);U+9B51(5,9); +U+9B52(0);U+9B52(0,9); +U+9B53(0);U+9B53(0); +U+9B54(0);U+9B54(5,9); +U+9B55(0);U+9B55(0,9); +U+9B56(0);U+9B56(0,9); +U+9B58(0);U+9B58(0,9);U+9B47(1,3,8) +U+9B59(0);U+9B59(0,9); +U+9B5A(0);U+9B5A(0,9);U+9C7C(1,3,8) +U+9B5B(0);U+9B5B(0,9);U+9C7D(1,3,8) +U+9B5C(0);U+9B5C(0); +U+9B5D(0);U+9B5D(0); +U+9B5E(0);U+9B5E(0); +U+9B5F(0);U+9B5F(0,9); +U+9B60(0);U+9B60(0,9); + +U+9B61(0);U+9B61(0,9);U+9493(4),U+91E3(0,1,4,8,9) +U+9B63(0);U+9B63(0); +U+9B64(0);U+9B64(0,9); +U+9B65(0);U+9B65(0); +U+9B66(0);U+9B66(0,9);U+9CA8(3),U+9BCA(1,3,8,9),U+9BCB(3) +U+9B67(0);U+9B67(3,9); +U+9B68(0);U+9B68(0,9);U+9C80(4,8) +U+9B69(0);U+9B69(0); +U+9B6A(0);U+9B6A(0); +U+9B6B(0);U+9B6B(0); +U+9B6C(0);U+9B6C(0,9); +U+9B6D(0);U+9B6D(0); +U+9B6E(0);U+9B6E(0); +U+9B6F(0);U+9B6F(0,9);U+9C81(1,3,8) +U+9B70(0);U+9B70(0,9); +U+9B71(0);U+9B71(0,9); +U+9B73(0);U+9B73(0); +U+9B74(0);U+9B74(0,9);U+9C82(1,3,8) +U+9B75(0);U+9B75(0,9); +U+9B76(0);U+9B76(3,9); +U+9B77(0);U+9B77(0,9);U+9C7F(1,3,8) +U+9B78(0);U+9B78(0); +U+9B79(0);U+9B79(0); +U+9B7A(0);U+9B7A(0,9);U+9C84(4,8) +U+9B7B(0);U+9B7B(0,9); +U+9B7C(0);U+9B7C(3,9);U+9C4B(3,9) +U+9B7D(0);U+9B7D(0,9);U+86B6(3,9) +U+9B7E(0);U+9B7E(0,9); +U+9B7F(0);U+9B7F(0); +U+9B80(0);U+9B80(0,9); +U+9B81(0);U+9B81(0);U+9C85(1,3,8) +U+9B82(0);U+9B82(0,9); +U+9B83(0);U+9B83(0);U+9C86(1,3,8) +U+9B84(0);U+9B84(0); +U+9B85(0);U+9B85(0,9); +U+9B86(0);U+9B86(4,9); +U+9B87(0);U+9B87(3,9); +U+9B88(0);U+9B88(0,9); +U+9B8A(0);U+9B8A(0);U+9C8C(4,8) +U+9B8B(0);U+9B8B(0);U+9C89(4,8) +U+9B8D(0);U+9B8D(0);U+9C8F(1,3,8) +U+9B8E(0);U+9B8E(0);U+9C87(1,3,8) +U+9B8F(0);U+9B8F(3); +U+9B90(0);U+9B90(0,9);U+9C90(1,3,8) +U+9B91(0);U+9B91(0,9);U+9C8D(1,3,8) +U+9B92(0);U+9B92(0,9);U+9C8B(1,3,8) +U+9B93(0);U+9B93(0,9);U+9C8A(1,3,8) +U+9B94(0);U+9B94(0); +U+9B95(0);U+9B95(0,9); +U+9B96(0);U+9B96(0); +U+9B97(0);U+9B97(0); +U+9B98(0);U+9B98(0); +U+9B9A(0);U+9B9A(0,9);U+9C92(1,3,8) +U+9B9B(0);U+9B9B(0,9); +U+9B9C(0);U+9B9C(0);U+9C98(4,8) +U+9B9D(0);U+9B9D(0);U+9C9E(1,3,8),U+9BD7(1,3,8,9) +U+9B9E(0);U+9B9E(0,9);U+9C95(4,8) +U+9B9F(0);U+9B9F(0); +U+9BA0(0);U+9BA0(0,9); +U+9BA1(0);U+9BA1(0,9); +U+9BA2(0);U+9BA2(0,9); +U+9BA3(0);U+9BA3(0);U+4C9F(1,3) +U+9BA4(0);U+9BA4(0,9); + +U+9BA5(0);U+9BA5(0,9); +U+9BA6(0);U+9BA6(0,9);U+9C96(1,3,8) +U+9BA7(0);U+9BA7(0); +U+9BA8(0);U+9BA8(3,9); +U+9BA9(0);U+9BA9(0); +U+9BAA(0);U+9BAA(0,9);U+9C94(1,3,8) +U+9BAB(0);U+9BAB(0,9);U+9C9B(1,3,8) +U+9BAC(0);U+9BAC(0); +U+9BAD(0);U+9BAD(0,9);U+9C91(1,3,8),U+89DF(0,1,3,4,8,9) +U+9BAE(0);U+9BAE(0,9);U+5C1F(2,3,8,9),U+5C20(2,8),U+9C9C(1,3,8) +U+9BAF(0);U+9BAF(0,9); +U+9BB0(0);U+9BB0(0); +U+9BB1(0);U+9BB1(0); +U+9BB2(0);U+9BB2(0); +U+9BB3(0);U+9BB3(0);U+9C93(4,8) +U+9BB4(0);U+9BB4(0); +U+9BB5(0);U+9BB5(0,9); +U+9BB6(0);U+9BB6(0,9);U+9CAA(4,8) +U+9BB7(0);U+9BB7(3); +U+9BB8(0);U+9BB8(0,9); +U+9BB9(0);U+9BB9(0,9); +U+9BBA(0);U+9BBA(0);U+9C9D(1,3,8) +U+9BBB(0);U+9BBB(3); +U+9BBC(0);U+9BBC(0); +U+9BBD(0);U+9BBD(0,9); +U+9BBE(0);U+9BBE(3); +U+9BBF(0);U+9BBF(0,9); +U+9BC0(0);U+9BC0(0,9);U+9CA7(1,3,8) +U+9BC1(0);U+9BC1(0,9);U+9CA0(1,3,8),U+9ABE(0,1,2,3,8,9) +U+9BC3(0);U+9BC3(0,9); +U+9BC4(0);U+9BC4(0,9); +U+9BC5(0);U+9BC5(0); +U+9BC6(0);U+9BC6(0,9); +U+9BC7(0);U+9BC7(0,9);U+9CA9(1,3,8) +U+9BC8(0);U+9BC8(3,9); +U+9BC9(0);U+9BC9(0,9);U+9CA4(1,3,8) +U+9BCA(0);U+9BCA(0,9);U+9BCB(3,8),U+9CA8(1,3,8),U+9B66(0,1,3,8,9) +U+9BCB(0);U+9BCA(3,8,9);U+9BCA(3,8,9),U+9CA8(3),U+9B66(0,3,9) +U+9BCC(0);U+9BCC(0); +U+9BCD(0);U+9BCD(0); +U+9BCE(0);U+9BCE(0); +U+9BCF(0);U+9BCF(0); +U+9BD0(0);U+9BD0(0); +U+9BD1(0);U+9BD1(0); +U+9BD2(0);U+9BD2(0);U+9CAC(4,8) +U+9BD3(0);U+9BD3(0,9); +U+9BD4(0);U+9BD4(0,9);U+9CBB(1,3,8) +U+9BD5(0);U+9BD5(0,9);U+9CAF(4,8) +U+9BD6(0);U+9BD6(0,9);U+9CAD(1,3,8) +U+9BD7(0);U+9BD7(0,9);U+9C9E(3),U+9B9D(0,1,3,8) +U+9BD8(0);U+9BD8(0); +U+9BD9(0);U+9BD9(0,9); +U+9BDA(0);U+9BDA(0,9); +U+9BDB(0);U+9BDB(0,9);U+9CB7(1,3,8) +U+9BDC(0);U+9BDC(3,9); +U+9BDD(0);U+9BDD(0);U+9CB4(4,8) +U+9BDE(0);U+9BDE(0,9); +U+9BDF(0);U+9BDF(0); +U+9BE0(0);U+9BE0(0,9); +U+9BE1(0);U+9BE1(0,9);U+9CB1(1,3,8) +U+9BE2(0);U+9BE2(0,9);U+9CB5(1,3,8) +U+9BE3(0);U+9BE3(0); + +U+9BE4(0);U+9BE4(0,9);U+9CB2(1,3,8) +U+9BE5(0);U+9BE5(0,9); +U+9BE6(0);U+9BE6(3,9); +U+9BE7(0);U+9BE7(0,9);U+9CB3(1,3,8) +U+9BE8(0);U+9BE8(0,9);U+9CB8(1,3,8) +U+9BE9(0);U+9BE9(0); +U+9BEA(0);U+9BEA(0,9);U+9CAE(1,3,8) +U+9BEB(0);U+9BEB(0,9);U+9CB0(1,3,8) +U+9BEC(0);U+9BEC(0,9); +U+9BED(0);U+9BED(0); +U+9BEE(0);U+9BEE(0); +U+9BEF(0);U+9BEF(0); +U+9BF0(0);U+9BF0(0,9);U+9CB6(1,3,8) +U+9BF1(0);U+9BF1(0); +U+9BF2(0);U+9BF2(0); +U+9BF3(0);U+9BF3(0); +U+9BF4(0);U+9BF4(0);U+9CBA(4,8) +U+9BF5(0);U+9BF5(0); +U+9BF7(0);U+9BF7(0,9);U+9CC0(4,8) +U+9BF8(0);U+9BF8(0,9); +U+9BF9(0);U+9BF9(0); +U+9BFA(0);U+9BFA(0); +U+9BFB(0);U+9BFB(0); +U+9BFC(0);U+9BFC(4); +U+9BFD(0);U+9BFD(0,9);U+9CAB(1,3,8),U+9C3F(1,3,8,9) +U+9BFE(0);U+9BFE(4); +U+9BFF(0);U+9BFF(0);U+9CCA(1,3,8) +U+9C02(0);U+9C02(0);U+9C97(1,3,8) +U+9C05(0);U+9C05(0,9); +U+9C06(0);U+9C06(0,9);U+4CA0(1,3) +U+9C07(0);U+9C07(0,9); +U+9C08(0);U+9C08(0,9);U+9CBD(1,3,8) +U+9C09(0);U+9C09(0,9);U+9CC7(1,3,8) +U+9C0A(0);U+9C0A(0); +U+9C0B(0);U+9C0B(0,9); +U+9C0C(0);U+9C0D(3,8,9);U+4CA1(1,3),U+9C0D(3,8,9),U+9CC5(1,3,8) +U+9C0D(0);U+9C0D(0,9);U+4CA1(1,3),U+9C0C(3,8),U+9CC5(1,3,8) +U+9C0E(0);U+9C0E(0,9); +U+9C0F(0);U+9C0F(0);U+9CBE(4,8) +U+9C10(0);U+9C10(0);U+9CC4(1,3,8),U+9C77(1,3,4,8,9) +U+9C11(0);U+9C11(0); +U+9C12(0);U+9C12(0,9);U+9CC6(1,3,8) +U+9C13(0);U+9C13(0,9);U+9CC3(1,3,8) +U+9C14(0);U+9C14(0,9); +U+9C15(0);U+9C15(0); +U+9C16(0);U+9C16(0); +U+9C17(0);U+9C17(0,9); +U+9C18(0);U+9C18(0); +U+9C19(0);U+9C19(0); +U+9C1A(0);U+9C1A(0); +U+9C1B(0);U+9C1B(0);U+9CC1(1,3,8) +U+9C1C(0);U+9C1C(0,9);U+9CD2(1,3,8) +U+9C1D(0);U+9C1D(0,9); +U+9C1E(0);U+9C1E(0); +U+9C1F(0);U+9C1F(0);U+9CD1(1,3) +U+9C20(0);U+9C20(0);U+9CCB(4,8) +U+9C21(0);U+9C21(0,9); +U+9C22(0);U+9C22(0); +U+9C23(0);U+9C23(0,9);U+9CA5(1,3,8) +U+9C24(0);U+9C24(3,9); +U+9C25(0);U+9C25(0,9);U+9CCF(1,3,8),U+9C5E(1,3,8,9) +U+9C26(0);U+9C26(0); +U+9C27(0);U+9C27(0);U+4CA2(1,3) + +U+9C28(0);U+9C28(0,9);U+9CCE(1,3,8) +U+9C29(0);U+9C29(0,9);U+9CD0(4,8) +U+9C2A(0);U+9C2A(0); +U+9C2B(0);U+9C2B(0,9);U+9CD9(3),U+9C45(1,3,8) +U+9C2C(0);U+9C2C(0,9); +U+9C2D(0);U+9C2D(0,9);U+9CCD(1,3,8) +U+9C2F(0);U+9C2F(0); +U+9C30(0);U+9C30(0); +U+9C31(0);U+9C31(0,9);U+9CA2(1,3,8) +U+9C32(0);U+9C32(0,9);U+9CCC(1,3,8),U+9F07(1,3,4,8,9) +U+9C33(0);U+9C33(0,9);U+9CD3(1,3,8) +U+9C34(0);U+9C34(0,9); +U+9C35(0);U+9C35(0);U+9CD8(1,3,8) +U+9C36(0);U+9C36(0,9); +U+9C37(0);U+9C37(0,9);U+9CA6(1,3,8) +U+9C38(0);U+9C38(0); +U+9C39(0);U+9C39(0,9);U+9CA3(1,3,8) +U+9C3A(0);U+9C3A(0);U+9CB9(4,8) +U+9C3B(0);U+9C3B(0,9);U+9CD7(1,3,8) +U+9C3C(0);U+9C3C(0,9);U+9CDB(1,3,8) +U+9C3D(0);U+9C3D(0,9); +U+9C3E(0);U+9C3E(0,9);U+9CD4(1,3,8) +U+9C3F(0);U+9C3F(0,9);U+9CAB(3),U+9BFD(0,1,3,8,9) +U+9C40(0);U+9C40(4,9); +U+9C41(0);U+9C41(0,9); +U+9C43(0);U+9C43(0); +U+9C44(0);U+9C44(0,9); +U+9C45(0);U+9C45(0);U+9CD9(1,3,8),U+9C2B(0,1,3,8,9) +U+9C46(0);U+9C46(0,9); +U+9C47(0);U+9C47(0); +U+9C48(0);U+9C48(0,9);U+9CD5(1,3,8) +U+9C49(0);U+9C49(0,9);U+9CD6(1,3,8),U+9F08(3,4,8),U+9F9E(3,8) +U+9C4A(0);U+9C4A(0,9); +U+9C4B(0);U+9C4B(0,9);U+9B7C(3,9) +U+9C4C(0);U+9C4C(0,9); +U+9C4D(0);U+9C4D(0,9); +U+9C4E(0);U+9C4E(0,9); +U+9C50(0);U+9C50(0,9); +U+9C52(0);U+9C52(0,9);U+9CDF(1,3,8) +U+9C53(0);U+9C54(2,3,8,9);U+9C54(2,3,8,9),U+9CDD(3) +U+9C54(0);U+9C54(0,9);U+9C53(2,3,8),U+9CDD(1,3,8) +U+9C55(0);U+9C55(0,9); +U+9C56(0);U+9C56(0,9);U+9CDC(1,3,8) +U+9C57(0);U+9C57(0,9);U+9CDE(1,3,8) +U+9C58(0);U+9C58(0,9);U+9C9F(1,3,8) +U+9C59(0);U+9C59(0,9); +U+9C5A(0);U+9C5A(0); +U+9C5B(0);U+9C5B(0); +U+9C5C(0);U+9C5C(0); +U+9C5D(0);U+9C5D(0);U+9CBC(4,8) +U+9C5E(0);U+9C5E(0,9);U+9CCF(3),U+9C25(0,1,3,8,9) +U+9C5F(0);U+9C5F(0,9);U+9C8E(1,3,8) +U+9C60(0);U+9C60(0,9);U+9C99(1,3,8) +U+9C62(0);U+9C62(3,9); +U+9C63(0);U+9C63(0,9);U+9CE3(1,3,8) +U+9C65(0);U+9C65(0); +U+9C66(0);U+9C66(0,9); +U+9C67(0);U+9C67(0,9);U+9CE2(1,3,8) +U+9C68(0);U+9C68(0,9);U+9CBF(1,3,8) +U+9C69(0);U+9C69(0); +U+9C6A(0);U+9C6A(0); +U+9C6B(0);U+9C6B(0); + +U+9C6C(0);U+9C6C(0); +U+9C6D(0);U+9C6D(0,9);U+9C9A(1,3,8) +U+9C6E(0);U+9C6E(3,9); +U+9C6F(0);U+9C6F(0);U+9CE0(4,8) +U+9C70(0);U+9C70(0); +U+9C71(0);U+9C71(0,9); +U+9C72(0);U+9C72(0); +U+9C73(0);U+9C73(0,9); +U+9C74(0);U+9C74(0,9); +U+9C75(0);U+9C75(0,9); +U+9C77(0);U+9C77(0,9);U+9CC4(4),U+9C10(0,1,3,4,8) +U+9C78(0);U+9C78(0,9);U+9C88(1,3,8) +U+9C79(0);U+9C79(0,9); +U+9C7A(0);U+9C7A(0,9);U+9CA1(1,3,8) +U+9C7C(0);U+9B5A(1,3,8,9);U+9B5A(1,3,8,9) +U+9C7D(0);U+9B5B(1,3,8,9);U+9B5B(1,3,8,9) +U+9C7E(0);U+9C7E(4); +U+9C7F(0);U+9B77(1,3,8,9);U+9B77(1,3,8,9) +U+9C80(0);U+9B68(4,8,9);U+9B68(4,8,9) +U+9C81(0);U+9B6F(1,3,8,9);U+9B6F(1,3,8,9) +U+9C82(0);U+9B74(1,3,8,9);U+9B74(1,3,8,9) +U+9C83(0);U+9C83(6); +U+9C84(0);U+9B7A(4,8,9);U+9B7A(4,8,9) +U+9C85(0);U+9B81(1,3,8);U+9B81(1,3,8) +U+9C86(0);U+9B83(1,3,8);U+9B83(1,3,8) +U+9C87(0);U+9B8E(1,3,8);U+9B8E(1,3,8) +U+9C88(0);U+9C78(1,3,8,9);U+9C78(1,3,8,9) +U+9C89(0);U+9B8B(4,8);U+9B8B(4,8) +U+9C8A(0);U+9B93(1,3,8,9);U+9B93(1,3,8,9) +U+9C8B(0);U+9B92(1,3,8,9);U+9B92(1,3,8,9) +U+9C8C(0);U+9B8A(4,8);U+9B8A(4,8) +U+9C8D(0);U+9B91(1,3,8,9);U+9B91(1,3,8,9) +U+9C8E(0);U+9C5F(1,3,8,9);U+9C5F(1,3,8,9) +U+9C8F(0);U+9B8D(1,3,8);U+9B8D(1,3,8) +U+9C90(0);U+9B90(1,3,8,9);U+9B90(1,3,8,9) +U+9C91(0);U+9BAD(1,3,8,9);U+89DF(1,3,4,9),U+9BAD(1,3,8,9) +U+9C92(0);U+9B9A(1,3,8,9);U+9B9A(1,3,8,9) +U+9C93(0);U+9BB3(4,8);U+9BB3(4,8) +U+9C94(0);U+9BAA(1,3,8,9);U+9BAA(1,3,8,9) +U+9C95(0);U+9B9E(4,8,9);U+9B9E(4,8,9) +U+9C96(0);U+9BA6(1,3,8,9);U+9BA6(1,3,8,9) +U+9C97(0);U+9C02(1,3,8);U+9C02(1,3,8) +U+9C98(0);U+9B9C(4,8);U+9B9C(4,8) +U+9C99(0);U+9C60(1,3,8,9);U+9C60(1,3,8,9) +U+9C9A(0);U+9C6D(1,3,8,9);U+9C6D(1,3,8,9) +U+9C9B(0);U+9BAB(1,3,8,9);U+9BAB(1,3,8,9) +U+9C9C(0);U+9BAE(1,3,8,9);U+5C1F(3,9),U+5C20(2),U+9BAE(1,3,8,9) +U+9C9D(0);U+9BBA(1,3,8);U+9BBA(1,3,8) +U+9C9E(0);U+9B9D(1,3,8);U+9B9D(1,3,8),U+9BD7(3,9) +U+9C9F(0);U+9C58(1,3,8,9);U+9C58(1,3,8,9) +U+9CA0(0);U+9BC1(1,3,8,9);U+9ABE(2,9),U+9BC1(1,3,8,9) +U+9CA1(0);U+9C7A(1,3,8,9);U+9C7A(1,3,8,9) +U+9CA2(0);U+9C31(1,3,8,9);U+9C31(1,3,8,9) +U+9CA3(0);U+9C39(1,3,8,9);U+9C39(1,3,8,9) +U+9CA4(0);U+9BC9(1,3,8,9);U+9BC9(1,3,8,9) +U+9CA5(0);U+9C23(1,3,8,9);U+9C23(1,3,8,9) +U+9CA6(0);U+9C37(1,3,8,9);U+9C37(1,3,8,9) +U+9CA7(0);U+9BC0(1,3,8,9);U+9BC0(1,3,8,9) +U+9CA8(0);U+9BCA(1,3,8,9);U+9B66(3,9),U+9BCA(1,3,8,9),U+9BCB(3) +U+9CA9(0);U+9BC7(1,3,8,9);U+9BC7(1,3,8,9) +U+9CAA(0);U+9BB6(4,8,9);U+9BB6(4,8,9) +U+9CAB(0);U+9BFD(1,3,8,9);U+9BFD(1,3,8,9),U+9C3F(3,9) +U+9CAC(0);U+9BD2(4,8);U+9BD2(4,8) + +U+9CAD(0);U+9BD6(1,3,8,9);U+9BD6(1,3,8,9) +U+9CAE(0);U+9BEA(1,3,8,9);U+9BEA(1,3,8,9) +U+9CAF(0);U+9BD5(4,8,9);U+9BD5(4,8,9) +U+9CB0(0);U+9BEB(1,3,8,9);U+9BEB(1,3,8,9) +U+9CB1(0);U+9BE1(1,3,8,9);U+9BE1(1,3,8,9) +U+9CB2(0);U+9BE4(1,3,8,9);U+9BE4(1,3,8,9) +U+9CB3(0);U+9BE7(1,3,8,9);U+9BE7(1,3,8,9) +U+9CB4(0);U+9BDD(4,8);U+9BDD(4,8) +U+9CB5(0);U+9BE2(1,3,8,9);U+9BE2(1,3,8,9) +U+9CB6(0);U+9BF0(1,3,8,9);U+9BF0(1,3,8,9) +U+9CB7(0);U+9BDB(1,3,8,9);U+9BDB(1,3,8,9) +U+9CB8(0);U+9BE8(1,3,8,9);U+9BE8(1,3,8,9) +U+9CB9(0);U+9C3A(4,8);U+9C3A(4,8) +U+9CBA(0);U+9BF4(4,8);U+9BF4(4,8) +U+9CBB(0);U+9BD4(1,3,8,9);U+9BD4(1,3,8,9) +U+9CBC(0);U+9C5D(4,8);U+9C5D(4,8) +U+9CBD(0);U+9C08(1,3,8,9);U+9C08(1,3,8,9) +U+9CBE(0);U+9C0F(4,8);U+9C0F(4,8) +U+9CBF(0);U+9C68(1,3,8,9);U+9C68(1,3,8,9) +U+9CC0(0);U+9BF7(4,8,9);U+9BF7(4,8,9) +U+9CC1(0);U+9C1B(1,3,8);U+9C1B(1,3,8) +U+9CC2(0);U+9CC2(4); +U+9CC3(0);U+9C13(1,3,8,9);U+9C13(1,3,8,9) +U+9CC4(0);U+9C77(4,9);U+9C10(1,3,8),U+9C77(4,9) +U+9CC5(0);U+9C0D(1,3,8,9);U+9C0D(1,3,8,9),U+4CA1(1,3,8),U+9C0C(1,3,8) +U+9CC6(0);U+9C12(1,3,8,9);U+9C12(1,3,8,9) +U+9CC7(0);U+9C09(1,3,8,9);U+9C09(1,3,8,9) +U+9CC8(0);U+9CC8(4); +U+9CC9(0);U+9CC9(4); +U+9CCA(0);U+9BFF(1,3,8);U+9BFF(1,3,8) +U+9CCB(0);U+9C20(4,8);U+9C20(4,8) +U+9CCC(0);U+9C32(1,3,8,9);U+9C32(1,3,8,9),U+9F07(4,9) +U+9CCD(0);U+9C2D(1,3,8,9);U+9C2D(1,3,8,9) +U+9CCE(0);U+9C28(1,3,8,9);U+9C28(1,3,8,9) +U+9CCF(0);U+9C25(1,3,8,9);U+9C25(1,3,8,9),U+9C5E(3,9) +U+9CD0(0);U+9C29(4,8,9);U+9C29(4,8,9) +U+9CD1(0);U+9C1F(1,3);U+9C1F(1,3) +U+9CD2(0);U+9C1C(1,3,8,9);U+9C1C(1,3,8,9) +U+9CD3(0);U+9C33(1,3,8,9);U+9C33(1,3,8,9) +U+9CD4(0);U+9C3E(1,3,8,9);U+9C3E(1,3,8,9) +U+9CD5(0);U+9C48(1,3,8,9);U+9C48(1,3,8,9) +U+9CD6(0);U+9C49(1,3,8,9);U+9C49(1,3,8,9),U+9F9E(3),U+9F08(1,3,4,8) +U+9CD7(0);U+9C3B(1,3,8,9);U+9C3B(1,3,8,9) +U+9CD8(0);U+9C35(1,3,8);U+9C35(1,3,8) +U+9CD9(0);U+9C45(1,3,8);U+9C2B(3,9),U+9C45(1,3,8) +U+9CDA(0);U+9CDA(6); +U+9CDB(0);U+9C3C(1,3,8,9);U+9C3C(1,3,8,9) +U+9CDC(0);U+9C56(1,3,8,9);U+9C56(1,3,8,9) +U+9CDD(0);U+9C54(1,3,8,9);U+9C53(3),U+9C54(1,3,8,9) +U+9CDE(0);U+9C57(1,3,8,9);U+9C57(1,3,8,9) +U+9CDF(0);U+9C52(1,3,8,9);U+9C52(1,3,8,9) +U+9CE0(0);U+9C6F(4,8);U+9C6F(4,8) +U+9CE1(0);U+9CE1(4); +U+9CE2(0);U+9C67(1,3,8,9);U+9C67(1,3,8,9) +U+9CE3(0);U+9C63(1,3,8,9);U+9C63(1,3,8,9) +U+9CE4(0);U+9CE4(6); +U+9CE5(0);U+9CE5(0,9);U+9E1F(1,3,8) +U+9CE6(0);U+9CE6(3,9); +U+9CE7(0);U+9CE7(0,9);U+51EB(4),U+9CEC(1,3,4,8) +U+9CE8(0);U+9CE8(0); +U+9CE9(0);U+9CE9(0,9);U+9E20(1,3,8) +U+9CEA(0);U+9CEA(0,9); +U+9CEB(0);U+9D08(3,9);U+96C1(3,8,9),U+9D08(3,9) + +U+9CEC(0);U+9CEC(0);U+51EB(1,3,8),U+9CE7(1,3,4,8,9) +U+9CED(0);U+9CED(0,9); +U+9CEE(0);U+96DE(8,9);U+96DE(8,9),U+9DC4(4),U+9E21(4) +U+9CEF(0);U+9CF3(3,8,9);U+51E4(3),U+9CF3(3,8,9) +U+9CF0(0);U+9CF0(0); +U+9CF1(0);U+9CF1(4,9); +U+9CF2(0);U+9CF2(0,9);U+9E24(4,8) +U+9CF3(0);U+9CF3(0,9);U+51E4(1,3,8),U+9CEF(3,8) +U+9CF4(0);U+9CF4(0,9);U+9E23(1,3,8) +U+9CF5(0);U+9CF5(0,9);U+9E28(3),U+9D07(1,3,8,9) +U+9CF6(0);U+9CF6(0,9);U+9E22(1,3,8) +U+9CF7(0);U+9CF7(0,9); +U+9CF8(0);U+9CF8(0); +U+9CF9(0);U+9CF9(3,9); +U+9CFA(0);U+9CFA(0,9); +U+9CFB(0);U+9CFB(0,9); +U+9CFC(0);U+9CFC(3,9); +U+9CFD(0);U+9CFD(0,9); +U+9CFE(0);U+9CFE(0);U+4D13(1,3) +U+9CFF(0);U+9CFF(0,9); +U+9D00(0);U+9D00(0,9); +U+9D01(0);U+9D01(0); +U+9D02(0);U+9D02(3);U+9D03(3,9) +U+9D03(0);U+9D03(0,9);U+9D02(3) +U+9D04(0);U+9D04(3,9); +U+9D05(0);U+9D05(0,9); +U+9D06(0);U+9D06(0,9);U+9E29(1,3,8) +U+9D07(0);U+9D07(0,9);U+9E28(1,3,8),U+9CF5(0,1,3,8,9) +U+9D08(0);U+9D08(0,9);U+96C1(2,3,8,9),U+9CEB(3) +U+9D09(0);U+9D09(0,9);U+9D76(2,3,8),U+9E26(1,3,8) +U+9D0A(0);U+9D0A(0); +U+9D0B(0);U+9D0B(0); +U+9D0F(0);U+9D0F(0); +U+9D10(0);U+9D10(0,9); +U+9D12(0);U+9D12(0,9);U+9E30(1,3,8) +U+9D13(0);U+9D13(0); +U+9D14(0);U+9D14(0,9); +U+9D15(0);U+9D15(0,9);U+9E35(1,3,8) +U+9D16(0);U+9D16(0); +U+9D17(0);U+9D17(0,9); +U+9D18(0);U+9D18(0,9); +U+9D19(0);U+9D19(0,9);U+96C9(3,9) +U+9D1A(0);U+9D1A(3); +U+9D1B(0);U+9D1B(0,9);U+9E33(1,3,8) +U+9D1C(0);U+9D1C(0); +U+9D1D(0);U+9D1D(0,9);U+9E32(1,3,8) +U+9D1E(0);U+9D1E(0,9);U+9E2E(1,3,8) +U+9D1F(0);U+9D1F(0,9);U+9E31(1,3,8) +U+9D20(0);U+9D20(0,9); +U+9D21(0);U+9D21(0); +U+9D22(0);U+9D22(0,9); +U+9D23(0);U+9D23(0,9);U+9E2A(1,3,8) +U+9D24(0);U+9D24(0); +U+9D25(0);U+9D25(3,9); +U+9D26(0);U+9D26(0,9);U+9E2F(1,3,8) +U+9D28(0);U+9D28(0,9);U+9E2D(1,3,8) +U+9D29(0);U+9D29(0,9); +U+9D2B(0);U+9D2B(0); +U+9D2D(0);U+9D2D(0,9); +U+9D2E(0);U+9D2E(0,9); +U+9D2F(0);U+9D2F(0,9);U+9E38(1,3,8) +U+9D30(0);U+9D30(0,9);U+9E39(1,3,8) +U+9D31(0);U+9D31(0,9); + +U+9D32(0);U+9D32(0); +U+9D33(0);U+9D33(3,9); +U+9D34(0);U+9D34(0);U+9E3B(1,3) +U+9D36(0);U+9D36(0,9); +U+9D37(0);U+9D37(0,9);U+4D15(1,3) +U+9D38(0);U+9D38(0,9); +U+9D39(0);U+9D39(0); +U+9D3A(0);U+9D3A(0); +U+9D3B(0);U+9D3B(0,9);U+9E3F(1,3,8) +U+9D3D(0);U+9D3D(3,9); +U+9D3E(0);U+9D3E(0,9); +U+9D3F(0);U+9D3F(0,9);U+9E3D(1,3,8) +U+9D40(0);U+9D40(0,9); +U+9D41(0);U+9D41(0,9);U+4D14(1,3) +U+9D42(0);U+9D42(0,9);U+9E3A(1,3,8) +U+9D43(0);U+9D43(0,9);U+9E3C(1,3,8) +U+9D45(0);U+9D45(0,9); +U+9D46(0);U+9D46(0); +U+9D47(0);U+9D47(0); +U+9D48(0);U+9D48(0); +U+9D49(0);U+9E1E(4,8,9);U+9E1E(4,8,9),U+9E3E(4) +U+9D4A(0);U+9D4A(0,9); +U+9D4B(0);U+9D4B(0,9); +U+9D4C(0);U+9D4C(3,9); +U+9D4D(0);U+9D4D(0); +U+9D4E(0);U+9D4E(0); +U+9D4F(0);U+9D4F(0,9); +U+9D50(0);U+9D50(0);U+9E40(4,8) +U+9D51(0);U+9D51(0,9);U+9E43(1,3,8) +U+9D52(0);U+9D52(0,9);U+9E46(1,3,8) +U+9D53(0);U+9D53(0,9);U+9E41(1,3,8) +U+9D54(0);U+9D54(3,9); +U+9D55(0);U+9D55(4); +U+9D56(0);U+9D56(0,9); +U+9D57(0);U+9D57(0,9); +U+9D58(0);U+9D58(0,9); +U+9D59(0);U+9D59(3,9); +U+9D5A(0);U+9D5A(0,9); +U+9D5B(0);U+9D5B(0,9);U+9888(3),U+981A(0,3,4),U+9838(3,4,8,9) +U+9D5C(0);U+9D5C(0,9);U+9E48(1,3,8) +U+9D5D(0);U+9D5D(0,9);U+9D5E(2,3,8),U+9E45(1,3,8) +U+9D5E(0);U+9D5D(2,3,8,9);U+9D5D(2,3,8,9),U+9E45(4) +U+9D5F(0);U+9D5F(0,9); +U+9D60(0);U+9D60(0,9);U+9E44(1,3,8) +U+9D61(0);U+9D61(0,9);U+9E49(1,3,8) +U+9D62(0);U+9D62(0); +U+9D63(0);U+9D63(0); +U+9D64(0);U+9D64(0); +U+9D65(0);U+9D65(0); +U+9D66(0);U+9D66(0); +U+9D67(0);U+9D67(0,9); +U+9D68(0);U+9D68(0,9); +U+9D69(0);U+9D69(0,9); +U+9D6A(0);U+9D6A(0,9);U+9E4C(1,3,8) +U+9D6B(0);U+9D6B(0,9); +U+9D6C(0);U+9D6C(0,9);U+9E4F(1,3,8) +U+9D6E(0);U+9D6E(0);U+9E50(1,3,8) +U+9D6F(0);U+9D6F(0,9);U+9E4E(4,8) +U+9D70(0);U+9D70(0,9);U+96D5(2,3,8,9),U+5F6B(2,3,8,9),U+7431(2,3,8,9) +U+9D71(0);U+9D71(0,9); +U+9D72(0);U+9D72(0,9);U+9E4A(1,3,8) +U+9D73(0);U+9D73(0,9); +U+9D74(0);U+9D74(0,9); + +U+9D75(0);U+9D75(0,9); +U+9D76(0);U+9D09(2,3,8,9);U+9D09(2,3,8,9),U+9E26(4) +U+9D77(0);U+9D77(0,9);U+9E53(4,8) +U+9D78(0);U+9D78(0,9); +U+9D79(0);U+9D79(0,9); +U+9D7A(0);U+9D7A(0); +U+9D7B(0);U+9D7B(0,9); +U+9D7C(0);U+9D7C(0); +U+9D7D(0);U+9D7D(0,9); +U+9D7E(0);U+9D7E(0);U+9E4D(4,8),U+9DA4(4,8,9) +U+9D7F(0);U+9D7F(0,9); +U+9D80(0);U+9D80(0,9); +U+9D81(0);U+9D81(0,9); +U+9D82(0);U+9D82(3,9); +U+9D83(0);U+9D83(0); +U+9D84(0);U+9D84(0,9);U+4D16(1,3) +U+9D85(0);U+9D85(3,9); +U+9D86(0);U+9D86(0,9); +U+9D87(0);U+9D87(0,9);U+9E2B(1,3,8) +U+9D88(0);U+9D88(0,9); +U+9D89(0);U+9D89(0,9);U+9E51(1,3,8) +U+9D8A(0);U+9D8A(0,9);U+9E52(1,3,8) +U+9D8B(0);U+9D8B(0,9); +U+9D8C(0);U+9D8C(0,9); +U+9D8D(0);U+9D8D(0); +U+9D8E(0);U+9D8E(0); +U+9D90(0);U+9D90(0,9); +U+9D91(0);U+9D91(0); +U+9D92(0);U+9D92(3,9);U+9DD8(3,9) +U+9D93(0);U+9D93(0);U+9E4B(1,3,8) +U+9D94(0);U+9D94(0,9); +U+9D96(0);U+9D96(0,9);U+9E59(1,3,8) +U+9D97(0);U+9D97(3,9); +U+9D98(0);U+9D98(0,9);U+9E55(1,3,8) +U+9D99(0);U+9D99(0,9); +U+9D9A(0);U+9D9A(0,9);U+9E57(1,3,8) +U+9D9B(0);U+9D9B(0,9); +U+9D9C(0);U+9D9C(0,9); +U+9D9D(0);U+9D9D(0,9); +U+9D9E(0);U+9D9E(0,9); +U+9D9F(0);U+9D9F(0,9); +U+9DA0(0);U+9DA0(0,9); +U+9DA1(0);U+9DA1(0,9);U+9E56(1,3,8) +U+9DA2(0);U+9DA2(0,9); +U+9DA3(0);U+9DA3(0,9); +U+9DA4(0);U+9DA4(0,9);U+9E4D(4),U+9D7E(0,4,8) +U+9DA5(0);U+9DA5(0);U+9E5B(1,3,8) +U+9DA6(0);U+9DA6(0,9); +U+9DA7(0);U+9DA7(0,9); +U+9DA8(0);U+9DA8(0,9); +U+9DA9(0);U+9DA9(0,9);U+9E5C(1,3,8) +U+9DAA(0);U+9DAA(0,9);U+4D17(1,3) +U+9DAB(0);U+9DAB(0); +U+9DAC(0);U+9DAC(0,9);U+9E27(1,3,8) +U+9DAD(0);U+9DAD(3,9); +U+9DAF(0);U+9DAF(0,9);U+83BA(1,3,8) +U+9DB0(0);U+9DB0(0); +U+9DB1(0);U+9DB1(0,9); +U+9DB2(0);U+9DB2(0,9);U+9E5F(4,8) +U+9DB3(0);U+9DB3(3,9); +U+9DB4(0);U+9DB4(0,9);U+9E64(1,3,8) +U+9DB5(0);U+9DB5(0,9);U+96CF(3),U+96DB(1,3,8,9) +U+9DB6(0);U+9DB6(0,9); + +U+9DB7(0);U+9DB7(0,9); +U+9DB8(0);U+9DB8(0,9); +U+9DB9(0);U+9DB9(0,9);U+9E60(4,8) +U+9DBA(0);U+9DBA(0,9);U+9E61(1,3,8) +U+9DBB(0);U+9DBB(0,9);U+9E58(1,3,8) +U+9DBC(0);U+9DBC(0,9);U+9E63(1,3,8) +U+9DBE(0);U+9DBE(0,9);U+7FF0(3,9) +U+9DBF(0);U+9DBF(0,9);U+9E5A(2,3) +U+9DC1(0);U+9DC1(0,9);U+9E62(4,8) +U+9DC2(0);U+9DC2(0,9);U+9E5E(1,8) +U+9DC3(0);U+9DC3(0,9); +U+9DC4(0);U+96DE(2,3,4,8,9);U+96DE(2,3,4,8,9),U+9CEE(4),U+9E21(1,3,8) +U+9DC5(0);U+9DC5(0,9); +U+9DC7(0);U+9DC7(0,9); +U+9DC8(0);U+9DC8(0,9);U+4D18(3),U+9DC9(1,3) +U+9DC9(0);U+9DC9(0);U+4D18(1,3),U+9DC8(1,3,9) +U+9DCA(0);U+9DCA(0,9);U+9E5D(4,8) +U+9DCB(0);U+9DCB(0,9); +U+9DCC(0);U+9DCC(0,9); +U+9DCD(0);U+9DCD(0,9);U+67AD(3),U+689F(1,3,8,9) +U+9DCE(0);U+9DCE(0,9); +U+9DCF(0);U+9DCF(0,9); +U+9DD0(0);U+9DD0(0,9); +U+9DD1(0);U+9DD1(0,9); +U+9DD2(0);U+9DD2(0,9); +U+9DD3(0);U+9DD3(0,9);U+9E67(1,3,8) +U+9DD4(0);U+9DD4(3); +U+9DD5(0);U+9DD5(0,9); +U+9DD6(0);U+9DD6(0,9);U+9E65(1,3,8) +U+9DD7(0);U+9DD7(0,9);U+9E25(1,3,8) +U+9DD8(0);U+9DD8(0,9);U+9D92(3,9) +U+9DD9(0);U+9DD9(0,9);U+9E37(1,3,8) +U+9DDA(0);U+9DDA(0,9);U+9E68(1,3,8) +U+9DDB(0);U+9DDB(0,9); +U+9DDC(0);U+9DDC(0,9); +U+9DDD(0);U+9DDD(0,9); +U+9DDE(0);U+9DDE(3,9); +U+9DDF(0);U+9DDF(0,9); +U+9DE0(0);U+9DE0(0); +U+9DE1(0);U+9DE1(0,9); +U+9DE2(0);U+9DE2(0,9); +U+9DE3(0);U+9DE3(0,9); +U+9DE4(0);U+9DE4(0,9); +U+9DE5(0);U+9DE5(0,9);U+9E36(1,3,8) +U+9DE6(0);U+9DE6(0,9);U+9E6A(1,3,8) +U+9DE7(0);U+9DE7(0); +U+9DE8(0);U+9DE8(0,9); +U+9DE9(0);U+9DE9(0,9); +U+9DEB(0);U+9DEB(0,9);U+9E54(4,8) +U+9DEC(0);U+9DEC(0,9); +U+9DED(0);U+9DED(0,9); +U+9DEE(0);U+9DEE(0,9); +U+9DEF(0);U+9DEF(0,9);U+9E69(1,3,8) +U+9DF0(0);U+9DF0(0,9);U+71D5(2,3,8,9),U+89FE(2,3,8,9) +U+9DF1(0);U+9DF1(3); +U+9DF2(0);U+9DF2(0,9);U+9E6B(1,3,8) +U+9DF3(0);U+9DF3(0,9);U+9E47(1,3,8),U+9DF4(1,3,8,9) +U+9DF4(0);U+9DF4(0,9);U+9E47(1),U+9DF3(0,1,3,8,9) +U+9DF5(0);U+9DF5(0,9); +U+9DF6(0);U+9DF6(0,9); +U+9DF7(0);U+9DF7(3,9); +U+9DF8(0);U+9DF8(0,9);U+9E6C(1,3,8) +U+9DF9(0);U+9DF9(0,9);U+9E70(1,3,8) + +U+9DFA(0);U+9DFA(0,9);U+9E6D(1,3,8) +U+9DFB(0);U+9DFB(3,9); +U+9DFD(0);U+9DFD(0,9);U+9E34(4,8) +U+9DFE(0);U+9DFE(0,9); +U+9DFF(0);U+9DFF(0,9);U+4D19(3),U+9E0A(1,3) +U+9E00(0);U+9E00(0,9); +U+9E01(0);U+9E01(0,9); +U+9E02(0);U+9E02(0,9); +U+9E03(0);U+9E03(0,9); +U+9E04(0);U+9E04(0,9); +U+9E05(0);U+9E05(0,9); +U+9E06(0);U+9E06(0,9); +U+9E07(0);U+9E07(0,9);U+9E6F(1,3,8) +U+9E08(0);U+9E08(0); +U+9E09(0);U+9E09(3,9); +U+9E0A(0);U+9E0A(0);U+4D19(1,3),U+9DFF(1,3,9) +U+9E0B(0);U+9E0B(0,9); +U+9E0C(0);U+9E0C(0);U+9E71(4,8) +U+9E0D(0);U+9E0D(3,9); +U+9E0F(0);U+9E0F(0,9);U+9E72(4,8) +U+9E10(0);U+9E10(0,9); +U+9E11(0);U+9E11(0,9); +U+9E12(0);U+9E12(0,9); +U+9E13(0);U+9E13(3,9); +U+9E14(0);U+9E14(0,9); +U+9E15(0);U+9E15(0,9);U+9E2C(1,3,8) +U+9E17(0);U+9E17(0,9); +U+9E18(0);U+9E18(0);U+9E74(4,8) +U+9E19(0);U+9E19(0,9); +U+9E1A(0);U+9E1A(0,9);U+9E66(1,3,8) +U+9E1B(0);U+9E1B(0,9);U+9E73(1,3,8) +U+9E1D(0);U+9E1D(0,9);U+9E42(1,3,8) +U+9E1E(0);U+9E1E(0,9);U+9D49(4,8),U+9E3E(1,3,8) +U+9E1F(0);U+9CE5(1,3,8,9);U+9CE5(1,3,8,9) +U+9E20(0);U+9CE9(1,3,8,9);U+9CE9(1,3,8,9) +U+9E21(0);U+96DE(4,8,9);U+96DE(4,8,9),U+9CEE(4),U+9DC4(1,3,8) +U+9E22(0);U+9CF6(1,3,8,9);U+9CF6(1,3,8,9) +U+9E23(0);U+9CF4(1,3,8,9);U+9CF4(1,3,8,9) +U+9E24(0);U+9CF2(4,8,9);U+9CF2(4,8,9) +U+9E25(0);U+9DD7(1,3,8,9);U+9DD7(1,3,8,9) +U+9E26(0);U+9D09(1,3,8,9);U+9D09(1,3,8,9),U+9D76(4) +U+9E27(0);U+9DAC(1,3,8,9);U+9DAC(1,3,8,9) +U+9E28(0);U+9D07(1,3,8,9);U+9CF5(3,9),U+9D07(1,3,8,9) +U+9E29(0);U+9D06(1,3,8,9);U+9D06(1,3,8,9) +U+9E2A(0);U+9D23(1,3,8,9);U+9D23(1,3,8,9) +U+9E2B(0);U+9D87(1,3,8,9);U+9D87(1,3,8,9) +U+9E2C(0);U+9E15(1,3,8,9);U+9E15(1,3,8,9) +U+9E2D(0);U+9D28(1,3,8,9);U+9D28(1,3,8,9) +U+9E2E(0);U+9D1E(1,3,8,9);U+9D1E(1,3,8,9) +U+9E2F(0);U+9D26(1,3,8,9);U+9D26(1,3,8,9) +U+9E30(0);U+9D12(1,3,8,9);U+9D12(1,3,8,9) +U+9E31(0);U+9D1F(1,3,8,9);U+9D1F(1,3,8,9) +U+9E32(0);U+9D1D(1,3,8,9);U+9D1D(1,3,8,9) +U+9E33(0);U+9D1B(1,3,8,9);U+9D1B(1,3,8,9) +U+9E34(0);U+9DFD(4,8,9);U+9DFD(4,8,9) +U+9E35(0);U+9D15(1,3,8,9);U+9D15(1,3,8,9) +U+9E36(0);U+9DE5(1,3,8,9);U+9DE5(1,3,8,9) +U+9E37(0);U+9DD9(1,3,8,9);U+9DD9(1,3,8,9) +U+9E38(0);U+9D2F(1,3,8,9);U+9D2F(1,3,8,9) +U+9E39(0);U+9D30(1,3,8,9);U+9D30(1,3,8,9) +U+9E3A(0);U+9D42(1,3,8,9);U+9D42(1,3,8,9) +U+9E3B(0);U+9D34(1,3);U+9D34(1,3) +U+9E3C(0);U+9D43(1,3,8,9);U+9D43(1,3,8,9) + +U+9E3D(0);U+9D3F(1,3,8,9);U+9D3F(1,3,8,9) +U+9E3E(0);U+9E1E(1,3,8,9);U+9D49(4),U+9E1E(1,3,8,9) +U+9E3F(0);U+9D3B(1,3,8,9);U+9D3B(1,3,8,9) +U+9E40(0);U+9D50(4,8);U+9D50(4,8) +U+9E41(0);U+9D53(1,3,8,9);U+9D53(1,3,8,9) +U+9E42(0);U+9E1D(1,3,8,9);U+9E1D(1,3,8,9) +U+9E43(0);U+9D51(1,3,8,9);U+9D51(1,3,8,9) +U+9E44(0);U+9D60(1,3,8,9);U+9D60(1,3,8,9) +U+9E45(0);U+9D5D(1,3,8,9);U+9D5D(1,3,8,9),U+9D5E(4) +U+9E46(0);U+9D52(1,3,8,9);U+9D52(1,3,8,9) +U+9E47(0);U+9DF4(1,9);U+9DF4(1,9),U+9DF3(1,3,8,9) +U+9E48(0);U+9D5C(1,3,8,9);U+9D5C(1,3,8,9) +U+9E49(0);U+9D61(1,3,8,9);U+9D61(1,3,8,9) +U+9E4A(0);U+9D72(1,3,8,9);U+9D72(1,3,8,9) +U+9E4B(0);U+9D93(1,3,8);U+9D93(1,3,8) +U+9E4C(0);U+9D6A(1,3,8,9);U+9D6A(1,3,8,9) +U+9E4D(0);U+9D7E(4,8);U+9D7E(4,8),U+9DA4(4,9) +U+9E4E(0);U+9D6F(4,8,9);U+9D6F(4,8,9) +U+9E4F(0);U+9D6C(1,3,8,9);U+9D6C(1,3,8,9) +U+9E50(0);U+9D6E(1,3,8);U+9D6E(1,3,8) +U+9E51(0);U+9D89(1,3,8,9);U+9D89(1,3,8,9) +U+9E52(0);U+9D8A(1,3,8,9);U+9D8A(1,3,8,9) +U+9E53(0);U+9D77(4,8,9);U+9D77(4,8,9) +U+9E54(0);U+9DEB(4,8,9);U+9DEB(4,8,9) +U+9E55(0);U+9D98(1,3,8,9);U+9D98(1,3,8,9) +U+9E56(0);U+9DA1(1,3,8,9);U+9DA1(1,3,8,9) +U+9E57(0);U+9D9A(1,3,8,9);U+9D9A(1,3,8,9) +U+9E58(0);U+9DBB(1,3,8,9);U+9DBB(1,3,8,9) +U+9E59(0);U+9D96(1,3,8,9);U+9D96(1,3,8,9) +U+9E5A(0);U+9DBF(2,3,9);U+9DBF(2,3,9) +U+9E5B(0);U+9DA5(1,3,8);U+9DA5(1,3,8) +U+9E5C(0);U+9DA9(1,3,8,9);U+9DA9(1,3,8,9) +U+9E5D(0);U+9DCA(4,8,9);U+9DCA(4,8,9) +U+9E5E(0);U+9DC2(1,8,9);U+9DC2(1,8,9) +U+9E5F(0);U+9DB2(4,8,9);U+9DB2(4,8,9) +U+9E60(0);U+9DB9(4,8,9);U+9DB9(4,8,9) +U+9E61(0);U+9DBA(1,3,8,9);U+9DBA(1,3,8,9) +U+9E62(0);U+9DC1(4,8,9);U+9DC1(4,8,9) +U+9E63(0);U+9DBC(1,3,8,9);U+9DBC(1,3,8,9) +U+9E64(0);U+9DB4(1,3,8,9);U+9DB4(1,3,8,9) +U+9E65(0);U+9DD6(1,3,8,9);U+9DD6(1,3,8,9) +U+9E66(0);U+9E1A(1,3,8,9);U+9E1A(1,3,8,9) +U+9E67(0);U+9DD3(1,3,8,9);U+9DD3(1,3,8,9) +U+9E68(0);U+9DDA(1,3,8,9);U+9DDA(1,3,8,9) +U+9E69(0);U+9DEF(1,3,8,9);U+9DEF(1,3,8,9) +U+9E6A(0);U+9DE6(1,3,8,9);U+9DE6(1,3,8,9) +U+9E6B(0);U+9DF2(1,3,8,9);U+9DF2(1,3,8,9) +U+9E6C(0);U+9DF8(1,3,8,9);U+9DF8(1,3,8,9) +U+9E6D(0);U+9DFA(1,3,8,9);U+9DFA(1,3,8,9) +U+9E6E(0);U+9E6E(6); +U+9E6F(0);U+9E07(1,3,8,9);U+9E07(1,3,8,9) +U+9E70(0);U+9DF9(1,3,8,9);U+9DF9(1,3,8,9) +U+9E71(0);U+9E0C(4,8);U+9E0C(4,8) +U+9E72(0);U+9E0F(4,8,9);U+9E0F(4,8,9) +U+9E73(0);U+9E1B(1,3,8,9);U+9E1B(1,3,8,9) +U+9E74(0);U+9E18(4,8);U+9E18(4,8) +U+9E75(0);U+9E75(0,9);U+5364(1,3),U+6EF7(4,9) +U+9E76(0);U+9E76(0); +U+9E77(0);U+9E77(0); +U+9E79(0);U+9E79(0,9);U+54B8(1,3,8,9) +U+9E7A(0);U+9E7A(0,9);U+9E7E(1,3,8) +U+9E7C(0);U+9E7C(0,9);U+7877(1,3,8),U+78B1(3,4,8),U+7906(1,3,4,8),U+96AA(1,3,4,8,9),U+9669(1,3,4,8) + +U+9E7D(0);U+9E7D(0,9);U+5869(3,8),U+76D0(1,3,8) +U+9E7E(0);U+9E7A(1,3,8,9);U+9E7A(1,3,8,9) +U+9E7F(0);U+9E7F(5,9); +U+9E80(0);U+9E80(0,9); +U+9E81(0);U+7C97(4,8,9);U+7C97(4,8,9),U+850D(3,4,8,9),U+89D5(2,3,4,8,9),U+9E84(3,4,8),U+9E86(3,4,8,9),U+9EA4(2,3,4,8,9) + +U+9E82(0);U+9E82(5,9); +U+9E83(0);U+9E83(0,9); +U+9E84(0);U+7C97(3,8,9);U+7C97(3,8,9),U+850D(3,8,9),U+89D5(2,3,8,9),U+9E81(3,4,8),U+9E86(3,8,9),U+9EA4(2,3,8,9) + +U+9E85(0);U+9E85(3); +U+9E86(0);U+9E86(0,9);U+7C97(3,9),U+850D(3,9),U+89D5(2,3,9),U+9E81(3,4,8),U+9E84(3,8),U+9EA4(2,3,9) + +U+9E87(0);U+9E87(5,9); +U+9E88(0);U+9E88(5,9); +U+9E89(0);U+9E89(0,9); +U+9E8A(0);U+9E8A(0,9);U+9E8B(3,9) +U+9E8B(0);U+9E8B(5,9);U+9E8A(3,9) +U+9E8C(0);U+9E8C(0,9); +U+9E8D(0);U+9E8D(0,9); +U+9E8E(0);U+9E8E(0,9); +U+9E91(0);U+9E91(0,9); +U+9E92(0);U+9E92(5,9); +U+9E93(0);U+9E93(5,9); +U+9E94(0);U+9E94(0,9); +U+9E96(0);U+9E96(4);U+9EA0(4,9) +U+9E97(0);U+9E97(0,9);U+4E3D(1,3,8) +U+9E99(0);U+9E99(0,9); +U+9E9A(0);U+9E9A(0,9); +U+9E9B(0);U+9E9B(3,9); +U+9E9C(0);U+9E9C(0,9); +U+9E9D(0);U+9E9D(5,9); +U+9E9F(0);U+9E9F(5,9); +U+9EA0(0);U+9EA0(0,9);U+9E96(4) +U+9EA1(0);U+9EA1(0,9); +U+9EA3(0);U+9EA3(0); +U+9EA4(0);U+9EA4(0,9);U+7C97(2,3,9),U+850D(2,3,9),U+89D5(2,3,9),U+9E81(2,3,4,8),U+9E84(2,3,8),U+9E86(2,3,9) + +U+9EA5(0);U+9EA5(0,9);U+9EA6(1,3,8) +U+9EA6(0);U+9EA5(1,3,8,9);U+9EA5(1,3,8,9) +U+9EA7(0);U+9EA7(3,9); +U+9EA8(0);U+9EA8(0); +U+9EA9(0);U+9EA9(0,9);U+9EB8(1,3,8) +U+9EAA(0);U+9EB5(2,3,8,9);U+9762(4,9),U+9EB5(2,3,8,9) +U+9EAD(0);U+9EAD(0,9); +U+9EAE(0);U+9EAE(0,9); +U+9EAF(0);U+66F2(1,3,9);U+66F2(1,3,9),U+9EB4(1,3,4,9) +U+9EB0(0);U+9EB0(3,9); +U+9EB2(0);U+9EB2(0); +U+9EB3(0);U+9EB3(0); +U+9EB4(0);U+9EB4(0,9);U+66F2(4,9),U+9EAF(1,3,4) +U+9EB5(0);U+9EB5(0,9);U+9762(1,3,8,9),U+9EAA(2,3,8) +U+9EB6(0);U+9EB6(0,9); +U+9EB7(0);U+9EB7(0,9); +U+9EB8(0);U+9EA9(1,3,8,9);U+9EA9(1,3,8,9) +U+9EBB(0);U+9EBB(5,9);U+75F2(3,9),U+75F3(4,9),U+8534(2,3),U+6DCB(2,3,4,5,9) +U+9EBC(0);U+9EBC(0,9);U+4E48(4,8,9),U+5E85(8),U+9EBD(3,8),U+5E7A(3,4,8) +U+9EBD(0);U+9EBC(3,8,9);U+4E48(1,3,8,9),U+5E85(4),U+9EBC(3,8,9),U+5E7A(1,3,8) +U+9EBE(0);U+9EBE(5,9); +U+9EBF(0);U+9EBF(0); +U+9EC0(0);U+9EC0(3,9); +U+9EC1(0);U+9EC1(0); +U+9EC2(0);U+9EC2(0,9); + +U+9EC3(0);U+9EC3(0,9);U+9EC4(4,8) +U+9EC4(0);U+9EC3(4,8,9);U+9EC3(4,8,9) +U+9EC5(0);U+9EC5(0); +U+9EC6(0);U+9EC6(0); +U+9EC7(0);U+9EC7(0); +U+9EC8(0);U+9EC8(0,9); +U+9EC9(0);U+9ECC(1,3,8,9);U+9ECC(1,3,8,9) +U+9ECA(0);U+9ECA(0); +U+9ECB(0);U+9ECB(0); +U+9ECC(0);U+9ECC(0,9);U+9EC9(1,3,8) +U+9ECD(0);U+9ECD(5,9); +U+9ECE(0);U+9ECE(5,9);U+83DE(3,9) +U+9ECF(0);U+9ECF(5,9); +U+9ED0(0);U+9ED0(3,9); +U+9ED1(0);U+9ED1(5,9);U+9ED2(4,8) +U+9ED2(0);U+9ED1(4,8,9);U+9ED1(4,8,9) +U+9ED3(0);U+9ED3(3,9); +U+9ED4(0);U+9ED4(5,9);U+8EE1(3,9) +U+9ED5(0);U+9ED5(0,9); +U+9ED6(0);U+9ED6(0,9); +U+9ED7(0);U+9ED7(0); +U+9ED8(0);U+9ED8(5,9);U+9ED9(4,8) +U+9ED9(0);U+9ED8(4,8,9);U+9ED8(4,8,9) +U+9EDA(0);U+9EDA(0,9); +U+9EDB(0);U+9EDB(5,9); +U+9EDC(0);U+9EDC(5,9); +U+9EDD(0);U+9EDD(5,9); +U+9EDE(0);U+9EDE(0,9);U+594C(4,8),U+70B9(1,3,8) +U+9EDF(0);U+9EDF(5,9); +U+9EE0(0);U+9EE0(5,9); +U+9EE1(0);U+9EF6(1,3,8,9);U+9EF6(1,3,8,9) +U+9EE2(0);U+9EE2(5); +U+9EE3(0);U+9EE3(0); +U+9EE4(0);U+9EE4(0,9); +U+9EE5(0);U+9EE5(5,9); +U+9EE6(0);U+9EE6(0,9); +U+9EE7(0);U+9EE7(5,9); +U+9EE8(0);U+9EE8(0,9);U+515A(1,3,8,9) +U+9EE9(0);U+9EF7(1,3,8,9);U+9EF7(1,3,8,9) +U+9EEA(0);U+9EF2(4,8,9);U+9EF2(4,8,9) +U+9EEB(0);U+9EEB(0,9); +U+9EED(0);U+9EED(0,9); +U+9EEE(0);U+9EEE(0,9); +U+9EEF(0);U+9EEF(5,9); +U+9EF0(0);U+9EF0(3,9); +U+9EF2(0);U+9EF2(0,9);U+9EEA(4,8) +U+9EF3(0);U+9EF3(0,9); +U+9EF4(0);U+9EF4(0,9);U+9709(1,3,9) +U+9EF5(0);U+9EF5(0,9); +U+9EF6(0);U+9EF6(0,9);U+9EE1(1,3,8) +U+9EF7(0);U+9EF7(0,9);U+9EE9(1,3,8) +U+9EF8(0);U+9EF8(0); +U+9EF9(0);U+9EF9(5,9); +U+9EFA(0);U+9EFA(0,9); +U+9EFB(0);U+9EFB(5,9); +U+9EFC(0);U+9EFC(5,9); +U+9EFD(0);U+9EFD(0,9);U+9EFE(1,3,8) +U+9EFE(0);U+9EFD(1,3,8,9);U+9EFD(1,3,8,9) +U+9EFF(0);U+9EFF(0,9);U+9F0B(1,3,8) +U+9F00(0);U+9F00(0,9); +U+9F01(0);U+9F01(0,9); +U+9F02(0);U+9F02(0);U+9F0C(4,8) +U+9F04(0);U+86DB(3,8,9);U+86DB(3,8,9) + +U+9F05(0);U+8718(3,8,9);U+8718(3,8,9) +U+9F06(0);U+9F06(0,9); +U+9F07(0);U+9F07(0,9);U+9CCC(4),U+9C32(0,1,3,4,8,9) +U+9F08(0);U+9C49(3,4,8,9);U+9C49(3,4,8,9),U+9CD6(1,3,4,8),U+9F9E(3,4,8) +U+9F09(0);U+9F09(0,9);U+9F0D(1,3,8) +U+9F0A(0);U+9F0A(0,9); +U+9F0B(0);U+9EFF(1,3,8,9);U+9EFF(1,3,8,9) +U+9F0C(0);U+9F02(4,8);U+9F02(4,8) +U+9F0D(0);U+9F09(1,3,8,9);U+9F09(1,3,8,9) +U+9F0E(0);U+9F0E(5,9); +U+9F0F(0);U+9F0F(0,9); +U+9F10(0);U+9F10(5,9); +U+9F12(0);U+9F12(3,9); +U+9F13(0);U+9F13(5,9);U+76B7(2,3,8),U+76BC(7,8) +U+9F15(0);U+9F15(0,9);U+51AC(1,3,8,9) +U+9F16(0);U+9F16(0,9); +U+9F17(0);U+9F17(5);U+9780(3,9) +U+9F18(0);U+9F18(3,9); +U+9F19(0);U+9F19(5,9); +U+9F1A(0);U+9F1A(0,9); +U+9F1B(0);U+9F1B(3,9); +U+9F1C(0);U+9F1C(0,9); +U+9F1D(0);U+9F1D(0); +U+9F1E(0);U+9F1E(4,9); +U+9F1F(0);U+9F1F(0); +U+9F20(0);U+9F20(5,9); +U+9F22(0);U+9F22(5,9); +U+9F23(0);U+9F23(0,9); +U+9F24(0);U+9F24(0,9); +U+9F25(0);U+9F25(0,9); +U+9F27(0);U+9F27(0); +U+9F28(0);U+9F28(0,9); +U+9F29(0);U+9F29(0,9); +U+9F2A(0);U+9F2A(3,9); +U+9F2B(0);U+9F2B(0,9); +U+9F2C(0);U+9F2C(5,9); +U+9F2D(0);U+9F2D(0,9); +U+9F2E(0);U+9F2E(0,9); +U+9F2F(0);U+9F2F(5,9); +U+9F30(0);U+9F30(0,9);U+9F33(4,9) +U+9F31(0);U+9F31(0,9); +U+9F32(0);U+9F32(0,9); +U+9F33(0);U+9F33(0,9);U+9F30(4,9) +U+9F34(0);U+9F34(0,9);U+9F39(2,3) +U+9F35(0);U+9F35(0,9); +U+9F36(0);U+9F36(0,9); +U+9F37(0);U+9F37(5,9); +U+9F38(0);U+9F38(0,9); +U+9F39(0);U+9F39(5);U+9F34(2,3,9) +U+9F3A(0);U+9F3A(0); +U+9F3B(0);U+9F3B(5,9); +U+9F3C(0);U+9F3C(0); +U+9F3D(0);U+9F3D(5,9); +U+9F3E(0);U+9F3E(5,9);U+54FB(3,9) +U+9F3F(0);U+9F3F(0);U+9F40(4,9) +U+9F40(0);U+9F40(0,9);U+9F3F(4) +U+9F41(0);U+9F41(0,9); +U+9F42(0);U+9F42(3,9); +U+9F43(0);U+9F43(0,9);U+981E(3,9) +U+9F44(0);U+9F44(5); +U+9F46(0);U+9F46(0,9); +U+9F47(0);U+9F47(3,9); +U+9F48(0);U+9F48(0,9); + +U+9F49(0);U+9F49(3,9); +U+9F4A(0);U+9F4A(0,9);U+4E9D(3,8),U+6589(3,8),U+9F50(1,3,8) +U+9F4B(0);U+9F4B(0,9);U+658B(1,3,8),U+658E(4,8) +U+9F4C(0);U+9F4C(0,9); +U+9F4D(0);U+9F4D(3,9); +U+9F4E(0);U+9F4E(0,9);U+8D4D(3),U+8CEB(0,1,3,8) +U+9F4F(0);U+9F4F(0,9);U+97F2(3,8),U+9F51(1,8),U+8640(0,1,3,8,9) +U+9F50(0);U+9F4A(1,3,8,9);U+4E9D(3,4),U+6589(3),U+9F4A(1,3,8,9) +U+9F51(0);U+9F4F(1,8,9);U+8640(3,9),U+97F2(3),U+9F4F(1,8,9) +U+9F52(0);U+9F52(0,9);U+6B6F(3,8),U+9F7F(1,3,8) +U+9F54(0);U+9F54(0,9);U+9F80(1,3,8) +U+9F55(0);U+9F55(0,9);U+9F81(4,8) +U+9F56(0);U+9F56(0,9); +U+9F57(0);U+9F57(0,9);U+9F82(4,8) +U+9F58(0);U+9F58(3,9); +U+9F59(0);U+9F59(0,9);U+9F85(1,3,8) +U+9F5A(0);U+9F5A(0); +U+9F5B(0);U+9F5B(3,9);U+9F65(3,9) +U+9F5C(0);U+9F5C(0,9);U+9F87(1,3,8) +U+9F5D(0);U+9F5D(3,9); +U+9F5E(0);U+9F5E(3,9); +U+9F5F(0);U+9F5F(0,9);U+9F83(1,3,8) +U+9F60(0);U+9F60(0,9);U+9F86(1,3,8) +U+9F61(0);U+9F61(0,9);U+9F84(1,3,8) +U+9F63(0);U+9F63(0,9);U+51FA(1,3,9),U+5C80(3) +U+9F64(0);U+9F64(0,9); +U+9F65(0);U+9F65(0,9);U+9F5B(3,9) +U+9F66(0);U+9F66(0,9);U+9F88(1,3,8) +U+9F67(0);U+9F67(0,9);U+556E(4),U+5699(2,3,8,9),U+56D3(3,9) +U+9F68(0);U+9F68(0); +U+9F69(0);U+54AC(2,3,8,9);U+54AC(2,3,8,9) +U+9F6A(0);U+9F6A(0,9);U+9F8A(1,3,8),U+8E00(0,1,3,8,9) +U+9F6B(0);U+9F6B(0,9);U+9F73(3) +U+9F6C(0);U+9F6C(0,9);U+9F89(1,3,8) +U+9F6E(0);U+9F6E(0,9); +U+9F6F(0);U+9F6F(3,9); +U+9F70(0);U+9F70(3,9); +U+9F71(0);U+9F71(0,9); +U+9F72(0);U+9F72(0,9);U+9F8B(1,3,8) +U+9F73(0);U+9F73(3);U+9F6B(3,9) +U+9F74(0);U+9F74(3,9); +U+9F75(0);U+9F75(0,9); +U+9F76(0);U+9F76(0,9);U+816D(2,3) +U+9F77(0);U+9F77(0,9);U+9F8C(1,3,8) +U+9F78(0);U+9F78(0,9); +U+9F79(0);U+9F79(0,9); +U+9F7A(0);U+9F7A(0,9); +U+9F7B(0);U+9F7B(0,9); +U+9F7C(0);U+9F7C(4); +U+9F7D(0);U+9F7D(0); +U+9F7E(0);U+9F7E(0,9); +U+9F7F(0);U+9F52(1,3,8,9);U+6B6F(3),U+9F52(1,3,8,9) +U+9F80(0);U+9F54(1,3,8,9);U+9F54(1,3,8,9) +U+9F81(0);U+9F55(4,8,9);U+9F55(4,8,9) +U+9F82(0);U+9F57(4,8,9);U+9F57(4,8,9) +U+9F83(0);U+9F5F(1,3,8,9);U+9F5F(1,3,8,9) +U+9F84(0);U+9F61(1,3,8,9);U+9F61(1,3,8,9) +U+9F85(0);U+9F59(1,3,8,9);U+9F59(1,3,8,9) +U+9F86(0);U+9F60(1,3,8,9);U+9F60(1,3,8,9) +U+9F87(0);U+9F5C(1,3,8,9);U+9F5C(1,3,8,9) +U+9F88(0);U+9F66(1,3,8,9);U+9F66(1,3,8,9) +U+9F89(0);U+9F6C(1,3,8,9);U+9F6C(1,3,8,9) +U+9F8A(0);U+9F6A(1,3,8,9);U+8E00(3,9),U+9F6A(1,3,8,9) + +U+9F8B(0);U+9F72(1,3,8,9);U+9F72(1,3,8,9) +U+9F8C(0);U+9F77(1,3,8,9);U+9F77(1,3,8,9) +U+9F8D(0);U+9F8D(0,9);U+7ADC(3,8),U+9F99(1,3,8),U+9F92(3,8,9) +U+9F8E(0);U+9F90(4,8,9);U+5390(4),U+5E9E(7),U+9F90(4,8,9) +U+9F8F(0);U+9F8F(0); +U+9F90(0);U+9F90(0,9);U+5390(8),U+5E9E(1,3,8),U+9F8E(4,8) +U+9F91(0);U+9F91(0,9);U+4DAE(1,3) +U+9F92(0);U+9F92(0,9);U+9F99(3),U+7ADC(0,3),U+9F8D(3,8,9) +U+9F93(0);U+9F93(0); +U+9F94(0);U+9F94(0,9);U+9F9A(1,3,8) +U+9F95(0);U+9F95(0,9);U+9F9B(1,3,8) +U+9F96(0);U+9F96(4);U+9F98(4,9) +U+9F97(0);U+9F97(3); +U+9F98(0);U+9F98(0,9);U+9F96(4) +U+9F99(0);U+9F8D(1,3,8,9);U+9F92(3,9),U+7ADC(7),U+9F8D(1,3,8,9) +U+9F9A(0);U+9F94(1,3,8,9);U+9F94(1,3,8,9) +U+9F9B(0);U+9F95(1,3,8,9);U+9F95(1,3,8,9) +U+9F9C(0);U+9F9C(0,9);U+4E80(4,8),U+9F9F(1,8) +U+9F9D(0);U+79CB(7,8,9);U+79CB(7,8,9),U+7A50(4),U+97A6(1,3,4,7,8,9) +U+9F9E(0);U+9C49(3,8,9);U+9C49(3,8,9),U+9CD6(3),U+9F08(3,4,8) +U+9F9F(0);U+9F9C(1,8,9);U+4E80(4),U+9F9C(1,8,9) +U+9FA0(0);U+9FA0(5,9); +U+9FA2(0);U+9FA2(0,9);U+548C(2,3,8,9),U+924C(2,3,8,9) +U+9FA4(0);U+9FA4(0,9); +U+9FA5(0);U+9FA5(0); diff --git a/java/com/google/domain/registry/keyring/api/BUILD b/java/com/google/domain/registry/keyring/api/BUILD new file mode 100644 index 000000000..c2663d359 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/BUILD @@ -0,0 +1,16 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "api", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//third_party/java/bouncycastle", + "//third_party/java/bouncycastle_bcpg", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + ], +) diff --git a/java/com/google/domain/registry/keyring/api/KeyModule.java b/java/com/google/domain/registry/keyring/api/KeyModule.java new file mode 100644 index 000000000..59f6dd394 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/KeyModule.java @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.keyring.api; + +import static com.google.common.base.Strings.emptyToNull; + +import com.google.common.base.Optional; + +import dagger.Module; +import dagger.Provides; + +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** Dagger module for keys stored in {@link Keyring}. */ +@Module +public final class KeyModule { + + /** Dagger qualifier for keys from {@link Keyring}. */ + @Qualifier + @Documented + public static @interface Key { + String value(); + } + + @Provides + @Key("brdaReceiverKey") + static PGPPublicKey provideBrdaReceiverKey(Keyring keyring) { + return keyring.getBrdaReceiverKey(); + } + + @Provides + @Key("brdaSigningKey") + static PGPKeyPair provideBrdaSigningKey(Keyring keyring) { + return keyring.getBrdaSigningKey(); + } + + @Provides + @Key("icannReportingPassword") + static String provideIcannReportingPassword(Keyring keyring) { + return keyring.getIcannReportingPassword(); + } + + @Provides + @Key("marksdbDnlLogin") + static Optional provideMarksdbDnlLogin(Keyring keyring) { + return Optional.fromNullable(emptyToNull(keyring.getMarksdbDnlLogin())); + } + + @Provides + @Key("marksdbLordnPassword") + static Optional provideMarksdbLordnPassword(Keyring keyring) { + return Optional.fromNullable(emptyToNull(keyring.getMarksdbLordnPassword())); + } + + @Provides + @Key("marksdbSmdrlLogin") + static Optional provideMarksdbSmdrlLogin(Keyring keyring) { + return Optional.fromNullable(emptyToNull(keyring.getMarksdbSmdrlLogin())); + } + + @Provides + @Key("rdeStagingEncryptionKey") + static PGPPublicKey provideRdeStagingEncryptionKey(Keyring keyring) { + return keyring.getRdeStagingEncryptionKey(); + } + + @Provides + @Key("rdeStagingEncryptionKey") + static byte[] provideRdeStagingEncryptionKeyAsBytes( + @Key("rdeStagingEncryptionKey") PGPPublicKey rdeStagingEncryptionKey) { + return PgpHelper.convertPublicKeyToBytes(rdeStagingEncryptionKey); + } + + @Provides + @Key("rdeStagingDecryptionKey") + static PGPPrivateKey provideRdeStagingDecryptionKey(Keyring keyring) { + return keyring.getRdeStagingDecryptionKey(); + } + + @Provides + @Key("rdeReceiverKey") + static PGPPublicKey provideRdeReceiverKey(Keyring keyring) { + return keyring.getRdeReceiverKey(); + } + + @Provides + @Key("rdeSigningKey") + static PGPKeyPair provideRdeSigningKey(Keyring keyring) { + return keyring.getRdeSigningKey(); + } + + @Provides + @Key("rdeSshClientPrivateKey") + static String provideRdeSshClientPrivateKey(Keyring keyring) { + return keyring.getRdeSshClientPrivateKey(); + } + + @Provides + @Key("rdeSshClientPublicKey") + static String provideRdeSshClientPublicKey(Keyring keyring) { + return keyring.getRdeSshClientPublicKey(); + } + + @Provides + @Key("jsonCredential") + static String provideJsonCredential(Keyring keyring) { + return keyring.getJsonCredential(); + } + + @Provides + @Key("braintreePrivateKey") + static String provideBraintreePrivateKey(Keyring keyring) { + return keyring.getBraintreePrivateKey(); + } +} diff --git a/java/com/google/domain/registry/keyring/api/Keyring.java b/java/com/google/domain/registry/keyring/api/Keyring.java new file mode 100644 index 000000000..6bb89509c --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/Keyring.java @@ -0,0 +1,165 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.keyring.api; + +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; + +import javax.annotation.concurrent.ThreadSafe; + +/** + * Domain Registry keyring interface. + * + *

Separate methods are defined for each specific situation in which the + * registry server needs a secret value, like a PGP key or password. + */ +@ThreadSafe +public interface Keyring extends AutoCloseable { + + /** + * Returns the key which should be used to sign RDE deposits being uploaded to a third-party. + * + *

When we give all our data to the escrow provider, they'll need + * a signature to ensure the data is authentic. + * + *

This keypair should only be known to the domain registry shared + * registry system. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + PGPKeyPair getRdeSigningKey(); + + /** + * Returns public key for encrypting escrow deposits being staged to cloud storage. + * + *

This adds an additional layer of security so cloud storage administrators + * won't be tempted to go poking around the App Engine Cloud Console and see a + * dump of the entire database. + * + *

This keypair should only be known to the domain registry shared + * registry system. + * + * @see #getRdeStagingDecryptionKey() + */ + PGPPublicKey getRdeStagingEncryptionKey(); + + /** + * Returns private key for decrypting escrow deposits retrieved from cloud storage. + * + *

This method may impose restrictions on who can call it. For example, we'd want + * to check that the caller isn't an HTTP request attacking a vulnerability in the + * admin console. The request should originate from a backend task queue servlet + * invocation of the RDE upload thing. + * + * @see #getRdeStagingEncryptionKey() + * @see com.google.domain.registry.rde.RdeUploadTask + */ + PGPPrivateKey getRdeStagingDecryptionKey(); + + /** + * Returns public key of escrow agent for encrypting deposits as they're uploaded. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + PGPPublicKey getRdeReceiverKey(); + + /** + * Returns the PGP key we use to sign Bulk Registration Data Access (BRDA) deposits. + * + * @see com.google.domain.registry.rde.BrdaCopyTask + */ + PGPKeyPair getBrdaSigningKey(); + + /** + * Returns public key of receiver of Bulk Registration Data Access (BRDA) deposits. + * + * @see com.google.domain.registry.rde.BrdaCopyTask + */ + PGPPublicKey getBrdaReceiverKey(); + + /** + * Returns public key for SSH client connections made by RDE. + * + *

This is a string containing what would otherwise be the contents of an + * {@code ~/.ssh/id_rsa.pub} file. It's usually a single line with the name of + * the algorithm, the base64 key, and the email address of the owner. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + String getRdeSshClientPublicKey(); + + /** + * Returns private key for SSH client connections made by RDE. + * + *

This is a string containing what would otherwise be the contents of an + * {@code ~/.ssh/id_rsa} file. It's ASCII-armored text. + * + *

This method may impose restrictions on who can call it. For example, we'd want + * to check that the caller isn't an HTTP request attacking a vulnerability in the + * admin console. The request should originate from a backend task queue servlet + * invocation of the RDE upload thing. + * + * @see com.google.domain.registry.rde.RdeUploadTask + */ + String getRdeSshClientPrivateKey(); + + /** + * Returns password to be used when uploading reports to ICANN. + * + * @see com.google.domain.registry.rde.RdeReportTask + */ + String getIcannReportingPassword(); + + /** + * Returns {@code user:password} login for TMCH MarksDB HTTP server DNL interface. + * + * @see com.google.domain.registry.tmch.TmchDnlTask + */ + String getMarksdbDnlLogin(); + + /** + * Returns password for TMCH MarksDB HTTP server LORDN interface. + * + * @see "com.google.domain.registry.tmch.LordnRequestInitializer" + */ + String getMarksdbLordnPassword(); + + /** + * Returns {@code user:password} login for TMCH MarksDB HTTP server SMDRL interface. + * + * @see com.google.domain.registry.tmch.TmchSmdrlTask + */ + String getMarksdbSmdrlLogin(); + + /** + * Returns the credentials for a service account on the Google AppEngine project downloaded from + * the Cloud Console dashboard in JSON format. + */ + String getJsonCredential(); + + /** + * Returns Braintree API private key for Registry. + * + *

This is a base32 value copied from the Braintree website. + * + * @see com.google.domain.registry.config.ConfigModule#provideBraintreePublicKey + */ + String getBraintreePrivateKey(); + + // Don't throw so try-with-resources works better. + @Override + void close(); +} diff --git a/java/com/google/domain/registry/keyring/api/PgpHelper.java b/java/com/google/domain/registry/keyring/api/PgpHelper.java new file mode 100644 index 000000000..474424565 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/PgpHelper.java @@ -0,0 +1,176 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.keyring.api; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Verify.verify; +import static com.google.common.base.Verify.verifyNotNull; +import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.DSA; +import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.ELGAMAL_GENERAL; +import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_GENERAL; +import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_SIGN; + +import com.google.common.base.Optional; +import com.google.common.base.VerifyException; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRing; +import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; + +import java.io.IOException; +import java.util.Iterator; + +/** Helper functions for extracting PGP keys from their keyrings. */ +public final class PgpHelper { + + /** + * Narrowed key search requirements. + * @see PgpHelper#lookupPublicKey + */ + public static enum KeyRequirement { ENCRYPT, SIGN, ENCRYPT_SIGN } + + /** Converts {@code publicKey} to bytes. */ + public static byte[] convertPublicKeyToBytes(PGPPublicKey publicKey) { + try { + return publicKey.getEncoded(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** Returns raw key bytes as a Bouncy Castle PGP public key. */ + public static PGPPublicKey loadPublicKeyBytes(byte[] data) { + try { + return lookupPublicSubkey(new BcPGPPublicKeyRing(data), KeyRequirement.ENCRYPT).get(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Search for public key on keyring based on a substring (like an email address). + * + * @throws VerifyException if the key couldn't be found. + * @see #lookupKeyPair + */ + public static PGPPublicKey lookupPublicKey( + PGPPublicKeyRingCollection keyring, String query, KeyRequirement want) { + try { + // Safe by specification. + @SuppressWarnings("unchecked") + Iterator results = + keyring.getKeyRings(checkNotNull(query, "query"), true, true); + verify(results.hasNext(), "No public key found matching substring: %s", query); + while (results.hasNext()) { + Optional result = lookupPublicSubkey(results.next(), want); + if (result.isPresent()) { + return result.get(); + } + } + throw new VerifyException(String.format( + "No public key (%s) found matching substring: %s", want, query)); + } catch (PGPException e) { + throw new VerifyException(String.format( + "Public key lookup with query %s failed: %s", query, e.getMessage())); + } + } + + /** + * Same as {@link #lookupPublicKey} but also retrieves the associated private key. + * + * @throws VerifyException if either keys couldn't be found. + * @see #lookupPublicKey + */ + @SuppressWarnings("deprecation") + public static PGPKeyPair lookupKeyPair( + PGPPublicKeyRingCollection publics, + PGPSecretKeyRingCollection privates, + String query, + KeyRequirement want) { + PGPPublicKey publicKey = lookupPublicKey(publics, query, want); + PGPPrivateKey privateKey; + try { + PGPSecretKey secret = verifyNotNull(privates.getSecretKey(publicKey.getKeyID()), + "Keyring missing private key associated with public key id: %x (query '%s')", + publicKey.getKeyID(), query); + // We do not support putting a password on the private key so we're just going to + // put char[0] here. + privateKey = secret.extractPrivateKey( + new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()) + .build(new char[0])); + } catch (PGPException e) { + throw new VerifyException(e.getMessage()); + } + return new PGPKeyPair(publicKey, privateKey); + } + + /** + * Return appropriate key or subkey for given task from public key. + * + *

Weirder older PGP public keys will actually have multiple keys. The main key will usually + * be sign-only in such situations. So you've gotta go digging in through the key packets and + * make sure you get the one that's valid for encryption, or whatever you want to do. + */ + public static Optional lookupPublicSubkey( + PGPPublicKeyRing ring, KeyRequirement want) { + // Safe by specification. + @SuppressWarnings("unchecked") + Iterator keys = ring.getPublicKeys(); + while (keys.hasNext()) { + PGPPublicKey key = keys.next(); + switch (want) { + case ENCRYPT: + if (key.isEncryptionKey()) { + return Optional.of(key); + } + break; + case SIGN: + if (isSigningKey(key)) { + return Optional.of(key); + } + break; + case ENCRYPT_SIGN: + if (key.isEncryptionKey() && isSigningKey(key)) { + return Optional.of(key); + } + break; + default: + throw new AssertionError(); + } + } + return Optional.absent(); + } + + /** Returns {@code true} if this key can be used for signing. */ + public static boolean isSigningKey(PGPPublicKey key) { + switch (key.getAlgorithm()) { + case RSA_GENERAL: + case RSA_SIGN: + case DSA: + case ELGAMAL_GENERAL: + return true; + default: + return false; + } + } +} diff --git a/java/com/google/domain/registry/keyring/api/VoidKeyring.java b/java/com/google/domain/registry/keyring/api/VoidKeyring.java new file mode 100644 index 000000000..9a8937e75 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/VoidKeyring.java @@ -0,0 +1,116 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.keyring.api; + +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; + +import javax.annotation.concurrent.Immutable; + +/** {@link Keyring} that throws {@link UnsupportedOperationException} if any methods are called. */ +@Immutable +public final class VoidKeyring implements Keyring { + + private static final String ERROR = "Keyring support not loaded"; + + /** @throws UnsupportedOperationException always */ + @Override + public PGPKeyPair getRdeSigningKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public PGPKeyPair getBrdaSigningKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public PGPPublicKey getRdeStagingEncryptionKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public PGPPrivateKey getRdeStagingDecryptionKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public PGPPublicKey getRdeReceiverKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public PGPPublicKey getBrdaReceiverKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getRdeSshClientPublicKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getRdeSshClientPrivateKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getIcannReportingPassword() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getMarksdbDnlLogin() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getMarksdbLordnPassword() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getMarksdbSmdrlLogin() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getJsonCredential() { + throw new UnsupportedOperationException(ERROR); + } + + /** @throws UnsupportedOperationException always */ + @Override + public String getBraintreePrivateKey() { + throw new UnsupportedOperationException(ERROR); + } + + /** Does nothing. */ + @Override + public void close() {} +} diff --git a/java/com/google/domain/registry/keyring/api/VoidKeyringModule.java b/java/com/google/domain/registry/keyring/api/VoidKeyringModule.java new file mode 100644 index 000000000..4de05dab1 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/VoidKeyringModule.java @@ -0,0 +1,32 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.keyring.api; + +import dagger.Module; +import dagger.Provides; + +import javax.annotation.concurrent.Immutable; + +/** Dagger keyring module that always returns {@link VoidKeyring} instances. */ +@Module +@Immutable +public final class VoidKeyringModule { + + /** Always returns a {@link VoidKeyring} instance. */ + @Provides + static Keyring provideKeyring() { + return new VoidKeyring(); + } +} diff --git a/java/com/google/domain/registry/keyring/api/package-info.java b/java/com/google/domain/registry/keyring/api/package-info.java new file mode 100644 index 000000000..fdee1a182 --- /dev/null +++ b/java/com/google/domain/registry/keyring/api/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.keyring.api; diff --git a/java/com/google/domain/registry/loadtest/BUILD b/java/com/google/domain/registry/loadtest/BUILD new file mode 100644 index 000000000..f16c41bef --- /dev/null +++ b/java/com/google/domain/registry/loadtest/BUILD @@ -0,0 +1,30 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +filegroup( + name = "templates", + srcs = glob(["templates/*.xml"]), +) + +java_library( + name = "loadtest", + srcs = glob(["*.java"]), + resources = [":templates"], + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/flows", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/loadtest/LoadTask.java b/java/com/google/domain/registry/loadtest/LoadTask.java new file mode 100644 index 000000000..b5df2df17 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/LoadTask.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.loadtest; + +import static com.google.cloud.sql.jdbc.internal.Charsets.UTF_8; +import static com.google.domain.registry.flows.EppController.handleEppCommand; + +import com.google.appengine.api.taskqueue.DeferredTask; +import com.google.domain.registry.flows.SessionMetadata.SessionSource; +import com.google.domain.registry.flows.StatelessRequestSessionMetadata; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition; + +/** A task that executes a single EPP command. */ +public class LoadTask implements DeferredTask { + + private static final long serialVersionUID = -7541344556045675149L; + + private final String clientId; + private final String xml; + + LoadTask(String clientId, String xml) { + this.clientId = clientId; + this.xml = xml; + } + + @Override + public void run() { + handleEppCommand( + xml.getBytes(UTF_8), + new StatelessRequestSessionMetadata( + clientId, + false, + false, + ProtocolDefinition.getVisibleServiceExtensionUris(), + SessionSource.LOADTEST)); + } +} diff --git a/java/com/google/domain/registry/loadtest/LoadTestAction.java b/java/com/google/domain/registry/loadtest/LoadTestAction.java new file mode 100644 index 000000000..7f6bf3efa --- /dev/null +++ b/java/com/google/domain/registry/loadtest/LoadTestAction.java @@ -0,0 +1,232 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.loadtest; + +import static com.google.appengine.api.taskqueue.QueueConstants.maxTasksPerAdd; +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withPayload; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Lists.partition; +import static com.google.common.collect.Lists.transform; +import static com.google.domain.registry.util.ResourceUtils.readResourceUtf8; +import static java.util.Arrays.asList; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.TaskEnqueuer; + +import org.joda.time.DateTime; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import javax.inject.Inject; + +/** Simple load test action that can generate configurable QPSes of various EPP actions. */ +@Action( + path = "/_dr/loadtest", + method = Action.Method.POST, + automaticallyPrintOk = true) +public class LoadTestAction implements Runnable { + + private static final int NUM_QUEUES = 5; + private static final int ARBITRARY_VALID_HOST_LENGTH = 40; + private static final int MAX_CONTACT_LENGTH = 13; + private static final int MAX_DOMAIN_LABEL_LENGTH = 63; + + private static final String EXISTING_DOMAIN = "testdomain"; + private static final String EXISTING_CONTACT = "contact"; + private static final String EXISTING_HOST = "ns1"; + + private static final Random random = new Random(); + + @Inject @Parameter("loadtestClientId") String clientId; + @Inject @Parameter("tld") String tld; + @Inject @Parameter("delaySeconds") int delaySeconds; + @Inject @Parameter("runSeconds") int runSeconds; + @Inject @Parameter("successfulDomainCreates") int successfulDomainCreates; + @Inject @Parameter("failedDomainCreates") int failedDomainCreates; + @Inject @Parameter("domainInfos") int domainInfos; + @Inject @Parameter("domainChecks") int domainChecks; + @Inject @Parameter("successfulContactCreates") int successfulContactCreates; + @Inject @Parameter("failedContactCreates") int failedContactCreates; + @Inject @Parameter("contactInfos") int contactInfos; + @Inject @Parameter("successfulHostCreates") int successfulHostCreates; + @Inject @Parameter("failedHostCreates") int failedHostCreates; + @Inject @Parameter("hostInfos") int hostInfos; + @Inject TaskEnqueuer taskEnqueuer; + @Inject LoadTestAction() {} + + @Override + public void run() { + checkArgument( + RegistryEnvironment.get() != RegistryEnvironment.PRODUCTION, + "DO NOT RUN LOADTESTS IN PROD!"); + + DateTime initialStartSecond = DateTime.now(UTC).plusSeconds(delaySeconds); + ImmutableList.Builder preTaskXmls = new ImmutableList.Builder<>(); + ImmutableList.Builder contactNamesBuilder = new ImmutableList.Builder<>(); + ImmutableList.Builder hostPrefixesBuilder = new ImmutableList.Builder<>(); + for (int i = 0; i < successfulDomainCreates; i++) { + String contactName = getRandomLabel(MAX_CONTACT_LENGTH); + String hostPrefix = getRandomLabel(ARBITRARY_VALID_HOST_LENGTH); + contactNamesBuilder.add(contactName); + hostPrefixesBuilder.add(hostPrefix); + preTaskXmls.add( + loadXml("contact_create").replace("%contact%", contactName), + loadXml("host_create").replace("%host%", hostPrefix)); + } + enqueue(createTasks(preTaskXmls.build(), DateTime.now(UTC))); + ImmutableList contactNames = contactNamesBuilder.build(); + ImmutableList hostPrefixes = hostPrefixesBuilder.build(); + + ImmutableList.Builder tasks = new ImmutableList.Builder<>(); + for (int offsetSeconds = 0; offsetSeconds < runSeconds; offsetSeconds++) { + DateTime startSecond = initialStartSecond.plusSeconds(offsetSeconds); + // The first "failed" creates might actually succeed if the object doesn't already exist, but + // that shouldn't affect the load numbers. + tasks.addAll(createTasks( + createNumCopies( + loadXml("contact_create").replace("%contact%", EXISTING_CONTACT), + failedContactCreates), + startSecond)); + tasks.addAll(createTasks( + createNumCopies( + loadXml("host_create").replace("%host%", EXISTING_HOST), + failedHostCreates), + startSecond)); + tasks.addAll(createTasks( + createNumCopies( + loadXml("domain_create") + .replace("%tld%", tld) + .replace("%domain%", EXISTING_DOMAIN) + .replace("%contact%", EXISTING_CONTACT) + .replace("%host%", EXISTING_HOST), + failedDomainCreates), + startSecond)); + // We can do infos on the known existing objects. + tasks.addAll(createTasks( + createNumCopies( + loadXml("contact_info").replace("%contact%", EXISTING_CONTACT), + contactInfos), + startSecond)); + tasks.addAll(createTasks( + createNumCopies( + loadXml("host_info").replace("%host%", EXISTING_HOST), + hostInfos), + startSecond)); + tasks.addAll(createTasks( + createNumCopies( + loadXml("domain_info") + .replace("%tld%", tld) + .replace("%domain%", EXISTING_DOMAIN), + domainInfos), + startSecond)); + // The domain check template uses "example.TLD" which won't exist, and one existing domain. + tasks.addAll(createTasks( + createNumCopies( + loadXml("domain_check") + .replace("%tld%", tld) + .replace("%domain%", EXISTING_DOMAIN), + domainChecks), + startSecond)); + // Do successful creates on random names + tasks.addAll(createTasks( + transform( + createNumCopies(loadXml("contact_create"), successfulContactCreates), + randomNameReplacer("%contact%", MAX_CONTACT_LENGTH)), + startSecond)); + tasks.addAll(createTasks( + transform( + createNumCopies(loadXml("host_create"), successfulHostCreates), + randomNameReplacer("%host%", ARBITRARY_VALID_HOST_LENGTH)), + startSecond)); + tasks.addAll(createTasks( + FluentIterable + .from(createNumCopies( + loadXml("domain_create").replace("%tld%", tld), + successfulDomainCreates)) + .transform(randomNameReplacer("%domain%", MAX_DOMAIN_LABEL_LENGTH)) + .transform(listNameReplacer("%contact%", contactNames)) + .transform(listNameReplacer("%host%", hostPrefixes)) + .toList(), + startSecond)); + } + enqueue(tasks.build()); + } + + private String loadXml(String name) { + return readResourceUtf8(LoadTestAction.class, String.format("templates/%s.xml", name)); + } + + private List createNumCopies(String xml, int numCopies) { + String[] xmls = new String[numCopies]; + Arrays.fill(xmls, xml); + return asList(xmls); + } + + private Function listNameReplacer(final String toReplace, List choices) { + final Iterator iterator = Iterators.cycle(choices); + return new Function() { + @Override + public String apply(String xml) { + return xml.replace(toReplace, iterator.next()); + }}; + } + + private Function randomNameReplacer(final String toReplace, final int numChars) { + return new Function() { + @Override + public String apply(String xml) { + return xml.replace(toReplace, getRandomLabel(numChars)); + }}; + } + + private String getRandomLabel(int numChars) { + StringBuilder name = new StringBuilder(); + for (int j = 0; j < numChars; j++) { + name.append(Character.forDigit(random.nextInt(Character.MAX_RADIX), Character.MAX_RADIX)); + } + return name.toString(); + } + + private List createTasks(List xmls, DateTime start) { + ImmutableList.Builder tasks = new ImmutableList.Builder<>(); + for (int i = 0; i < xmls.size(); i++) { + // Space tasks evenly within across a second. + int offsetMillis = (int) (1000.0 / xmls.size() * i); + tasks.add(withPayload(new LoadTask(clientId, xmls.get(i))) + .etaMillis(start.plusMillis(offsetMillis).getMillis())); + } + return tasks.build(); + } + + private void enqueue(List tasks) { + List> chunks = partition(tasks, maxTasksPerAdd()); + // Farm out tasks to multiple queues to work around queue qps quotas. + for (int i = 0; i < chunks.size(); i++) { + taskEnqueuer.enqueue(getQueue("load" + (i % NUM_QUEUES)), chunks.get(i)); + } + } +} diff --git a/java/com/google/domain/registry/loadtest/LoadTestModule.java b/java/com/google/domain/registry/loadtest/LoadTestModule.java new file mode 100644 index 000000000..a8bad2e5a --- /dev/null +++ b/java/com/google/domain/registry/loadtest/LoadTestModule.java @@ -0,0 +1,114 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.loadtest; + +import static com.google.domain.registry.request.RequestParameters.extractIntParameter; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; + +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** + * Dagger module for loadtest package. + * + * @see "com.google.domain.registry.module.backend.ToolsComponent" + */ +@Module +public final class LoadTestModule { + + // There's already an @Parameter("clientId") for CreateGroupsTask that's only optional, and we + // want this one to be required, so give it a different name. + @Provides + @Parameter("loadtestClientId") + static String provideClientId(HttpServletRequest req) { + return extractRequiredParameter(req, "clientId"); + } + + @Provides + @Parameter("delaySeconds") + static int provideDelaySeconds(HttpServletRequest req) { + return extractIntParameter(req, "delaySeconds"); + } + + @Provides + @Parameter("runSeconds") + static int provideRunSeconds(HttpServletRequest req) { + return extractIntParameter(req, "runSeconds"); + } + + @Provides + @Parameter("successfulDomainCreates") + static int provideSuccessfulDomainCreates(HttpServletRequest req) { + return extractIntParameter(req, "successfulDomainCreates"); + } + + @Provides + @Parameter("failedDomainCreates") + static int provideFailedDomainCreates(HttpServletRequest req) { + return extractIntParameter(req, "failedDomainCreates"); + } + + @Provides + @Parameter("domainInfos") + static int provideDomainInfos(HttpServletRequest req) { + return extractIntParameter(req, "domainInfos"); + } + + @Provides + @Parameter("domainChecks") + static int provideDomainChecks(HttpServletRequest req) { + return extractIntParameter(req, "domainChecks"); + } + + @Provides + @Parameter("successfulContactCreates") + static int provideSuccessfulContactCreates(HttpServletRequest req) { + return extractIntParameter(req, "successfulContactCreates"); + } + + @Provides + @Parameter("failedContactCreates") + static int provideFailedContactCreates(HttpServletRequest req) { + return extractIntParameter(req, "failedContactCreates"); + } + + @Provides + @Parameter("contactInfos") + static int provideContactInfos(HttpServletRequest req) { + return extractIntParameter(req, "contactInfos"); + } + + @Provides + @Parameter("successfulHostCreates") + static int provideSuccessfulHostCreates(HttpServletRequest req) { + return extractIntParameter(req, "successfulHostCreates"); + } + + @Provides + @Parameter("failedHostCreates") + static int provideFailedHostCreates(HttpServletRequest req) { + return extractIntParameter(req, "failedHostCreates"); + } + + @Provides + @Parameter("hostInfos") + static int provideHostInfos(HttpServletRequest req) { + return extractIntParameter(req, "hostInfos"); + } +} diff --git a/java/com/google/domain/registry/loadtest/templates/contact_create.xml b/java/com/google/domain/registry/loadtest/templates/contact_create.xml new file mode 100644 index 000000000..db2ae0c11 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/contact_create.xml @@ -0,0 +1,33 @@ + + + + + %contact% + + John Doe + Example Inc. + + 123 Example Dr. + Suite 100 + Dulles + VA + 20166-6503 + US + + + +1.7035555555 + +1.7035555556 + jdoe@example.com + + 2fooBAR + + + + + + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/contact_info.xml b/java/com/google/domain/registry/loadtest/templates/contact_info.xml new file mode 100644 index 000000000..5f85c1e4e --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/contact_info.xml @@ -0,0 +1,14 @@ + + + + + %contact% + + 2fooBAR + + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/domain_check.xml b/java/com/google/domain/registry/loadtest/templates/domain_check.xml new file mode 100644 index 000000000..bd8889760 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/domain_check.xml @@ -0,0 +1,11 @@ + + + + + %domain%.%tld% + example.%tld% + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/domain_create.xml b/java/com/google/domain/registry/loadtest/templates/domain_create.xml new file mode 100644 index 000000000..152937a39 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/domain_create.xml @@ -0,0 +1,21 @@ + + + + + %domain%.%tld% + 2 + + %host%.example.com + + %contact% + %contact% + %contact% + + 2fooBAR + + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/domain_info.xml b/java/com/google/domain/registry/loadtest/templates/domain_info.xml new file mode 100644 index 000000000..9c57fe0b2 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/domain_info.xml @@ -0,0 +1,11 @@ + + + + + %domain%.%tld% + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/host_create.xml b/java/com/google/domain/registry/loadtest/templates/host_create.xml new file mode 100644 index 000000000..8aa90ea21 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/host_create.xml @@ -0,0 +1,11 @@ + + + + + %host%.example.com + + + trid + + diff --git a/java/com/google/domain/registry/loadtest/templates/host_info.xml b/java/com/google/domain/registry/loadtest/templates/host_info.xml new file mode 100644 index 000000000..45696cf05 --- /dev/null +++ b/java/com/google/domain/registry/loadtest/templates/host_info.xml @@ -0,0 +1,11 @@ + + + + + %host%.example.com + + + trid + + diff --git a/java/com/google/domain/registry/mapreduce/BUILD b/java/com/google/domain/registry/mapreduce/BUILD new file mode 100644 index 000000000..e21cc3de8 --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/BUILD @@ -0,0 +1,26 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "mapreduce", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_mapreduce2:appengine_mapreduce", + "//third_party/java/appengine_pipeline", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/mapreduce/ChunkingKeyInput.java b/java/com/google/domain/registry/mapreduce/ChunkingKeyInput.java new file mode 100644 index 000000000..f638848fd --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/ChunkingKeyInput.java @@ -0,0 +1,113 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import com.google.appengine.api.datastore.Key; +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.InputReader; +import com.google.common.collect.ImmutableList; + +import java.io.IOException; +import java.util.List; +import java.util.NoSuchElementException; + +/** A MapReduce {@link Input} adapter that chunks an input of keys into sublists of keys. */ +public class ChunkingKeyInput extends Input> { + + private static final long serialVersionUID = 1670202385246824694L; + + private final Input input; + private final int chunkSize; + + public ChunkingKeyInput(Input input, int chunkSize) { + this.input = input; + this.chunkSize = chunkSize; + } + + /** + * An input reader that wraps around another input reader and returns its contents in chunks of + * a given size. + */ + private static class ChunkingKeyInputReader extends InputReader> { + + private static final long serialVersionUID = 53502324675703263L; + + private final InputReader reader; + private final int chunkSize; + + ChunkingKeyInputReader(InputReader reader, int chunkSize) { + this.reader = reader; + this.chunkSize = chunkSize; + } + + @Override + public List next() throws IOException { + ImmutableList.Builder chunk = new ImmutableList.Builder<>(); + try { + for (int i = 0; i < chunkSize; i++) { + chunk.add(reader.next()); + } + } catch (NoSuchElementException e) { + // Amazingly this is the recommended (and only) way to test for hasNext(). + } + ImmutableList builtChunk = chunk.build(); + if (builtChunk.isEmpty()) { + throw new NoSuchElementException(); // Maintain the contract. + } + return builtChunk; + } + + @Override + public Double getProgress() { + return reader.getProgress(); + } + + @Override + public void beginShard() throws IOException { + reader.beginShard(); + } + + @Override + public void beginSlice() throws IOException { + reader.beginSlice(); + } + + @Override + public void endSlice() throws IOException { + reader.endSlice(); + } + + @Override + public void endShard() throws IOException { + reader.endShard(); + } + + @Override + public long estimateMemoryRequirement() { + // The reader's memory requirement plus the memory for this chunk's worth of buffered keys. + // 256 comes from DatastoreKeyInputReader.AVERAGE_KEY_SIZE. + return reader.estimateMemoryRequirement() + chunkSize * 256; + } + } + + @Override + public List>> createReaders() throws IOException { + ImmutableList.Builder>> readers = new ImmutableList.Builder<>(); + for (InputReader reader : input.createReaders()) { + readers.add(new ChunkingKeyInputReader(reader, chunkSize)); + } + return readers.build(); + } +} diff --git a/java/com/google/domain/registry/mapreduce/ConcatenatingInput.java b/java/com/google/domain/registry/mapreduce/ConcatenatingInput.java new file mode 100644 index 000000000..c0822e0e7 --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/ConcatenatingInput.java @@ -0,0 +1,66 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.InputReader; +import com.google.appengine.tools.mapreduce.inputs.ConcatenatingInputReader; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ListMultimap; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * A MapReduce {@link Input} adapter that joins multiple inputs. + * + * @param input type + */ +public class ConcatenatingInput extends Input { + + private static final long serialVersionUID = 1225981408139437077L; + + private final Set> inputs; + private final int numShards; + + public ConcatenatingInput(Iterable> inputs, int numShards) { + this.inputs = ImmutableSet.copyOf(inputs); + this.numShards = numShards; + } + + @Override + public List> createReaders() throws IOException { + ListMultimap> shards = ArrayListMultimap.create(); + int i = 0; + for (Input input : inputs) { + for (InputReader reader : input.createReaders()) { + // Covariant cast is safe because an InputReader only outputs I and never consumes it. + @SuppressWarnings("unchecked") + InputReader typedReader = (InputReader) reader; + shards.put(i % numShards, typedReader); + i++; + } + } + ImmutableList.Builder> concatenatingReaders = new ImmutableList.Builder<>(); + for (Collection> shard : shards.asMap().values()) { + concatenatingReaders.add(new ConcatenatingInputReader<>(ImmutableList.copyOf(shard))); + } + return concatenatingReaders.build(); + } +} diff --git a/java/com/google/domain/registry/mapreduce/EppResourceInputs.java b/java/com/google/domain/registry/mapreduce/EppResourceInputs.java new file mode 100644 index 000000000..5e2ff8f1c --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/EppResourceInputs.java @@ -0,0 +1,396 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.all; +import static com.google.common.collect.Lists.asList; +import static com.google.domain.registry.model.EntityClasses.CLASS_TO_KIND_FUNCTION; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.difference; +import static com.google.domain.registry.util.TypeUtils.hasAnnotation; + +import com.google.appengine.api.datastore.Cursor; +import com.google.appengine.api.datastore.QueryResultIterator; +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.InputReader; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.index.EppResourceIndex; +import com.google.domain.registry.model.index.EppResourceIndexBucket; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.EntitySubclass; +import com.googlecode.objectify.cmd.Query; + +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Mapreduce {@link Input} types (and related helpers) for {@link EppResource} keys and objects. + * + *

The inputs provided by this class are not deletion-aware and do not project the resources + * forward in time. That is the responsibility of mappers that use these inputs. + */ +public class EppResourceInputs { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** Number of bytes in 1MB of memory, used for memory estimates. */ + private static final long ONE_MB = 1024 * 1024; + + /** Returns a MapReduce {@link Input} that loads all {@link EppResourceIndex} objects. */ + public static Input createIndexInput() { + return new IndexInput(); + } + + /** + * Returns a MapReduce {@link Input} that loads all {@link EppResource} objects of a given type, + * including deleted resources. + * + *

Note: Do not concatenate multiple EntityInputs together (this is inefficient as it iterates + * through all buckets multiple times). Specify the types in a single input, or load all types by + * specifying {@link EppResource} as the class. + */ + @SafeVarargs + public static Input createEntityInput( + Class resourceClass, + Class... moreResourceClasses) { + return new EntityInput(ImmutableSet.copyOf(asList(resourceClass, moreResourceClasses))); + } + + /** + * Returns a MapReduce {@link Input} that loads keys to all {@link EppResource} objects of a given + * type, including deleted resources. + * + *

Note: Do not concatenate multiple KeyInputs together (this is inefficient as it iterates + * through all buckets multiple times). Specify the types in a single input, or load all types by + * specifying {@link EppResource} as the class. + */ + @SafeVarargs + public static Input> createKeyInput( + Class resourceClass, + Class... moreResourceClasses) { + ImmutableSet> resourceClasses = + ImmutableSet.copyOf(asList(resourceClass, moreResourceClasses)); + checkArgument( + all(resourceClasses, not(hasAnnotation(EntitySubclass.class))), + "Mapping over keys requires a non-polymorphic Entity"); + return new KeyInput<>(resourceClasses); + } + + /** Base class for {@link Input} classes that map over {@link EppResourceIndex}. */ + private abstract static class BaseInput extends Input { + + private static final long serialVersionUID = -6681886718929462122L; + + @Override + public List> createReaders() { + ImmutableList.Builder> readers = new ImmutableList.Builder<>(); + for (Key bucketKey : EppResourceIndexBucket.getAllBuckets()) { + readers.add(bucketToReader(bucketKey)); + } + return readers.build(); + } + + /** Creates a reader that returns the resources under a bucket. */ + protected abstract InputReader bucketToReader(Key bucketKey); + } + + /** + * A MapReduce {@link Input} that loads all {@link EppResourceIndex} entities. + */ + private static class IndexInput extends BaseInput { + + private static final long serialVersionUID = -1231269296567279059L; + + @Override + protected InputReader bucketToReader(Key bucketKey) { + return new IndexReader(bucketKey); + } + } + + /** A MapReduce {@link Input} that loads all {@link EppResource} objects of a given type. */ + private static class EntityInput extends BaseInput { + + private static final long serialVersionUID = 8162607479124406226L; + + private final ImmutableSet> resourceClasses; + + public EntityInput(ImmutableSet> resourceClasses) { + this.resourceClasses = resourceClasses; + checkResourceClassesForInheritance(resourceClasses); + } + + @Override + protected InputReader bucketToReader(Key bucketKey) { + return new EntityReader(bucketKey, resourceClasses); + } + } + + /** + * A MapReduce {@link Input} that loads keys to all {@link EppResource} objects of a given type. + * + *

When mapping over keys we can't distinguish between Objectify polymorphic types. + */ + private static class KeyInput extends BaseInput> { + + private static final long serialVersionUID = -5426821384707653743L; + + private final ImmutableSet> resourceClasses; + + public KeyInput(ImmutableSet> resourceClasses) { + this.resourceClasses = resourceClasses; + checkResourceClassesForInheritance(resourceClasses); + } + + @Override + protected InputReader> bucketToReader(Key bucketKey) { + return new KeyReader<>(bucketKey, resourceClasses); + } + } + + /** Base class for {@link InputReader} classes that map over {@link EppResourceIndex}. */ + private abstract static class BaseReader extends InputReader { + + private static final long serialVersionUID = -2970253037856017147L; + + /** + * The resource kinds to filter for. + * + *

This can be empty, or any of {"ContactResource", "HostResource", "DomainBase"}. It will + * never contain "EppResource", "DomainResource" or "DomainApplication" since these aren't + * actual kinds in Datastore. + */ + private final ImmutableSet filterKinds; + + private final Key bucketKey; + private final long memoryEstimate; + + private Cursor cursor; + private int total; + private int loaded; + + private transient QueryResultIterator queryIterator; + + BaseReader( + Key + bucketKey, + long memoryEstimate, + ImmutableSet filterKinds) { + this.bucketKey = bucketKey; + this.memoryEstimate = memoryEstimate; + this.filterKinds = filterKinds; + } + + /** Called once at start. Cache the expected size. */ + @Override + public void beginShard() { + total = query().count(); + } + + /** Called every time we are deserialized. Create a new query or resume an existing one. */ + @Override + public void beginSlice() { + Query query = query(); + if (cursor != null) { + // The underlying query is strongly consistent, and according to the documentation at + // https://cloud.google.com/appengine/docs/java/datastore/queries#Java_Data_consistency + // "strongly consistent queries are always transactionally consistent". However, each time + // we restart the query at a cursor we have a new effective query, and "if the results for a + // query change between uses of a cursor, the query notices only changes that occur in + // results after the cursor. If a new result appears before the cursor's position for the + // query, it will not be returned when the results after the cursor are fetched." + // What this means in practice is that entities that are created after the initial query + // begins may or may not be seen by this reader, depending on whether the query was + // paused and restarted with a cursor before it would have reached the new entity. + query = query.startAt(cursor); + } + queryIterator = query.iterator(); + } + + /** Called occasionally alongside {@link #next}. */ + @Override + public Double getProgress() { + // Cap progress at 1.0, since the query's count() can increase during the run of the mapreduce + // if more entities are written, but we've cached the value once in "total". + return Math.min(1.0, ((double) loaded) / total); + } + + /** Called before we are serialized. Save a serializable cursor for this query. */ + @Override + public void endSlice() { + cursor = queryIterator.getCursor(); + } + + /** Query for children of this bucket. */ + Query query() { + Query query = ofy().load().type(EppResourceIndex.class).ancestor(bucketKey); + return filterKinds.isEmpty() ? query : query.filter("kind in", filterKinds); + } + + /** Returns the estimated memory that will be used by this reader in bytes. */ + @Override + public long estimateMemoryRequirement() { + return memoryEstimate; + } + + /** + * Get the next {@link EppResourceIndex} from the query. + * + * @throws NoSuchElementException if there are no more elements. + */ + EppResourceIndex nextEri() { + loaded++; + try { + return queryIterator.next(); + } finally { + ofy().clearSessionCache(); // Try not to leak memory. + } + } + } + + /** Reader that maps over {@link EppResourceIndex} and returns the index objects themselves. */ + private static class IndexReader extends BaseReader { + + private static final long serialVersionUID = -4816383426796766911L; + + public IndexReader(Key bucketKey) { + // Estimate 1MB of memory for this reader, which is massive overkill. + // Use an empty set for the filter kinds, which disables filtering. + super(bucketKey, ONE_MB, ImmutableSet.of()); + } + + /** + * Called for each map invocation. + * + * @throws NoSuchElementException if there are no more elements, as specified in the + * {@link InputReader#next} Javadoc. + */ + @Override + public EppResourceIndex next() throws NoSuchElementException { + return nextEri(); + } + } + + /** + * Reader that maps over {@link EppResourceIndex} and returns resource keys. + * + *

When mapping over keys we can't distinguish between Objectify polymorphic types. + */ + private static class KeyReader extends BaseReader> { + + private static final long serialVersionUID = -428232054739189774L; + + public KeyReader( + Key bucketKey, ImmutableSet> resourceClasses) { + super( + bucketKey, + ONE_MB, // Estimate 1MB of memory for this reader, which is massive overkill. + varargsToKinds(resourceClasses)); + } + + /** + * Called for each map invocation. + * + * @throws NoSuchElementException if there are no more elements, as specified in the + * {@link InputReader#next} Javadoc. + */ + @Override + @SuppressWarnings("unchecked") + public Key next() throws NoSuchElementException { + // This is a safe cast because we filtered on kind inside the query. + return (Key) nextEri().getReference().getKey(); + } + } + + /** Reader that maps over {@link EppResourceIndex} and returns resources. */ + private static class EntityReader extends BaseReader { + + private static final long serialVersionUID = -8042933349899971801L; + + /** + * The resource classes to postfilter for. + * + *

This can be {@link EppResource} or any descendant classes, regardless of whether those + * classes map directly to a kind in datastore, with the restriction that none of the classes + * is a supertype of any of the others. + */ + private final ImmutableSet> resourceClasses; + + public EntityReader( + Key bucketKey, + ImmutableSet> resourceClasses) { + super( + bucketKey, + ONE_MB * 2, // Estimate 2MB of memory for this reader, since it loads a (max 1MB) entity. + varargsToKinds(resourceClasses)); + this.resourceClasses = resourceClasses; + } + + /** + * Called for each map invocation. + * + * @throws NoSuchElementException if there are no more elements, as specified in the + * {@link InputReader#next} Javadoc. + */ + @Override + public R next() throws NoSuchElementException { + // Loop until we find a value, or nextRef() throws a NoSuchElementException. + while (true) { + Ref reference = nextEri().getReference(); + EppResource resource = reference.get(); + if (resource == null) { + logger.severefmt("Broken ERI reference: %s", reference.getKey()); + continue; + } + // Postfilter to distinguish polymorphic types (e.g. DomainBase and DomainResource). + for (Class resourceClass : resourceClasses) { + if (resourceClass.isAssignableFrom(resource.getClass())) { + @SuppressWarnings("unchecked") + R r = (R) resource; + return r; + } + } + } + } + } + + private static ImmutableSet varargsToKinds( + ImmutableSet> resourceClasses) { + // Ignore EppResource when finding kinds, since it doesn't have one and doesn't imply filtering. + return resourceClasses.contains(EppResource.class) + ? ImmutableSet.of() + : FluentIterable.from(resourceClasses).transform(CLASS_TO_KIND_FUNCTION).toSet(); + } + + private static void checkResourceClassesForInheritance( + ImmutableSet> resourceClasses) { + for (Class resourceClass : resourceClasses) { + for (Class potentialSuperclass : difference(resourceClasses, resourceClass)) { + checkArgument( + !potentialSuperclass.isAssignableFrom(resourceClass), + "Cannot specify resource classes with inheritance relationship: %s extends %s", + resourceClass, + potentialSuperclass); + } + } + } +} diff --git a/java/com/google/domain/registry/mapreduce/MapreduceAction.java b/java/com/google/domain/registry/mapreduce/MapreduceAction.java new file mode 100644 index 000000000..e2dcda743 --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/MapreduceAction.java @@ -0,0 +1,24 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import com.google.domain.registry.request.Action; + +/** + * Marker interface to denote an action intended for the Mapreduce queue. + * + *

Classes that implement this interface are expected to have {@link Action} set. + */ +public interface MapreduceAction extends Runnable {} diff --git a/java/com/google/domain/registry/mapreduce/MapreduceModule.java b/java/com/google/domain/registry/mapreduce/MapreduceModule.java new file mode 100644 index 000000000..5570e4534 --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/MapreduceModule.java @@ -0,0 +1,52 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import static com.google.domain.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN; +import static com.google.domain.registry.mapreduce.MapreduceRunner.PARAM_MAP_SHARDS; +import static com.google.domain.registry.mapreduce.MapreduceRunner.PARAM_REDUCE_SHARDS; +import static com.google.domain.registry.request.RequestParameters.extractBooleanParameter; +import static com.google.domain.registry.request.RequestParameters.extractOptionalIntParameter; + +import com.google.common.base.Optional; +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the mapreduce package. */ +@Module +public final class MapreduceModule { + + @Provides + @Parameter(PARAM_DRY_RUN) + static boolean provideIsDryRun(HttpServletRequest req) { + return extractBooleanParameter(req, PARAM_DRY_RUN); + } + + @Provides + @Parameter(PARAM_MAP_SHARDS) + static Optional provideMapShards(HttpServletRequest req) { + return extractOptionalIntParameter(req, PARAM_MAP_SHARDS); + } + + @Provides + @Parameter(PARAM_REDUCE_SHARDS) + static Optional provideReduceShards(HttpServletRequest req) { + return extractOptionalIntParameter(req, PARAM_REDUCE_SHARDS); + } +} diff --git a/java/com/google/domain/registry/mapreduce/MapreduceRunner.java b/java/com/google/domain/registry/mapreduce/MapreduceRunner.java new file mode 100644 index 000000000..7c95f47db --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/MapreduceRunner.java @@ -0,0 +1,246 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import static com.google.appengine.api.search.checkers.Preconditions.checkNotNull; +import static com.google.appengine.tools.pipeline.PipelineServiceFactory.newPipelineService; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.MapJob; +import com.google.appengine.tools.mapreduce.MapReduceJob; +import com.google.appengine.tools.mapreduce.MapReduceSettings; +import com.google.appengine.tools.mapreduce.MapReduceSpecification; +import com.google.appengine.tools.mapreduce.MapSettings; +import com.google.appengine.tools.mapreduce.MapSpecification; +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.appengine.tools.mapreduce.Marshallers; +import com.google.appengine.tools.mapreduce.Output; +import com.google.appengine.tools.mapreduce.Reducer; +import com.google.appengine.tools.mapreduce.outputs.NoOutput; +import com.google.appengine.tools.pipeline.Job0; +import com.google.appengine.tools.pipeline.JobSetting; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.PipelineUtils; + +import org.joda.time.Duration; + +import java.io.Serializable; + +import javax.inject.Inject; + +/** + * Runner for map-only or full map and reduce mapreduces. + * + *

We use hardcoded serialization marshallers for moving data between steps, so all types used as + * keys or values must implement {@link Serializable}. + */ +public class MapreduceRunner { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + public static final String PARAM_DRY_RUN = "dryRun"; + public static final String PARAM_MAP_SHARDS = "mapShards"; + public static final String PARAM_REDUCE_SHARDS = "reduceShards"; + + private static final String BASE_URL = "/_dr/mapreduce/"; + private static final String QUEUE_NAME = "mapreduce"; + + private final Optional httpParamMapShards; + private final Optional httpParamReduceShards; + + // Default to 3 minutes since many slices will contain datastore queries that time out at 4:30. + private Duration sliceDuration = Duration.standardMinutes(3); + private String jobName; + private String moduleName; + + // If no reduce shards are set via http params, use this many shards. + private int defaultReduceShards = 1; + + /** + * @param mapShards number of map shards; if omitted, the {@link Input} objects will choose + * @param reduceShards number of reduce shards; if omitted, uses {@link #defaultReduceShards} + */ + @Inject + @VisibleForTesting + public MapreduceRunner( + @Parameter(PARAM_MAP_SHARDS) Optional mapShards, + @Parameter(PARAM_REDUCE_SHARDS) Optional reduceShards) { + this.httpParamMapShards = mapShards; + this.httpParamReduceShards = reduceShards; + } + + /** Set the max time to run a slice before serializing; defaults to 3 minutes. */ + public MapreduceRunner setSliceDuration(Duration sliceDuration) { + this.sliceDuration = checkArgumentNotNull(sliceDuration, "sliceDuration"); + return this; + } + + /** Set the human readable job name for display purposes. */ + public MapreduceRunner setJobName(String jobName) { + this.jobName = checkArgumentNotNull(jobName, "jobName"); + return this; + } + + /** Set the module to run in. */ + public MapreduceRunner setModuleName(String moduleName) { + this.moduleName = checkArgumentNotNull(moduleName, "moduleName"); + return this; + } + + /** Set the default number of reducers, if not overriden by the http param. */ + public MapreduceRunner setDefaultReduceShards(int defaultReduceShards) { + this.defaultReduceShards = checkNotNull(defaultReduceShards, "defaultReduceShards"); + return this; + } + + /** + * Create a map-only mapreduce to be run as part of a pipeline. + * + * @see #runMapOnly for creating and running an independent map-only mapreduce + * + * @param mapper instance of a mapper class + * @param inputs input sources for the mapper + * @param mapper input type + * @param individual output record type sent to the {@link Output} + * @param overall output result type + */ + public MapJob createMapOnlyJob( + Mapper mapper, + Output output, + Iterable> inputs) { + checkCommonRequiredFields(inputs, mapper); + return new MapJob<>( + new MapSpecification.Builder() + .setJobName(jobName) + .setInput(new ConcatenatingInput<>(inputs, httpParamMapShards.or(Integer.MAX_VALUE))) + .setMapper(mapper) + .setOutput(output) + .build(), + new MapSettings.Builder() + .setWorkerQueueName(QUEUE_NAME) + .setBaseUrl(BASE_URL) + .setModule(moduleName) + .setMillisPerSlice((int) sliceDuration.getMillis()) + .build()); + } + + /** + * Kick off a map-only mapreduce. + * + *

For simplicity, the mapreduce is hard-coded with {@link NoOutput}, on the assumption that + * all work will be accomplished via side effects during the map phase. + * + * @see #createMapOnlyJob for creating and running a map-only mapreduce as part of a pipeline + * + * @param mapper instance of a mapper class + * @param inputs input sources for the mapper + * @param mapper input type + * @return the job id + */ + public String runMapOnly( + Mapper mapper, + Iterable> inputs) { + return runAsPipeline(createMapOnlyJob(mapper, new NoOutput(), inputs)); + } + + /** + * Create a mapreduce job to be run as part of a pipeline. + * + * @see #runMapreduce for creating and running an independent mapreduce + * + * @param mapper instance of a mapper class + * @param reducer instance of a reducer class + * @param inputs input sources for the mapper + * @param mapper input type + * @param emitted key type + * @param emitted value type + * @param individual output record type sent to the {@link Output} + * @param overall output result type + */ + public final MapReduceJob + createMapreduceJob( + Mapper mapper, + Reducer reducer, + Output output, + Iterable> inputs) { + checkCommonRequiredFields(inputs, mapper); + checkArgumentNotNull(reducer, "reducer"); + return new MapReduceJob<>( + new MapReduceSpecification.Builder() + .setJobName(jobName) + .setInput(new ConcatenatingInput<>(inputs, httpParamMapShards.or(Integer.MAX_VALUE))) + .setMapper(mapper) + .setReducer(reducer) + .setOutput(output) + .setKeyMarshaller(Marshallers.getSerializationMarshaller()) + .setValueMarshaller(Marshallers.getSerializationMarshaller()) + .setNumReducers(httpParamReduceShards.or(defaultReduceShards)) + .build(), + new MapReduceSettings.Builder() + .setWorkerQueueName(QUEUE_NAME) + .setBaseUrl(BASE_URL) + .setModule(moduleName) + .setMillisPerSlice((int) sliceDuration.getMillis()) + .build()); + } + + /** + * Kick off a mapreduce job. + * + *

For simplicity, the mapreduce is hard-coded with {@link NoOutput}, on the assumption that + * all work will be accomplished via side effects during the map or reduce phases. + * + * @see #createMapreduceJob for creating and running a mapreduce as part of a pipeline + * + * @param mapper instance of a mapper class + * @param reducer instance of a reducer class + * @param inputs input sources for the mapper + * @param mapper input type + * @param emitted key type + * @param emitted value type + * @return the job id + */ + public final String runMapreduce( + Mapper mapper, + Reducer reducer, + Iterable> inputs) { + return runAsPipeline( + createMapreduceJob(mapper, reducer, new NoOutput(), inputs)); + } + + private void checkCommonRequiredFields(Iterable inputs, Mapper mapper) { + checkNotNull(jobName, "jobName"); + checkNotNull(moduleName, "moduleName"); + checkArgumentNotNull(inputs, "inputs"); + checkArgumentNotNull(mapper, "mapper"); + } + + private String runAsPipeline(Job0 job) { + String jobId = newPipelineService().startNewPipeline( + job, + new JobSetting.OnModule(moduleName), + new JobSetting.OnQueue(QUEUE_NAME)); + logger.infofmt( + "Started '%s' %s job: %s", + jobName, + job instanceof MapJob ? "map" : "mapreduce", + PipelineUtils.createJobPath(jobId)); + return jobId; + } +} diff --git a/java/com/google/domain/registry/mapreduce/NullInput.java b/java/com/google/domain/registry/mapreduce/NullInput.java new file mode 100644 index 000000000..b0788053b --- /dev/null +++ b/java/com/google/domain/registry/mapreduce/NullInput.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.mapreduce; + +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.InputReader; +import com.google.common.collect.ImmutableList; + +import java.util.List; +import java.util.NoSuchElementException; + +/** An input that returns a single {@code null} value. */ +public class NullInput extends Input { + + private static final long serialVersionUID = 1816836937031979851L; + + private static final class NullReader extends InputReader { + + private static final long serialVersionUID = -8176201363578913125L; + + boolean read = false; + + @Override + public T next() throws NoSuchElementException { + if (read) { + throw new NoSuchElementException(); + } + read = true; + return null; + } + + @Override + public Double getProgress() { + return read ? 1.0 : 0.0; + } + } + + @Override + public List> createReaders() { + return ImmutableList.of(new NullReader()); + } +} diff --git a/java/com/google/domain/registry/model/AbstractFieldExposer.java b/java/com/google/domain/registry/model/AbstractFieldExposer.java new file mode 100644 index 000000000..022d39aaf --- /dev/null +++ b/java/com/google/domain/registry/model/AbstractFieldExposer.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import java.lang.reflect.Field; + +/** + * A helper that exposes package-private fields in this package for reflective lookup. + *

+ * By adding a subclass of this to every package in the model, we can write generic code that can + * access fields with package private access. The other alternative is to call + * {@link Field#setAccessible} with {@code true} on any such Field objects, but that does not work + * reliably in Google App Engine cross-package because of its custom security manager + * implementation. + */ +public abstract class AbstractFieldExposer { + public abstract Object getFieldValue(Object instance, Field field) throws IllegalAccessException; + + public abstract void setFieldValue(Object instance, Field field, Object value) + throws IllegalAccessException; + + public abstract void setAccessible(Field field); +} diff --git a/java/com/google/domain/registry/model/BUILD b/java/com/google/domain/registry/model/BUILD new file mode 100644 index 000000000..ccbdf4fa5 --- /dev/null +++ b/java/com/google/domain/registry/model/BUILD @@ -0,0 +1,94 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + +FIELD_EXPOSERS = [ + "FieldExposer.java", + "billing/FieldExposer.java", + "common/FieldExposer.java", + "contact/FieldExposer.java", + "dns/FieldExposer.java", + "domain/FieldExposer.java", + "domain/allocate/FieldExposer.java", + "domain/fee/FieldExposer.java", + "domain/launch/FieldExposer.java", + "domain/rgp/FieldExposer.java", + "domain/secdns/FieldExposer.java", + "eppcommon/FieldExposer.java", + "eppinput/FieldExposer.java", + "eppoutput/FieldExposer.java", + "export/FieldExposer.java", + "host/FieldExposer.java", + "index/FieldExposer.java", + "mark/FieldExposer.java", + "ofy/FieldExposer.java", + "poll/FieldExposer.java", + "registrar/FieldExposer.java", + "registry/FieldExposer.java", + "registry/label/FieldExposer.java", + "reporting/FieldExposer.java", + "server/FieldExposer.java", + "rde/FieldExposer.java", + "smd/FieldExposer.java", + "tmch/FieldExposer.java", + "transfer/FieldExposer.java", + "translators/FieldExposer.java", +] + + +# Generate FieldExposer classes to work around AppEngine's security limitations. +genrule( + name = "field_exposers", + srcs = ["generate_field_exposer.sh"], + outs = FIELD_EXPOSERS, + cmd = "for FILE in $(OUTS); do " + + "./$(location generate_field_exposer.sh) $$FILE >> $$FILE;" + + "done", + visibility = ["//visibility:private"], +) + +# Generate a registry of FieldExposers. +genrule( + name = "field_exposer_registry", + srcs = ["generate_field_exposer_registry.sh"], + outs = ["FieldExposerRegistry.java"], + cmd = "./$(location generate_field_exposer_registry.sh) \"" + + ", ".join(FIELD_EXPOSERS) + + ");\" >\"$@\"", + visibility = ["//visibility:private"], +) + +java_library( + name = "model", + srcs = glob([ + "*.java", + "*/*.java", + "*/*/*.java", + ]) + ["FieldExposerRegistry.java"] + FIELD_EXPOSERS, + deps = [ + ":field_exposer_registry", + ":field_exposers", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/cache", + "//java/com/google/common/collect", + "//java/com/google/common/hash", + "//java/com/google/common/io", + "//java/com/google/common/math", + "//java/com/google/common/net", + "//java/com/google/common/primitives", + "//java/com/google/common/reflect", + "//java/com/google/common/util/concurrent", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/xml", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + "//third_party/java/joda_money", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/model/BackupGroupRoot.java b/java/com/google/domain/registry/model/BackupGroupRoot.java new file mode 100644 index 000000000..bd84b4dcb --- /dev/null +++ b/java/com/google/domain/registry/model/BackupGroupRoot.java @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import com.google.domain.registry.model.EppResource.SharedFields; + +import javax.xml.bind.annotation.XmlTransient; + +/** + * Base class for entities that are the root of a Registry 2.0 entity group that gets enrolled in + * commit logs for backup purposes. + * + *

The commit log system needs to preserve the ordering of closely timed mutations to entities + * in a single entity group. We require an {@link UpdateAutoTimestamp} field on the root of a group + * so that we can enforce strictly increasing timestamps. + */ +public abstract class BackupGroupRoot extends ImmutableObject { + /** + * An automatically managed timestamp of when this object was last written to datastore. + * + *

Note that this is distinct from the EPP-specified {@link SharedFields#lastUpdateTime} on + * {@link EppResource} objects, in that it is updated on every save, rather than just in response + * to an {@code } command. + */ + @XmlTransient + UpdateAutoTimestamp updateTimestamp = UpdateAutoTimestamp.create(null); + + /** Get the {@link UpdateAutoTimestamp} for this entity. */ + public final UpdateAutoTimestamp getUpdateAutoTimestamp() { + return updateTimestamp; + } +} diff --git a/java/com/google/domain/registry/model/Buildable.java b/java/com/google/domain/registry/model/Buildable.java new file mode 100644 index 000000000..92963e2f4 --- /dev/null +++ b/java/com/google/domain/registry/model/Buildable.java @@ -0,0 +1,108 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.ofy.ObjectifyService; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import java.lang.reflect.Field; + +/** Interface for {@link ImmutableObject} subclasses that have a builder. */ +public interface Buildable { + + Builder asBuilder(); + + /** + * Boilerplate for immutable builders. + *

+ * This can be used without implementing {@link Buildable}. + */ + public abstract static class Builder { + + private S instance; + + protected Builder() { + this.instance = new TypeInstantiator(getClass()){}.instantiate(); + // Only ImmutableObject is allowed, but enforcing that via the generics gets ugly. + checkState(instance instanceof ImmutableObject); + } + + protected Builder(S instance) { + this.instance = checkNotNull(instance); + } + + protected S getInstance() { + return checkNotNull(instance, "Cannot modify state after calling 'build()'."); + } + + /** Build the instance. */ + public S build() { + try { + // If this object has a Long or long Objectify @Id field that is not set, set it now. + Field idField = null; + try { + idField = ModelUtils.getAllFields(instance.getClass()).get( + ofy().factory().getMetadata(instance.getClass()).getKeyMetadata().getIdFieldName()); + } catch (Exception e) { + // Expected if the class is not registered with Objectify. + } + if (idField != null + && !idField.getType().equals(String.class) + && Optional.fromNullable((Long) ModelUtils.getFieldValue(instance, idField)) + .or(0L) == 0) { + ModelUtils.setFieldValue(instance, idField, ObjectifyService.allocateId()); + } + return instance; + } finally { + // Clear the internal instance so you can't accidentally mutate it through this builder. + instance = null; + } + } + } + + /** Boilerplate for abstract immutable builders that need to be able to cast "this". */ + public abstract class GenericBuilder> extends Builder { + protected GenericBuilder() {} + + protected GenericBuilder(S instance) { + super(instance); + } + + @SuppressWarnings("unchecked") + protected B thisCastToDerived() { + return (B) this; + } + } + + /** + * Interface for objects that can produce an "overlay", which means a copy where non-null fields + * from another object are copied over, but null fields on the source are not. + *

+ * Warning: Do not use {@code emptyToNull} methods in the getters of an {@link Overlayable}! We + * use null to mean "skip this field" whereas empty means "set this field to empty", so they are + * semantically different. + * + * @param the derived type + */ + public interface Overlayable extends Buildable { + /** Return an overlay of this object using non-null fields from the source. */ + T overlay(T source); + } +} diff --git a/java/com/google/domain/registry/model/CreateAutoTimestamp.java b/java/com/google/domain/registry/model/CreateAutoTimestamp.java new file mode 100644 index 000000000..103102588 --- /dev/null +++ b/java/com/google/domain/registry/model/CreateAutoTimestamp.java @@ -0,0 +1,40 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import com.google.domain.registry.model.translators.CreateAutoTimestampTranslatorFactory; + +import org.joda.time.DateTime; + +/** + * A timestamp that auto-updates when first saved to datastore. + * + * @see CreateAutoTimestampTranslatorFactory + */ +public class CreateAutoTimestamp extends ImmutableObject { + + DateTime timestamp; + + /** Returns the timestamp. */ + public DateTime getTimestamp() { + return timestamp; + } + + public static CreateAutoTimestamp create(DateTime timestamp) { + CreateAutoTimestamp instance = new CreateAutoTimestamp(); + instance.timestamp = timestamp; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/EntityClasses.java b/java/com/google/domain/registry/model/EntityClasses.java new file mode 100644 index 000000000..6d451e1dc --- /dev/null +++ b/java/com/google/domain/registry/model/EntityClasses.java @@ -0,0 +1,129 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.billing.RegistrarBillingEntry; +import com.google.domain.registry.model.billing.RegistrarCredit; +import com.google.domain.registry.model.billing.RegistrarCreditBalance; +import com.google.domain.registry.model.common.EntityGroupRoot; +import com.google.domain.registry.model.common.GaeUserIdConverter; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.export.LogsExportCursor; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.index.DomainApplicationIndex; +import com.google.domain.registry.model.index.EppResourceIndex; +import com.google.domain.registry.model.index.EppResourceIndexBucket; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.model.ofy.CommitLogBucket; +import com.google.domain.registry.model.ofy.CommitLogCheckpoint; +import com.google.domain.registry.model.ofy.CommitLogCheckpointRoot; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.CommitLogMutation; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.rde.RdeRevision; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.label.PremiumList; +import com.google.domain.registry.model.registry.label.ReservedList; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.server.Lock; +import com.google.domain.registry.model.server.ServerSecret; +import com.google.domain.registry.model.smd.SignedMarkRevocationList; +import com.google.domain.registry.model.tmch.ClaimsListShard; +import com.google.domain.registry.model.tmch.ClaimsListShard.ClaimsListRevision; +import com.google.domain.registry.model.tmch.ClaimsListShard.ClaimsListSingleton; +import com.google.domain.registry.model.tmch.TmchCrl; + +import com.googlecode.objectify.Key; + +/** Sets of classes of the Objectify-registered entities in use throughout the model. */ +public final class EntityClasses { + + /** Set of entity classes. */ + @SuppressWarnings("unchecked") // varargs + public static final ImmutableSet> ALL_CLASSES = + ImmutableSet.>of( + BillingEvent.Cancellation.class, + BillingEvent.Modification.class, + BillingEvent.OneTime.class, + BillingEvent.Recurring.class, + ClaimsListShard.class, + ClaimsListRevision.class, + ClaimsListSingleton.class, + CommitLogBucket.class, + CommitLogCheckpoint.class, + CommitLogCheckpointRoot.class, + CommitLogManifest.class, + CommitLogMutation.class, + ContactResource.class, + DomainApplication.class, + DomainApplicationIndex.class, + DomainBase.class, + DomainResource.class, + EntityGroupRoot.class, + EppResourceIndex.class, + EppResourceIndexBucket.class, + ForeignKeyIndex.ForeignKeyContactIndex.class, + ForeignKeyIndex.ForeignKeyDomainIndex.class, + ForeignKeyIndex.ForeignKeyHostIndex.class, + GaeUserIdConverter.class, + HistoryEntry.class, + HostResource.class, + Lock.class, + LogsExportCursor.class, + PollMessage.class, + PollMessage.Autorenew.class, + PollMessage.OneTime.class, + PremiumList.class, + PremiumList.PremiumListEntry.class, + PremiumList.PremiumListRevision.class, + RdeRevision.class, + Registrar.class, + RegistrarBillingEntry.class, + RegistrarContact.class, + RegistrarCredit.class, + RegistrarCreditBalance.class, + Registry.class, + RegistryCursor.class, + ReservedList.class, + ServerSecret.class, + SignedMarkRevocationList.class, + TmchCrl.class); + + /** + * Function that converts an Objectify-registered class to its datastore kind name. + * + *

Note that this mapping is not one-to-one, since polymorphic subclasses of an entity all + * have the same datastore kind. (In theory, two distinct top-level entities could also map to + * the same kind since it's just {@code class.getSimpleName()}, but we test against that.) + */ + public static final Function, String> CLASS_TO_KIND_FUNCTION = + new Function, String>() { + @Override + public String apply(Class clazz) { + return Key.getKind(clazz); + } + }; + + private EntityClasses() {} +} diff --git a/java/com/google/domain/registry/model/EppResource.java b/java/com/google/domain/registry/model/EppResource.java new file mode 100644 index 000000000..8b375cef2 --- /dev/null +++ b/java/com/google/domain/registry/model/EppResource.java @@ -0,0 +1,441 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.union; +import static com.google.domain.registry.util.CollectionUtils.difference; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.transfer.TransferData; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.OnLoad; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** An Epp entity object such as a contact or a host. */ +@XmlTransient +public abstract class EppResource extends BackupGroupRoot implements Buildable, ResponseData { + + /** + * Unique identifier in the registry for this resource. + * + *

This is in the (\w|_){1,80}-\w{1,8} format specified by RFC 5730 for roidType. + */ + @Id + @XmlElement(name = "roid") + String repoId; + + /** The shared fields for this resource. */ + // TODO(b/19035583): Remove this after touching all resources and waiting long enough to be sure + // we don't need to reload old commit logs. + @XmlTransient + SharedFields sharedFields = new SharedFields(); + + /** The ID of the registrar that is currently sponsoring this resource. */ + @Index + @XmlElement(name = "clID") + String currentSponsorClientId; + + /** The ID of the registrar that created this resource. */ + @XmlElement(name = "crID") + String creationClientId; + + /** + * The ID of the registrar that last updated this resource. + * + *

This does not refer to the last delta made on this object, which might include out-of-band + * edits; it only includes EPP-visible modifications such as {@literal }. Can be null if + * the resource has never been modified. + */ + @XmlElement(name = "upID") + String lastEppUpdateClientId; + + /** The time when this resource was created. */ + // Map the method to XML, not the field, because if we map the field (with an adaptor class) it + // will never be omitted from the xml even if the timestamp inside creationTime is null and we + // return null from the adaptor. (Instead it gets written as an empty tag.) + @XmlTransient + CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null); + + /** + * The time when this resource was or will be deleted. + * + *

    + *
  • For deleted resources, this is in the past. + *
  • For pending-delete resources, this is in the near future. + *
  • For active resources, this is {@code END_OF_TIME}. + *
+ * + *

This scheme allows for setting pending deletes in the future and having them magically drop + * out of the index at that time, as long as we query for resources whose deletion time is before + * now. + */ + @Index + @XmlTransient + DateTime deletionTime; + + + /** + * The time that this resource was last updated. + * + *

This does not refer to the last delta made on this object, which might include out-of-band + * edits; it only includes EPP-visible modifications such as {@literal }. Can be null if + * the resource has never been modified. + */ + @XmlElement(name = "upDate") + DateTime lastEppUpdateTime; + + /** + * The time that this resource was last transferred. + * + *

Can be null if the resource has never been transferred. + */ + // Map the method to XML, not the field, so subclasses can override it. + @XmlTransient + DateTime lastTransferTime; + + /** Status values associated with this resource. */ + Set status; + + /** Data about any pending or past transfers on this contact. */ + @XmlTransient + TransferData transferData; + + /** + * Sorted map of {@link DateTime} keys (modified time) to {@link CommitLogManifest} entries. + * + *

Note: Only the last revision on a given date is stored. The key is the transaction + * timestamp, not midnight. + * + * @see com.google.domain.registry.model.translators.CommitLogRevisionsTranslatorFactory + */ + @XmlTransient + ImmutableSortedMap> revisions = ImmutableSortedMap.of(); + + public final String getRepoId() { + return repoId; + } + + @XmlElement(name = "crDate") + public final DateTime getCreationTime() { + return creationTime.getTimestamp(); + } + + public final String getCreationClientId() { + return creationClientId; + } + + public final DateTime getLastEppUpdateTime() { + return lastEppUpdateTime; + } + + public final String getLastEppUpdateClientId() { + return lastEppUpdateClientId; + } + + public final String getCurrentSponsorClientId() { + return currentSponsorClientId; + } + + public final ImmutableSet getStatusValues() { + return nullToEmptyImmutableCopy(status); + } + + public final TransferData getTransferData() { + return Optional.fromNullable(transferData).or(TransferData.EMPTY); + } + + /** Returns whether there is any transferData. */ + public final boolean hasTransferData() { + return transferData != null; + } + + @XmlElement(name = "trDate") + public DateTime getLastTransferTime() { + return lastTransferTime; + } + + public final DateTime getDeletionTime() { + return deletionTime; + } + + public ImmutableSortedMap> getRevisions() { + return nullToEmptyImmutableCopy(revisions); + } + + /** Return a clone of the resource with timed status values modified using the given time. */ + public abstract EppResource cloneProjectedAtTime(DateTime now); + + /** Get the foreign key string for this resource. */ + public abstract String getForeignKey(); + + /** Override of {@link Buildable#asBuilder} so that the extra methods are visible. */ + @Override + public abstract Builder asBuilder(); + + /** EppResources that are loaded via foreign keys should implement this marker interface. */ + public interface ForeignKeyedEppResource {} + + /** Common shared fields for {@link EppResource} types. */ + //TODO(b/19035583): Delete this class. + @Embed + public static class SharedFields extends ImmutableObject { + + /** The id of the registry client that is currently sponsoring this resource. */ + @Index + String currentSponsorClientId; + + /** The ID of the registry client that created this resource. */ + String creationRegistryClientId; + + /** + * The ID of the last registry client to update this resource. This does not refer to the last + * delta made on this object, which might include transfer flows or out-of-band edits; a + * resource must literally have had an EPP {@literal } called on it for this field to be + * set. Can be null if the resource has never had {@literal } called on it. + */ + @IgnoreSave(IfNull.class) + String lastUpdateRegistryClientId; + + /** The time when this resource was created. */ + @XmlTransient + CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null); + + /** + * The time when this resource was or will be deleted. + *

+ * For deleted resources, this is in the past. + * For pending-delete resources, this is in the near future. + * For active resources, this is {@code END_OF_TIME}. + *

+ * This scheme allows for setting pending deletes in the future and having them magically drop + * out of the index at that time, as long as we query for resources whose delete time is + * before now. + */ + @Index + DateTime deletionTime; + + /** + * The time that this resource was last updated. Can be null if the resource has never had + * {@literal } called on it. + */ + @IgnoreSave(IfNull.class) + DateTime lastUpdateTime; + + /** + * The time that this resource was last transferred. Can be null if the resource has never been + * transferred. + */ + @IgnoreSave(IfNull.class) + DateTime lastTransferTime; + + /** Legacy field for status values associated with this resource. */ + // TODO(b/25442343): Remove this. + @XmlTransient + Set statusValues; + + /** Data about any pending or past transfers on this contact. */ + @IgnoreSave(IfNull.class) + TransferData transferData; + } + + /** Read sharedFields values into their new locations. */ + // TODO(b/25442343,b/19035583): Remove this. + @OnLoad + public void loadLegacySharedFields() { + currentSponsorClientId = sharedFields.currentSponsorClientId; + creationClientId = sharedFields.creationRegistryClientId; + lastEppUpdateClientId = sharedFields.lastUpdateRegistryClientId; + creationTime = sharedFields.creationTime; + deletionTime = sharedFields.deletionTime; + lastEppUpdateTime = sharedFields.lastUpdateTime; + lastTransferTime = sharedFields.lastTransferTime; + status = sharedFields.statusValues == null + ? null + : FluentIterable.from(sharedFields.statusValues) + .transform(StatusValue.LEGACY_CONVERTER.reverse()) + .toSet(); + transferData = sharedFields.transferData; + } + + /** Abstract builder for {@link EppResource} types. */ + public abstract static class Builder> + extends GenericBuilder { + + /** Create a {@link Builder} wrapping a new instance. */ + protected Builder() {} + + /** Create a {@link Builder} wrapping the given instance. */ + protected Builder(T instance) { + super(instance); + // Clone the SharedFields since the setters on this builder mutate its fields directly. + instance.sharedFields = ImmutableObject.clone(instance.sharedFields); + } + + /** Set the time this resource was created. Should only be used in tests. */ + @VisibleForTesting + public B setCreationTimeForTest(DateTime creationTime) { + getInstance().creationTime = CreateAutoTimestamp.create(creationTime); + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.creationTime = CreateAutoTimestamp.create(creationTime); + return thisCastToDerived(); + } + + /** Set the time after which this resource should be considered deleted. */ + public B setDeletionTime(DateTime deletionTime) { + getInstance().deletionTime = deletionTime; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.deletionTime = deletionTime; + return thisCastToDerived(); + } + + /** Set the current sponsoring registrar. */ + public B setCurrentSponsorClientId(String currentSponsorClientId) { + getInstance().currentSponsorClientId = currentSponsorClientId; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.currentSponsorClientId = currentSponsorClientId; + return thisCastToDerived(); + } + + /** Set the registrar that created this resource. */ + public B setCreationClientId(String creationClientId) { + getInstance().creationClientId = creationClientId; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.creationRegistryClientId = creationClientId; + return thisCastToDerived(); + } + + /** Set the time when a {@literal } was performed on this resource. */ + public B setLastEppUpdateTime(DateTime lastEppUpdateTime) { + getInstance().lastEppUpdateTime = lastEppUpdateTime; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.lastUpdateTime = lastEppUpdateTime; + return thisCastToDerived(); + } + + /** Set the registrar who last performed a {@literal } on this resource. */ + public B setLastEppUpdateClientId(String lastEppUpdateClientId) { + getInstance().lastEppUpdateClientId = lastEppUpdateClientId; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.lastUpdateRegistryClientId = lastEppUpdateClientId; + return thisCastToDerived(); + } + + /** Set the time when this resource was transferred. */ + public B setLastTransferTime(DateTime lastTransferTime) { + getInstance().lastTransferTime = lastTransferTime; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.lastTransferTime = lastTransferTime; + return thisCastToDerived(); + } + + /** Set this resource's status values. */ + public B setStatusValues(ImmutableSet statusValues) { + getInstance().status = statusValues; + // TODO(b/25442343): Stop setting the legacy field. + getInstance().sharedFields.statusValues = statusValues == null + ? null + : FluentIterable.from(statusValues) + .transform(StatusValue.LEGACY_CONVERTER) + .toSet(); + return thisCastToDerived(); + } + + /** Add to this resource's status values. */ + public B addStatusValue(StatusValue statusValue) { + return addStatusValues(ImmutableSet.of(statusValue)); + } + + /** Remove from this resource's status values. */ + public B removeStatusValue(StatusValue statusValue) { + return removeStatusValues(ImmutableSet.of(statusValue)); + } + + /** Add to this resource's status values. */ + public B addStatusValues(ImmutableSet statusValues) { + return setStatusValues(ImmutableSet.copyOf( + union(getInstance().getStatusValues(), statusValues))); + } + + /** Remove from this resource's status values. */ + public B removeStatusValues(ImmutableSet statusValues) { + return setStatusValues(ImmutableSet.copyOf( + difference(getInstance().getStatusValues(), statusValues))); + } + + /** Set this resource's transfer data. */ + public B setTransferData(TransferData transferData) { + getInstance().transferData = transferData; + // TODO(b/19035583): Stop setting the legacy field. + getInstance().sharedFields.transferData = transferData; + return thisCastToDerived(); + } + + /** Set this resource's repoId. */ + public B setRepoId(String repoId) { + getInstance().repoId = repoId; + return thisCastToDerived(); + } + + /** Wipe out any personal information in the resource. */ + public B wipeOut() { + return thisCastToDerived(); + } + + /** Build the resource, nullifying empty strings and sets and setting defaults. */ + @Override + public T build() { + // An EPP object has an implicit status of OK if no pending operations or prohibitions exist + // (i.e. no other status value besides LINKED is present). + removeStatusValue(StatusValue.OK); + if (difference(getInstance().getStatusValues(), StatusValue.LINKED).isEmpty()) { + addStatusValue(StatusValue.OK); + } + return buildWithoutImplicitStatusValues(); + } + + /** Build the resource, nullifying empty strings and sets and setting defaults. */ + public T buildWithoutImplicitStatusValues() { + // If TransferData is totally empty, set it to null. + if (TransferData.EMPTY.equals(getInstance().transferData)) { + setTransferData(null); + } + // If there is no deletion time, set it to END_OF_TIME. + setDeletionTime(Optional.fromNullable(getInstance().deletionTime).or(END_OF_TIME)); + return ImmutableObject.cloneEmptyToNull(super.build()); + } + } +} diff --git a/java/com/google/domain/registry/model/EppResourceUtils.java b/java/com/google/domain/registry/model/EppResourceUtils.java new file mode 100644 index 000000000..a2d9fb38a --- /dev/null +++ b/java/com/google/domain/registry/model/EppResourceUtils.java @@ -0,0 +1,408 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterables.transform; +import static com.google.domain.registry.model.RoidSuffixes.getRoidSuffixForTld; +import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; +import static com.google.domain.registry.util.DateTimeUtils.latestOf; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.EppResource.Builder; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.EppResource.SharedFields; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.index.ForeignKeyIndex; +import com.google.domain.registry.model.ofy.CommitLogManifest; +import com.google.domain.registry.model.ofy.CommitLogMutation; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.Result; +import com.googlecode.objectify.util.ResultNow; + +import org.joda.time.DateTime; +import org.joda.time.Interval; + +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import javax.annotation.Nullable; + +/** Utilities for working with {@link EppResource}. */ +public final class EppResourceUtils { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** Returns the full domain repoId of the format HEX-TLD for the specified long id and tld. */ + public static String createDomainRoid(long repoId, String tld) { + return createRoid(repoId, getRoidSuffixForTld(tld)); + } + + /** + * Returns the full contact/host repoId of the format HEX-GOOGLE for the specified long repo id. + */ + public static String createContactHostRoid(long repoId) { + return createRoid( + repoId, RegistryEnvironment.get().config().getContactAndHostRepositoryIdentifier()); + } + + private static String createRoid(long repoId, String roidSuffix) { + // %X is uppercase hexadecimal. + return String.format("%X-%s", repoId, roidSuffix); + } + + /** Helper to call {@link EppResource#cloneProjectedAtTime} without warnings. */ + @SuppressWarnings("unchecked") + private static final T cloneProjectedAtTime(T resource, DateTime now) { + return (T) resource.cloneProjectedAtTime(now); + } + + /** + * Loads the last created version of an {@link EppResource} from the datastore by foreign key. + * + *

Returns null if no resource with this foreign key was ever created, or if the most recently + * created resource was deleted before time "now". + * + *

Loading an {@link EppResource} by itself is not sufficient to know its current state since + * it may have various expirable conditions and status values that might implicitly change its + * state as time progresses even if it has not been updated in the datastore. Rather, the + * resource must be combined with a timestamp to view its current state. We use a global last + * updated timestamp on the entire entity group (which is essentially free since all writes to + * the entity group must be serialized anyways) to guarantee monotonically increasing write + * times, so forwarding our projected time to the greater of "now", and this update timestamp + * guarantees that we're not projecting into the past. + * + * @param clazz the resource type to load + * @param foreignKey id to match + * @param now the current logical time to project resources at + */ + public static T loadByUniqueId( + Class clazz, String foreignKey, DateTime now) { + // For regular foreign-keyed resources, get the ref by loading the FKI; for domain applications, + // we can construct the ref directly, since the provided foreignKey is just the repoId. + Ref resourceRef = ForeignKeyedEppResource.class.isAssignableFrom(clazz) + ? loadAndGetReference(clazz, foreignKey, now) + : Ref.create(Key.create(null, clazz, foreignKey)); + if (resourceRef == null) { + return null; + } + T resource = resourceRef.get(); + if (resource == null + // You'd think this couldn't happen, but it can. For polymorphic entities, a Ref or Key is + // of necessity a reference to the base type (since datastore doesn't have polymorphism and + // Objectify is faking it). In the non-foreign-key code path above where we directly create + // a Ref, there is no way to know whether the Ref points to an instance of the desired + // subclass without loading it. Due to type erasure, it gets stuffed into "resource" without + // causing a ClassCastException even if it's the wrong type until you actually try to use it + // as the wrong type, at which point it blows up somewhere else in the code. Concretely, + // this means that without this line bad things would happen if you tried to load a + // DomainApplication using the id of a DomainResource (but not vice versa). + || !clazz.isInstance(resource) + || isAtOrAfter(now, resource.getDeletionTime())) { + return null; + } + // When setting status values based on a time, choose the greater of "now" and the resource's + // UpdateAutoTimestamp. For non-mutating uses (info, whois, etc.), this is equivalent to rolling + // "now" forward to at least the last update on the resource, so that a read right after a write + // doesn't appear stale. For mutating flows, if we had to roll now forward then the flow will + // fail when it tries to save anything via Ofy, since "now" is needed to be > the last update + // time for writes. + return cloneProjectedAtTime( + resource, + latestOf(now, resource.getUpdateAutoTimestamp().getTimestamp())); + } + + /** Loads returns the hosts specified by the given ReferenceUnions. */ + public static ImmutableSet loadReferencedNameservers( + Set> hostRefs) { + ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); + for (ReferenceUnion hostRef : hostRefs) { + HostResource host = hostRef.getLinked().get(); + if (host != null) { + builder.add(host); + } + } + return builder.build(); + } + + /** Loads and returns the contacts specified by the given ReferenceUnions. */ + public static ImmutableSet loadReferencedContacts( + Set> contactRefs) { + ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); + for (ReferenceUnion contactRef : contactRefs) { + builder.add(contactRef.getLinked().get()); + } + return builder.build(); + } + + /** + * Checks multiple {@link EppResource} objects from the datastore by unique ids. + *

+ * There are currently no resources that support checks and do not use foreign keys. If we need to + * support that case in the future, we can loosen the type to allow any {@link EppResource} and + * add code to do the lookup by id directly. + * + * @param clazz the resource type to load + * @param uniqueIds a list of ids to match + * @param now the logical time of the check + */ + public static Set checkResourcesExist( + Class clazz, List uniqueIds, final DateTime now) { + return ForeignKeyIndex.load(clazz, uniqueIds, now).keySet(); + } + + /** + * Loads resources that match some filter and that have {@link SharedFields#deletionTime} that is + * not before "now". + * + *

This is an eventually consistent query. + * + * @param clazz the resource type to load + * @param now the logical time of the check + * @param filterDefinition the filter to apply when loading resources + * @param filterValue the acceptable value for the filter + */ + public static Iterable queryNotDeleted( + Class clazz, DateTime now, String filterDefinition, Object filterValue) { + return transform( + ofy().load().type(clazz) + .filter(filterDefinition, filterValue) + .filter("sharedFields.deletionTime >", now.toDate()), + EppResourceUtils.transformAtTime(now)); + } + + /** + * Returns a Function that transforms an EppResource to the given DateTime, suitable for use with + * Iterables.transform() over a collection of EppResources. + */ + public static Function transformAtTime(final DateTime now) { + return new Function() { + @Override + public T apply(T resource) { + return cloneProjectedAtTime(resource, now); + }}; + } + + /** + * The lifetime of a resource is from its creation time, inclusive, through its deletion time, + * exclusive, which happily maps to the behavior of Interval. + */ + private static Interval getLifetime(EppResource resource) { + return new Interval(resource.getCreationTime(), resource.getDeletionTime()); + } + + public static boolean isActive(EppResource resource, DateTime time) { + return getLifetime(resource).contains(time); + } + + public static boolean isDeleted(EppResource resource, DateTime time) { + return !isActive(resource, time); + } + + /** Process an automatic transfer on a resource. */ + public static void setAutomaticTransferSuccessProperties( + Builder builder, TransferData transferData) { + checkArgument(TransferStatus.PENDING.equals(transferData.getTransferStatus())); + builder.removeStatusValue(StatusValue.PENDING_TRANSFER) + .setTransferData(transferData.asBuilder() + .setTransferStatus(TransferStatus.SERVER_APPROVED) + .setServerApproveEntities(null) + .setServerApproveBillingEvent(null) + .setServerApproveAutorenewEvent(null) + .setServerApproveAutorenewPollMessage(null) + .build()) + .setLastTransferTime(transferData.getPendingTransferExpirationTime()) + .setCurrentSponsorClientId(transferData.getGainingClientId()); + } + + /** + * Perform common operations for projecting an {@link EppResource} at a given time: + *

    + *
  • Process an automatic transfer. + *
+ */ + public static void projectResourceOntoBuilderAtTime( + T resource, Builder builder, DateTime now) { + TransferData transferData = resource.getTransferData(); + // If there's a pending transfer that has expired, process it. + DateTime expirationTime = transferData.getPendingTransferExpirationTime(); + if (TransferStatus.PENDING.equals(transferData.getTransferStatus()) + && isBeforeOrAt(expirationTime, now)) { + setAutomaticTransferSuccessProperties(builder, transferData); + } + } + + /** + * Rewinds an {@link EppResource} object to a given point in time. + * + *

This method costs nothing if {@code resource} is already current. Otherwise it needs to + * perform a single asynchronous key fetch operation. + * + *

Warning: A resource can only be rolled backwards in time, not forwards; therefore + * {@code resource} should be whatever's currently in datastore. + * + *

Warning: Revisions are granular to 24-hour periods. It's recommended that + * {@code timestamp} be set to midnight. Otherwise you must take into consideration that under + * certain circumstances, a resource might be restored to a revision on the previous day, even if + * there were revisions made earlier on the same date as {@code timestamp}; however, a resource + * will never be restored to a revision occuring after {@code timestamp}. This behavior is due to + * the way {@link com.google.domain.registry.model.translators.CommitLogRevisionsTranslatorFactory + * CommitLogRevisionsTranslatorFactory} manages the {@link EppResource#revisions} field. Please + * note however that the creation and deletion times of a resource are granular to the + * millisecond. + * + * @return an asynchronous operation returning resource at {@code timestamp} or {@code null} if + * if resource is deleted or not yet created + */ + public static + Result loadAtPointInTime(final T resource, final DateTime timestamp) { + // If we're before the resource creation time, don't try to find a "most recent revision". + if (timestamp.isBefore(resource.getCreationTime())) { + return new ResultNow<>(null); + } + // If the resource was not modified after the requested time, then use it as-is, otherwise find + // the most recent revision asynchronously, and return an async result that wraps that revision + // and returns it projected forward to exactly the desired timestamp, or null if the resource is + // deleted at that timestamp. + final Result loadResult = + (isAtOrAfter(timestamp, resource.getUpdateAutoTimestamp().getTimestamp())) + ? new ResultNow<>(resource) + : loadMostRecentRevisionAtTime(resource, timestamp); + return new Result() { + @Override + public T now() { + T loadedResource = loadResult.now(); + return loadedResource == null ? null + : (isActive(loadedResource, timestamp) + ? cloneProjectedAtTime(loadedResource, timestamp) + : null); + }}; + } + + /** + * Returns an asynchronous result holding the most recent datastore revision of a given + * EppResource before or at the provided timestamp using the EppResource revisions map, falling + * back to using the earliest revision or the resource as-is if there are no revisions. + * + * @see #loadAtPointInTime(EppResource, DateTime) + */ + private static Result loadMostRecentRevisionAtTime( + final T resource, final DateTime timestamp) { + final Key resourceKey = Key.create(resource); + final Ref revision = findMostRecentRevisionAtTime(resource, timestamp); + if (revision == null) { + logger.severefmt("No revision found for %s, falling back to resource.", resourceKey); + return new ResultNow<>(resource); + } + final Result mutationResult = + ofy().load().key(CommitLogMutation.createKey(revision.getKey(), resourceKey)); + return new Result() { + @Override + public T now() { + CommitLogMutation mutation = mutationResult.now(); + if (mutation != null) { + return ofy().load().fromEntity(mutation.getEntity()); + } + logger.severefmt( + "Couldn't load mutation for revision at %s for %s, falling back to resource." + + " Revision: %s", + timestamp, resourceKey, revision); + return resource; + } + }; + } + + @Nullable + private static Ref + findMostRecentRevisionAtTime(final T resource, final DateTime timestamp) { + final Key resourceKey = Key.create(resource); + Entry> revision = resource.getRevisions().floorEntry(timestamp); + if (revision != null) { + logger.infofmt("Found revision history at %s for %s: %s", timestamp, resourceKey, revision); + return revision.getValue(); + } + // Fall back to the earliest revision if we don't have one before the requested timestamp. + revision = resource.getRevisions().firstEntry(); + if (revision != null) { + logger.severefmt("Found no revision history at %s for %s, using earliest revision: %s", + timestamp, resourceKey, revision); + return revision.getValue(); + } + // Ultimate fallback: There are no revisions whatsoever, so return null. + logger.severefmt("Found no revision history at all for %s", resourceKey); + return null; + } + + /** + * Find keys of domains or applications that reference a specified contact or host. + * + *

This is an eventually consistent query. + * + * @param clazz the referent type (contact or host) + * @param ref the referent key + * @param now the logical time of the check + * @param limit max number of keys to return + */ + public static List> queryDomainsUsingResource( + Class clazz, Ref ref, DateTime now, int limit) { + checkArgument(ContactResource.class.equals(clazz) || HostResource.class.equals(clazz)); + return ofy().load().type(DomainBase.class) + .filter( + clazz.equals(ContactResource.class) + ? "allContacts.contactId.linked" + : "nameservers.linked", + ref) + .filter("sharedFields.deletionTime >", now) + .limit(limit) + .keys() + .list(); + } + + /** Clone a contact or host with an eventually-consistent notion of LINKED. */ + public static EppResource cloneResourceWithLinkedStatus(EppResource resource, DateTime now) { + Builder builder = resource.asBuilder(); + if (queryDomainsUsingResource(resource.getClass(), Ref.create(resource), now, 1).isEmpty()) { + builder.removeStatusValue(StatusValue.LINKED); + } else { + builder.addStatusValue(StatusValue.LINKED); + } + return builder.build(); + } + + /** Exception to throw when failing to parse a repo id. */ + public static class InvalidRepoIdException extends Exception { + + public InvalidRepoIdException(String message) { + super(message); + } + } + + private EppResourceUtils() {} +} diff --git a/java/com/google/domain/registry/model/ImmutableObject.java b/java/com/google/domain/registry/model/ImmutableObject.java new file mode 100644 index 000000000..bb998cc5b --- /dev/null +++ b/java/com/google/domain/registry/model/ImmutableObject.java @@ -0,0 +1,167 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Functions.identity; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Maps.transformValues; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Maps; +import com.google.domain.registry.model.domain.ReferenceUnion; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Ignore; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import javax.annotation.concurrent.Immutable; +import javax.xml.bind.annotation.XmlTransient; + +/** An immutable object that implements {@link #equals}, {@link #hashCode} and {@link #toString}. */ +@Immutable +@XmlTransient +public abstract class ImmutableObject implements Cloneable { + + @Ignore + @XmlTransient + Integer hashCode; + + private boolean equalsImmutableObject(ImmutableObject other) { + return getClass().equals(other.getClass()) + && hashCode() == other.hashCode() + && ModelUtils.getFieldValues(this).equals(ModelUtils.getFieldValues(other)); + } + + @Override + public boolean equals(Object other) { + return other instanceof ImmutableObject && equalsImmutableObject((ImmutableObject) other); + } + + @Override + public int hashCode() { + if (hashCode == null) { + hashCode = Arrays.hashCode(ModelUtils.getFieldValues(this).values().toArray()); + } + return hashCode; + } + + /** Returns a clone of the given object. */ + @SuppressWarnings("unchecked") + protected static T clone(T t) { + try { + T clone = (T) t.clone(); + // Clear the hashCode since we often mutate clones before handing them out. + clone.hashCode = null; + return clone; + } catch (CloneNotSupportedException e) { // Yes it is. + throw new IllegalStateException(); + } + } + + /** Returns a clone of the given object with empty fields set to null. */ + protected static T cloneEmptyToNull(T t) { + return ModelUtils.cloneEmptyToNull(t); + } + + /** + * Returns a string view of the object, formatted like: + * + *

+   * ModelObject (@12345): {
+   *   field1=value1
+   *   field2=[a,b,c]
+   *   field3=AnotherModelObject: {
+   *     foo=bar
+   *   }
+   * }
+   * 
+ */ + @Override + public String toString() { + return toStringHelper(identity()); + } + + /** + * Similar to toString(), with a full expansion of embedded ImmutableObjects, + * collections, and references. + */ + public String toHydratedString() { + return toStringHelper(new Function() { + @Override + public Object apply(Object input) { + if (input instanceof ReferenceUnion) { + return apply(((ReferenceUnion) input).getLinked().get()); + } else if (input instanceof Ref) { + // Only follow references of type Ref, not of type Key (the latter deliberately used for + // references that should not be followed) + return apply(((Ref) input).get()); + } else if (input instanceof Map) { + return transformValues((Map) input, this); + } else if (input instanceof Collection) { + return transform((Collection) input, this); + } else if (input instanceof ImmutableObject) { + return ((ImmutableObject) input).toHydratedString(); + } + return input; + }}); + } + + public String toStringHelper(Function transformation) { + Map sortedFields = Maps.newTreeMap(); + sortedFields.putAll( + transformValues(ModelUtils.getFieldValues(this), transformation)); + return String.format( + "%s (@%s): {\n%s", + getClass().getSimpleName(), + System.identityHashCode(this), + Joiner.on('\n').join(sortedFields.entrySet())) + .replaceAll("\n", "\n ") + "\n}"; + } + + /** Helper function to recursively convert a ImmutableObject to a Map of generic objects. */ + private static final Function TO_MAP_HELPER = new Function() { + @Override + public Object apply(Object o) { + if (o == null) { + return null; + } else if (o instanceof ImmutableObject) { + Map result = + Maps.transformValues(ModelUtils.getFieldValues(o), this); + return result; + } else if (o instanceof Map) { + return Maps.transformValues((Map) o, this); + } else if (o instanceof Set) { + return FluentIterable.from((Set) o).transform(this).toSet(); + } else if (o instanceof Collection) { + return FluentIterable.from((Collection) o).transform(this).toList(); + } else if (o instanceof Number || o instanceof Boolean) { + return o; + } else { + return o.toString(); + } + }}; + + /** Returns a map of all object fields (including sensitive data) that's used to produce diffs. */ + @SuppressWarnings("unchecked") + public Map toDiffableFieldMap() { + return (Map) TO_MAP_HELPER.apply(this); + } +} diff --git a/java/com/google/domain/registry/model/JsonMapBuilder.java b/java/com/google/domain/registry/model/JsonMapBuilder.java new file mode 100644 index 000000000..38c435d6f --- /dev/null +++ b/java/com/google/domain/registry/model/JsonMapBuilder.java @@ -0,0 +1,91 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.collect.FluentIterable; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Helper class for {@link Jsonifiable} classes to generate JSON maps for RPC responses. + * + *

The returned map is mutable. Map entries can be {@code null} but list entries can not. If a + * list is passed as {@code null}, it'll be substituted with empty list. Lists are not mutable. + */ +public final class JsonMapBuilder { + + private static final Function> TO_JSON_OBJECT = + new Function>() { + @Override + public Map apply(Jsonifiable input) { + return input.toJsonMap(); + }}; + + private final Map map = new LinkedHashMap<>(); + + public JsonMapBuilder put(String name, @Nullable Boolean value) { + map.put(name, value); + return this; + } + + public JsonMapBuilder put(String name, @Nullable Number value) { + map.put(name, value); + return this; + } + + public JsonMapBuilder put(String name, @Nullable String value) { + map.put(name, value); + return this; + } + + public JsonMapBuilder put(String name, @Nullable Jsonifiable value) { + map.put(name, value == null ? null : value.toJsonMap()); + return this; + } + + public JsonMapBuilder put(String name, @Nullable Enum value) { + map.put(name, value == null ? null : value.name()); + return this; + } + + public JsonMapBuilder putString(String name, @Nullable T value) { + map.put(name, value == null ? null : value.toString()); + return this; + } + + public JsonMapBuilder putListOfStrings(String name, @Nullable Iterable value) { + map.put(name, value == null ? Collections.EMPTY_LIST + : FluentIterable.from(value).transform(Functions.toStringFunction()).toList()); + return this; + } + + public JsonMapBuilder putListOfJsonObjects( + String name, @Nullable Iterable value) { + map.put(name, value == null ? Collections.EMPTY_LIST + : FluentIterable.from(value).transform(TO_JSON_OBJECT).toList()); + return this; + } + + /** Returns mutable JSON object. Please dispose of the builder object after calling me. */ + public Map build() { + return map; + } +} diff --git a/java/com/google/domain/registry/model/Jsonifiable.java b/java/com/google/domain/registry/model/Jsonifiable.java new file mode 100644 index 000000000..22a9e5aa9 --- /dev/null +++ b/java/com/google/domain/registry/model/Jsonifiable.java @@ -0,0 +1,29 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import java.util.Map; + +/** Interface for objects that may be converted to JSON. */ +public interface Jsonifiable { + + /** + * Returns a JSON representation of this object. + * + *

The returned value must not return sensitive fields, so that it may be safe to return to + * the client via an API response. + */ + Map toJsonMap(); +} diff --git a/java/com/google/domain/registry/model/ModelUtils.java b/java/com/google/domain/registry/model/ModelUtils.java new file mode 100644 index 000000000..3f42834bc --- /dev/null +++ b/java/com/google/domain/registry/model/ModelUtils.java @@ -0,0 +1,296 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.instanceOf; +import static com.google.common.base.Predicates.isNull; +import static com.google.common.base.Predicates.or; +import static com.google.common.collect.Iterables.all; +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.transformValues; +import static com.google.common.collect.Sets.newLinkedHashSet; +import static java.util.Arrays.asList; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.Parent; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Deque; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** A collection of static methods that deal with reflection on model classes. */ +public class ModelUtils { + + /** Caches all instance fields on an object, including non-public and inherited fields. */ + private static final LoadingCache, ImmutableMap> ALL_FIELDS_CACHE = + CacheBuilder.newBuilder().build(new CacheLoader, ImmutableMap>() { + @Override + public ImmutableMap load(Class clazz) { + Deque> hierarchy = new LinkedList<>(); + // Walk the hierarchy up to but not including ImmutableObject (to ignore hashCode). + for (; clazz != ImmutableObject.class; clazz = clazz.getSuperclass()) { + // Add to the front, so that shadowed fields show up later in the list. + // This will mean that getFieldValues will show the most derived value. + hierarchy.addFirst(clazz); + } + Map fields = new LinkedHashMap<>(); + for (Class hierarchyClass : hierarchy) { + Package pakkage = hierarchyClass.getPackage(); + // Don't use hierarchyClass.getFields() because it only picks up public fields. + for (Field field : hierarchyClass.getDeclaredFields()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + // Strictly speaking this shouldn't be necessary since all of these fields + // are already accessible to their FieldExposer, but it is more performant + // to access fields if they are marked accessible this way because it skips + // various security checks. + checkNotNull( + FIELD_EXPOSERS.get(pakkage), + "No FieldExposer registered for %s", pakkage.getName()) + .setAccessible(field); + fields.put(field.getName(), field); + } + } + return ImmutableMap.copyOf(fields); + }}); + + /** Per-package trampolines to expose package-private fields for reflection. */ + private static final Map FIELD_EXPOSERS = Maps.uniqueIndex( + FieldExposerRegistry.getFieldExposers(), + new Function() { + @Override + public Package apply(AbstractFieldExposer exposer) { + return exposer.getClass().getPackage(); + }}); + + /** Lists all instance fields on an object, including non-public and inherited fields. */ + static Map getAllFields(Class clazz) { + return ALL_FIELDS_CACHE.getUnchecked(clazz); + } + + /** Return a string representing the persisted schema of a type or enum. */ + static String getSchema(Class clazz) { + StringBuilder stringBuilder = new StringBuilder(); + Iterable body; + if (clazz.isEnum()) { + stringBuilder.append("enum "); + body = FluentIterable.from(asList(clazz.getEnumConstants())); + } else { + stringBuilder.append("class "); + body = FluentIterable.from(getAllFields(clazz).values()) + .filter(new Predicate() { + @Override + public boolean apply(Field field) { + return !field.isAnnotationPresent(Ignore.class); + }}) + .transform(new Function() { + @Override + public Object apply(Field field) { + String annotation = field.isAnnotationPresent(Id.class) + ? "@Id " + : field.isAnnotationPresent(Parent.class) + ? "@Parent " + : ""; + String type = field.getType().isArray() + ? field.getType().getComponentType().getName() + "[]" + : field.getGenericType().toString().replaceFirst("class ", ""); + return String.format("%s%s %s", annotation, type, field.getName()); + }}); + } + return stringBuilder + .append(clazz.getName()).append(" {\n ") + .append(Joiner.on(";\n ").join(Ordering.usingToString().sortedCopy(body))) + .append(";\n}") + .toString(); + } + + /** + * Returns the set of Class objects of all persisted fields. This includes the parameterized + * type(s) of any fields (if any). + */ + static Set> getPersistedFieldTypes(Class clazz) { + ImmutableSet.Builder> builder = new ImmutableSet.Builder<>(); + for (Field field : getAllFields(clazz).values()) { + // Skip fields that aren't persisted to datastore. + if (field.isAnnotationPresent(Ignore.class)) { + continue; + } + + // If the field's type is the same as the field's class object, then it's a non-parameterized + // type, and thus we just add it directly. We also don't bother looking at the parameterized + // types of Key and Ref objects, since they are just references to other objects and don't + // actual embed themselves in the persisted object anyway. + Class fieldClazz = field.getType(); + Type fieldType = field.getGenericType(); + builder.add(fieldClazz); + if (fieldType.equals(fieldClazz) || Ref.class.equals(clazz) || Key.class.equals(clazz)) { + continue; + } + + // If the field is a parameterized type, then also add the parameterized field. + if (fieldType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) fieldType; + for (Type actualType : parameterizedType.getActualTypeArguments()) { + if (actualType instanceof Class) { + builder.add((Class) actualType); + } else { + // We intentionally ignore types that are parameterized on non-concrete types. In theory + // we could have collections embedded within collections, but Objectify does not allow + // that. + } + } + } + } + return builder.build(); + } + + /** Retrieves a field value via reflection. */ + static Object getFieldValue(Object instance, Field field) { + try { + return Preconditions.checkNotNull( + FIELD_EXPOSERS.get(field.getDeclaringClass().getPackage()), + "No FieldExposer registered for %s", field.getDeclaringClass().getPackage().getName()) + .getFieldValue(instance, field); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + /** Sets a field value via reflection. */ + static void setFieldValue(Object instance, Field field, Object value) { + try { + Preconditions.checkNotNull( + FIELD_EXPOSERS.get(field.getDeclaringClass().getPackage()), + "No FieldExposer registered for %s", field.getDeclaringClass().getPackage().getName()) + .setFieldValue(instance, field, value); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns a map from field names (including non-public and inherited fields) to values. + *

+ * This turns arrays into {@link List} objects so that ImmutableObject can more easily use the + * returned map in its implementation of {@link ImmutableObject#toString} and + * {@link ImmutableObject#equals}, which work by comparing and printing these maps. + */ + static Map getFieldValues(Object instance) { + // Don't make this ImmutableMap because field values can be null. + Map values = new LinkedHashMap<>(); + for (Field field : getAllFields(instance.getClass()).values()) { + Object value = getFieldValue(instance, field); + if (value != null && value.getClass().isArray()) { + // It's surprisingly difficult to convert arrays into lists if the array might be primitive. + final Object arrayValue = value; + value = new AbstractList() { + @Override + public Object get(int index) { + return Array.get(arrayValue, index); + } + + @Override + public int size() { + return Array.getLength(arrayValue); + }}; + } + values.put(field.getName(), value); + } + return values; + } + + /** Functional helper for {@link #cloneEmptyToNull}. */ + private static final Function CLONE_EMPTY_TO_NULL = new Function() { + @Override + public Object apply(Object obj) { + if (obj instanceof ImmutableSortedMap) { + // ImmutableSortedMapTranslatorFactory handles empty for us. If the object is null, then + // its on-save hook can't run. + return obj; + } + if ("".equals(obj) + || (obj instanceof Collection && ((Collection) obj).isEmpty()) + || (obj instanceof Map && ((Map) obj).isEmpty()) + || (obj != null && obj.getClass().isArray() && Array.getLength(obj) == 0)) { + return null; + } + Predicate immutableObjectOrNull = or(isNull(), instanceOf(ImmutableObject.class)); + if ((obj instanceof Set || obj instanceof List) + && all((Iterable) obj, immutableObjectOrNull)) { + // Recurse into sets and lists, but only if they contain ImmutableObjects. + FluentIterable fluent = FluentIterable.from((Iterable) obj).transform(this); + return (obj instanceof List) ? newArrayList(fluent) : newLinkedHashSet(fluent); + } + if (obj instanceof Map && all(((Map) obj).values(), immutableObjectOrNull)) { + // Recurse into maps with ImmutableObject values. + return transformValues((Map) obj, this); + } + if (obj instanceof ImmutableObject) { + // Recurse on the fields of an ImmutableObject. + ImmutableObject copy = ImmutableObject.clone((ImmutableObject) obj); + for (Field field : getAllFields(obj.getClass()).values()) { + Object oldValue = getFieldValue(obj, field); + Object newValue = apply(oldValue); + if (!Objects.equals(oldValue, newValue)) { + setFieldValue(copy, field, newValue); + } + } + return copy; + } + return obj; + }}; + + /** Returns a clone of the object and sets empty collections, arrays, maps and strings to null. */ + @SuppressWarnings("unchecked") + protected static T cloneEmptyToNull(T obj) { + return (T) CLONE_EMPTY_TO_NULL.apply(obj); + } + + @VisibleForTesting + static void resetCaches() { + ALL_FIELDS_CACHE.invalidateAll(); + } +} diff --git a/java/com/google/domain/registry/model/RoidSuffixes.java b/java/com/google/domain/registry/model/RoidSuffixes.java new file mode 100644 index 000000000..6801df461 --- /dev/null +++ b/java/com/google/domain/registry/model/RoidSuffixes.java @@ -0,0 +1,65 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CacheUtils.memoizeWithShortExpiration; + +import com.google.common.base.Supplier; +import com.google.common.collect.HashBiMap; +import com.google.domain.registry.model.registry.Registry; + +import com.googlecode.objectify.Work; + +/** Utility class for dealing with EPP ROID suffixes. */ +public final class RoidSuffixes { + + private static Supplier> roidSuffixMapCache = + memoizeWithShortExpiration(new Supplier>() { + @Override + public HashBiMap get() { + return ofy().doTransactionless(new Work>() { + @Override + public HashBiMap run() { + HashBiMap bimap = HashBiMap.create(); + for (Registry registry : + ofy().load().type(Registry.class).ancestor(getCrossTldKey()).list()) { + bimap.put(registry.getTldStr(), registry.getRoidSuffix()); + } + return bimap; + } + }); + } + }); + + /** + * Returns the roid suffix corresponding to the given tld using the per-tld roidSuffix field. + * + * @throws IllegalStateException if there is no such tld, or the tld does not have a roid suffix + * configured on it + */ + public static String getRoidSuffixForTld(String tld) { + String roidSuffix = roidSuffixMapCache.get().get(tld); + checkState(roidSuffix != null, "Could not find ROID suffix for TLD %s", tld); + return roidSuffix; + } + + public static boolean isRoidSuffixUsed(String roidSuffix) { + return roidSuffixMapCache.get().containsValue(roidSuffix); + } + +} diff --git a/java/com/google/domain/registry/model/SchemaVersion.java b/java/com/google/domain/registry/model/SchemaVersion.java new file mode 100644 index 000000000..ab081bc5a --- /dev/null +++ b/java/com/google/domain/registry/model/SchemaVersion.java @@ -0,0 +1,75 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.common.base.Predicates.assignableFrom; +import static com.google.common.base.Predicates.or; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Ordering; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.SortedSet; +import java.util.TreeSet; + +/** Utility methods for getting the version of the model schema from the model code. */ +public final class SchemaVersion { + + /** + * Returns a set of classes corresponding to all types persisted within the model classes, sorted + * by the string representation. + */ + private static SortedSet> getAllPersistedTypes() { + SortedSet> persistedTypes = new TreeSet<>(Ordering.usingToString()); + Queue> queue = new ArrayDeque<>(); + // Do a breadth-first search for persisted types, starting with @Entity types and expanding each + // ImmutableObject by querying it for all its persisted field types. + persistedTypes.addAll(EntityClasses.ALL_CLASSES); + queue.addAll(persistedTypes); + while (!queue.isEmpty()) { + Class clazz = queue.remove(); + if (ImmutableObject.class.isAssignableFrom(clazz)) { + for (Class persistedFieldType : ModelUtils.getPersistedFieldTypes(clazz)) { + if (persistedTypes.add(persistedFieldType)) { + // If we haven't seen this type before, add it to the queue to query its field types. + queue.add(persistedFieldType); + } + } + } + } + return persistedTypes; + } + + /** + * Return a string representing the schema which includes the definition of all persisted entity + * types (and their field types, recursively). Each definition contains the field names and their + * types (for classes), or else a list of all possible values (for enums). + */ + public static String getSchema() { + return FluentIterable.from(getAllPersistedTypes()) + .filter(or(assignableFrom(Enum.class), assignableFrom(ImmutableObject.class))) + .transform(new Function, String>() { + @Override + public String apply(Class clazz) { + return ModelUtils.getSchema(clazz); + }}) + .join(Joiner.on('\n')); + } + + private SchemaVersion() {} +} diff --git a/java/com/google/domain/registry/model/UpdateAutoTimestamp.java b/java/com/google/domain/registry/model/UpdateAutoTimestamp.java new file mode 100644 index 000000000..f4e899937 --- /dev/null +++ b/java/com/google/domain/registry/model/UpdateAutoTimestamp.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model; + +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.translators.UpdateAutoTimestampTranslatorFactory; + +import org.joda.time.DateTime; + +/** + * A timestamp that auto-updates on each save to datastore. + * + * @see UpdateAutoTimestampTranslatorFactory + */ +public class UpdateAutoTimestamp extends ImmutableObject { + + DateTime timestamp; + + /** Returns the timestamp, or {@link #START_OF_TIME} if it's null. */ + public DateTime getTimestamp() { + return Optional.fromNullable(timestamp).or(START_OF_TIME); + } + + public static UpdateAutoTimestamp create(DateTime timestamp) { + UpdateAutoTimestamp instance = new UpdateAutoTimestamp(); + instance.timestamp = timestamp; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/annotations/ExternalMessagingName.java b/java/com/google/domain/registry/model/annotations/ExternalMessagingName.java new file mode 100644 index 000000000..8ad03e800 --- /dev/null +++ b/java/com/google/domain/registry/model/annotations/ExternalMessagingName.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotation to provide a name for a class to use in external error messages. */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ExternalMessagingName { + String value(); +} diff --git a/java/com/google/domain/registry/model/annotations/NotBackedUp.java b/java/com/google/domain/registry/model/annotations/NotBackedUp.java new file mode 100644 index 000000000..50d460665 --- /dev/null +++ b/java/com/google/domain/registry/model/annotations/NotBackedUp.java @@ -0,0 +1,47 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.annotations; + +import com.googlecode.objectify.annotation.Entity; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for an Objectify {@link Entity} to indicate that it should not be backed up by the + * default datastore backup configuration (it may be backed up by something else). + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface NotBackedUp { + Reason reason(); + + /** Reasons why a given entity does not need to be be backed up. */ + public enum Reason { + /** This entity is transient by design and has only a short-term useful lifetime. */ + TRANSIENT, + + /** This entity's data is already regularly pulled down from an external source. */ + EXTERNALLY_SOURCED, + + /** This entity is generated automatically by the app and will be recreated if need be. */ + AUTO_GENERATED, + + /** Commit log entities are exported separately from the regular backups, by design. */ + COMMIT_LOGS + } +} diff --git a/java/com/google/domain/registry/model/annotations/VirtualEntity.java b/java/com/google/domain/registry/model/annotations/VirtualEntity.java new file mode 100644 index 000000000..651690ac1 --- /dev/null +++ b/java/com/google/domain/registry/model/annotations/VirtualEntity.java @@ -0,0 +1,32 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.annotations; + +import com.googlecode.objectify.annotation.Entity; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for an Objectify {@link Entity} to indicate that it is a "virtual entity". + * + *

A virtual entity type exists only to define part of the parentage key hierarchy for its + * child entities, and is never actually persisted and thus has no fields besides its ID field. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface VirtualEntity {} diff --git a/java/com/google/domain/registry/model/billing/BillingEvent.java b/java/com/google/domain/registry/model/billing/BillingEvent.java new file mode 100644 index 000000000..f24e2cb32 --- /dev/null +++ b/java/com/google/domain/registry/model/billing/BillingEvent.java @@ -0,0 +1,541 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.billing; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.common.TimeOfYear; +import com.google.domain.registry.model.domain.GracePeriod; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferData.TransferServerApproveEntity; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.Objects; +import java.util.Set; + +/** A billable event in a domain's lifecycle. */ +public abstract class BillingEvent extends ImmutableObject + implements Buildable, TransferServerApproveEntity { + + /** The reason for the bill. */ + public enum Reason { + CREATE, + TRANSFER, + RENEW, + AUTO_RENEW, + RESTORE, + SERVER_STATUS, + ERROR + } + + /** Set of flags that can be applied to billing events. */ + public enum Flag { + ALLOCATION, + ANCHOR_TENANT, + LANDRUSH, + SUNRISE + } + + /** Entity id. */ + @Id + long id; + + @Parent + Key parent; + + /** The registrar to bill. */ + @Index + String clientId; + + /** When this event was created. For recurring events, this is also the recurrence start time. */ + @Index + DateTime eventTime; + + /** The reason for the bill. */ + Reason reason; + + /** The fully qualified domain name of the domain that the bill is for. */ + String targetId; + + Set flags; + + public String getClientId() { + return clientId; + } + + public DateTime getEventTime() { + return eventTime; + } + + public long getId() { + return id; + } + + public Reason getReason() { + return reason; + } + + public String getTargetId() { + return targetId; + } + + public Key getParentKey() { + return parent; + } + + public ImmutableSet getFlags() { + return nullToEmptyImmutableCopy(flags); + } + + /** Override Buildable.asBuilder() to give this method stronger typing. */ + @Override + public abstract Builder asBuilder(); + + /** An abstract builder for {@link BillingEvent}. */ + public abstract static class Builder> + extends GenericBuilder { + + protected Builder() {} + + protected Builder(T instance) { + super(instance); + } + + public B setReason(Reason reason) { + getInstance().reason = reason; + return thisCastToDerived(); + } + + public B setId(Long id) { + getInstance().id = id; + return thisCastToDerived(); + } + + public B setClientId(String clientId) { + getInstance().clientId = clientId; + return thisCastToDerived(); + } + + public B setEventTime(DateTime eventTime) { + getInstance().eventTime = eventTime; + return thisCastToDerived(); + } + + public B setTargetId(String targetId) { + getInstance().targetId = targetId; + return thisCastToDerived(); + } + + public B setFlags(ImmutableSet flags) { + getInstance().flags = flags; + return thisCastToDerived(); + } + + public B setParent(HistoryEntry parent) { + getInstance().parent = Key.create(parent); + return thisCastToDerived(); + } + + public B setParent(Key parentKey) { + getInstance().parent = parentKey; + return thisCastToDerived(); + } + + @Override + public T build() { + T instance = getInstance(); + checkNotNull(instance.reason); + checkNotNull(instance.clientId); + checkNotNull(instance.eventTime); + checkNotNull(instance.targetId); + checkNotNull(instance.parent); + return super.build(); + } + } + + /** A one-time billable event. */ + @Entity + public static class OneTime extends BillingEvent { + + /** The billable value. */ + Money cost; + + /** When the cost should be billed. */ + @Index + DateTime billingTime; + + /** + * The period in years of the action being billed for, if applicable, otherwise null. + * Used for financial reporting. + */ + @IgnoreSave(IfNull.class) + Integer periodYears = null; + + public Money getCost() { + return cost; + } + + public DateTime getBillingTime() { + return billingTime; + } + + public Integer getPeriodYears() { + return periodYears; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link OneTime} since it is immutable. */ + public static class Builder extends BillingEvent.Builder { + + public Builder() {} + + private Builder(OneTime instance) { + super(instance); + } + + public Builder setCost(Money cost) { + getInstance().cost = cost; + return this; + } + + public Builder setPeriodYears(Integer periodYears) { + checkNotNull(periodYears); + checkArgument(periodYears > 0); + getInstance().periodYears = periodYears; + return this; + } + + public Builder setBillingTime(DateTime billingTime) { + getInstance().billingTime = billingTime; + return this; + } + + @Override + public OneTime build() { + OneTime instance = getInstance(); + checkNotNull(instance.billingTime); + checkNotNull(instance.cost); + checkState(!instance.cost.isNegative(), "Costs should be non-negative."); + ImmutableSet reasonsWithPeriods = + Sets.immutableEnumSet(Reason.CREATE, Reason.RENEW, Reason.TRANSFER); + checkState( + reasonsWithPeriods.contains(instance.reason) == (instance.periodYears != null), + "Period years must be set if and only if reason is CREATE, RENEW, or TRANSFER."); + return super.build(); + } + } + } + + /** + * A recurring billable event. + *

+ * Unlike {@link OneTime} events, these do not store an explicit cost, since the cost of the + * recurring event might change and each time we bill for it we need to bill at the current cost, + * not the value that was in use at the time the recurrence was created. + */ + @Entity + public static class Recurring extends BillingEvent { + + /** + * The billing event recurs every year between {@link #eventTime} and this time on the + * [month, day, time] specified in {@link #recurrenceTimeOfYear}. + */ + @Index + DateTime recurrenceEndTime; + + /** + * The eventTime recurs every year on this [month, day, time] between {@link #eventTime} and + * {@link #recurrenceEndTime}, inclusive of the start but not of the end. + *

+ * This field is denormalized from {@link #eventTime} to allow for an efficient index, but it + * always has the same data as that field. + *

+ * Note that this is a recurrence of the event time, not the billing time. The billing time can + * be calculated by adding the relevant grace period length to this date. The reason for this + * requirement is that the event time recurs on a {@link org.joda.time.Period} schedule (same + * day of year, which can be 365 or 366 days later) which is what {@link TimeOfYear} can model, + * whereas the billing time is a fixed {@link org.joda.time.Duration} later. + */ + @Index + TimeOfYear recurrenceTimeOfYear; + + public DateTime getRecurrenceEndTime() { + return recurrenceEndTime; + } + + public TimeOfYear getRecurrenceTimeOfYear() { + return recurrenceTimeOfYear; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link Recurring} since it is immutable. */ + public static class Builder extends BillingEvent.Builder { + + public Builder() {} + + private Builder(Recurring instance) { + super(instance); + } + + public Builder setRecurrenceEndTime(DateTime recurrenceEndTime) { + getInstance().recurrenceEndTime = recurrenceEndTime; + return this; + } + + @Override + public Recurring build() { + Recurring instance = getInstance(); + checkNotNull(instance.eventTime); + checkNotNull(instance.reason); + instance.recurrenceTimeOfYear = TimeOfYear.fromDateTime(instance.eventTime); + instance.recurrenceEndTime = + Optional.fromNullable(instance.recurrenceEndTime).or(END_OF_TIME); + return super.build(); + } + } + } + + /** + * An event representing a cancellation of one of the other two billable event types. + *

+ * This is implemented as a separate event rather than a bit on BillingEvent in order to preserve + * the immutability of billing events. + */ + @Entity + public static class Cancellation extends BillingEvent { + + /** The billing time of the charge that is being cancelled. */ + @Index + DateTime billingTime; + + /** The one-time billing event to cancel, or null for autorenew cancellations. */ + @IgnoreSave(IfNull.class) + Ref refOneTime = null; + + /** The recurring billing event to cancel, or null for non-autorenew cancellations. */ + @IgnoreSave(IfNull.class) + Ref refRecurring = null; + + public DateTime getBillingTime() { + return billingTime; + } + + public Ref getEventRef() { + return firstNonNull(refOneTime, refRecurring); + } + + /** The mapping from billable grace period types to originating billing event reasons. */ + static final ImmutableMap GRACE_PERIOD_TO_REASON = + ImmutableMap.of( + GracePeriodStatus.ADD, Reason.CREATE, + GracePeriodStatus.AUTO_RENEW, Reason.AUTO_RENEW, + GracePeriodStatus.RENEW, Reason.RENEW, + GracePeriodStatus.TRANSFER, Reason.TRANSFER); + + /** + * Creates a cancellation billing event for the provided grace period parented on the provided + * history entry (and with the same event time) that will cancel out the + * grace-period-originating billing event on the supplied targetId. + */ + public static BillingEvent.Cancellation forGracePeriod( + GracePeriod gracePeriod, HistoryEntry historyEntry, String targetId) { + return new BillingEvent.Cancellation.Builder() + .setReason(checkNotNull(GRACE_PERIOD_TO_REASON.get(gracePeriod.getType()))) + .setTargetId(targetId) + .setClientId(gracePeriod.getClientId()) + .setEventTime(historyEntry.getModificationTime()) + // The charge being cancelled will take place at the grace period's expiration time. + .setBillingTime(gracePeriod.getExpirationTime()) + .setEventRef(gracePeriod.getBillingEvent()) + .setParent(historyEntry) + .build(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link Cancellation} since it is immutable. */ + public static class Builder extends BillingEvent.Builder { + + private Ref refTemp; + + public Builder() {} + + private Builder(Cancellation instance) { + super(instance); + } + + public Builder setBillingTime(DateTime billingTime) { + getInstance().billingTime = billingTime; + return this; + } + + public Builder setEventRef(Ref eventRef) { + refTemp = eventRef; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public Cancellation build() { + Cancellation instance = getInstance(); + checkNotNull(instance.billingTime); + checkNotNull(instance.reason); + // If refTemp is set, use it to populate the correct ref. + if (refTemp != null) { + if (Reason.AUTO_RENEW.equals(instance.reason)) { + instance.refRecurring = (Ref) refTemp; + } else { + instance.refOneTime = (Ref) refTemp; + } + } + // Ensure that even if refTemp was not set, the builder has exactly one of the two refs + // set to a non-null value (using != as an XOR for booleans). + checkState((instance.refOneTime == null) != (instance.refRecurring == null)); + return super.build(); + } + } + } + + /** + * An event representing a modification of an existing one-time billing event. + */ + @Entity + public static class Modification extends BillingEvent { + + /** The change in cost that should be applied to the original billing event. */ + Money cost; + + /** The one-time billing event to modify. */ + Ref eventRef; + + /** + * Description of the modification (and presumably why it was issued). This text may appear as a + * line item on an invoice or report about such modifications. + */ + String description; + + public Money getCost() { + return cost; + } + + public Ref getEventRef() { + return eventRef; + } + + public String getDescription() { + return description; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** + * Create a new Modification billing event which is a refund of the given OneTime billing event + * and that is parented off the given HistoryEntry. + * + *

Note that this method may appear to be unused most of the time, but it is kept around + * because it is needed by one-off scrap tools that need to make billing adjustments. + */ + public static Modification createRefundFor( + OneTime billingEvent, HistoryEntry historyEntry, String description) { + return new Builder() + .setClientId(billingEvent.getClientId()) + .setFlags(billingEvent.getFlags()) + .setReason(billingEvent.getReason()) + .setTargetId(billingEvent.getTargetId()) + .setEventRef(Ref.create(billingEvent)) + .setEventTime(historyEntry.getModificationTime()) + .setDescription(description) + .setCost(billingEvent.getCost().negated()) + .setParent(historyEntry) + .build(); + } + + /** A builder for {@link Modification} since it is immutable. */ + public static class Builder extends BillingEvent.Builder { + + public Builder() {} + + private Builder(Modification instance) { + super(instance); + } + + public Builder setCost(Money cost) { + getInstance().cost = cost; + return this; + } + + public Builder setEventRef(Ref eventRef) { + getInstance().eventRef = eventRef; + return this; + } + + public Builder setDescription(String description) { + getInstance().description = description; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public Modification build() { + Modification instance = getInstance(); + checkNotNull(instance.reason); + checkNotNull(instance.eventRef); + BillingEvent.OneTime billingEvent = instance.eventRef.get(); + checkArgument(Objects.equals( + instance.cost.getCurrencyUnit(), + billingEvent.cost.getCurrencyUnit()), + "Referenced billing event is in a different currency"); + return super.build(); + } + } + } +} diff --git a/java/com/google/domain/registry/model/billing/RegistrarBillingEntry.java b/java/com/google/domain/registry/model/billing/RegistrarBillingEntry.java new file mode 100644 index 000000000..7f888bcde --- /dev/null +++ b/java/com/google/domain/registry/model/billing/RegistrarBillingEntry.java @@ -0,0 +1,212 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.billing; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.base.Verify.verifyNotNull; + +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.JsonMapBuilder; +import com.google.domain.registry.model.Jsonifiable; +import com.google.domain.registry.model.registrar.Registrar; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Log of monthly invoices and payments for a Registrar customer. + * + *

This is a one-off single-entry bookkeeping system. There is a separate account for each + * (registrar, currency) pair. + * + *

You should never update these entities once they've been inserted into datastore. If you need + * to change something, add a correction entry. + */ +@Entity +public class RegistrarBillingEntry extends ImmutableObject implements Jsonifiable { + + @Parent + Key parent; + + /** Arbitrary unique identifier. */ + @Id + long id; + + /** + * External transaction identifier or {@code null} if this is an invoice entry. + * + *

This is the ID or token that the payment gateway gives us, which represents the transaction + * in their database. + */ + @Nullable + String transactionId; + + /** + * Time at which this entry was created. + * + *

This value is unique and monotonic for a given ({@link #parent}, {@link #currency}) pair. + */ + @Index + DateTime created; + + /** Completely arbitrary description of payment. */ + String description; + + /** + * Currency of transaction. + * + *

This field is identical to {@code amount.getCurrencyUnit()} and is only here so it can be + * indexed in datastore. + */ + @Index + CurrencyUnit currency; + + /** + * Amount and currency of invoice or payment. + * + *

This field is positive for debits (e.g. monthly invoice entries) and negative for credits + * (e.g. credit card payment transaction entries.) + */ + Money amount; + + /** + * Balance of account for this currency. + * + *

This is {@code amount + previous.balance}. + */ + Money balance; + + public Key getParent() { + return parent; + } + + public long getId() { + return id; + } + + @Nullable + public String getTransactionId() { + return transactionId; + } + + public DateTime getCreated() { + return verifyNotNull(created, "created missing: %s", this); + } + + public String getDescription() { + return verifyNotNull(description, "description missing: %s", this); + } + + public CurrencyUnit getCurrency() { + return verifyNotNull(currency, "currency missing: %s", this); + } + + public Money getAmount() { + return verifyNotNull(amount, "amount missing: %s", this); + } + + public Money getBalance() { + return verifyNotNull(balance, "balance missing: %s", this); + } + + @Override + public Map toJsonMap() { + return new JsonMapBuilder() + .put("id", id) + .put("transactionId", getTransactionId()) + .putString("created", getCreated()) + .put("description", getDescription()) + .putString("currency", getCurrency()) + .putString("amount", getAmount().getAmount()) + .putString("balance", getBalance().getAmount()) + .build(); + } + + /** A builder for constructing a {@link RegistrarBillingEntry}, since it's immutable. */ + public static class Builder extends Buildable.Builder { + + @Nullable + private RegistrarBillingEntry previous; + + public Builder() {} + + public Builder setParent(Registrar parent) { + getInstance().parent = Key.create(parent); + return this; + } + + public Builder setCreated(DateTime created) { + getInstance().created = created; + return this; + } + + public Builder setPrevious(@Nullable RegistrarBillingEntry previous) { + this.previous = previous; + return this; + } + + public Builder setTransactionId(@Nullable String transactionId) { + getInstance().transactionId = transactionId; + return this; + } + + public Builder setDescription(String description) { + getInstance().description = checkNotNull(emptyToNull(description)); + return this; + } + + public Builder setAmount(Money amount) { + checkArgument(!amount.isZero(), "Amount can't be zero"); + getInstance().amount = amount; + getInstance().currency = amount.getCurrencyUnit(); + return this; + } + + @Override + public RegistrarBillingEntry build() { + checkNotNull(getInstance().parent, "parent"); + checkNotNull(getInstance().created, "created"); + checkNotNull(getInstance().description, "description"); + checkNotNull(getInstance().amount, "amount"); + if (previous == null) { + getInstance().balance = getInstance().amount; + } else { + getInstance().balance = previous.balance.plus(getInstance().amount); + checkState(getInstance().parent.equals(previous.parent), + "Parent not same as previous:\nNew: %s\nPrevious: %s", + getInstance(), previous); + checkState(getInstance().created.isAfter(previous.created), + "Created timestamp not after previous:\nNew: %s\nPrevious: %s", + getInstance(), previous); + } + return cloneEmptyToNull(super.build()); + } + } +} diff --git a/java/com/google/domain/registry/model/billing/RegistrarBillingUtils.java b/java/com/google/domain/registry/model/billing/RegistrarBillingUtils.java new file mode 100644 index 000000000..57b9de6e0 --- /dev/null +++ b/java/com/google/domain/registry/model/billing/RegistrarBillingUtils.java @@ -0,0 +1,100 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.billing; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Maps.EntryTransformer; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registry.Registries; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.util.CacheUtils; + +import com.googlecode.objectify.cmd.Query; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; + +import java.util.Map; + +/** Utilities for managing the billing of {@link Registrar} customers. */ +public final class RegistrarBillingUtils { + + private static final Supplier> CURRENCIES_CACHE = + CacheUtils.memoizeWithShortExpiration( + new Supplier>() { + @Override + public ImmutableSortedSet get() { + return FluentIterable + .from(Registries.getTlds()) + .transform(new Function() { + @Override + public CurrencyUnit apply(String tld) { + return Registry.get(tld).getCurrency(); + }}) + .toSortedSet(Ordering.natural()); + } + }); + + /** + * Returns set of currencies in which registrars may be billed. + * + *

Each TLD has a currency associated with it. We don't do conversions. The registrar customer + * gets a separate bill for each currency. + */ + public static ImmutableSortedSet getCurrencies() { + return CURRENCIES_CACHE.get(); + } + + /** + * Returns query of {@link RegistrarBillingEntry} for each currency, most recent first. + * + *

Note: Currency map keys are returned in sorted order, from {@link #getCurrencies()}. + */ + public static ImmutableMap> getBillingEntryQueries( + final Registrar registrar) { + return Maps.toMap(getCurrencies(), + new Function>() { + @Override + public Query apply(CurrencyUnit currency) { + return ofy().load() + .type(RegistrarBillingEntry.class) + .ancestor(registrar) + .filter("currency", currency) + .order("-created"); + }}); + } + + /** Returns amount of money registrar currently owes registry in each currency. */ + public static Map loadBalance(Registrar registrar) { + return Maps.transformEntries(getBillingEntryQueries(registrar), + new EntryTransformer, Money>() { + @Override + public Money transformEntry( + CurrencyUnit currency, Query query) { + RegistrarBillingEntry entry = query.first().now(); + return entry != null ? entry.getBalance() : Money.zero(currency); + }}); + } + + private RegistrarBillingUtils() {} +} diff --git a/java/com/google/domain/registry/model/billing/RegistrarCredit.java b/java/com/google/domain/registry/model/billing/RegistrarCredit.java new file mode 100644 index 000000000..ef4835f15 --- /dev/null +++ b/java/com/google/domain/registry/model/billing/RegistrarCredit.java @@ -0,0 +1,216 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.billing; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.assertTldExists; + +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registry.Registry; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; + +/** A per-registrar billing credit, applied toward future charges for registrar activity. */ +@Entity +public final class RegistrarCredit extends ImmutableObject implements Buildable { + + /** + * The type of credit represented. The ordering below determines the order in which credits of + * of different types will be applied to an invoice charge. + */ + // Note: Right now the ordering is actually maintained manually via a hard-coded table in the + // relevant billing query, so if adding a credit type here, add it there as well. + // TODO(b/19031546): make the query automatically reflect the order in this enum. + public enum CreditType { + /** Credit awarded as an incentive to participate in sunrise/landrush auctions. */ + AUCTION("Auction Credit"), + + /** Credit awarded as part of a promotional deal. */ + PROMOTION("Promotional Credit"); + + /** A descriptive name for a credit of this type. */ + private String descriptiveName; + + CreditType(String descriptiveName) { + this.descriptiveName = descriptiveName; + } + + public String getDescriptiveName() { + return descriptiveName; + } + } + + @Id + long id; + + /** The registrar to whom this credit belongs. */ + @Parent + Ref parent; + + /** The type of credit. */ + CreditType type; + + /** + * The time that this credit was created. If a registrar has multiple credits of a given type, + * the older credits will be applied first. + */ + DateTime creationTime; + + /** The currency in which the balance for this credit is stored. */ + CurrencyUnit currency; + + /** The line item description to use when displaying this credit on an invoice. */ + String description; + + /** + * The TLD in which this credit applies. + * + *

For auction credits, this is also the TLD for which the relevant auctions occurred. + */ + String tld; + + public Ref getParent() { + return parent; + } + + public CreditType getType() { + return type; + } + + public DateTime getCreationTime() { + return creationTime; + } + + public CurrencyUnit getCurrency() { + return currency; + } + + public String getDescription() { + return description; + } + + public String getTld() { + return tld; + } + + /** Returns a string representation of this credit. */ + public String getSummary() { + String fields = Joiner.on(' ').join(type, creationTime, tld); + return String.format("%s (%s/%d) - %s", description, parent.getKey().getName(), id, fields); + } + + /** Returns the default description for this {@link RegistrarCredit} instance. */ + private String getDefaultDescription() { + return type.getDescriptiveName() + " for ." + tld; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A Builder for {@link RegistrarCredit}. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + public Builder(RegistrarCredit instance) { + super(instance); + } + + public Builder setParent(Registrar parent) { + getInstance().parent = Ref.create(parent); + return this; + } + + public Builder setType(CreditType type) { + getInstance().type = type; + return this; + } + + public Builder setCreationTime(DateTime creationTime) { + getInstance().creationTime = creationTime; + return this; + } + + public Builder setCurrency(CurrencyUnit currency) { + getInstance().currency = currency; + return this; + } + + public Builder setDescription(String description) { + getInstance().description = description; + return this; + } + + public Builder setTld(String tld) { + getInstance().tld = tld; + return this; + } + + @Override + public RegistrarCredit build() { + RegistrarCredit instance = getInstance(); + checkNotNull(instance.parent, "parent credit"); + checkNotNull(instance.type, "type"); + checkNotNull(instance.creationTime, "creationTime"); + checkNotNull(instance.currency, "currency"); + assertTldExists(checkNotNull(instance.tld, "tld")); + checkArgument( + Registry.get(instance.tld).getCurrency().equals(instance.currency), + "Credits must be in the currency of the assigned TLD"); + instance.description = + Optional.fromNullable(instance.description).or(instance.getDefaultDescription()); + return super.build(); + } + } + + /** Ordering that sorts credits first by type and then by creation time. */ + private static final Ordering CREDIT_PRIORITY_ORDERING = + new Ordering() { + @Override + public int compare(RegistrarCredit left, RegistrarCredit right) { + return ComparisonChain.start() + .compare(left.type, right.type) + .compare(left.creationTime, right.creationTime) + .result(); + } + }; + + /** + * Loads all RegistrarCredit entities for the given Registrar. + * + *

The resulting list sorts the credits first by type and then by creation time. + */ + public static ImmutableList loadAllForRegistrar(Registrar registrar) { + return FluentIterable.from(ofy().load().type(RegistrarCredit.class).ancestor(registrar)) + .toSortedList(CREDIT_PRIORITY_ORDERING); + } +} diff --git a/java/com/google/domain/registry/model/billing/RegistrarCreditBalance.java b/java/com/google/domain/registry/model/billing/RegistrarCreditBalance.java new file mode 100644 index 000000000..7c219bb4c --- /dev/null +++ b/java/com/google/domain/registry/model/billing/RegistrarCreditBalance.java @@ -0,0 +1,253 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.billing; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.collect.ForwardingNavigableMap; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; +import com.googlecode.objectify.impl.ref.DeadRef; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.HashMap; +import java.util.Map; + +/** + * The balance of a {@link RegistrarCredit} at a given point in time. + * + *

A credit balance has two related times in addition to the monetary amount: the effective time, + * which represents the time at which the amount becomes the actual credit balance; and the + * written time, which represents the time at which this balance object was saved. + * + *

The active balance of a credit object before (at) any given point in time T can be found by + * taking the balance object with the latest effective time that is before (before or at) T, and + * breaking any ties by choosing the mostly recently written among those balances. + */ +@Entity +public final class RegistrarCreditBalance extends ImmutableObject implements Buildable { + + @Id + long id; + + /** The registrar credit object for which this represents a balance. */ + @Parent + Ref parent; + + /** The time at which this balance amount should become effective. */ + DateTime effectiveTime; + + /** + * The time at which this balance update was written. + * + *

Used to break ties in cases where there are multiple balances with the same effective time, + * as the last written balance will take priority. + */ + DateTime writtenTime; + + /** The monetary amount of credit balance remaining as of the effective time. */ + Money amount; + + public Ref getParent() { + return parent; + } + + public DateTime getEffectiveTime() { + return effectiveTime; + } + + public DateTime getWrittenTime() { + return writtenTime; + } + + public Money getAmount() { + return amount; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A Builder for an {@link RegistrarCreditBalance}. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + public Builder(RegistrarCreditBalance instance) { + super(instance); + } + + public RegistrarCreditBalance.Builder setParent(RegistrarCredit parent) { + // Use a DeadRef so that we can retrieve the actual instance provided later on in build(). + getInstance().parent = new DeadRef<>(Key.create(parent), parent); + return this; + } + + public RegistrarCreditBalance.Builder setEffectiveTime(DateTime effectiveTime) { + getInstance().effectiveTime = effectiveTime; + return this; + } + + public RegistrarCreditBalance.Builder setWrittenTime(DateTime writtenTime) { + getInstance().writtenTime = writtenTime; + return this; + } + + public RegistrarCreditBalance.Builder setAmount(Money amount) { + checkArgument(amount.isPositiveOrZero(), "Credit balance amount cannot be negative"); + getInstance().amount = amount; + return this; + } + + @Override + public RegistrarCreditBalance build() { + RegistrarCreditBalance instance = getInstance(); + checkNotNull(instance.parent); + checkNotNull(instance.effectiveTime); + checkNotNull(instance.writtenTime); + checkNotNull(instance.amount); + RegistrarCredit credit = instance.parent.get(); + checkState( + instance.amount.getCurrencyUnit().equals(credit.getCurrency()), + "Currency of balance amount differs from credit currency (%s vs %s)", + instance.amount.getCurrencyUnit(), + credit.getCurrency()); + return super.build(); + } + } + + /** + * A map of maps representing the historical credit balance information for a given credit. + * + *

Specifically, this class provides a high-level view of the balances for a given credit + * by in essence grouping them first by effective time and then by written time. This facilitates + * the printing of a readable representation of a credit's balance history, and the retrieval of + * the active balance at a given time (as described above on RegistrarCreditBalance). + */ + public static class BalanceMap + extends ForwardingNavigableMap> { + + /** + * Constructs a BalanceMap for the given registrar credit by loading all RegistrarCreditBalance + * entities for the credit and then inserting them into a map of maps keyed first by effective + * time and then by written time with the balance amount as the value. + */ + public static BalanceMap createForCredit(RegistrarCredit registrarCredit) { + // Build up the data in a mutable map of maps. + Map> map = new HashMap<>(); + for (RegistrarCreditBalance balance : + ofy().load().type(RegistrarCreditBalance.class).ancestor(registrarCredit)) { + // Create the submap at this key if it doesn't exist already. + Map submap = + Optional.fromNullable(map.get(balance.effectiveTime)) + .or(new HashMap()); + submap.put(balance.writtenTime, balance.amount); + map.put(balance.effectiveTime, submap); + } + // Wrap the mutable map of maps in an immutable BalanceMap. + return new BalanceMap(map); + } + + /** The immutable map of maps used as the backing map. */ + private final ImmutableSortedMap> delegate; + + /** + * Constructs an immutable BalanceMap from balance data provided as a map of maps. + * + *

The constructed BalanceMap delegates to an immutable copy of the provided map of maps. + * This copy is created by first making a view of the map in which each submap is replaced by + * an immutable copy, and then making an immutable copy of that view. + */ + @VisibleForTesting + BalanceMap(Map> data) { + delegate = ImmutableSortedMap.copyOf( + Maps.transformValues( + data, + new Function, ImmutableSortedMap>() { + @Override + public ImmutableSortedMap apply(Map map) { + return ImmutableSortedMap.copyOf(map, Ordering.natural()); + } + }), + Ordering.natural()); + } + + @Override + protected ImmutableSortedMap> delegate() { + return delegate; + } + + /** + * Returns the most recently written balance for the effective time corresponding to this entry, + * or {@link Optional#absent()} if this entry is null. + */ + private Optional getMostRecentlyWrittenBalance( + Map.Entry> balancesAtEffectiveTime) { + return balancesAtEffectiveTime == null + ? Optional.absent() + // Don't use Optional.fromNullable() here since it's an error if there's a empty submap. + : Optional.of(balancesAtEffectiveTime.getValue().lastEntry().getValue()); + } + + /** + * Returns the active balance at a given time as described above on RegistrarCreditBalance, or + * {@link Optional#absent()} if no balance was active at that time (i.e. the time provided is + * before the first effectiveTime of any balance for the credit this BalanceMap represents). + */ + public Optional getActiveBalanceAtTime(DateTime time) { + return getMostRecentlyWrittenBalance(delegate.floorEntry(time)); + } + + /** + * Returns the active balance before a given time as described above on RegistrarCreditBalance, + * or {@link Optional#absent()} if no balance was active before that time (i.e. the time + * provided is before or at the first effectiveTime of any balance for the credit). + */ + public Optional getActiveBalanceBeforeTime(DateTime time) { + return getMostRecentlyWrittenBalance(delegate.lowerEntry(time)); + } + + /** Returns a string representation of this BalanceMap's data. */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + for (Map.Entry> entry : delegate.entrySet()) { + builder.append(String.format(" - %s\n", entry.getKey())); + for (Map.Entry subEntry : entry.getValue().entrySet()) { + builder.append( + String.format(" - %s - %s\n", subEntry.getKey(), subEntry.getValue())); + } + } + return builder.toString(); + } + } +} diff --git a/java/com/google/domain/registry/model/common/CrossTldSingleton.java b/java/com/google/domain/registry/model/common/CrossTldSingleton.java new file mode 100644 index 000000000..a46595cde --- /dev/null +++ b/java/com/google/domain/registry/model/common/CrossTldSingleton.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; + +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +/** A singleton entity in the datastore. */ +public abstract class CrossTldSingleton extends ImmutableObject { + + public static final long SINGLETON_ID = 1; // There is always exactly one of these. + + @Id + long id = SINGLETON_ID; + + @Parent + Key parent = getCrossTldKey(); +} diff --git a/java/com/google/domain/registry/model/common/EntityGroupRoot.java b/java/com/google/domain/registry/model/common/EntityGroupRoot.java new file mode 100644 index 000000000..f98c29d49 --- /dev/null +++ b/java/com/google/domain/registry/model/common/EntityGroupRoot.java @@ -0,0 +1,47 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import com.google.domain.registry.model.BackupGroupRoot; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +/** + * The root key for the entity group which is known as the cross-tld entity group for historical + * reasons. + * + *

This exists as a storage place for common configuration options and global settings that + * aren't updated too frequently. Entities in this entity group are usually cached upon load. The + * reason this common entity group exists is because it enables strongly consistent queries and + * updates across this seldomly updated data. This shared entity group also helps cut down on + * a potential ballooning in the number of entity groups enlisted in transactions. + * + *

Historically, each TLD used to have a separate namespace, and all entities for a TLD were in + * a single EntityGroupRoot for that TLD. Hence why there was a "cross-tld" entity group -- it was + * the entity group for the single namespace where global data applicable for all TLDs lived. + */ +@Entity +public class EntityGroupRoot extends BackupGroupRoot { + + @Id + private String id; + + /** The root key for cross-tld resources such as registrars. */ + public static final Key getCrossTldKey() { + return Key.create(EntityGroupRoot.class, "cross-tld"); + } +} diff --git a/java/com/google/domain/registry/model/common/GaeUserIdConverter.java b/java/com/google/domain/registry/model/common/GaeUserIdConverter.java new file mode 100644 index 000000000..d74a1b233 --- /dev/null +++ b/java/com/google/domain/registry/model/common/GaeUserIdConverter.java @@ -0,0 +1,78 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import static com.google.domain.registry.model.ofy.ObjectifyService.allocateId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.appengine.api.users.User; +import com.google.common.base.Splitter; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; + +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +/** + * A helper class to convert email addresses to GAE user ids. It does so by persisting a User + * object with the email address to datastore, and then immediately reading it back. + */ +@Entity +@NotBackedUp(reason = Reason.TRANSIENT) +public class GaeUserIdConverter extends ImmutableObject { + + @Id + public long id; + + User user; + + /** + * Converts an email address to a GAE user id. + * + * @return Numeric GAE user id (in String form), or null if email address has no GAE id + */ + public static String convertEmailAddressToGaeUserId(String emailAddress) { + final GaeUserIdConverter gaeUserIdConverter = new GaeUserIdConverter(); + gaeUserIdConverter.id = allocateId(); + gaeUserIdConverter.user = + new User(emailAddress, Splitter.on('@').splitToList(emailAddress).get(1)); + + try { + // Perform these operations in a transactionless context to avoid enlisting in some outer + // transaction (if any). + ofy().doTransactionless(new VoidWork() { + @Override + public void vrun() { + ofy().saveWithoutBackup().entity(gaeUserIdConverter).now(); + }}); + + // The read must be done in its own transaction to avoid reading from the session cache. + return ofy().transactNew(new Work() { + @Override + public String run() { + return ofy().load().entity(gaeUserIdConverter).safe().user.getUserId(); + }}); + } finally { + ofy().doTransactionless(new VoidWork() { + @Override + public void vrun() { + ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now(); + }}); + } + } +} diff --git a/java/com/google/domain/registry/model/common/PersistedRangeLong.java b/java/com/google/domain/registry/model/common/PersistedRangeLong.java new file mode 100644 index 000000000..92a09eb02 --- /dev/null +++ b/java/com/google/domain/registry/model/common/PersistedRangeLong.java @@ -0,0 +1,56 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import com.google.common.collect.BoundType; +import com.google.common.collect.Range; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +/** An object that's equivalent to a {@code Range} that can be persisted to datastore. */ +@Embed +public class PersistedRangeLong extends ImmutableObject { + + private Long lowerBound = null; + private BoundType lowerBoundType = null; + + private Long upperBound = null; + private BoundType upperBoundType = null; + + public Range asRange() { + Range range = Range.all(); + if (lowerBound != null) { + range = range.intersection(Range.downTo(lowerBound, lowerBoundType)); + } + if (upperBound != null) { + range = range.intersection(Range.upTo(upperBound, upperBoundType)); + } + return range; + } + + public static PersistedRangeLong create(Range range) { + PersistedRangeLong instance = new PersistedRangeLong(); + if (range.hasLowerBound()) { + instance.lowerBound = range.lowerEndpoint(); + instance.lowerBoundType = range.lowerBoundType(); + } + if (range.hasUpperBound()) { + instance.upperBound = range.upperEndpoint(); + instance.upperBoundType = range.upperBoundType(); + } + return instance; + } +} diff --git a/java/com/google/domain/registry/model/common/TimeOfYear.java b/java/com/google/domain/registry/model/common/TimeOfYear.java new file mode 100644 index 000000000..e7f5ed978 --- /dev/null +++ b/java/com/google/domain/registry/model/common/TimeOfYear.java @@ -0,0 +1,93 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; + +import com.google.common.base.Splitter; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Index; + +import org.joda.time.DateTime; + +import java.util.List; + +/** + * A time of year (month, day, millis of day) that can be stored in a sort-friendly format. + *

+ * This is conceptually similar to {@code MonthDay} in Joda or more generally to Joda's + * {@code Partial}, but the parts we need are too simple to justify a full implementation of + * {@code Partial}. + *

+ * For simplicity, the native representation of this class's data is its stored format. This allows + * it to be embeddable with no translation needed and also delays parsing of the string on load + * until it's actually needed. + */ +@Embed +public class TimeOfYear extends ImmutableObject { + + /** + * The time as "month day millis" with all fields left-padded with zeroes so that lexographic + * sorting will do the right thing. + */ + @Index + String timeString; + + /** + * Constructs a {@link TimeOfYear} from a {@link DateTime}. + *

+ * This handles leap years in an intentionally peculiar way by always treating February 29 as + * February 28. It is impossible to construct a {@link TimeOfYear} for February 29th. + */ + public static TimeOfYear fromDateTime(DateTime dateTime) { + DateTime nextYear = dateTime.plusYears(1); // This turns February 29 into February 28. + TimeOfYear instance = new TimeOfYear(); + instance.timeString = String.format( + "%02d %02d %08d", + nextYear.getMonthOfYear(), + nextYear.getDayOfMonth(), + nextYear.getMillisOfDay()); + return instance; + } + + /** Get the first {@link DateTime} with this month/day/millis that is at or after the start. */ + public DateTime atOrAfter(DateTime start) { + DateTime withSameYear = getDateTimeWithSameYear(start); + return isAtOrAfter(withSameYear, start) ? withSameYear : withSameYear.plusYears(1); + } + + /** Get the first {@link DateTime} with this month/day/millis that is at or before the end. */ + public DateTime beforeOrAt(DateTime end) { + DateTime withSameYear = getDateTimeWithSameYear(end); + return isBeforeOrAt(withSameYear, end) ? withSameYear : withSameYear.minusYears(1); + } + + /** + * Return a new datetime with the same year as the parameter but projected to the month, day, and + * time of day of this object. + */ + private DateTime getDateTimeWithSameYear(DateTime date) { + List monthDayMillis = Splitter.on(' ').splitToList(timeString); + // Do not be clever and use Ints.stringConverter here. That does radix guessing, and bad things + // will happen because of the leading zeroes. + return date + .withMonthOfYear(Integer.parseInt(monthDayMillis.get(0))) + .withDayOfMonth(Integer.parseInt(monthDayMillis.get(1))) + .withMillisOfDay(Integer.parseInt(monthDayMillis.get(2))); + } +} diff --git a/java/com/google/domain/registry/model/common/TimedTransitionProperty.java b/java/com/google/domain/registry/model/common/TimedTransitionProperty.java new file mode 100644 index 000000000..3021acf38 --- /dev/null +++ b/java/com/google/domain/registry/model/common/TimedTransitionProperty.java @@ -0,0 +1,189 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.common; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.latestOf; + +import com.google.common.base.Function; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.util.TypeUtils; + +import com.googlecode.objectify.mapper.Mapper; + +import org.joda.time.DateTime; + +import java.util.NavigableMap; +import java.util.TreeMap; + +/** + * An entity property whose value transitions over time. Each value it takes on becomes active + * at a corresponding instant, and remains active until the next transition occurs. At least one + * "start of time" value (corresponding to START_OF_TIME, i.e. the Unix epoch) must be provided + * so that the property will have a value for all possible times. + *

+ * This concept is naturally represented by a sorted map of {@code DateTime} to {@code V}, but + * the AppEngine datastore cannot natively represent a map keyed on non-strings. Instead, we + * store an ordered list of transitions and use Objectify's @Mapify annotation to automatically + * recreate the sorted map on load from the datastore, which is used as a backing map for this + * property; the property itself also implements Map by way of extending ForwardingMap, so that + * this property can stored directly as the @Mapify field in the entity. + *

+ * The type parameter {@code T} specifies a user-defined subclass of {@code TimedTransition} to + * use for storing the list of transitions. The user is given this choice of subclass so that the + * field of the value type stored in the transition can be given a customized name. + */ +public class TimedTransitionProperty> + extends ForwardingMap { + + /** + * A transition to a value of type {@code V} at a certain time. This superclass only has a field + * for the {@code DateTime}, which means that subclasses should supply the field of type {@code V} + * and implementations of the abstract getter and setter methods to access that field. This design + * is so that subclasses tagged with @Embed can define a custom field name for their value, for + * the purpose of backwards compatibility and better readability of the datastore representation. + *

+ * The public visibility of this class exists only so that it can be subclassed; clients should + * never call any methods on this class or attempt to access its members, but should instead + * treat it as a customizable implementation detail of {@code TimedTransitionProperty}. However, + * note that subclasses must also have public visibility so that they can be instantiated via + * reflection in a call to {@code fromValueMap}. + */ + public abstract static class TimedTransition extends ImmutableObject { + /** The time at which this value becomes the active value. */ + private DateTime transitionTime; + + /** Returns the value that this transition will activate. */ + protected abstract V getValue(); + + /** Sets the value that will be activated at this transition's time. */ + protected abstract void setValue(V value); + } + + /** Mapper for use with @Mapify; extracts the time from a TimedTransition to use it as a key. */ + public static class TimeMapper implements Mapper> { + @Override + public DateTime getKey(TimedTransition transition) { + return transition.transitionTime; + } + } + + /** + * Converts the provided value map into the equivalent transition map, using transition objects + * of the given TimedTransition subclass. The value map must be sorted according to the natural + * ordering of its DateTime keys, and keys cannot be earlier than START_OF_TIME. + */ + // NB: The Class parameter could be eliminated by getting the class via reflection, but then + // the callsite cannot infer T, so unless you explicitly call this as .fromValueMap() it + // will default to using just TimedTransition, which fails at runtime. + private static > NavigableMap makeTransitionMap( + ImmutableSortedMap valueMap, + final Class timedTransitionSubclass) { + checkArgument( + Ordering.natural().equals(valueMap.comparator()), + "Timed transition value map must have transition time keys in chronological order"); + return Maps.transformEntries(valueMap, new Maps.EntryTransformer() { + // For each entry in the input value map, make the output map have an entry at the + // corresponding time that points to a transition containing that time and that value. + @Override + public T transformEntry(DateTime transitionTime, V value) { + checkArgument(!transitionTime.isBefore(START_OF_TIME), + "Timed transition times cannot be earlier than START_OF_TIME / Unix Epoch"); + T subclass = TypeUtils.instantiate(timedTransitionSubclass); + ((TimedTransition) subclass).transitionTime = transitionTime; + subclass.setValue(value); + return subclass; + }}); + } + + /** + * Returns a new immutable {@code TimedTransitionProperty} representing the given map of DateTime + * to value, with transitions constructed using the given {@code TimedTransition} subclass. + *

+ * This method should be the normal method for constructing a {@TimedTransitionProperty}. + */ + public static > TimedTransitionProperty fromValueMap( + ImmutableSortedMap valueMap, + final Class timedTransitionSubclass) { + return new TimedTransitionProperty<>(ImmutableSortedMap.copyOf( + makeTransitionMap(valueMap, timedTransitionSubclass))); + } + + /** + * Returns a new mutable {@code TimedTransitionProperty} representing the given map of DateTime + * to value, with transitions constructed using the given {@code TimedTransition} subclass. + *

+ * This method should only be used for initializing fields that are declared with the @Mapify + * annotation. The map for those fields must be mutable so that Objectify can load values from + * the datastore into the map, but clients should still never mutate the field's map directly. + */ + public static > TimedTransitionProperty forMapify( + ImmutableSortedMap valueMap, + Class timedTransitionSubclass) { + return new TimedTransitionProperty<>(new TreeMap<>( + makeTransitionMap(valueMap, timedTransitionSubclass))); + } + + /** The backing map of DateTime to TimedTransition subclass used to store the transitions. */ + private final NavigableMap backingMap; + + /** Returns a new {@code TimedTransitionProperty} backed by the provided map instance. */ + private TimedTransitionProperty(NavigableMap backingMap) { + checkArgument(backingMap.get(START_OF_TIME) != null, + "Must provide transition entry for the start of time (Unix Epoch)"); + this.backingMap = backingMap; + } + + /** + * Checks whether this TimedTransitionProperty is in a valid state, i.e. whether it has a + * transition entry for START_OF_TIME, and throws IllegalStateException if not. + */ + public void checkValidity() { + checkState(backingMap.get(START_OF_TIME) != null, + "Timed transition values missing required entry for the start of time (Unix Epoch)"); + } + + @Override + protected NavigableMap delegate() { + return backingMap; + } + + /** Returns the map of DateTime to value that is the "natural" representation of this property. */ + public ImmutableSortedMap toValueMap() { + return ImmutableSortedMap.copyOfSorted(Maps.transformValues( + backingMap, + new Function() { + @Override + public V apply(T timedTransition) { + return timedTransition.getValue(); + }})); + } + + /** + * Returns the value of the property that is active at the specified time. The active value for + * a time before START_OF_TIME is extrapolated to be the value that is active at START_OF_TIME. + */ + public V getValueAtTime(DateTime time) { + // Retrieve the current value by finding the latest transition before or at the given time, + // where any given time earlier than START_OF_TIME is replaced by START_OF_TIME. + return backingMap.floorEntry(latestOf(START_OF_TIME, time)).getValue().getValue(); + } +} diff --git a/java/com/google/domain/registry/model/contact/ContactAddress.java b/java/com/google/domain/registry/model/contact/ContactAddress.java new file mode 100644 index 000000000..6543b1818 --- /dev/null +++ b/java/com/google/domain/registry/model/contact/ContactAddress.java @@ -0,0 +1,37 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import com.google.domain.registry.model.eppcommon.Address; + +import com.googlecode.objectify.annotation.Embed; + +/** + * EPP Contact Address + *

+ * This class is embedded inside the {@link PostalInfo} of an EPP contact to hold its address. The + * fields are all defined in parent class {@link Address}, but the subclass is still necessary to + * pick up the contact namespace. + *

+ * This does not implement {@code Overlayable} because it is intended to be bulk replaced on update. + * + * @see PostalInfo + */ +@Embed +public class ContactAddress extends Address { + + /** Builder for {@link ContactAddress}. */ + public static class Builder extends Address.Builder {} +} diff --git a/java/com/google/domain/registry/model/contact/ContactAuthInfo.java b/java/com/google/domain/registry/model/contact/ContactAuthInfo.java new file mode 100644 index 000000000..436426125 --- /dev/null +++ b/java/com/google/domain/registry/model/contact/ContactAuthInfo.java @@ -0,0 +1,51 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppcommon.AuthInfo; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlType; + +/** A version of authInfo specifically for contacts. */ +@Embed +@XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0") +public class ContactAuthInfo extends AuthInfo { + + public static ContactAuthInfo create(PasswordAuth pw) { + ContactAuthInfo instance = new ContactAuthInfo(); + instance.pw = pw; + return instance; + } + + @Override + public void verifyAuthorizedFor(EppResource eppResource) throws BadAuthInfoException { + ContactResource contact = (ContactResource) eppResource; + PasswordAuth passwordAuth = checkNotNull(getPw()); + + // It's rather strange to specify a repoId on a contact auth info. Instead of explicitly + // rejecting it, we'll just make sure the repoId matches this particular contact. + if (passwordAuth.getRepoId() != null && !contact.getRepoId().equals(getRepoId())) { + throw new BadAuthInfoException(); + } + if (!contact.getAuthInfo().getPw().getValue().equals(passwordAuth.getValue())) { + throw new BadAuthInfoException(); + } + } +} diff --git a/java/com/google/domain/registry/model/contact/ContactCommand.java b/java/com/google/domain/registry/model/contact/ContactCommand.java new file mode 100644 index 000000000..7080574cd --- /dev/null +++ b/java/com/google/domain/registry/model/contact/ContactCommand.java @@ -0,0 +1,239 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource.Builder; +import com.google.domain.registry.model.contact.PostalInfo.Type; +import com.google.domain.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; + +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** A collection of {@link ContactResource} commands. */ +public class ContactCommand { + + /** The fields on "chgType" from {@link "http://tools.ietf.org/html/rfc5733"}. */ + @XmlTransient + public static class ContactCreateOrChange extends ImmutableObject + implements ResourceCreateOrChange { + + /** Postal info for the contact. */ + List postalInfo; + + /** Contact’s voice number. */ + ContactPhoneNumber voice; + + /** Contact’s fax number. */ + ContactPhoneNumber fax; + + /** Contact’s email address. */ + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String email; + + /** Authorization info (aka transfer secret) of the contact. */ + ContactAuthInfo authInfo; + + /** Disclosure policy. */ + Disclose disclose; + + /** Helper method to move between the postal infos list and the individual getters. */ + protected Map getPostalInfosAsMap() { + // There can be no more than 2 postalInfos (enforced by the schema), and if there are 2 they + // must be of different types (not enforced). If the type is repeated, uniqueIndex will throw. + checkState(nullToEmpty(postalInfo).size() <= 2); + return Maps.uniqueIndex(nullToEmpty(postalInfo), new Function() { + @Override + public Type apply(PostalInfo info) { + return info.getType(); + }}); + } + + @Override + public void applyTo(Builder builder) { + if (authInfo != null) { + builder.setAuthInfo(authInfo); + } + if (disclose != null) { + builder.setDisclose(disclose); + } + if (email != null) { + builder.setEmailAddress(email); + } + if (fax != null) { + builder.setFaxNumber(fax); + } + if (voice != null) { + builder.setVoiceNumber(voice); + } + } + } + + /** An abstract contact command that contains authorization info. */ + @XmlTransient + public static class AbstractContactAuthCommand extends AbstractSingleResourceCommand { + /** Authorization info used to validate if client has permissions to perform this operation. */ + ContactAuthInfo authInfo; + + @Override + public ContactAuthInfo getAuthInfo() { + return authInfo; + } + } + + /** + * A create command for a {@link ContactResource}, mapping "createType" from + * {@link "http://tools.ietf.org/html/rfc5733"}. + */ + @XmlType(propOrder = {"contactId", "postalInfo", "voice", "fax", "email", "authInfo", "disclose"}) + @XmlRootElement + public static class Create extends ContactCreateOrChange + implements SingleResourceCommand, ResourceCreateOrChange { + /** + * Unique identifier for this contact. + *

+ * This is only unique in the sense that for any given lifetime specified as the time range from + * (creationTime, deletionTime) there can only be one contact in the datastore with this id. + * However, there can be many contacts with the same id and non-overlapping lifetimes. + */ + @XmlElement(name = "id") + String contactId; + + @Override + public String getTargetId() { + return contactId; + } + + @Override + public ContactAuthInfo getAuthInfo() { + return authInfo; + } + + @Override + public void applyTo(ContactResource.Builder builder) { + super.applyTo(builder); + if (contactId != null) { + builder.setContactId(contactId); + } + Map postalInfosAsMap = getPostalInfosAsMap(); + if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) { + builder.setInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED)); + } + if (postalInfosAsMap.containsKey(Type.LOCALIZED)) { + builder.setLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED)); + } + } + } + + /** A delete command for a {@link ContactResource}. */ + @XmlRootElement + public static class Delete extends AbstractSingleResourceCommand {} + + /** An info request for a {@link ContactResource}. */ + @XmlRootElement + @XmlType(propOrder = {"targetId", "authInfo"}) + public static class Info extends AbstractContactAuthCommand {} + + /** A check request for {@link ContactResource}. */ + @XmlRootElement + public static class Check extends ResourceCheck {} + + /** A transfer operation for a {@link ContactResource}. */ + @XmlRootElement + @XmlType(propOrder = {"targetId", "authInfo"}) + public static class Transfer extends AbstractContactAuthCommand {} + + /** An update to a {@link ContactResource}. */ + @XmlRootElement + @XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"}) + public static class Update + extends ResourceUpdate { + + @XmlElement(name = "chg") + protected Change innerChange; + + @XmlElement(name = "add") + protected AddRemove innerAdd; + + @XmlElement(name = "rem") + protected AddRemove innerRemove; + + @Override + protected Change getNullableInnerChange() { + return innerChange; + } + + @Override + protected AddRemove getNullableInnerAdd() { + return innerAdd; + } + + @Override + protected AddRemove getNullableInnerRemove() { + return innerRemove; + } + + /** The inner change type on a contact update command. */ + public static class AddRemove extends ResourceUpdate.AddRemove {} + + /** The inner change type on a contact update command. */ + @XmlType(propOrder = {"postalInfo", "voice", "fax", "email", "authInfo", "disclose"}) + public static class Change extends ContactCreateOrChange { + /** + * The spec requires the following behaviors: + *

    + *
  • If you update part of a postal info, the fields that you didn't update are unchanged. + *
  • If you update one postal info but not the other, the other is deleted. + *
+ * Therefore, if you want to preserve one postal info and update another you need to send the + * update and also something that technically updates the preserved one, even if it only + * "updates" it by setting just one field to the same value. + */ + @Override + public void applyTo(ContactResource.Builder builder) { + super.applyTo(builder); + Map postalInfosAsMap = getPostalInfosAsMap(); + if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) { + builder.overlayInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED)); + if (postalInfosAsMap.size() == 1) { + builder.setLocalizedPostalInfo(null); + } + } + if (postalInfosAsMap.containsKey(Type.LOCALIZED)) { + builder.overlayLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED)); + if (postalInfosAsMap.size() == 1) { + builder.setInternationalizedPostalInfo(null); + } + } + } + } + } +} diff --git a/java/com/google/domain/registry/model/contact/ContactPhoneNumber.java b/java/com/google/domain/registry/model/contact/ContactPhoneNumber.java new file mode 100644 index 000000000..61f852dda --- /dev/null +++ b/java/com/google/domain/registry/model/contact/ContactPhoneNumber.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import com.google.domain.registry.model.eppcommon.PhoneNumber; + +import com.googlecode.objectify.annotation.Embed; + +/** + * EPP Contact Phone Number + *

+ * This class is embedded inside a {@link ContactResource} hold the phone number of an EPP contact. + * The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is still + * necessary to pick up the contact namespace. + * + * @see ContactResource + */ +@Embed +public class ContactPhoneNumber extends PhoneNumber { + + /** Builder for {@link ContactPhoneNumber}. */ + public static class Builder extends PhoneNumber.Builder {} +} diff --git a/java/com/google/domain/registry/model/contact/ContactResource.java b/java/com/google/domain/registry/model/contact/ContactResource.java new file mode 100644 index 000000000..36337d09d --- /dev/null +++ b/java/com/google/domain/registry/model/contact/ContactResource.java @@ -0,0 +1,259 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.domain.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime; + +import com.google.common.base.Predicates; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Lists; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.contact.PostalInfo.Type; +import com.google.domain.registry.model.eppcommon.AuthInfo; + +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** A persistable Contact resource including mutable and non-mutable fields. */ +@XmlRootElement(name = "infData") +@XmlType(propOrder = { + "contactId", + "repoId", + "status", + "postalInfosAsList", + "voice", + "fax", + "email", + "currentSponsorClientId", + "creationClientId", + "creationTime", + "lastEppUpdateClientId", + "lastEppUpdateTime", + "lastTransferTime", + "authInfo", + "disclose" }) +@Cache +@Entity +@ExternalMessagingName("contact") +public class ContactResource extends EppResource implements ForeignKeyedEppResource { + + /** + * Unique identifier for this contact. + *

+ * This is only unique in the sense that for any given lifetime specified as the time range from + * (creationTime, deletionTime) there can only be one contact in the datastore with this id. + * However, there can be many contacts with the same id and non-overlapping lifetimes. + */ + @XmlTransient + String contactId; + + /** + * Localized postal info for the contact. All contained values must be representable in the 7-bit + * US-ASCII character set. Personal info; cleared by wipeOut(). + */ + @IgnoreSave(IfNull.class) + @XmlTransient + PostalInfo localizedPostalInfo; + + /** Internationalized postal info for the contact. Personal info; cleared by wipeOut(). */ + @IgnoreSave(IfNull.class) + @XmlTransient + PostalInfo internationalizedPostalInfo; + + /** Contact’s voice number. Personal info; cleared by wipeOut(). */ + @IgnoreSave(IfNull.class) + ContactPhoneNumber voice; + + /** Contact’s fax number. Personal info; cleared by wipeOut(). */ + @IgnoreSave(IfNull.class) + ContactPhoneNumber fax; + + /** Contact’s email address. Personal info; cleared by wipeOut(). */ + @IgnoreSave(IfNull.class) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String email; + + /** Authorization info (aka transfer secret) of the contact. */ + ContactAuthInfo authInfo; + + // If any new fields are added which contain personal information, make sure they are cleared by + // the wipeOut() function, so that data is not kept around for deleted contacts. + + /** Disclosure policy. */ + @IgnoreSave(IfNull.class) + Disclose disclose; + + @XmlElement(name = "id") + public String getContactId() { + return contactId; + } + + public PostalInfo getLocalizedPostalInfo() { + return localizedPostalInfo; + } + + public PostalInfo getInternationalizedPostalInfo() { + return internationalizedPostalInfo; + } + + public ContactPhoneNumber getVoiceNumber() { + return voice; + } + + public ContactPhoneNumber getFaxNumber() { + return fax; + } + + public String getEmailAddress() { + return email; + } + + public AuthInfo getAuthInfo() { + return authInfo; + } + + public Disclose getDisclose() { + return disclose; + } + + @Override + public String getForeignKey() { + return contactId; + } + + /** + * Postal info for the contact. + *

+ * The XML marshalling expects the {@link PostalInfo} objects in a list, but we can't actually + * persist them to datastore that way because Objectify can't handle collections of embedded + * objects that themselves contain collections, and there's a list of streets inside. This method + * transforms the persisted format to the XML format for marshalling. + */ + @XmlElement(name = "postalInfo") + public List getPostalInfosAsList() { + return FluentIterable + .from(Lists.newArrayList(localizedPostalInfo, internationalizedPostalInfo)) + .filter(Predicates.notNull()) + .toList(); + } + + @Override + public ContactResource cloneProjectedAtTime(DateTime now) { + Builder builder = this.asBuilder(); + projectResourceOntoBuilderAtTime(this, builder, now); + return builder.build(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link ContactResource}, since it is immutable. */ + public static class Builder extends EppResource.Builder { + public Builder() {} + + private Builder(ContactResource instance) { + super(instance); + } + + public Builder setContactId(String contactId) { + getInstance().contactId = contactId; + return this; + } + + public Builder setLocalizedPostalInfo(PostalInfo localizedPostalInfo) { + checkArgument(localizedPostalInfo == null + || Type.LOCALIZED.equals(localizedPostalInfo.getType())); + getInstance().localizedPostalInfo = localizedPostalInfo; + return this; + } + + public Builder setInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) { + checkArgument(internationalizedPostalInfo == null + || Type.INTERNATIONALIZED.equals(internationalizedPostalInfo.getType())); + getInstance().internationalizedPostalInfo = internationalizedPostalInfo; + return this; + } + + public Builder overlayLocalizedPostalInfo(PostalInfo localizedPostalInfo) { + return setLocalizedPostalInfo(getInstance().localizedPostalInfo == null + ? localizedPostalInfo + : getInstance().localizedPostalInfo.overlay(localizedPostalInfo)); + } + + public Builder overlayInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) { + return setInternationalizedPostalInfo(getInstance().internationalizedPostalInfo == null + ? internationalizedPostalInfo + : getInstance().internationalizedPostalInfo.overlay(internationalizedPostalInfo)); + } + + public Builder setVoiceNumber(ContactPhoneNumber voiceNumber) { + getInstance().voice = voiceNumber; + return this; + } + + public Builder setFaxNumber(ContactPhoneNumber faxNumber) { + getInstance().fax = faxNumber; + return this; + } + + public Builder setEmailAddress(String emailAddress) { + getInstance().email = emailAddress; + return this; + } + + public Builder setAuthInfo(ContactAuthInfo authInfo) { + getInstance().authInfo = authInfo; + return this; + } + + public Builder setDisclose(Disclose disclose) { + getInstance().disclose = disclose; + return this; + } + + @Override + public Builder wipeOut() { + this.setEmailAddress(null); + this.setFaxNumber(null); + this.setInternationalizedPostalInfo(null); + this.setLocalizedPostalInfo(null); + this.setVoiceNumber(null); + return super.wipeOut(); + } + + @Override + public ContactResource build() { + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/contact/Disclose.java b/java/com/google/domain/registry/model/contact/Disclose.java new file mode 100644 index 000000000..80f8ffcbb --- /dev/null +++ b/java/com/google/domain/registry/model/contact/Disclose.java @@ -0,0 +1,136 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppcommon.PresenceMarker; + +import com.googlecode.objectify.annotation.Embed; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + +/** The "discloseType" from {@link "http://tools.ietf.org/html/rfc5733"}. */ +@Embed +@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"}) +public class Disclose extends ImmutableObject { + + List name; + + List org; + + List addr; + + PresenceMarker voice; + + PresenceMarker fax; + + PresenceMarker email; + + @XmlAttribute + Boolean flag; + + public ImmutableList getNames() { + return nullToEmptyImmutableCopy(name); + } + + public ImmutableList getOrgs() { + return nullToEmptyImmutableCopy(org); + } + + public ImmutableList getAddrs() { + return nullToEmptyImmutableCopy(addr); + } + + public PresenceMarker getVoice() { + return voice; + } + + public PresenceMarker getFax() { + return fax; + } + + public PresenceMarker getEmail() { + return email; + } + + public Boolean getFlag() { + return flag; + } + + /** The "intLocType" from {@link "http://tools.ietf.org/html/rfc5733"}. */ + @Embed + public static class PostalInfoChoice extends ImmutableObject { + @XmlAttribute + PostalInfo.Type type; + + public PostalInfo.Type getType() { + return type; + } + + @VisibleForTesting + public static PostalInfoChoice create(PostalInfo.Type type) { + PostalInfoChoice instance = new PostalInfoChoice(); + instance.type = type; + return instance; + } + } + + /** A builder for {@link Disclose} since it is immutable. */ + @VisibleForTesting + public static class Builder extends Buildable.Builder { + public Builder setNames(ImmutableList names) { + getInstance().name = names; + return this; + } + + public Builder setOrgs(ImmutableList orgs) { + getInstance().org = orgs; + return this; + } + + public Builder setAddrs(ImmutableList addrs) { + getInstance().addr = addrs; + return this; + } + + public Builder setVoice(PresenceMarker voice) { + getInstance().voice = voice; + return this; + } + + public Builder setFax(PresenceMarker fax) { + getInstance().fax = fax; + return this; + } + + public Builder setEmail(PresenceMarker email) { + getInstance().email = email; + return this; + } + + public Builder setFlag(boolean flag) { + getInstance().flag = flag; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/contact/PostalInfo.java b/java/com/google/domain/registry/model/contact/PostalInfo.java new file mode 100644 index 000000000..621902e26 --- /dev/null +++ b/java/com/google/domain/registry/model/contact/PostalInfo.java @@ -0,0 +1,122 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.contact; + +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.Buildable.Overlayable; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.NormalizedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Implementation of both "postalInfoType" and "chgPostalInfoType" from + * {@link "http://tools.ietf.org/html/rfc5733"}. + */ +@Embed +@XmlType(propOrder = {"name", "org", "address", "type"}) +public class PostalInfo extends ImmutableObject implements Overlayable { + + /** The type of the address, either localized or international. */ + public enum Type { + @XmlEnumValue("loc") + LOCALIZED, + @XmlEnumValue("int") + INTERNATIONALIZED + } + + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + String name; + + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + String org; + + @XmlElement(name = "addr") + ContactAddress address; + + @XmlAttribute + Type type; + + public String getName() { + return name; + } + + public String getOrg() { + return org; + } + + public ContactAddress getAddress() { + return address; + } + + public Type getType() { + return type; + } + + @Override + public PostalInfo overlay(PostalInfo source) { + // Don't overlay the type field, as that should never change. + checkState(source.type == null || source.type == type); + return asBuilder() + .setName(Optional.fromNullable(source.getName()).or(Optional.fromNullable(name)).orNull()) + .setOrg(Optional.fromNullable(source.getOrg()).or(Optional.fromNullable(org)).orNull()) + .setAddress( + Optional.fromNullable(source.getAddress()).or(Optional.fromNullable(address)).orNull()) + .build(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link PostalInfo}, since its changes get overlayed. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(PostalInfo instance) { + super(instance); + } + + public Builder setName(String name) { + getInstance().name = name; + return this; + } + + public Builder setOrg(String org) { + getInstance().org = org; + return this; + } + + public Builder setAddress(ContactAddress address) { + getInstance().address = address; + return this; + } + + public Builder setType(Type type) { + getInstance().type = type; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/contact/package-info.java b/java/com/google/domain/registry/model/contact/package-info.java new file mode 100644 index 000000000..cc5fa05f5 --- /dev/null +++ b/java/com/google/domain/registry/model/contact/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:contact-1.0", + xmlns = @XmlNs(prefix = "contact", namespaceURI = "urn:ietf:params:xml:ns:contact-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.contact; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/domain/DesignatedContact.java b/java/com/google/domain/registry/model/domain/DesignatedContact.java new file mode 100644 index 000000000..cf829edeb --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DesignatedContact.java @@ -0,0 +1,73 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource; + +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Index; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlValue; + +/** + * XML type for contact identifiers associated with a domain. + * + * @see "http://tools.ietf.org/html/rfc5731#section-2.2" + */ +@Embed +public class DesignatedContact extends ImmutableObject { + + /** + * XML type for contact types. This can be either: {@code "admin"}, {@code "billing"}, or + * {@code "tech"} and corresponds to {@code contactAttrType} in {@code domain-1.0.xsd}. + */ + public enum Type { + @XmlEnumValue("admin") + ADMIN, + @XmlEnumValue("billing") + BILLING, + @XmlEnumValue("tech") + TECH, + /** The registrant type is not reflected in XML and exists only for internal use. */ + REGISTRANT; + } + + @VisibleForTesting + public static DesignatedContact create(Type type, ReferenceUnion contact) { + DesignatedContact instance = new DesignatedContact(); + instance.type = type; + instance.contactId = contact; + return instance; + } + + @XmlAttribute(required = true) + Type type; + + @Index + @XmlValue + ReferenceUnion contactId; + + public Type getType() { + return type; + } + + public ReferenceUnion getContactId() { + return contactId; + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainApplication.java b/java/com/google/domain/registry/model/domain/DomainApplication.java new file mode 100644 index 000000000..a39704a44 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainApplication.java @@ -0,0 +1,172 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.domain.launch.ApplicationStatus; +import com.google.domain.registry.model.domain.launch.LaunchPhase; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.smd.EncodedSignedMark; + +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.EntitySubclass; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.List; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** An application to create a domain. */ +@XmlRootElement(name = "infData") +@XmlType(propOrder = { + "fullyQualifiedDomainName", + "repoId", + "status", + "registrant", + "contacts", + "nameservers", + "currentSponsorClientId", + "creationClientId", + "creationTime", + "lastEppUpdateClientId", + "lastEppUpdateTime", + "authInfo"}) +@Cache +@EntitySubclass(index = true) +@ExternalMessagingName("application") +public class DomainApplication extends DomainBase { + + /** + * The transaction id of the EPP command that created this application. This is saved off so that + * we can generate the poll message communicating the application result once it is rejected or + * allocated. + * + *

This field may be null for applications that were created before the field was added. + */ + @XmlTransient + Trid creationTrid; + + /** + * The phase which this application is registered for. We store this only so we can return it back + * to the user on info commands. + */ + @XmlTransient + LaunchPhase phase; + + /** The current status of this application. */ + @XmlTransient + ApplicationStatus applicationStatus; + + /** The encoded signed marks which were asserted when this application was created. */ + @XmlTransient + List encodedSignedMarks; + + /** The amount paid at auction for the right to register the domain. Used only for reporting. */ + @XmlTransient + Money auctionPrice; + + @Override + public String getFullyQualifiedDomainName() { + return fullyQualifiedDomainName; + } + + public Trid getCreationTrid() { + return creationTrid; + } + + public LaunchPhase getPhase() { + return phase; + } + + public ApplicationStatus getApplicationStatus() { + return applicationStatus; + } + + public ImmutableList getEncodedSignedMarks() { + return nullToEmptyImmutableCopy(encodedSignedMarks); + } + + public Money getAuctionPrice() { + return auctionPrice; + } + + /** Domain applications don't expose transfer time, so override this and mark it xml transient. */ + @XmlTransient + @Override + public final DateTime getLastTransferTime() { + return super.getLastTransferTime(); + } + + /** + * The application id is the repoId. + */ + @Override + public String getForeignKey() { + return getRepoId(); + } + + @Override + public DomainApplication cloneProjectedAtTime(DateTime now) { + // Applications have no grace periods and can't be transferred, so there is nothing to project. + return this; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link DomainApplication}, since it is immutable. */ + public static class Builder extends DomainBase.Builder { + + public Builder() {} + + private Builder(DomainApplication instance) { + super(instance); + } + + public Builder setCreationTrid(Trid creationTrid) { + getInstance().creationTrid = creationTrid; + return this; + } + + public Builder setPhase(LaunchPhase phase) { + getInstance().phase = phase; + return this; + } + + public Builder setApplicationStatus(ApplicationStatus applicationStatus) { + getInstance().applicationStatus = applicationStatus; + return this; + } + + public Builder setEncodedSignedMarks(ImmutableList encodedSignedMarks) { + getInstance().encodedSignedMarks = encodedSignedMarks; + return this; + } + + public Builder setAuctionPrice(Money auctionPrice) { + getInstance().auctionPrice = auctionPrice; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainAuthInfo.java b/java/com/google/domain/registry/model/domain/DomainAuthInfo.java new file mode 100644 index 000000000..197f4e70e --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainAuthInfo.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.eppcommon.AuthInfo; + +import com.googlecode.objectify.annotation.Embed; + +/** A version of authInfo specifically for domains. */ +@Embed +public class DomainAuthInfo extends AuthInfo { + + public static DomainAuthInfo create(PasswordAuth pw) { + DomainAuthInfo instance = new DomainAuthInfo(); + instance.pw = pw; + return instance; + } + + @Override + public void verifyAuthorizedFor(EppResource eppResource) throws BadAuthInfoException { + DomainBase domain = (DomainBase) eppResource; + checkNotNull(getPw()); + if (getRepoId() != null) { + // Make sure the repo id matches one of the contacts on the domain. + ReferenceUnion foundContact = null; + for (ReferenceUnion contact : domain.getReferencedContacts()) { + String contactRepoId = contact.getLinked().getKey().getName(); + if (getRepoId().equals(contactRepoId)) { + foundContact = contact; + break; + } + } + if (foundContact == null) { + throw new BadAuthInfoException(); + } + // Check if the password provided matches the password on the referenced contact. + if (!foundContact.getLinked().get().getAuthInfo().getPw().getValue().equals( + getPw().getValue())) { + throw new BadAuthInfoException(); + } + } else { + // If not repository ID is specified, then check the password against the domain's password. + if (!domain.getAuthInfo().getPw().getValue().equals(getPw().getValue())) { + throw new BadAuthInfoException(); + } + } + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainBase.java b/java/com/google/domain/registry/model/domain/DomainBase.java new file mode 100644 index 000000000..9f690a051 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainBase.java @@ -0,0 +1,293 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.union; +import static com.google.domain.registry.model.domain.DesignatedContact.Type.REGISTRANT; +import static com.google.domain.registry.model.domain.DomainUtils.getTldFromDomainName; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; +import static com.google.domain.registry.util.CollectionUtils.union; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResourceUtils; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.launch.LaunchNotice; +import com.google.domain.registry.model.domain.secdns.DelegationSignerData; +import com.google.domain.registry.model.eppcommon.AuthInfo; +import com.google.domain.registry.model.host.HostResource; + +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.OnLoad; +import com.googlecode.objectify.condition.IfNull; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlTransient; + +/** Shared base class for {@link DomainResource} and {@link DomainApplication}. */ +@XmlTransient +@Entity +public abstract class DomainBase extends EppResource { + + /** + * Fully qualified domain name, which serves as the foreign key for this domain. + *

+ * This is only unique in the sense that for any given lifetime specified as the time range from + * (creationTime, deletionTime) there can only be one domain in the datastore with this name. + * However, there can be many domains with the same name and non-overlapping lifetimes. + * + * @invariant fullyQualifiedDomainName == fullyQualifiedDomainName.toLowerCase() + */ + @Index + @XmlElement(name = "name") + String fullyQualifiedDomainName; + + /** The top level domain this is under, dernormalized from {@link #fullyQualifiedDomainName}. */ + @Index + @XmlTransient + String tld; + + /** References to hosts that are the nameservers for the domain. */ + @XmlElementWrapper(name = "ns") + @XmlElement(name = "hostObj") + Set> nameservers; + + /** + * Associated contacts for the domain (other than registrant). + *

+ * This field is marked with {@literal @}Ignore so that {@link DomainBase} subclasses won't + * persist it. Instead, the data in this field and in the {@link #registrant} are both stored in + * {@link DomainBase#allContacts} to allow for more efficient queries. + */ + @Ignore + @XmlElement(name = "contact") + Set contacts; + + /** + * The union of the contacts in {@link #contacts} and {@link #registrant}. This is so we can query + * across all contacts at once. It is maintained by the builder and by {@link #unpackageContacts}. + */ + @XmlTransient + Set allContacts; + + /** + * A reference to the registrant who registered this domain. + *

+ * This field is marked with {@literal @}Ignore so that {@link DomainBase} subclasses won't + * persist it. Instead, the data in this field and in the {@link DomainBase#contacts} are + * both stored in {@link DomainBase#allContacts} to allow for more efficient queries. + */ + @Ignore + ReferenceUnion registrant; + + /** Authorization info (aka transfer secret) of the domain. */ + DomainAuthInfo authInfo; + + /** + * Data used to construct DS records for this domain. + *

+ * This is {@literal @}XmlTransient because it needs to be returned under the "extension" tag + * of an info response rather than inside the "infData" tag. + */ + @XmlTransient + Set dsData; + + /** + * The claims notice supplied when this application or domain was created, if there was one. It's + * {@literal @}XmlTransient because it's not returned in an info response. + */ + @IgnoreSave(IfNull.class) + @XmlTransient + LaunchNotice launchNotice; + + /** + * Name of first IDN table associated with TLD that matched the characters in this domain label. + * + * @see com.google.domain.registry.tldconfig.idn.IdnLabelValidator#findValidIdnTableForTld + */ + @IgnoreSave(IfNull.class) + @XmlTransient + String idnTableName; + + public String getFullyQualifiedDomainName() { + return fullyQualifiedDomainName; + } + + public ImmutableSortedSet getDsData() { + return nullToEmptyImmutableSortedCopy(dsData); + } + + public LaunchNotice getLaunchNotice() { + return launchNotice; + } + + public String getIdnTableName() { + return idnTableName; + } + + public ImmutableSet> getNameservers() { + return nullToEmptyImmutableCopy(nameservers); + } + + /** Loads and returns all linked nameservers. */ + public ImmutableSet loadNameservers() { + return EppResourceUtils.loadReferencedNameservers(getNameservers()); + } + + public ReferenceUnion getRegistrant() { + return registrant; + } + + public ContactResource loadRegistrant() { + return registrant.getLinked().get(); + } + + public ImmutableSet getContacts() { + return nullToEmptyImmutableCopy(contacts); + } + + public AuthInfo getAuthInfo() { + return authInfo; + } + + /** Returns all referenced contacts from this domain or application. */ + public ImmutableSet> getReferencedContacts() { + ImmutableSet.Builder> contactsBuilder = + new ImmutableSet.Builder<>(); + for (DesignatedContact designated : nullToEmptyImmutableCopy(allContacts)) { + contactsBuilder.add(designated.getContactId()); + } + return contactsBuilder.build(); + } + + /** Loads and returns all referenced contacts from this domain or application. */ + public ImmutableSet loadReferencedContacts() { + return EppResourceUtils.loadReferencedContacts(getReferencedContacts()); + } + + public String getTld() { + return tld; + } + + /** + * On load, unpackage the {@link #allContacts} field, placing the registrant into + * {@link #registrant} field and all other contacts into {@link #contacts}. + */ + @OnLoad + void unpackageContacts() { + ImmutableSet.Builder contactsBuilder = new ImmutableSet.Builder<>(); + for (DesignatedContact contact : nullToEmptyImmutableCopy(allContacts)) { + if (REGISTRANT.equals(contact.getType())){ + registrant = contact.getContactId(); + } else { + contactsBuilder.add(contact); + } + } + contacts = contactsBuilder.build(); + } + + /** An override of {@link EppResource#asBuilder} with tighter typing. */ + @Override + public abstract Builder asBuilder(); + + /** A builder for constructing {@link DomainBase}, since it is immutable. */ + public abstract static class Builder> + extends EppResource.Builder { + protected Builder() {} + + protected Builder(T instance) { + super(instance); + } + + @Override + public T build() { + T instance = getInstance(); + checkState( + !isNullOrEmpty(instance.fullyQualifiedDomainName), "Missing fullyQualifiedDomainName"); + instance.tld = getTldFromDomainName(instance.fullyQualifiedDomainName); + instance.allContacts = instance.registrant == null ? instance.contacts : union( + instance.getContacts(), DesignatedContact.create(REGISTRANT, instance.registrant)); + return super.build(); + } + + public B setFullyQualifiedDomainName(String fullyQualifiedDomainName) { + getInstance().fullyQualifiedDomainName = fullyQualifiedDomainName; + return thisCastToDerived(); + } + + public B setDsData(ImmutableSet dsData) { + getInstance().dsData = dsData; + return thisCastToDerived(); + } + + public B setRegistrant(ReferenceUnion registrant) { + getInstance().registrant = registrant; + return thisCastToDerived(); + } + + public B setAuthInfo(DomainAuthInfo authInfo) { + getInstance().authInfo = authInfo; + return thisCastToDerived(); + } + + public B setNameservers(ImmutableSet> nameservers) { + getInstance().nameservers = nameservers; + return thisCastToDerived(); + } + + public B addNameservers(ImmutableSet> nameservers) { + return setNameservers( + ImmutableSet.copyOf(union(getInstance().getNameservers(), nameservers))); + } + + public B removeNameservers(ImmutableSet> nameservers) { + return setNameservers( + ImmutableSet.copyOf(difference(getInstance().getNameservers(), nameservers))); + } + + public B setContacts(ImmutableSet contacts) { + getInstance().contacts = contacts; + return thisCastToDerived(); + } + + public B addContacts(ImmutableSet contacts) { + return setContacts(ImmutableSet.copyOf(union(getInstance().getContacts(), contacts))); + } + + public B removeContacts(ImmutableSet contacts) { + return setContacts(ImmutableSet.copyOf(difference(getInstance().getContacts(), contacts))); + } + + public B setLaunchNotice(LaunchNotice launchNotice) { + getInstance().launchNotice = launchNotice; + return thisCastToDerived(); + } + + public B setIdnTableName(String idnTableName) { + getInstance().idnTableName = idnTableName; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainCommand.java b/java/com/google/domain/registry/model/domain/DomainCommand.java new file mode 100644 index 000000000..d3f47fbe4 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainCommand.java @@ -0,0 +1,462 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Sets.intersection; +import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.eppcommon.AuthInfo; +import com.google.domain.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.host.HostResource; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; +import org.joda.time.LocalDate; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** A collection of {@link DomainResource} commands. */ +public class DomainCommand { + + /** The default validity period (if not specified) is 1 year for all operations. */ + static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS); + + /** + * A common interface for {@link Create} and {@link Update} to support linking resources. + * + * @param the actual type (either {@link Create} or {@link Update}) + */ + public interface CreateOrUpdate> extends SingleResourceCommand { + /** Creates a copy of this command with hard links to hosts and contacts. */ + public T cloneAndLinkReferences(DateTime now) throws InvalidReferenceException; + } + + /** The fields on "chgType" from {@link "http://tools.ietf.org/html/rfc5731"}. */ + @XmlTransient + public static class DomainCreateOrChange> + extends ImmutableObject implements ResourceCreateOrChange { + + /** A reference to the registrant who registered this domain. */ + ReferenceUnion registrant; + + /** Authorization info (aka transfer secret) of the domain. */ + DomainAuthInfo authInfo; + + @Override + public void applyTo(B builder) { + if (registrant != null) { + builder.setRegistrant(registrant); + } + if (authInfo != null) { + builder.setAuthInfo(authInfo); + } + } + } + + /** + * A create command for a {@link DomainBase}, mapping "createType" from + * {@link "http://tools.ietf.org/html/rfc5731"}. + */ + @XmlRootElement + @XmlType(propOrder = { + "fullyQualifiedDomainName", "period", "nameservers", "registrant", "contacts", "authInfo" }) + public static class Create + extends DomainCreateOrChange> + implements CreateOrUpdate { + + /** Fully qualified domain name, which serves as a unique identifier for this domain. */ + @XmlElement(name = "name") + String fullyQualifiedDomainName; + + /** References to hosts that are the nameservers for the domain. */ + @XmlElementWrapper(name = "ns") + @XmlElement(name = "hostObj") + Set> nameservers; + + /** Associated contacts for the domain (other than registrant). */ + @XmlElement(name = "contact") + Set contacts; + + /** The period that this domain's state was set to last for (e.g. 1-10 years). */ + Period period; + + public Period getPeriod() { + return firstNonNull(period, DEFAULT_PERIOD); + } + + @Override + public String getTargetId() { + return fullyQualifiedDomainName; + } + + public String getFullyQualifiedDomainName() { + return fullyQualifiedDomainName; + } + + public ImmutableSet> getNameservers() { + return nullSafeImmutableCopy(nameservers); + } + + public ImmutableSet getContacts() { + return nullSafeImmutableCopy(contacts); + } + + public ReferenceUnion getRegistrant() { + return registrant; + } + + @Override + public AuthInfo getAuthInfo() { + return authInfo; + } + + @Override + public void applyTo(DomainBase.Builder builder) { + super.applyTo(builder); + if (fullyQualifiedDomainName != null) { + builder.setFullyQualifiedDomainName(fullyQualifiedDomainName); + } + if (nameservers != null) { + builder.setNameservers(getNameservers()); + } + if (contacts != null) { + builder.setContacts(getContacts()); + } + } + + /** Creates a copy of this {@link Create} with hard links to hosts and contacts. */ + @Override + public Create cloneAndLinkReferences(DateTime now) throws InvalidReferenceException { + Create clone = clone(this); + clone.nameservers = linkHosts(clone.nameservers, now); + clone.contacts = linkContacts(clone.contacts, now); + clone.registrant = clone.registrant == null + ? null : linkReference(clone.registrant, ContactResource.class, now); + return clone; + } + } + + /** A delete command for a {@link DomainBase}. */ + @XmlRootElement + public static class Delete extends AbstractSingleResourceCommand {} + + /** An info request for a {@link DomainBase}. */ + @XmlRootElement + public static class Info extends ImmutableObject implements SingleResourceCommand { + + /** The name of the domain to look up, and an attribute specifying the host lookup type. */ + @XmlElement(name = "name") + NameWithHosts fullyQualifiedDomainName; + + DomainAuthInfo authInfo; + + /** Enum of the possible values for the "hosts" attribute in info flows. */ + public enum HostsRequest { + @XmlEnumValue("all") + ALL, + + @XmlEnumValue("del") + DELEGATED, + + @XmlEnumValue("sub") + SUBORDINATE, + + @XmlEnumValue("none") + NONE; + + public boolean requestDelegated() { + return this == ALL || this == DELEGATED; + } + + public boolean requestSubordinate() { + return this == ALL || this == SUBORDINATE; + } + } + + /** Info commands use a variant syntax where the name tag has a "hosts" attribute. */ + public static class NameWithHosts extends ImmutableObject { + @XmlAttribute + HostsRequest hosts; + + @XmlValue + String name; + } + + /** Get the enum that specifies the requested hosts (applies only to info flows). */ + public HostsRequest getHostsRequest() { + // Null "hosts" is implicitly ALL. + return MoreObjects.firstNonNull(fullyQualifiedDomainName.hosts, HostsRequest.ALL); + } + + @Override + public String getTargetId() { + return fullyQualifiedDomainName.name; + } + + @Override + public DomainAuthInfo getAuthInfo() { + return authInfo; + } + } + + /** A check request for {@link DomainResource}. */ + @XmlRootElement + public static class Check extends ResourceCheck {} + + /** A renew command for a {@link DomainResource}. */ + @XmlRootElement + public static class Renew extends AbstractSingleResourceCommand { + @XmlElement(name = "curExpDate") + LocalDate currentExpirationDate; + + /** The period that this domain's state was set to last for. */ + Period period; + + public LocalDate getCurrentExpirationDate() { + return currentExpirationDate; + } + + public Period getPeriod() { + return firstNonNull(period, DEFAULT_PERIOD); + } + } + + /** A transfer operation for a {@link DomainResource}. */ + @XmlRootElement + public static class Transfer extends AbstractSingleResourceCommand { + /** The period to extend this domain's registration upon completion of the transfer. */ + Period period; + + /** Authorization info used to validate if client has permissions to perform this operation. */ + DomainAuthInfo authInfo; + + public Period getPeriod() { + return firstNonNull(period, DEFAULT_PERIOD); + } + + @Override + public DomainAuthInfo getAuthInfo() { + return authInfo; + } + } + + /** An update to a {@link DomainBase}. */ + @XmlRootElement + @XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"}) + public static class Update + extends ResourceUpdate, Update.Change> + implements CreateOrUpdate { + + @XmlElement(name = "chg") + protected Change innerChange; + + @XmlElement(name = "add") + protected AddRemove innerAdd; + + @XmlElement(name = "rem") + protected AddRemove innerRemove; + + @Override + protected Change getNullableInnerChange() { + return innerChange; + } + + @Override + protected AddRemove getNullableInnerAdd() { + return innerAdd; + } + + @Override + protected AddRemove getNullableInnerRemove() { + return innerRemove; + } + + public boolean noChangesPresent() { + AddRemove emptyAddRemove = new AddRemove(); + return emptyAddRemove.equals(getInnerAdd()) + && emptyAddRemove.equals(getInnerRemove()) + && new Change().equals(getInnerChange()); + } + + /** The inner change type on a domain update command. */ + @XmlType(propOrder = {"nameservers", "contacts", "statusValues"}) + public static class AddRemove extends ResourceUpdate.AddRemove { + /** References to hosts that are the nameservers for the domain. */ + @XmlElementWrapper(name = "ns") + @XmlElement(name = "hostObj") + Set> nameservers; + + /** Associated contacts for the domain. */ + @XmlElement(name = "contact") + Set contacts; + + public ImmutableSet> getNameservers() { + return nullToEmptyImmutableCopy(nameservers); + } + + public ImmutableSet getContacts() { + return nullToEmptyImmutableCopy(contacts); + } + + /** Creates a copy of this {@link AddRemove} with hard links to hosts and contacts. */ + private AddRemove cloneAndLinkReferences(DateTime now) throws InvalidReferenceException { + AddRemove clone = clone(this); + clone.nameservers = linkHosts(clone.nameservers, now); + clone.contacts = linkContacts(clone.contacts, now); + return clone; + } + } + + /** The inner change type on a domain update command. */ + @XmlType(propOrder = {"registrant", "authInfo"}) + public static class Change extends DomainCreateOrChange> { + + public ReferenceUnion getRegistrant() { + return registrant; + } + + /** Creates a copy of this {@link Change} with hard links to hosts and contacts. */ + Change cloneAndLinkReferences(DateTime now) throws InvalidReferenceException { + Change clone = clone(this); + clone.registrant = clone.registrant == null + ? null : linkReference(clone.registrant, ContactResource.class, now); + return clone; + } + } + + @Override + public void applyTo(DomainBase.Builder builder) throws AddRemoveSameValueException { + super.applyTo(builder); + getInnerChange().applyTo(builder); + AddRemove add = getInnerAdd(); + AddRemove remove = getInnerRemove(); + if (!intersection(add.getNameservers(), remove.getNameservers()).isEmpty()) { + throw new AddRemoveSameValueException(); + } + builder.addNameservers(add.getNameservers()); + builder.removeNameservers(remove.getNameservers()); + if (!intersection(add.getContacts(), remove.getContacts()).isEmpty()) { + throw new AddRemoveSameValueException(); + } + builder.addContacts(add.getContacts()); + builder.removeContacts(remove.getContacts()); + } + + /** + * Creates a copy of this {@link Update} with hard links to hosts and contacts. + *

+ * As a side effect, this will turn null innerAdd/innerRemove/innerChange into empty versions of + * those classes, which is harmless because the getters do that anyways. + */ + @Override + public Update cloneAndLinkReferences(DateTime now) throws InvalidReferenceException { + Update clone = clone(this); + clone.innerAdd = clone.getInnerAdd().cloneAndLinkReferences(now); + clone.innerRemove = clone.getInnerRemove().cloneAndLinkReferences(now); + clone.innerChange = clone.getInnerChange().cloneAndLinkReferences(now); + return clone; + } + } + + private static Set> linkHosts( + Set> hosts, + DateTime now) throws InvalidReferenceException { + if (hosts == null) { + return null; + } + ImmutableSet.Builder> linked = new ImmutableSet.Builder<>(); + for (ReferenceUnion host : hosts) { + linked.add(linkReference(host, HostResource.class, now)); + } + return linked.build(); + } + + private static Set linkContacts( + Set contacts, DateTime now) throws InvalidReferenceException { + if (contacts == null) { + return null; + } + ImmutableSet.Builder linkedContacts = new ImmutableSet.Builder<>(); + for (DesignatedContact contact : contacts) { + linkedContacts.add(DesignatedContact.create( + contact.getType(), + linkReference(contact.getContactId(), ContactResource.class, now))); + } + return linkedContacts.build(); + } + + /** Turn a foreign-keyed {@link ReferenceUnion} into a linked one. */ + private static ReferenceUnion linkReference( + final ReferenceUnion reference, final Class clazz, final DateTime now) + throws InvalidReferenceException { + if (reference.getForeignKey() == null) { + return reference; + } + Ref ref = ofy().doTransactionless(new Work>() { + @Override + public Ref run() { + return loadAndGetReference(clazz, reference.getForeignKey(), now); + } + }); + if (ref == null) { + throw new InvalidReferenceException(clazz, reference.getForeignKey()); + } + return ReferenceUnion.create(ref); + } + + /** Exception to throw when a referenced object does not exist. */ + public static class InvalidReferenceException extends Exception { + private String foreignKey; + private Class type; + + InvalidReferenceException(Class type, String foreignKey) { + this.type = checkNotNull(type); + this.foreignKey = foreignKey; + } + + public String getForeignKey() { + return foreignKey; + } + + public Class getType() { + return type; + } + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainRenewData.java b/java/com/google/domain/registry/model/domain/DomainRenewData.java new file mode 100644 index 000000000..ef9a34ea1 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainRenewData.java @@ -0,0 +1,41 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import com.google.domain.registry.model.eppoutput.Response.ResponseData; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** The {@link ResponseData} returned when renewing a domain. */ +@XmlRootElement(name = "renData") +@XmlType(propOrder = {"name", "expirationDate"}) +public class DomainRenewData implements ResponseData { + + String name; + + @XmlElement(name = "exDate") + DateTime expirationDate; + + public static DomainRenewData create(String name, DateTime expirationDate) { + DomainRenewData instance = new DomainRenewData(); + instance.name = name; + instance.expirationDate = expirationDate; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainResource.java b/java/com/google/domain/registry/model/domain/DomainResource.java new file mode 100644 index 000000000..d325b83f0 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainResource.java @@ -0,0 +1,413 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.common.collect.Sets.intersection; +import static com.google.domain.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime; +import static com.google.domain.registry.model.EppResourceUtils.setAutomaticTransferSuccessProperties; +import static com.google.domain.registry.util.CollectionUtils.difference; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.union; +import static com.google.domain.registry.util.DateTimeUtils.earliestOf; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; +import static com.google.domain.registry.util.DateTimeUtils.leapSafeAddYears; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.poll.PollMessage; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.EntitySubclass; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; +import org.joda.time.Interval; + +import java.util.HashSet; +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** A persistable domain resource including mutable and non-mutable fields. */ +@XmlRootElement(name = "infData") +@XmlType(propOrder = { + "fullyQualifiedDomainName", + "repoId", + "status", + "registrant", + "contacts", + "nameservers", + "subordinateHosts", + "currentSponsorClientId", + "creationClientId", + "creationTime", + "lastEppUpdateClientId", + "lastEppUpdateTime", + "registrationExpirationTime", + "lastTransferTime", + "authInfo"}) +@Cache +@EntitySubclass(index = true) +@ExternalMessagingName("domain") +public class DomainResource extends DomainBase implements ForeignKeyedEppResource { + + /** The max number of years that a domain can be registered for, as set by ICANN policy. */ + public static final int MAX_REGISTRATION_YEARS = 10; + + /** Status values which prohibit DNS information from being published. */ + private static final ImmutableSet DNS_PUBLISHING_PROHIBITED_STATUSES = + ImmutableSet.of( + StatusValue.CLIENT_HOLD, + StatusValue.INACTIVE, + StatusValue.PENDING_DELETE, + StatusValue.SERVER_HOLD); + + /** Fully qualified host names of this domain's active subordinate hosts. */ + @XmlElement(name = "host") + Set subordinateHosts; + + /** When this domain's registration will expire. */ + @XmlElement(name = "exDate") + DateTime registrationExpirationTime; + + /** + * The poll message associated with this domain being deleted. + *

+ * This field should be null if the domain is not in pending delete. If it is, the field should + * refer to a {@link PollMessage} timed to when the domain is fully deleted. If the domain is + * restored, the message should be deleted. + */ + @XmlTransient + Key deletePollMessage; + + /** + * The recurring billing event associated with this domain's autorenewals. + *

+ * The recurrence should be open ended unless the domain is in pending delete or fully deleted, in + * which case it should be closed at the time the delete was requested. Whenever the domain's + * {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one + * should be created, and this field should be updated to point to the new one. + */ + @XmlTransient + Ref autorenewBillingEvent; + + /** + * The recurring poll message associated with this domain's autorenewals. + *

+ * The recurrence should be open ended unless the domain is in pending delete or fully deleted, in + * which case it should be closed at the time the delete was requested. Whenever the domain's + * {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one + * should be created, and this field should be updated to point to the new one. + */ + @XmlTransient + Ref autorenewPollMessage; + + /** The unexpired grace periods for this domain (some of which may not be active yet). */ + @XmlTransient + Set gracePeriods; + + /** + * The id of the signed mark that was used to create the sunrise application for this domain. + * Will only be populated for domains allocated from a sunrise application. + */ + @IgnoreSave(IfNull.class) + @XmlTransient + String smdId; + + /** + * The time that the application used to allocate this domain was created. Will only be populated + * for domains allocated from an application. + */ + @IgnoreSave(IfNull.class) + @XmlTransient + DateTime applicationTime; + + /** + * A reference to the application used to allocate this domain. Will only be populated for domains + * allocated from an application. + */ + @IgnoreSave(IfNull.class) + @XmlTransient + Ref application; + + public ImmutableSet getSubordinateHosts() { + return nullToEmptyImmutableCopy(subordinateHosts); + } + + public DateTime getRegistrationExpirationTime() { + return registrationExpirationTime; + } + + public Key getDeletePollMessage() { + return deletePollMessage; + } + + public Ref getAutorenewBillingEvent() { + return autorenewBillingEvent; + } + + public Ref getAutorenewPollMessage() { + return autorenewPollMessage; + } + + public ImmutableSet getGracePeriods() { + return nullToEmptyImmutableCopy(gracePeriods); + } + + public String getSmdId() { + return smdId; + } + + public DateTime getApplicationTime() { + return applicationTime; + } + + public Ref getApplication() { + return application; + } + + @Override + public String getForeignKey() { + return fullyQualifiedDomainName; + } + + /** Returns true if DNS information should be published for the given domain. */ + public boolean shouldPublishToDns() { + return intersection(getStatusValues(), DNS_PUBLISHING_PROHIBITED_STATUSES).isEmpty(); + } + + /** + * Returns the Registry Grace Period Statuses for this domain. + *

+ * This collects all statuses from the domain's {@link GracePeriod}s and also adds the + * PENDING_DELETE status if needed. + */ + public ImmutableSet getGracePeriodStatuses() { + Set gracePeriodStatuses = new HashSet<>(); + for (GracePeriod gracePeriod : getGracePeriods()) { + gracePeriodStatuses.add(gracePeriod.getType()); + } + if (getStatusValues().contains(StatusValue.PENDING_DELETE) + && !gracePeriodStatuses.contains(GracePeriodStatus.REDEMPTION)) { + gracePeriodStatuses.add(GracePeriodStatus.PENDING_DELETE); + } + return ImmutableSet.copyOf(gracePeriodStatuses); + } + + /** + * The logic in this method, which handles implicit server approval of transfers, very closely + * parallels the logic in {@code DomainTransferApproveFlow} which handles explicit client + * approvals. + */ + @Override + public DomainResource cloneProjectedAtTime(final DateTime now) { + + TransferData transferData = getTransferData(); + DateTime transferExpirationTime = transferData.getPendingTransferExpirationTime(); + + // If there's a pending transfer that has expired, handle it. + if (TransferStatus.PENDING.equals(transferData.getTransferStatus()) + && isBeforeOrAt(transferExpirationTime, now)) { + // Project until just before the transfer time. This will handle the case of an autorenew + // before the transfer was even requested or during the request period. + // If the transfer time is precisely the moment that the domain expires, there will not be an + // autorenew billing event (since we end the recurrence at transfer time and recurrences are + // exclusive of their ending), and we can just proceed with the transfer. + DomainResource domainAtTransferTime = + cloneProjectedAtTime(transferExpirationTime.minusMillis(1)); + // If we are within an autorenew grace period, the transfer will subsume the autorenew. There + // will already be a cancellation written in advance by the transfer request flow, so we don't + // need to worry about billing, but we do need to reduce the number of years added to the + // expiration time by one to account for the year added by the autorenew. + int extraYears = transferData.getExtendedRegistrationYears(); + if (domainAtTransferTime.getGracePeriodStatuses().contains(GracePeriodStatus.AUTO_RENEW)) { + extraYears--; + } + // Set the expiration, autorenew events, and grace period for the transfer. (Transfer ends + // all other graces). + Builder builder = domainAtTransferTime.asBuilder() + // Extend the registration by the correct number of years from the expiration time that + // was current on the domain right before the transfer, capped at 10 years from the + // moment of the transfer. + .setRegistrationExpirationTime(extendRegistrationWithCap( + transferExpirationTime, + domainAtTransferTime.getRegistrationExpirationTime(), + extraYears)) + // Set the speculatively-written new autorenew events as the domain's autorenew events. + .setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) + .setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage()) + // Set the grace period using a ref to the prescheduled transfer billing event. Not using + // GracePeriod.forBillingEvent() here in order to avoid the actual datastore fetch. + .setGracePeriods(ImmutableSet.of(GracePeriod.create( + GracePeriodStatus.TRANSFER, + transferExpirationTime.plus(Registry.get(getTld()).getTransferGracePeriodLength()), + transferData.getGainingClientId(), + Ref.create(transferData.getServerApproveBillingEvent().key())))); + // Set all remaining transfer properties. + setAutomaticTransferSuccessProperties(builder, transferData); + // Finish projecting to now. + return builder.build().cloneProjectedAtTime(now); + } + + // There is no transfer. Do any necessary autorenews. + + Builder builder = asBuilder(); + if (isBeforeOrAt(registrationExpirationTime, now)) { + // Autorenew by the number of years between the old expiration time and now. + DateTime lastAutorenewTime = leapSafeAddYears( + registrationExpirationTime, + new Interval(registrationExpirationTime, now).toPeriod().getYears()); + DateTime newExpirationTime = lastAutorenewTime.plusYears(1); + builder + .setRegistrationExpirationTime(newExpirationTime) + .addGracePeriod(GracePeriod.create( + GracePeriodStatus.AUTO_RENEW, + lastAutorenewTime.plus(Registry.get(getTld()).getAutoRenewGracePeriodLength()), + getCurrentSponsorClientId(), + Ref.create(autorenewBillingEvent.key()))); + } + + // Remove any grace periods that have expired. + DomainResource almostBuilt = builder.build(); + builder = almostBuilt.asBuilder(); + for (GracePeriod gracePeriod : almostBuilt.getGracePeriods()) { + if (isBeforeOrAt(gracePeriod.getExpirationTime(), now)) { + builder.removeGracePeriod(gracePeriod); + } + } + + // Handle common properties like setting or unsetting linked status. This also handles the + // general case of pending transfers for other resource types, but since we've always handled + // a pending transfer by this point that's a no-op for domains. + projectResourceOntoBuilderAtTime(almostBuilt, builder, now); + return builder.build(); + } + + /** Return what the expiration time would be if the given number of years were added to it. */ + public static DateTime extendRegistrationWithCap( + DateTime now, DateTime currentExpirationTime, Integer extendedRegistrationYears) { + // We must cap registration at the max years (aka 10), even if that truncates the last year. + return earliestOf( + leapSafeAddYears( + currentExpirationTime, Optional.fromNullable(extendedRegistrationYears).or(0)), + leapSafeAddYears(now, MAX_REGISTRATION_YEARS)); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link DomainResource}, since it is immutable. */ + public static class Builder extends DomainBase.Builder { + + public Builder() {} + + private Builder(DomainResource instance) { + super(instance); + } + + @Override + public DomainResource build() { + // A DomainResource has status INACTIVE if there are no nameservers. + if (getInstance().getNameservers().isEmpty()) { + addStatusValue(StatusValue.INACTIVE); + } else { // There are nameservers, so make sure INACTIVE isn't there. + removeStatusValue(StatusValue.INACTIVE); + } + // This must be called after we add or remove INACTIVE, since that affects whether we get OK. + return super.build(); + } + + public Builder setSubordinateHosts(ImmutableSet subordinateHosts) { + getInstance().subordinateHosts = subordinateHosts; + return thisCastToDerived(); + } + + public Builder addSubordinateHost(String hostToAdd) { + return setSubordinateHosts(ImmutableSet.copyOf( + union(getInstance().getSubordinateHosts(), hostToAdd))); + } + + public Builder removeSubordinateHost(String hostToRemove) { + return setSubordinateHosts(ImmutableSet.copyOf( + difference(getInstance().getSubordinateHosts(), hostToRemove))); + } + + public Builder setRegistrationExpirationTime(DateTime registrationExpirationTime) { + getInstance().registrationExpirationTime = registrationExpirationTime; + return this; + } + + public Builder setDeletePollMessage(Key deletePollMessage) { + getInstance().deletePollMessage = deletePollMessage; + return this; + } + + public Builder setAutorenewBillingEvent(Ref autorenewBillingEvent) { + getInstance().autorenewBillingEvent = autorenewBillingEvent; + return this; + } + + public Builder setAutorenewPollMessage(Ref autorenewPollMessage) { + getInstance().autorenewPollMessage = autorenewPollMessage; + return this; + } + + public Builder setSmdId(String smdId) { + getInstance().smdId = smdId; + return this; + } + + public Builder setApplicationTime(DateTime applicationTime) { + getInstance().applicationTime = applicationTime; + return this; + } + + public Builder setApplication(Ref application) { + getInstance().application = application; + return this; + } + + public Builder setGracePeriods(ImmutableSet gracePeriods) { + getInstance().gracePeriods = gracePeriods; + return this; + } + + public Builder addGracePeriod(GracePeriod gracePeriod) { + getInstance().gracePeriods = union(getInstance().getGracePeriods(), gracePeriod); + return this; + } + + public Builder removeGracePeriod(GracePeriod gracePeriod) { + getInstance().gracePeriods = difference(getInstance().getGracePeriods(), gracePeriod); + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/domain/DomainUtils.java b/java/com/google/domain/registry/model/domain/DomainUtils.java new file mode 100644 index 000000000..ca135306b --- /dev/null +++ b/java/com/google/domain/registry/model/domain/DomainUtils.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Strings; +import com.google.common.net.InternetDomainName; + +/** + * Contains static utility methods for dealing with domains. + */ +public class DomainUtils { + + /** + * Returns the canonicalized TLD part of a valid domain name (just an SLD, no subdomains) by + * stripping off the leftmost part. + * + *

This function is compatible with multi-part tlds. + * + * @throws IllegalArgumentException if there is no TLD + */ + public static String getTldFromDomainName(String fullyQualifiedDomainName) { + checkArgument( + !Strings.isNullOrEmpty(fullyQualifiedDomainName), + "fullyQualifiedDomainName cannot be null or empty"); + InternetDomainName domainName = InternetDomainName.from(fullyQualifiedDomainName); + checkArgument(domainName.hasParent(), "fullyQualifiedDomainName does not have a TLD"); + return domainName.parent().toString(); + } +} diff --git a/java/com/google/domain/registry/model/domain/GracePeriod.java b/java/com/google/domain/registry/model/domain/GracePeriod.java new file mode 100644 index 000000000..4b9089bad --- /dev/null +++ b/java/com/google/domain/registry/model/domain/GracePeriod.java @@ -0,0 +1,137 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Embed; + +import org.joda.time.DateTime; + +import javax.annotation.Nullable; + +/** + * A domain grace period with an expiration time. + *

+ * When a grace period expires, it is lazily removed from the {@link DomainResource} the next time + * the resource is loaded from the datastore. + */ +@Embed +public class GracePeriod extends ImmutableObject { + + /** The type of grace period. */ + GracePeriodStatus type; + + /** When the grace period ends. */ + DateTime expirationTime; + + /** The registrar to bill. */ + String clientId; + + /** + * The one-time billing event corresponding to the action that triggered this grace period, or + * null if not applicable. Not set for autorenew grace periods (which instead use the field + * {@code billingEventRecurring}) or for redemption grace periods (since deletes have no cost). + */ + // NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections. + Ref billingEventOneTime = null; + + /** + * The recurring billing event corresponding to the action that triggered this grace period, if + * applicable - i.e. if the action was an autorenew - or null in all other cases. + */ + // NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections. + Ref billingEventRecurring = null; + + public GracePeriodStatus getType() { + // NB: We implicitly convert SUNRUSH_ADD to ADD, since they should be functionally equivalent. + return type == GracePeriodStatus.SUNRUSH_ADD ? GracePeriodStatus.ADD : type; + } + + public boolean isSunrushAddGracePeriod() { + return type == GracePeriodStatus.SUNRUSH_ADD; + } + + public DateTime getExpirationTime() { + return expirationTime; + } + + public String getClientId() { + return clientId; + } + + /** + * Returns the ref to the billing event associated with this grace period, or null if there is + * no applicable billing event (i.e. this is a redemption grace period). + */ + @Nullable + public Ref getBillingEvent() { + return Optional.>fromNullable(billingEventOneTime) + .or(Optional.>fromNullable(billingEventRecurring)) + .orNull(); + } + + /** + * Returns the one time billing event. The value will only be non-null if the type of this grace + * period is not AUTO_RENEW. + */ + + public Ref getOneTimeBillingEvent() { + return billingEventOneTime; + } + + /** + * Returns the recurring billing event. The value will only be non-null if the type of this grace + * period is AUTO_RENEW. + */ + public Ref getRecurringBillingEvent() { + return billingEventRecurring; + } + + /** + * Constructs a GracePeriod with some interpretation of the parameters. In particular, selects + * the field to store the billing event ref in based on the specified grace period status type. + */ + @SuppressWarnings("unchecked") + public static GracePeriod create( + GracePeriodStatus type, + DateTime expirationTime, + String clientId, + @Nullable Ref billingEvent) { + GracePeriod instance = new GracePeriod(); + instance.type = checkNotNull(type); + instance.expirationTime = checkNotNull(expirationTime); + instance.clientId = checkNotNull(clientId); + if (GracePeriodStatus.AUTO_RENEW.equals(instance.type)) { + instance.billingEventRecurring = (Ref) billingEvent; + } else { + instance.billingEventOneTime = (Ref) billingEvent; + } + return instance; + } + + /** Constructs a GracePeriod of the given type from the provided one-time BillingEvent. */ + public static GracePeriod forBillingEvent( + GracePeriodStatus type, BillingEvent.OneTime billingEvent) { + return create( + type, billingEvent.getBillingTime(), billingEvent.getClientId(), Ref.create(billingEvent)); + } +} diff --git a/java/com/google/domain/registry/model/domain/Period.java b/java/com/google/domain/registry/model/domain/Period.java new file mode 100644 index 000000000..32a5c25c9 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/Period.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + + +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlValue; + +/** The "periodType" from {@link "http://tools.ietf.org/html/rfc5731"}. */ +@Embed +public class Period extends ImmutableObject { + + @XmlAttribute + Unit unit; + + @XmlValue + Integer value; + + public Unit getUnit() { + return unit; + } + + public Integer getValue() { + return value; + } + + /** The unit enum. */ + public enum Unit { + @XmlEnumValue("y") + YEARS, + + @XmlEnumValue("m") + MONTHS, + } + + public static Period create(int value, Unit unit) { + Period instance = new Period(); + instance.value = value; + instance.unit = unit; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/ReferenceUnion.java b/java/com/google/domain/registry/model/domain/ReferenceUnion.java new file mode 100644 index 000000000..72095daf7 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/ReferenceUnion.java @@ -0,0 +1,104 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.host.HostResource; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.Index; + +import java.io.Serializable; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** + * A "union" type to represent referenced objects as either a foreign key or as a link to another + * object in the datastore. + *

+ * This type always marshals as the "foreign key". When it is explicitly storing a foreign key it + * gets the value from its own string field. When it is linked to another object, it gets the value + * from the other object. + *

+ * When a {@link ReferenceUnion} comes in from Epp, either in an update or a delete, it fills in the + * "foreign key" string field, but as soon as the relevant Flow runs it deletes that field and + * replaces it with a linked {@link Ref} to the object named by that string. We can't do this in a + * {@code XmlJavaTypeAdapter} because failing a lookup is a business logic error, not a failure to + * parse the XML. + * + * @param the type being referenced + */ +@Embed +public class ReferenceUnion extends ImmutableObject implements Serializable { + + @Index + Ref linked; + + /** This is never persisted, and only ever populated to marshal or unmarshal to or from XML. */ + @Ignore + String foreignKey; + + public Ref getLinked() { + return linked; + } + + public String getForeignKey() { + return foreignKey; + } + + /** An adapter that is aware of the union inside {@link ReferenceUnion}. */ + public static class Adapter + extends XmlAdapter> { + + @Override + public ReferenceUnion unmarshal(String foreignKey) throws Exception { + return ReferenceUnion.create(foreignKey); + } + + @Override + public String marshal(ReferenceUnion reference) throws Exception { + return reference.getForeignKey() == null + ? reference.getLinked().get().getForeignKey() + : reference.getForeignKey(); + } + } + + /** An adapter for references to contacts. */ + static class ContactReferenceUnionAdapter extends ReferenceUnion.Adapter{} + + /** An adapter for references to hosts. */ + static class HostReferenceUnionAdapter extends ReferenceUnion.Adapter{} + + public static ReferenceUnion create(String foreignKey) { + ReferenceUnion instance = new ReferenceUnion<>(); + instance.foreignKey = foreignKey; + return instance; + } + + public static ReferenceUnion create(Ref linked) { + ReferenceUnion instance = new ReferenceUnion<>(); + instance.linked = linked; + return instance; + } + + /** Convenience method. */ + public static ReferenceUnion create(T resource) { + return create(Ref.create(resource)); + } +} diff --git a/java/com/google/domain/registry/model/domain/allocate/AllocateCreateExtension.java b/java/com/google/domain/registry/model/domain/allocate/AllocateCreateExtension.java new file mode 100644 index 000000000..8ebddede5 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/allocate/AllocateCreateExtension.java @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.allocate; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.domain.launch.LaunchNotice; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents an allocate extension that will be present on EPP commands to + * allocate a domain from an application. + *

+ * This object holds XML data which JAXB will unmarshal from an EPP domain create command extension. + * The XML will have the following enclosing structure: + * + *

 {@code
+ *   
+ *     
+ *       
+ *         
+ *       
+ *       
+ *         
+ *           
+ *         
+ *       
+ *     
+ *   
+ * } 
+ * + * @see CommandExtension + */ +@XmlRootElement(name = "create") +public class AllocateCreateExtension extends ImmutableObject implements CommandExtension { + + /** Holds the ROID of the application that was used to allocate this domain. */ + String applicationRoid; + + /** The time that the application was created. */ + DateTime applicationTime; + + /** + * Signed mark identifier for this create. Only present when allocating a domain from a sunrise + * application. + */ + String smdId; + + /** + * The claims notice for this create. Only present when allocating a domain from a landrush + * application that matches a pre-registered mark in the TMCH. + */ + LaunchNotice notice; + + public String getApplicationRoid() { + return applicationRoid; + } + + public DateTime getApplicationTime() { + return applicationTime; + } + + public String getSmdId() { + return smdId; + } + + public LaunchNotice getNotice() { + return notice; + } +} diff --git a/java/com/google/domain/registry/model/domain/allocate/package-info.java b/java/com/google/domain/registry/model/domain/allocate/package-info.java new file mode 100644 index 000000000..c8c076736 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/allocate/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:google:params:xml:ns:allocate-1.0", + xmlns = @XmlNs(prefix = "allocate", namespaceURI = "urn:google:params:xml:ns:allocate-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.domain.allocate; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/domain/fee/BaseFee.java b/java/com/google/domain/registry/model/domain/fee/BaseFee.java new file mode 100644 index 000000000..e4a628d09 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/BaseFee.java @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import static com.google.common.base.MoreObjects.firstNonNull; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.xml.PeriodAdapter; + +import org.joda.time.Period; + +import java.math.BigDecimal; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** Base class for the fee and credit types. */ +@XmlTransient +public class BaseFee extends ImmutableObject { + + /** Enum for when a fee is applied. */ + public enum AppliedType { + @XmlEnumValue("immediate") + IMMEDIATE, + + @XmlEnumValue("delayed") + DELAYED + } + + @XmlAttribute + String description; + + @XmlAttribute + AppliedType applied; + + @XmlAttribute(name = "grace-period") + @XmlJavaTypeAdapter(PeriodAdapter.class) + Period gracePeriod; + + @XmlAttribute + Boolean refundable; + + @XmlValue + BigDecimal cost; + + public String getDescription() { + return description; + } + + public AppliedType getApplied() { + return firstNonNull(applied, AppliedType.IMMEDIATE); + } + + public Period getGracePeriod() { + return firstNonNull(gracePeriod, Period.ZERO); + } + + public Boolean getRefundable() { + return firstNonNull(refundable, true); + } + + public BigDecimal getCost() { + return cost; + } + + public boolean hasDefaultAttributes() { + return getGracePeriod().equals(Period.ZERO) + && getApplied().equals(AppliedType.IMMEDIATE) + && getRefundable(); + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/BaseFeeCommand.java b/java/com/google/domain/registry/model/domain/fee/BaseFeeCommand.java new file mode 100644 index 000000000..4a26225f2 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/BaseFeeCommand.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.ImmutableObject; + +import org.joda.money.CurrencyUnit; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** Base class for general transform commands with fees (create, renew, update, transfer). */ +@XmlTransient +public class BaseFeeCommand extends ImmutableObject { + + /** The currency of the fee. */ + CurrencyUnit currency; + + /** + * The magnitude of the fee, in the specified units, with an optional description. + *

+ * This is a list because a single operation can involve multiple fees. + */ + @XmlElement(name = "fee") + List fees; + + public CurrencyUnit getCurrency() { + return currency; + } + + public List getFees() { + return fees; + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/BaseFeeCommandResponse.java b/java/com/google/domain/registry/model/domain/fee/BaseFeeCommandResponse.java new file mode 100644 index 000000000..083884b93 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/BaseFeeCommandResponse.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; + +import org.joda.money.CurrencyUnit; + +import java.util.List; + +import javax.xml.bind.annotation.XmlTransient; + +/** Base class for fee responses on general transform commands (create, update, renew, transfer). */ +@XmlTransient +public class BaseFeeCommandResponse extends ImmutableObject { + + /** The currency of the fee. */ + CurrencyUnit currency; + + /** + * The magnitude of the fee, in the specified units, with an optional description. + *

+ * This is a list because a single operation can involve multiple fees. + */ + List fee; + + /** Abstract builder for {@link BaseFeeCommandResponse}. */ + public abstract static class Builder> + extends GenericBuilder { + public B setCurrency(CurrencyUnit currency) { + getInstance().currency = currency; + return thisCastToDerived(); + } + + public B setFee(ImmutableList fee) { + getInstance().fee = fee; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/BaseFeeRequest.java b/java/com/google/domain/registry/model/domain/fee/BaseFeeRequest.java new file mode 100644 index 000000000..728ba67f8 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/BaseFeeRequest.java @@ -0,0 +1,52 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.domain.Period; + +import org.joda.money.CurrencyUnit; + +import javax.xml.bind.annotation.XmlTransient; + +/** Base class for the fee requests on check and info. */ +@XmlTransient +public class BaseFeeRequest extends ImmutableObject { + + /** The default validity period (if not specified) is 1 year for all operations. */ + static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS); + + /** A three-character ISO4217 currency code. */ + CurrencyUnit currency; + + /** The command being checked. */ + FeeCommandDescriptor command; + + /** The period for the command being checked. */ + Period period; + + public CurrencyUnit getCurrency() { + return currency; + } + + public FeeCommandDescriptor getCommand() { + return command; + } + + public Period getPeriod() { + return Optional.fromNullable(period).or(DEFAULT_PERIOD); + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/BaseFeeResponse.java b/java/com/google/domain/registry/model/domain/fee/BaseFeeResponse.java new file mode 100644 index 000000000..6ae005ffe --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/BaseFeeResponse.java @@ -0,0 +1,91 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.domain.Period; + +import org.joda.money.CurrencyUnit; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** Base class for the fee responses on check and info. */ +@XmlTransient +public class BaseFeeResponse extends ImmutableObject { + /** The currency of the fee. */ + CurrencyUnit currency; + + /** The command that was checked. */ + FeeCommandDescriptor command; + + /** The period that was checked. */ + Period period; + + /** + * The magnitude of the fee, in the specified units, with an optional description. + *

+ * This is a list because a single operation can involve multiple fees. + */ + List fee; + + /** + * The type of the fee. + *

+ * We will use "premium" for fees on premium names, and omit the field otherwise. + */ + @XmlElement(name = "class") + String feeClass; + + public String getFeeClass() { + return feeClass; + } + + /** Abstract builder for {@link BaseFeeResponse}. */ + public abstract static class Builder> + extends GenericBuilder { + public B setCurrency(CurrencyUnit currency) { + getInstance().currency = currency; + return thisCastToDerived(); + } + + public B setCommand(FeeCommandDescriptor command) { + getInstance().command = command; + return thisCastToDerived(); + } + + public B setPeriod(Period period) { + getInstance().period = period; + return thisCastToDerived(); + } + + public B setFee(Fee... fee) { + // If there are no fees, set the field to null to suppress the 'fee' section in the xml. + getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fee)); + return thisCastToDerived(); + } + + public B setClass(String feeClass) { + getInstance().feeClass = feeClass; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/Credit.java b/java/com/google/domain/registry/model/domain/fee/Credit.java new file mode 100644 index 000000000..7f895642d --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/Credit.java @@ -0,0 +1,29 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.math.BigDecimal; + +/** A credit, in currency units specified elsewhere in the xml, and with an optional description. */ +public class Credit extends BaseFee { + public static Credit create(BigDecimal cost, String description) { + Credit instance = new Credit(); + instance.cost = checkNotNull(cost); + instance.description = description; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/Fee.java b/java/com/google/domain/registry/model/domain/fee/Fee.java new file mode 100644 index 000000000..acc63d329 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/Fee.java @@ -0,0 +1,29 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.math.BigDecimal; + +/** A fee, in currency units specified elsewhere in the xml, and with an optional description. */ +public class Fee extends BaseFee { + public static Fee create(BigDecimal cost, String description) { + Fee instance = new Fee(); + instance.cost = checkNotNull(cost); + instance.description = description; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeCheckExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeCheckExtension.java new file mode 100644 index 000000000..300aed02b --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeCheckExtension.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain check commands. */ +@XmlRootElement(name = "check") +public class FeeCheckExtension extends ImmutableObject implements CommandExtension { + + /** The default validity period (if not specified) is 1 year for all operations. */ + static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS); + + @XmlElement(name = "domain") + Set domains; + + public ImmutableSet getDomains() { + return nullToEmptyImmutableCopy(domains); + } + + /** A check request for the fee to perform a given command on a given domain. */ + @XmlType(propOrder = {"name", "currency", "command", "period"}) + public static class DomainCheck extends BaseFeeRequest { + /** The fully qualified domain name being checked. */ + String name; + + public String getName() { + return name; + } + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeCheckResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeCheckResponseExtension.java new file mode 100644 index 000000000..fa04aadc5 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeCheckResponseExtension.java @@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain check commands. + */ +@XmlRootElement(name = "chkData") +public class FeeCheckResponseExtension extends ImmutableObject implements ResponseExtension { + + /** Check responses. */ + @XmlElement(name = "cd") + ImmutableList feeChecks; + + @VisibleForTesting + public ImmutableList getChecks() { + return feeChecks; + } + + public static FeeCheckResponseExtension create(ImmutableList feeChecks) { + FeeCheckResponseExtension instance = new FeeCheckResponseExtension(); + instance.feeChecks = feeChecks; + return instance; + } + + /** The response for a check on a single resource. */ + @XmlType(propOrder = {"name", "currency", "command", "period", "fee", "feeClass"}) + public static class FeeCheck extends BaseFeeResponse { + /** The name of the domain that was checked, with an attribute indicating if it is premium. */ + String name; + + /** A builder for {@link FeeCheck}. */ + public static class Builder extends BaseFeeResponse.Builder { + public Builder setName(String name) { + getInstance().name = name; + return this; + } + } + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeCommandDescriptor.java b/java/com/google/domain/registry/model/domain/fee/FeeCommandDescriptor.java new file mode 100644 index 000000000..1102559f7 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeCommandDescriptor.java @@ -0,0 +1,67 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.common.base.CharMatcher; +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlValue; + +/** A command name along with the launch phase and subphase it is to be executed in. */ +public class FeeCommandDescriptor extends ImmutableObject { + + /** The name of a command that might have an associated fee. */ + public enum CommandName { + CREATE, + RENEW, + TRANSFER, + RESTORE, + UNKNOWN + } + + @XmlAttribute + String phase; + + @XmlAttribute + String subphase; + + @XmlValue + String command; + + public String getPhase() { + return phase; + } + + public String getSubphase() { + return subphase; + } + + public String getUnparsedCommandName() { + return command; + } + + public CommandName getCommand() { + // Require the xml string to be lowercase. + if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) { + try { + return CommandName.valueOf(command.toUpperCase()); + } catch (IllegalArgumentException e) { + // Swallow this and return UNKNOWN below because there's no matching CommandName. + } + } + return CommandName.UNKNOWN; + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeCreateExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeCreateExtension.java new file mode 100644 index 000000000..be116ae82 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeCreateExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain create commands. */ +@XmlRootElement(name = "create") +@XmlType(propOrder = {"currency", "fees"}) +public class FeeCreateExtension extends BaseFeeCommand implements CommandExtension {} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeCreateResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeCreateResponseExtension.java new file mode 100644 index 000000000..ca41bb685 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeCreateResponseExtension.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain create commands. + */ +@XmlRootElement(name = "creData") +@XmlType(propOrder = {"currency", "fee"}) +public class FeeCreateResponseExtension extends BaseFeeCommandResponse + implements ResponseExtension { + /** A builder for {@link FeeCreateResponseExtension}. */ + public static class Builder + extends BaseFeeCommandResponse.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeDeleteResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeDeleteResponseExtension.java new file mode 100644 index 000000000..840973b02 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeDeleteResponseExtension.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import org.joda.money.CurrencyUnit; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain create commands. + */ +@XmlRootElement(name = "delData") +public class FeeDeleteResponseExtension extends ImmutableObject implements ResponseExtension { + + /** The currency of the credit(s). */ + CurrencyUnit currency; + + /** + * The magnitude of the credit(s), in the specified units, with an optional description. + *

+ * This is a list because a single delete can receive multiple credits. + */ + @XmlElement(name = "credit") + List credits; + + /** Builder for {@link FeeDeleteResponseExtension}. */ + public static class Builder extends GenericBuilder { + public Builder setCurrency(CurrencyUnit currency) { + getInstance().currency = currency; + return thisCastToDerived(); + } + + public Builder setCredits(ImmutableList credits) { + getInstance().credits = credits; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeInfoExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeInfoExtension.java new file mode 100644 index 000000000..a9fa74976 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeInfoExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain info commands. */ +@XmlRootElement(name = "info") +@XmlType(propOrder = {"currency", "command", "period"}) +public class FeeInfoExtension extends BaseFeeRequest implements CommandExtension {} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeInfoResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeInfoResponseExtension.java new file mode 100644 index 000000000..72a1b6a29 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeInfoResponseExtension.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain info commands. + */ +@XmlRootElement(name = "infData") +@XmlType(propOrder = {"currency", "command", "period", "fee", "feeClass"}) +public class FeeInfoResponseExtension extends BaseFeeResponse implements ResponseExtension { + /** A builder for {@link FeeInfoResponseExtension}. */ + public static class Builder extends BaseFeeResponse.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeRenewExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeRenewExtension.java new file mode 100644 index 000000000..7cbe5284a --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeRenewExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain renew commands. */ +@XmlRootElement(name = "renew") +@XmlType(propOrder = {"currency", "fees"}) +public class FeeRenewExtension extends BaseFeeCommand implements CommandExtension {} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeRenewResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeRenewResponseExtension.java new file mode 100644 index 000000000..b935d8b41 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeRenewResponseExtension.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain create commands. + */ +@XmlRootElement(name = "renData") +@XmlType(propOrder = {"currency", "fee"}) +public class FeeRenewResponseExtension extends BaseFeeCommandResponse + implements ResponseExtension { + /** A builder for {@link FeeRenewResponseExtension}. */ + public static class Builder + extends BaseFeeCommandResponse.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeTransferExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeTransferExtension.java new file mode 100644 index 000000000..dadad9a41 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeTransferExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain transfer requests. */ +@XmlRootElement(name = "transfer") +@XmlType(propOrder = {"currency", "fees"}) +public class FeeTransferExtension extends BaseFeeCommand implements CommandExtension {} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeTransferResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeTransferResponseExtension.java new file mode 100644 index 000000000..9e8aaf0fd --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeTransferResponseExtension.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain transfer requests. + */ +@XmlRootElement(name = "trnData") +@XmlType(propOrder = {"currency", "fee"}) +public class FeeTransferResponseExtension extends BaseFeeCommandResponse + implements ResponseExtension { + /** A builder for {@link FeeTransferResponseExtension}. */ + public static class Builder + extends BaseFeeCommandResponse.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeUpdateExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeUpdateExtension.java new file mode 100644 index 000000000..d3de617ca --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeUpdateExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** A fee extension that may be present on domain update commands. */ +@XmlRootElement(name = "update") +@XmlType(propOrder = {"currency", "fees"}) +public class FeeUpdateExtension extends BaseFeeCommand implements CommandExtension {} diff --git a/java/com/google/domain/registry/model/domain/fee/FeeUpdateResponseExtension.java b/java/com/google/domain/registry/model/domain/fee/FeeUpdateResponseExtension.java new file mode 100644 index 000000000..47381c8f0 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/FeeUpdateResponseExtension.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a fee extension that may be present on the response to EPP + * domain update commands. + */ +@XmlRootElement(name = "updData") +@XmlType(propOrder = {"currency", "fee"}) +public class FeeUpdateResponseExtension extends BaseFeeCommandResponse + implements ResponseExtension { + /** A builder for {@link FeeUpdateResponseExtension}. */ + public static class Builder + extends BaseFeeCommandResponse.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/fee/package-info.java b/java/com/google/domain/registry/model/domain/fee/package-info.java new file mode 100644 index 000000000..52c416d77 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/fee/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:fee-0.6", + xmlns = @XmlNs(prefix = "fee", namespaceURI = "urn:ietf:params:xml:ns:fee-0.6"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(CurrencyUnitAdapter.class) +package com.google.domain.registry.model.domain.fee; + +import com.google.domain.registry.model.translators.CurrencyUnitAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/domain/launch/ApplicationIdTargetExtension.java b/java/com/google/domain/registry/model/domain/launch/ApplicationIdTargetExtension.java new file mode 100644 index 000000000..1ff25bc06 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/ApplicationIdTargetExtension.java @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +/** Marker interface for EPP extensions which override the EPP notion of id with their own. */ +public interface ApplicationIdTargetExtension extends CommandExtension { + /** Get the application id to use as the resource id for commands using this extension. */ + String getApplicationId(); +} diff --git a/java/com/google/domain/registry/model/domain/launch/ApplicationStatus.java b/java/com/google/domain/registry/model/domain/launch/ApplicationStatus.java new file mode 100644 index 000000000..7c667b837 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/ApplicationStatus.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import static com.google.common.base.CaseFormat.LOWER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; + +import com.google.domain.registry.model.translators.EnumToAttributeAdapter; +import com.google.domain.registry.model.translators.EnumToAttributeAdapter.EppEnum; + +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Represents the EPP application status. + *

+ * These values are never read from a command and only used in responses, so, we don't need to model + * anything we don't output. We don't model the CUSTOM status because we don't use it. This allows + * us to also avoid modeling the "name" attribute which is only used with CUSTOM. We don't model the + * "lang" attribute because we only support English and that's the default. + *

+ * Given all of this, we can use {@link EnumToAttributeAdapter} to make this code very simple. + * + * @see "http://tools.ietf.org/html/draft-tan-epp-launchphase-11#section-2.3" + */ +@XmlJavaTypeAdapter(EnumToAttributeAdapter.class) +public enum ApplicationStatus implements EppEnum { + ALLOCATED, + INVALID, + PENDING_ALLOCATION, + PENDING_VALIDATION, + REJECTED, + VALIDATED; + + @Override + public String getXmlName() { + return UPPER_UNDERSCORE.to(LOWER_CAMEL, name()); + } + + /** + * Returns true if this status is a final status - that is, it should not transition to any other + * application status after this one. + */ + public boolean isFinalStatus() { + return ALLOCATED.equals(this) || REJECTED.equals(this); + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchCheckExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchCheckExtension.java new file mode 100644 index 000000000..1d13ebe3f --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchCheckExtension.java @@ -0,0 +1,83 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import static com.google.common.base.MoreObjects.firstNonNull; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a launch extension that may be present on EPP domain check + * commands. + *

+ * This object holds XML data which JAXB will unmarshal from an EPP domain check command extension. + * The XML will have the following enclosing structure: + * + *

 {@code
+ *   
+ *     
+ *       
+ *         
+ *       
+ *       
+ *         
+ *           
+ *         
+ *       
+ *     
+ *   
+ * } 
+ * + * @see CommandExtension + */ +@XmlRootElement(name = "check") +public class LaunchCheckExtension extends ImmutableObject implements CommandExtension { + + /** The default check type is "claims" if not specified. */ + private static final CheckType DEFAULT_CHECK_TYPE = CheckType.CLAIMS; + + /** Type of domain check being requested. */ + public enum CheckType { + /** A check to see if the specified domain names are available to be provisioned. */ + @XmlEnumValue("avail") + AVAILABILITY, + + /** A check to see if there are matching trademarks on the specified domain names. */ + @XmlEnumValue("claims") + CLAIMS; + } + + /** + * The launch phase this command is intended to run against. If it does not match the server's + * current launch phase, the command will be rejected. + */ + LaunchPhase phase; + + @XmlAttribute + CheckType type; + + public CheckType getCheckType() { + return firstNonNull(type, DEFAULT_CHECK_TYPE); + } + + public LaunchPhase getPhase() { + return phase; + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchCheckResponseExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchCheckResponseExtension.java new file mode 100644 index 000000000..4f3808578 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchCheckResponseExtension.java @@ -0,0 +1,94 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** + * An XML data object that represents a launch extension that may be present on the response to EPP + * domain check commands. + */ +@XmlRootElement(name = "chkData") +@XmlType(propOrder = {"phase", "launchChecks"}) +public class LaunchCheckResponseExtension extends ImmutableObject implements ResponseExtension { + + /** The launch phase that this domain check was run against. */ + LaunchPhase phase; + + /** Check responses. */ + @XmlElement(name = "cd") + ImmutableList launchChecks; + + @VisibleForTesting + public LaunchPhase getPhase() { + return phase; + } + + @VisibleForTesting + public ImmutableList getChecks() { + return launchChecks; + } + + /** The response for a check on a single resource. */ + public static class LaunchCheck extends ImmutableObject { + /** An element containing the name and availability of a resource. */ + LaunchCheckName name; + + /** A key used to generate a Trademark Claims Notice. Only returned on claims checks. */ + String claimKey; + + public static LaunchCheck create(LaunchCheckName name, String claimKey) { + LaunchCheck instance = new LaunchCheck(); + instance.name = name; + instance.claimKey = claimKey; + return instance; + } + } + + /** Holds the name and availability of a checked resource. */ + public static class LaunchCheckName extends ImmutableObject { + /** Whether the resource is available. */ + @XmlAttribute + boolean exists; + + /** The name of the resource being checked. */ + @XmlValue + String name; + + public static LaunchCheckName create(boolean exists, String name) { + LaunchCheckName instance = new LaunchCheckName(); + instance.exists = exists; + instance.name = name; + return instance; + } + } + + public static LaunchCheckResponseExtension create( + LaunchPhase phase, ImmutableList launchChecks) { + LaunchCheckResponseExtension instance = new LaunchCheckResponseExtension(); + instance.phase = phase; + instance.launchChecks = launchChecks; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchCreateExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchCreateExtension.java new file mode 100644 index 000000000..ddd03f592 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchCreateExtension.java @@ -0,0 +1,117 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; +import com.google.domain.registry.model.smd.AbstractSignedMark; +import com.google.domain.registry.model.smd.EncodedSignedMark; +import com.google.domain.registry.model.smd.SignedMark; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a launch extension that may be present on EPP domain create + * commands. + *

+ * This object holds XML data which JAXB will unmarshal from an EPP domain create command extension. + * The XML will have the following enclosing structure: + * + *

 {@code
+ *   
+ *     
+ *       
+ *         
+ *       
+ *       
+ *         
+ *           
+ *         
+ *       
+ *     
+ *   
+ * } 
+ * + * @see CommandExtension + */ +@XmlRootElement(name = "create") +public class LaunchCreateExtension extends LaunchExtension implements CommandExtension { + + /** Type of domain creation being requested. */ + public enum CreateType { + /** + * A Launch Application refers to a registration made during a launch phase when the server + * accepts multiple applications for the same domain name. + */ + @XmlEnumValue("application") + APPLICATION, + + /** + * A Launch Registration refers to a registration made during a launch phase when the server + * uses a "first-come, first-served" model. + */ + @XmlEnumValue("registration") + REGISTRATION; + } + + @XmlAttribute + CreateType type; + + /** + * A list of signed marks or encoded signed marks which assert the client's ability to register + * the specified domain name. Each one contains both a Mark object with information about its + * claim(s), and an XML signature over that mark object which is cryptographically signed. This is + * used in the "signed mark" validation model. + */ + @XmlElementRefs({ + @XmlElementRef(type = EncodedSignedMark.class), + @XmlElementRef(type = SignedMark.class)}) + List signedMarks; + + /** + * A CodeMark is an abstract entity which contains either a secret code or a mark (or both) to + * assert its ability to register a particular mark. It is used in the "code", "mark", and "code + * with mark" validation models, none of which are supported by this codebase at this time. As + * such, it is stored only as an Object to mark its existence, but not further unmarshaled. + */ + List codeMark; + + /** The claims notice for this create, required if creating a domain with a claimed label. */ + LaunchNotice notice; + + public CreateType getCreateType() { + return type; + } + + public ImmutableList getSignedMarks() { + return nullToEmptyImmutableCopy(signedMarks); + } + + public boolean hasCodeMarks() { + return codeMark != null && !codeMark.isEmpty(); + } + + public LaunchNotice getNotice() { + return notice; + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchCreateResponseExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchCreateResponseExtension.java new file mode 100644 index 000000000..5aed39be2 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchCreateResponseExtension.java @@ -0,0 +1,32 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a launch extension that may be present on the response to EPP + * domain application create commands. + */ +@XmlRootElement(name = "creData") +@XmlType(propOrder = {"phase", "applicationId"}) +public class LaunchCreateResponseExtension extends LaunchExtension implements ResponseExtension { + /** Builder for {@link LaunchCreateResponseExtension}. */ + public static class Builder + extends LaunchExtension.Builder {} +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchDeleteExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchDeleteExtension.java new file mode 100644 index 000000000..f33644306 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchDeleteExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a launch extension that may be present on EPP domain delete + * commands. + */ +@XmlRootElement(name = "delete") +public class LaunchDeleteExtension + extends LaunchExtension implements ApplicationIdTargetExtension {} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchExtension.java new file mode 100644 index 000000000..12c5f6e28 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchExtension.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * A launch extension which can be passed in to domain update and delete, and also returned from + * domain create. + */ +@XmlTransient +public abstract class LaunchExtension extends ImmutableObject { + + /** The launch phase that this domain application was created in. */ + LaunchPhase phase; + + /** Application ID of the domain application. */ + @XmlElement(name = "applicationID") + String applicationId; + + public LaunchPhase getPhase() { + return phase; + } + + public String getApplicationId() { + return applicationId; + } + + /** A builder for constructing {@link LaunchExtension}. */ + public static class Builder> + extends GenericBuilder { + public B setPhase(LaunchPhase phase) { + getInstance().phase = phase; + return thisCastToDerived(); + } + + public B setApplicationId(String applicationId) { + getInstance().applicationId = applicationId; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchInfoExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchInfoExtension.java new file mode 100644 index 000000000..ea12c685a --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchInfoExtension.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a launch extension that may be present on EPP domain info + * commands. + */ +@XmlRootElement(name = "info") +public class LaunchInfoExtension + extends LaunchExtension implements ApplicationIdTargetExtension { + + /** Whether or not to include mark information in the response. */ + @XmlAttribute + Boolean includeMark; + + public Boolean getIncludeMark() { + return includeMark; + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchInfoResponseExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchInfoResponseExtension.java new file mode 100644 index 000000000..f7fb9b22f --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchInfoResponseExtension.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.mark.Mark; + +import com.googlecode.objectify.annotation.Embed; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * An XML data object that represents a launch extension that may be present on the response to EPP + * domain application info commands. + */ +@Embed +@XmlRootElement(name = "infData") +@XmlType(propOrder = { "phase", "applicationId", "applicationStatus", "marks"}) +public class LaunchInfoResponseExtension extends LaunchExtension implements ResponseExtension { + + /** The current status of this application. */ + @XmlElement(name = "status") + ApplicationStatus applicationStatus; + + /** The marks associated with this application. */ + @XmlElement(name = "mark", namespace = "urn:ietf:params:xml:ns:mark-1.0") + List marks; + + /** Builder for {@link LaunchInfoResponseExtension}. */ + public static class Builder + extends LaunchExtension.Builder { + public Builder setApplicationStatus(ApplicationStatus applicationStatus) { + getInstance().applicationStatus = applicationStatus; + return this; + } + + public Builder setMarks(ImmutableList marks) { + getInstance().marks = marks; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchNotice.java b/java/com/google/domain/registry/model/domain/launch/LaunchNotice.java new file mode 100644 index 000000000..8a6166230 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchNotice.java @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.hash.Hashing.crc32; +import static com.google.common.io.BaseEncoding.base16; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Optional; +import com.google.common.primitives.Ints; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** The claims notice id from the claims phase. */ +@Embed +@XmlType(propOrder = {"noticeId", "expirationTime", "acceptedTime"}) +public class LaunchNotice extends ImmutableObject { + + /** An empty instance to use in place of null. */ + private static final NoticeIdType EMPTY_NOTICE_ID = new NoticeIdType(); + + /** An id with a validator-id attribute. */ + @Embed + public static class NoticeIdType extends ImmutableObject { + + /** + * The Trademark Claims Notice ID from + * {@link "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3"}. + */ + @XmlValue + String tcnId; + + /** The identifier of the TMDB provider to use, defaulting to the TMCH. */ + @IgnoreSave(IfNull.class) + @XmlAttribute(name = "validatorID") + String validatorId; + + public String getTcnId() { + return tcnId; + } + + public String getValidatorId() { + // The default value is "tmch". + return Optional.fromNullable(validatorId).or("tmch"); + } + } + + @XmlElement(name = "noticeID") + NoticeIdType noticeId; + + @XmlElement(name = "notAfter") + DateTime expirationTime; + + @XmlElement(name = "acceptedDate") + DateTime acceptedTime; + + public NoticeIdType getNoticeId() { + return Optional.fromNullable(noticeId).or(EMPTY_NOTICE_ID); + } + + public DateTime getExpirationTime() { + return expirationTime; + } + + public DateTime getAcceptedTime() { + return acceptedTime; + } + + /** + * Validate the checksum of the notice against the domain label. + * + * @throws IllegalArgumentException + * @throws InvalidChecksumException + */ + public void validate(String domainLabel) throws InvalidChecksumException { + // According to http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3, a TCNID + // is always 8 chars of checksum + 19 chars of a decimal notice id. Check the length before + // taking substrings to avoid an IndexOutOfBoundsException. + String tcnId = getNoticeId().getTcnId(); + checkArgument(tcnId.length() == 27); + + int checksum = Ints.fromByteArray(base16().decode(tcnId.substring(0, 8).toUpperCase())); + String noticeId = tcnId.substring(8); + checkArgument(CharMatcher.inRange('0', '9').matchesAllOf(noticeId)); + + // The checksum in the first 8 chars must match the crc32 of label + expiration + notice id. + String stringToHash = + domainLabel + MILLISECONDS.toSeconds(getExpirationTime().getMillis()) + noticeId; + int computedChecksum = crc32().hashString(stringToHash, UTF_8).asInt(); + if (checksum != computedChecksum) { + throw new InvalidChecksumException(); + } + } + + /** Thrown from validate() if the checksum is invalid. */ + public static class InvalidChecksumException extends Exception {} + + public static LaunchNotice create( + String tcnId, String validatorId, DateTime expirationTime, DateTime acceptedTime) { + LaunchNotice instance = new LaunchNotice(); + instance.noticeId = new NoticeIdType(); + instance.noticeId.tcnId = tcnId; + instance.noticeId.validatorId = "tmch".equals(validatorId) ? null : validatorId; + instance.expirationTime = expirationTime; + instance.acceptedTime = acceptedTime; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchPhase.java b/java/com/google/domain/registry/model/domain/launch/LaunchPhase.java new file mode 100644 index 000000000..2713978a5 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchPhase.java @@ -0,0 +1,126 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import static com.google.common.base.CaseFormat.LOWER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.domain.registry.util.TypeUtils.getTypesafeEnumMapping; +import static java.util.Objects.hash; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlValue; + +/** + * The launch phase of the TLD being addressed by this command. + *

+ * The launch phase refers to the various stages that a TLD goes through before entering general + * availability. The various phases are described below (in order that they usually occur). + */ +@Embed +public class LaunchPhase extends ImmutableObject { + + /** + * The phase during which trademark holders can submit registrations or applications with + * trademark information that can be validated by the server. + */ + public static final LaunchPhase SUNRISE = create("sunrise", null); + + /** + * A post-Sunrise phase when non-trademark holders are allowed to register domain names with steps + * taken to address a large volume of initial registrations. + */ + public static final LaunchPhase LANDRUSH = create("landrush", null); + + /** A combined sunrise/landrush phase. */ + public static final LaunchPhase SUNRUSH = create("sunrise", "landrush"); + + /** + * The Trademark Claims phase, as defined in the TMCH Functional Specification, in which a Claims + * Notice must be displayed to a prospective registrant of a domain name that matches trademarks. + */ + public static final LaunchPhase CLAIMS = create("claims", null); + + /** A post-launch phase that is also referred to as "steady state". */ + public static final LaunchPhase OPEN = create("open", null); + + /** A custom server launch phase that is defined using the "name" attribute. */ + public static final LaunchPhase CUSTOM = create("custom", null); + + private static final Map LAUNCH_PHASES = initEnumMapping(); + + /** + * Returns a map of the static final fields to their values, case-converted. + */ + private static final ImmutableMap initEnumMapping() { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Entry entry : getTypesafeEnumMapping(LaunchPhase.class).entrySet()) { + builder.put(UPPER_UNDERSCORE.to(LOWER_CAMEL, entry.getKey()), entry.getValue()); + } + return builder.build(); + } + + /** Private create function for the typesafe enum pattern. */ + public static LaunchPhase create(String phase, String subphase) { + LaunchPhase instance = new LaunchPhase(); + instance.phase = phase; + instance.subphase = subphase; + return instance; + } + + @XmlValue + String phase; + + /** + * Holds the name of a custom phase if the main phase is "custom", or a sub-phase for all other + * values. + */ + @XmlAttribute(name = "name") + String subphase; + + public String getPhase() { + return phase; + } + + public String getSubphase() { + return subphase; + } + + public static LaunchPhase fromValue(String value) { + return LAUNCH_PHASES.get(value); + } + + /** A special equals implementation that only considers the string value. */ + @Override + public boolean equals(Object other) { + return other instanceof LaunchPhase + && Objects.equals(phase, ((LaunchPhase) other).phase) + && Objects.equals(subphase, ((LaunchPhase) other).subphase); + } + + /** A special hashCode implementation that only considers the string value. */ + @Override + public int hashCode() { + return hash(phase, subphase); + } +} diff --git a/java/com/google/domain/registry/model/domain/launch/LaunchUpdateExtension.java b/java/com/google/domain/registry/model/domain/launch/LaunchUpdateExtension.java new file mode 100644 index 000000000..21f097b42 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/LaunchUpdateExtension.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.launch; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * An XML data object that represents a launch extension that may be present on EPP domain update + * commands. + */ +@XmlRootElement(name = "update") +public class LaunchUpdateExtension + extends LaunchExtension implements ApplicationIdTargetExtension {} diff --git a/java/com/google/domain/registry/model/domain/launch/package-info.java b/java/com/google/domain/registry/model/domain/launch/package-info.java new file mode 100644 index 000000000..d48693e58 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/launch/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:launch-1.0", + xmlns = @XmlNs(prefix = "launch", namespaceURI = "urn:ietf:params:xml:ns:launch-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.domain.launch; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/domain/metadata/MetadataExtension.java b/java/com/google/domain/registry/model/domain/metadata/MetadataExtension.java new file mode 100644 index 000000000..6b10a99b9 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/metadata/MetadataExtension.java @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.metadata; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** A metadata extension that may be present on EPP create/mutate commands. */ +@XmlRootElement(name = "metadata") +public class MetadataExtension extends ImmutableObject implements CommandExtension { + + /** The reason for the change. */ + @XmlElement(name = "reason") + String reason; + + /** Whether a change was requested by a registrar. */ + @XmlElement(name = "requestedByRegistrar") + boolean requestedByRegistrar; + + /** + * Whether a domain is being created for an anchor tenant. This field is only + * relevant for domain creates, and should be omitted for all other operations. + */ + @XmlElement(name = "anchorTenant") + boolean isAnchorTenant; + + public String getReason() { + return reason; + } + + public boolean getRequestedByRegistrar() { + return requestedByRegistrar; + } + + public boolean getIsAnchorTenant() { + return isAnchorTenant; + } +} diff --git a/java/com/google/domain/registry/model/domain/metadata/package-info.java b/java/com/google/domain/registry/model/domain/metadata/package-info.java new file mode 100644 index 000000000..a3dccba55 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/metadata/package-info.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:google:params:xml:ns:metadata-1.0", + xmlns = @XmlNs(prefix = "metadata", namespaceURI = "urn:google:params:xml:ns:metadata-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +package com.google.domain.registry.model.domain.metadata; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; + diff --git a/java/com/google/domain/registry/model/domain/package-info.java b/java/com/google/domain/registry/model/domain/package-info.java new file mode 100644 index 000000000..17d209f6a --- /dev/null +++ b/java/com/google/domain/registry/model/domain/package-info.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:domain-1.0", + xmlns = @XmlNs(prefix = "domain", namespaceURI = "urn:ietf:params:xml:ns:domain-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapters({ + @XmlJavaTypeAdapter(UtcDateTimeAdapter.class), + @XmlJavaTypeAdapter(ContactReferenceUnionAdapter.class), + @XmlJavaTypeAdapter(HostReferenceUnionAdapter.class), + @XmlJavaTypeAdapter(DateAdapter.class)}) +package com.google.domain.registry.model.domain; + +import com.google.domain.registry.model.domain.ReferenceUnion.ContactReferenceUnionAdapter; +import com.google.domain.registry.model.domain.ReferenceUnion.HostReferenceUnionAdapter; +import com.google.domain.registry.xml.DateAdapter; +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; + diff --git a/java/com/google/domain/registry/model/domain/rgp/GracePeriodStatus.java b/java/com/google/domain/registry/model/domain/rgp/GracePeriodStatus.java new file mode 100644 index 000000000..67ce2c8bc --- /dev/null +++ b/java/com/google/domain/registry/model/domain/rgp/GracePeriodStatus.java @@ -0,0 +1,104 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.rgp; + +import com.google.domain.registry.model.translators.EnumToAttributeAdapter; +import com.google.domain.registry.model.translators.EnumToAttributeAdapter.EppEnum; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Represents a Registry Grace Period status, as defined by + * RFC 3915. + * + * @see "https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en" + */ +@XmlJavaTypeAdapter(EnumToAttributeAdapter.class) +public enum GracePeriodStatus implements EppEnum { + + /** + * This grace period is provided after the initial registration of a domain name. If the domain + * name is deleted by the registrar during this period, the registry provides a credit to the + * registrar for the cost of the registration. + */ + ADD("addPeriod"), + + /** + * This grace period is provided after a domain name registration period expires and is extended + * (renewed) automatically by the registry. If the domain name is deleted by the registrar during + * this period, the registry provides a credit to the registrar for the cost of the renewal. + */ + AUTO_RENEW("autoRenewPeriod"), + + /** + * This status value is used to describe a domain for which a command has been received, + * but the domain has not yet been purged because an opportunity exists to restore the domain and + * abort the deletion process. + */ + REDEMPTION("redemptionPeriod"), + + /** + * This grace period is provided after a domain name registration period is explicitly extended + * (renewed) by the registrar. If the domain name is deleted by the registrar during this period, + * the registry provides a credit to the registrar for the cost of the renewal. + */ + RENEW("renewPeriod"), + + /** + * This status value is used to describe a domain that has entered the purge processing state + * after completing the redemptionPeriod state. A domain in this status MUST also have the EPP + * pendingDelete status. + */ + PENDING_DELETE("pendingDelete"), + + /** + * This status value is used to describe a domain that is in the process of being restored after + * being in the redemptionPeriod state. + */ + PENDING_RESTORE("pendingRestore"), + + /** + * This grace period is provided after the allocation of a domain name that was applied for during + * sunrise or landrush. If the domain name is deleted by the registrar during this period, the + * registry provides a credit to the registrar for the cost of the registration. This grace period + * is cancelled when any nameservers are set on the domain, at which point it converts to a + * standard add grace period. + * + *

Note that this status shows up as "addPeriod" in XML, which is the same as the add grace + * period. This is done deliberately so as not to break the standard EPP schema. + */ + SUNRUSH_ADD("addPeriod"), + + /** + * This grace period is provided after the successful transfer of domain name registration + * sponsorship from one registrar to another registrar. If the domain name is deleted by the new + * sponsoring registrar during this period, the registry provides a credit to the registrar for + * the cost of the transfer. + */ + TRANSFER("transferPeriod"); + + @XmlAttribute(name = "s") + private final String xmlName; + + GracePeriodStatus(String xmlName) { + this.xmlName = xmlName; + } + + @Override + public String getXmlName() { + return xmlName; + } +} diff --git a/java/com/google/domain/registry/model/domain/rgp/RestoreCommand.java b/java/com/google/domain/registry/model/domain/rgp/RestoreCommand.java new file mode 100644 index 000000000..55651f7d4 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/rgp/RestoreCommand.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.rgp; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; + +/** The EPP RGP restore command. */ +public class RestoreCommand { + + /** Restore operation to perform on this domain. */ + @XmlEnum + public enum RestoreOp { + @XmlEnumValue("request") + REQUEST, + + @XmlEnumValue("report") + REPORT; + } + + /** The restore operation. */ + @XmlAttribute + RestoreOp op; + + /** A marker object that will be non-null if a report was passed. */ + Object report; + + public RestoreOp getRestoreOp() { + return op; + } + + public boolean hasRestoreReport() { + return report != null; + } +} diff --git a/java/com/google/domain/registry/model/domain/rgp/RgpInfoExtension.java b/java/com/google/domain/registry/model/domain/rgp/RgpInfoExtension.java new file mode 100644 index 000000000..5a71d9398 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/rgp/RgpInfoExtension.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.rgp; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import javax.xml.bind.annotation.XmlRootElement; + +/** The EPP registry grace period extension to be returned with domain info commands. */ +@XmlRootElement(name = "infData") +public class RgpInfoExtension extends ImmutableObject implements ResponseExtension { + + /** Registry grace period statuses for this domain. */ + ImmutableSet rgpStatus; + + public static RgpInfoExtension create(ImmutableSet rgpStatus) { + RgpInfoExtension instance = new RgpInfoExtension(); + instance.rgpStatus = rgpStatus; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/rgp/RgpUpdateExtension.java b/java/com/google/domain/registry/model/domain/rgp/RgpUpdateExtension.java new file mode 100644 index 000000000..59450eb5e --- /dev/null +++ b/java/com/google/domain/registry/model/domain/rgp/RgpUpdateExtension.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.rgp; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import javax.xml.bind.annotation.XmlRootElement; + +/** The EPP RGP extension that may be present on domain update commands. */ +@XmlRootElement(name = "update") +public class RgpUpdateExtension extends ImmutableObject implements CommandExtension { + + RestoreCommand restore; + + public RestoreCommand getRestoreCommand() { + return restore; + } +} diff --git a/java/com/google/domain/registry/model/domain/rgp/package-info.java b/java/com/google/domain/registry/model/domain/rgp/package-info.java new file mode 100644 index 000000000..193afb8a3 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/rgp/package-info.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:rgp-1.0", + xmlns = @XmlNs(prefix = "rgp", namespaceURI = "urn:ietf:params:xml:ns:rgp-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +package com.google.domain.registry.model.domain.rgp; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; + diff --git a/java/com/google/domain/registry/model/domain/secdns/DelegationSignerData.java b/java/com/google/domain/registry/model/domain/secdns/DelegationSignerData.java new file mode 100644 index 000000000..ab6ae22c2 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/secdns/DelegationSignerData.java @@ -0,0 +1,95 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.secdns; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Holds the data necessary to construct a single Delegation Signer (DS) record for a domain. + * + * @see RFC 5910 + * @see RFC 4034 + */ +@Embed +@XmlType(name = "dsData") +public class DelegationSignerData + extends ImmutableObject implements Comparable { + + /** The identifier for this particular key in the domain. */ + int keyTag; + + /** + * The algorithm used by this key. + * + * @see RFC 4034 Appendix A.1 + */ + @XmlElement(name = "alg") + int algorithm; + + /** + * The algorithm used to generate the digest. + * + * @see RFC 4034 Appendix A.2 + */ + int digestType; + + /** + * The hexBinary digest of the public key. + * + * @see RFC 4034 Section 5.1.4 + */ + @XmlJavaTypeAdapter(HexBinaryAdapter.class) + byte[] digest; + + public int getKeyTag() { + return keyTag; + } + + public int getAlgorithm() { + return algorithm; + } + + public int getDigestType() { + return digestType; + } + + public byte[] getDigest() { + return digest; + } + + @VisibleForTesting + public static DelegationSignerData create( + int keyTag, int algorithm, int digestType, byte[] digest) { + DelegationSignerData instance = new DelegationSignerData(); + instance.keyTag = keyTag; + instance.algorithm = algorithm; + instance.digestType = digestType; + instance.digest = digest; + return instance; + } + + @Override + public int compareTo(DelegationSignerData other) { + return Integer.compare(getKeyTag(), other.getKeyTag()); + } +} diff --git a/java/com/google/domain/registry/model/domain/secdns/SecDnsCreateExtension.java b/java/com/google/domain/registry/model/domain/secdns/SecDnsCreateExtension.java new file mode 100644 index 000000000..e20b1137f --- /dev/null +++ b/java/com/google/domain/registry/model/domain/secdns/SecDnsCreateExtension.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.secdns; + +import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** The EPP secDNS extension that may be present on domain create commands. */ +@XmlRootElement(name = "create") +@XmlType(propOrder = {"maxSigLife", "dsData"}) +public class SecDnsCreateExtension extends ImmutableObject implements CommandExtension { + /** + * Time in seconds until the signature should expire. + *

+ * We do not support expirations, but we need this field to be able to return appropriate errors. + */ + Long maxSigLife; + + /** Signatures for this domain. */ + Set dsData; + + public Long getMaxSigLife() { + return maxSigLife; + } + + public ImmutableSet getDsData() { + return nullSafeImmutableCopy(dsData); + } +} diff --git a/java/com/google/domain/registry/model/domain/secdns/SecDnsInfoExtension.java b/java/com/google/domain/registry/model/domain/secdns/SecDnsInfoExtension.java new file mode 100644 index 000000000..feea72b78 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/secdns/SecDnsInfoExtension.java @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.secdns; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlRootElement; + +/** The EPP secDNS extension to be returned with domain info commands. */ +@XmlRootElement(name = "infData") +@Embed +public class SecDnsInfoExtension extends ImmutableObject implements ResponseExtension { + + /** Signatures for this domain. */ + ImmutableSet dsData; + + public static SecDnsInfoExtension create(ImmutableSet dsData) { + SecDnsInfoExtension instance = new SecDnsInfoExtension(); + instance.dsData = dsData; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/domain/secdns/SecDnsUpdateExtension.java b/java/com/google/domain/registry/model/domain/secdns/SecDnsUpdateExtension.java new file mode 100644 index 000000000..22a88faad --- /dev/null +++ b/java/com/google/domain/registry/model/domain/secdns/SecDnsUpdateExtension.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.domain.secdns; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** The EPP secDNS extension that may be present on domain update commands. */ +@XmlRootElement(name = "update") +@XmlType(propOrder = {"remove", "add", "change"}) +public class SecDnsUpdateExtension extends ImmutableObject implements CommandExtension { + + /** + * Specifies whether this update is urgent. + *

+ * We don't support urgent updates but we need this to be present to provide appropriate error + * messages if a client requests it. + */ + @XmlAttribute + Boolean urgent; + + /** Allows removing some or all delegations. */ + @XmlElement(name = "rem") + Remove remove; + + /** Allows adding new delegations. */ + Add add; + + /** Would allow changing maxSigLife except that we don't support it. */ + @XmlElement(name = "chg") + Change change; + + public Boolean getUrgent() { + return urgent; + } + + public Remove getRemove() { + return remove; + } + + public Add getAdd() { + return add; + } + + public Change getChange() { + return change; + } + + @XmlTransient + abstract static class AddRemoveBase extends ImmutableObject { + /** Delegations to add or remove. */ + Set dsData; + + public ImmutableSet getDsData() { + return nullToEmptyImmutableCopy(dsData); + } + } + + /** The inner add type on the update extension. */ + public static class Add extends AddRemoveBase {} + + /** The inner remove type on the update extension. */ + @XmlType(propOrder = {"all", "dsData"}) + public static class Remove extends AddRemoveBase { + /** Whether to remove all delegations. */ + Boolean all; + + public Boolean getAll() { + return all; + } + } + + /** The inner change type on the update extension, though we don't actually support changes. */ + public static class Change extends ImmutableObject { + /** + * Time in seconds until the signature should expire. + *

+ * We do not support expirations, but we need this field to be able to return appropriate + * errors. + */ + Long maxSigLife; + } +} diff --git a/java/com/google/domain/registry/model/domain/secdns/package-info.java b/java/com/google/domain/registry/model/domain/secdns/package-info.java new file mode 100644 index 000000000..02dae4c73 --- /dev/null +++ b/java/com/google/domain/registry/model/domain/secdns/package-info.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:secDNS-1.1", + xmlns = @XmlNs(prefix = "secDNS", namespaceURI = "urn:ietf:params:xml:ns:secDNS-1.1"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +package com.google.domain.registry.model.domain.secdns; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; + diff --git a/java/com/google/domain/registry/model/eppcommon/Address.java b/java/com/google/domain/registry/model/eppcommon/Address.java new file mode 100644 index 000000000..d0ccd2464 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/Address.java @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.JsonMapBuilder; +import com.google.domain.registry.model.Jsonifiable; + +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.NormalizedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Container for generic street address. + *

+ * This is the "addrType" type from {@link "http://tools.ietf.org/html/rfc5733"}. It also matches + * the "addrType" type from {@link "http://tools.ietf.org/html/draft-lozano-tmch-smd"}. + * + * @see com.google.domain.registry.model.contact.ContactAddress + * @see com.google.domain.registry.model.mark.MarkAddress + * @see com.google.domain.registry.model.registrar.RegistrarAddress + */ +@XmlTransient +public class Address extends ImmutableObject implements Jsonifiable { + + /** The schema validation will enforce that this has 3 lines at most. */ + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + List street; + + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + String city; + + @XmlElement(name = "sp") + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + String state; + + @XmlElement(name = "pc") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String zip; + + @XmlElement(name = "cc") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String countryCode; + + public ImmutableList getStreet() { + return nullToEmptyImmutableCopy(street); + } + + public String getCity() { + return city; + } + + public String getState() { + return state; + } + + public String getZip() { + return zip; + } + + public String getCountryCode() { + return countryCode; + } + + @Override + public Map toJsonMap() { + return new JsonMapBuilder() + .putListOfStrings("street", street) + .put("city", city) + .put("state", state) + .put("zip", zip) + .put("countryCode", countryCode) + .build(); + } + + /** A builder for constructing {@link Address}. */ + @VisibleForTesting + public static class Builder extends Buildable.Builder { + public Builder setStreet(ImmutableList street) { + checkArgument( + street == null || (!street.isEmpty() && street.size() <= 3), + "Street address must have [1-3] lines: %s", street); + getInstance().street = street; + return this; + } + + public Builder setCity(String city) { + getInstance().city = city; + return this; + } + + public Builder setState(String state) { + getInstance().state = state; + return this; + } + + public Builder setZip(String zip) { + getInstance().zip = zip; + return this; + } + + public Builder setCountryCode(String countryCode) { + checkArgument( + countryCode == null || countryCode.length() == 2, + "Country code should be a 2 character string"); + getInstance().countryCode = countryCode; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/eppcommon/AuthInfo.java b/java/com/google/domain/registry/model/eppcommon/AuthInfo.java new file mode 100644 index 000000000..310ff94e8 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/AuthInfo.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.NormalizedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * The "authInfoType" complex type. + *

+ * RFCs 5731 and 5732 define this almost identically up to the namespace. + */ +@XmlTransient +public abstract class AuthInfo extends ImmutableObject { + + /** + * Verify that the authorization info is valid for the given resource in the given tld. + * + * @throws BadAuthInfoException if this authorization info is invalid for this resource + */ + public abstract void verifyAuthorizedFor(EppResource eppResource) throws BadAuthInfoException; + + protected PasswordAuth pw; + + public PasswordAuth getPw() { + return pw; + } + + /** The "pwAuthInfoType" complex type. */ + @Embed + @XmlType(namespace = "urn:ietf:params:xml:ns:eppcom-1.0") + public static class PasswordAuth extends ImmutableObject { + @XmlValue + @XmlJavaTypeAdapter(NormalizedStringAdapter.class) + String value; + + @XmlAttribute(name = "roid") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String repoId; + + public String getValue() { + return value; + } + + public String getRepoId() { + return repoId; + } + + public static PasswordAuth create(String value, String repoId) { + PasswordAuth instance = new PasswordAuth(); + instance.value = value; + instance.repoId = repoId; + return instance; + } + + public static PasswordAuth create(String value) { + return create(value, null); + } + } + + /** Returns the repoId for the contact this auth info is associated with. */ + protected String getRepoId() { + return pw.getRepoId(); + } + + /** Exception to throw when an auth info can't be verified. */ + public static class BadAuthInfoException extends Exception {} +} diff --git a/java/com/google/domain/registry/model/eppcommon/PhoneNumber.java b/java/com/google/domain/registry/model/eppcommon/PhoneNumber.java new file mode 100644 index 000000000..c0ba9e2d9 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/PhoneNumber.java @@ -0,0 +1,88 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Container for generic E164 phone number. + *

+ * This is the "e164" type from {@link "http://tools.ietf.org/html/rfc5733"}. It also matches the + * "e164Type" type from {@link "http://tools.ietf.org/html/draft-lozano-tmch-smd"}. + * + *

+ * "Contact telephone number structure is derived from structures defined in [ITU.E164.2005]. + * Telephone numbers described in this mapping are character strings that MUST begin with a plus + * sign ("+", ASCII value 0x002B), followed by a country code defined in [ITU.E164.2005], followed + * by a dot (".", ASCII value 0x002E), followed by a sequence of digits representing the telephone + * number. An optional "x" attribute is provided to note telephone extension information." + *

+ * + * @see com.google.domain.registry.model.contact.ContactPhoneNumber + * @see com.google.domain.registry.model.mark.MarkPhoneNumber + */ +@XmlTransient +public class PhoneNumber extends ImmutableObject { + + @XmlValue + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String phoneNumber; + + @XmlAttribute(name = "x") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String extension; + + public String getPhoneNumber() { + return phoneNumber; + } + + public String getExtension() { + return extension; + } + + public String toPhoneString() { + return phoneNumber + (extension != null ? " x" + extension : ""); + } + + /** A builder for constructing {@link PhoneNumber}. */ + @VisibleForTesting + public static class Builder extends Buildable.Builder { + @Override + public T build() { + checkNotNull(getInstance().phoneNumber, "phoneNumber"); + return super.build(); + } + + public Builder setPhoneNumber(String phoneNumber) { + getInstance().phoneNumber = phoneNumber; + return this; + } + + public Builder setExtension(String extension) { + getInstance().extension = extension; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/eppcommon/PresenceMarker.java b/java/com/google/domain/registry/model/eppcommon/PresenceMarker.java new file mode 100644 index 000000000..9dc3fd5ef --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/PresenceMarker.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlTransient; + +/** + * Used as the value of a tag that is present in the XML but has no children or value. + *

+ * When placed in a field "foo", this will correctly unmarshal from both {@code } and + * {@code }, and will unmarshal always to {@code }. + */ +@Embed +public class PresenceMarker extends ImmutableObject implements Serializable { + @XmlTransient + boolean marked = true; +} diff --git a/java/com/google/domain/registry/model/eppcommon/ProtocolDefinition.java b/java/com/google/domain/registry/model/eppcommon/ProtocolDefinition.java new file mode 100644 index 000000000..56ad31406 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/ProtocolDefinition.java @@ -0,0 +1,113 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import static com.google.common.collect.Maps.uniqueIndex; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.domain.allocate.AllocateCreateExtension; +import com.google.domain.registry.model.domain.fee.FeeCheckExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.domain.rgp.RgpUpdateExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsCreateExtension; +import com.google.domain.registry.model.eppinput.EppInput.CommandExtension; + +import java.util.EnumSet; +import java.util.Set; + +import javax.xml.bind.annotation.XmlSchema; + +/** Constants that define the EPP protocol version we support. */ +public class ProtocolDefinition { + public static final String VERSION = "1.0"; + + public static final String LANGUAGE = "en"; + + public static final Set SUPPORTED_OBJECT_SERVICES = ImmutableSet.of( + "urn:ietf:params:xml:ns:host-1.0", + "urn:ietf:params:xml:ns:domain-1.0", + "urn:ietf:params:xml:ns:contact-1.0"); + + /** Enums repesenting valid service extensions that are recognized by the server. */ + public enum ServiceExtension { + LAUNCH_EXTENSION_1_0(LaunchCreateExtension.class, true), + REDEMPTION_GRACE_PERIOD_1_0(RgpUpdateExtension.class, true), + SECURE_DNS_1_1(SecDnsCreateExtension.class, true), + FEE_0_6(FeeCheckExtension.class, true), + ALLOCATE_1_0(AllocateCreateExtension.class, false), + METADATA_1_0(MetadataExtension.class, false); + + private String uri; + private boolean visible; + + ServiceExtension(Class clazz, boolean visible) { + this.uri = getCommandExtensionUri(clazz); + this.visible = visible; + } + + public String getUri() { + return uri; + } + + public boolean getVisible() { + return visible; + } + + /** Returns the namespace URI of the command extension class. */ + public static String getCommandExtensionUri(Class clazz) { + return clazz.getPackage().getAnnotation(XmlSchema.class).namespace(); + } + } + + /** Converts a service extension enum to its URI. */ + private static final Function TO_URI_FUNCTION = + new Function() { + @Override + public String apply(ServiceExtension serviceExtension) { + return serviceExtension.getUri(); + }}; + + /** This stores a map from URI back to the service extension enum. */ + private static final ImmutableMap serviceExtensionByUri = + uniqueIndex(EnumSet.allOf(ServiceExtension.class), TO_URI_FUNCTION); + + /** Returns the service extension enum associated with a URI, or null if none are associated. */ + public static ServiceExtension getServiceExtensionFromUri(String uri) { + return serviceExtensionByUri.get(uri); + } + + /** A set of all the visible extension URIs. */ + private static final ImmutableSet visibleServiceExtensionUris = + FluentIterable.from(EnumSet.allOf(ServiceExtension.class)) + .filter( + new Predicate() { + @Override + public boolean apply(ServiceExtension serviceExtension) { + return serviceExtension.getVisible(); + } + }) + .transform(TO_URI_FUNCTION) + .toSet(); + + /** Return the set of all visible service extension URIs. */ + public static ImmutableSet getVisibleServiceExtensionUris() { + return visibleServiceExtensionUris; + } +} diff --git a/java/com/google/domain/registry/model/eppcommon/StatusValue.java b/java/com/google/domain/registry/model/eppcommon/StatusValue.java new file mode 100644 index 000000000..24ddc7a14 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/StatusValue.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import static com.google.common.base.CaseFormat.LOWER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Strings.nullToEmpty; + +import com.google.common.base.Converter; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.translators.EnumToAttributeAdapter.EppEnum; +import com.google.domain.registry.model.translators.StatusValueAdapter; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Represents an EPP status value for hosts, contacts, and domains, as defined in RFC 5731, 5732, + * and 5733. The values here are the union of all 3 sets of status values. + * + *

The RFCs define extra optional metadata (language and message) that we don't use and therefore + * don't model. + * + *

Note that {@code StatusValue.LINKED} should never be stored. Rather, it should be calculated + * on the fly whenever needed using an eventually consistent query (i.e. in info flows). + * + * @see "https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en" + */ +@XmlJavaTypeAdapter(StatusValueAdapter.class) +public enum StatusValue implements EppEnum { + + CLIENT_DELETE_PROHIBITED, + CLIENT_HOLD, + CLIENT_RENEW_PROHIBITED, + CLIENT_TRANSFER_PROHIBITED, + CLIENT_UPDATE_PROHIBITED, + INACTIVE, + LINKED, + OK, + PENDING_CREATE, + PENDING_DELETE, + PENDING_TRANSFER, + PENDING_UPDATE, + SERVER_DELETE_PROHIBITED, + SERVER_HOLD, + SERVER_RENEW_PROHIBITED, + SERVER_TRANSFER_PROHIBITED, + SERVER_UPDATE_PROHIBITED; + + private final String xmlName = UPPER_UNDERSCORE.to(LOWER_CAMEL, name()); + + @Override + public String getXmlName() { + return xmlName; + } + + public boolean isClientSettable() { + // This is the actual definition of client-settable statuses; see RFC5730 section 2.3. + return xmlName.startsWith("client"); + } + + public boolean isChargedStatus() { + return xmlName.startsWith("server") && xmlName.endsWith("Prohibited"); + } + + public static StatusValue fromXmlName(String xmlName) { + return StatusValue.valueOf(LOWER_CAMEL.to(UPPER_UNDERSCORE, nullToEmpty(xmlName))); + } + + /** Stripped down version of the legacy format of status values for migration purposes. */ + // TODO(b/25442343): Remove this. + @Embed + public static class LegacyStatusValue extends ImmutableObject { + String xmlStatusValue; + } + + /** Converter between the old and new formats. */ + // TODO(b/25442343): Remove this. + public static final Converter LEGACY_CONVERTER = + new Converter() { + @Override + protected LegacyStatusValue doForward(StatusValue status) { + LegacyStatusValue legacyStatus = new LegacyStatusValue(); + legacyStatus.xmlStatusValue = status.xmlName; + return legacyStatus; + } + + @Override + protected StatusValue doBackward(LegacyStatusValue legacyStatus) { + return StatusValue.fromXmlName(legacyStatus.xmlStatusValue); + } + }; +} diff --git a/java/com/google/domain/registry/model/eppcommon/Trid.java b/java/com/google/domain/registry/model/eppcommon/Trid.java new file mode 100644 index 000000000..fbe3d35d7 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/Trid.java @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppcommon; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.io.BaseEncoding; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import java.nio.ByteBuffer; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +/** + * "A {@code TRID} (transaction identifier) element containing the transaction identifier assigned + * by the server to the command for which the response is being returned. The transaction identifier + * is formed using the {@code clTRID} associated with the command if supplied by the client and a + * {@code svTRID} (server transaction identifier) that is assigned by and unique to the server." + */ +@Embed +@XmlType(propOrder = {"clientTransactionId", "serverTransactionId"}) +public class Trid extends ImmutableObject { + + private static final String SERVER_ID = getServerId(); + private static final AtomicLong COUNTER = new AtomicLong(); + + /** Creates a unique id for this server instance, as a base64 encoded UUID. */ + private static String getServerId() { + UUID uuid = UUID.randomUUID(); + ByteBuffer buffer = ByteBuffer.allocate(16); + buffer.asLongBuffer() + .put(0, uuid.getMostSignificantBits()) + .put(1, uuid.getLeastSignificantBits()); + return BaseEncoding.base64().encode(buffer.array()); + } + + /** The server transaction id. */ + @XmlElement(name = "svTRID", namespace = "urn:ietf:params:xml:ns:epp-1.0") + String serverTransactionId; + + /** The client transaction id, if provided by the client, otherwise null. */ + @XmlElement(name = "clTRID", namespace = "urn:ietf:params:xml:ns:epp-1.0") + String clientTransactionId; + + public String getServerTransactionId() { + return serverTransactionId; + } + + public String getClientTransactionId() { + return clientTransactionId; + } + + public static Trid create(String clientTransactionId) { + Trid instance = new Trid(); + instance.clientTransactionId = clientTransactionId; + // The server id can be at most 64 characters. The SERVER_ID is at most 22 characters (128 bits + // in base64), plus the dash. That leaves 41 characters, so we just append the counter in hex. + instance.serverTransactionId = String.format("%s-%x", SERVER_ID, COUNTER.incrementAndGet()); + return instance; + } + + @VisibleForTesting + public static Trid create(String clientTransactionId, String serverTransactionId) { + Trid instance = new Trid(); + instance.clientTransactionId = clientTransactionId; + instance.serverTransactionId = serverTransactionId; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/eppcommon/package-info.java b/java/com/google/domain/registry/model/eppcommon/package-info.java new file mode 100644 index 000000000..10b1134b4 --- /dev/null +++ b/java/com/google/domain/registry/model/eppcommon/package-info.java @@ -0,0 +1,22 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +/** + * Domain Registry datastore model common/shared classes. + *

+ * This package is intended to hold classes which are shared across multiple XML namespaces. As + * such, no default namespace is declared in this package, and all objects in this package should be + * declared XmlTransient. + */ +package com.google.domain.registry.model.eppcommon; diff --git a/java/com/google/domain/registry/model/eppinput/EppInput.java b/java/com/google/domain/registry/model/eppinput/EppInput.java new file mode 100644 index 000000000..137ba974b --- /dev/null +++ b/java/com/google/domain/registry/model/eppinput/EppInput.java @@ -0,0 +1,361 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppinput; + +import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactCommand; +import com.google.domain.registry.model.domain.DomainCommand; +import com.google.domain.registry.model.domain.allocate.AllocateCreateExtension; +import com.google.domain.registry.model.domain.fee.FeeCheckExtension; +import com.google.domain.registry.model.domain.fee.FeeCreateExtension; +import com.google.domain.registry.model.domain.fee.FeeInfoExtension; +import com.google.domain.registry.model.domain.fee.FeeRenewExtension; +import com.google.domain.registry.model.domain.fee.FeeTransferExtension; +import com.google.domain.registry.model.domain.fee.FeeUpdateExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateExtension; +import com.google.domain.registry.model.domain.launch.LaunchDeleteExtension; +import com.google.domain.registry.model.domain.launch.LaunchInfoExtension; +import com.google.domain.registry.model.domain.launch.LaunchUpdateExtension; +import com.google.domain.registry.model.domain.metadata.MetadataExtension; +import com.google.domain.registry.model.domain.rgp.RgpUpdateExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsCreateExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsUpdateExtension; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck; +import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand; +import com.google.domain.registry.model.host.HostCommand; + +import java.util.List; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** This class represents the root EPP XML element for input. */ +@XmlRootElement(name = "epp") +public class EppInput extends ImmutableObject { + + @XmlElements({ + @XmlElement(name = "command", type = CommandWrapper.class), + @XmlElement(name = "hello", type = Hello.class) }) + CommandWrapper commandWrapper; + + public CommandWrapper getCommandWrapper() { + return commandWrapper; + } + + public String getCommandName() { + return (commandWrapper instanceof Hello) + ? Hello.class.getSimpleName() + : commandWrapper.getCommand().getClass().getSimpleName(); + } + + public ImmutableList getTargetIds() { + InnerCommand innerCommand = commandWrapper.getCommand(); + ResourceCommand resourceCommand = innerCommand instanceof ResourceCommandWrapper + ? ((ResourceCommandWrapper) innerCommand).getResourceCommand() + : null; + if (resourceCommand instanceof SingleResourceCommand) { + return ImmutableList.of(((SingleResourceCommand) resourceCommand).getTargetId()); + } else if (resourceCommand instanceof ResourceCheck) { + return ((ResourceCheck) resourceCommand).getTargetIds(); + } else { + return ImmutableList.of(); + } + } + + /** Get the extension based on type, or null. If there are multiple, it chooses the first. */ + public E getSingleExtension(Class clazz) { + return FluentIterable.from(getCommandWrapper().getExtensions()).filter(clazz).first().orNull(); + } + + /** A tag that goes inside of an EPP {@literal }. */ + public static class InnerCommand extends ImmutableObject {} + + /** A command that has an extension inside of it. */ + public static class ResourceCommandWrapper extends InnerCommand { + @XmlElementRefs({ + @XmlElementRef(type = ContactCommand.Check.class), + @XmlElementRef(type = ContactCommand.Create.class), + @XmlElementRef(type = ContactCommand.Delete.class), + @XmlElementRef(type = ContactCommand.Info.class), + @XmlElementRef(type = ContactCommand.Transfer.class), + @XmlElementRef(type = ContactCommand.Update.class), + @XmlElementRef(type = DomainCommand.Check.class), + @XmlElementRef(type = DomainCommand.Create.class), + @XmlElementRef(type = DomainCommand.Delete.class), + @XmlElementRef(type = DomainCommand.Info.class), + @XmlElementRef(type = DomainCommand.Renew.class), + @XmlElementRef(type = DomainCommand.Transfer.class), + @XmlElementRef(type = DomainCommand.Update.class), + @XmlElementRef(type = HostCommand.Check.class), + @XmlElementRef(type = HostCommand.Create.class), + @XmlElementRef(type = HostCommand.Delete.class), + @XmlElementRef(type = HostCommand.Info.class), + @XmlElementRef(type = HostCommand.Update.class)}) + ResourceCommand resourceCommand; + + public ResourceCommand getResourceCommand() { + return resourceCommand; + } + } + + /** Epp envelope wrapper for check on some objects. */ + public static class Check extends ResourceCommandWrapper {} + + /** Epp envelope wrapper for create of some object. */ + public static class Create extends ResourceCommandWrapper {} + + /** Epp envelope wrapper for delete of some object. */ + public static class Delete extends ResourceCommandWrapper {} + + /** Epp envelope wrapper for info on some object. */ + public static class Info extends ResourceCommandWrapper {} + + /** Epp envelope wrapper for renewing some object. */ + public static class Renew extends ResourceCommandWrapper {} + + /** Epp envelope wrapper for transferring some object. */ + public static class Transfer extends ResourceCommandWrapper { + + /** Enum of the possible values for the "op" attribute in transfer flows. */ + public enum TransferOp { + @XmlEnumValue("approve") + APPROVE, + + @XmlEnumValue("cancel") + CANCEL, + + @XmlEnumValue("query") + QUERY, + + @XmlEnumValue("reject") + REJECT, + + @XmlEnumValue("request") + REQUEST; + } + + @XmlAttribute(name = "op") + TransferOp transferOp; + + public TransferOp getTransferOp() { + return transferOp; + } + } + + /** Epp envelope wrapper for update of some object. */ + public static class Update extends ResourceCommandWrapper {} + + /** Poll command. */ + public static class Poll extends InnerCommand { + + /** Enum of the possible values for the "op" attribute in poll commands. */ + public enum PollOp { + + /** Acknowledge a poll message was received. */ + @XmlEnumValue("ack") + ACK, + + /** Request the next poll message. */ + @XmlEnumValue("req") + REQUEST; + } + + @XmlAttribute + PollOp op; + + @XmlAttribute + String msgID; + + public PollOp getPollOp() { + return op; + } + + public String getMessageId() { + return msgID; + } + } + + /** Login command. */ + public static class Login extends InnerCommand { + @XmlElement(name = "clID") + String clientId; + + @XmlElement(name = "pw") + String password; + + @XmlElement(name = "newPW") + String newPassword; + + Options options; + + @XmlElement(name = "svcs") + Services services; + + public String getClientId() { + return clientId; + } + + public String getPassword() { + return password; + } + + public String getNewPassword() { + return newPassword; + } + + public Options getOptions() { + return options; + } + + public Services getServices() { + return services; + } + } + + /** Logout command. */ + public static class Logout extends InnerCommand {} + + /** The "command" element that holds an actual command inside of it. */ + @XmlType(propOrder = {"command", "extension", "clTRID"}) + public static class CommandWrapper extends ImmutableObject { + @XmlElements({ + @XmlElement(name = "check", type = Check.class), + @XmlElement(name = "create", type = Create.class), + @XmlElement(name = "delete", type = Delete.class), + @XmlElement(name = "info", type = Info.class), + @XmlElement(name = "login", type = Login.class), + @XmlElement(name = "logout", type = Logout.class), + @XmlElement(name = "poll", type = Poll.class), + @XmlElement(name = "renew", type = Renew.class), + @XmlElement(name = "transfer", type = Transfer.class), + @XmlElement(name = "update", type = Update.class) }) + InnerCommand command; + + /** Zero or more command extensions. */ + @XmlElementRefs({ + @XmlElementRef(type = AllocateCreateExtension.class), + @XmlElementRef(type = FeeCheckExtension.class), + @XmlElementRef(type = FeeCreateExtension.class), + @XmlElementRef(type = FeeInfoExtension.class), + @XmlElementRef(type = FeeRenewExtension.class), + @XmlElementRef(type = FeeTransferExtension.class), + @XmlElementRef(type = FeeUpdateExtension.class), + @XmlElementRef(type = LaunchCheckExtension.class), + @XmlElementRef(type = LaunchCreateExtension.class), + @XmlElementRef(type = LaunchDeleteExtension.class), + @XmlElementRef(type = LaunchInfoExtension.class), + @XmlElementRef(type = LaunchUpdateExtension.class), + @XmlElementRef(type = MetadataExtension.class), + @XmlElementRef(type = RgpUpdateExtension.class), + @XmlElementRef(type = SecDnsCreateExtension.class), + @XmlElementRef(type = SecDnsUpdateExtension.class) }) + @XmlElementWrapper + List extension; + + String clTRID; + + public String getClTrid() { + return clTRID; + } + + public InnerCommand getCommand() { + return command; + } + + public ImmutableList getExtensions() { + return nullToEmptyImmutableCopy(extension); + } + } + + /** Empty type to represent the empty "hello" command. */ + public static class Hello extends CommandWrapper {} + + /** An options object inside of {@link Login}. */ + public static class Options extends ImmutableObject { + @XmlJavaTypeAdapter(VersionAdapter.class) + String version; + + @XmlElement(name = "lang") + String language; + + public String getLanguage() { + return language; + } + } + + /** A services object inside of {@link Login}. */ + public static class Services extends ImmutableObject { + @XmlElement(name = "objURI") + Set objectServices; + + @XmlElementWrapper(name = "svcExtension") + @XmlElement(name = "extURI") + Set serviceExtensions; + + public ImmutableSet getObjectServices() { + return nullSafeImmutableCopy(objectServices); + } + + public ImmutableSet getServiceExtensions() { + return nullSafeImmutableCopy(serviceExtensions); + } + } + + /** + * RFC 5730 says we should check the version and return special error code 2100 if it isn't + * what we support, but it also specifies a schema that only allows 1.0 in the version field, so + * any other version doesn't validate. As a result, if we didn't do this here it would throw a + * {@code SyntaxErrorException} when it failed to validate. + * + * @see "http://tools.ietf.org/html/rfc5730#page-41" + */ + public static class VersionAdapter extends XmlAdapter { + @Override + public String unmarshal(String version) throws Exception { + if (!"1.0".equals(version)) { + throw new WrongProtocolVersionException(); + } + return version; + } + + @Override + public String marshal(String ignored) throws Exception { + throw new UnsupportedOperationException(); + } + } + + /** Marker interface for types that can go in the {@link CommandWrapper#extension} field. */ + public interface CommandExtension {} + + /** Exception to throw if encountering a protocol version other than "1.0". */ + public static class WrongProtocolVersionException extends Exception {} +} diff --git a/java/com/google/domain/registry/model/eppinput/ResourceCommand.java b/java/com/google/domain/registry/model/eppinput/ResourceCommand.java new file mode 100644 index 000000000..0703c451d --- /dev/null +++ b/java/com/google/domain/registry/model/eppinput/ResourceCommand.java @@ -0,0 +1,152 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppinput; + +import static com.google.common.collect.Sets.intersection; +import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.Buildable.Builder; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppcommon.AuthInfo; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import java.util.List; +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlTransient; + +/** Commands for EPP resources. */ +public interface ResourceCommand { + + /** + * A command for a single {@link EppResource}. + *

+ * In general commands should extend {@link AbstractSingleResourceCommand} instead of + * implementing this directly, but "Create" commands can't do that since they need to inherit + * from a base class that gives them all of the resource's fields. The domain "Info" command + * also can't do that since it's "name" field is overloaded with a "hosts" attribute. + */ + public interface SingleResourceCommand extends ResourceCommand { + String getTargetId(); + + AuthInfo getAuthInfo(); + } + + /** Abstract implementation of {@link ResourceCommand}. */ + @XmlTransient + public abstract static class AbstractSingleResourceCommand extends ImmutableObject + implements SingleResourceCommand { + @XmlElements({ + @XmlElement(name = "id"), + @XmlElement(name = "name") }) + String targetId; + + @Override + public String getTargetId() { + return targetId; + } + + @Override + public AuthInfo getAuthInfo() { + return null; + } + } + + /** A check command for an {@link EppResource}. */ + @XmlTransient + public static class ResourceCheck extends ImmutableObject implements ResourceCommand { + @XmlElements({ + @XmlElement(name = "id"), + @XmlElement(name = "name") }) + List targetUniqueIds; + + public ImmutableList getTargetIds() { + return nullSafeImmutableCopy(targetUniqueIds); + } + } + + /** A create command, or the inner change (as opposed to add or remove) part of an update. */ + public interface ResourceCreateOrChange> { + public abstract void applyTo(B builder); + } + + /** + * An update command for an {@link EppResource}. + * + * @param the add-remove type + * @param the change type + */ + @XmlTransient + public abstract static class ResourceUpdate + , + C extends ResourceCreateOrChange> extends AbstractSingleResourceCommand { + + /** Part of an update command that specifies set values to add or remove. */ + @XmlTransient + public abstract static class AddRemove extends ImmutableObject { + @XmlElement(name = "status") + Set statusValues; + + public ImmutableSet getStatusValues() { + return nullToEmptyImmutableCopy(statusValues); + } + } + + protected abstract C getNullableInnerChange(); + + protected abstract A getNullableInnerAdd(); + + protected abstract A getNullableInnerRemove(); + + // Don't use MoreObjects.firstNonNull in these method because it will result in an unneeded + // reflective instantiation when the object isn't null. + + public C getInnerChange() { + C change = getNullableInnerChange(); + return change == null ? new TypeInstantiator(getClass()){}.instantiate() : change; + } + + public A getInnerAdd() { + A add = getNullableInnerAdd(); + return add == null ? new TypeInstantiator(getClass()){}.instantiate() : add; + } + + public A getInnerRemove() { + A remove = getNullableInnerRemove(); + return remove == null ? new TypeInstantiator(getClass()){}.instantiate() : remove; + } + + public void applyTo(B builder) throws AddRemoveSameValueException { + getInnerChange().applyTo(builder); + if (!intersection(getInnerAdd().getStatusValues(), getInnerRemove().getStatusValues()) + .isEmpty()) { + throw new AddRemoveSameValueException(); + } + builder.addStatusValues(getInnerAdd().getStatusValues()); + builder.removeStatusValues(getInnerRemove().getStatusValues()); + } + } + + /** Exception for adding and removing the same value in {@link ResourceUpdate#applyTo}. */ + public static class AddRemoveSameValueException extends Exception {} +} diff --git a/java/com/google/domain/registry/model/eppinput/package-info.java b/java/com/google/domain/registry/model/eppinput/package-info.java new file mode 100644 index 000000000..e43206bf6 --- /dev/null +++ b/java/com/google/domain/registry/model/eppinput/package-info.java @@ -0,0 +1,27 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:epp-1.0", + xmlns = @XmlNs(prefix = "", namespaceURI = "urn:ietf:params:xml:ns:epp-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +package com.google.domain.registry.model.eppinput; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; + diff --git a/java/com/google/domain/registry/model/eppoutput/CheckData.java b/java/com/google/domain/registry/model/eppoutput/CheckData.java new file mode 100644 index 000000000..c3bbbc2b5 --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/CheckData.java @@ -0,0 +1,167 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** The "chkDataType" complex type. */ +@XmlTransient +public abstract class CheckData extends ImmutableObject implements ResponseData { + + /** The check responses. We must explicitly list the namespaced versions of {@link Check}. */ + @XmlElements({ + @XmlElement( + name = "cd", namespace = "urn:ietf:params:xml:ns:contact-1.0", type = ContactCheck.class), + @XmlElement( + name = "cd", namespace = "urn:ietf:params:xml:ns:domain-1.0", type = DomainCheck.class), + @XmlElement( + name = "cd", namespace = "urn:ietf:params:xml:ns:host-1.0", type = HostCheck.class)}) + ImmutableList checks; + + protected static T init(T instance, ImmutableList checks) { + instance.checks = checks; + return instance; + } + + public ImmutableList getChecks() { + return checks; + } + + /** The response for a check on a single resource. */ + @XmlTransient + public static class Check extends ImmutableObject { + /** An element containing the name or id and availability of a resource. */ + @XmlElements({ + @XmlElement(name = "name", type = CheckName.class), + @XmlElement(name = "id", type = CheckID.class)}) + CheckNameOrID nameOrId; + + /** A message explaining the availability of this resource. */ + String reason; + + protected static T init(T instance, CheckNameOrID nameOrId, String reason) { + instance.nameOrId = nameOrId; + instance.reason = reason; + return instance; + } + } + + /** + * The "checkNameType" and "checkIDType" types. + *

+ * Although these are specified in the Epp extension RFCs and not in RFC 5730, which implies that + * they should be implemented per-extension, all of RFCs 5731, 5732 and 5733 define them + * identically except for the namespace and some slightly renamed fields, allowing us to share + * some code between the different extensions. + */ + public abstract static class CheckNameOrID extends ImmutableObject { + /** Whether the resource is available. */ + @XmlAttribute + boolean avail; + + /** The name of the resource being checked. */ + @XmlValue + String value; + + public boolean getAvail() { + return avail; + } + + protected static T init(T instance, boolean avail, String value) { + instance.avail = avail; + instance.value = value; + return instance; + } + } + + /** The name for a resource in a check response. */ + public static class CheckName extends CheckNameOrID { + protected static CheckName create(boolean avail, String name) { + return init(new CheckName(), avail, name); + } + } + + /** The id for a resource in a check response. */ + public static class CheckID extends CheckNameOrID { + protected static CheckID create(boolean avail, String id) { + return init(new CheckID(), avail, id); + } + } + + /** A version with contact namespacing. */ + @XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0") + public static class ContactCheck extends Check { + public static ContactCheck create(boolean avail, String id, String reason) { + return init(new ContactCheck(), CheckID.create(avail, id), reason); + } + } + + /** A version with domain namespacing. */ + @XmlType(namespace = "urn:ietf:params:xml:ns:domain-1.0") + public static class DomainCheck extends Check { + public static DomainCheck create(boolean avail, String name, String reason) { + return init(new DomainCheck(), CheckName.create(avail, name), reason); + } + + public CheckName getName() { + return (CheckName) nameOrId; + } + + public String getReason() { + return reason; + } + } + + /** A version with host namespacing. */ + @XmlType(namespace = "urn:ietf:params:xml:ns:host-1.0") + public static class HostCheck extends Check { + public static HostCheck create(boolean avail, String name, String reason) { + return init(new HostCheck(), CheckName.create(avail, name), reason); + } + } + + /** A version with contact namespacing. */ + @XmlRootElement(name = "chkData", namespace = "urn:ietf:params:xml:ns:contact-1.0") + public static class ContactCheckData extends CheckData { + public static ContactCheckData create(ImmutableList checks) { + return init(new ContactCheckData(), checks); + } + } + + /** A version with domain namespacing. */ + @XmlRootElement(name = "chkData", namespace = "urn:ietf:params:xml:ns:domain-1.0") + public static class DomainCheckData extends CheckData { + public static DomainCheckData create(ImmutableList checks) { + return init(new DomainCheckData(), checks); + } + } + /** A version with host namespacing. */ + @XmlRootElement(name = "chkData", namespace = "urn:ietf:params:xml:ns:host-1.0") + public static class HostCheckData extends CheckData { + public static HostCheckData create(ImmutableList checks) { + return init(new HostCheckData(), checks); + } + } +} diff --git a/java/com/google/domain/registry/model/eppoutput/CreateData.java b/java/com/google/domain/registry/model/eppoutput/CreateData.java new file mode 100644 index 000000000..4132908fd --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/CreateData.java @@ -0,0 +1,84 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import com.google.domain.registry.model.eppoutput.Response.ResponseData; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** The {@link ResponseData} returned when creating a resource. */ +@XmlTransient +public abstract class CreateData implements ResponseData { + + @XmlElement(name = "crDate") + protected DateTime creationDate; + + /** An acknowledgment message indicating that a contact was created. */ + @XmlRootElement(name = "creData", namespace = "urn:ietf:params:xml:ns:contact-1.0") + @XmlType(propOrder = {"id", "creationDate"}, namespace = "urn:ietf:params:xml:ns:contact-1.0") + public static class ContactCreateData extends CreateData { + + String id; + + public static ContactCreateData create(String id, DateTime creationDate) { + ContactCreateData instance = new ContactCreateData(); + instance.id = id; + instance.creationDate = creationDate; + return instance; + } + } + + /** An acknowledgment message indicating that a domain was created. */ + @XmlRootElement(name = "creData", namespace = "urn:ietf:params:xml:ns:domain-1.0") + @XmlType( + propOrder = {"name", "creationDate", "expirationDate"}, + namespace = "urn:ietf:params:xml:ns:domain-1.0") + public static class DomainCreateData extends CreateData { + + String name; + + @XmlElement(name = "exDate") + DateTime expirationDate; + + public static DomainCreateData create( + String name, DateTime creationDate, DateTime expirationDate) { + DomainCreateData instance = new DomainCreateData(); + instance.name = name; + instance.creationDate = creationDate; + instance.expirationDate = expirationDate; + return instance; + } + } + + /** An acknowledgment message indicating that a host was created. */ + @XmlRootElement(name = "creData", namespace = "urn:ietf:params:xml:ns:host-1.0") + @XmlType(propOrder = {"name", "creationDate"}, namespace = "urn:ietf:params:xml:ns:host-1.0") + public static class HostCreateData extends CreateData { + + String name; + + public static HostCreateData create(String name, DateTime creationDate) { + HostCreateData instance = new HostCreateData(); + instance.name = name; + instance.creationDate = creationDate; + return instance; + } + } +} diff --git a/java/com/google/domain/registry/model/eppoutput/EppOutput.java b/java/com/google/domain/registry/model/eppoutput/EppOutput.java new file mode 100644 index 000000000..92e970043 --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/EppOutput.java @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +/** This class represents the root EPP XML element for output. */ +@XmlRootElement(name = "epp") +public class EppOutput extends ImmutableObject { + @XmlElements({ + @XmlElement(name = "response", type = Response.class), + @XmlElement(name = "greeting", type = Greeting.class) }) + ResponseOrGreeting responseOrGreeting; + + public static EppOutput create(ResponseOrGreeting responseOrGreeting) { + EppOutput instance = new EppOutput(); + instance.responseOrGreeting = responseOrGreeting; + return instance; + } + + @VisibleForTesting + public boolean isSuccess() { + return ((Response) responseOrGreeting).result.getCode().isSuccess(); + } + + public Response getResponse() { + return (Response) responseOrGreeting; + } + + public boolean isResponse() { + return responseOrGreeting instanceof Response; + } + + /** Marker interface for types allowed inside of an {@link EppOutput}. */ + public interface ResponseOrGreeting {} +} diff --git a/java/com/google/domain/registry/model/eppoutput/Greeting.java b/java/com/google/domain/registry/model/eppoutput/Greeting.java new file mode 100644 index 000000000..6f6a41388 --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/Greeting.java @@ -0,0 +1,88 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import static org.joda.time.DateTimeZone.UTC; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppcommon.PresenceMarker; +import com.google.domain.registry.model.eppcommon.ProtocolDefinition; +import com.google.domain.registry.model.eppoutput.EppOutput.ResponseOrGreeting; + +import org.joda.time.DateTime; + +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; + +/** + * A greeting, defined in {@link "http://tools.ietf.org/html/rfc5730"}. + *

+ * It would be nice to make this a singleton, but we need the {@link #svDate} field to stay current. + */ +public class Greeting extends ImmutableObject implements ResponseOrGreeting { + + String svID = "Charleston Road Registry"; + DateTime svDate = DateTime.now(UTC); + + /** This is never changed, so it might as well be static for efficiency. */ + @XmlElement + static SvcMenu svcMenu = new SvcMenu(); + + /** This is never changed, so it might as well be static for efficiency. */ + @XmlElement + static Dcp dcp = new Dcp(); + + static class SvcMenu extends ImmutableObject { + String version = ProtocolDefinition.VERSION; + String lang = ProtocolDefinition.LANGUAGE; + Set objURI = ProtocolDefinition.SUPPORTED_OBJECT_SERVICES; + + @XmlElementWrapper(name = "svcExtension") + Set extURI = ProtocolDefinition.getVisibleServiceExtensionUris(); + } + + static class Dcp extends ImmutableObject { + Access access = new Access(); + Statement statement = new Statement(); + } + + static class Access extends ImmutableObject { + PresenceMarker all = new PresenceMarker(); + } + + static class Statement extends ImmutableObject { + Purpose purpose = new Purpose(); + Recipient recipient = new Recipient(); + Retention retention = new Retention(); + } + + static class Purpose extends ImmutableObject { + PresenceMarker admin = new PresenceMarker(); + PresenceMarker prov = new PresenceMarker(); + } + + static class Recipient extends ImmutableObject { + PresenceMarker ours = new PresenceMarker(); + + @XmlElement(name = "public") + PresenceMarker publicObj = new PresenceMarker(); + } + + static class Retention extends ImmutableObject { + PresenceMarker indefinite = new PresenceMarker(); + } +} diff --git a/java/com/google/domain/registry/model/eppoutput/Response.java b/java/com/google/domain/registry/model/eppoutput/Response.java new file mode 100644 index 000000000..ec06a2af6 --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/Response.java @@ -0,0 +1,202 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainRenewData; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.fee.FeeCheckResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeCreateResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeDeleteResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeInfoResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeRenewResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeTransferResponseExtension; +import com.google.domain.registry.model.domain.fee.FeeUpdateResponseExtension; +import com.google.domain.registry.model.domain.launch.LaunchCheckResponseExtension; +import com.google.domain.registry.model.domain.launch.LaunchCreateResponseExtension; +import com.google.domain.registry.model.domain.launch.LaunchInfoResponseExtension; +import com.google.domain.registry.model.domain.rgp.RgpInfoExtension; +import com.google.domain.registry.model.domain.secdns.SecDnsInfoExtension; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.eppoutput.CheckData.ContactCheckData; +import com.google.domain.registry.model.eppoutput.CheckData.DomainCheckData; +import com.google.domain.registry.model.eppoutput.CheckData.HostCheckData; +import com.google.domain.registry.model.eppoutput.CreateData.ContactCreateData; +import com.google.domain.registry.model.eppoutput.CreateData.DomainCreateData; +import com.google.domain.registry.model.eppoutput.CreateData.HostCreateData; +import com.google.domain.registry.model.eppoutput.EppOutput.ResponseOrGreeting; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.poll.MessageQueueInfo; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; +import com.google.domain.registry.model.transfer.TransferResponse.ContactTransferResponse; +import com.google.domain.registry.model.transfer.TransferResponse.DomainTransferResponse; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * The Response class represents an EPP response message. + * + *

From the RFC: "An EPP server responds to a client command by returning a response to the + * client. EPP commands are atomic, so a command will either succeed completely or fail completely. + * Success and failure results MUST NOT be mixed." + * + * @see "http://tools.ietf.org/html/rfc5730#section-2.6" + */ +@XmlType(propOrder = {"result", "messageQueueInfo", "resData", "extensions", "trid"}) +public class Response extends ImmutableObject implements ResponseOrGreeting { + + /** The TRID associated with this response. */ + @XmlElement(name = "trID") + Trid trid; + + /** The command result. The RFC allows multiple failure results, but we always return one. */ + Result result; + + /** + * The time the command that created this response was executed. + *

+ * This is for logging purposes only and is not returned to the user. + */ + @XmlTransient + DateTime executionTime; + + /** + * The repository id of a new object if this is a create response, or null. + *

+ * This is for logging purposes only and is not returned to the user. + */ + @XmlTransient + String createdRepoId; + + /** + * Information about messages queued for retrieval. This may appear in response to any EPP message + * (if messages are queued), but in practice this will only be set in response to a poll request. + */ + @XmlElement(name = "msgQ") + MessageQueueInfo messageQueueInfo; + + /** Zero or more response "resData" results. */ + @XmlElementRefs({ + @XmlElementRef(type = ContactResource.class), + @XmlElementRef(type = DomainApplication.class), + @XmlElementRef(type = DomainResource.class), + @XmlElementRef(type = HostResource.class), + @XmlElementRef(type = ContactCheckData.class), + @XmlElementRef(type = ContactCreateData.class), + @XmlElementRef(type = ContactPendingActionNotificationResponse.class), + @XmlElementRef(type = ContactTransferResponse.class), + @XmlElementRef(type = DomainCheckData.class), + @XmlElementRef(type = DomainCreateData.class), + @XmlElementRef(type = DomainPendingActionNotificationResponse.class), + @XmlElementRef(type = DomainRenewData.class), + @XmlElementRef(type = DomainTransferResponse.class), + @XmlElementRef(type = HostCheckData.class), + @XmlElementRef(type = HostCreateData.class)}) + @XmlElementWrapper + ImmutableList resData; + + /** Zero or more response extensions. */ + @XmlElementRefs({ + @XmlElementRef(type = FeeCheckResponseExtension.class), + @XmlElementRef(type = FeeCreateResponseExtension.class), + @XmlElementRef(type = FeeDeleteResponseExtension.class), + @XmlElementRef(type = FeeInfoResponseExtension.class), + @XmlElementRef(type = FeeRenewResponseExtension.class), + @XmlElementRef(type = FeeTransferResponseExtension.class), + @XmlElementRef(type = FeeUpdateResponseExtension.class), + @XmlElementRef(type = LaunchCheckResponseExtension.class), + @XmlElementRef(type = LaunchCreateResponseExtension.class), + @XmlElementRef(type = LaunchInfoResponseExtension.class), + @XmlElementRef(type = RgpInfoExtension.class), + @XmlElementRef(type = SecDnsInfoExtension.class) }) + @XmlElementWrapper(name = "extension") + ImmutableList extensions; + + public DateTime getExecutionTime() { + return executionTime; + } + + public String getCreatedRepoId() { + return createdRepoId; + } + + public ImmutableList getResponseData() { + return resData; + } + + public ImmutableList getExtensions() { + return extensions; + } + + public Result getResult() { + return result; + } + + /** Marker interface for types that can go in the {@link #resData} field. */ + public interface ResponseData {} + + /** Marker interface for types that can go in the {@link #extensions} field. */ + public interface ResponseExtension {} + + /** Builder for {@link Response} because it is immutable. */ + public static class Builder extends Buildable.Builder { + public Builder setTrid(Trid trid) { + getInstance().trid = trid; + return this; + } + + public Builder setResult(Result result) { + getInstance().result = result; + return this; + } + + public Builder setMessageQueueInfo(MessageQueueInfo messageQueueInfo) { + getInstance().messageQueueInfo = messageQueueInfo; + return this; + } + + public Builder setExecutionTime(DateTime executionTime) { + getInstance().executionTime = executionTime; + return this; + } + + public Builder setCreatedRepoId(String createdRepoId) { + getInstance().createdRepoId = createdRepoId; + return this; + } + + public Builder setResData(ImmutableList resData) { + getInstance().resData = resData; + return this; + } + + public Builder setExtensions(ImmutableList extensions) { + getInstance().extensions = extensions; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/eppoutput/Result.java b/java/com/google/domain/registry/model/eppoutput/Result.java new file mode 100644 index 000000000..6351e5175 --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/Result.java @@ -0,0 +1,190 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.eppoutput; + +import static com.google.domain.registry.util.XmlEnumUtils.enumToXml; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnumValue; + +/** + * "If the command was processed successfully, only one {@code Result} element MUST be returned. If + * the command was not processed successfully, multiple {@code Result} elements MAY be returned to + * document failure conditions." + */ +public class Result extends ImmutableObject { + + /** + * "EPP result codes are based on the theory of reply codes described in section 4.2.1 of + * [RFC5321]. EPP uses four decimal digits to describe the success or failure of each EPP command. + * Each of the digits of the reply have special significance." + * + * "The first digit denotes command success or failure. The second digit denotes the response + * category, such as command syntax or security. The third and fourth digits provide explicit + * response detail within each response category." + */ + public enum Code { + @XmlEnumValue("1000") + Success("Command completed successfully"), + + @XmlEnumValue("1001") + SuccessWithActionPending("Command completed successfully; action pending"), + + @XmlEnumValue("1300") + SuccessWithNoMessages("Command completed successfully; no messages"), + + @XmlEnumValue("1301") + SuccessWithAckMessage("Command completed successfully; ack to dequeue"), + + @XmlEnumValue("1500") + SuccessAndClose("Command completed successfully; ending session"), + + @XmlEnumValue("2000") + UnknownCommand("Unknown command"), + + @XmlEnumValue("2001") + SyntaxError("Command syntax error"), + + @XmlEnumValue("2002") + CommandUseError("Command use error"), + + @XmlEnumValue("2003") + RequiredParameterMissing("Required parameter missing"), + + @XmlEnumValue("2004") + ParameterValueRangeError("Parameter value range error"), + + @XmlEnumValue("2005") + ParameterValueSyntaxError("Parameter value syntax error"), + + @XmlEnumValue("2100") + UnimplementedProtocolVersion("Unimplemented protocol version"), + + @XmlEnumValue("2101") + UnimplementedCommand("Unimplemented command"), + + @XmlEnumValue("2102") + UnimplementedOption("Unimplemented option"), + + @XmlEnumValue("2103") + UnimplementedExtension("Unimplemented extension"), + + @XmlEnumValue("2200") + AuthenticationError("Authentication error"), + + @XmlEnumValue("2201") + AuthorizationError("Authorization error"), + + @XmlEnumValue("2202") + InvalidAuthorizationInformationError("Invalid authorization information"), + + @XmlEnumValue("2300") + ObjectPendingTransfer("Object pending transfer"), + + @XmlEnumValue("2301") + ObjectNotPendingTransfer("Object not pending transfer"), + + @XmlEnumValue("2302") + ObjectExists("Object exists"), + + @XmlEnumValue("2303") + ObjectDoesNotExist("Object does not exist"), + + @XmlEnumValue("2304") + StatusProhibitsOperation("Object status prohibits operation"), + + @XmlEnumValue("2305") + AssociationProhibitsOperation("Object association prohibits operation"), + + @XmlEnumValue("2306") + ParameterValuePolicyError("Parameter value policy error"), + + @XmlEnumValue("2307") + UnimplementedObjectService("Unimplemented object service"), + + @XmlEnumValue("2400") + CommandFailed("Command failed"), + + @XmlEnumValue("2501") + AuthenticationErrorClosingConnection("Authentication error; server closing connection"); + + /** A four-digit (positive) number that describes the success or failure of the command. */ + public final int code; + + /** A human-readable description of the response code. */ + public final String msg; + + /** + * An RFC 4646 language code. + * + * @see "http://tools.ietf.org/html/rfc4646" + */ + public final String msgLang; + + /** @param msg a human-readable description of the response code; required. */ + Code(String msg) { + this.code = Integer.parseInt(enumToXml(this)); + Preconditions.checkArgument( + (int) Math.log10(code) == 3, + "Response code must be a four-digit (positive) number."); + this.msg = Preconditions.checkNotNull(msg, "A message must be specified."); + this.msgLang = "en"; // All of our messages are English. + } + + /** @return true iff the response code is in the 1xxx category, representing success. */ + public boolean isSuccess() { + return code < 2000; + } + + @Override + public String toString() { + return String.format("{code:'%s', msg:'%s', msgLang:'%s'}", code, msg, msgLang); + } + } + + /** The result code for this result. This is always present. */ + @XmlAttribute + Code code; + + /** An explanation of the result code. */ + String msg; + + public Code getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public static Result create(Code code, String msg) { + Result instance = new Result(); + instance.code = code; + // If no message was set, pick up a default message from the Code enum. + Preconditions.checkState( + !code.isSuccess() || msg == null, + "Only error result codes may have a message"); + instance.msg = MoreObjects.firstNonNull(msg, code.msg); + return instance; + } + + public static Result create(Code code) { + return create(code, null); + } +} diff --git a/java/com/google/domain/registry/model/eppoutput/package-info.java b/java/com/google/domain/registry/model/eppoutput/package-info.java new file mode 100644 index 000000000..80a2b3ccf --- /dev/null +++ b/java/com/google/domain/registry/model/eppoutput/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:epp-1.0", + xmlns = @XmlNs(prefix = "", namespaceURI = "urn:ietf:params:xml:ns:epp-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.eppoutput; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/export/LogsExportCursor.java b/java/com/google/domain/registry/model/export/LogsExportCursor.java new file mode 100644 index 000000000..5d387f51d --- /dev/null +++ b/java/com/google/domain/registry/model/export/LogsExportCursor.java @@ -0,0 +1,82 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.export; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.common.CrossTldSingleton; +import com.google.domain.registry.model.common.PersistedRangeLong; + +import com.googlecode.objectify.annotation.Entity; + +import java.util.List; +import java.util.Set; + +/** A saved cursor of exported log records so far. */ +@Entity +public class LogsExportCursor extends CrossTldSingleton implements Buildable { + + /** + * A set of timestamp ranges (expressesd in microseconds since the epoch) that have been exported + * to GCS. + */ + Set exportedRanges; + + /** + * A list of filenames that are pending import into bigquery. Files may not have been imported + * into bigquery on previous iterations if there are gaps in the exported ranges. + */ + List filesPendingImport; + + public ImmutableSet getExportedRanges() { + return nullToEmptyImmutableCopy(exportedRanges); + } + + public ImmutableList getFilesPendingImport() { + return nullToEmptyImmutableCopy(filesPendingImport); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link LogsExportCursor} objects, since they are immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(LogsExportCursor instance) { + super(instance); + } + + public Builder setExportedRanges(ImmutableSet exportedRanges) { + getInstance().exportedRanges = exportedRanges; + return this; + } + + public Builder setFilesPendingImport(ImmutableList filesPendingImport) { + getInstance().filesPendingImport = filesPendingImport; + return this; + } + + @Override + public LogsExportCursor build() { + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/generate_field_exposer.sh b/java/com/google/domain/registry/model/generate_field_exposer.sh new file mode 100755 index 000000000..e9e0d45f5 --- /dev/null +++ b/java/com/google/domain/registry/model/generate_field_exposer.sh @@ -0,0 +1,36 @@ +#!/bin/sh - +# +# Copyright 2016 Google Inc. All rights reserved. +# +# 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. + +# Generate a FieldExposer for a given package + +printf "package com.google.domain.registry.model"\ +`echo $1 | sed -e 's/.*\/model\(.*\).FieldExposer\.java/\1/' -e 's/\//./g'`";\ +\n\n\ +import com.google.domain.registry.model.AbstractFieldExposer;\n\n\ +import java.lang.reflect.Field;\n\n\ +/** A helper that exposes package-private fields in this package for reflective lookup. */\n\ +public class FieldExposer extends AbstractFieldExposer {\n\ + public Object getFieldValue(Object instance, Field field) throws IllegalAccessException {\n\ + return field.get(instance);\n\ + }\n\n\ + public void setFieldValue(Object instance, Field field, Object value)\n\ + throws IllegalAccessException {\n\ + field.set(instance, value);\n\ + }\n\n\ + public void setAccessible(Field field) {\n\ + field.setAccessible(true);\n\ + }\n\ +}\n" diff --git a/java/com/google/domain/registry/model/generate_field_exposer_registry.sh b/java/com/google/domain/registry/model/generate_field_exposer_registry.sh new file mode 100755 index 000000000..dca5f9779 --- /dev/null +++ b/java/com/google/domain/registry/model/generate_field_exposer_registry.sh @@ -0,0 +1,31 @@ +#!/bin/sh - +# +# Copyright 2016 Google Inc. All rights reserved. +# +# 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. + +# Generate a FieldExposer for a given package + +printf "package com.google.domain.registry.model;\n\n\ +import com.google.domain.registry.model.AbstractFieldExposer;\n\n\ +import com.google.common.collect.ImmutableList;\n\n\ +/** A registry of all {@link AbstractFieldExposer} impls. */\n\ +class FieldExposerRegistry {\n\ + static ImmutableList getFieldExposers() {\n\ + return ImmutableList.of(\n" +for FILE in $@; do + echo $FILE | sed \ + -e 's/\(.*\).java/ new com.google.domain.registry.model.\1()/' \ + -e 's/\//./g' +done +printf " }\n}\n" diff --git a/java/com/google/domain/registry/model/host/HostCommand.java b/java/com/google/domain/registry/model/host/HostCommand.java new file mode 100644 index 000000000..0eabe8618 --- /dev/null +++ b/java/com/google/domain/registry/model/host/HostCommand.java @@ -0,0 +1,143 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.host; + +import static com.google.common.collect.Sets.intersection; +import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange; +import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate; + +import java.net.InetAddress; +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** A collection of {@link HostResource} commands. */ +public class HostCommand { + + /** The fields on "chgType" from {@link "http://tools.ietf.org/html/rfc5732"}. */ + @XmlTransient + abstract static class HostCreateOrChange extends AbstractSingleResourceCommand + implements ResourceCreateOrChange { + /** IP Addresses for this host. Can be null if this is an external host. */ + @XmlElement(name = "addr") + Set inetAddresses; + + public ImmutableSet getInetAddresses() { + return nullSafeImmutableCopy(inetAddresses); + } + + public String getFullyQualifiedHostName() { + return getTargetId(); + } + + @Override + public void applyTo(HostResource.Builder builder) { + if (getFullyQualifiedHostName() != null) { + builder.setFullyQualifiedHostName(getFullyQualifiedHostName()); + } + if (getInetAddresses() != null) { + builder.setInetAddresses(getInetAddresses()); + } + } + } + + /** + * A create command for a {@link HostResource}, mapping "createType" from + * {@link "http://tools.ietf.org/html/rfc5732"}. + */ + @XmlType(propOrder = {"targetId", "inetAddresses" }) + @XmlRootElement + public static class Create + extends HostCreateOrChange implements ResourceCreateOrChange {} + + /** A delete command for a {@link HostResource}. */ + @XmlRootElement + public static class Delete extends AbstractSingleResourceCommand {} + + /** An info request for a {@link HostResource}. */ + @XmlRootElement + public static class Info extends AbstractSingleResourceCommand {} + + /** A check request for {@link HostResource}. */ + @XmlRootElement + public static class Check extends ResourceCheck {} + + /** An update to a {@link HostResource}. */ + @XmlRootElement + @XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"}) + public static class Update extends ResourceUpdate + { + + @XmlElement(name = "chg") + protected Change innerChange; + + @XmlElement(name = "add") + protected AddRemove innerAdd; + + @XmlElement(name = "rem") + protected AddRemove innerRemove; + + @Override + protected Change getNullableInnerChange() { + return innerChange; + } + + @Override + protected AddRemove getNullableInnerAdd() { + return innerAdd; + } + + @Override + protected AddRemove getNullableInnerRemove() { + return innerRemove; + } + + /** The add/remove type on a host update command. */ + @XmlType(propOrder = { "inetAddresses", "statusValues" }) + public static class AddRemove extends ResourceUpdate.AddRemove { + /** IP Addresses for this host. Can be null if this is an external host. */ + @XmlElement(name = "addr") + Set inetAddresses; + + public ImmutableSet getInetAddresses() { + return nullToEmptyImmutableCopy(inetAddresses); + } + } + + /** The inner change type on a host update command. */ + @XmlType(propOrder = {"targetId", "inetAddresses" }) + public static class Change extends HostCreateOrChange {} + + @Override + public void applyTo(HostResource.Builder builder) throws AddRemoveSameValueException { + super.applyTo(builder); + if (!intersection(getInnerAdd().getInetAddresses(), getInnerRemove().getInetAddresses()) + .isEmpty()) { + throw new AddRemoveSameValueException(); + } + builder.addInetAddresses(getInnerAdd().getInetAddresses()); + builder.removeInetAddresses(getInnerRemove().getInetAddresses()); + } + } +} diff --git a/java/com/google/domain/registry/model/host/HostResource.java b/java/com/google/domain/registry/model/host/HostResource.java new file mode 100644 index 000000000..7b59efcd3 --- /dev/null +++ b/java/com/google/domain/registry/model/host/HostResource.java @@ -0,0 +1,208 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.host; + +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.union; +import static com.google.domain.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; + +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +import java.net.InetAddress; +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * A persistable Host resource including mutable and non-mutable fields. + * + *

A host's {@link TransferData} is stored on the superordinate domain. Non-subordinate hosts + * don't carry a full set of TransferData; all they have is lastTransferTime. + */ +@XmlRootElement(name = "infData") +@XmlType(propOrder = { + "fullyQualifiedHostName", + "repoId", + "status", + "inetAddresses", + "currentSponsorClientId", + "creationClientId", + "creationTime", + "lastEppUpdateClientId", + "lastEppUpdateTime", + "lastTransferTime" }) +@Cache +@Entity +@ExternalMessagingName("host") +public class HostResource extends EppResource implements ForeignKeyedEppResource { + + /** + * Fully qualified hostname, which is a unique identifier for this host. + *

+ * This is only unique in the sense that for any given lifetime specified as the time range from + * (creationTime, deletionTime) there can only be one host in the datastore with this name. + * However, there can be many hosts with the same name and non-overlapping lifetimes. + */ + // TODO(b/25644770): Backfill this index. Until that's done, don't rely on it! + @Index + @XmlTransient + String fullyQualifiedHostName; + + /** IP Addresses for this host. Can be null if this is an external host. */ + @Index + @XmlTransient + Set inetAddresses; + + /** The superordinate domain of this host, or null if this is an external host. */ + @Index + @IgnoreSave(IfNull.class) + @XmlTransient + Ref superordinateDomain; + + /** + * The most recent time that the superordinate domain was changed, or null if this host is + * external. + */ + @XmlTransient + DateTime lastSuperordinateChange; + + @XmlElement(name = "name") + public String getFullyQualifiedHostName() { + return fullyQualifiedHostName; + } + + public Ref getSuperordinateDomain() { + return superordinateDomain; + } + + @XmlElement(name = "addr") + public ImmutableSet getInetAddresses() { + return nullToEmptyImmutableCopy(inetAddresses); + } + + public DateTime getLastSuperordinateChange() { + return lastSuperordinateChange; + } + + @Override + public String getForeignKey() { + return fullyQualifiedHostName; + } + + @Override + public HostResource cloneProjectedAtTime(DateTime now) { + Builder builder = this.asBuilder(); + projectResourceOntoBuilderAtTime(this, builder, now); + + if (superordinateDomain == null) { + // If this was a subordinate host to a domain that was being transferred, there might be a + // pending transfer still extant, so remove it. + builder.setTransferData(null).removeStatusValue(StatusValue.PENDING_TRANSFER); + } else { + // For hosts with superordinate domains, the client id, last transfer time, and transfer data + // need to be read off the domain projected to the correct time. + DomainResource domainAtTime = superordinateDomain.get().cloneProjectedAtTime(now); + builder.setCurrentSponsorClientId(domainAtTime.getCurrentSponsorClientId()); + // If the superordinate domain's last transfer time is what is relevant, because the host's + // superordinate domain was last changed less recently than the domain's last transfer, then + // use the last transfer time on the domain. + if (Optional.fromNullable(lastSuperordinateChange).or(START_OF_TIME) + .isBefore(Optional.fromNullable(domainAtTime.getLastTransferTime()).or(START_OF_TIME))) { + builder.setLastTransferTime(domainAtTime.getLastTransferTime()); + } + // Copy the transfer status and data from the superordinate domain onto the host, because the + // host's doesn't matter and the superordinate domain always has the canonical data. + TransferData domainTransferData = domainAtTime.getTransferData(); + if (TransferStatus.PENDING.equals(domainTransferData.getTransferStatus())) { + builder.addStatusValue(StatusValue.PENDING_TRANSFER); + } else { + builder.removeStatusValue(StatusValue.PENDING_TRANSFER); + } + builder.setTransferData(domainTransferData); + } + return builder.build(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link HostResource}, since it is immutable. */ + public static class Builder extends EppResource.Builder { + public Builder() {} + + private Builder(HostResource instance) { + super(instance); + } + + public Builder setFullyQualifiedHostName(String fullyQualifiedHostName) { + getInstance().fullyQualifiedHostName = fullyQualifiedHostName; + return this; + } + + public Builder setInetAddresses(ImmutableSet inetAddresses) { + getInstance().inetAddresses = inetAddresses; + return this; + } + + public Builder setLastSuperordinateChange(DateTime lastSuperordinateChange) { + getInstance().lastSuperordinateChange = lastSuperordinateChange; + return this; + } + + public Builder addInetAddresses(ImmutableSet inetAddresses) { + return setInetAddresses(ImmutableSet.copyOf( + union(getInstance().getInetAddresses(), inetAddresses))); + } + + public Builder removeInetAddresses(ImmutableSet inetAddresses) { + return setInetAddresses(ImmutableSet.copyOf( + difference(getInstance().getInetAddresses(), inetAddresses))); + } + + public Builder setSuperordinateDomain(Ref superordinateDomain) { + getInstance().superordinateDomain = superordinateDomain; + return this; + } + + @Override + public HostResource build() { + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/host/InetAddressAdapter.java b/java/com/google/domain/registry/model/host/InetAddressAdapter.java new file mode 100644 index 000000000..89b16ca02 --- /dev/null +++ b/java/com/google/domain/registry/model/host/InetAddressAdapter.java @@ -0,0 +1,69 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.host; + +import com.google.common.net.InetAddresses; + +import java.net.Inet6Address; +import java.net.InetAddress; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Used by JAXB to convert InetAddress objects to and from AddrType objects, which are the + * intermediate representations of IP addresses in EPP host commands. + */ +public final class InetAddressAdapter + extends XmlAdapter { + + /** + * Intermediate representation of an IP address on a host object. This object only exists + * temporarily until it is converted by JAXB to and from an InetAddress via this adapter. + */ + static class AddressShim { + @XmlValue + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String ipAddress; + + @XmlAttribute(name = "ip") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + String ipVersion; + } + + @Override + public AddressShim marshal(InetAddress inetAddress) { + AddressShim shim = new AddressShim(); + shim.ipAddress = InetAddresses.toAddrString(inetAddress); + shim.ipVersion = (inetAddress instanceof Inet6Address) ? "v6" : "v4"; + return shim; + } + + @Override + public InetAddress unmarshal(AddressShim shim) throws IpVersionMismatchException { + InetAddress inetAddress = InetAddresses.forString(shim.ipAddress); + // Enforce that "v6" is used iff the address is ipv6. (For ipv4, "v4" is allowed to be missing.) + if (inetAddress instanceof Inet6Address != "v6".equals(shim.ipVersion)) { + throw new IpVersionMismatchException(); + } + return inetAddress; + } + + /** Exception for when the specified type of an address (v4/v6) doesn't match its actual type. */ + public static class IpVersionMismatchException extends Exception {} +} diff --git a/java/com/google/domain/registry/model/host/package-info.java b/java/com/google/domain/registry/model/host/package-info.java new file mode 100644 index 000000000..dd4a295c9 --- /dev/null +++ b/java/com/google/domain/registry/model/host/package-info.java @@ -0,0 +1,34 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:host-1.0", + xmlns = @XmlNs(prefix = "host", namespaceURI = "urn:ietf:params:xml:ns:host-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapters({ + @XmlJavaTypeAdapter(UtcDateTimeAdapter.class), + @XmlJavaTypeAdapter(InetAddressAdapter.class)}) +package com.google.domain.registry.model.host; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; + diff --git a/java/com/google/domain/registry/model/index/DomainApplicationIndex.java b/java/com/google/domain/registry/model/index/DomainApplicationIndex.java new file mode 100644 index 000000000..4ea83c2a9 --- /dev/null +++ b/java/com/google/domain/registry/model/index/DomainApplicationIndex.java @@ -0,0 +1,132 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.index; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.isNullOrEmpty; +import static com.google.domain.registry.util.DateTimeUtils.latestOf; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.BackupGroupRoot; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.util.CollectionUtils; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +import org.joda.time.DateTime; + +import java.util.Set; + +import javax.annotation.Nullable; + +/** + * Entity for tracking all domain applications with a given fully qualified domain name. Since this + * resource is always kept up to date as additional domain applications are created, it is never + * necessary to query them explicitly from Datastore. + */ +@Entity +@Cache +public class DomainApplicationIndex extends BackupGroupRoot { + + @Id + String fullyQualifiedDomainName; + + /** + * A set of all domain applications with this fully qualified domain name. Never null or empty. + */ + Set> references; + + /** Returns a cloned list of all references on this index. */ + public ImmutableSet> getReferences() { + return ImmutableSet.copyOf(references); + } + + public String getFullyQualifiedDomainName() { + return fullyQualifiedDomainName; + } + + /** + * Creates a DomainApplicationIndex with the specified list of references. Only use this method + * for data migrations. You probably want {@link #createUpdatedInstance}. + */ + public static DomainApplicationIndex createWithSpecifiedReferences( + String fullyQualifiedDomainName, + ImmutableSet> references) { + checkArgument(!isNullOrEmpty(fullyQualifiedDomainName), + "fullyQualifiedDomainName must not be null or empty."); + checkArgument(!isNullOrEmpty(references), "References must not be null or empty."); + DomainApplicationIndex instance = new DomainApplicationIndex(); + instance.fullyQualifiedDomainName = fullyQualifiedDomainName; + instance.references = references; + return instance; + } + + public static Key createKey(DomainApplication application) { + return Key.create(DomainApplicationIndex.class, application.getFullyQualifiedDomainName()); + } + + /** + * Returns an iterable of all DomainApplications for the given fully qualified domain name that + * do not have a deletion time before the supplied DateTime. + */ + public static Iterable loadActiveApplicationsByDomainName( + String fullyQualifiedDomainName, DateTime now) { + DomainApplicationIndex index = load(fullyQualifiedDomainName); + if (index == null) { + return ImmutableSet.of(); + } + ImmutableSet.Builder apps = new ImmutableSet.Builder<>(); + for (DomainApplication app : ofy().load().refs(index.getReferences()).values()) { + DateTime forwardedNow = latestOf(now, app.getUpdateAutoTimestamp().getTimestamp()); + if (app.getDeletionTime().isAfter(forwardedNow)) { + apps.add(app.cloneProjectedAtTime(forwardedNow)); + } + } + return apps.build(); + } + + /** + * Returns the DomainApplicationIndex for the given fully qualified domain name. Note that this + * can return null if there are no domain applications for this fully qualified domain name. + */ + @Nullable + public static DomainApplicationIndex load(String fullyQualifiedDomainName) { + return ofy() + .load() + .type(DomainApplicationIndex.class) + .id(fullyQualifiedDomainName) + .now(); + } + + /** + * Saves a new DomainApplicationIndex for this resource or updates the existing one. This is + * the preferred method for creating an instance of DomainApplicationIndex because this performs + * the correct merging logic to add the given domain application to an existing index if there + * is one. + */ + public static DomainApplicationIndex createUpdatedInstance(DomainApplication application) { + DomainApplicationIndex existing = load(application.getFullyQualifiedDomainName()); + ImmutableSet> newReferences = CollectionUtils.union( + (existing == null ? ImmutableSet.>of() : existing.getReferences()), + Ref.create(application)); + return createWithSpecifiedReferences(application.getFullyQualifiedDomainName(), newReferences); + } +} diff --git a/java/com/google/domain/registry/model/index/EppResourceIndex.java b/java/com/google/domain/registry/model/index/EppResourceIndex.java new file mode 100644 index 000000000..4ca18ed83 --- /dev/null +++ b/java/com/google/domain/registry/model/index/EppResourceIndex.java @@ -0,0 +1,68 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.index; + +import static com.google.domain.registry.util.TypeUtils.instantiate; + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.BackupGroupRoot; +import com.google.domain.registry.model.EppResource; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; + +/** An index that allows for quick enumeration of all EppResource entities (e.g. via map reduce). */ +@Entity +public class EppResourceIndex extends BackupGroupRoot { + + @Id + String id; + + @Parent + Key bucket; + + Ref reference; + + @Index + String kind; + + public Ref getReference() { + return reference; + } + + @VisibleForTesting + public Key getBucket() { + return bucket; + } + + @VisibleForTesting + public static EppResourceIndex create( + Key bucket, Key resourceKey) { + EppResourceIndex instance = instantiate(EppResourceIndex.class); + instance.reference = Ref.create(resourceKey); + instance.kind = resourceKey.getKind(); + instance.id = resourceKey.getString(); // creates a web-safe key string + instance.bucket = bucket; + return instance; + } + + public static EppResourceIndex create(Key resourceKey) { + return create(EppResourceIndexBucket.getBucketKey(resourceKey), resourceKey); + } +} diff --git a/java/com/google/domain/registry/model/index/EppResourceIndexBucket.java b/java/com/google/domain/registry/model/index/EppResourceIndexBucket.java new file mode 100644 index 000000000..68144c10e --- /dev/null +++ b/java/com/google/domain/registry/model/index/EppResourceIndexBucket.java @@ -0,0 +1,66 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.index; + +import com.google.common.collect.ImmutableList; +import com.google.common.hash.Hashing; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.VirtualEntity; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +/** A virtual entity to represent buckets to which EppResourceIndex objects are randomly added. */ +@Entity +@VirtualEntity +public class EppResourceIndexBucket extends ImmutableObject { + + @Id + private long bucketId; + + /** + * Deterministic function that returns a bucket id based on the resource's roid. + * NB: At the moment, nothing depends on this being deterministic, so we have the ability to + * change the number of buckets and utilize a random distribution once we do. + */ + private static long getBucketIdFromEppResource(Key resourceKey) { + int numBuckets = RegistryEnvironment.get().config().getEppResourceIndexBucketCount(); + // IDs can't be 0, so add 1 to the hash. + return Hashing.consistentHash(resourceKey.getName().hashCode(), numBuckets) + 1; + } + + /** Gets a bucket key as a function of an EppResource to be indexed. */ + public static Key getBucketKey(Key resourceKey) { + return Key.create(EppResourceIndexBucket.class, getBucketIdFromEppResource(resourceKey)); + } + + /** Gets the specified numbered bucket key. */ + public static Key getBucketKey(int bucketId) { + return Key.create(EppResourceIndexBucket.class, bucketId); + } + + /** Returns the keys to all buckets. */ + public static Iterable> getAllBuckets() { + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + int numBuckets = RegistryEnvironment.get().config().getEppResourceIndexBucketCount(); + for (int bucketId = 1; bucketId <= numBuckets; bucketId++) { + builder.add(getBucketKey(bucketId)); + } + return builder.build(); + } +} diff --git a/java/com/google/domain/registry/model/index/ForeignKeyIndex.java b/java/com/google/domain/registry/model/index/ForeignKeyIndex.java new file mode 100644 index 000000000..6ba1fe1f6 --- /dev/null +++ b/java/com/google/domain/registry/model/index/ForeignKeyIndex.java @@ -0,0 +1,168 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.index; + +import static com.google.common.collect.Maps.filterValues; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.TypeUtils.instantiate; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.BackupGroupRoot; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; + +import org.joda.time.DateTime; + +import java.util.Map; + +/** + * Class to map a foreign key to the active instance of {@link EppResource} whose unique id matches + * the foreign key string. The instance is never deleted, but it is updated if a newer entity + * becomes the active entity. + */ +public abstract class ForeignKeyIndex extends BackupGroupRoot { + + /** The {@link ForeignKeyIndex} type for {@link ContactResource} entities. */ + @Cache + @Entity + public static class ForeignKeyContactIndex extends ForeignKeyIndex {} + + /** The {@link ForeignKeyIndex} type for {@link DomainResource} entities. */ + @Cache + @Entity + public static class ForeignKeyDomainIndex extends ForeignKeyIndex {} + + /** The {@link ForeignKeyIndex} type for {@link HostResource} entities. */ + @Cache + @Entity + public static class ForeignKeyHostIndex extends ForeignKeyIndex {} + + private static final Map< + Class, + Class>> RESOURCE_CLASS_TO_FKI_CLASS = + ImmutableMap., Class>>of( + ContactResource.class, ForeignKeyContactIndex.class, + DomainResource.class, ForeignKeyDomainIndex.class, + HostResource.class, ForeignKeyHostIndex.class); + + @Id + String foreignKey; + + /** + * The deletion time of this {@link ForeignKeyIndex}. + * + *

This will generally be equal to the deletion time of {@link #topReference}. However, in the + * case of a {@link HostResource} that was renamed, this field will hold the time of the rename. + */ + @Index + DateTime deletionTime; + + /** + * The referenced resource. + * + *

This field holds the only reference. It is named "topReference" for historical reasons. + */ + Ref topReference; + + public String getForeignKey() { + return foreignKey; + } + + public DateTime getDeletionTime() { + return deletionTime; + } + + public Ref getReference() { + return topReference; + } + + /** + * Create a {@link ForeignKeyIndex} instance for a resource, expiring at a specified time. + */ + public static ForeignKeyIndex create( + E resource, DateTime deletionTime) { + ForeignKeyIndex instance = instantiate(RESOURCE_CLASS_TO_FKI_CLASS.get(resource.getClass())); + instance.topReference = Ref.create(resource); + instance.foreignKey = resource.getForeignKey(); + instance.deletionTime = deletionTime; + return instance; + } + + /** Create a {@link ForeignKeyIndex} key for a resource. */ + public static Key> createKey(EppResource resource) { + return Key.create( + RESOURCE_CLASS_TO_FKI_CLASS.get(resource.getClass()), resource.getForeignKey()); + } + + /** + * Loads a reference to an {@link EppResource} from the datastore by foreign key. + * + *

Returns absent if no foreign key index with this foreign key was ever created, or if the + * most recently created foreign key index was deleted before time "now". This method does not + * actually check that the referenced resource actually exists. However, for normal epp resources, + * it is safe to assume that the referenced resource exists if the foreign key index does. + * + * @param clazz the resource type to load + * @param foreignKey id to match + * @param now the current logical time to use when checking for soft deletion of the foreign key + * index + */ + public static Ref loadAndGetReference( + Class clazz, String foreignKey, DateTime now) { + ForeignKeyIndex index = load(clazz, foreignKey, now); + return (index == null) ? null : index.getReference(); + } + + /** + * Load a {@link ForeignKeyIndex} by class and id string that is active at or after the specified + * moment in time. + * + *

This will return null if the {@link ForeignKeyIndex} doesn't exist or has been soft deleted. + */ + public static ForeignKeyIndex load( + Class clazz, String foreignKey, DateTime now) { + return load(clazz, ImmutableList.of(foreignKey), now).get(foreignKey); + } + + /** + * Load a list of {@link ForeignKeyIndex} instances by class and id strings that are active at or + * after the specified moment in time. + * + *

The returned map will omit any keys for which the {@link ForeignKeyIndex} doesn't exist or + * has been soft deleted. + */ + @SuppressWarnings("unchecked") + public static Map> load( + Class clazz, Iterable foreignKeys, final DateTime now) { + return (Map>) filterValues( + ofy().load().type(RESOURCE_CLASS_TO_FKI_CLASS.get(clazz)).ids(foreignKeys), + new Predicate>() { + @Override + public boolean apply(ForeignKeyIndex fki) { + return now.isBefore(fki.deletionTime); + }}); + } +} diff --git a/java/com/google/domain/registry/model/mark/CommonMarkContactFields.java b/java/com/google/domain/registry/model/mark/CommonMarkContactFields.java new file mode 100644 index 000000000..358b7fbf4 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/CommonMarkContactFields.java @@ -0,0 +1,74 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import com.google.domain.registry.model.ImmutableObject; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Common fields shared amongst all mark contact subclasses. + * + * @see MarkContact + * @see MarkHolder + */ +@XmlTransient +public class CommonMarkContactFields extends ImmutableObject { + + /** Name of the contact. */ + String name; + + /** Name of the contact's organization. */ + @XmlElement(name = "org") + String organization; + + /** Contact's address information. */ + @XmlElement(name = "addr") + MarkAddress address; + + /** Contact's voice telephone number. */ + MarkPhoneNumber voice; + + /** Contact's fax telephone number. */ + MarkPhoneNumber fax; + + /** Contact's email. */ + String email; + + public String getName() { + return name; + } + + public String getOrganization() { + return organization; + } + + public MarkAddress getAddress() { + return address; + } + + public MarkPhoneNumber getVoice() { + return voice; + } + + public MarkPhoneNumber getFax() { + return fax; + } + + public String getEmail() { + return email; + } +} diff --git a/java/com/google/domain/registry/model/mark/CommonMarkFields.java b/java/com/google/domain/registry/model/mark/CommonMarkFields.java new file mode 100644 index 000000000..d55380fd6 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/CommonMarkFields.java @@ -0,0 +1,84 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Common fields shared amongst all mark instances. + * + * @see CourtMark + * @see Trademark + * @see TreatyOrStatuteMark + */ +@XmlTransient +public abstract class CommonMarkFields extends ImmutableObject { + + /** + * The id of the mark. The value is a concatenation of the local identifier, followed by a hyphen, + * followed by the issuer identifier. + */ + String id; + + /** The mark text string. */ + String markName; + + /** Information about the holder of the mark. */ + @XmlElement(name = "holder") + List markHolders; + + /** Contact information for the representative of the mark registration. */ + @XmlElement(name = "contact") + List contacts; + + /** List of A-labels that correspond to the mark name. */ + @XmlElement(name = "label") + List labels; + + /** The full description of goods and services mentioned in the mark registration document. */ + String goodsAndServices; + + public String getId() { + return id; + } + + public String getMarkName() { + return markName; + } + + public ImmutableList getMarkHolders() { + return nullToEmptyImmutableCopy(markHolders); + } + + public ImmutableList getContacts() { + return nullToEmptyImmutableCopy(contacts); + } + + public ImmutableList getLabels() { + return nullToEmptyImmutableCopy(labels); + } + + public String getGoodsAndServices() { + return goodsAndServices; + } +} diff --git a/java/com/google/domain/registry/model/mark/CourtMark.java b/java/com/google/domain/registry/model/mark/CourtMark.java new file mode 100644 index 000000000..391f63295 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/CourtMark.java @@ -0,0 +1,66 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +/** Holds information about a mark derived from a court opinion. */ +@XmlType(propOrder = { + "id", + "markName", + "markHolders", + "contacts", + "labels", + "goodsAndServices", + "referenceNumber", + "protectionDate", + "countryCode", + "regions", + "courtName"}) +public class CourtMark extends ProtectedMark { + + /** The two-character code of the country where the court is located. */ + @XmlElement(name = "cc") + String countryCode; + + /** + * The name of a city, state, province, or other geographic region of the above country code in + * which the mark is protected. + */ + @XmlElement(name = "region") + List regions; + + /** The name of the court. */ + String courtName; + + public String getCountryCode() { + return countryCode; + } + + public ImmutableList getRegions() { + return nullToEmptyImmutableCopy(regions); + } + + public String getCourtName() { + return courtName; + } +} diff --git a/java/com/google/domain/registry/model/mark/Mark.java b/java/com/google/domain/registry/model/mark/Mark.java new file mode 100644 index 000000000..c736027e1 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/Mark.java @@ -0,0 +1,60 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Information about one or more marks. + *

+ * A mark is a term for a label with some sort of legally protected status. The most well known + * version is a registered trademark, but marks can also be derived from court opinions, treaties, + * or statutes. + */ +@XmlRootElement(name = "mark") +public class Mark extends ImmutableObject { + + /** Marks derived from a registered trademark. */ + @XmlElement(name = "trademark") + List trademarks; + + /** Marks dervied from a treaty or statue. */ + @XmlElement(name = "treatyOrStatute") + List treatyOrStatuteMarks; + + /** Marks dervied from a court opinion. */ + @XmlElement(name = "court") + List courtMarks; + + public ImmutableList getTrademarks() { + return nullToEmptyImmutableCopy(trademarks); + } + + public ImmutableList getTreatyOrStatuteMarks() { + return nullToEmptyImmutableCopy(treatyOrStatuteMarks); + } + + public ImmutableList getCourtMarks() { + return nullToEmptyImmutableCopy(courtMarks); + } +} diff --git a/java/com/google/domain/registry/model/mark/MarkAddress.java b/java/com/google/domain/registry/model/mark/MarkAddress.java new file mode 100644 index 000000000..1bdacc829 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/MarkAddress.java @@ -0,0 +1,32 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import com.google.domain.registry.model.eppcommon.Address; + +/** + * Mark Holder/Owner Address + *

+ * This class is embedded inside {@link CommonMarkContactFields} hold the address of a mark contact + * or holder. The fields are all defined in parent class {@link Address}, but the subclass is still + * necessary to pick up the mark namespace. + * + * @see CommonMarkContactFields + */ +public class MarkAddress extends Address { + + /** Builder for {@link MarkAddress}. */ + public static class Builder extends Address.Builder {} +} diff --git a/java/com/google/domain/registry/model/mark/MarkContact.java b/java/com/google/domain/registry/model/mark/MarkContact.java new file mode 100644 index 000000000..ad7a1a131 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/MarkContact.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; + +/** Contact information for the representative of the mark. */ +public class MarkContact extends CommonMarkContactFields { + + /** The type of the contact that represents the mark. */ + @XmlEnum + enum ContactType { + @XmlEnumValue("owner") + OWNER, + + @XmlEnumValue("agent") + AGENT, + + @XmlEnumValue("thirdParty") + THIRD_PARTY; + } + + @XmlAttribute + ContactType type; + + public ContactType getType() { + return type; + } +} diff --git a/java/com/google/domain/registry/model/mark/MarkHolder.java b/java/com/google/domain/registry/model/mark/MarkHolder.java new file mode 100644 index 000000000..236e9abbf --- /dev/null +++ b/java/com/google/domain/registry/model/mark/MarkHolder.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; + +/** Contact information for the holder of the mark. */ +public class MarkHolder extends CommonMarkContactFields { + + /** The type of the entitlement for the holder of the mark. */ + @XmlEnum + enum EntitlementType { + @XmlEnumValue("owner") + OWNER, + + @XmlEnumValue("assignee") + ASSIGNEE, + + @XmlEnumValue("licensee") + LICENSEE; + } + + @XmlAttribute + EntitlementType entitlement; + + public EntitlementType getEntitlementType() { + return entitlement; + } +} diff --git a/java/com/google/domain/registry/model/mark/MarkPhoneNumber.java b/java/com/google/domain/registry/model/mark/MarkPhoneNumber.java new file mode 100644 index 000000000..4cb3c5199 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/MarkPhoneNumber.java @@ -0,0 +1,32 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import com.google.domain.registry.model.eppcommon.PhoneNumber; + +/** + * Mark Holder/Owner Phone Number + *

+ * This class is embedded inside {@link CommonMarkContactFields} hold the phone number of a mark + * contact or holder. The fields are all defined in parent class {@link PhoneNumber}, but the + * subclass is still necessary to pick up the mark namespace. + * + * @see CommonMarkContactFields + */ +public class MarkPhoneNumber extends PhoneNumber { + + /** Builder for {@link MarkPhoneNumber}. */ + public static class Builder extends PhoneNumber.Builder {} +} diff --git a/java/com/google/domain/registry/model/mark/MarkProtection.java b/java/com/google/domain/registry/model/mark/MarkProtection.java new file mode 100644 index 000000000..9d6afd889 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/MarkProtection.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.ImmutableObject; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; + +/** A country and region of a country where a mark is protected. */ +public class MarkProtection extends ImmutableObject { + + /** The two-character code of the country where the mark is protected. */ + @XmlElement(name = "cc") + String countryCode; + + /** + * The name of a city, state, province, or other geographic region of the above country code in + * which the mark is protected. + */ + String region; + + /** The two-character codes of the countries of this ruling. */ + @XmlElement(name = "ruling") + List rulingCountryCodes; + + public String getCountryCode() { + return countryCode; + } + + public String getRegion() { + return region; + } + + public ImmutableList getRulingCountryCodes() { + return nullToEmptyImmutableCopy(rulingCountryCodes); + } +} diff --git a/java/com/google/domain/registry/model/mark/ProtectedMark.java b/java/com/google/domain/registry/model/mark/ProtectedMark.java new file mode 100644 index 000000000..a83af29c3 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/ProtectedMark.java @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** Common fields for {@link CourtMark} and {@link TreatyOrStatuteMark}. */ +@XmlTransient +public abstract class ProtectedMark extends CommonMarkFields { + /** The date of protection of the mark. */ + @XmlElement(name = "proDate") + DateTime protectionDate; + + /** + * The reference number of the court's opinion for a court mark, or the number of the mark of the + * treaty or statute. + */ + @XmlElement(name = "refNum") + String referenceNumber; + + public DateTime getProtectionDate() { + return protectionDate; + } + + public String getReferenceNumber() { + return referenceNumber; + } +} diff --git a/java/com/google/domain/registry/model/mark/Trademark.java b/java/com/google/domain/registry/model/mark/Trademark.java new file mode 100644 index 000000000..5a7a8183b --- /dev/null +++ b/java/com/google/domain/registry/model/mark/Trademark.java @@ -0,0 +1,99 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; + +import org.joda.time.DateTime; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +/** Holds information about a registered trademark. */ +@XmlType(propOrder = { + "id", + "markName", + "markHolders", + "contacts", + "jurisdiction", + "markClasses", + "labels", + "goodsAndServices", + "applicationId", + "applicationDate", + "registrationNumber", + "registrationDate", + "expirationDate"}) +public class Trademark extends CommonMarkFields { + + /** Two character code of the jurisdiction where the mark was registered. */ + String jurisdiction; + + /** Nice Classification numbers of the mark. */ + @XmlElement(name = "class") + List markClasses; + + /** The trademark application id registered in the trademark office. */ + @XmlElement(name = "apId") + String applicationId; + + /** The date that the trademark was applied for. */ + @XmlElement(name = "apDate") + DateTime applicationDate; + + /** The trademark registration number registered in the trademark office. */ + @XmlElement(name = "regNum") + String registrationNumber; + + /** The date the trademark was registered. */ + @XmlElement(name = "regDate") + DateTime registrationDate; + + /** Expiration date of the trademark. */ + @XmlElement(name = "exDate") + DateTime expirationDate; + + public String getJurisdiction() { + return jurisdiction; + } + + public ImmutableList getMarkClasses() { + return nullToEmptyImmutableCopy(markClasses); + } + + public String getApplicationId() { + return applicationId; + } + + public DateTime getApplicationDate() { + return applicationDate; + } + + public String getRegistrationNumber() { + return registrationNumber; + } + + public DateTime getRegistrationDate() { + return registrationDate; + } + + public DateTime getExpirationDate() { + return expirationDate; + } +} diff --git a/java/com/google/domain/registry/model/mark/TreatyOrStatuteMark.java b/java/com/google/domain/registry/model/mark/TreatyOrStatuteMark.java new file mode 100644 index 000000000..f5ac087b7 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/TreatyOrStatuteMark.java @@ -0,0 +1,65 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.mark; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableList; + +import org.joda.time.DateTime; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +/** Information about a mark derived from a treaty or statute. */ +@XmlType(propOrder = { + "id", + "markName", + "markHolders", + "contacts", + "markProtections", + "labels", + "goodsAndServices", + "referenceNumber", + "protectionDate", + "title", + "executionDate"}) +public class TreatyOrStatuteMark extends ProtectedMark { + + /** A list of countries and region of the country where the mark is protected. */ + @XmlElement(name = "protection") + List markProtections; + + /** The title of the treaty or statute. */ + String title; + + /** Execution date of the treaty or statute. */ + @XmlElement(name = "execDate") + DateTime executionDate; + + public ImmutableList getMarkProtections() { + return nullToEmptyImmutableCopy(markProtections); + } + + public String getTitle() { + return title; + } + + public DateTime getExecutionDate() { + return executionDate; + } +} diff --git a/java/com/google/domain/registry/model/mark/package-info.java b/java/com/google/domain/registry/model/mark/package-info.java new file mode 100644 index 000000000..ffe81f150 --- /dev/null +++ b/java/com/google/domain/registry/model/mark/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:mark-1.0", + xmlns = @XmlNs(prefix = "mark", namespaceURI = "urn:ietf:params:xml:ns:mark-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.mark; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/ofy/AugmentedDeleter.java b/java/com/google/domain/registry/model/ofy/AugmentedDeleter.java new file mode 100644 index 000000000..8d42bd131 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/AugmentedDeleter.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.domain.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; +import static com.googlecode.objectify.ObjectifyService.ofy; +import static java.util.Arrays.asList; + +import com.google.common.base.Functions; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Iterables; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Result; +import com.googlecode.objectify.cmd.DeleteType; +import com.googlecode.objectify.cmd.Deleter; + +import java.util.Arrays; + +/** + * A Deleter that forwards to {@code ofy().delete()}, but can be augmented via subclassing to + * do custom processing on the keys to be deleted prior to their deletion. + */ +abstract class AugmentedDeleter implements Deleter { + private final Deleter delegate = ofy().delete(); + + /** Extension method to allow this Deleter to do extra work prior to the actual delete. */ + protected abstract void handleDeletion(Iterable> keys); + + @Override + public Result entities(Iterable entities) { + handleDeletion(Iterables.transform(entities, OBJECTS_TO_KEYS)); + return delegate.entities(entities); + } + + @Override + public Result entities(Object... entities) { + handleDeletion(FluentIterable.from(asList(entities)).transform(OBJECTS_TO_KEYS)); + return delegate.entities(entities); + } + + @Override + public Result entity(Object entity) { + handleDeletion(Arrays.>asList(Key.create(entity))); + return delegate.entity(entity); + } + + @Override + public Result key(Key key) { + handleDeletion(Arrays.>asList(key)); + return delegate.keys(key); + } + + @Override + public Result keys(Iterable> keys) { + // Magic to convert the type Iterable> (a family of types which allows for + // homogeneous iterables of a fixed Key type, e.g. List>, and is convenient for + // callers) into the type Iterable> (a concrete type of heterogeneous keys, which is + // convenient for users). We do this by passing each key through the identity function + // parameterized for Key, which erases any homogeneous typing on the iterable. + // See: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104 + Iterable> retypedKeys = Iterables.transform(keys, Functions.>identity()); + handleDeletion(retypedKeys); + return delegate.keys(keys); + } + + @Override + public Result keys(Key... keys) { + handleDeletion(Arrays.asList(keys)); + return delegate.keys(keys); + } + + /** Augmenting this gets ugly; you can always just use keys(Key.create(...)) instead. */ + @Override + public DeleteType type(Class clazz) { + throw new UnsupportedOperationException(); + } +} diff --git a/java/com/google/domain/registry/model/ofy/AugmentedSaver.java b/java/com/google/domain/registry/model/ofy/AugmentedSaver.java new file mode 100644 index 000000000..99331a140 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/AugmentedSaver.java @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.appengine.api.datastore.Entity; +import com.google.common.collect.ImmutableList; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Result; +import com.googlecode.objectify.cmd.Saver; + +import java.util.Arrays; +import java.util.Map; + +/** + * A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to + * do custom processing on the entities to be saved prior to their saving. + */ +abstract class AugmentedSaver implements Saver { + private final Saver delegate = ofy().save(); + + /** Extension method to allow this Saver to do extra work prior to the actual save. */ + protected abstract void handleSave(Iterable entities); + + @Override + public Result, E>> entities(Iterable entities) { + handleSave(entities); + return delegate.entities(entities); + } + + @Override + @SafeVarargs + public final Result, E>> entities(E... entities) { + handleSave(Arrays.asList(entities)); + return delegate.entities(entities); + } + + @Override + public Result> entity(E entity) { + handleSave(ImmutableList.of(entity)); + return delegate.entity(entity); + } + + @Override + public Entity toEntity(Object pojo) { + // No call to the extension method, since toEntity() doesn't do any actual saving. + return delegate.toEntity(pojo); + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLogBucket.java b/java/com/google/domain/registry/model/ofy/CommitLogBucket.java new file mode 100644 index 000000000..bf60c3f1b --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLogBucket.java @@ -0,0 +1,177 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.DiscreteDomain.integers; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Range; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.util.NonFinalForTesting; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +import org.joda.time.DateTime; + +import java.util.Random; + +/** + * Root for a random commit log bucket. + * + *

This is used to shard {@link CommitLogManifest} objects into + * {@link com.google.domain.registry.config.RegistryConfig#getCommitLogBucketCount() N} entity + * groups. This increases transaction throughput, while maintaining the ability to perform + * strongly-consistent ancestor queries. + * + * @see "https://cloud.google.com/appengine/articles/scaling/contention" + */ +@Entity +@NotBackedUp(reason = Reason.COMMIT_LOGS) +public class CommitLogBucket extends ImmutableObject implements Buildable { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** Ranges from 1 to {@link #getNumBuckets()}, inclusive; starts at 1 since IDs can't be 0. */ + @Id + long bucketNum; + + /** The timestamp of the last {@link CommitLogManifest} written to this bucket. */ + DateTime lastWrittenTime = START_OF_TIME; + + public int getBucketNum() { + return (int) bucketNum; + } + + public DateTime getLastWrittenTime() { + return lastWrittenTime; + } + + /** + * Returns the key for the specified bucket ID. + * + *

Always use this method in preference to manually creating bucket keys, since manual keys + * are not guaranteed to have a valid bucket ID number. + */ + public static Key getBucketKey(int num) { + checkArgument(getBucketIdRange().contains(num), "%s not in %s", num, getBucketIdRange()); + return getBucketKeyUnsafe(num); + } + + private static Key getBucketKeyUnsafe(int num) { + return Key.create(CommitLogBucket.class, num); + } + + /** Returns a sorted set of all the possible numeric bucket IDs. */ + public static ImmutableSortedSet getBucketIds() { + return ContiguousSet.create(getBucketIdRange(), integers()); + } + + private static int getNumBuckets() { + return ENVIRONMENT.config().getCommitLogBucketCount(); + } + + private static Range getBucketIdRange() { + return Range.closed(1, getNumBuckets()); + } + + /** Returns an arbitrary numeric bucket ID. Default behavior is randomly chosen IDs. */ + public static int getArbitraryBucketId() { + return bucketIdSupplier.get(); + } + + /** + * Supplier of valid bucket IDs to use for {@link #getArbitraryBucketId()}. + * + *

Default supplier is one that returns bucket IDs via uniform random selection, but can be + * overridden in tests that rely on predictable bucket assignment for commit logs. + */ + @NonFinalForTesting + private static Supplier bucketIdSupplier = + new Supplier() { + private final Random random = new Random(); + + @Override + public Integer get() { + return random.nextInt(getNumBuckets()) + 1; // Add 1 since IDs can't be 0. + } + }; + + /** Returns the loaded bucket for the given key, or a new object if the bucket doesn't exist. */ + public static CommitLogBucket loadBucket(Key bucketKey) { + CommitLogBucket bucket = ofy().load().key(bucketKey).now(); + return bucket == null + ? new CommitLogBucket.Builder().setBucketNum(bucketKey.getId()).build() + : bucket; + } + + /** Returns the set of all loaded commit log buckets, filling in missing buckets with new ones. */ + public static ImmutableSet loadAllBuckets() { + ofy().load().keys(getAllBucketKeys()); // Load all buckets into session cache at once. + ImmutableSet.Builder allBuckets = new ImmutableSet.Builder<>(); + for (Key key : getAllBucketKeys()) { + allBuckets.add(loadBucket(key)); + } + return allBuckets.build(); + } + + /** Returns all commit log bucket keys, in ascending order by bucket ID. */ + public static ImmutableSet> getAllBucketKeys() { + return FluentIterable.from(getBucketIds()) + .transform(new Function>() { + @Override + public Key apply(Integer bucketId) { + return getBucketKeyUnsafe(bucketId); + }}) + .toSet(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link CommitLogBucket} since it is immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + public Builder(CommitLogBucket instance) { + super(instance); + } + + public Builder setBucketNum(long bucketNum) { + getInstance().bucketNum = bucketNum; + return this; + } + + public Builder setLastWrittenTime(DateTime lastWrittenTime) { + getInstance().lastWrittenTime = lastWrittenTime; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLogCheckpoint.java b/java/com/google/domain/registry/model/ofy/CommitLogCheckpoint.java new file mode 100644 index 000000000..88d3bf9fd --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLogCheckpoint.java @@ -0,0 +1,98 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Entity representing a point-in-time consistent view of datastore, based on commit logs. + * + *

Conceptually, this entity consists of two pieces of information: the checkpoint "wall" time + * and a set of bucket checkpoint times. The former is the ID for this checkpoint (constrained + * to be unique upon checkpoint creation) and also represents the approximate wall time of the + * consistent datastore view this checkpoint represents. The latter is really a mapping from + * bucket ID to timestamp, where the timestamp dictates the upper bound (inclusive) on commit logs + * from that bucket to include when restoring the datastore to this checkpoint. + */ +@Entity +@NotBackedUp(reason = Reason.COMMIT_LOGS) +public class CommitLogCheckpoint extends ImmutableObject { + + /** Shared singleton parent entity for commit log checkpoints. */ + @Parent + Key parent = CommitLogCheckpointRoot.getKey(); + + /** The checkpoint's approximate "wall" time (in millis since the epoch). */ + @Id + long checkpointTime; + + /** Bucket checkpoint times for this checkpoint, ordered to match up with buckets 1-N. */ + List bucketTimestamps = new ArrayList<>(); + + public DateTime getCheckpointTime() { + return new DateTime(checkpointTime, UTC); + } + + /** Returns the bucket checkpoint times as a map from bucket ID to commit timestamp. */ + public ImmutableMap getBucketTimestamps() { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (int i = 0; i < bucketTimestamps.size(); ++i) { + // Add 1 to map the bucket timestamps properly to buckets indexed from 1-N. + builder.put(i + 1, bucketTimestamps.get(i)); + } + return builder.build(); + } + + /** + * Creates a CommitLogCheckpoint for the given wall time and bucket checkpoint times, specified + * as a map from bucket ID to bucket commit timestamp. + */ + public static CommitLogCheckpoint create( + DateTime checkpointTime, + ImmutableMap bucketTimestamps) { + checkArgument( + Objects.equals(CommitLogBucket.getBucketIds().asList(), bucketTimestamps.keySet().asList()), + "Bucket ids are incorrect: %s", + bucketTimestamps.keySet()); + CommitLogCheckpoint instance = new CommitLogCheckpoint(); + instance.checkpointTime = checkpointTime.getMillis(); + instance.bucketTimestamps = ImmutableList.copyOf(bucketTimestamps.values()); + return instance; + } + + /** Creates a key for the CommitLogCheckpoint for the given wall time. */ + public static Key createKey(DateTime checkpointTime) { + return Key.create( + CommitLogCheckpointRoot.getKey(), CommitLogCheckpoint.class, checkpointTime.getMillis()); + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLogCheckpointRoot.java b/java/com/google/domain/registry/model/ofy/CommitLogCheckpointRoot.java new file mode 100644 index 000000000..9c26947e0 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLogCheckpointRoot.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +import org.joda.time.DateTime; + +/** + * Singleton parent entity for all commit log checkpoints. + */ +@Entity +@NotBackedUp(reason = Reason.COMMIT_LOGS) +public class CommitLogCheckpointRoot extends ImmutableObject { + + public static final long SINGLETON_ID = 1; // There is always exactly one of these. + + @Id + long id = SINGLETON_ID; + + /** Singleton key for CommitLogCheckpointParent. */ + public static Key getKey() { + return Key.create(CommitLogCheckpointRoot.class, SINGLETON_ID); + } + + /** The timestamp of the last {@link CommitLogCheckpoint} written. */ + DateTime lastWrittenTime = START_OF_TIME; + + public DateTime getLastWrittenTime() { + return lastWrittenTime; + } + + public static CommitLogCheckpointRoot loadRoot() { + CommitLogCheckpointRoot root = ofy().load().key(getKey()).now(); + return root == null ? new CommitLogCheckpointRoot() : root; + } + + public static CommitLogCheckpointRoot create(DateTime lastWrittenTime) { + CommitLogCheckpointRoot instance = new CommitLogCheckpointRoot(); + instance.lastWrittenTime = lastWrittenTime; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLogManifest.java b/java/com/google/domain/registry/model/ofy/CommitLogManifest.java new file mode 100644 index 000000000..e428c3168 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLogManifest.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Archived datastore transaction that can be replayed. + * + *

Entities of this kind are entity group sharded using a {@link CommitLogBucket} parent. Each + * object that was saved during this transaction is stored in a {@link CommitLogMutation} child + * entity. + */ +@Entity +@NotBackedUp(reason = Reason.COMMIT_LOGS) +public class CommitLogManifest extends ImmutableObject { + + /** Commit log manifests are parented on a random bucket. */ + @Parent + Key parent; + + /** + * The commit time (in millis since the epoch). + * + *

This will be unique among siblings sharing the same parent {@link CommitLogBucket}. + */ + @Id + long commitTime; + + /** Keys that were deleted in this commit. (Saves are recorded in child entities.) */ + Set> deletions = new LinkedHashSet<>(); + + public DateTime getCommitTime() { + return new DateTime(commitTime, UTC); + } + + public int getBucketId() { + return (int) parent.getId(); + } + + public ImmutableSet> getDeletions() { + return nullToEmptyImmutableCopy(deletions); + } + + public static CommitLogManifest create( + Key parent, DateTime commitTime, Set> deletions) { + CommitLogManifest instance = new CommitLogManifest(); + instance.parent = parent; + instance.commitTime = commitTime.getMillis(); + instance.deletions = nullToEmptyImmutableCopy(deletions); + return instance; + } + + public static Key createKey(Key parent, DateTime commitTime) { + return Key.create(parent, CommitLogManifest.class, commitTime.getMillis()); + } + + /** Returns the commit time encoded into a CommitLogManifest key. */ + public static DateTime extractCommitTime(Key manifestKey) { + return new DateTime(manifestKey.getId(), UTC); + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLogMutation.java b/java/com/google/domain/registry/model/ofy/CommitLogMutation.java new file mode 100644 index 000000000..c1d83c8ba --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLogMutation.java @@ -0,0 +1,94 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.appengine.api.datastore.EntityTranslator.convertToPb; +import static com.google.appengine.api.datastore.EntityTranslator.createFromPbBytes; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.appengine.api.datastore.KeyFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +/** Representation of a saved entity in a {@link CommitLogManifest} (not deletes). */ +@Entity +@NotBackedUp(reason = Reason.COMMIT_LOGS) +public class CommitLogMutation extends ImmutableObject { + + /** The manifest this belongs to. */ + @Parent + Key parent; + + /** Serialized web-safe string representation of saved entity key. */ + @Id + String entityKey; + + /** + * Raw entity that was saved during the transaction, serialized as a protocol buffer. + * + *

This value will be written to a GCS file by an export task. + */ + byte[] entityProtoBytes; + + public byte[] getEntityProtoBytes() { + return entityProtoBytes.clone(); + } + + /** Deserializes embedded entity bytes and returns it. */ + public com.google.appengine.api.datastore.Entity getEntity() { + return createFromPbBytes(entityProtoBytes); + } + + /** + * Returns a new mutation entity created from an @Entity ImmutableObject instance. + * + *

The mutation key is generated deterministically from the {@code entity} key. The object is + * converted to a raw datastore Entity, serialized to bytes, and stored within the mutation. + */ + public static CommitLogMutation create(Key parent, Object entity) { + return createFromRaw(parent, ofy().save().toEntity(entity)); + } + + /** + * Returns a new mutation entity created from a raw datastore Entity instance. + * + *

The mutation key is generated deterministically from the {@code entity} key. The Entity + * itself is serialized to bytes and stored within the returned mutation. + */ + @VisibleForTesting + public static CommitLogMutation createFromRaw( + Key parent, + com.google.appengine.api.datastore.Entity rawEntity) { + CommitLogMutation instance = new CommitLogMutation(); + instance.parent = parent; + // Creates a web-safe key string. + instance.entityKey = KeyFactory.keyToString(rawEntity.getKey()); + instance.entityProtoBytes = convertToPb(rawEntity).toByteArray(); + return instance; + } + + /** Returns the key of a mutation based on the {@code entityKey} of the entity it stores. */ + public static + Key createKey(Key parent, Key entityKey) { + return Key.create(parent, CommitLogMutation.class, entityKey.getString()); + } +} diff --git a/java/com/google/domain/registry/model/ofy/CommitLoggedWork.java b/java/com/google/domain/registry/model/ofy/CommitLoggedWork.java new file mode 100644 index 000000000..4ec07330e --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/CommitLoggedWork.java @@ -0,0 +1,213 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.in; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Maps.filterKeys; +import static com.google.common.collect.Sets.difference; +import static com.google.common.collect.Sets.union; +import static com.google.domain.registry.model.ofy.CommitLogBucket.loadBucket; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.BackupGroupRoot; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; + +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** Wrapper for {@link Work} that associates a time with each attempt. */ +class CommitLoggedWork extends VoidWork { + + private final Work work; + private final Clock clock; + + /** + * Temporary place to store the result of a non-void work. + * + *

We don't want to return the result directly because we are going to try to recover from a + * {@link com.google.appengine.api.datastore.DatastoreTimeoutException} deep inside Objectify + * when it tries to commit the transaction. When an exception is thrown the return value would be + * lost, but sometimes we will be able to determine that we actually succeeded despite the + * timeout, and we'll want to get the result. + */ + private R result; + + /** + * Temporary place to store the key of the commit log manifest. + * + *

We can use this to determine whether a transaction that failed with a + * {@link com.google.appengine.api.datastore.DatastoreTimeoutException} actually succeeded. If + * the manifest exists, and if the contents of the commit log are what we expected to have saved, + * then the transaction committed. If the manifest does not exist, then the transaction failed and + * is retryable. + */ + protected CommitLogManifest manifest; + + /** + * Temporary place to store the mutations belonging to the commit log manifest. + * + *

These are used along with the manifest to determine whether a transaction succeeded. + */ + protected ImmutableSet mutations = ImmutableSet.of(); + + /** Lifecycle marker to track whether {@link #vrun} has been called. */ + private boolean vrunCalled; + + CommitLoggedWork(Work work, Clock clock) { + this.work = work; + this.clock = clock; + } + + protected TransactionInfo createNewTransactionInfo() { + return new TransactionInfo(clock.nowUtc()); + } + + boolean hasRun() { + return vrunCalled; + } + + R getResult() { + checkState(vrunCalled, "Cannot call getResult() before vrun()"); + return result; + } + + CommitLogManifest getManifest() { + checkState(vrunCalled, "Cannot call getManifest() before vrun()"); + return manifest; + } + + ImmutableSet getMutations() { + checkState(vrunCalled, "Cannot call getMutations() before vrun()"); + return mutations; + } + + @Override + public void vrun() { + // The previous time will generally be null, except when using transactNew. + TransactionInfo previous = Ofy.TRANSACTION_INFO.get(); + // Set the time to be used for "now" within the transaction. + try { + Ofy.TRANSACTION_INFO.set(createNewTransactionInfo()); + result = work.run(); + saveCommitLog(Ofy.TRANSACTION_INFO.get()); + } finally { + Ofy.TRANSACTION_INFO.set(previous); + } + vrunCalled = true; + } + + /** Records all mutations enrolled by this transaction to a {@link CommitLogManifest} entry. */ + private void saveCommitLog(TransactionInfo info) { + ImmutableSet> touchedKeys = info.getTouchedKeys(); + if (touchedKeys.isEmpty()) { + return; + } + CommitLogBucket bucket = loadBucket(info.bucketKey); + // Enforce unique monotonic property on CommitLogBucket.getLastWrittenTime(). + if (isBeforeOrAt(info.transactionTime, bucket.getLastWrittenTime())) { + throw new TimestampInversionException(info.transactionTime, bucket.getLastWrittenTime()); + } + Map, BackupGroupRoot> rootsForTouchedKeys = + getBackupGroupRoots(touchedKeys); + Map, BackupGroupRoot> rootsForUntouchedKeys = + getBackupGroupRoots(difference(getObjectifySessionCacheKeys(), touchedKeys)); + // Check the update timestamps of all keys in the transaction, whether touched or merely read. + checkBackupGroupRootTimestamps( + info.transactionTime, + union(rootsForUntouchedKeys.entrySet(), rootsForTouchedKeys.entrySet())); + // Find any BGRs that have children which were touched but were not themselves touched. + Set untouchedRootsWithTouchedChildren = + ImmutableSet.copyOf(filterKeys(rootsForTouchedKeys, not(in(touchedKeys))).values()); + manifest = CommitLogManifest.create(info.bucketKey, info.transactionTime, info.getDeletes()); + final Key manifestKey = Key.create(manifest); + mutations = FluentIterable + .from(union(info.getSaves(), untouchedRootsWithTouchedChildren)) + .transform(new Function() { + @Override + public CommitLogMutation apply(Object saveEntity) { + return CommitLogMutation.create(manifestKey, saveEntity); + }}) + .toSet(); + ofy().save() + .entities(new ImmutableSet.Builder<>() + .add(manifest) + .add(bucket.asBuilder().setLastWrittenTime(info.transactionTime).build()) + .addAll(mutations) + .addAll(untouchedRootsWithTouchedChildren) + .build()) + .now(); + } + + /** + * Returns keys read by Objectify during this transaction. + * + *

This won't include the keys of asynchronous save and delete operations that haven't been + * reaped. But that's ok because we already logged all of those keys in {@link TransactionInfo} + * and only need this method to figure out what was loaded. + */ + private ImmutableSet> getObjectifySessionCacheKeys() { + return ((SessionKeyExposingObjectify) ofy()).getSessionKeys(); + } + + /** Check that the timestamp of each BackupGroupRoot is in the past. */ + private void checkBackupGroupRootTimestamps( + DateTime transactionTime, Set, BackupGroupRoot>> bgrEntries) { + ImmutableMap.Builder, DateTime> builder = new ImmutableMap.Builder<>(); + for (Entry, BackupGroupRoot> entry : bgrEntries) { + DateTime updateTime = entry.getValue().getUpdateAutoTimestamp().getTimestamp(); + if (!updateTime.isBefore(transactionTime)) { + builder.put(entry.getKey(), updateTime); + } + } + ImmutableMap, DateTime> problematicRoots = builder.build(); + if (!problematicRoots.isEmpty()) { + throw new TimestampInversionException(transactionTime, problematicRoots); + } + } + + /** Find the set of {@link BackupGroupRoot} ancestors of the given keys. */ + private Map, BackupGroupRoot> getBackupGroupRoots(Iterable> keys) { + Set> rootKeys = new HashSet<>(); + for (Key key : keys) { + while (key != null + && !BackupGroupRoot.class + .isAssignableFrom(ofy().factory().getMetadata(key).getEntityClass())) { + key = key.getParent(); + } + if (key != null) { + @SuppressWarnings("unchecked") + Key rootKey = (Key) key; + rootKeys.add(rootKey); + } + } + return ImmutableMap.copyOf(ofy().load().keys(rootKeys)); + } +} diff --git a/java/com/google/domain/registry/model/ofy/ObjectifyService.java b/java/com/google/domain/registry/model/ofy/ObjectifyService.java new file mode 100644 index 000000000..350bfdcd5 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/ObjectifyService.java @@ -0,0 +1,182 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.appengine.api.memcache.ErrorHandlers.getConsistentLogAndContinue; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.not; +import static com.google.domain.registry.util.TypeUtils.hasAnnotation; +import static com.googlecode.objectify.ObjectifyService.factory; + +import com.google.appengine.api.datastore.DatastoreServiceFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Iterables; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.EntityClasses; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.translators.CidrAddressBlockTranslatorFactory; +import com.google.domain.registry.model.translators.CommitLogRevisionsTranslatorFactory; +import com.google.domain.registry.model.translators.CreateAutoTimestampTranslatorFactory; +import com.google.domain.registry.model.translators.CurrencyUnitTranslatorFactory; +import com.google.domain.registry.model.translators.DurationTranslatorFactory; +import com.google.domain.registry.model.translators.InetAddressTranslatorFactory; +import com.google.domain.registry.model.translators.ReadableInstantUtcTranslatorFactory; +import com.google.domain.registry.model.translators.UpdateAutoTimestampTranslatorFactory; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Objectify; +import com.googlecode.objectify.ObjectifyFactory; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.EntitySubclass; +import com.googlecode.objectify.impl.translate.TranslatorFactory; +import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Level; + +/** + * An instance of Ofy, obtained via {@code #ofy()}, should be used to access all persistable + * objects. The class contains a static initializer to call factory().register(...) on all + * persistable objects in this package. + */ +public class ObjectifyService { + + /** + * A placeholder String passed into DatastoreService.allocateIds that ensures that all ids are + * initialized from the same id pool. + */ + public static final String APP_WIDE_ALLOCATION_KIND = "common"; + + /** A singleton instance of our Ofy wrapper. */ + private static final Ofy OFY = new Ofy(null); + + /** + * Returns a singleton {@link Ofy} instance. + * + *

Deprecated: This will go away once everything injects {@code Ofy}. + */ + public static Ofy ofy() { + return OFY; + } + + static { + initOfyOnce(); + } + + /** Ensures that Objectify has been fully initialized. */ + public static void initOfy() { + // This method doesn't actually do anything; it's here so that callers have something to call + // to ensure that the static initialization of ObjectifyService has been performed (which Java + // guarantees will happen exactly once, before any static methods are invoked). + // + // See JLS section 12.4: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 + } + + /** + * Performs static initialization for Objectify to register types and do other setup. + * + *

This method is non-idempotent, so it should only be called exactly once, which is achieved + * by calling it from this class's static initializer block. + */ + private static void initOfyOnce() { + // Set an ObjectifyFactory that uses our extended ObjectifyImpl. + // The "false" argument means that we are not using the v5-style Objectify embedded entities. + com.googlecode.objectify.ObjectifyService.setFactory(new ObjectifyFactory(false) { + @Override + public Objectify begin() { + return new SessionKeyExposingObjectify(this); + }}); + + // Translators must be registered before any entities can be registered. + registerTranslators(); + registerEntityClasses(EntityClasses.ALL_CLASSES); + + // Set the memcache error handler so that we don't see internally logged errors. + factory().setMemcacheErrorHandler(getConsistentLogAndContinue(Level.INFO)); + } + + /** Register translators that allow less common types to be stored directly in Datastore. */ + private static void registerTranslators() { + for (TranslatorFactory translatorFactory : Arrays.asList( + new ReadableInstantUtcTranslatorFactory(), + new CidrAddressBlockTranslatorFactory(), + new CurrencyUnitTranslatorFactory(), + new DurationTranslatorFactory(), + new InetAddressTranslatorFactory(), + new MoneyStringTranslatorFactory(), + new CreateAutoTimestampTranslatorFactory(), + new UpdateAutoTimestampTranslatorFactory(), + new CommitLogRevisionsTranslatorFactory())) { + factory().getTranslators().add(translatorFactory); + } + } + + /** Register classes that can be persisted via Objectify as datastore entities. */ + private static void registerEntityClasses( + Iterable> entityClasses) { + // Register all the @Entity classes before any @EntitySubclass classes so that we can check + // that every @Entity registration is a new kind and every @EntitySubclass registration is not. + // This is future-proofing for Objectify 5.x where the registration logic gets less lenient. + for (Class clazz : Iterables.concat( + Iterables.filter(entityClasses, hasAnnotation(Entity.class)), + Iterables.filter(entityClasses, not(hasAnnotation(Entity.class))))) { + String kind = Key.getKind(clazz); + boolean registered = factory().getMetadata(kind) != null; + if (clazz.isAnnotationPresent(Entity.class)) { + // Objectify silently ignores re-registrations for a given kind string, even if the classes + // being registered are distinct. Throw an exception if that would happen here. + checkState(!registered, + "Kind '%s' already registered, cannot register new @Entity %s", + kind, clazz.getCanonicalName()); + } else if (clazz.isAnnotationPresent(EntitySubclass.class)) { + // Ensure that any @EntitySubclass classes have also had their parent @Entity registered, + // which Objectify nominally requires but doesn't enforce in 4.x (though it may in 5.x). + checkState(registered, + "No base entity for kind '%s' registered yet, cannot register new @EntitySubclass %s", + kind, clazz.getCanonicalName()); + } + com.googlecode.objectify.ObjectifyService.register(clazz); + // Autogenerated ids make the commit log code very difficult since we won't always be able + // to create a key for an entity immediately when requesting a save. Disallow that here. + checkState( + !factory().getMetadata(clazz).getKeyMetadata().isIdGeneratable(), + "Can't register %s: Autogenerated ids (@Id on a Long) are not supported.", kind); + } + } + + /** Counts of used ids for use in unit tests. Outside tests this is never used. */ + private static final AtomicLong nextTestId = new AtomicLong(1); // ids cannot be zero + + /** Allocates an id. */ + public static long allocateId() { + return RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get()) + ? nextTestId.getAndIncrement() + : DatastoreServiceFactory.getDatastoreService() + .allocateIds(APP_WIDE_ALLOCATION_KIND, 1) + .iterator() + .next() + .getId(); + } + + /** Resets the global test id counter (i.e. sets the next id to 1). */ + @VisibleForTesting + public static void resetNextTestId() { + checkState(RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get()), + "Can't call resetTestIdCounts() from RegistryEnvironment.%s", + RegistryEnvironment.get()); + nextTestId.set(1); // ids cannot be zero + } +} diff --git a/java/com/google/domain/registry/model/ofy/Ofy.java b/java/com/google/domain/registry/model/ofy/Ofy.java new file mode 100644 index 000000000..4253d5af1 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/Ofy.java @@ -0,0 +1,351 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Maps.uniqueIndex; +import static com.google.domain.registry.util.CollectionUtils.union; +import static com.google.domain.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.appengine.api.datastore.DatastoreFailureException; +import com.google.appengine.api.datastore.DatastoreTimeoutException; +import com.google.appengine.api.datastore.ReadPolicy.Consistency; +import com.google.appengine.api.taskqueue.TransientFailureException; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.VirtualEntity; +import com.google.domain.registry.model.ofy.ReadOnlyWork.KillTransactionException; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.Sleeper; +import com.google.domain.registry.util.SystemClock; +import com.google.domain.registry.util.SystemSleeper; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Objectify; +import com.googlecode.objectify.ObjectifyFactory; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.cmd.Deleter; +import com.googlecode.objectify.cmd.Loader; +import com.googlecode.objectify.cmd.Saver; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.lang.annotation.Annotation; +import java.util.Objects; + +import javax.inject.Inject; + +/** + * A wrapper around ofy(). + *

+ * The primary purpose of this class is to add functionality to support commit logs. It is simpler + * to wrap {@link Objectify} rather than extend it because this way we can remove some methods that + * we don't really want exposed and add some shortcuts. + */ +public class Ofy { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** Default clock for transactions that don't provide one. */ + @NonFinalForTesting + static Clock clock = new SystemClock(); + + /** Default sleeper for transactions that don't provide one. */ + @NonFinalForTesting + static Sleeper sleeper = new SystemSleeper(); + + /** + * An injected clock that overrides the static clock. + * + *

Eventually the static clock should go away when we are 100% injected, but for now we need to + * preserve the old way of overriding the clock in tests by changing the static field. + */ + private final Clock injectedClock; + + /** Retry for 8^2 * 100ms = ~25 seconds. */ + private static final int NUM_RETRIES = 8; + + @Inject + public Ofy(Clock injectedClock) { + this.injectedClock = injectedClock; + } + + /** + * Thread local transaction info. There can only be one active transaction on a thread at a given + * time, and this will hold metadata for it. + */ + static final ThreadLocal TRANSACTION_INFO = new ThreadLocal<>(); + + /** Returns the wrapped Objectify's ObjectifyFactory. */ + public ObjectifyFactory factory() { + return ofy().factory(); + } + + /** Clears the session cache. */ + public void clearSessionCache() { + ofy().clear(); + } + + public boolean inTransaction() { + return ofy().getTransaction() != null; + } + + public void assertInTransaction() { + checkState(inTransaction(), "Must be called in a transaction"); + } + + public Loader load() { + return ofy().load(); + } + + public Loader loadEventuallyConsistent() { + return ofy().consistency(Consistency.EVENTUAL).load(); + } + + /** + * Delete, augmented to enroll the deleted entities in a commit log. + * + *

We only allow this in transactions so commit logs can be written in tandem with the delete. + */ + public Deleter delete() { + return new AugmentedDeleter() { + @Override + protected void handleDeletion(Iterable> keys) { + assertInTransaction(); + checkState(Iterables.all(keys, notNull()), "Can't delete a null key."); + checkProhibitedAnnotations(keys, NotBackedUp.class, VirtualEntity.class); + TRANSACTION_INFO.get().putDeletes(keys); + } + }; + } + + /** + * Delete, without any augmentations. + * + *

No backups get written. + */ + public Deleter deleteWithoutBackup() { + return ofy().delete(); + } + + /** + * Save, augmented to enroll the saved entities in a commit log and to check that we're not saving + * virtual entities. + * + *

We only allow this in transactions so commit logs can be written in tandem with the save. + */ + public Saver save() { + return new AugmentedSaver() { + @Override + protected void handleSave(Iterable entities) { + assertInTransaction(); + checkState(Iterables.all(entities, notNull()), "Can't save a null entity."); + checkProhibitedAnnotations(entities, NotBackedUp.class, VirtualEntity.class); + ImmutableMap, ?> keysToEntities = uniqueIndex(entities, OBJECTS_TO_KEYS); + TRANSACTION_INFO.get().putSaves(keysToEntities); + } + }; + } + + /** + * Save, without any augmentations except to check that we're not saving any virtual entities. + *

+ * No backups get written. + */ + public Saver saveWithoutBackup() { + return new AugmentedSaver() { + @Override + protected void handleSave(Iterable entities) { + checkProhibitedAnnotations(entities, VirtualEntity.class); + } + }; + } + + private Clock getClock() { + return injectedClock == null ? clock : injectedClock; + } + + /** Execute a transaction. */ + public R transact(Work work) { + // If we are already in a transaction, don't wrap in a CommitLoggedWork. + return inTransaction() ? work.run() : transactNew(work); + } + + /** Pause the current transaction (if any) and complete this one before returning to it. */ + public R transactNew(Work work) { + // Wrap the Work in a CommitLoggedWork so that we can give transactions a frozen view of time + // and maintain commit logs for them. + return transactCommitLoggedWork(new CommitLoggedWork<>(work, getClock())); + } + + /** + * Transact with commit logs and retry with exponential backoff. + * + *

This method is broken out from {@link #transactNew(Work)} for testing purposes. + */ + @VisibleForTesting + R transactCommitLoggedWork(CommitLoggedWork work) { + long baseRetryMillis = RegistryEnvironment.get().config().getBaseOfyRetryDuration().getMillis(); + for (long attempt = 0, sleepMillis = baseRetryMillis; + true; + attempt++, sleepMillis *= 2) { + try { + ofy().transactNew(work); + return work.getResult(); + } catch (TransientFailureException + | TimestampInversionException + | DatastoreTimeoutException + | DatastoreFailureException e) { + // TransientFailureExceptions come from task queues and always mean nothing committed. + // TimestampInversionExceptions are thrown by our code and are always retryable as well. + // However, datastore exceptions might get thrown even if the transaction succeeded. + if ((e instanceof DatastoreTimeoutException || e instanceof DatastoreFailureException) + && checkIfAlreadySucceeded(work)) { + return work.getResult(); + } + if (attempt == NUM_RETRIES) { + throw e; // Give up. + } + sleeper.sleepUninterruptibly(Duration.millis(sleepMillis)); + logger.infofmt(e, "Retrying %s, attempt %s", e.getClass().getSimpleName(), attempt); + } + } + } + + /** + * We can determine whether a transaction has succeded by trying to read the commit log back in + * its own retryable read-only transaction. + */ + private Boolean checkIfAlreadySucceeded(final CommitLoggedWork work) { + return work.hasRun() && transactNewReadOnly(new Work() { + @Override + public Boolean run() { + CommitLogManifest manifest = work.getManifest(); + if (manifest == null) { + // Work ran but no commit log was created. This might mean that the transaction did not + // write anything to datastore. We can safely retry because it only reads. (Although the + // transaction might have written a task to a queue, we consider that safe to retry too + // since we generally assume that tasks might be doubly executed.) Alternatively it + // might mean that the transaction wrote to datastore but turned off commit logs by + // exclusively using save/deleteWithoutBackups() rather than save/delete(). Although we + // have no hard proof that retrying is safe, we use these methods judiciously and it is + // reasonable to assume that if the transaction really did succeed that the retry will + // either be idempotent or will fail with a non-transient error. + return false; + } + return Objects.equals( + union(work.getMutations(), manifest), + ImmutableSet.copyOf(ofy().load().ancestor(manifest))); + }}); + } + + /** A read-only transaction is useful to get strongly consistent reads at a shared timestamp. */ + public R transactNewReadOnly(Work work) { + ReadOnlyWork readOnlyWork = new ReadOnlyWork<>(work, getClock()); + try { + ofy().transactNew(readOnlyWork); + } catch (TransientFailureException | DatastoreTimeoutException | DatastoreFailureException e) { + // These are always retryable for a read-only operation. + return transactNewReadOnly(work); + } catch (KillTransactionException e) { + // Expected; we killed the transaction as a safety measure, and now we can return the result. + return readOnlyWork.getResult(); + } + throw new AssertionError(); // How on earth did we get here? + } + + /** Execute some work in a transactionless context. */ + public R doTransactionless(Work work) { + try { + com.googlecode.objectify.ObjectifyService.push( + com.googlecode.objectify.ObjectifyService.ofy().transactionless()); + return work.run(); + } finally { + com.googlecode.objectify.ObjectifyService.pop(); + } + } + + /** + * Execute some work with a fresh session cache. + * + *

This is useful in cases where we want to load the latest possible data from datastore but + * don't need point-in-time consistency across loads and consequently don't need a transaction. + * Note that unlike a transaction's fresh session cache, the contents of this cache will be + * discarded once the work completes, rather than being propagated into the enclosing session. + */ + public R doWithFreshSessionCache(Work work) { + try { + com.googlecode.objectify.ObjectifyService.push( + com.googlecode.objectify.ObjectifyService.factory().begin()); + return work.run(); + } finally { + com.googlecode.objectify.ObjectifyService.pop(); + } + } + + /** Get the time associated with the start of this particular transaction attempt. */ + public DateTime getTransactionTime() { + assertInTransaction(); + return TRANSACTION_INFO.get().transactionTime; + } + + /** Returns key of {@link CommitLogManifest} that will be saved when the transaction ends. */ + public Key getCommitLogManifestKey() { + assertInTransaction(); + TransactionInfo info = TRANSACTION_INFO.get(); + return Key.create(info.bucketKey, CommitLogManifest.class, info.transactionTime.getMillis()); + } + + /** + * Returns the @Entity-annotated base class for an object that is either an {@code Key} or an + * object of an entity class registered with Objectify. + */ + @VisibleForTesting + static Class getBaseEntityClassFromEntityOrKey(Object entityOrKey) { + // Convert both keys and entities into keys, so that we get consistent behavior in either case. + Key key = (entityOrKey instanceof Key ? (Key) entityOrKey : Key.create(entityOrKey)); + // Get the entity class associated with this key's kind, which should be the base @Entity class + // from which the kind name is derived. Don't be tempted to use getMetadata(String kind) or + // getMetadataForEntity(T pojo) instead; the former won't throw an exception for an unknown + // kind (it just returns null) and the latter will return the @EntitySubclass if there is one. + return ofy().factory().getMetadata(key).getEntityClass(); + } + + /** + * Checks that the base @Entity classes for the provided entities or keys don't have any of the + * specified forbidden annotations. + */ + @SafeVarargs + private static void checkProhibitedAnnotations( + Iterable entitiesOrKeys, Class... annotations) { + for (Object entityOrKey : entitiesOrKeys) { + Class entityClass = getBaseEntityClassFromEntityOrKey(entityOrKey); + for (Class annotation : annotations) { + checkArgument(!entityClass.isAnnotationPresent(annotation), + "Can't save/delete a @%s entity: %s", annotation.getSimpleName(), entityClass); + } + } + } +} diff --git a/java/com/google/domain/registry/model/ofy/OfyFilter.java b/java/com/google/domain/registry/model/ofy/OfyFilter.java new file mode 100644 index 000000000..6c8a83a60 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/OfyFilter.java @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +/** A filter that statically registers types with Objectify. */ +public class OfyFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) + throws IOException, ServletException { + filterChain.doFilter(request, response); + } + + @Override + public void init(FilterConfig config) throws ServletException { + // Make sure that we've registered all types before we do anything else with Objectify. + ObjectifyService.initOfy(); + } + + @Override + public void destroy() {} +} diff --git a/java/com/google/domain/registry/model/ofy/ReadOnlyWork.java b/java/com/google/domain/registry/model/ofy/ReadOnlyWork.java new file mode 100644 index 000000000..b83d73eae --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/ReadOnlyWork.java @@ -0,0 +1,41 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Work; + +/** Wrapper for {@link Work} that disallows mutations and fails the transaction at the end. */ +class ReadOnlyWork extends CommitLoggedWork { + + ReadOnlyWork(Work work, Clock clock) { + super(work, clock); + } + + @Override + protected TransactionInfo createNewTransactionInfo() { + return super.createNewTransactionInfo().setReadOnly(); + } + + @Override + public void vrun() { + super.vrun(); + throw new KillTransactionException(); + } + + /** Exception used to exit a transaction. */ + static class KillTransactionException extends RuntimeException {} +} diff --git a/java/com/google/domain/registry/model/ofy/SessionKeyExposingObjectify.java b/java/com/google/domain/registry/model/ofy/SessionKeyExposingObjectify.java new file mode 100644 index 000000000..851dde4e5 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/SessionKeyExposingObjectify.java @@ -0,0 +1,34 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import com.google.common.collect.ImmutableSet; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.ObjectifyFactory; +import com.googlecode.objectify.impl.ObjectifyImpl; + +/** Registry-specific Objectify subclass that exposes the keys used in the current session. */ +public class SessionKeyExposingObjectify extends ObjectifyImpl { + + public SessionKeyExposingObjectify(ObjectifyFactory factory) { + super(factory); + } + + /** Expose the protected method that provides the keys read, saved or deleted in a session. */ + ImmutableSet> getSessionKeys() { + return ImmutableSet.copyOf(getSession().keys()); + } +} diff --git a/java/com/google/domain/registry/model/ofy/TimestampInversionException.java b/java/com/google/domain/registry/model/ofy/TimestampInversionException.java new file mode 100644 index 000000000..91a57e632 --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/TimestampInversionException.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static java.util.Arrays.asList; + +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.domain.registry.model.BackupGroupRoot; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Objectify; + +import org.joda.time.DateTime; + +import java.util.Map; + +/** + * Exception when trying to write to the datastore with a timestamp that is inconsistent with + * a partial ordering on transactions that touch the same entities. + */ +class TimestampInversionException extends RuntimeException { + + static String getFileAndLine(StackTraceElement callsite) { + return callsite.getFileName() + ":" + callsite.getLineNumber(); + } + + TimestampInversionException( + DateTime transactionTime, Map, DateTime> problematicRoots) { + this(transactionTime, "entities rooted under:\n" + problematicRoots); + } + + TimestampInversionException(DateTime transactionTime, DateTime updateTimestamp) { + this(transactionTime, String.format("update timestamp (%s)", updateTimestamp)); + } + + private TimestampInversionException(DateTime transactionTime, String problem) { + super(Joiner.on('\n').join( + String.format( + "Timestamp inversion between transaction time (%s) and %s", + transactionTime, + problem), + getFileAndLine(FluentIterable.from(asList(new Exception().getStackTrace())) + .firstMatch(new Predicate() { + @Override + public boolean apply(StackTraceElement element) { + return !element.getClassName().startsWith(Objectify.class.getPackage().getName()) + && !element.getClassName().startsWith(Ofy.class.getName()); + }}).get()))); + } +} diff --git a/java/com/google/domain/registry/model/ofy/TransactionInfo.java b/java/com/google/domain/registry/model/ofy/TransactionInfo.java new file mode 100644 index 000000000..3ddce48ac --- /dev/null +++ b/java/com/google/domain/registry/model/ofy/TransactionInfo.java @@ -0,0 +1,99 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.ofy; + +import static com.google.common.base.Functions.constant; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Maps.filterValues; +import static com.google.common.collect.Maps.toMap; +import static com.google.domain.registry.model.ofy.CommitLogBucket.getArbitraryBucketId; +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import com.googlecode.objectify.Key; + +import org.joda.time.DateTime; + +import java.util.Map; + +/** Metadata for an {@link Ofy} transaction that saves commit logs. */ +class TransactionInfo { + + private static final Predicate IS_DELETE = Predicates.equalTo(Delete.SENTINEL); + + private enum Delete { SENTINEL } + + /** Logical "now" of the transaction. */ + DateTime transactionTime; + + /** Whether this is a read-only transaction. */ + private boolean readOnly; + + /** Bucket shard to under which commit log will be stored, chosen at random (in production). */ + final Key bucketKey = CommitLogBucket.getBucketKey(getArbitraryBucketId()); + + /** + * Accumulator of save/delete operations performed in transaction. + * + *

The {@link ImmutableMap} builder provides us the benefit of not permitting duplicates. + * This allows us to avoid potential race conditions where the same key is mutated twice in a + * transaction. + */ + private final ImmutableMap.Builder, Object> changesBuilder = new ImmutableMap.Builder<>(); + + TransactionInfo(DateTime now) { + this.transactionTime = now; + ofy().load().key(bucketKey); // Asynchronously load value into session cache. + } + + TransactionInfo setReadOnly() { + this.readOnly = true; + return this; + } + + void assertNotReadOnly() { + checkState(!readOnly, "This is a read only transaction."); + } + + void putSaves(Map, ?> keysToEntities) { + assertNotReadOnly(); + changesBuilder.putAll(keysToEntities); + } + + void putDeletes(Iterable> keys) { + assertNotReadOnly(); + changesBuilder.putAll(toMap(keys, constant(TransactionInfo.Delete.SENTINEL))); + } + + ImmutableSet> getTouchedKeys() { + return ImmutableSet.copyOf(changesBuilder.build().keySet()); + } + + ImmutableSet> getDeletes() { + return ImmutableSet.copyOf(filterValues(changesBuilder.build(), IS_DELETE).keySet()); + } + + ImmutableSet getSaves() { + return FluentIterable + .from(changesBuilder.build().values()) + .filter(Predicates.not(IS_DELETE)) + .toSet(); + } +} diff --git a/java/com/google/domain/registry/model/package-info.java b/java/com/google/domain/registry/model/package-info.java new file mode 100644 index 000000000..a962d611a --- /dev/null +++ b/java/com/google/domain/registry/model/package-info.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:epp-1.0", + xmlns = @XmlNs(namespaceURI = "urn:ietf:params:xml:ns:epp-1.0", prefix = ""), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * This package defines all entities which are managed via EPP XML and persisted to the Datastore + * via Objectify. + *

+ * All first class entities are represented as a "Resource" class - {@link DomainResource}, + * {@link HostResource}, {@link ContactResource}, and {@link RegistrarResource}. Resource objects + * are written in a single shared entity group per TLD. All commands that operate on those entities + * are grouped in a "Command" class- {@link DomainCommand}, {@link HostCommand}, + * {@link ContactCommand}. The Resource does double duty as both the persisted representation and as + * the XML-marshallable object returned in respond to Info commands. + *

+ * Command classes are never persisted, and the Objectify annotations on the Create and Update + * classes are purely for the benefit of the derived Resource classes that inherit from them. + * Whenever a command that mutates the model is executed, a HistoryEvent is stored with the affected + * Resource as its datastore parent. All history entries have an indexed modification time field so + * that the history can be read in chronological order. + */ diff --git a/java/com/google/domain/registry/model/poll/MessageQueueInfo.java b/java/com/google/domain/registry/model/poll/MessageQueueInfo.java new file mode 100644 index 000000000..9741ce265 --- /dev/null +++ b/java/com/google/domain/registry/model/poll/MessageQueueInfo.java @@ -0,0 +1,70 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.poll; + +import com.google.domain.registry.model.ImmutableObject; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; + +/** Information about the message queue for the currently logged in registrar. */ +public class MessageQueueInfo extends ImmutableObject { + + /** The date and time that the current message was enqueued. */ + @XmlElement(name = "qDate") + DateTime queueDate; + + /** A human-readable message. */ + String msg; + + /** The number of messages currently in the queue. */ + @XmlAttribute(name = "count") + Integer queueLength; + + /** The id of the message currently at the head of the queue. */ + @XmlAttribute(name = "id") + String messageId; + + public DateTime getQueueDate() { + return queueDate; + } + + public String getMsg() { + return msg; + } + + public Integer getQueueLength() { + return queueLength; + } + + public String getMessageId() { + return messageId; + } + + public static MessageQueueInfo create( + DateTime queueDate, + String msg, + Integer queueLength, + String messageId) { + MessageQueueInfo instance = new MessageQueueInfo(); + instance.queueDate = queueDate; + instance.msg = msg; + instance.queueLength = queueLength; + instance.messageId = messageId; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/poll/PendingActionNotificationResponse.java b/java/com/google/domain/registry/model/poll/PendingActionNotificationResponse.java new file mode 100644 index 000000000..4dc8c9575 --- /dev/null +++ b/java/com/google/domain/registry/model/poll/PendingActionNotificationResponse.java @@ -0,0 +1,124 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.poll; + + +import com.google.common.annotations.VisibleForTesting; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; + +import com.googlecode.objectify.annotation.Embed; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** The {@link ResponseData} returned when completing a pending action on a domain. */ +@XmlTransient +public abstract class PendingActionNotificationResponse + extends ImmutableObject implements ResponseData { + + /** The inner name type that contains a name and the result boolean. */ + @Embed + static class NameOrId extends ImmutableObject { + @XmlValue + String value; + + @XmlAttribute(name = "paResult") + boolean actionResult; + } + + @XmlTransient + NameOrId nameOrId; + + @XmlElement(name = "paTRID") + Trid trid; + + @XmlElement(name = "paDate") + DateTime processedDate; + + public String getNameAsString() { + return nameOrId.value; + } + + @VisibleForTesting + public Trid getTrid() { + return trid; + } + + @VisibleForTesting + public boolean getActionResult() { + return nameOrId.actionResult; + } + + @SuppressWarnings("unchecked") + protected T init( + String nameOrId, boolean actionResult, Trid trid, DateTime processedDate) { + this.nameOrId = new NameOrId(); + this.nameOrId.value = nameOrId; + this.nameOrId.actionResult = actionResult; + this.trid = trid; + this.processedDate = processedDate; + return (T) this; + } + + /** An adapter to output the XML in response to resolving a pending command on a domain. */ + @Embed + @XmlRootElement(name = "panData", namespace = "urn:ietf:params:xml:ns:domain-1.0") + @XmlType( + propOrder = {"name", "trid", "processedDate"}, + namespace = "urn:ietf:params:xml:ns:domain-1.0") + public static class DomainPendingActionNotificationResponse + extends PendingActionNotificationResponse { + + @XmlElement + NameOrId getName() { + return nameOrId; + } + + public static DomainPendingActionNotificationResponse create( + String fullyQualifiedDomainName, boolean actionResult, Trid trid, DateTime processedDate) { + return new DomainPendingActionNotificationResponse().init( + fullyQualifiedDomainName, actionResult, trid, processedDate); + } + } + + /** An adapter to output the XML in response to resolving a pending command on a contact. */ + @Embed + @XmlRootElement(name = "panData", namespace = "urn:ietf:params:xml:ns:contact-1.0") + @XmlType( + propOrder = {"id", "trid", "processedDate"}, + namespace = "urn:ietf:params:xml:ns:contact-1.0") + public static class ContactPendingActionNotificationResponse + extends PendingActionNotificationResponse { + + @XmlElement + NameOrId getId() { + return nameOrId; + } + + public static ContactPendingActionNotificationResponse create( + String contactId, boolean actionResult, Trid trid, DateTime processedDate) { + return new ContactPendingActionNotificationResponse().init( + contactId, actionResult, trid, processedDate); + } + } +} diff --git a/java/com/google/domain/registry/model/poll/PollMessage.java b/java/com/google/domain/registry/model/poll/PollMessage.java new file mode 100644 index 000000000..1c8363abb --- /dev/null +++ b/java/com/google/domain/registry/model/poll/PollMessage.java @@ -0,0 +1,324 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.poll; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull; +import static com.google.domain.registry.util.CollectionUtils.isNullOrEmpty; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Converter; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.ExternalMessagingName; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.domain.DomainRenewData; +import com.google.domain.registry.model.domain.launch.LaunchInfoResponseExtension; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; +import com.google.domain.registry.model.eppoutput.Response.ResponseExtension; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse; +import com.google.domain.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.transfer.TransferData.TransferServerApproveEntity; +import com.google.domain.registry.model.transfer.TransferResponse.ContactTransferResponse; +import com.google.domain.registry.model.transfer.TransferResponse.DomainTransferResponse; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.EntitySubclass; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.List; + +/** A poll message that is pending for a registrar. */ +@Entity +@ExternalMessagingName("message") +public abstract class PollMessage + extends ImmutableObject implements Buildable, TransferServerApproveEntity { + + + public static final Converter, String> EXTERNAL_KEY_CONVERTER = + new PollMessageExternalKeyConverter(); + + /** Entity id. */ + @Id + long id; + + @Parent + Key parent; + + /** The registrar that this poll message will be delivered to. */ + @Index + String clientId; + + /** The time when the poll message should be delivered. May be in the future. */ + @Index + DateTime eventTime; + + /** Human readable message that will be returned with this poll message. */ + String msg; + + public Key getParentKey() { + return parent; + } + + public Long getId() { + return id; + } + + public String getClientId() { + return clientId; + } + + public DateTime getEventTime() { + return eventTime; + } + + public String getMsg() { + return msg; + } + + public abstract ImmutableList getResponseData(); + + public abstract ImmutableList getResponseExtensions(); + + /** Override Buildable.asBuilder() to give this method stronger typing. */ + @Override + public abstract Builder asBuilder(); + + /** Builder for {@link PollMessage} because it is immutable. */ + @VisibleForTesting + public abstract static class Builder> + extends GenericBuilder { + + protected Builder() {} + + protected Builder(T instance) { + super(instance); + } + + @VisibleForTesting + public B setId(Long id) { + getInstance().id = id; + return thisCastToDerived(); + } + + public B setClientId(String clientId) { + getInstance().clientId = clientId; + return thisCastToDerived(); + } + + public B setEventTime(DateTime eventTime) { + getInstance().eventTime = eventTime; + return thisCastToDerived(); + } + + public B setMsg(String msg) { + getInstance().msg = msg; + return thisCastToDerived(); + } + + public B setParent(HistoryEntry parent) { + getInstance().parent = Key.create(parent); + return thisCastToDerived(); + } + + public B setParentKey(Key parentKey) { + getInstance().parent = parentKey; + return thisCastToDerived(); + } + + @Override + public T build() { + T instance = getInstance(); + checkNotNull(instance.clientId); + checkNotNull(instance.eventTime); + checkNotNull(instance.parent); + return super.build(); + } + } + + /** A one-time poll message. */ + @EntitySubclass(index = false) + public static class OneTime extends PollMessage { + + // Response data. Objectify cannot persist a base class type, so we must have a separate field + // to hold every possible derived type of ResponseData that we might store. + List contactPendingActionNotificationResponses; + List contactTransferResponses; + List domainPendingActionNotificationResponses; + List domainTransferResponses; + + // Extensions. Objectify cannot persist a base class type, so we must have a separate field + // to hold every possible derived type of ResponseExtensions that we might store. + // + // Note that we cannot store a list of LaunchInfoResponseExtension objects since it contains a + // list of embedded Mark objects, and embedded lists of lists are not allowed. This shouldn't + // matter since there's no scenario where multiple launch info response extensions are ever + // returned. + LaunchInfoResponseExtension launchInfoResponseExtension; + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + @Override + public ImmutableList getResponseData() { + return new ImmutableList.Builder() + .addAll(nullToEmpty(contactPendingActionNotificationResponses)) + .addAll(nullToEmpty(contactTransferResponses)) + .addAll(nullToEmpty(domainPendingActionNotificationResponses)) + .addAll(nullToEmpty(domainTransferResponses)) + .build(); + } + + /** + * Returns the class of the parent EppResource that this poll message is associated with, + * either DomainBase or ContactResource. + */ + public Class getParentResourceClass() { + if (!isNullOrEmpty(domainPendingActionNotificationResponses) + || !isNullOrEmpty(domainTransferResponses)) { + return DomainBase.class; + } else if (!isNullOrEmpty(contactPendingActionNotificationResponses) + || !isNullOrEmpty(contactTransferResponses)) { + return ContactResource.class; + } else { + throw new IllegalStateException(String.format( + "PollMessage.OneTime %s does not correspond with an EppResource of a known type", + Key.create(this))); + } + } + + @Override + public ImmutableList getResponseExtensions() { + return (launchInfoResponseExtension == null) ? ImmutableList.of() : + ImmutableList.of(launchInfoResponseExtension); + } + + /** A builder for {@link OneTime} since it is immutable. */ + @VisibleForTesting + public static class Builder extends PollMessage.Builder { + + public Builder() {} + + private Builder(OneTime instance) { + super(instance); + } + + public Builder setResponseData(ImmutableList responseData) { + FluentIterable iterable = FluentIterable.from(responseData); + getInstance().contactPendingActionNotificationResponses = forceEmptyToNull( + iterable.filter(ContactPendingActionNotificationResponse.class).toList()); + getInstance().contactTransferResponses = forceEmptyToNull( + iterable.filter(ContactTransferResponse.class).toList()); + getInstance().domainPendingActionNotificationResponses = forceEmptyToNull( + iterable.filter(DomainPendingActionNotificationResponse.class).toList()); + getInstance().domainTransferResponses = forceEmptyToNull( + iterable.filter(DomainTransferResponse.class).toList()); + return this; + } + + public Builder setResponseExtensions( + ImmutableList responseExtensions) { + getInstance().launchInfoResponseExtension = FluentIterable + .from(responseExtensions) + .filter(LaunchInfoResponseExtension.class) + .first() + .orNull(); + return this; + } + } + } + + /** An autorenew poll message which recurs annually. */ + @EntitySubclass(index = false) + public static class Autorenew extends PollMessage { + + /** The target id of the autorenew event. */ + String targetId; + + /** The autorenew recurs annually between {@link #eventTime} and this time. */ + @Index + DateTime autorenewEndTime; + + public String getTargetId() { + return targetId; + } + + public DateTime getAutorenewEndTime() { + return autorenewEndTime; + } + + @Override + public ImmutableList getResponseData() { + // Note that the event time is when the auto-renew occured, so the expiration time in the + // response should be 1 year past that, since it denotes the new expiration time. + return ImmutableList.of( + DomainRenewData.create(getTargetId(), getEventTime().plusYears(1))); + } + + @Override + public ImmutableList getResponseExtensions() { + return ImmutableList.of(); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link Autorenew} since it is immutable. */ + @VisibleForTesting + public static class Builder extends PollMessage.Builder { + + public Builder() {} + + private Builder(Autorenew instance) { + super(instance); + } + + public Builder setTargetId(String targetId) { + getInstance().targetId = targetId; + return this; + } + + public Builder setAutorenewEndTime(DateTime autorenewEndTime) { + getInstance().autorenewEndTime = autorenewEndTime; + return this; + } + + @Override + public Autorenew build() { + Autorenew instance = getInstance(); + instance.autorenewEndTime = + Optional.fromNullable(instance.autorenewEndTime).or(END_OF_TIME); + return super.build(); + } + } + } +} diff --git a/java/com/google/domain/registry/model/poll/PollMessageExternalKeyConverter.java b/java/com/google/domain/registry/model/poll/PollMessageExternalKeyConverter.java new file mode 100644 index 000000000..aa263590f --- /dev/null +++ b/java/com/google/domain/registry/model/poll/PollMessageExternalKeyConverter.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.poll; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Converter; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableBiMap; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainBase; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.reporting.HistoryEntry; + +import com.googlecode.objectify.Key; + +import java.util.List; + +/** + * A converter between external key strings for PollMessages and Objectify Keys to the resource. + * + *

The format of the key string is A-B-C-D-E as follows: + * + *

+ *   A = EppResource.typeId (decimal)
+ *   B = EppResource.repoId prefix (STRING)
+ *   C = EppResource.repoId suffix (STRING)
+ *   D = HistoryEntry.id (decimal)
+ *   E = PollMessage.id (decimal)
+ * 
+ */ +public class PollMessageExternalKeyConverter extends Converter, String> { + + /** An exception thrown when an external key cannot be parsed. */ + public static class PollMessageExternalKeyParseException extends RuntimeException {} + + /** + * A map of IDs used in external keys corresponding to which EppResource class the poll message + * belongs to. + */ + public static final ImmutableBiMap, Long> EXTERNAL_KEY_CLASS_ID_MAP = + ImmutableBiMap., Long>of( + DomainBase.class, 1L, + ContactResource.class, 2L, + HostResource.class, 3L); + + @Override + protected String doForward(Key key) { + @SuppressWarnings("unchecked") + Key ancestorResource = + (Key) (Key) key.getParent().getParent(); + long externalKeyClassId = EXTERNAL_KEY_CLASS_ID_MAP.get( + ofy().factory().getMetadata(ancestorResource.getKind()).getEntityClass()); + return String.format("%d-%s-%d-%d", + externalKeyClassId, + ancestorResource.getName(), + key.getParent().getId(), + key.getId()); + } + + /** + * Returns an Objectify Key to a PollMessage corresponding with the external key string. + * + * @throws PollMessageExternalKeyParseException if the external key has an invalid format. + */ + @Override + protected Key doBackward(String externalKey) { + List idComponents = Splitter.on('-').splitToList(externalKey); + if (idComponents.size() != 5) { + throw new PollMessageExternalKeyParseException(); + } + try { + Class resourceClazz = + EXTERNAL_KEY_CLASS_ID_MAP.inverse().get(Long.parseLong(idComponents.get(0))); + if (resourceClazz == null) { + throw new PollMessageExternalKeyParseException(); + } + return Key.create( + Key.create( + Key.create( + null, + resourceClazz, + String.format("%s-%s", idComponents.get(1), idComponents.get(2))), + HistoryEntry.class, + Long.parseLong(idComponents.get(3))), + PollMessage.class, + Long.parseLong(idComponents.get(4))); + } catch (NumberFormatException e) { + throw new PollMessageExternalKeyParseException(); + } + } +} + diff --git a/java/com/google/domain/registry/model/poll/package-info.java b/java/com/google/domain/registry/model/poll/package-info.java new file mode 100644 index 000000000..7fa4a535a --- /dev/null +++ b/java/com/google/domain/registry/model/poll/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:epp-1.0", + xmlns = @XmlNs(prefix = "", namespaceURI = "urn:ietf:params:xml:ns:epp-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.poll; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/rde/RdeMode.java b/java/com/google/domain/registry/model/rde/RdeMode.java new file mode 100644 index 000000000..eef0d90ce --- /dev/null +++ b/java/com/google/domain/registry/model/rde/RdeMode.java @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.rde; + +import com.google.common.base.Ascii; + +/** Mode of operation for RDE and BRDA. */ +public enum RdeMode { + + /** Include all information is in the escrow deposit. */ + FULL, + + /** + * BRDA Periodic Access to Thin Registration Data. + * + *

This mode of operation provides ICANN with minimal information about registered domains + * and their associated registrars, per gTLD Registry Agreement, Specification 4 § 3.1. + * + * @see "http://newgtlds.icann.org/en/applicants/agb/agreement-approved-09jan14-en.htm" + */ + THIN; + + public String getFilenameComponent() { + return Ascii.toLowerCase(name()); + } +} diff --git a/java/com/google/domain/registry/model/rde/RdeNamingUtils.java b/java/com/google/domain/registry/model/rde/RdeNamingUtils.java new file mode 100644 index 000000000..d11bdae24 --- /dev/null +++ b/java/com/google/domain/registry/model/rde/RdeNamingUtils.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +/** Utility class for generating RDE filenames and string IDs. */ +public final class RdeNamingUtils { + + private static final DateTimeFormatter DATE_FORMATTER = ISODateTimeFormat.date(); + + /** + * Returns extensionless RDE filename in format {@code ___S<#>_R}. + * + *

This naming scheme is defined in the {@code gTLD_Applicant_Guidebook_full.pdf}. + */ + public static + String makeRydeFilename(String tld, DateTime date, RdeMode mode, int series, int revision) { + checkArgument(series >= 1, "series >= 1"); + checkArgument(revision >= 0, "revision >= 0"); + return String.format("%s_S%d_R%d", makePartialName(tld, date, mode), series, revision); + } + + /** Returns same thing as {@link #makeRydeFilename} except without the series and revision. */ + static String makePartialName(String tld, DateTime date, RdeMode mode) { + return String.format("%s_%s_%s", + checkNotNull(tld), formatDate(date), mode.getFilenameComponent()); + } + + /** Returns date as a hyphened string with ISO-8601 ordering, e.g. {@code 1984-12-18}. */ + private static String formatDate(DateTime date) { + checkArgument(date.withTimeAtStartOfDay().equals(date), "Not midnight: %s", date); + return DATE_FORMATTER.print(date); + } + + private RdeNamingUtils() {} +} diff --git a/java/com/google/domain/registry/model/rde/RdeRevision.java b/java/com/google/domain/registry/model/rde/RdeRevision.java new file mode 100644 index 000000000..c55d7280b --- /dev/null +++ b/java/com/google/domain/registry/model/rde/RdeRevision.java @@ -0,0 +1,89 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Verify.verify; +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.rde.RdeNamingUtils.makePartialName; + +import com.google.common.base.VerifyException; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +import org.joda.time.DateTime; + +/** + * Datastore entity for tracking RDE revisions. + * + *

This class is used by the RDE staging, upload, and reporting systems to determine the revision + * that should be used in the generated filename. It also determines whether or not a {@code resend} + * flag is included in the generated XML. + */ +@Entity +public final class RdeRevision extends ImmutableObject { + + /** String triplet of tld, date, and mode, e.g. {@code soy_2015-09-01_full}. */ + @Id + String id; + + /** + * Number of last revision successfully staged to GCS. + * + *

This values begins at zero upon object creation and thenceforth incremented transactionally. + */ + int revision; + + /** + * Returns next revision ID to use when staging a new deposit file for the given triplet. + * + * @return {@code 0} for first deposit generation and {@code >0} for resends + */ + public static int getNextRevision(String tld, DateTime date, RdeMode mode) { + RdeRevision object = + ofy().load().type(RdeRevision.class).id(makePartialName(tld, date, mode)).now(); + return object == null ? 0 : object.revision + 1; + } + + /** + * Sets the revision ID for a given triplet. + * + *

This method verifies that the current revision is {@code revision - 1}, or that the object + * does not exist in datastore if {@code revision == 0}. + * + * @throws IllegalStateException if not in a transaction + * @throws VerifyException if datastore state doesn't meet the above criteria + */ + public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) { + checkArgument(revision >= 0, "Negative revision: %s", revision); + String triplet = makePartialName(tld, date, mode); + ofy().assertInTransaction(); + RdeRevision object = ofy().load().type(RdeRevision.class).id(triplet).now(); + if (revision == 0) { + verify(object == null, "RdeRevision object already created: %s", object); + } else { + verifyNotNull(object, "RDE revision object missing for %s?! revision=%s", triplet, revision); + verify(object.revision == revision - 1, + "RDE revision object should be at %s but was: %s", revision - 1, object); + } + object = new RdeRevision(); + object.id = triplet; + object.revision = revision; + ofy().save().entity(object); + } +} diff --git a/java/com/google/domain/registry/model/registrar/Registrar.java b/java/com/google/domain/registry/model/registrar/Registrar.java new file mode 100644 index 000000000..5b3b218a7 --- /dev/null +++ b/java/com/google/domain/registry/model/registrar/Registrar.java @@ -0,0 +1,850 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registrar; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Predicates.in; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.common.io.BaseEncoding.base64; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.assertTldExists; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; +import static com.google.domain.registry.util.X509Utils.getCertificateHash; +import static com.google.domain.registry.util.X509Utils.loadCertificate; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.CreateAutoTimestamp; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.JsonMapBuilder; +import com.google.domain.registry.model.Jsonifiable; +import com.google.domain.registry.model.UpdateAutoTimestamp; +import com.google.domain.registry.model.common.EntityGroupRoot; +import com.google.domain.registry.util.CidrAddressBlock; +import com.google.domain.registry.util.NonFinalForTesting; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateParsingException; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.regex.Pattern; + +/** Information about a registrar. */ +@Cache +@Entity +public class Registrar extends ImmutableObject implements Buildable, Jsonifiable { + + /** Represents the type of a registrar entity. */ + public enum Type { + /** A real-world, third-party registrar. Should have non-null IANA and billing IDs. */ + REAL(Predicates.notNull()), + + /** + * A registrar account used by a real third-party registrar undergoing operational testing + * and evaluation. Should only be created in sandbox, and should have null IANA/billing IDs. + */ + OTE(Predicates.isNull()), + + /** + * A registrar used for predelegation testing. Should have a null billing ID. The IANA ID + * should be either 9995 or 9996, which are reserved for predelegation testing. + */ + PDT(in(ImmutableSet.of(9995L, 9996L))), + + /** + * A registrar used for external monitoring by ICANN. Should have IANA ID 9997 and a null + * billing ID. + */ + EXTERNAL_MONITORING(equalTo(9997L)), + + /** + * A registrar used for when the registry acts as a registrar. Must have either IANA ID + * 9998 (for billable transactions) or 9999 (for non-billable transactions). */ + // TODO(b/13786188): determine what billing ID for this should be, if any. + INTERNAL(in(ImmutableSet.of(9998L, 9999L))), + + /** A registrar used for internal monitoring. Should have null IANA/billing IDs. */ + MONITORING(Predicates.isNull()), + + /** A registrar used for internal testing. Should have null IANA/billing IDs. */ + TEST(Predicates.isNull()); + + /** + * Predicate for validating IANA IDs for this type of registrar. + * + * @see "http://www.iana.org/assignments/registrar-ids/registrar-ids.txt" + */ + private final Predicate ianaIdValidator; + + private Type(Predicate ianaIdValidator) { + this.ianaIdValidator = ianaIdValidator; + } + + /** Returns true if the given IANA identifier is valid for this registrar type. */ + public boolean isValidIanaId(Long ianaId) { + return ianaIdValidator.apply(ianaId); + } + } + + /** Represents the state of a persisted registrar entity. */ + public enum State { + /** + * This registrar is provisioned and may have access to the testing environment, but is not yet + * allowed to access the production environment. + */ + PENDING, + + /** This is an active registrar account which is allowed to provision and modify domains. */ + ACTIVE, + + /** + * This is a suspended account which is disallowed from provisioning new domains, but can + * otherwise still perform other operations to continue operations. + */ + SUSPENDED; + } + + /** Method for acquiring money from a registrar customer. */ + public enum BillingMethod { + + /** Billing method where billing invoice data is exported to an external accounting system. */ + EXTERNAL, + + /** Billing method where we accept Braintree credit card payments in the Registrar Console. */ + BRAINTREE; + } + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** Reports the type of data on file re: registrar certificates (full cert, hash only, none). */ + // Note: May be unnecessary, pending a conversation on how to best report on this data. + public enum CertificateState { NONE, CERTIFICATE_HASH, CERTIFICATE } + + /** Regex for E.164 phone number format specified by {@code contact.xsd}. */ + private static final Pattern E164_PATTERN = Pattern.compile("\\+[0-9]{1,3}\\.[0-9]{1,14}"); + + /** Regex for telephone support passcode (5 digit string). */ + public static final Pattern PHONE_PASSCODE_PATTERN = Pattern.compile("\\d{5}"); + + /** The states in which a {@link Registrar} is considered {@link #isActive active}. */ + private static final ImmutableSet ACTIVE_STATES = + Sets.immutableEnumSet(State.ACTIVE, State.SUSPENDED); + + /** + * The types for which a {@link Registrar} should be included in WHOIS and RDAP output. We exclude + * PDT and TEST. We considered excluding INTERNAL as well, but decided that troubleshooting would + * be easier with INTERNAL registrars visible. + */ + //TODO(b/27274151): Expand documentation of this field. + private static final ImmutableSet PUBLICLY_VISIBLE_TYPES = + Sets.immutableEnumSet( + Type.REAL, Type.OTE, Type.EXTERNAL_MONITORING, Type.MONITORING, Type.INTERNAL); + + @Parent + Key parent = getCrossTldKey(); + + /** + * Unique registrar client id. Must conform to "clIDType" as defined in RFC5730. + * @see "http://tools.ietf.org/html/rfc5730#section-4.2" + */ + @Id + String clientIdentifier; + + /** + * Registrar name. This is a distinct from the client identifier since there are no restrictions + * on its length. + *

+ * NB: We are assuming that this field is unique across all registrar entities. This is not + * formally enforced in our datastore, but should be enforced by ICANN in that no two registrars + * will be accredited with the same name. + * + * @see "http://www.icann.org/registrar-reports/accredited-list.html" + */ + @Index + String registrarName; + + /** The type of this registrar. */ + Type type; + + /** The state of this registrar. */ + State state; + + /** The set of TLDs which this registrar is allowed to access. */ + Set allowedTlds; + + /** Host name of WHOIS server. */ + String whoisServer; + + /** + * Whether registration of premium names should be blocked over EPP. If this is set to true, then + * the only way to register premium names is with the superuser flag. + */ + boolean blockPremiumNames; + + // Authentication. + + /** X.509 PEM client certificate(s) used to authenticate registrar to EPP service. */ + String clientCertificate; + + /** Base64 encoded SHA256 hash of {@link #clientCertificate}. */ + String clientCertificateHash; + + /** + * Optional secondary X.509 PEM certificate to try if {@link #clientCertificate} does not work. + * + *

This allows registrars to migrate certificates without downtime. + */ + String failoverClientCertificate; + + /** Base64 encoded SHA256 hash of {@link #failoverClientCertificate}. */ + String failoverClientCertificateHash; + + /** A whitelist of netmasks (in CIDR notation) which the client is allowed to connect from. */ + List ipAddressWhitelist; + + /** A hashed password for EPP access. The hash is a base64 encoded SHA256 string. */ + String passwordHash; + + /** Randomly generated hash salt. */ + String salt; + + // The following fields may appear redundant to the above, but are + // implied by RFC examples and should be interpreted as "for the + // Registrar as a whole". + /** + * Localized {@link RegistrarAddress} for this registrar. Contents can be represented in + * unrestricted UTF-8. + */ + @IgnoreSave(IfNull.class) + RegistrarAddress localizedAddress; + + /** + * Internationalized {@link RegistrarAddress} for this registrar. All contained values must be + * representable in the 7-bit US-ASCII character set. + */ + @IgnoreSave(IfNull.class) + RegistrarAddress internationalizedAddress; + + /** Voice number. */ + String phoneNumber; + + /** Fax number. */ + String faxNumber; + + /** Email address. */ + String emailAddress; + + // External IDs. + + /** + * Registrar identifier used for reporting to ICANN. + *

    + *
  • 8 is used for Testing Registrar. + *
  • 9997 is used by ICAAN for SLA monitoring. + *
  • 9999 is used for cases when the registry operator acts as registrar. + *
+ * @see "http://www.iana.org/assignments/registrar-ids/registrar-ids.txt" + */ + Long ianaIdentifier; + + /** Identifier of registrar used in external billing system (e.g. Oracle). */ + Long billingIdentifier; + + /** URL of registrar's website. */ + String url; + + /** Referral URL of registrar. */ + String referralUrl; + + /** + * ICANN referral email address. + * + *

This value is specified in the initial registrar contact. It can't be edited in the web GUI + * and it must be specified when the registrar account is created. + */ + String icannReferralEmail; + + /** Id of the folder in drive used to publish information for this registrar. */ + String driveFolderId; + + // Metadata. + + /** The time when this registrar was created. */ + CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null); + + /** An automatically managed last-saved timestamp. */ + UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null); + + /** + * The time that the certificate was last updated. + */ + DateTime lastCertificateUpdateTime; + + /** + * Telephone support passcode (5-digit numeric) + */ + String phonePasscode; + + /** + * A dirty bit for whether RegistrarContact changes have been made that haven't been synced to + * Google Groups yet. When creating a new instance, contacts require syncing by default. + */ + boolean contactsRequireSyncing = true; + + /** + * Method for receiving money from a registrar customer. + * + *

Each registrar may opt-in to their preferred billing method. This value can be changed at + * any time using the {@code update_registrar} command. + * + *

Note: This value should not be changed if the balance is non-zero. + */ + BillingMethod billingMethod; + + @NonFinalForTesting + private static Supplier saltSupplier = new Supplier() { + @Override + public byte[] get() { + // There are 32 bytes in a sha-256 hash, and the salt should generally be the same size. + byte[] salt = new byte[32]; + new SecureRandom().nextBytes(salt); + return salt; + }}; + + public String getClientIdentifier() { + return clientIdentifier; + } + + public DateTime getCreationTime() { + return creationTime.getTimestamp(); + } + + public Long getIanaIdentifier() { + return ianaIdentifier; + } + + public Long getBillingIdentifier() { + return billingIdentifier; + } + + public DateTime getLastUpdateTime() { + return lastUpdateTime.getTimestamp(); + } + + public DateTime getLastCertificateUpdateTime() { + return lastCertificateUpdateTime; + } + + public String getRegistrarName() { + return registrarName; + } + + public Type getType() { + return type; + } + + public State getState() { + return state; + } + + public ImmutableSortedSet getAllowedTlds() { + return nullToEmptyImmutableSortedCopy(allowedTlds); + } + + /** Returns {@code true} if registrar is active. */ + public boolean isActive() { + return ACTIVE_STATES.contains(state); + } + + /** Returns {@code true} if registrar should be visible in WHOIS results. */ + public boolean isActiveAndPubliclyVisible() { + return ACTIVE_STATES.contains(state) && PUBLICLY_VISIBLE_TYPES.contains(type); + } + + public CertificateState getCertificateState() { + if (!isNullOrEmpty(clientCertificate)) { + return CertificateState.CERTIFICATE; + } else if (!isNullOrEmpty(clientCertificateHash)) { + return CertificateState.CERTIFICATE_HASH; + } else { + return CertificateState.NONE; + } + } + + public String getClientCertificate() { + return clientCertificate; + } + + public String getClientCertificateHash() { + return clientCertificateHash; + } + + public String getFailoverClientCertificate() { + return failoverClientCertificate; + } + + public String getFailoverClientCertificateHash() { + return failoverClientCertificateHash; + } + + public ImmutableList getIpAddressWhitelist() { + return nullToEmptyImmutableCopy(ipAddressWhitelist); + } + + public RegistrarAddress getLocalizedAddress() { + return localizedAddress; + } + + public RegistrarAddress getInternationalizedAddress() { + return internationalizedAddress; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public String getFaxNumber() { + return faxNumber; + } + + public String getEmailAddress() { + return emailAddress; + } + + public String getWhoisServer() { + if (whoisServer == null) { + return ENVIRONMENT.config().getRegistrarDefaultWhoisServer(); + } + return whoisServer; + } + + public boolean getBlockPremiumNames() { + return blockPremiumNames; + } + + public boolean getContactsRequireSyncing() { + return contactsRequireSyncing; + } + + public String getUrl() { + return url; + } + + public String getReferralUrl() { + if (referralUrl == null) { + return ENVIRONMENT.config().getRegistrarDefaultReferralUrl().toString(); + } + return referralUrl; + } + + public String getIcannReferralEmail() { + return nullToEmpty(icannReferralEmail); + } + + public String getDriveFolderId() { + return driveFolderId; + } + + public BillingMethod getBillingMethod() { + return firstNonNull(billingMethod, BillingMethod.EXTERNAL); + } + + /** + * Returns a list of all {@link RegistrarContact} objects for this registrar sorted by their email + * address. + */ + public ImmutableSortedSet getContacts() { + return FluentIterable + .from(ofy().load().type(RegistrarContact.class).ancestor(Registrar.this)) + .filter(notNull()) + .toSortedSet(new Comparator() { + @Override + public int compare(RegistrarContact rc1, RegistrarContact rc2) { + return rc1.getEmailAddress().compareTo(rc2.getEmailAddress()); + }}); + } + + @Override + public Map toJsonMap() { + return new JsonMapBuilder() + .put("clientIdentifier", clientIdentifier) + .put("ianaIdentifier", ianaIdentifier) + .put("billingIdentifier", billingIdentifier) + .putString("creationTime", creationTime.getTimestamp()) + .putString("lastUpdateTime", lastUpdateTime.getTimestamp()) + .putString("lastCertificateUpdateTime", lastCertificateUpdateTime) + .put("registrarName", registrarName) + .put("type", type) + .put("state", state) + .put("clientCertificate", clientCertificate) + .put("clientCertificateHash", clientCertificateHash) + .put("failoverClientCertificate", failoverClientCertificate) + .put("failoverClientCertificateHash", failoverClientCertificateHash) + .put("localizedAddress", localizedAddress) + .put("internationalizedAddress", internationalizedAddress) + .put("phoneNumber", phoneNumber) + .put("faxNumber", faxNumber) + .put("emailAddress", emailAddress) + .put("whoisServer", getWhoisServer()) + .put("blockPremiumNames", blockPremiumNames) + .put("url", url) + .put("referralUrl", getReferralUrl()) + .put("icannReferralEmail", getIcannReferralEmail()) + .put("driveFolderId", driveFolderId) + .put("phoneNumber", phoneNumber) + .put("phonePasscode", phonePasscode) + .putListOfStrings("allowedTlds", getAllowedTlds()) + .putListOfStrings("ipAddressWhitelist", ipAddressWhitelist) + .putListOfJsonObjects("contacts", getContacts()) + .build(); + } + + private String hashPassword(String password) { + try { + return base64().encode( + MessageDigest.getInstance("SHA-256").digest( + (password + salt).getBytes(UTF_8))); + } catch (NoSuchAlgorithmException e) { + // All implementations of MessageDigest are required to support SHA-256. + throw Throwables.propagate(e); + } + } + + private static String checkValidPhoneNumber(String phoneNumber) { + checkArgument( + E164_PATTERN.matcher(phoneNumber).matches(), + "Not a valid E.164 phone number: %s", phoneNumber); + return phoneNumber; + } + + public boolean testPassword(String password) { + return hashPassword(password).equals(passwordHash); + } + + public String getPhonePasscode() { + return phonePasscode; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link Registrar}, since it is immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(Registrar instance) { + super(instance); + } + + public Builder setClientIdentifier(String clientIdentifier) { + // Client id must be [3,16] chars long. See "clIDType" in the base EPP schema of RFC 5730. + // (Need to validate this here as there's no matching EPP XSD for validation.) + checkArgument(clientIdentifier.length() >= 3 && clientIdentifier.length() <= 16, + "Client identifier must be 3-16 characters long."); + getInstance().clientIdentifier = clientIdentifier; + return this; + } + + public Builder setIanaIdentifier(Long ianaIdentifier) { + checkArgument(ianaIdentifier == null || ianaIdentifier > 0, + "IANA ID must be a positive number"); + getInstance().ianaIdentifier = ianaIdentifier; + return this; + } + + public Builder setBillingIdentifier(Long billingIdentifier) { + checkArgument(billingIdentifier == null || billingIdentifier > 0, + "Billing ID must be a positive number"); + getInstance().billingIdentifier = billingIdentifier; + return this; + } + + public Builder setRegistrarName(String registrarName) { + getInstance().registrarName = registrarName; + return this; + } + + public Builder setType(Type type) { + getInstance().type = type; + return this; + } + + public Builder setState(State state) { + getInstance().state = state; + return this; + } + + public Builder setAllowedTlds(Set allowedTlds) { + for (String tld : allowedTlds) { + assertTldExists(tld); + } + getInstance().allowedTlds = ImmutableSortedSet.copyOf(allowedTlds); + return this; + } + + public Builder setClientCertificate(String clientCertificate, DateTime now) { + clientCertificate = emptyToNull(clientCertificate); + String clientCertificateHash = calculateHash(clientCertificate); + if (!Objects.equals(clientCertificate, getInstance().clientCertificate) + || !Objects.equals(clientCertificateHash, getInstance().clientCertificateHash)) { + getInstance().clientCertificate = clientCertificate; + getInstance().clientCertificateHash = clientCertificateHash; + getInstance().lastCertificateUpdateTime = now; + } + return this; + } + + public Builder setFailoverClientCertificate(String clientCertificate, DateTime now) { + clientCertificate = emptyToNull(clientCertificate); + String clientCertificateHash = calculateHash(clientCertificate); + if (!Objects.equals(clientCertificate, getInstance().failoverClientCertificate) + || !Objects.equals(clientCertificateHash, getInstance().failoverClientCertificateHash)) { + getInstance().failoverClientCertificate = clientCertificate; + getInstance().failoverClientCertificateHash = clientCertificateHash; + getInstance().lastCertificateUpdateTime = now; + } + return this; + } + + private static String calculateHash(String clientCertificate) { + if (clientCertificate == null) { + return null; + } + try { + return getCertificateHash(loadCertificate(clientCertificate)); + } catch (CertificateParsingException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Sets client certificate hash, but not the certificate. + * + *

Warning: {@link #setClientCertificate(String, DateTime)} sets the hash for you and + * is preferred. Calling this method will nullify the {@code clientCertificate} field. + */ + public Builder setClientCertificateHash(String clientCertificateHash) { + if (clientCertificateHash != null) { + checkArgument(Pattern.matches("[A-Za-z0-9+/]+", clientCertificateHash), + "--cert_hash not a valid base64 (no padding) value"); + checkArgument(base64().decode(clientCertificateHash).length == 256 / 8, + "--cert_hash base64 does not decode to 256 bits"); + } + getInstance().clientCertificate = null; + getInstance().clientCertificateHash = clientCertificateHash; + return this; + } + + public Builder setContactsRequireSyncing(boolean contactsRequireSyncing) { + getInstance().contactsRequireSyncing = contactsRequireSyncing; + return this; + } + + public Builder setIpAddressWhitelist(Iterable ipAddressWhitelist) { + getInstance().ipAddressWhitelist = ImmutableList.copyOf(ipAddressWhitelist); + return this; + } + + public Builder setLocalizedAddress(RegistrarAddress localizedAddress) { + getInstance().localizedAddress = localizedAddress; + return this; + } + + public Builder setInternationalizedAddress(RegistrarAddress internationalizedAddress) { + getInstance().internationalizedAddress = internationalizedAddress; + return this; + } + + public Builder setPhoneNumber(String phoneNumber) { + getInstance().phoneNumber = (phoneNumber == null) + ? null + : checkValidPhoneNumber(phoneNumber); + return this; + } + + public Builder setFaxNumber(String faxNumber) { + getInstance().faxNumber = (faxNumber == null) + ? null + : checkValidPhoneNumber(faxNumber); + return this; + } + + public Builder setEmailAddress(String emailAddress) { + getInstance().emailAddress = emailAddress; + return this; + } + + public Builder setWhoisServer(String whoisServer) { + getInstance().whoisServer = whoisServer; + return this; + } + + public Builder setBlockPremiumNames(boolean blockPremiumNames) { + getInstance().blockPremiumNames = blockPremiumNames; + return this; + } + + public Builder setUrl(String url) { + getInstance().url = url; + return this; + } + + public Builder setReferralUrl(String referralUrl) { + getInstance().referralUrl = referralUrl; + return this; + } + + public Builder setIcannReferralEmail(String icannReferralEmail) { + getInstance().icannReferralEmail = icannReferralEmail; + return this; + } + + public Builder setDriveFolderId(String driveFolderId) { + getInstance().driveFolderId = driveFolderId; + return this; + } + + public Builder setBillingMethod(BillingMethod billingMethod) { + getInstance().billingMethod = billingMethod; + return this; + } + + public Builder setPassword(String password) { + // Passwords must be [6,16] chars long. See "pwType" in the base EPP schema of RFC 5730. + checkArgument(password != null && password.length() >= 6 && password.length() <= 16, + "Password must be [6,16] characters long."); + getInstance().salt = base64().encode(saltSupplier.get()); + getInstance().passwordHash = getInstance().hashPassword(password); + return this; + } + + /** @throws IllegalArgumentException if provided passcode is not 5-digit numeric */ + public Builder setPhonePasscode(String phonePasscode) { + checkArgument(phonePasscode == null + || PHONE_PASSCODE_PATTERN.matcher(phonePasscode).matches(), + "Not a valid telephone passcode (must be 5 digits long): %s", phonePasscode); + getInstance().phonePasscode = phonePasscode; + return this; + } + + /** Build the registrar, nullifying empty fields. */ + @Override + public Registrar build() { + checkNotNull(getInstance().type, "Registrar type cannot be null"); + checkArgument(getInstance().type.isValidIanaId(getInstance().ianaIdentifier), + String.format("Supplied IANA ID is not valid for %s registrar type: %s", + getInstance().type, getInstance().ianaIdentifier)); + return cloneEmptyToNull(super.build()); + } + } + + /** Load a registrar entity by its client id. */ + public static Registrar loadByClientId(final String clientId) { + return ofy().doTransactionless(new Work() { + @Override + public Registrar run() { + return ofy().load() + .type(Registrar.class) + .parent(getCrossTldKey()) + .id(clientId) + .now(); + }}); + } + + /** + * Load registrar entities by client id range. + * + * @param clientIdStart returned registrars will have a client id greater than or equal to this + * @param clientIdAfterEnd returned registrars will have a client id less than this + * @param resultSetMaxSize the maximum number of registrar entities to be returned + */ + public static Iterable loadByClientIdRange( + final String clientIdStart, final String clientIdAfterEnd, final int resultSetMaxSize) { + return ofy().doTransactionless(new Work>() { + @Override + public Iterable run() { + return ofy().load() + .type(Registrar.class) + .filterKey(">=", Key.create(getCrossTldKey(), Registrar.class, clientIdStart)) + .filterKey("<", Key.create(getCrossTldKey(), Registrar.class, clientIdAfterEnd)) + .limit(resultSetMaxSize); + }}); + } + + /** Loads all registrar entities. */ + public static Iterable loadAll() { + return ofy().load().type(Registrar.class).ancestor(getCrossTldKey()); + } + + /** Loads all active registrar entities. */ + public static FluentIterable loadAllActive() { + return FluentIterable.from(loadAll()).filter(IS_ACTIVE); + } + + private static final Predicate IS_ACTIVE = new Predicate() { + @Override + public boolean apply(Registrar registrar) { + return registrar.isActive(); + }}; + + /** Loads all active registrar entities. */ + public static FluentIterable loadAllActiveAndPubliclyVisible() { + return FluentIterable.from(loadAll()).filter(IS_ACTIVE_AND_PUBLICLY_VISIBLE); + } + + private static final Predicate IS_ACTIVE_AND_PUBLICLY_VISIBLE = + new Predicate() { + @Override + public boolean apply(Registrar registrar) { + return registrar.isActiveAndPubliclyVisible(); + }}; +} diff --git a/java/com/google/domain/registry/model/registrar/RegistrarAddress.java b/java/com/google/domain/registry/model/registrar/RegistrarAddress.java new file mode 100644 index 000000000..e80b02d09 --- /dev/null +++ b/java/com/google/domain/registry/model/registrar/RegistrarAddress.java @@ -0,0 +1,45 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registrar; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull; + +import com.google.domain.registry.model.eppcommon.Address; + +import com.googlecode.objectify.annotation.Embed; + +/** + * Registrar Address + *

+ * This class is embedded inside a {@link Registrar} object to hold its address. The fields are all + * defined in parent class {@link Address} so that it can share it with other similar address + * classes. + */ +@Embed +public class RegistrarAddress extends Address { + + /** Builder for {@link RegistrarAddress}. */ + public static class Builder extends Address.Builder { + @Override + public RegistrarAddress build() { + RegistrarAddress instance = getInstance(); + checkNotNull(forceEmptyToNull(instance.getStreet()), "Missing street"); + checkNotNull(instance.getCity(), "Missing city"); + checkNotNull(instance.getCountryCode(), "Missing country code"); + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/registrar/RegistrarContact.java b/java/com/google/domain/registry/model/registrar/RegistrarContact.java new file mode 100644 index 000000000..829a8ce9b --- /dev/null +++ b/java/com/google/domain/registry/model/registrar/RegistrarContact.java @@ -0,0 +1,318 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registrar; + +import static com.google.common.base.Functions.toStringFunction; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Sets.difference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; +import static com.google.domain.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS; + +import com.google.common.base.Enums; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.JsonMapBuilder; +import com.google.domain.registry.model.Jsonifiable; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only + * enable key equality. + * + *

IMPORTANT NOTE: Any time that you change, update, or delete RegistrarContact entities, you + * *MUST* also modify the persisted Registrar entity with {@link Registrar#contactsRequireSyncing} + * set to true. + */ +@Cache +@Entity +public class RegistrarContact extends ImmutableObject implements Jsonifiable { + + @Parent + Key parent; + + /** + * Registrar contacts types for partner communication tracking. + * + *

Note: These types only matter to the registry. They are not meant to be used for + * WHOIS or RDAP results. + */ + public enum Type { + ABUSE("abuse", true), + ADMIN("primary", true), + BILLING("billing", true), + LEGAL("legal", true), + MARKETING("marketing", false), + TECH("technical", true), + WHOIS("whois-inquiry", true); + + private final String displayName; + + private final boolean required; + + public String getDisplayName() { + return displayName; + } + + public boolean isRequired() { + return required; + } + + private Type(String display, boolean required) { + this.displayName = display; + this.required = required; + } + } + + /** The name of the contact. */ + String name; + + /** The email address of the contact. */ + @Id + String emailAddress; + + /** The voice number of the contact. */ + String phoneNumber; + + /** The fax number of the contact. */ + String faxNumber; + + /** + * Multiple types are used to associate the registrar contact with + * various mailing groups. This data is internal to the registry. + */ + Set types; + + /** + * A GAE user ID allowed to act as this registrar contact. + * + *

This can be derived from a known email address using http://email-to-gae-id.appspot.com. + * + * @see com.google.appengine.api.users.User#getUserId() + */ + @Index + String gaeUserId; + + /** + * Whether this contact is publicly visible in WHOIS results as an Admin contact. + */ + boolean visibleInWhoisAsAdmin = false; + + /** + * Whether this contact is publicly visible in WHOIS results as a Technical contact. + */ + boolean visibleInWhoisAsTech = false; + + public static ImmutableSet typesFromCSV(String csv) { + return typesFromStrings(Arrays.asList(csv.split(","))); + } + + public static ImmutableSet typesFromStrings(Iterable typeNames) { + return FluentIterable.from(typeNames).transform(Enums.stringConverter(Type.class)).toSet(); + } + + /** + * Helper to update the contacts associated with a Registrar. This requires querying for the + * existing contacts, deleting existing contacts that are not part of the given {@code contacts} + * set, and then saving the given {@code contacts}. + * + *

IMPORTANT NOTE: If you call this method then it is your responsibility to also persist the + * relevant Registrar entity with the {@link Registrar#contactsRequireSyncing} field set to true. + */ + public static void updateContacts( + final Registrar registrar, final Set contacts) { + ofy().transact(new VoidWork() { + @Override + public void vrun() { + ofy().delete().keys(difference( + ImmutableSet.copyOf( + ofy().load().type(RegistrarContact.class).ancestor(registrar).keys()), + FluentIterable.from(contacts).transform(OBJECTS_TO_KEYS).toSet())); + ofy().save().entities(contacts); + }}); + } + + public Key getParent() { + return parent; + } + + public String getName() { + return name; + } + + public String getEmailAddress() { + return emailAddress; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public String getFaxNumber() { + return faxNumber; + } + + public ImmutableSortedSet getTypes() { + return nullToEmptyImmutableSortedCopy(types); + } + + public boolean getVisibleInWhoisAsAdmin() { + return visibleInWhoisAsAdmin; + } + + public boolean getVisibleInWhoisAsTech() { + return visibleInWhoisAsTech; + } + + public String getGaeUserId() { + return gaeUserId; + } + + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** + * Returns a string representation that's human friendly. + * + *

The output will look something like this:

   {@code
+   *
+   *   Some Person
+   *   person@example.com
+   *   Tel: +1.2125650666
+   *   Types: [ADMIN, WHOIS]
+   *   Visible in WHOIS as Admin contact: Yes
+   *   Visible in WHOIS as Technical contact: No
+   *   GAE-UserID: 1234567890}
+ */ + public String toStringMultilinePlainText() { + StringBuilder result = new StringBuilder(256); + result.append(getName()).append('\n'); + result.append(getEmailAddress()).append('\n'); + if (phoneNumber != null) { + result.append("Tel: ").append(getPhoneNumber()).append('\n'); + } + if (faxNumber != null) { + result.append("Fax: ").append(getFaxNumber()).append('\n'); + } + result.append("Types: ").append(getTypes()).append('\n'); + result.append("Visible in WHOIS as Admin contact: ") + .append(getVisibleInWhoisAsAdmin() ? "Yes" : "No") + .append("\n"); + result.append("Visible in WHOIS as Technical contact: ") + .append(getVisibleInWhoisAsTech() ? "Yes" : "No") + .append("\n"); + if (getGaeUserId() != null) { + result.append("GAE-UserID: ").append(getGaeUserId()).append('\n'); + } + return result.toString(); + } + + @Override + public Map toJsonMap() { + return new JsonMapBuilder() + .put("name", name) + .put("emailAddress", emailAddress) + .put("phoneNumber", phoneNumber) + .put("faxNumber", faxNumber) + .put("types", Joiner.on(',').join(transform(getTypes(), toStringFunction()))) + .put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin) + .put("visibleInWhoisAsTech", visibleInWhoisAsTech) + .put("gaeUserId", gaeUserId) + .build(); + } + + /** A builder for constructing a {@link RegistrarContact}, since it is immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(RegistrarContact instance) { + super(instance); + } + + public Builder setParent(Registrar parent) { + return this.setParent(Key.create(parent)); + } + + public Builder setParent(Key parentKey) { + getInstance().parent = parentKey; + return this; + } + + /** Build the registrar, nullifying empty fields. */ + @Override + public RegistrarContact build() { + checkNotNull(getInstance().parent, "Registrar parent cannot be null"); + checkNotNull(getInstance().emailAddress, "Email address cannot be null"); + return cloneEmptyToNull(super.build()); + } + + public Builder setName(String name) { + getInstance().name = name; + return this; + } + + public Builder setEmailAddress(String emailAddress) { + getInstance().emailAddress = emailAddress; + return this; + } + + public Builder setPhoneNumber(String phoneNumber) { + getInstance().phoneNumber = phoneNumber; + return this; + } + + public Builder setFaxNumber(String faxNumber) { + getInstance().faxNumber = faxNumber; + return this; + } + + public Builder setTypes(Iterable types) { + getInstance().types = ImmutableSet.copyOf(types); + return this; + } + + public Builder setVisibleInWhoisAsAdmin(boolean visible) { + getInstance().visibleInWhoisAsAdmin = visible; + return this; + } + + public Builder setVisibleInWhoisAsTech(boolean visible) { + getInstance().visibleInWhoisAsTech = visible; + return this; + } + + public Builder setGaeUserId(String gaeUserId) { + getInstance().gaeUserId = gaeUserId; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/registry/Registries.java b/java/com/google/domain/registry/model/registry/Registries.java new file mode 100644 index 000000000..3591549c4 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/Registries.java @@ -0,0 +1,112 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.collect.Maps.filterValues; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CacheUtils.memoizeWithShortExpiration; + +import com.google.common.base.Optional; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.model.registry.Registry.TldType; + +import com.googlecode.objectify.Work; + +/** Utilities for finding and listing {@link Registry} entities. */ +public final class Registries { + + private Registries() {} + + /** Supplier of a cached registries map. */ + private static Supplier> cache = createFreshCache(); + + /** + * Returns a newly-created Supplier of a registries to types map. + * + *

The supplier's get() method enters a transactionless context briefly to avoid enrolling the + * query inside an unrelated client-affecting transaction. + */ + private static Supplier> createFreshCache() { + return memoizeWithShortExpiration(new Supplier>() { + @Override + public ImmutableMap get() { + return ofy().doTransactionless(new Work>() { + @Override + public ImmutableMap run() { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (Registry registry : ofy().load().type(Registry.class).ancestor(getCrossTldKey())) { + builder.put(registry.getTldStr(), registry.getTldType()); + } + return builder.build(); + }}); + }}); + } + + /** Manually reset the static cache backing the methods on this class. */ + // TODO(b/24903801): offer explicit cached and uncached paths instead. + public static void resetCache() { + cache = createFreshCache(); + } + + public static ImmutableSet getTlds() { + return cache.get().keySet(); + } + + public static ImmutableSet getTldsOfType(TldType type) { + return ImmutableSet.copyOf(filterValues(cache.get(), equalTo(type)).keySet()); + } + + /** Shortcut to check whether a tld exists or else throw. If it exists, it is returned back. */ + public static String assertTldExists(String tld) { + checkArgument( + getTlds().contains(checkNotNull(emptyToNull(tld), "Null or empty TLD specified")), + "TLD %s does not exist", + tld); + return tld; + } + + /** + * Returns the TLD which the domain name or hostname falls under, no matter how many levels of + * subdomains there are. + */ + public static Optional findTldForName(InternetDomainName domainName) { + ImmutableSet tlds = getTlds(); + while (domainName.hasParent()) { + domainName = domainName.parent(); + if (tlds.contains(domainName.toString())) { + return Optional.of(domainName); + } + } + return Optional.absent(); + } + + /** + * Returns the registered TLD which this domain name falls under, or throws an exception if no + * match exists. + */ + public static InternetDomainName findTldForNameOrThrow(InternetDomainName domainName) { + return checkNotNull( + findTldForName(domainName).orNull(), + "Domain name is not under a recognized TLD: %s", domainName.toString()); + } +} diff --git a/java/com/google/domain/registry/model/registry/Registry.java b/java/com/google/domain/registry/model/registry/Registry.java new file mode 100644 index 000000000..bfcd937d5 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/Registry.java @@ -0,0 +1,782 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Predicates.not; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.label.PremiumList.getPremiumPrice; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.joda.money.CurrencyUnit.USD; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Ordering; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.BackupGroupRoot; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.CreateAutoTimestamp; +import com.google.domain.registry.model.common.EntityGroupRoot; +import com.google.domain.registry.model.common.TimedTransitionProperty; +import com.google.domain.registry.model.common.TimedTransitionProperty.TimedTransition; +import com.google.domain.registry.model.registry.label.PremiumList; +import com.google.domain.registry.model.registry.label.ReservedList; +import com.google.domain.registry.util.Idn; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Mapify; +import com.googlecode.objectify.annotation.OnSave; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.Set; + +/** Persisted per-TLD configuration data. */ +@Cache +@Entity +public class Registry extends BackupGroupRoot implements Buildable { + + @Parent + Key parent = getCrossTldKey(); + + @Id + /** + * The canonical string representation of the TLD associated with this {@link Registry}, which + * is the standard ASCII for regular TLDs and punycoded ASCII for IDN TLDs. + */ + String tldStrId; + + /** + * A duplicate of {@link #tldStrId}, to simplify BigQuery reporting since the id field becomes + * {@code __key__.name} rather than being exported as a named field. + */ + String tldStr; + + /** + * The suffix that identifies roids as belonging to this specific tld, e.g. -HOW for .how. + */ + String roidSuffix; + + /** Default values for all the relevant TLD parameters. */ + public static final TldState DEFAULT_TLD_STATE = TldState.PREDELEGATION; + public static final boolean DEFAULT_ESCROW_ENABLED = false; + public static final boolean DEFAULT_DNS_PAUSED = false; + public static final Duration DEFAULT_ADD_GRACE_PERIOD = Duration.standardDays(5); + public static final Duration DEFAULT_SUNRUSH_ADD_GRACE_PERIOD = Duration.standardDays(30); + public static final Duration DEFAULT_AUTO_RENEW_GRACE_PERIOD = Duration.standardDays(45); + public static final Duration DEFAULT_REDEMPTION_GRACE_PERIOD = Duration.standardDays(30); + public static final Duration DEFAULT_RENEW_GRACE_PERIOD = Duration.standardDays(5); + public static final Duration DEFAULT_TRANSFER_GRACE_PERIOD = Duration.standardDays(5); + public static final Duration DEFAULT_AUTOMATIC_TRANSFER_LENGTH = Duration.standardDays(5); + public static final Duration DEFAULT_PENDING_DELETE_LENGTH = Duration.standardDays(5); + public static final Duration DEFAULT_ANCHOR_TENANT_ADD_GRACE_PERIOD = Duration.standardDays(30); + public static final CurrencyUnit DEFAULT_CURRENCY = USD; + public static final Money DEFAULT_CREATE_BILLING_COST = Money.of(USD, 8); + public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8); + public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100); + public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20); + + /** The type of TLD, which determines things like backups and escrow policy. */ + public enum TldType { + /** A real, official TLD. */ + REAL, + + /** A test TLD, for the prober. */ + TEST + } + + /** + * The states a TLD can be in at any given point in time. The ordering below is the required + * sequence of states (ignoring {@link #PDT} which is a pseudo-state). + */ + public enum TldState { + /** The state of not yet being delegated to this registry in the root zone by IANA. */ + PREDELEGATION, + + /** + * The state in which only trademark holders can submit applications for domains. Doing so + * requires a claims notice to be submitted with the application. + * */ + SUNRISE, + + /** + * The state representing the overlap of {@link #SUNRISE} with a "landrush" state in which + * anyone can submit an application for a domain name. Sunrise applications may continue + * during landrush, so we model the overlap as a distinct state named "sunrush". + */ + SUNRUSH, + + /** + * The state in which anyone can submit an application for a domain name. Sunrise applications + * are not allowed during this phase. + */ + LANDRUSH, + + /** + * A state in which no domain operations are permitted. Generally used after sunrise or + * landrush to allocate uncontended applications and send contended applications to auction. + * This state is special in that it has no ordering constraints and can appear after any phase. + */ + QUIET_PERIOD, + + /** The steady state of a TLD in which all SLDs are available via first-come, first-serve. */ + GENERAL_AVAILABILITY, + + /** A "fake" state for use in predelegation testing. Acts like {@link #GENERAL_AVAILABILITY}. */ + PDT + } + + /** + * A transition to a TLD state at a specific time, for use in a TimedTransitionProperty. + * Public because AppEngine's security manager requires this for instantiation via reflection. + */ + @Embed + public static class TldStateTransition extends TimedTransition { + /** The TLD state. */ + private TldState tldState; + + @Override + public TldState getValue() { + return tldState; + } + + @Override + protected void setValue(TldState tldState) { + this.tldState = tldState; + } + } + + /** + * A transition to a given billing cost at a specific time, for use in a TimedTransitionProperty. + * Public because AppEngine's security manager requires this for instantiation via reflection. + */ + @Embed + public static class BillingCostTransition extends TimedTransition { + /** The billing cost value. */ + private Money billingCost; + + @Override + public Money getValue() { + return billingCost; + } + + @Override + protected void setValue(Money billingCost) { + this.billingCost = billingCost; + } + } + + /** A cache that loads the {@link Registry} for a given tld. */ + private static final LoadingCache> CACHE = CacheBuilder.newBuilder() + .expireAfterWrite( + RegistryEnvironment.get().config().getSingletonCacheRefreshDuration().getMillis(), + MILLISECONDS) + .build(new CacheLoader>() { + @Override + public Optional load(final String tld) { + // Enter a transactionless context briefly; we don't want to enroll every TLD in a + // transaction that might be wrapping this call, and memcached results are fine here. + return Optional.fromNullable(ofy().doTransactionless(new Work() { + @Override + public Registry run() { + return ofy() + .load() + .key(Key.create(getCrossTldKey(), Registry.class, tld)) + .now(); + }})); + }}); + + /** Returns the registry for a given TLD, throwing if none exists. */ + public static Registry get(String tld) { + Registry registry = CACHE.getUnchecked(tld).orNull(); + if (registry == null) { + throw new RegistryNotFoundException(tld); + } + return registry; + } + + /** Whenever a registry is saved, invalidate the cache entry. */ + @OnSave + void updateCache() { + CACHE.invalidate(tldStr); + } + + /** + * The unicode-aware representation of the TLD associated with this {@link Registry}. + *

+ * This will be equal to {@link #tldStr} for ASCII TLDs, but will be non-ASCII for IDN TLDs. + * We store this in a field so that it will be retained upon import into BigQuery. + */ + String tldUnicode; + + /** Id of the folder in drive used to publish information for this TLD. */ + String driveFolderId; + + /** The type of the TLD, whether it's real or for testing. */ + TldType tldType = TldType.REAL; + + /** + * A property that transitions to different TldStates at different times. Stored as a list + * of TldStateTransition embedded objects using the @Mapify annotation. + */ + @Mapify(TimedTransitionProperty.TimeMapper.class) + TimedTransitionProperty tldStateTransitions = + TimedTransitionProperty.forMapify( + ImmutableSortedMap.of(START_OF_TIME, DEFAULT_TLD_STATE), + TldStateTransition.class); + + /** An automatically managed creation timestamp. */ + CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null); + + /** The set of reserved lists that are applicable to this registry. */ + Set> reservedLists; + + /** Retrieves an ImmutableSet of all ReservedLists associated with this tld. */ + public ImmutableSet> getReservedLists() { + return nullToEmptyImmutableCopy(reservedLists); + } + + /** The {@link PremiumList} for this TLD. */ + Key premiumList; + + /** Should RDE upload a nightly escrow deposit for this TLD? */ + boolean escrowEnabled = DEFAULT_ESCROW_ENABLED; + + /** Whether the pull queue that writes to authoritative DNS is paused for this TLD. */ + boolean dnsPaused = DEFAULT_DNS_PAUSED; + + /** Whether the price must be acknowledged to register premiun names on this TLD. */ + boolean premiumPriceAckRequired = true; + + /** The length of the add grace period for this TLD. */ + Duration addGracePeriodLength = DEFAULT_ADD_GRACE_PERIOD; + + /** The length of the add grace period for this TLD. */ + Duration anchorTenantAddGracePeriodLength = DEFAULT_ANCHOR_TENANT_ADD_GRACE_PERIOD; + + /** The length of the sunrush add grace period for this TLD. */ + Duration sunrushAddGracePeriodLength = DEFAULT_SUNRUSH_ADD_GRACE_PERIOD; + + /** The length of the auto renew grace period for this TLD. */ + Duration autoRenewGracePeriodLength = DEFAULT_AUTO_RENEW_GRACE_PERIOD; + + /** The length of the redemption grace period for this TLD. */ + Duration redemptionGracePeriodLength = DEFAULT_REDEMPTION_GRACE_PERIOD; + + /** The length of the renew grace period for this TLD. */ + Duration renewGracePeriodLength = DEFAULT_RENEW_GRACE_PERIOD; + + /** The length of the transfer grace period for this TLD. */ + Duration transferGracePeriodLength = DEFAULT_TRANSFER_GRACE_PERIOD; + + /** The length of time before a transfer is automatically approved for this TLD. */ + Duration automaticTransferLength = DEFAULT_AUTOMATIC_TRANSFER_LENGTH; + + /** The length of time a domain spends in the non-redeemable pending delete phase for this TLD. */ + Duration pendingDeleteLength = DEFAULT_PENDING_DELETE_LENGTH; + + /** The currency unit for all costs associated with this TLD. */ + CurrencyUnit currency = DEFAULT_CURRENCY; + + /** The per-year billing cost for registering a new domain name. */ + Money createBillingCost = DEFAULT_CREATE_BILLING_COST; + + /** The one-time billing cost for restoring a domain name from the redemption grace period. */ + Money restoreBillingCost = DEFAULT_RESTORE_BILLING_COST; + + /** The one-time billing cost for changing the server status (i.e. lock). */ + Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST; + + /** + * A property that transitions to different renew billing costs at different times. Stored as a + * list of BillingCostTransition embedded objects using the @Mapify annotation. + *

+ * A given value of this property represents the per-year billing cost for renewing a domain name. + * This cost is also used to compute costs for transfers, since each transfer includes a renewal + * to ensure transfers have a cost. + */ + @Mapify(TimedTransitionProperty.TimeMapper.class) + TimedTransitionProperty renewBillingCostTransitions = + TimedTransitionProperty.forMapify( + ImmutableSortedMap.of(START_OF_TIME, DEFAULT_RENEW_BILLING_COST), + BillingCostTransition.class); + + String lordnUsername; + + /** The end of the claims period (at or after this time, claims no longer applies). */ + DateTime claimsPeriodEnd = END_OF_TIME; + + public String getTldStr() { + return tldStr; + } + + public String getRoidSuffix() { + return roidSuffix; + } + + /** Retrieve the actual domain name representing the TLD for which this registry operates. */ + public InternetDomainName getTld() { + return InternetDomainName.from(tldStr); + } + + /** Retrieve the TLD type (real or test). */ + public TldType getTldType() { + return tldType; + } + + /** + * Retrieve the TLD state at the given time. Defaults to {@link TldState#PREDELEGATION}. + *

+ * Note that {@link TldState#PDT} TLDs pretend to be in {@link TldState#GENERAL_AVAILABILITY}. + */ + public TldState getTldState(DateTime now) { + TldState state = tldStateTransitions.getValueAtTime(now); + return TldState.PDT.equals(state) ? TldState.GENERAL_AVAILABILITY : state; + } + + /** Retrieve whether this TLD is in predelegation testing. */ + public boolean isPdt(DateTime now) { + return TldState.PDT.equals(tldStateTransitions.getValueAtTime(now)); + } + + public DateTime getCreationTime() { + return creationTime.getTimestamp(); + } + + public boolean getEscrowEnabled() { + return escrowEnabled; + } + + public boolean getDnsPaused() { + return dnsPaused; + } + + public String getDriveFolderId() { + return driveFolderId; + } + + public boolean getPremiumPriceAckRequired() { + return premiumPriceAckRequired; + } + + public Duration getAddGracePeriodLength() { + return addGracePeriodLength; + } + + public Duration getSunrushAddGracePeriodLength() { + return sunrushAddGracePeriodLength; + } + + public Duration getAutoRenewGracePeriodLength() { + return autoRenewGracePeriodLength; + } + + public Duration getRedemptionGracePeriodLength() { + return redemptionGracePeriodLength; + } + + public Duration getRenewGracePeriodLength() { + return renewGracePeriodLength; + } + + public Duration getTransferGracePeriodLength() { + return transferGracePeriodLength; + } + + public Duration getAutomaticTransferLength() { + return automaticTransferLength; + } + + public Duration getPendingDeleteLength() { + return pendingDeleteLength; + } + + public Duration getAnchorTenantAddGracePeriodLength() { + return anchorTenantAddGracePeriodLength; + } + + public Key getPremiumList() { + return premiumList; + } + + public CurrencyUnit getCurrency() { + return currency; + } + + /** Use {@link #getDomainCreateCost} instead of this to find the cost for a domain create. */ + @VisibleForTesting + public Money getStandardCreateCost() { + return createBillingCost; + } + + /** + * Returns the add-on cost of a domain restore (the flat registry-wide fee charged in addition to + * one year of renewal for that name). + */ + public Money getStandardRestoreCost() { + return restoreBillingCost; + } + + /** + * Use {@link #getDomainRenewCost} instead of this to find the cost for a domain renew, and all + * derived costs (i.e. autorenews, transfers, and the per-domain part of a restore cost). + */ + @VisibleForTesting + public Money getStandardRenewCost(DateTime now) { + return renewBillingCostTransitions.getValueAtTime(now); + } + + /** + * Returns the cost of a server status change (i.e. lock). + */ + public Money getServerStatusChangeCost() { + return serverStatusChangeBillingCost; + } + + public ImmutableSortedMap getTldStateTransitions() { + return tldStateTransitions.toValueMap(); + } + + public ImmutableSortedMap getRenewBillingCostTransitions() { + return renewBillingCostTransitions.toValueMap(); + } + + private Optional getPremiumPriceForSld(String sldName) { + return getPremiumPriceForSld(InternetDomainName.from(sldName)); + } + + private Optional getPremiumPriceForSld(InternetDomainName domainName) { + checkArgument(getTld().equals(domainName.parent()), + "Domain name %s is not an SLD for TLD %s", domainName.toString(), tldStr); + String label = domainName.parts().get(0); + return getPremiumPrice(label, tldStr); + } + + /** Returns true if the given domain name is on the premium price list. */ + public boolean isPremiumName(String domainName) { + return isPremiumName(InternetDomainName.from(domainName)); + } + + /** Returns true if the given domain name is on the premium price list. */ + public boolean isPremiumName(InternetDomainName domainName) { + return getPremiumPriceForSld(domainName).isPresent(); + } + + /** Returns the billing cost for registering the specified domain name for this many years. */ + public Money getDomainCreateCost(String domainName, int years) { + checkArgument(years > 0, "Number of years must be positive"); + Money annualCost = getPremiumPriceForSld(domainName).or(getStandardCreateCost()); + return annualCost.multipliedBy(years); + } + + /** Returns the billing cost for renewing the specified domain name for this many years. */ + public Money getDomainRenewCost(String domainName, int years, DateTime now) { + checkArgument(years > 0, "Number of years must be positive"); + Money annualCost = getPremiumPriceForSld(domainName).or(getStandardRenewCost(now)); + return annualCost.multipliedBy(years); + } + + public String getLordnUsername() { + return lordnUsername; + } + + public DateTime getClaimsPeriodEnd() { + return claimsPeriodEnd; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link Registry} objects, since they are immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(Registry instance) { + super(instance); + } + + public Builder setTldType(TldType tldType) { + getInstance().tldType = tldType; + return this; + } + + /** Sets the TLD state to transition to the specified states at the specified times. */ + public Builder setTldStateTransitions( + ImmutableSortedMap tldStatesMap) { + checkNotNull(tldStatesMap, "TLD states map cannot be null"); + // Filter out any entries with QUIET_PERIOD as the value before checking for ordering, since + // that phase is allowed to appear anywhere. + checkArgument(Ordering.natural().isStrictlyOrdered( + Iterables.filter(tldStatesMap.values(), not(equalTo(TldState.QUIET_PERIOD)))), + "The TLD states are chronologically out of order"); + getInstance().tldStateTransitions = + TimedTransitionProperty.fromValueMap(tldStatesMap, TldStateTransition.class); + return this; + } + + public Builder setTldStr(String tldStr) { + checkArgument(tldStr != null, "TLD must not be null."); + getInstance().tldStr = tldStr; + return this; + } + + public Builder setEscrowEnabled(boolean enabled) { + getInstance().escrowEnabled = enabled; + return this; + } + + public Builder setDnsPaused(boolean paused) { + getInstance().dnsPaused = paused; + return this; + } + + public Builder setDriveFolderId(String driveFolderId) { + getInstance().driveFolderId = driveFolderId; + return this; + } + + public Builder setPremiumPriceAckRequired(boolean premiumPriceAckRequired) { + getInstance().premiumPriceAckRequired = premiumPriceAckRequired; + return this; + } + + public Builder setAddGracePeriodLength(Duration addGracePeriodLength) { + checkArgument(addGracePeriodLength.isLongerThan(Duration.ZERO), + "addGracePeriodLength must be non-zero"); + getInstance().addGracePeriodLength = addGracePeriodLength; + return this; + } + + public Builder setSunrushAddGracePeriodLength(Duration sunrushAddGracePeriodLength) { + checkArgument(sunrushAddGracePeriodLength.isLongerThan(Duration.ZERO), + "sunrushAddGracePeriodLength must be non-zero"); + getInstance().sunrushAddGracePeriodLength = sunrushAddGracePeriodLength; + return this; + } + + /** Warning! Changing this will affect the billing time of autorenew events in the past. */ + public Builder setAutoRenewGracePeriodLength(Duration autoRenewGracePeriodLength) { + checkArgument(autoRenewGracePeriodLength.isLongerThan(Duration.ZERO), + "autoRenewGracePeriodLength must be non-zero"); + getInstance().autoRenewGracePeriodLength = autoRenewGracePeriodLength; + return this; + } + + public Builder setRedemptionGracePeriodLength(Duration redemptionGracePeriodLength) { + checkArgument(redemptionGracePeriodLength.isLongerThan(Duration.ZERO), + "redemptionGracePeriodLength must be non-zero"); + getInstance().redemptionGracePeriodLength = redemptionGracePeriodLength; + return this; + } + + public Builder setRenewGracePeriodLength(Duration renewGracePeriodLength) { + checkArgument(renewGracePeriodLength.isLongerThan(Duration.ZERO), + "renewGracePeriodLength must be non-zero"); + getInstance().renewGracePeriodLength = renewGracePeriodLength; + return this; + } + + public Builder setTransferGracePeriodLength(Duration transferGracePeriodLength) { + checkArgument(transferGracePeriodLength.isLongerThan(Duration.ZERO), + "transferGracePeriodLength must be non-zero"); + getInstance().transferGracePeriodLength = transferGracePeriodLength; + return this; + } + + public Builder setAutomaticTransferLength(Duration automaticTransferLength) { + checkArgument(automaticTransferLength.isLongerThan(Duration.ZERO), + "automaticTransferLength must be non-zero"); + getInstance().automaticTransferLength = automaticTransferLength; + return this; + } + + public Builder setPendingDeleteLength(Duration pendingDeleteLength) { + checkArgument(pendingDeleteLength.isLongerThan(Duration.ZERO), + "pendingDeleteLength must be non-zero"); + getInstance().pendingDeleteLength = pendingDeleteLength; + return this; + } + + public Builder setCurrency(CurrencyUnit currency) { + checkArgument(currency != null, "currency must be non-null"); + getInstance().currency = currency; + return this; + } + + public Builder setCreateBillingCost(Money amount) { + checkArgument(amount.isPositiveOrZero(), "billing costs must be non-negative"); + getInstance().createBillingCost = amount; + return this; + } + + public Builder setReservedListsByName(Set reservedListNames) { + checkArgument(reservedListNames != null, "reservedListNames must not be null"); + ImmutableSet.Builder> builder = new ImmutableSet.Builder<>(); + for (String reservedListName : reservedListNames) { + // Check for existence of the reserved list and throw an exception if it doesn't exist. + Optional reservedList = ReservedList.get(reservedListName); + if (!reservedList.isPresent()) { + throw new IllegalStateException( + "Could not find reserved list " + reservedListName + " to add to the tld"); + } + builder.add(Key.create(reservedList.get())); + } + getInstance().reservedLists = builder.build(); + return this; + } + + public Builder setReservedLists(ReservedList... reservedLists) { + return setReservedLists(ImmutableSet.copyOf(reservedLists)); + } + + public Builder setReservedLists(Set reservedLists) { + checkArgumentNotNull(reservedLists, "reservedLists must not be null"); + ImmutableSet.Builder> builder = new ImmutableSet.Builder<>(); + for (ReservedList reservedList : reservedLists) { + builder.add(Key.create(reservedList)); + } + getInstance().reservedLists = builder.build(); + return this; + } + + public Builder setPremiumList(PremiumList premiumList) { + getInstance().premiumList = (premiumList == null) ? null : Key.create(premiumList); + return this; + } + + public Builder setRestoreBillingCost(Money amount) { + checkArgument(amount.isPositiveOrZero(), "billing costs must be non-negative"); + getInstance().restoreBillingCost = amount; + return this; + } + + /** + * Sets the renew billing cost to transition to the specified values at the specified times. + *

+ * Renew billing costs transitions should only be added at least 5 days (the length of an + * automatic transfer) in advance, to avoid discrepancies between the cost stored with the + * billing event (created when the transfer is requested) and the cost at the time when the + * transfer actually occurs (5 days later). + */ + public Builder setRenewBillingCostTransitions( + ImmutableSortedMap renewCostsMap) { + checkNotNull(renewCostsMap, "Renew billing costs map cannot be null"); + checkArgument(Iterables.all( + renewCostsMap.values(), + new Predicate() { + @Override + public boolean apply(Money amount) { + return amount.isPositiveOrZero(); + }}), + "Renew billing costs cannot be negative"); + getInstance().renewBillingCostTransitions = + TimedTransitionProperty.fromValueMap(renewCostsMap, BillingCostTransition.class); + return this; + } + + public Builder setRoidSuffix(String roidSuffix) { + getInstance().roidSuffix = roidSuffix; + return this; + } + + public Builder setServerStatusChangeBillingCost(Money amount) { + checkArgument(amount.isPositiveOrZero(), "billing costs must be non-negative"); + getInstance().serverStatusChangeBillingCost = amount; + return this; + } + + public Builder setLordnUsername(String username) { + getInstance().lordnUsername = username; + return this; + } + + public Builder setClaimsPeriodEnd(DateTime claimsPeriodEnd) { + getInstance().claimsPeriodEnd = checkArgumentNotNull(claimsPeriodEnd); + return this; + } + + @Override + public Registry build() { + final Registry instance = getInstance(); + // Pick up the name of the associated TLD from the instance object. + String tldName = instance.tldStr; + checkArgument(tldName != null, "No registry TLD specified."); + // Check for canonical form by converting to an InternetDomainName and then back. + checkArgument( + InternetDomainName.isValid(tldName) + && tldName.equals(InternetDomainName.from(tldName).toString()), + "Cannot create registry for TLD that is not a valid, canonical domain name"); + // Check the validity of all TimedTransitionProperties to ensure that they have values for + // START_OF_TIME. The setters above have already checked this for new values, but also check + // here to catch cases where we loaded an invalid TimedTransitionProperty from datastore and + // cloned it into a new builder, to block re-building a Registry in an invalid state. + instance.tldStateTransitions.checkValidity(); + instance.renewBillingCostTransitions.checkValidity(); + // All costs must be in the expected currency. + // TODO(b/21854155): When we move PremiumList into datastore, verify its currency too. + checkArgument( + instance.getStandardCreateCost().getCurrencyUnit().equals(instance.currency), + "Create cost must be in the registry's currency"); + checkArgument( + instance.getStandardRestoreCost().getCurrencyUnit().equals(instance.currency), + "Restore cost must be in the registry's currency"); + checkArgument( + Iterables.all( + instance.getRenewBillingCostTransitions().values(), + new Predicate(){ + @Override + public boolean apply(Money money) { + return money.getCurrencyUnit().equals(instance.currency); + }}), + "Renew costs must be in the registry's currency"); + instance.tldStrId = tldName; + instance.tldUnicode = Idn.toUnicode(tldName); + return super.build(); + } + } + + /** Exception to throw when no Registry is found for a given tld. */ + public static class RegistryNotFoundException extends RuntimeException{ + RegistryNotFoundException(String tld) { + super("No registry object found for " + tld); + } + } +} diff --git a/java/com/google/domain/registry/model/registry/RegistryCursor.java b/java/com/google/domain/registry/model/registry/RegistryCursor.java new file mode 100644 index 000000000..9eb8aa728 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/RegistryCursor.java @@ -0,0 +1,92 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.common.base.Optional; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +/** Shared entity type for per-TLD date cursors. */ +@Entity +public class RegistryCursor extends ImmutableObject { + + /** The types of cursors, used as the string id field for each cursor in datastore. */ + public enum CursorType { + /** Cursor for ensuring rolling transactional isolation of BRDA staging operation. */ + BRDA, + + /** Cursor for ensuring rolling transactional isolation of RDE report operation. */ + RDE_REPORT, + + /** Cursor for ensuring rolling transactional isolation of RDE staging operation. */ + RDE_STAGING, + + /** Cursor for ensuring rolling transactional isolation of RDE upload operation. */ + RDE_UPLOAD, + + /** + * Cursor that tracks the last time we talked to the escrow provider's SFTP server for a given + * TLD. + * + *

Our escrow provider has an odd feature where separate deposits uploaded within two hours + * of each other will be merged into a single deposit. This is problematic in situations where + * the cursor might be a few days behind and is trying to catch up. + * + *

The way we solve this problem is by having {@code RdeUploadTask} check this cursor before + * performing an upload for a given TLD. If the cursor is less than two hours old, the task will + * fail with a status code above 300 and App Engine will keep retrying the task until it's + * ready. + */ + RDE_UPLOAD_SFTP; + } + + @Parent + Key registry; + + @Id + String cursorType; + + DateTime date; + + /** Convenience shortcut to load a cursor for a given registry and cursor type. */ + public static Optional load(Registry registry, CursorType cursorType) { + Key key = + Key.create(Key.create(registry), RegistryCursor.class, cursorType.name()); + RegistryCursor cursor = ofy().load().key(key).now(); + return Optional.fromNullable(cursor == null ? null : cursor.date); + } + + /** Convenience shortcut to save a cursor. */ + public static void save(Registry registry, CursorType cursorType, DateTime value) { + ofy().save().entity(create(registry, cursorType, value)); + } + + /** Creates a new cursor instance. */ + public static RegistryCursor create(Registry registry, CursorType cursorType, DateTime date) { + RegistryCursor instance = new RegistryCursor(); + instance.registry = Key.create(registry); + instance.cursorType = cursorType.name(); + instance.date = date; + return instance; + } +} diff --git a/java/com/google/domain/registry/model/registry/label/BaseDomainLabelList.java b/java/com/google/domain/registry/model/registry/label/BaseDomainLabelList.java new file mode 100644 index 000000000..70413efe2 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/BaseDomainLabelList.java @@ -0,0 +1,193 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry.label; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.registry.Registries.getTlds; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.cache.CacheLoader.InvalidCacheLoadException; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.common.EntityGroupRoot; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.label.ReservedList.ReservedListEntry; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Nullable; + +/** + * Base class for {@link ReservedList} and {@link PremiumList} objects stored in Datastore. + * + * @param The type of the root value being listed, e.g. {@link ReservationType}. + * @param The type of domain label entry being listed, e.g. {@link ReservedListEntry} (note, + * must subclass {@link DomainLabelEntry}. + */ +public abstract class BaseDomainLabelList, R extends DomainLabelEntry> + extends ImmutableObject implements Buildable { + + @Id + String name; + + @Parent + Key parent = getCrossTldKey(); + + DateTime creationTime; + + DateTime lastUpdateTime; + + String description; + + public String getName() { + return name; + } + + public DateTime getCreationTime() { + return creationTime; + } + + public DateTime getLastUpdateTime() { + return lastUpdateTime; + } + + /** + * Turns the list CSV data into a map of labels to parsed data of type R. + * + * @param lines the CSV file, line by line + */ + @VisibleForTesting + protected ImmutableMap parse(Iterable lines) { + Map labelsToEntries = new HashMap<>(); + for (String line : lines) { + R entry = createFromLine(line); + if (entry == null) { + continue; + } + String label = entry.getLabel(); + // Adds the label to the list of all labels if it (a) doesn't already exist, or (b) already + // exists, but the new value has higher priority (as determined by sort order). + labelsToEntries.put( + label, Ordering.natural().nullsFirst().max(labelsToEntries.get(label), entry)); + } + return ImmutableMap.copyOf(labelsToEntries); + } + + /** + * Creates a new entry in the label list from the given line of text. Returns null if the line is + * empty and does not contain an entry. + * + * @throws IllegalArgumentException if the line cannot be parsed correctly. + */ + @Nullable + abstract R createFromLine(String line); + + /** + * Helper function to extract the comment from an input line. Returns a list containing the line + * (sans comment) and the comment (in that order). If the line was blank or empty, then this + * method returns an empty list. + */ + protected static List splitOnComment(String line) { + String comment = ""; + int index = line.indexOf('#'); + if (index != -1) { + comment = line.substring(index + 1).trim(); + line = line.substring(0, index).trim(); + } else { + line = line.trim(); + } + return line.isEmpty() ? ImmutableList.of() : ImmutableList.of(line, comment); + } + + /** Gets the names of the tlds that reference this list. */ + public final ImmutableSet getReferencingTlds() { + ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); + Key> key = Key.create(this); + for (String tld : getTlds()) { + if (hasReference(Registry.get(tld), key)) { + builder.add(tld); + } + } + return builder.build(); + } + + protected abstract boolean hasReference( + Registry registry, Key> key); + + protected static Optional getFromCache(String listName, LoadingCache cache) { + try { + return Optional.of(cache.get(listName)); + } catch (InvalidCacheLoadException e) { + return Optional.absent(); + } catch (ExecutionException e) { + throw new UncheckedExecutionException("Could not retrieve list named " + listName, e); + } + } + + /** Base builder for derived classes of {@link BaseDomainLabelList}. */ + public abstract static class Builder, B extends Builder> + extends GenericBuilder { + + public Builder() {} + + protected Builder(T instance) { + super(instance); + } + + public B setName(String name) { + getInstance().name = name; + return thisCastToDerived(); + } + + public B setCreationTime(DateTime creationTime) { + getInstance().creationTime = creationTime; + return thisCastToDerived(); + } + + public B setLastUpdateTime(DateTime lastUpdateTime) { + getInstance().lastUpdateTime = lastUpdateTime; + return thisCastToDerived(); + } + + public B setDescription(String description) { + getInstance().description = description; + return thisCastToDerived(); + } + + @Override + public T build() { + checkArgument(!isNullOrEmpty(getInstance().name), "List must have a name"); + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/registry/label/DomainLabelEntry.java b/java/com/google/domain/registry/model/registry/label/DomainLabelEntry.java new file mode 100644 index 000000000..9cfce06f0 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/DomainLabelEntry.java @@ -0,0 +1,84 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry.label; + +import static com.google.common.base.Strings.emptyToNull; +import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Id; + +/** + * Represents a label entry parsed from a line in a Reserved List txt file. + * + * @param The type of the value stored for the domain label, e.g. {@link ReservationType}. + */ +public abstract class DomainLabelEntry, D extends DomainLabelEntry> + extends ImmutableObject implements Comparable { + + @Id + String label; + + String comment; + + /** + * Returns the label of the field, which also happens to be used as the key for the Map object + * that is serialized from Datastore. + */ + public String getLabel() { + return label; + } + + /** + * Returns the value of the field (used for determining which entry takes priority over another). + */ + public abstract T getValue(); + + @Override + @SuppressWarnings("unchecked") + public int compareTo(D other) { + return ((Comparable) getValue()).compareTo(other.getValue()); + } + + /** A generic builder base. */ + public abstract static class Builder, B extends Builder> + extends GenericBuilder { + + public Builder() {} + + protected Builder(T instance) { + super(instance); + } + + public B setLabel(String label) { + getInstance().label = label; + return thisCastToDerived(); + } + + public B setComment(String comment) { + getInstance().comment = comment; + return thisCastToDerived(); + } + + @Override + public T build() { + checkArgumentNotNull(emptyToNull(getInstance().label), "Label must be specified"); + checkArgumentNotNull(getInstance().getValue(), "Value must be specified"); + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/registry/label/PremiumList.java b/java/com/google/domain/registry/model/registry/label/PremiumList.java new file mode 100644 index 000000000..312a269aa --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/PremiumList.java @@ -0,0 +1,383 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry.label; + +import static com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Iterables.partition; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.allocateId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.google.appengine.api.datastore.EntityNotFoundException; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Splitter; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheLoader.InvalidCacheLoadException; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.VirtualEntity; +import com.google.domain.registry.model.registry.Registry; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.OnLoad; +import com.googlecode.objectify.annotation.Parent; +import com.googlecode.objectify.cmd.Query; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Nullable; + +/** + * A premium list entity, persisted to Datastore, that is used to check domain label prices. + */ +@Entity +@Cache +public final class PremiumList extends BaseDomainLabelList { + + /** The number of premium list entry entities that are created and deleted per batch. */ + private static final int TRANSACTION_BATCH_SIZE = 200; + + /** Stores the revision key for the set of currently used premium list entry entities. */ + Key revisionKey; + + @Ignore + Map premiumListMap; + + /** Virtual parent entity for premium list entry entities associated with a single revision. */ + @Entity + @VirtualEntity + public static class PremiumListRevision extends ImmutableObject { + @Parent + Key parent; + + @Id + long revisionId; + + static Key createKey(PremiumList parent) { + PremiumListRevision revision = new PremiumListRevision(); + revision.parent = Key.create(parent); + revision.revisionId = allocateId(); + return Key.create(revision); + } + } + + private static LoadingCache cache = CacheBuilder + .newBuilder() + .expireAfterWrite( + RegistryEnvironment.get().config().getDomainLabelListCacheDuration().getMillis(), + MILLISECONDS) + .build(new CacheLoader() { + @Override + public PremiumList load(final String listName) { + return ofy().doTransactionless(new Work() { + @Override + public PremiumList run() { + return ofy().load() + .type(PremiumList.class) + .parent(getCrossTldKey()) + .id(listName) + .now(); + }}); + }}); + + /** + * Gets the premium price for the specified label on the specified tld, or returns Optional.absent + * if there is no premium price. + */ + public static Optional getPremiumPrice(String label, String tld) { + Registry registry = Registry.get(checkNotNull(tld, "tld")); + if (registry.getPremiumList() == null) { + return Optional. absent(); + } + String listName = registry.getPremiumList().getName(); + Optional premiumList = get(listName); + if (!premiumList.isPresent()) { + throw new IllegalStateException("Could not load premium list named " + listName); + } + return premiumList.get().getPremiumPrice(label); + } + + @OnLoad + private void loadPremiumListMap() { + try { + ImmutableMap.Builder entriesMap = new ImmutableMap.Builder<>(); + if (revisionKey != null) { + for (PremiumListEntry entry : loadEntriesForCurrentRevision()) { + entriesMap.put(entry.getLabel(), entry); + } + } + premiumListMap = entriesMap.build(); + } catch (Exception e) { + throw new RuntimeException("Could not retrieve entries for premium list " + name, e); + } + } + + /** + * Gets the premium price for the specified label in the current PremiumList, or returns + * Optional.absent if there is no premium price. + */ + public Optional getPremiumPrice(String label) { + return Optional.fromNullable( + premiumListMap.containsKey(label) ? premiumListMap.get(label).getValue() : null); + } + + public Map getPremiumListEntries() { + return nullToEmptyImmutableCopy(premiumListMap); + } + + public Key getRevisionKey() { + return revisionKey; + } + + /** Returns the PremiumList with the specified name. */ + public static Optional get(String name) { + try { + return Optional.of(cache.get(name)); + } catch (InvalidCacheLoadException e) { + return Optional. absent(); + } catch (ExecutionException e) { + throw new UncheckedExecutionException("Could not retrieve premium list named " + name, e); + } + } + + /** + * Returns whether a PremiumList of the given name exists, without going through the overhead + * of loading up all of the premium list entities. Also does not hit the cache. + */ + public static boolean exists(String name) { + try { + // Use DatastoreService to bypass the @OnLoad method that loads the premium list entries. + getDatastoreService().get(Key.create(getCrossTldKey(), PremiumList.class, name).getRaw()); + return true; + } catch (EntityNotFoundException e) { + return false; + } + } + + /** + * A premium list entry entity, persisted to Datastore. Each instance represents the price of a + * single label on a given TLD. + */ + @Entity + @Cache + public static class PremiumListEntry extends DomainLabelEntry + implements Buildable { + + @Parent + Key parent; + + Money price; + + @Override + public Money getValue() { + return price; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** + * A builder for constructing {@link PremiumList} objects, since they are immutable. + */ + public static class Builder extends DomainLabelEntry.Builder { + public Builder() {} + + private Builder(PremiumListEntry instance) { + super(instance); + } + + public Builder setParent(Key parentKey) { + getInstance().parent = parentKey; + return this; + } + + public Builder setPrice(Money price) { + getInstance().price = price; + return this; + } + } + } + + @Override + @Nullable + PremiumListEntry createFromLine(String originalLine) { + List lineAndComment = splitOnComment(originalLine); + if (lineAndComment.isEmpty()) { + return null; + } + String line = lineAndComment.get(0); + String comment = lineAndComment.get(1); + List parts = Splitter.on(',').trimResults().splitToList(line); + checkArgument(parts.size() == 2, "Could not parse line in premium list: %s", originalLine); + return new PremiumListEntry.Builder() + .setLabel(parts.get(0)) + .setPrice(Money.parse(parts.get(1))) + .setComment(comment) + .build(); + } + + /** + * Persists a PremiumList object to Datastore. + * + *

The flow here is: save the new premium list entries parented on that revision entity, + * save/update the PremiumList, and then delete the old premium list entries associated with the + * old revision. + */ + public PremiumList saveAndUpdateEntries() { + final Optional oldPremiumList = get(name); + // Save the new child entities in a series of transactions. + for (final List batch + : partition(premiumListMap.values(), TRANSACTION_BATCH_SIZE)) { + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().save().entities(batch); + }}); + } + // Save the new PremiumList itself. + PremiumList updated = ofy().transactNew(new Work() { + @Override + public PremiumList run() { + DateTime now = ofy().getTransactionTime(); + // Assert that the premium list hasn't been changed since we started this process. + checkState( + Objects.equals( + ofy().load().type(PremiumList.class).parent(getCrossTldKey()).id(name).now(), + oldPremiumList.orNull()), + "PremiumList was concurrently edited"); + PremiumList newList = PremiumList.this.asBuilder() + .setLastUpdateTime(now) + .setCreationTime( + oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now) + .build(); + ofy().save().entity(newList); + return newList; + }}); + // Update the cache. + PremiumList.cache.put(name, updated); + // Delete the entities under the old PremiumList, if any. + if (oldPremiumList.isPresent()) { + oldPremiumList.get().deleteEntries(); + } + return updated; + } + + @Override + public boolean hasReference(Registry registry, Key> key) { + return Objects.equals(registry.getPremiumList(), key); + } + + /** Deletes the PremiumList and all of its child entities. */ + public void delete() { + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().delete().entity(PremiumList.this); + }}); + deleteEntries(); + cache.invalidate(name); + } + + private void deleteEntries() { + if (revisionKey == null) { + return; + } + for (final List> batch : partition( + loadEntriesForCurrentRevision().keys(), + TRANSACTION_BATCH_SIZE)) { + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().delete().keys(batch); + }}); + } + } + + private Query loadEntriesForCurrentRevision() { + return ofy().load().type(PremiumListEntry.class).ancestor(revisionKey); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link PremiumList} objects, since they are immutable. */ + public static class Builder extends BaseDomainLabelList.Builder { + + public Builder() {} + + private Builder(PremiumList instance) { + super(instance); + } + + private boolean entriesWereUpdated; + + public Builder setPremiumListMap(ImmutableMap premiumListMap) { + entriesWereUpdated = true; + getInstance().premiumListMap = premiumListMap; + return this; + } + + /** Updates the premiumListMap from input lines. */ + public Builder setPremiumListMapFromLines(Iterable lines) { + return setPremiumListMap(getInstance().parse(lines)); + } + + @Override + public PremiumList build() { + final PremiumList instance = getInstance(); + if (getInstance().revisionKey == null || entriesWereUpdated) { + getInstance().revisionKey = PremiumListRevision.createKey(instance); + } + // When we build an instance, make sure all entries are parented on its revisionKey. + instance.premiumListMap = Maps.transformValues( + nullToEmpty(instance.premiumListMap), + new Function() { + @Override + public PremiumListEntry apply(PremiumListEntry entry) { + return entry.asBuilder().setParent(instance.revisionKey).build(); + }}); + return super.build(); + } + } +} diff --git a/java/com/google/domain/registry/model/registry/label/ReservationType.java b/java/com/google/domain/registry/model/registry/label/ReservationType.java new file mode 100644 index 000000000..aee7a2fd8 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/ReservationType.java @@ -0,0 +1,46 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry.label; + +import static com.google.common.base.Preconditions.checkState; + +import javax.annotation.Nullable; + +/** Enum describing reservation on a label in a {@link ReservedList} */ +public enum ReservationType { + + // We explicitly set the severity, even though we have a checkState that makes it equal to the + // ordinal, so that no one accidentally reorders these values and changes the sort order. + + UNRESERVED(null, 0), + ALLOWED_IN_SUNRISE("Reserved for non-sunrise", 1), + MISTAKEN_PREMIUM("Reserved", 2), + RESERVED_FOR_ANCHOR_TENANT("Reserved", 3), + NAME_COLLISION("Cannot be delegated", 4), + FULLY_BLOCKED("Reserved", 5); + + @Nullable + private final String messageForCheck; + + ReservationType(@Nullable String messageForCheck, int severity) { + this.messageForCheck = messageForCheck; + checkState(ordinal() == severity); + } + + @Nullable + public String getMessageForCheck() { + return messageForCheck; + } +} diff --git a/java/com/google/domain/registry/model/registry/label/ReservedList.java b/java/com/google/domain/registry/model/registry/label/ReservedList.java new file mode 100644 index 000000000..af60e4789 --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/ReservedList.java @@ -0,0 +1,316 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.registry.label; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.label.ReservationType.FULLY_BLOCKED; +import static com.google.domain.registry.model.registry.label.ReservationType.RESERVED_FOR_ANCHOR_TENANT; +import static com.google.domain.registry.model.registry.label.ReservationType.UNRESERVED; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.google.common.base.Optional; +import com.google.common.base.Splitter; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.registry.Registry; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Mapify; +import com.googlecode.objectify.mapper.Mapper; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Nullable; + +/** + * A reserved list entity, persisted to Datastore, that is used to check domain label reservations. + */ +@Entity +@Cache +public final class ReservedList + extends BaseDomainLabelList { + + @Mapify(ReservedListEntry.LabelMapper.class) + Map reservedListMap; + + boolean shouldPublish = true; + + /** + * A reserved list entry entity, persisted to Datastore, that represents a single label and its + * reservation type. + */ + @Embed + public static class ReservedListEntry + extends DomainLabelEntry { + + ReservationType reservationType; + + /** + * Contains the auth code necessary to register a domain with this label. + * Note that this field will only ever be populated for entries with type + * RESERVED_FOR_ANCHOR_TENANT. + */ + String authCode; + + /** Mapper for use with @Mapify */ + static class LabelMapper implements Mapper { + @Override + public String getKey(ReservedListEntry entry) { + return entry.getLabel(); + } + } + + public static ReservedListEntry create( + String label, + ReservationType reservationType, + @Nullable String authCode, + String comment) { + if (authCode != null) { + checkArgument(reservationType == RESERVED_FOR_ANCHOR_TENANT, + "Only anchor tenant reservations should have an auth code configured"); + } else { + checkArgument(reservationType != RESERVED_FOR_ANCHOR_TENANT, + "Anchor tenant reservations must have an auth code configured"); + } + ReservedListEntry entry = new ReservedListEntry(); + entry.label = label; + entry.reservationType = reservationType; + entry.authCode = authCode; + entry.comment = comment; + return entry; + } + + @Override + public ReservationType getValue() { + return reservationType; + } + + public String getAuthCode() { + return authCode; + } + } + + @Override + protected boolean hasReference(Registry registry, Key> key) { + return registry.getReservedLists().contains(key); + } + + /** Determines whether the ReservedList is in use on any Registry */ + public boolean isInUse() { + return !getReferencingTlds().isEmpty(); + } + + /** + * Returns whether this reserved list is included in the concatenated list of reserved terms + * published to Google Drive for viewing by registrars. + */ + public boolean getShouldPublish() { + return shouldPublish; + } + + public ImmutableMap getReservedListEntries() { + return ImmutableMap.copyOf(nullToEmpty(reservedListMap)); + } + + /** + * Gets a ReservedList by name using the caching layer. + * + * @return An Optional that has a value if a reserved list exists by the given + * name, or absent if not. + * @throws UncheckedExecutionException if some other error occurs while trying to load the + * ReservedList from the cache or Datastore. + */ + public static Optional get(String listName) { + return getFromCache(listName, cache); + } + + /** Loads a ReservedList from its Objectify key. */ + public static Optional load(Key key) { + return get(key.getName()); + } + + /** + * Queries the set of all reserved lists associated with the specified tld and returns the + * reservation type of the first occurrence of label seen. If the label is in none of the lists, + * it returns UNRESERVED. + */ + public static ReservationType getReservation(String label, String tld) { + checkNotNull(label, "label"); + if (label.length() == 0 || label.length() == 2) { + return FULLY_BLOCKED; // All 2-letter labels are FULLY_BLOCKED. + } + ReservedListEntry entry = getReservedListEntry(label, tld); + return (entry != null) ? entry.reservationType : UNRESERVED; + } + + /** + * Returns true if the given label and TLD is reserved for an anchor tenant, and the given + * auth code matches the one set on the reservation. + */ + public static boolean matchesAnchorTenantReservation(String label, String tld, String authCode) { + ReservedListEntry entry = getReservedListEntry(label, tld); + return entry != null + && entry.reservationType == RESERVED_FOR_ANCHOR_TENANT + && Objects.equals(entry.getAuthCode(), authCode); + } + + /** + * Helper function to retrieve the entry associated with this label and TLD, or null if no such + * entry exists. + */ + @Nullable + private static ReservedListEntry getReservedListEntry(String label, String tld) { + Registry registry = Registry.get(checkNotNull(tld, "tld")); + ImmutableSet> reservedLists = registry.getReservedLists(); + ImmutableSet lists = loadReservedLists(reservedLists); + ReservedListEntry entry = null; + + // Loop through all reservation lists and check each one for the inputted label, and return + // the most severe ReservationType found. + for (ReservedList rl : lists) { + Map entries = rl.getReservedListEntries(); + ReservedListEntry nextEntry = entries.get(label); + if (nextEntry != null + && (entry == null || nextEntry.reservationType.compareTo(entry.reservationType) > 0)) { + entry = nextEntry; + } + } + return entry; + } + + private static ImmutableSet loadReservedLists( + ImmutableSet> reservedListKeys) { + ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); + for (Key listKey : reservedListKeys) { + try { + builder.add(cache.get(listKey.getName())); + } catch (ExecutionException e) { + throw new UncheckedExecutionException(String.format( + "Could not load the reserved list '%s' from the cache", listKey.getName()), e); + } + } + + return builder.build(); + } + + private static LoadingCache cache = CacheBuilder + .newBuilder() + .expireAfterWrite( + RegistryEnvironment.get().config().getDomainLabelListCacheDuration().getMillis(), + MILLISECONDS) + .build(new CacheLoader() { + @Override + public ReservedList load(String listName) { + return ofy().load().type(ReservedList.class).parent(getCrossTldKey()).id(listName).now(); + }}); + + /** Deletes the ReservedList with the given name. */ + public static void delete(final String listName) { + final ReservedList reservedList = ReservedList.get(listName).orNull(); + checkState( + reservedList != null, + "Attempted to delete reserved list %s which doesn't exist", + listName); + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().delete().entity(reservedList).now(); + } + }); + cache.invalidate(listName); + } + + /** + * Gets the {@link ReservationType} of a label in a single ReservedList, or returns an absent + * Optional if none exists in the list. + * + *

Note that this logic is significantly less complicated than the getReservation() methods, + * which are applicable to an entire Registry, and need to check across multiple reserved lists. + */ + public Optional getReservationInList(String label) { + ReservedListEntry entry = getReservedListEntries().get(label); + return Optional.fromNullable(entry == null ? null : entry.reservationType); + } + + @Override + @Nullable + ReservedListEntry createFromLine(String originalLine) { + List lineAndComment = splitOnComment(originalLine); + if (lineAndComment.isEmpty()) { + return null; + } + String line = lineAndComment.get(0); + String comment = lineAndComment.get(1); + List parts = Splitter.on(',').trimResults().splitToList(line); + checkArgument(parts.size() == 2 || parts.size() == 3, + "Could not parse line in reserved list: %s", originalLine); + String label = parts.get(0); + ReservationType reservationType = ReservationType.valueOf(parts.get(1)); + String authCode = (parts.size() > 2) ? parts.get(2) : null; + return ReservedListEntry.create(label, reservationType, authCode, comment); + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** + * A builder for constructing {@link ReservedList} objects, since they are immutable. + */ + public static class Builder extends BaseDomainLabelList.Builder { + public Builder() {} + + private Builder(ReservedList instance) { + super(instance); + } + + public Builder setReservedListMap(ImmutableMap reservedListMap) { + getInstance().reservedListMap = reservedListMap; + return this; + } + + public Builder setShouldPublish(boolean shouldPublish) { + getInstance().shouldPublish = shouldPublish; + return this; + } + + /** + * Updates the reservedListMap from input lines. + * + * @throws IllegalArgumentException if the lines cannot be parsed correctly. + */ + public Builder setReservedListMapFromLines(Iterable lines) { + return setReservedListMap(getInstance().parse(lines)); + } + } +} diff --git a/java/com/google/domain/registry/model/registry/label/package-info.java b/java/com/google/domain/registry/model/registry/label/package-info.java new file mode 100644 index 000000000..6bdb8d5ff --- /dev/null +++ b/java/com/google/domain/registry/model/registry/label/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.model.registry.label; diff --git a/java/com/google/domain/registry/model/reporting/HistoryEntry.java b/java/com/google/domain/registry/model/reporting/HistoryEntry.java new file mode 100644 index 000000000..42382a981 --- /dev/null +++ b/java/com/google/domain/registry/model/reporting/HistoryEntry.java @@ -0,0 +1,225 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.reporting; + +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.eppcommon.Trid; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; +import com.googlecode.objectify.condition.IfNull; + +import org.joda.time.DateTime; + +/** A record of an EPP command that mutated a resource. */ +@Entity +public class HistoryEntry extends ImmutableObject implements Buildable { + + /** Represents the type of history entry. */ + public enum Type { + CONTACT_CREATE, + CONTACT_DELETE, + CONTACT_DELETE_FAILURE, + CONTACT_PENDING_DELETE, + CONTACT_TRANSFER_APPROVE, + CONTACT_TRANSFER_CANCEL, + CONTACT_TRANSFER_REJECT, + CONTACT_TRANSFER_REQUEST, + CONTACT_UPDATE, + DOMAIN_ALLOCATE, + DOMAIN_APPLICATION_CREATE, + DOMAIN_APPLICATION_DELETE, + DOMAIN_APPLICATION_UPDATE, + DOMAIN_APPLICATION_STATUS_UPDATE, + DOMAIN_CREATE, + DOMAIN_DELETE, + DOMAIN_RENEW, + DOMAIN_RESTORE, + DOMAIN_TRANSFER_APPROVE, + DOMAIN_TRANSFER_CANCEL, + DOMAIN_TRANSFER_REJECT, + DOMAIN_TRANSFER_REQUEST, + DOMAIN_UPDATE, + HOST_CREATE, + HOST_DELETE, + HOST_DELETE_FAILURE, + HOST_PENDING_DELETE, + HOST_UPDATE, + /** + * A synthetic history entry created by a tool or back-end migration script outside of the scope + * of usual EPP flows. These are sometimes needed to serve as parents for billing events or poll + * messages that otherwise wouldn't have a suitable parent. + */ + SYNTHETIC + } + + /** The autogenerated id of this event. */ + @Id + long id; + + /** The resource this event mutated. */ + @Parent + Ref parent; + + /** The type of history entry. */ + Type type; + + /** + * The length of time that a create, allocate, renewal, or transfer request was issued for. Will + * be null for all other types. + */ + @IgnoreSave(IfNull.class) + Period period; + + /** The actual EPP xml of the command, stored as bytes to be agnostic of encoding. */ + byte[] xmlBytes; + + /** The time the command occurred. */ + @Index + DateTime modificationTime; + + /** The id of the registrar that sent the command. */ + @Index + String clientId; + + /** Transaction id that made this change. */ + Trid trid; + + /** Whether this change was created by a superuser. */ + boolean bySuperuser; + + /** Reason for the change. */ + String reason; + + /** Whether this change was requested by a registrar. */ + Boolean requestedByRegistrar; + + public Ref getParent() { + return parent; + } + + public Type getType() { + return type; + } + + public Period getPeriod() { + return period; + } + + public byte[] getXmlBytes() { + return xmlBytes; + } + + public DateTime getModificationTime() { + return modificationTime; + } + + public String getClientId() { + return clientId; + } + + public Trid getTrid() { + return trid; + } + + public boolean getBySuperuser() { + return bySuperuser; + } + + public String getReason() { + return reason; + } + + public Boolean getRequestedByRegistrar() { + return requestedByRegistrar; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for {@link HistoryEntry} since it is immutable */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + public Builder(HistoryEntry instance) { + super(instance); + } + + public Builder setParent(EppResource parent) { + getInstance().parent = Ref.create(parent); + return this; + } + + public Builder setParent(Key parentKey) { + getInstance().parent = Ref.create(parentKey); + return this; + } + + public Builder setType(Type type) { + getInstance().type = type; + return this; + } + + public Builder setPeriod(Period period) { + getInstance().period = period; + return this; + } + + public Builder setXmlBytes(byte[] xmlBytes) { + getInstance().xmlBytes = xmlBytes; + return this; + } + + public Builder setModificationTime(DateTime modificationTime) { + getInstance().modificationTime = modificationTime; + return this; + } + + public Builder setClientId(String clientId) { + getInstance().clientId = clientId; + return this; + } + + public Builder setTrid(Trid trid) { + getInstance().trid = trid; + return this; + } + + public Builder setBySuperuser(boolean bySuperuser) { + getInstance().bySuperuser = bySuperuser; + return this; + } + + public Builder setReason(String reason) { + getInstance().reason = reason; + return this; + } + + public Builder setRequestedByRegistrar(Boolean requestedByRegistrar) { + getInstance().requestedByRegistrar = requestedByRegistrar; + return this; + } + } +} diff --git a/java/com/google/domain/registry/model/server/Lock.java b/java/com/google/domain/registry/model/server/Lock.java new file mode 100644 index 000000000..22002f26d --- /dev/null +++ b/java/com/google/domain/registry/model/server/Lock.java @@ -0,0 +1,253 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.server; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterables.getFirst; +import static com.google.common.collect.Iterables.skip; +import static com.google.common.collect.Sets.newLinkedHashSet; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.isAtOrAfter; + +import com.google.common.base.Strings; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.util.AppEngineTimeLimiter; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nullable; + +/** + * A lock on some shared resource. Locks are either specific to a tld or global to the entire + * system, in which case a tld of null is used. + */ +@Entity +@NotBackedUp(reason = Reason.TRANSIENT) +public class Lock extends ImmutableObject { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** Fudge factor to make sure we kill threads before a lock actually expires. */ + private static final Duration LOCK_TIMEOUT_FUDGE = Duration.standardSeconds(5); + + /** The name of the locked resource. */ + @Id + String lockId; + + /** When the lock can be considered implicitly released. */ + DateTime expirationTime; + + /** + * Insertion-ordered set of classes requesting access to the lock. + * + *

A class can only acquire the lock if the queue is empty or if it is at the top of the + * queue. This allows us to prevent starvation between processes competing for the lock. + */ + LinkedHashSet queue = new LinkedHashSet<>(); + + /** + * Create a new {@link Lock} for the given resource name in the specified tld (which can be + * null for cross-tld locks). + */ + private static Lock create( + String resourceName, + @Nullable String tld, + DateTime expirationTime, + LinkedHashSet queue) { + checkArgument(!Strings.isNullOrEmpty(resourceName), "resourceName cannot be null or empty"); + Lock instance = new Lock(); + // Add the tld to the Lock's id so that it is unique for locks acquiring the same resource + // across different TLDs. + instance.lockId = makeLockId(resourceName, tld); + instance.expirationTime = expirationTime; + instance.queue = queue; + return instance; + } + + private static String makeLockId(String resourceName, @Nullable String tld) { + return String.format("%s-%s", tld, resourceName); + } + + /** Join the queue waiting on this lock (unless you are already in the queue). */ + static void joinQueue( + final Class requester, + final String resourceName, + @Nullable final String tld) { + // This transaction doesn't use the clock, so it's fine to use the default. + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + Lock lock = ofy().load().type(Lock.class).id(makeLockId(resourceName, tld)).now(); + LinkedHashSet queue = (lock == null) + ? new LinkedHashSet() : newLinkedHashSet(lock.queue); + queue.add(requester.getCanonicalName()); + DateTime expirationTime = (lock == null) ? START_OF_TIME : lock.expirationTime; + ofy().saveWithoutBackup().entity(create(resourceName, tld, expirationTime, queue)); + }}); + } + + /** Try to acquire a lock. Returns null if it can't be acquired. */ + static Lock acquire( + final Class requester, + final String resourceName, + @Nullable final String tld, + final Duration leaseLength) { + // It's important to use transactNew rather than transact, because a Lock can be used to control + // access to resources like GCS that can't be transactionally rolled back. Therefore, the lock + // must be definitively acquired before it is used, even when called inside another transaction. + return ofy().transactNew(new Work() { + @Override + public Lock run() { + Lock lock = ofy().load().type(Lock.class).id(makeLockId(resourceName, tld)).now(); + if (lock == null || isAtOrAfter(ofy().getTransactionTime(), lock.expirationTime)) { + String requesterName = (requester == null) ? "" : requester.getCanonicalName(); + if (!getFirst(nullToEmpty((lock == null) ? null : lock.queue), requesterName) + .equals(requesterName)) { + // Another class is at the top of the queue; we can't acquire the lock. + return null; + } + Lock newLock = create( + resourceName, + tld, + ofy().getTransactionTime().plus(leaseLength), + newLinkedHashSet((lock == null) + ? ImmutableList.of() : skip(lock.queue, 1))); + // Locks are not parented under an EntityGroupRoot (so as to avoid write contention) and + // don't need to be backed up. + ofy().saveWithoutBackup().entity(newLock); + return newLock; + } + return null; + }}); + } + + /** Release the lock. */ + void release() { + // Just use the default clock because we aren't actually doing anything that will use the clock. + ofy().transact(new VoidWork() { + @Override + public void vrun() { + // To release a lock, check that no one else has already obtained it and if not delete it. + // If the lock in datastore was different then this lock is gone already; this can happen + // if release() is called around the expiration time and the lock expires underneath us. + Lock loadedLock = ofy().load().type(Lock.class).id(lockId).now(); + if (Lock.this.equals(loadedLock)) { + // Use noBackupOfy() so that we don't create a commit log entry for deleting the lock. + ofy().deleteWithoutBackup().entity(Lock.this); + } + }}); + } + + /** + * Acquire one or more locks and execute a Void {@link Callable} on a thread that will be + * killed if it doesn't complete before the lease expires. + * + *

If the requester isn't null, this will join each lock's queue before attempting to acquire + * that lock. Clients that are concerned with starvation should specify a requester and those that + * aren't shouldn't. + * + *

Note that locks are specific either to a given tld or to the entire system (in which case + * tld should be passed as null). + * + * @return whether all locks were acquired and the callable was run. + */ + public static boolean executeWithLocks( + final Callable callable, + @Nullable Class requester, + @Nullable String tld, + Duration leaseLength, + String... lockNames) { + try { + return AppEngineTimeLimiter.create().callWithTimeout( + new LockingCallable( + callable, requester, Strings.emptyToNull(tld), leaseLength, lockNames), + leaseLength.minus(LOCK_TIMEOUT_FUDGE).getMillis(), + TimeUnit.MILLISECONDS, + true); + } catch (Exception e) { + throw Throwables.propagate(e); + } + } + + /** A {@link Callable} that acquires and releases a lock around a delegate {@link Callable}. */ + private static class LockingCallable implements Callable { + final Callable delegate; + final Class requester; + @Nullable final String tld; + final Duration leaseLength; + final Set lockNames; + + LockingCallable( + Callable delegate, + Class requester, + String tld, + Duration leaseLength, + String... lockNames) { + checkArgument(leaseLength.isLongerThan(LOCK_TIMEOUT_FUDGE)); + this.delegate = delegate; + this.requester = requester; + this.tld = tld; + this.leaseLength = leaseLength; + // Make sure we join locks in a fixed (lexicographical) order to avoid deadlock. + this.lockNames = ImmutableSortedSet.copyOf(lockNames); + } + + @Override + public Boolean call() throws Exception { + Set acquiredLocks = new HashSet<>(); + try { + for (String lockName : lockNames) { + if (requester != null) { + joinQueue(requester, lockName, tld); + } + Lock lock = acquire(requester, lockName, tld, leaseLength); + if (lock == null) { + logger.infofmt("Couldn't acquire lock: %s", lockName); + return false; + } + logger.infofmt("Acquired lock: %s", lockName); + acquiredLocks.add(lock); + } + delegate.call(); + return true; + } finally { + for (Lock lock : acquiredLocks) { + lock.release(); + logger.infofmt("Released lock: %s", lock.lockId); + } + } + } + } +} diff --git a/java/com/google/domain/registry/model/server/ServerSecret.java b/java/com/google/domain/registry/model/server/ServerSecret.java new file mode 100644 index 000000000..d76a21f96 --- /dev/null +++ b/java/com/google/domain/registry/model/server/ServerSecret.java @@ -0,0 +1,67 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.server; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.model.common.CrossTldSingleton; + +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Unindex; + +import java.util.UUID; + +/** A secret number used for generating tokens (such as XSRF tokens). */ +@Entity +@Cache +@Unindex +@NotBackedUp(reason = Reason.AUTO_GENERATED) +public class ServerSecret extends CrossTldSingleton { + + private static ServerSecret secret; + + long mostSignificant; + long leastSignificant; + + /** + * Get the server secret, creating it if the datastore doesn't have one already. + *

+ * There's a tiny risk of a race here if two calls to this happen simultaneously and create + * different keys, in which case one of the calls will end up with an incorrect key. However, this + * happens precisely once in the history of the system (after that it's always in datastore) so + * it's not worth worrying about. + */ + public static UUID getServerSecret() { + if (secret == null) { + secret = ofy().load().entity(new ServerSecret()).now(); + } + if (secret == null) { + secret = new ServerSecret(); + UUID uuid = UUID.randomUUID(); + secret.mostSignificant = uuid.getMostSignificantBits(); + secret.leastSignificant = uuid.getLeastSignificantBits(); + ofy().transact(new VoidWork(){ + @Override + public void vrun() { + ofy().saveWithoutBackup().entity(secret); + }}); + } + return new UUID(secret.mostSignificant, secret.leastSignificant); + } +} diff --git a/java/com/google/domain/registry/model/smd/AbstractSignedMark.java b/java/com/google/domain/registry/model/smd/AbstractSignedMark.java new file mode 100644 index 000000000..a67dd668b --- /dev/null +++ b/java/com/google/domain/registry/model/smd/AbstractSignedMark.java @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +/** + * Marker interface for signed mark types. + * + * @see EncodedSignedMark + * @see SignedMark + */ +public interface AbstractSignedMark {} diff --git a/java/com/google/domain/registry/model/smd/EncodedSignedMark.java b/java/com/google/domain/registry/model/smd/EncodedSignedMark.java new file mode 100644 index 000000000..1caa77391 --- /dev/null +++ b/java/com/google/domain/registry/model/smd/EncodedSignedMark.java @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.common.io.BaseEncoding.base64; + +import com.google.appengine.api.datastore.Text; +import com.google.domain.registry.model.ImmutableObject; + +import com.googlecode.objectify.annotation.Embed; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * Encoded data representation of a {@link SignedMark} object. + * + * @see + * draft-lozano-tmch-smd-02 § 2.4 + */ +@Embed +@XmlRootElement(name = "encodedSignedMark") +public class EncodedSignedMark extends ImmutableObject implements AbstractSignedMark { + + private static final String ENCODING_DEFAULT = "base64"; + + /** Encoding used for contained data. Default is {@value #ENCODING_DEFAULT}. */ + @XmlAttribute + String encoding; + + /** + * Encoded data. This is stored in a Text field rather than a String because Objectify cannot + * autoconvert Strings greater than 500 characters to Text within {@link Embed} collections. + */ + @XmlValue + @XmlJavaTypeAdapter(RemoveWhitespaceTextAdapter.class) + Text encodedData; + + public String getEncoding() { + return firstNonNull(encoding, ENCODING_DEFAULT); + } + + public String getEncodedData() { + return encodedData == null ? "" : encodedData.getValue(); + } + + public static EncodedSignedMark create(String encoding, String encodedData) { + EncodedSignedMark instance = new EncodedSignedMark(); + instance.encoding = encoding; + instance.encodedData = new Text(encodedData); + return instance; + } + + public byte[] getBytes() { + try { + return base64().decode(getEncodedData()); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); // Turn e into a runtime exception. + } + } +} diff --git a/java/com/google/domain/registry/model/smd/IssuerInfo.java b/java/com/google/domain/registry/model/smd/IssuerInfo.java new file mode 100644 index 000000000..ae93ce472 --- /dev/null +++ b/java/com/google/domain/registry/model/smd/IssuerInfo.java @@ -0,0 +1,69 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.mark.MarkPhoneNumber; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; + +/** Holds information about the issuer of a mark registration. */ +public class IssuerInfo extends ImmutableObject { + + @XmlAttribute(name = "issuerID") + String issuerId; + + /** The issuer identifier. */ + @XmlElement(name = "issuerID") + String id; + + /** The organization name of the issuer. */ + @XmlElement(name = "org") + String organization; + + /** Issuer customer support email address. */ + String email; + + /** The HTTP URL of the issuer's site. */ + String url; + + /** The issuer's voice telephone number. */ + MarkPhoneNumber voice; + + public String getIssuerId() { + return issuerId; + } + + public String getId() { + return id; + } + + public String getOrganization() { + return organization; + } + + public String getEmail() { + return email; + } + + public String getUrl() { + return url; + } + + public MarkPhoneNumber getVoice() { + return voice; + } +} diff --git a/java/com/google/domain/registry/model/smd/RemoveWhitespaceTextAdapter.java b/java/com/google/domain/registry/model/smd/RemoveWhitespaceTextAdapter.java new file mode 100644 index 000000000..0d6790fbe --- /dev/null +++ b/java/com/google/domain/registry/model/smd/RemoveWhitespaceTextAdapter.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +import com.google.appengine.api.datastore.Text; +import com.google.common.base.CharMatcher; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** + * {@link XmlAdapter} which removes all whitespace from a string and then converts the result a + * {@link Text} object. + */ +public class RemoveWhitespaceTextAdapter extends XmlAdapter { + + private static final CharMatcher WHITESPACE = CharMatcher.anyOf(" \t\r\n"); + + @Override + public Text unmarshal(String value) { + return (value == null) ? null : new Text(WHITESPACE.removeFrom(value)); + } + + @Override + public String marshal(Text t) { + return (t == null) ? null : t.getValue(); + } +} diff --git a/java/com/google/domain/registry/model/smd/SignedMark.java b/java/com/google/domain/registry/model/smd/SignedMark.java new file mode 100644 index 000000000..d2954d55a --- /dev/null +++ b/java/com/google/domain/registry/model/smd/SignedMark.java @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.mark.Mark; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents an XML fragment that is digitally signed by the TMCH to prove ownership over a mark. + **/ +@XmlRootElement(name = "signedMark") +public class SignedMark extends ImmutableObject implements AbstractSignedMark { + + /** XSD ID for use with an IDREF URI from the Signature element. */ + @XmlAttribute(name = "id") + String xsdId; + + /** + * Signed mark identifier. This is a concatenation of the local identifier, followed by a hyphen, + * followed by the issuer identifier. + */ + String id; + + /** Information of the issuer of the mark registration. */ + IssuerInfo issuerInfo; + + /** Creation time of this signed mark. */ + @XmlElement(name = "notBefore") + DateTime creationTime; + + /** Expiration time of this signed mark. */ + @XmlElement(name = "notAfter") + DateTime expirationTime; + + /** Mark information. */ + @XmlElementRef(type = Mark.class) + Mark mark; + + /** + * Digital signature of the signed mark. Note that we don't unmarshal this data, as there is + * already an existing Java library to handle validation of this signature. + * + * @see javax.xml.crypto.dsig.XMLSignature + */ + @XmlElement(name = "Signature", namespace = "http://www.w3.org/2000/09/xmldsig#") + Object xmlSignature; + + public String getId() { + return id; + } + + public DateTime getCreationTime() { + return creationTime; + } + + public DateTime getExpirationTime() { + return expirationTime; + } + + public Mark getMark() { + return mark; + } + + public boolean hasSignature() { + return xmlSignature != null; + } +} diff --git a/java/com/google/domain/registry/model/smd/SignedMarkRevocationList.java b/java/com/google/domain/registry/model/smd/SignedMarkRevocationList.java new file mode 100644 index 000000000..8bc170422 --- /dev/null +++ b/java/com/google/domain/registry/model/smd/SignedMarkRevocationList.java @@ -0,0 +1,191 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.smd; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Iterables.isEmpty; +import static com.google.domain.registry.model.common.EntityGroupRoot.getCrossTldKey; +import static com.google.domain.registry.model.ofy.ObjectifyService.allocateId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CacheUtils.memoizeWithShortExpiration; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.model.common.EntityGroupRoot; +import com.google.domain.registry.util.CollectionUtils; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.EmbedMap; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.OnSave; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.Map; + +/** + * Signed Mark Data Revocation List (SMDRL). + *

+ * Represents a SMDRL file downloaded from the TMCH MarksDB each day. The list holds the ids of + * all the {@link SignedMark SignedMarks} that have been revoked. A new list is created for each + * new file that's created, depending on the timestamp. + *

+ * We'll be putting the entire table into a single entity for the sake of performance. But in order + * to avoid exceeding the one megabyte max entity size limit, we'll also be sharding that entity + * into multiple entities, each entity containing {@value #SHARD_SIZE} rows. + * + * @see com.google.domain.registry.tmch.SmdrlCsvParser + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.2" + */ +@Entity +@NotBackedUp(reason = Reason.EXTERNALLY_SOURCED) +public class SignedMarkRevocationList extends ImmutableObject { + + @VisibleForTesting + static final int SHARD_SIZE = 10000; + + /** Common ancestor for queries. */ + @Parent + Key parent = getCrossTldKey(); + + /** ID for the sharded entity. */ + @Id + long id; + + /** Time when this list was last updated, as specified in the first line of the CSV file. */ + DateTime creationTime; + + /** A map from SMD IDs to revocation time. */ + @EmbedMap + Map revokes; + + /** Indicates that this is a shard rather than a "full" list. */ + @Ignore + boolean isShard; + + /** + * A cached supplier that fetches the SMDRL shards from the datastore and recombines them into a + * single {@link SignedMarkRevocationList} object. + */ + private static final Supplier CACHE = + memoizeWithShortExpiration(new Supplier() { + @Override + public SignedMarkRevocationList get() { + // Open a new transactional read even if we are in a transaction currently. + return ofy().transactNewReadOnly(new Work() { + @Override + public SignedMarkRevocationList run() { + Iterable shards = ofy() + .load() + .type(SignedMarkRevocationList.class) + .ancestor(getCrossTldKey()); + DateTime creationTime = + isEmpty(shards) + ? START_OF_TIME + : checkNotNull(Iterables.get(shards, 0).creationTime, "creationTime"); + ImmutableMap.Builder revokes = new ImmutableMap.Builder<>(); + for (SignedMarkRevocationList shard : shards) { + revokes.putAll(shard.revokes); + checkState( + creationTime.equals(shard.creationTime), + "Inconsistent creation times: %s vs. %s", creationTime, shard.creationTime); + } + return create(creationTime, revokes.build()); + }}); + }}); + + /** Return a single logical instance that combines all the datastore shards. */ + public static SignedMarkRevocationList get() { + return CACHE.get(); + } + + /** Create a new {@link SignedMarkRevocationList} without saving it. */ + public static SignedMarkRevocationList create( + DateTime creationTime, ImmutableMap revokes) { + SignedMarkRevocationList instance = new SignedMarkRevocationList(); + instance.creationTime = checkNotNull(creationTime, "creationTime"); + instance.revokes = checkNotNull(revokes, "revokes"); + return instance; + } + + /** Returns {@code true} if the SMD ID has been revoked at the given point in time. */ + public boolean isSmdRevoked(String smdId, DateTime now) { + DateTime revoked = revokes.get(checkNotNull(smdId, "smdId")); + if (revoked == null) { + return false; + } + return isBeforeOrAt(revoked, now); + } + + /** Returns the creation timestamp specified at the top of the SMDRL CSV file. */ + public DateTime getCreationTime() { + return creationTime; + } + + /** Returns the number of revocations. */ + public int size() { + return revokes.size(); + } + + /** Save this list to the datastore in sharded form. Returns {@code this}. */ + public SignedMarkRevocationList save() { + ofy().transact(new VoidWork() { + @Override + public void vrun() { + ofy().deleteWithoutBackup().keys(ofy() + .load() + .type(SignedMarkRevocationList.class) + .ancestor(getCrossTldKey()) + .keys()); + ofy().saveWithoutBackup().entities(FluentIterable + .from(CollectionUtils.partitionMap(revokes, SHARD_SIZE)) + .transform(new Function, SignedMarkRevocationList>() { + @Override + public SignedMarkRevocationList apply(ImmutableMap shardRevokes) { + SignedMarkRevocationList shard = create(creationTime, shardRevokes); + shard.id = allocateId(); + shard.isShard = true; // Avoid the exception in disallowUnshardedSaves(). + return shard; + }})); + }}); + return this; + } + + /** As a safety mechanism, fail if someone tries to save this class directly. */ + @OnSave + void disallowUnshardedSaves() { + if (!isShard) { + throw new UnshardedSaveException(); + } + } + + /** Exception when trying to directly save a {@link SignedMarkRevocationList} without sharding. */ + public static class UnshardedSaveException extends RuntimeException {} +} diff --git a/java/com/google/domain/registry/model/smd/package-info.java b/java/com/google/domain/registry/model/smd/package-info.java new file mode 100644 index 000000000..067083a54 --- /dev/null +++ b/java/com/google/domain/registry/model/smd/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:signedMark-1.0", + xmlns = @XmlNs(prefix = "smd", namespaceURI = "urn:ietf:params:xml:ns:signedMark-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.smd; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/tmch/ClaimsListShard.java b/java/com/google/domain/registry/model/tmch/ClaimsListShard.java new file mode 100644 index 000000000..903313646 --- /dev/null +++ b/java/com/google/domain/registry/model/tmch/ClaimsListShard.java @@ -0,0 +1,277 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.tmch; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Verify.verify; +import static com.google.domain.registry.model.ofy.ObjectifyService.allocateId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.CacheUtils.memoizeWithShortExpiration; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.model.annotations.VirtualEntity; +import com.google.domain.registry.model.common.CrossTldSingleton; +import com.google.domain.registry.util.CollectionUtils; +import com.google.domain.registry.util.Concurrent; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.EmbedMap; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.OnSave; +import com.googlecode.objectify.annotation.Parent; + +import org.joda.time.DateTime; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * A list of TMCH claims labels and their associated claims keys. + * + *

The claims list is actually sharded into multiple {@link ClaimsListShard} entities to work + * around the Datastore limitation of 1M max size per entity. However, when calling {@link #get} all + * of the shards are recombined into one {@link ClaimsListShard} object. + * + *

ClaimsList shards are tied to a specific revision and are persisted individually, then the + * entire claims list is atomically shifted over to using the new shards by persisting the new + * revision object and updating the {@link ClaimsListSingleton} pointing to it. This bypasses the + * 10MB per transaction limit. + * + *

Therefore, it is never OK to save an instance of this class directly to Datastore. Instead you + * must use the {@link #save} method to do it for you. + */ +@Entity +@NotBackedUp(reason = Reason.EXTERNALLY_SOURCED) +public class ClaimsListShard extends ImmutableObject { + + @VisibleForTesting + public static final int SHARD_SIZE = 10000; + + @Id + long id; + + @Parent + Key parent; + + /** When the claims list was last updated. */ + DateTime creationTime; + + /** A map from labels to claims keys. */ + @EmbedMap + Map labelsToKeys; + + /** Indicates that this is a shard rather than a "full" list. */ + @Ignore + boolean isShard = false; + + /** + * A cached supplier that fetches the claims list shards from the datastore and recombines them + * into a single {@link ClaimsListShard} object. + */ + private static final Supplier CACHE = + memoizeWithShortExpiration(new Supplier() { + @Override + public ClaimsListShard get() { + // Find the most recent revision. + Key revisionKey = getCurrentRevision(); + + Map combinedLabelsToKeys = new HashMap<>(); + DateTime creationTime = START_OF_TIME; + if (revisionKey != null) { + // Grab all of the keys for the shards that belong to the current revision. + final List> shardKeys = + ofy().load().type(ClaimsListShard.class).ancestor(revisionKey).keys().list(); + + // Load all of the shards concurrently, each in a separate transaction. + List shards = Concurrent.transform( + shardKeys, new Function, ClaimsListShard>() { + @Override + public ClaimsListShard apply(final Key key) { + return ofy().transactNewReadOnly(new Work() { + @Override + public ClaimsListShard run() { + return ofy().load().key(key).now(); + }}); + }}); + + // Combine the shards together and return the concatenated ClaimsList. + if (!shards.isEmpty()) { + creationTime = shards.get(0).creationTime; + for (ClaimsListShard shard : shards) { + combinedLabelsToKeys.putAll(shard.labelsToKeys); + checkState( + creationTime.equals(shard.creationTime), "Inconsistent creation times."); + } + } + } + return create(creationTime, ImmutableMap.copyOf(combinedLabelsToKeys)); + }}); + + public DateTime getCreationTime() { + return creationTime; + } + + public String getClaimKey(String label) { + return labelsToKeys.get(label); + } + + public ImmutableMap getLabelsToKeys() { + return ImmutableMap.copyOf(labelsToKeys); + } + + /** Returns the number of claims. */ + public int size() { + return labelsToKeys.size(); + } + + /** + * Save the Claims list to Datastore by writing the new shards in a series of transactions, + * switching over to using them atomically, then deleting the old ones. + */ + public void save() { + // Figure out what the next versionId should be based on which ones already exist. + final Key oldRevision = getCurrentRevision(); + final Key parentKey = ClaimsListRevision.createKey(); + + // Save the ClaimsList shards in separate transactions. + Concurrent.transform(CollectionUtils.partitionMap(labelsToKeys, SHARD_SIZE), + new Function, ClaimsListShard>() { + @Override + public ClaimsListShard apply(final ImmutableMap labelsToKeysShard) { + return ofy().transactNew(new Work() { + @Override + public ClaimsListShard run() { + ClaimsListShard shard = create(creationTime, labelsToKeysShard); + shard.isShard = true; + shard.parent = parentKey; + ofy().saveWithoutBackup().entity(shard); + return shard; + }}); + }}); + + // Persist the new revision, thus causing the newly created shards to go live. + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + verify(getCurrentRevision() == null && oldRevision == null + || getCurrentRevision().equals(oldRevision), + "ClaimsList on Registries was updated by someone else while attempting to update."); + ofy().saveWithoutBackup().entity(ClaimsListSingleton.create(parentKey)); + // Delete the old ClaimsListShard entities. + if (oldRevision != null) { + ofy().deleteWithoutBackup() + .keys(ofy().load().type(ClaimsListShard.class).ancestor(oldRevision).keys()); + } + }}); + } + + public static ClaimsListShard create( + DateTime creationTime, ImmutableMap labelsToKeys) { + ClaimsListShard instance = new ClaimsListShard(); + instance.id = allocateId(); + instance.creationTime = checkNotNull(creationTime); + instance.labelsToKeys = checkNotNull(labelsToKeys); + return instance; + } + + /** Return a single logical instance that combines all the datastore shards. */ + @Nullable + public static ClaimsListShard get() { + return CACHE.get(); + } + + /** As a safety mechanism, fail if someone tries to save this class directly. */ + @OnSave + void disallowUnshardedSaves() { + if (!isShard) { + throw new UnshardedSaveException(); + } + } + + /** Virtual parent entity for claims list shards of a specific revision. */ + @Entity + @VirtualEntity + public static class ClaimsListRevision extends ImmutableObject { + @Parent + Key parent; + + @Id + long versionId; + + @VisibleForTesting + public static Key createKey(ClaimsListSingleton singleton) { + ClaimsListRevision revision = new ClaimsListRevision(); + revision.versionId = allocateId(); + revision.parent = Key.create(singleton); + return Key.create(revision); + } + + @VisibleForTesting + public static Key createKey() { + return createKey(new ClaimsListSingleton()); + } + } + + /** + * Serves as the coordinating claims list singleton linking to the {@link ClaimsListRevision} + * that is live. + */ + @Entity + @Cache + @NotBackedUp(reason = Reason.EXTERNALLY_SOURCED) + public static class ClaimsListSingleton extends CrossTldSingleton { + Key activeRevision; + + static ClaimsListSingleton create(Key revision) { + ClaimsListSingleton instance = new ClaimsListSingleton(); + instance.activeRevision = revision; + return instance; + } + + @VisibleForTesting + public void setActiveRevision(Key revision) { + activeRevision = revision; + } + } + + /** + * Returns the current ClaimsListRevision if there is one, or null if no claims list revisions + * have ever been persisted yet. + */ + @Nullable + public static Key getCurrentRevision() { + ClaimsListSingleton singleton = ofy().load().entity(new ClaimsListSingleton()).now(); + return singleton == null ? null : singleton.activeRevision; + } + + /** Exception when trying to directly save a {@link ClaimsListShard} without sharding. */ + public static class UnshardedSaveException extends RuntimeException {} +} diff --git a/java/com/google/domain/registry/model/tmch/TmchCrl.java b/java/com/google/domain/registry/model/tmch/TmchCrl.java new file mode 100644 index 000000000..054059eb8 --- /dev/null +++ b/java/com/google/domain/registry/model/tmch/TmchCrl.java @@ -0,0 +1,75 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.tmch; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.model.annotations.NotBackedUp; +import com.google.domain.registry.model.annotations.NotBackedUp.Reason; +import com.google.domain.registry.model.common.CrossTldSingleton; + +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; + +import org.joda.time.DateTime; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** Datastore singleton for ICANN's TMCH CA certificate revocation list (CRL). */ +@Entity +@Cache +@Immutable +@NotBackedUp(reason = Reason.EXTERNALLY_SOURCED) +public final class TmchCrl extends CrossTldSingleton { + + String crl; + DateTime updated; + + /** Returns the singleton instance of this entity, without memoization. */ + @Nullable + public static TmchCrl get() { + return ofy().load().entity(new TmchCrl()).now(); + } + + /** + * Change the datastore singleton to a new ASCII-armored X.509 CRL. + *

+ * Please do not call this function unless your CRL is properly formatted, signed by the root, + * and actually newer than the one currently in the datastore. + */ + public static void set(final String crl) { + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + TmchCrl tmchCrl = new TmchCrl(); + tmchCrl.updated = ofy().getTransactionTime(); + tmchCrl.crl = checkNotNull(crl, "crl"); + ofy().saveWithoutBackup().entity(tmchCrl); + }}); + } + + /** ASCII-armored X.509 certificate revocation list. */ + public final String getCrl() { + return crl; + } + + /** Time we last updated the datastore with a newer ICANN CRL. */ + public final DateTime getUpdated() { + return updated; + } +} diff --git a/java/com/google/domain/registry/model/transfer/BaseTransferObject.java b/java/com/google/domain/registry/model/transfer/BaseTransferObject.java new file mode 100644 index 000000000..cf2bb4a34 --- /dev/null +++ b/java/com/google/domain/registry/model/transfer/BaseTransferObject.java @@ -0,0 +1,118 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.transfer; + +import com.google.domain.registry.model.Buildable.GenericBuilder; +import com.google.domain.registry.model.ImmutableObject; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** Fields common to {@link TransferData} and {@link TransferResponse}. */ +@XmlTransient +public abstract class BaseTransferObject extends ImmutableObject { + /** + * The status of the current or last transfer. Can be null if never transferred. Note that we + * leave IgnoreSave off this field so that we can ensure that TransferData loaded from Objectify + * will always be non-null. + */ + @XmlElement(name = "trStatus") + TransferStatus transferStatus; + + /** The gaining registrar of the current or last transfer. Can be null if never transferred. */ + @XmlElement(name = "reID") + String gainingClientId; + + /** The time that the last transfer was requested. Can be null if never transferred. */ + @XmlElement(name = "reDate") + DateTime transferRequestTime; + + /** The losing registrar of the current or last transfer. Can be null if never transferred. */ + @XmlElement(name = "acID") + String losingClientId; + + /** + * If the current transfer status is pending, then this holds the time that the transfer must be + * acted upon before the server will automatically approve the transfer. For all other states, + * this holds the time that the last pending transfer ended. Can be null if never transferred. + */ + @XmlElement(name = "acDate") + DateTime pendingTransferExpirationTime; + + public TransferStatus getTransferStatus() { + return transferStatus; + } + + public String getGainingClientId() { + return gainingClientId; + } + + public DateTime getTransferRequestTime() { + return transferRequestTime; + } + + public String getLosingClientId() { + return losingClientId; + } + + public DateTime getPendingTransferExpirationTime() { + return pendingTransferExpirationTime; + } + + /** Base class for builders of {@link BaseTransferObject} subclasses. */ + public abstract static class Builder> + extends GenericBuilder { + + /** Create a {@link Builder} wrapping a new instance. */ + protected Builder() {} + + /** Create a {@link Builder} wrapping the given instance. */ + protected Builder(T instance) { + super(instance); + } + + /** Set this resource's transfer status. */ + public B setTransferStatus(TransferStatus transferStatus) { + getInstance().transferStatus = transferStatus; + return thisCastToDerived(); + } + + /** Set the gaining registrar for a pending transfer on this resource. */ + public B setGainingClientId(String gainingClientId) { + getInstance().gainingClientId = gainingClientId; + return thisCastToDerived(); + } + + /** Set the time that the current transfer request was made on this resource. */ + public B setTransferRequestTime(DateTime transferRequestTime) { + getInstance().transferRequestTime = transferRequestTime; + return thisCastToDerived(); + } + + /** Set the losing registrar for a pending transfer on this resource. */ + public B setLosingClientId(String losingClientId) { + getInstance().losingClientId = losingClientId; + return thisCastToDerived(); + } + + /** Set the expiration time of the current pending transfer. */ + public B setPendingTransferExpirationTime(DateTime pendingTransferExpirationTime) { + getInstance().pendingTransferExpirationTime = pendingTransferExpirationTime; + return thisCastToDerived(); + } + } +} diff --git a/java/com/google/domain/registry/model/transfer/TransferData.java b/java/com/google/domain/registry/model/transfer/TransferData.java new file mode 100644 index 000000000..0e30a50f2 --- /dev/null +++ b/java/com/google/domain/registry/model/transfer/TransferData.java @@ -0,0 +1,177 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.transfer; + +import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy; + +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.Buildable; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.billing.BillingEvent; +import com.google.domain.registry.model.eppcommon.Trid; +import com.google.domain.registry.model.poll.PollMessage; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.IgnoreSave; +import com.googlecode.objectify.annotation.Unindex; +import com.googlecode.objectify.condition.IfNull; + +import java.util.Set; + +/** + * Common transfer data for {@link EppResource} types. Only applies to domains and contacts; + * hosts are implicitly transferred with their superordinate domain. + */ +@Embed +@Unindex +public class TransferData extends BaseTransferObject implements Buildable { + + public static final TransferData EMPTY = new TransferData(); + + /** + * The billing event and poll messages associated with a server-approved transfer. + *

+ * This field should be null if there is not currently a pending transfer or if the object being + * transferred is not a domain. If there is a pending transfer for a domain there should be a + * number of poll messages and billing events for both the gaining and losing registrars. If the + * pending transfer is explicitly approved, rejected or cancelled, the referenced entities should + * be deleted. + *

+ * Keys are stored here instead of references to facilitate bulk deletion (the typical use case, + * as described above), since Objectify allows bulk deletion by key but not by reference. + */ + @IgnoreSave(IfNull.class) + Set> serverApproveEntities; + + /** + * The regular one-time billing event that will be charged for a server-approved transfer. + *

+ * This field should be null if there is not currently a pending transfer or if the object being + * transferred is not a domain. + */ + @IgnoreSave(IfNull.class) + Ref serverApproveBillingEvent; + + /** + * The autorenew billing event that should be associated with this resource after the transfer. + *

+ * This field should be null if there is not currently a pending transfer or if the object being + * transferred is not a domain. + */ + @IgnoreSave(IfNull.class) + Ref serverApproveAutorenewEvent; + + /** + * The autorenew poll message that should be associated with this resource after the transfer. + *

+ * This field should be null if there is not currently a pending transfer or if the object being + * transferred is not a domain. + */ + @IgnoreSave(IfNull.class) + Ref serverApproveAutorenewPollMessage; + + /** The transaction id of the most recent transfer request (or null if there never was one). */ + Trid transferRequestTrid; + + /** + * The number of years to add to the registration expiration time if this transfer is approved. + * Can be null if never transferred, or for resource types where it's not applicable. + */ + Integer extendedRegistrationYears; + + public ImmutableSet> getServerApproveEntities() { + return nullToEmptyImmutableCopy(serverApproveEntities); + } + + public Ref getServerApproveBillingEvent() { + return serverApproveBillingEvent; + } + + public Ref getServerApproveAutorenewEvent() { + return serverApproveAutorenewEvent; + } + + public Ref getServerApproveAutorenewPollMessage() { + return serverApproveAutorenewPollMessage; + } + + public Trid getTransferRequestTrid() { + return transferRequestTrid; + } + + public Integer getExtendedRegistrationYears() { + return extendedRegistrationYears; + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** Builder for {@link TransferData} because it is immutable. */ + public static class Builder extends BaseTransferObject.Builder { + + /** Create a {@link Builder} wrapping a new instance. */ + public Builder() {} + + /** Create a {@link Builder} wrapping the given instance. */ + private Builder(TransferData instance) { + super(instance); + } + + public Builder setServerApproveEntities( + ImmutableSet> serverApproveEntities) { + getInstance().serverApproveEntities = serverApproveEntities; + return this; + } + + public Builder setServerApproveBillingEvent( + Ref serverApproveBillingEvent) { + getInstance().serverApproveBillingEvent = serverApproveBillingEvent; + return this; + } + + public Builder setServerApproveAutorenewEvent( + Ref serverApproveAutorenewEvent) { + getInstance().serverApproveAutorenewEvent = serverApproveAutorenewEvent; + return this; + } + + public Builder setServerApproveAutorenewPollMessage( + Ref serverApproveAutorenewPollMessage) { + getInstance().serverApproveAutorenewPollMessage = serverApproveAutorenewPollMessage; + return this; + } + + public Builder setTransferRequestTrid(Trid transferRequestTrid) { + getInstance().transferRequestTrid = transferRequestTrid; + return this; + } + + /** Set the years to add to the registration if this transfer completes. */ + public Builder setExtendedRegistrationYears(Integer extendedRegistrationYears) { + getInstance().extendedRegistrationYears = extendedRegistrationYears; + return thisCastToDerived(); + } + } + + /** + * Marker interface for objects that are written in anticipation of a server approval, and + * therefore need to be deleted under any other outcome. + */ + public interface TransferServerApproveEntity {} +} diff --git a/java/com/google/domain/registry/model/transfer/TransferResponse.java b/java/com/google/domain/registry/model/transfer/TransferResponse.java new file mode 100644 index 000000000..c45cb919e --- /dev/null +++ b/java/com/google/domain/registry/model/transfer/TransferResponse.java @@ -0,0 +1,110 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.transfer; + +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.eppoutput.Response.ResponseData; + +import com.googlecode.objectify.annotation.Embed; + +import org.joda.time.DateTime; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * A response to a transfer command on a {@link EppResource}. This base class contains fields that + * are common to all transfer responses; derived classes add resource specific fields. + */ +@XmlTransient +public abstract class TransferResponse extends BaseTransferObject implements ResponseData { + + /** An adapter to output the XML in response to a transfer command on a domain. */ + @Embed + @XmlRootElement(name = "trnData", namespace = "urn:ietf:params:xml:ns:domain-1.0") + @XmlType(propOrder = { + "fullyQualifiedDomainName", + "transferStatus", + "gainingClientId", + "transferRequestTime", + "losingClientId", + "pendingTransferExpirationTime", + "extendedRegistrationExpirationTime"}, + namespace = "urn:ietf:params:xml:ns:domain-1.0") + public static class DomainTransferResponse extends TransferResponse { + + @XmlElement(name = "name") + String fullyQualifiedDomainName; + + public String getFullyQualifiedDomainName() { + return fullyQualifiedDomainName; + } + + /** + * The new registration expiration time that will take effect if this transfer is approved. This + * will only be set on pending or approved transfers, not on cancelled or rejected ones. + */ + @XmlElement(name = "exDate") + DateTime extendedRegistrationExpirationTime; + + /** Builder for {@link DomainTransferResponse}. */ + public static class Builder + extends BaseTransferObject.Builder { + public Builder setFullyQualifiedDomainNameName(String fullyQualifiedDomainName) { + getInstance().fullyQualifiedDomainName = fullyQualifiedDomainName; + return this; + } + + /** Set the registration expiration time that will take effect if this transfer completes. */ + public Builder setExtendedRegistrationExpirationTime( + DateTime extendedRegistrationExpirationTime) { + getInstance().extendedRegistrationExpirationTime = extendedRegistrationExpirationTime; + return this; + } + } + } + + /** An adapter to output the XML in response to a transfer command on a contact. */ + @Embed + @XmlRootElement(name = "trnData", namespace = "urn:ietf:params:xml:ns:contact-1.0") + @XmlType(propOrder = { + "contactId", + "transferStatus", + "gainingClientId", + "transferRequestTime", + "losingClientId", + "pendingTransferExpirationTime"}, + namespace = "urn:ietf:params:xml:ns:contact-1.0") + public static class ContactTransferResponse extends TransferResponse { + + @XmlElement(name = "id") + String contactId; + + public String getContactId() { + return contactId; + } + + /** Builder for {@link ContactTransferResponse}. */ + public static class Builder + extends BaseTransferObject.Builder { + public Builder setContactId(String contactId) { + getInstance().contactId = contactId; + return this; + } + } + } +} diff --git a/java/com/google/domain/registry/model/transfer/TransferStatus.java b/java/com/google/domain/registry/model/transfer/TransferStatus.java new file mode 100644 index 000000000..624c9cc6c --- /dev/null +++ b/java/com/google/domain/registry/model/transfer/TransferStatus.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.transfer; + +import com.google.common.base.CaseFormat; + +import javax.xml.bind.annotation.XmlEnumValue; + +/** Represents the EPP transfer status as defined in RFC 5730. */ +public enum TransferStatus { + @XmlEnumValue("clientApproved") + CLIENT_APPROVED("Transfer approved."), + + @XmlEnumValue("clientCancelled") + CLIENT_CANCELLED("Transfer cancelled."), + + @XmlEnumValue("clientRejected") + CLIENT_REJECTED("Transfer rejected."), + + @XmlEnumValue("pending") + PENDING("Transfer requested."), + + @XmlEnumValue("serverApproved") + SERVER_APPROVED("Transfer approved."), + + @XmlEnumValue("serverCancelled") + SERVER_CANCELLED("Transfer cancelled."); + + private final String message; + + private TransferStatus(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public String getXmlName() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, toString()); + } +} diff --git a/java/com/google/domain/registry/model/transfer/package-info.java b/java/com/google/domain/registry/model/transfer/package-info.java new file mode 100644 index 000000000..5396f0120 --- /dev/null +++ b/java/com/google/domain/registry/model/transfer/package-info.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@XmlSchema( + namespace = "urn:ietf:params:xml:ns:epp-1.0", + xmlns = @XmlNs(prefix = "", namespaceURI = "urn:ietf:params:xml:ns:epp-1.0"), + elementFormDefault = XmlNsForm.QUALIFIED) +@XmlAccessorType(XmlAccessType.FIELD) +@XmlJavaTypeAdapter(UtcDateTimeAdapter.class) +package com.google.domain.registry.model.transfer; + +import com.google.domain.registry.xml.UtcDateTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + diff --git a/java/com/google/domain/registry/model/translators/AbstractSimpleTranslatorFactory.java b/java/com/google/domain/registry/model/translators/AbstractSimpleTranslatorFactory.java new file mode 100644 index 000000000..d384af38a --- /dev/null +++ b/java/com/google/domain/registry/model/translators/AbstractSimpleTranslatorFactory.java @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import com.google.domain.registry.util.TypeUtils.TypeInstantiator; + +import com.googlecode.objectify.impl.Path; +import com.googlecode.objectify.impl.Property; +import com.googlecode.objectify.impl.translate.CreateContext; +import com.googlecode.objectify.impl.translate.LoadContext; +import com.googlecode.objectify.impl.translate.SaveContext; +import com.googlecode.objectify.impl.translate.ValueTranslator; +import com.googlecode.objectify.impl.translate.ValueTranslatorFactory; + +import java.lang.reflect.Type; + +/** Common boilerplate for translator factories. */ +public abstract class AbstractSimpleTranslatorFactory extends ValueTranslatorFactory { + + public AbstractSimpleTranslatorFactory(Class

clazz) { + super(clazz); + } + + @Override + protected final ValueTranslator createSafe( + Path path, Property property, Type type, CreateContext ctx) { + return new ValueTranslator(path, new TypeInstantiator(getClass()){}.getExactType()) { + + SimpleTranslator simpleTranslator = createTranslator(); + + @Override + protected P loadValue(D datastoreValue, LoadContext ctx) { + return simpleTranslator.loadValue(datastoreValue); + } + + @Override + protected D saveValue(P pojoValue, SaveContext ctx) { + return simpleTranslator.saveValue(pojoValue); + } + }; + } + + /** Translator with reduced boilerplate. */ + interface SimpleTranslator { + P loadValue(D datastoreValue); + + D saveValue(P pojoValue); + } + + abstract SimpleTranslator createTranslator(); +} diff --git a/java/com/google/domain/registry/model/translators/CidrAddressBlockTranslatorFactory.java b/java/com/google/domain/registry/model/translators/CidrAddressBlockTranslatorFactory.java new file mode 100644 index 000000000..0f3507562 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/CidrAddressBlockTranslatorFactory.java @@ -0,0 +1,40 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import com.google.domain.registry.util.CidrAddressBlock; + +/** Stores {@link CidrAddressBlock} as a canonicalized string. */ +public class CidrAddressBlockTranslatorFactory + extends AbstractSimpleTranslatorFactory { + + public CidrAddressBlockTranslatorFactory() { + super(CidrAddressBlock.class); + } + + @Override + SimpleTranslator createTranslator() { + return new SimpleTranslator(){ + @Override + public CidrAddressBlock loadValue(String datastoreValue) { + return CidrAddressBlock.create(datastoreValue); + } + + @Override + public String saveValue(CidrAddressBlock pojoValue) { + return pojoValue.toString(); + }}; + } +} diff --git a/java/com/google/domain/registry/model/translators/CommitLogRevisionsTranslatorFactory.java b/java/com/google/domain/registry/model/translators/CommitLogRevisionsTranslatorFactory.java new file mode 100644 index 000000000..b35a06e54 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/CommitLogRevisionsTranslatorFactory.java @@ -0,0 +1,77 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; + +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Ordering; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.ofy.CommitLogManifest; + +import com.googlecode.objectify.Ref; + +import org.joda.time.DateTime; + +/** + * Objectify translator for {@code ImmutableSortedMap>} fields. + * + *

This translator is responsible for doing three things: + *

    + *
  1. Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner + * similar to {@code @Mapify}. + *
  2. Inserting a reference to the transaction's {@link CommitLogManifest} on save. + *
  3. Truncating the map to include only the last key per day for the last 30 days. + *
+ * + *

This allows you to have a field on your model object that tracks historical revisions of + * itself, which can be binary searched for point-in-time restoration. + * + *

Warning: Fields of this type must not be {@code null}, or else new entries can't be + * inserted. You must take care to initialize the field to empty. + * + * @see com.google.domain.registry.model.EppResource + */ +public final class CommitLogRevisionsTranslatorFactory + extends ImmutableSortedMapTranslatorFactory> { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + /** + * Add a reference to the current commit log to the resource's revisions map. + * + *

This method also prunes the revisions map. It guarantees to keep enough data so that floor + * will work going back N days. It does this by making sure one entry exists before that duration, + * and pruning everything after it. The size of the map is guaranteed to never exceed N+2. + * + *

We store a maximum of one entry per day. It will be the last transaction that happened on + * that day. + * + * @see com.google.domain.registry.config.RegistryConfig#getCommitLogDatastoreRetention() + */ + @Override + ImmutableSortedMap> transformBeforeSave( + ImmutableSortedMap> revisions) { + DateTime now = ofy().getTransactionTime(); + DateTime threshold = now.minus(ENVIRONMENT.config().getCommitLogDatastoreRetention()); + DateTime preThresholdTime = firstNonNull(revisions.floorKey(threshold), START_OF_TIME); + return new ImmutableSortedMap.Builder>(Ordering.natural()) + .putAll(revisions.subMap(preThresholdTime, true, now.withTimeAtStartOfDay(), false)) + .put(now, Ref.create(ofy().getCommitLogManifestKey())) + .build(); + } +} diff --git a/java/com/google/domain/registry/model/translators/CreateAutoTimestampTranslatorFactory.java b/java/com/google/domain/registry/model/translators/CreateAutoTimestampTranslatorFactory.java new file mode 100644 index 000000000..209b34b81 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/CreateAutoTimestampTranslatorFactory.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import static com.google.common.base.MoreObjects.firstNonNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.domain.registry.model.CreateAutoTimestamp; + +import org.joda.time.DateTime; + +import java.util.Date; + +/** Saves {@link CreateAutoTimestamp} as either its value, or the current time if it was null. */ +public class CreateAutoTimestampTranslatorFactory + extends AbstractSimpleTranslatorFactory { + + public CreateAutoTimestampTranslatorFactory() { + super(CreateAutoTimestamp.class); + } + + @Override + SimpleTranslator createTranslator() { + return new SimpleTranslator() { + + /** + * Load an existing timestamp. It can be assumed to be non-null since if the field is null in + * datastore then Objectify will skip this translator and directly load a null. + */ + @Override + public CreateAutoTimestamp loadValue(Date datastoreValue) { + return CreateAutoTimestamp.create(new DateTime(datastoreValue, UTC)); + } + + /** Save a timestamp, setting it to the current time if it did not have a previous value. */ + @Override + public Date saveValue(CreateAutoTimestamp pojoValue) { + return firstNonNull(pojoValue.getTimestamp(), ofy().getTransactionTime()).toDate(); + }}; + } +} diff --git a/java/com/google/domain/registry/model/translators/CurrencyUnitAdapter.java b/java/com/google/domain/registry/model/translators/CurrencyUnitAdapter.java new file mode 100644 index 000000000..41f60adf7 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/CurrencyUnitAdapter.java @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import static com.google.common.base.Strings.nullToEmpty; + +import org.joda.money.CurrencyUnit; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** Adapter to use Joda {@link CurrencyUnit} when marshalling strings. */ +public class CurrencyUnitAdapter extends XmlAdapter { + + /** Parses a string into a {@link CurrencyUnit} object. */ + @Override + public CurrencyUnit unmarshal(String currency) throws UnknownCurrencyException { + try { + return CurrencyUnit.of(nullToEmpty(currency).trim()); + } catch (IllegalArgumentException e) { + throw new UnknownCurrencyException(); + } + } + + /** Converts {@link CurrencyUnit} to a string. */ + @Override + public String marshal(CurrencyUnit currency) { + return currency == null ? null : currency.toString(); + } + + /** Exception to throw when failing to parse a currency. */ + public static class UnknownCurrencyException extends Exception {} +} diff --git a/java/com/google/domain/registry/model/translators/CurrencyUnitTranslatorFactory.java b/java/com/google/domain/registry/model/translators/CurrencyUnitTranslatorFactory.java new file mode 100644 index 000000000..011582658 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/CurrencyUnitTranslatorFactory.java @@ -0,0 +1,40 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import org.joda.money.CurrencyUnit; + +/** Stores {@link CurrencyUnit} as a canonicalized string. */ +public class CurrencyUnitTranslatorFactory + extends AbstractSimpleTranslatorFactory { + + public CurrencyUnitTranslatorFactory() { + super(CurrencyUnit.class); + } + + @Override + SimpleTranslator createTranslator() { + return new SimpleTranslator(){ + @Override + public CurrencyUnit loadValue(String datastoreValue) { + return CurrencyUnit.of(datastoreValue); + } + + @Override + public String saveValue(CurrencyUnit pojoValue) { + return pojoValue.toString(); + }}; + } +} diff --git a/java/com/google/domain/registry/model/translators/DurationTranslatorFactory.java b/java/com/google/domain/registry/model/translators/DurationTranslatorFactory.java new file mode 100644 index 000000000..e3bce4c8e --- /dev/null +++ b/java/com/google/domain/registry/model/translators/DurationTranslatorFactory.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import org.joda.time.Duration; + +/** Stores {@link Duration} as a canonicalized string. */ +public class DurationTranslatorFactory extends AbstractSimpleTranslatorFactory { + + public DurationTranslatorFactory() { + super(Duration.class); + } + + @Override + protected SimpleTranslator createTranslator() { + return new SimpleTranslator() { + @Override + public Duration loadValue(String datastoreValue) { + return Duration.parse(datastoreValue); + } + + @Override + public String saveValue(Duration pojoValue) { + return pojoValue.toString(); + }}; + } +} diff --git a/java/com/google/domain/registry/model/translators/EnumToAttributeAdapter.java b/java/com/google/domain/registry/model/translators/EnumToAttributeAdapter.java new file mode 100644 index 000000000..9424ec8a2 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/EnumToAttributeAdapter.java @@ -0,0 +1,56 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.adapters.XmlAdapter; + +/** + * Used by JAXB to convert enums to the peculiar EPP format that puts the value in an attribute. + * + * @param the enum type + */ +public class EnumToAttributeAdapter & EnumToAttributeAdapter.EppEnum> + extends XmlAdapter { + + /** Interface for epp enums that can be transformed with this adapter. */ + public interface EppEnum { + String getXmlName(); + } + + /** + * EPP's peculiar enum format. + *

+ * It's meant to allow more information inside the element, but it's an annoyance when we want to + * deal with pure enums. + */ + static class EnumShim { + @XmlAttribute + String s; + } + + // Enums that can be unmarshalled from input can override this. + @Override + public E unmarshal(EnumShim shim) throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + public final EnumShim marshal(E enumeration) throws Exception { + EnumShim shim = new EnumShim(); + shim.s = enumeration.getXmlName(); + return shim; + } +} diff --git a/java/com/google/domain/registry/model/translators/ImmutableSortedMapTranslatorFactory.java b/java/com/google/domain/registry/model/translators/ImmutableSortedMapTranslatorFactory.java new file mode 100644 index 000000000..2453b968e --- /dev/null +++ b/java/com/google/domain/registry/model/translators/ImmutableSortedMapTranslatorFactory.java @@ -0,0 +1,168 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.erase; +import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.getTypeParameter; + +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Ordering; +import com.google.common.reflect.TypeToken; + +import com.googlecode.objectify.impl.Node; +import com.googlecode.objectify.impl.Path; +import com.googlecode.objectify.impl.Property; +import com.googlecode.objectify.impl.translate.CreateContext; +import com.googlecode.objectify.impl.translate.ListNodeTranslator; +import com.googlecode.objectify.impl.translate.LoadContext; +import com.googlecode.objectify.impl.translate.SaveContext; +import com.googlecode.objectify.impl.translate.SkipException; +import com.googlecode.objectify.impl.translate.Translator; +import com.googlecode.objectify.impl.translate.TranslatorFactory; +import com.googlecode.objectify.impl.translate.TranslatorRegistry; + +import java.lang.reflect.Type; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Abstract Objectify translator for {@link ImmutableSortedMap} fields. + * + *

This class should be extended for each set of concrete key/value types you wish to support. + * This translator will only apply to {@code ImmutableSortedMap} model fields that have precicely + * the same type parameters you specified. + * + *

This translator serves a similar purpose to + * {@link com.googlecode.objectify.impl.translate.MapifyTranslatorFactory @Mapify}. Except this + * maintains perfect immutability of the field value. Subclasses may override the + * {@link #transformBeforeSave(ImmutableSortedMap)} methods to perform mutation on a per-concrete + * type basis. This abstraction is also more readable than {@code @Mapify} because it shifts the + * boilerplate into translator magic, rather than convoluting model data structures. + * + *

Entity Data Layout

+ * + *

For example, if you had an {@code ImmutableSortedMap} on a field named + * {@code field}, then this would look like:

   {@code
+ *
+ *   field.key -> [key1, key2]
+ *   field.value -> [value1, value2]}
+ * + *

If you had an {@code ImmutableSortedMap} on a field named + * {@code field}, where {@code EmbeddedClass} defines two {@code foo} and {@code bar} fields, then + * the embedded properties might look like:

   {@code
+ *
+ *   field.key -> [key1, key2]
+ *   field.value.foo -> [foo1, foo2]
+ *   field.value.bar -> [bar1, bar2]}
+ * + * @param key type for sorted map which must be {@link Comparable} + * @param value type for sorted map + */ +abstract class ImmutableSortedMapTranslatorFactory, V> + implements TranslatorFactory> { + + private final TypeToken keyType = new TypeToken(getClass()) {}; + private final TypeToken valueType = new TypeToken(getClass()) {}; + private final String keyProperty; + private final String valueProperty; + + ImmutableSortedMapTranslatorFactory() { + this("key", "value"); + } + + /** Constructs a instance that's compatible with models migrated from {@code @Mapify}. */ + ImmutableSortedMapTranslatorFactory(String keyProperty, String valueProperty) { + this.keyProperty = checkNotNull(keyProperty); + this.valueProperty = checkNotNull(valueProperty); + } + + /** Allows for changing the field data structure before it's written to the raw entity object. */ + ImmutableSortedMap transformBeforeSave(ImmutableSortedMap map) { + return map; + } + + @Override + public final Translator> + create(Path path, Property property, Type type, CreateContext ctx) { + if (!ImmutableSortedMap.class.equals(erase(type))) { + return null; // skip me and try to find another matching translator + } + Type fieldKeyType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[0]); + Type fieldValueType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[1]); + if (fieldKeyType == null || fieldValueType == null) { + return null; // no type information is available + } + if (!keyType.isSupertypeOf(fieldKeyType) || !valueType.isSupertypeOf(fieldValueType)) { + return null; // this ImmutableSortedMap does not have the same concrete component types + } + ctx.enterCollection(path); + ctx.enterEmbed(path); + try { + // The component types can also be translated by Objectify! + TranslatorRegistry translators = ctx.getFactory().getTranslators(); + final Translator keyTranslator = + translators.create(path.extend(keyProperty), property, fieldKeyType, ctx); + final Translator valueTranslator = + translators.create(path.extend(valueProperty), property, fieldValueType, ctx); + return new ListNodeTranslator>() { + @Override + protected ImmutableSortedMap loadList(Node node, LoadContext ctx) { + ImmutableSortedMap.Builder map = + new ImmutableSortedMap.Builder<>(Ordering.natural()); + for (Node child : node) { + try { + map.put(keyTranslator.load(child.get(keyProperty), ctx), + valueTranslator.load(child.get(valueProperty), ctx)); + } catch (SkipException e) { + // no problem, just skip that one + } + } + return map.build(); + } + + @Override + protected Node saveList( + @Nullable ImmutableSortedMap mapFromPojo, + Path path, + boolean index, + SaveContext ctx) { + checkState(!index, "At path %s: Index not allowed", path); + ImmutableSortedMap mapToSave = transformBeforeSave( + ImmutableSortedMap.copyOfSorted(nullToEmpty(mapFromPojo))); + if (mapToSave.isEmpty()) { + throw new SkipException(); // the datastore doesn't store empty lists + } + Node node = new Node(path); + for (Map.Entry entry : mapToSave.entrySet()) { + Node item = new Node(path); + item.put(keyProperty, + keyTranslator.save(entry.getKey(), path.extend(keyProperty), index, ctx)); + item.put(valueProperty, + valueTranslator.save(entry.getValue(), path.extend(valueProperty), index, ctx)); + node.addToList(item); + } + return node; + } + }; + } finally { + ctx.exitEmbed(); + ctx.exitCollection(); + } + } +} diff --git a/java/com/google/domain/registry/model/translators/InetAddressTranslatorFactory.java b/java/com/google/domain/registry/model/translators/InetAddressTranslatorFactory.java new file mode 100644 index 000000000..e005b983f --- /dev/null +++ b/java/com/google/domain/registry/model/translators/InetAddressTranslatorFactory.java @@ -0,0 +1,42 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import com.google.common.net.InetAddresses; + +import java.net.InetAddress; + +/** Stores {@link InetAddress} as a canonicalized string. */ +public class InetAddressTranslatorFactory + extends AbstractSimpleTranslatorFactory { + + public InetAddressTranslatorFactory() { + super(InetAddress.class); + } + + @Override + SimpleTranslator createTranslator() { + return new SimpleTranslator() { + @Override + public InetAddress loadValue(String datastoreValue) { + return InetAddresses.forString(datastoreValue); + } + + @Override + public String saveValue(InetAddress pojoValue) { + return pojoValue.getHostAddress(); + }}; + } +} diff --git a/java/com/google/domain/registry/model/translators/ReadableInstantUtcTranslatorFactory.java b/java/com/google/domain/registry/model/translators/ReadableInstantUtcTranslatorFactory.java new file mode 100644 index 000000000..0d64e762c --- /dev/null +++ b/java/com/google/domain/registry/model/translators/ReadableInstantUtcTranslatorFactory.java @@ -0,0 +1,68 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import com.googlecode.objectify.impl.Path; +import com.googlecode.objectify.impl.Property; +import com.googlecode.objectify.impl.TypeUtils; +import com.googlecode.objectify.impl.translate.CreateContext; +import com.googlecode.objectify.impl.translate.LoadContext; +import com.googlecode.objectify.impl.translate.SaveContext; +import com.googlecode.objectify.impl.translate.ValueTranslator; +import com.googlecode.objectify.impl.translate.ValueTranslatorFactory; +import com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector; + +import org.joda.time.DateTimeZone; +import org.joda.time.ReadableInstant; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Type; +import java.util.Date; + + +/** + * Stores Joda {@link ReadableInstant} types ({@code DateTime}, etc) as a {@link java.util.Date}. + *

+ * This is a fork of the {@code ReadableInstantTranslatorFactory} that comes bundled with Objectify. + * The original reifies a {@link ReadableInstant} using the machine's local time zone. This version + * always uses UTC. + */ +public class ReadableInstantUtcTranslatorFactory + extends ValueTranslatorFactory { + + public ReadableInstantUtcTranslatorFactory() { + super(ReadableInstant.class); + } + + @Override + protected ValueTranslator createSafe( + Path path, Property property, Type type, CreateContext ctx) { + final Class clazz = GenericTypeReflector.erase(type); + + return new ValueTranslator(path, Date.class) { + @Override + protected ReadableInstant loadValue(Date value, LoadContext ctx) { + // All the Joda instants have a constructor that will take a Date and timezone. + Constructor ctor = TypeUtils.getConstructor(clazz, Object.class, DateTimeZone.class); + return (ReadableInstant) TypeUtils.newInstance(ctor, value, DateTimeZone.UTC); + } + + @Override + protected Date saveValue(ReadableInstant value, SaveContext ctx) { + return value.toInstant().toDate(); + } + }; + } +} diff --git a/java/com/google/domain/registry/model/translators/StatusValueAdapter.java b/java/com/google/domain/registry/model/translators/StatusValueAdapter.java new file mode 100644 index 000000000..6c8ee1fa5 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/StatusValueAdapter.java @@ -0,0 +1,26 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import com.google.domain.registry.model.eppcommon.StatusValue; + +/** Adapter for {@link StatusValue}. */ +public class StatusValueAdapter extends EnumToAttributeAdapter { + @Override + public StatusValue unmarshal(EnumShim shim) { + // The value must be a valid enum value from the xsd, or JAXB will never get this far. + return StatusValue.fromXmlName(shim.s); + } +} diff --git a/java/com/google/domain/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java b/java/com/google/domain/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java new file mode 100644 index 000000000..825553716 --- /dev/null +++ b/java/com/google/domain/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.model.translators; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.domain.registry.model.UpdateAutoTimestamp; + +import org.joda.time.DateTime; + +import java.util.Date; + +/** Saves {@link UpdateAutoTimestamp} as the current time. */ +public class UpdateAutoTimestampTranslatorFactory + extends AbstractSimpleTranslatorFactory { + + public UpdateAutoTimestampTranslatorFactory() { + super(UpdateAutoTimestamp.class); + } + + @Override + SimpleTranslator createTranslator() { + return new SimpleTranslator() { + + /** + * Load an existing timestamp. It can be assumed to be non-null since if the field is null in + * datastore then Objectify will skip this translator and directly load a null. + */ + @Override + public UpdateAutoTimestamp loadValue(Date datastoreValue) { + // Load an existing timestamp, or treat it as START_OF_TIME if none exists. + return UpdateAutoTimestamp.create(new DateTime(datastoreValue, UTC)); + } + + /** Save a timestamp, setting it to the current time. */ + @Override + public Date saveValue(UpdateAutoTimestamp pojoValue) { + return ofy().getTransactionTime().toDate(); + }}; + } +} diff --git a/java/com/google/domain/registry/module/backend/BUILD b/java/com/google/domain/registry/module/backend/BUILD new file mode 100644 index 000000000..a5dcb601f --- /dev/null +++ b/java/com/google/domain/registry/module/backend/BUILD @@ -0,0 +1,50 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "backend", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//java/com/google/domain/registry/backup", + "//java/com/google/domain/registry/bigquery", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/cron", + "//java/com/google/domain/registry/dns", + "//java/com/google/domain/registry/dns/writer/api", + "//java/com/google/domain/registry/export", + "//java/com/google/domain/registry/export/sheet", + "//java/com/google/domain/registry/flows", + "//java/com/google/domain/registry/gcs", + "//java/com/google/domain/registry/groups", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/mapreduce", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/rde", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/request:modules", + "//java/com/google/domain/registry/tmch", + "//java/com/google/domain/registry/util", + "//third_party/java/bouncycastle", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/servlet/servlet_api", + ], +) + +# This rule is used so bazel can generate "backend_jar_deploy.jar" (which +# contains transitive dependencies) for deployment to App Engine. It MUST +# explicitly depend upon upon anything loaded at runtime, e.g. old servlets +# referenced by the module's web.xml file, that isn't statically linked above. +java_binary( + name = "backend_jar", + create_executable = 0, + runtime_deps = [ + ":backend", + ], +) diff --git a/java/com/google/domain/registry/module/backend/BackendComponent.java b/java/com/google/domain/registry/module/backend/BackendComponent.java new file mode 100644 index 000000000..d4ecb1bde --- /dev/null +++ b/java/com/google/domain/registry/module/backend/BackendComponent.java @@ -0,0 +1,74 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.backend; + +import com.google.domain.registry.bigquery.BigqueryModule; +import com.google.domain.registry.config.ConfigModule; +import com.google.domain.registry.dns.writer.api.VoidDnsWriterModule; +import com.google.domain.registry.export.DriveModule; +import com.google.domain.registry.export.sheet.SpreadsheetServiceModule; +import com.google.domain.registry.gcs.GcsServiceModule; +import com.google.domain.registry.groups.DirectoryModule; +import com.google.domain.registry.groups.GroupsModule; +import com.google.domain.registry.groups.GroupssettingsModule; +import com.google.domain.registry.keyring.api.KeyModule; +import com.google.domain.registry.keyring.api.VoidKeyringModule; +import com.google.domain.registry.rde.JSchModule; +import com.google.domain.registry.request.Modules.AppIdentityCredentialModule; +import com.google.domain.registry.request.Modules.DatastoreServiceModule; +import com.google.domain.registry.request.Modules.GoogleCredentialModule; +import com.google.domain.registry.request.Modules.Jackson2Module; +import com.google.domain.registry.request.Modules.ModulesServiceModule; +import com.google.domain.registry.request.Modules.URLFetchServiceModule; +import com.google.domain.registry.request.Modules.UrlFetchTransportModule; +import com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.util.SystemClock.SystemClockModule; +import com.google.domain.registry.util.SystemSleeper.SystemSleeperModule; + +import dagger.Component; + +import javax.inject.Singleton; + +/** Dagger component with instance lifetime for "backend" App Engine module. */ +@Singleton +@Component( + modules = { + AppIdentityCredentialModule.class, + BigqueryModule.class, + ConfigModule.class, + DatastoreServiceModule.class, + DirectoryModule.class, + DriveModule.class, + GcsServiceModule.class, + GoogleCredentialModule.class, + GroupsModule.class, + GroupssettingsModule.class, + JSchModule.class, + Jackson2Module.class, + KeyModule.class, + ModulesServiceModule.class, + SpreadsheetServiceModule.class, + SystemClockModule.class, + SystemSleeperModule.class, + URLFetchServiceModule.class, + UrlFetchTransportModule.class, + UseAppIdentityCredentialForGoogleApisModule.class, + VoidDnsWriterModule.class, + VoidKeyringModule.class, + }) +interface BackendComponent { + BackendRequestComponent startRequest(RequestModule requestModule); +} diff --git a/java/com/google/domain/registry/module/backend/BackendModule.java b/java/com/google/domain/registry/module/backend/BackendModule.java new file mode 100644 index 000000000..bdf0cd89d --- /dev/null +++ b/java/com/google/domain/registry/module/backend/BackendModule.java @@ -0,0 +1,39 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.backend; + +import static com.google.domain.registry.model.registry.Registries.assertTldExists; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; + +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; + +import dagger.Module; +import dagger.Provides; + +import javax.servlet.http.HttpServletRequest; + +/** + * Dagger module for injecting common settings for all Backend tasks. + */ +@Module +public class BackendModule { + + @Provides + @Parameter(RequestParameters.PARAM_TLD) + static String provideTld(HttpServletRequest req) { + return assertTldExists(extractRequiredParameter(req, RequestParameters.PARAM_TLD)); + } +} diff --git a/java/com/google/domain/registry/module/backend/BackendRequestComponent.java b/java/com/google/domain/registry/module/backend/BackendRequestComponent.java new file mode 100644 index 000000000..dd46903d2 --- /dev/null +++ b/java/com/google/domain/registry/module/backend/BackendRequestComponent.java @@ -0,0 +1,102 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.backend; + +import com.google.domain.registry.backup.BackupModule; +import com.google.domain.registry.backup.CommitLogCheckpointAction; +import com.google.domain.registry.backup.DeleteOldCommitLogsAction; +import com.google.domain.registry.backup.ExportCommitLogDiffAction; +import com.google.domain.registry.backup.RestoreCommitLogsAction; +import com.google.domain.registry.cron.CommitLogFanoutAction; +import com.google.domain.registry.cron.CronModule; +import com.google.domain.registry.cron.TldFanoutAction; +import com.google.domain.registry.dns.DnsModule; +import com.google.domain.registry.dns.PublishDnsUpdatesAction; +import com.google.domain.registry.dns.ReadDnsQueueAction; +import com.google.domain.registry.dns.RefreshDns; +import com.google.domain.registry.dns.WriteDnsTask; +import com.google.domain.registry.export.BigqueryPollJobAction; +import com.google.domain.registry.export.ExportRequestModule; +import com.google.domain.registry.export.ExportReservedTermsTask; +import com.google.domain.registry.export.SyncGroupMembersTask; +import com.google.domain.registry.export.sheet.SheetModule; +import com.google.domain.registry.export.sheet.SyncRegistrarsSheetTask; +import com.google.domain.registry.flows.async.AsyncFlowsModule; +import com.google.domain.registry.flows.async.DeleteContactResourceAction; +import com.google.domain.registry.flows.async.DeleteHostResourceAction; +import com.google.domain.registry.flows.async.DnsRefreshForHostRenameAction; +import com.google.domain.registry.mapreduce.MapreduceModule; +import com.google.domain.registry.rde.BrdaCopyTask; +import com.google.domain.registry.rde.RdeModule; +import com.google.domain.registry.rde.RdeReportTask; +import com.google.domain.registry.rde.RdeReporter; +import com.google.domain.registry.rde.RdeStagingAction; +import com.google.domain.registry.rde.RdeUploadTask; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.request.RequestScope; +import com.google.domain.registry.tmch.NordnUploadAction; +import com.google.domain.registry.tmch.NordnVerifyAction; +import com.google.domain.registry.tmch.TmchCrlTask; +import com.google.domain.registry.tmch.TmchDnlTask; +import com.google.domain.registry.tmch.TmchModule; +import com.google.domain.registry.tmch.TmchSmdrlTask; + +import dagger.Subcomponent; + +/** Dagger component with per-request lifetime for "backend" App Engine module. */ +@RequestScope +@Subcomponent( + modules = { + AsyncFlowsModule.class, + BackendModule.class, + BackupModule.class, + CronModule.class, + DnsModule.class, + ExportRequestModule.class, + MapreduceModule.class, + RdeModule.class, + RequestModule.class, + SheetModule.class, + TmchModule.class, + }) +interface BackendRequestComponent { + BigqueryPollJobAction bigqueryPollJobAction(); + BrdaCopyTask brdaCopyTask(); + CommitLogCheckpointAction commitLogCheckpointAction(); + CommitLogFanoutAction commitLogFanoutAction(); + DeleteContactResourceAction deleteContactResourceAction(); + DeleteHostResourceAction deleteHostResourceAction(); + DeleteOldCommitLogsAction deleteOldCommitLogsAction(); + DnsRefreshForHostRenameAction dnsRefreshForHostRenameAction(); + ExportCommitLogDiffAction exportCommitLogDiffAction(); + ExportReservedTermsTask exportReservedTermsTask(); + NordnUploadAction nordnUploadAction(); + NordnVerifyAction nordnVerifyAction(); + PublishDnsUpdatesAction publishDnsUpdatesAction(); + ReadDnsQueueAction readDnsQueueAction(); + RdeReportTask rdeReportTask(); + RdeStagingAction rdeStagingAction(); + RdeUploadTask rdeUploadTask(); + RdeReporter rdeReporter(); + RefreshDns refreshDns(); + RestoreCommitLogsAction restoreCommitLogsAction(); + SyncGroupMembersTask syncGroupMembersTask(); + SyncRegistrarsSheetTask syncRegistrarsSheetTask(); + TldFanoutAction tldFanoutAction(); + TmchCrlTask tmchCrlTask(); + TmchDnlTask tmchDnlTask(); + TmchSmdrlTask tmchSmdrlTask(); + WriteDnsTask writeDnsTask(); +} diff --git a/java/com/google/domain/registry/module/backend/BackendServlet.java b/java/com/google/domain/registry/module/backend/BackendServlet.java new file mode 100644 index 000000000..fd1717893 --- /dev/null +++ b/java/com/google/domain/registry/module/backend/BackendServlet.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.backend; + +import static java.util.Arrays.asList; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.domain.registry.request.RequestHandler; +import com.google.domain.registry.request.RequestModule; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.security.Security; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet that should handle all requests to our "backend" App Engine module. */ +public final class BackendServlet extends HttpServlet { + + private static final BackendComponent component = DaggerBackendComponent.create(); + + private static final RequestHandler requestHandler = + RequestHandler.create(BackendRequestComponent.class, FluentIterable + .from(asList(BackendRequestComponent.class.getMethods())) + .transform(new Function() { + @Override + public Method apply(Method method) { + method.setAccessible(true); // Make App Engine's security manager happy. + return method; + }})); + + @Override + public void init() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + requestHandler.handleRequest(req, rsp, component.startRequest(new RequestModule(req, rsp))); + } +} diff --git a/java/com/google/domain/registry/module/backend/package-info.java b/java/com/google/domain/registry/module/backend/package-info.java new file mode 100644 index 000000000..f5d7f6fa0 --- /dev/null +++ b/java/com/google/domain/registry/module/backend/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.module.backend; diff --git a/java/com/google/domain/registry/module/frontend/BUILD b/java/com/google/domain/registry/module/frontend/BUILD new file mode 100644 index 000000000..b3174b623 --- /dev/null +++ b/java/com/google/domain/registry/module/frontend/BUILD @@ -0,0 +1,44 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "frontend", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/domain/registry/braintree", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/rdap", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/request:modules", + "//java/com/google/domain/registry/ui", + "//java/com/google/domain/registry/ui/server/registrar", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/whois", + "//third_party/java/bouncycastle", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/servlet/servlet_api", + ], +) + +# This rule is used so bazel can generate "frontend_jar_deploy.jar" (which +# contains transitive dependencies) for deployment to App Engine. It MUST +# explicitly depend upon upon anything loaded at runtime, e.g. old servlets +# referenced by the module's web.xml file, that isn't statically linked above. +java_binary( + name = "frontend_jar", + create_executable = 0, + runtime_deps = [ + ":frontend", + "//java/com/google/domain/registry/monitoring/whitebox", # MetricsTaskServlet + "//java/com/google/domain/registry/ui/server/admin", # AdminUiServlet, etc. + "//java/com/google/domain/registry/ui/server/api", # CheckApiServlet + "//java/com/google/domain/registry/ui/server/registrar", # ConsoleUiServlet, etc. + ], +) diff --git a/java/com/google/domain/registry/module/frontend/FrontendComponent.java b/java/com/google/domain/registry/module/frontend/FrontendComponent.java new file mode 100644 index 000000000..b0a225918 --- /dev/null +++ b/java/com/google/domain/registry/module/frontend/FrontendComponent.java @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.frontend; + +import com.google.domain.registry.braintree.BraintreeModule; +import com.google.domain.registry.config.ConfigModule; +import com.google.domain.registry.keyring.api.KeyModule; +import com.google.domain.registry.keyring.api.VoidKeyringModule; +import com.google.domain.registry.request.Modules.UserServiceModule; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.ui.ConsoleConfigModule; +import com.google.domain.registry.util.SystemClock.SystemClockModule; + +import dagger.Component; + +import javax.inject.Singleton; + +/** Dagger component with instance lifetime for "default" App Engine module. */ +@Singleton +@Component( + modules = { + BraintreeModule.class, + ConfigModule.class, + ConsoleConfigModule.class, + KeyModule.class, + SystemClockModule.class, + UserServiceModule.class, + VoidKeyringModule.class, + }) +interface FrontendComponent { + FrontendRequestComponent startRequest(RequestModule requestModule); +} diff --git a/java/com/google/domain/registry/module/frontend/FrontendRequestComponent.java b/java/com/google/domain/registry/module/frontend/FrontendRequestComponent.java new file mode 100644 index 000000000..c0ca470bf --- /dev/null +++ b/java/com/google/domain/registry/module/frontend/FrontendRequestComponent.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.frontend; + +import com.google.domain.registry.rdap.RdapAutnumAction; +import com.google.domain.registry.rdap.RdapDomainAction; +import com.google.domain.registry.rdap.RdapDomainSearchAction; +import com.google.domain.registry.rdap.RdapEntityAction; +import com.google.domain.registry.rdap.RdapEntitySearchAction; +import com.google.domain.registry.rdap.RdapHelpAction; +import com.google.domain.registry.rdap.RdapIpAction; +import com.google.domain.registry.rdap.RdapModule; +import com.google.domain.registry.rdap.RdapNameserverAction; +import com.google.domain.registry.rdap.RdapNameserverSearchAction; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.request.RequestScope; +import com.google.domain.registry.ui.server.registrar.RegistrarPaymentAction; +import com.google.domain.registry.ui.server.registrar.RegistrarPaymentSetupAction; +import com.google.domain.registry.whois.WhoisHttpServer; +import com.google.domain.registry.whois.WhoisModule; +import com.google.domain.registry.whois.WhoisServer; + +import dagger.Subcomponent; + +/** Dagger component with per-request lifetime for "default" App Engine module. */ +@RequestScope +@Subcomponent( + modules = { + RdapModule.class, + RequestModule.class, + WhoisModule.class, + }) +interface FrontendRequestComponent { + RdapAutnumAction rdapAutnumAction(); + RegistrarPaymentAction registrarPaymentAction(); + RegistrarPaymentSetupAction registrarPaymentSetupAction(); + RdapDomainAction rdapDomainAction(); + RdapDomainSearchAction rdapDomainSearchAction(); + RdapEntityAction rdapEntityAction(); + RdapEntitySearchAction rdapEntitySearchAction(); + RdapHelpAction rdapHelpAction(); + RdapIpAction rdapDefaultAction(); + RdapNameserverAction rdapNameserverAction(); + RdapNameserverSearchAction rdapNameserverSearchAction(); + WhoisHttpServer whoisHttpServer(); + WhoisServer whoisServer(); +} diff --git a/java/com/google/domain/registry/module/frontend/FrontendServlet.java b/java/com/google/domain/registry/module/frontend/FrontendServlet.java new file mode 100644 index 000000000..57f5b987d --- /dev/null +++ b/java/com/google/domain/registry/module/frontend/FrontendServlet.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.frontend; + +import static java.util.Arrays.asList; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.domain.registry.request.RequestHandler; +import com.google.domain.registry.request.RequestModule; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.security.Security; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet that should handle all requests to our "default" App Engine module. */ +public final class FrontendServlet extends HttpServlet { + + private static final FrontendComponent component = DaggerFrontendComponent.create(); + + private static final RequestHandler requestHandler = + RequestHandler.create(FrontendRequestComponent.class, FluentIterable + .from(asList(FrontendRequestComponent.class.getMethods())) + .transform(new Function() { + @Override + public Method apply(Method method) { + method.setAccessible(true); // Make App Engine's security manager happy. + return method; + }})); + + @Override + public void init() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + requestHandler.handleRequest(req, rsp, component.startRequest(new RequestModule(req, rsp))); + } +} diff --git a/java/com/google/domain/registry/module/frontend/package-info.java b/java/com/google/domain/registry/module/frontend/package-info.java new file mode 100644 index 000000000..df89fa596 --- /dev/null +++ b/java/com/google/domain/registry/module/frontend/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.module.frontend; diff --git a/java/com/google/domain/registry/module/tools/BUILD b/java/com/google/domain/registry/module/tools/BUILD new file mode 100644 index 000000000..3e2ed9791 --- /dev/null +++ b/java/com/google/domain/registry/module/tools/BUILD @@ -0,0 +1,43 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "tools", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/export", + "//java/com/google/domain/registry/gcs", + "//java/com/google/domain/registry/groups", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/loadtest", + "//java/com/google/domain/registry/mapreduce", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/request:modules", + "//java/com/google/domain/registry/tools/mapreduce", + "//java/com/google/domain/registry/tools/server", + "//java/com/google/domain/registry/util", + "//third_party/java/bouncycastle", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/servlet/servlet_api", + ], +) + +# This rule is used so bazel can generate "tools_jar_deploy.jar" (which +# contains transitive dependencies) for deployment to App Engine. It MUST +# explicitly depend upon upon anything loaded at runtime, e.g. old servlets +# referenced by the module's web.xml file, that isn't statically linked above. +java_binary( + name = "tools_jar", + create_executable = 0, + runtime_deps = [ + ":tools", + "//java/com/google/domain/registry/ui/server/admin", # VerifyOteServlet + ], +) diff --git a/java/com/google/domain/registry/module/tools/ToolsComponent.java b/java/com/google/domain/registry/module/tools/ToolsComponent.java new file mode 100644 index 000000000..167dece5d --- /dev/null +++ b/java/com/google/domain/registry/module/tools/ToolsComponent.java @@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.tools; + +import com.google.domain.registry.config.ConfigModule; +import com.google.domain.registry.export.DriveModule; +import com.google.domain.registry.gcs.GcsServiceModule; +import com.google.domain.registry.groups.DirectoryModule; +import com.google.domain.registry.groups.GroupsModule; +import com.google.domain.registry.groups.GroupssettingsModule; +import com.google.domain.registry.keyring.api.KeyModule; +import com.google.domain.registry.keyring.api.VoidKeyringModule; +import com.google.domain.registry.request.Modules.AppIdentityCredentialModule; +import com.google.domain.registry.request.Modules.DatastoreServiceModule; +import com.google.domain.registry.request.Modules.GoogleCredentialModule; +import com.google.domain.registry.request.Modules.Jackson2Module; +import com.google.domain.registry.request.Modules.UrlFetchTransportModule; +import com.google.domain.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.util.SystemClock.SystemClockModule; +import com.google.domain.registry.util.SystemSleeper.SystemSleeperModule; + +import dagger.Component; + +import javax.inject.Singleton; + +/** Dagger component with instance lifetime for "tools" App Engine module. */ +@Singleton +@Component( + modules = { + AppIdentityCredentialModule.class, + ConfigModule.class, + DatastoreServiceModule.class, + DirectoryModule.class, + DriveModule.class, + GcsServiceModule.class, + GoogleCredentialModule.class, + GroupsModule.class, + GroupssettingsModule.class, + Jackson2Module.class, + KeyModule.class, + UrlFetchTransportModule.class, + UseAppIdentityCredentialForGoogleApisModule.class, + SystemClockModule.class, + SystemSleeperModule.class, + VoidKeyringModule.class, + }) +interface ToolsComponent { + ToolsRequestComponent startRequest(RequestModule requestModule); +} diff --git a/java/com/google/domain/registry/module/tools/ToolsRequestComponent.java b/java/com/google/domain/registry/module/tools/ToolsRequestComponent.java new file mode 100644 index 000000000..45d32641c --- /dev/null +++ b/java/com/google/domain/registry/module/tools/ToolsRequestComponent.java @@ -0,0 +1,71 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.tools; + +import com.google.domain.registry.export.PublishDetailReportAction; +import com.google.domain.registry.loadtest.LoadTestAction; +import com.google.domain.registry.loadtest.LoadTestModule; +import com.google.domain.registry.mapreduce.MapreduceModule; +import com.google.domain.registry.request.RequestModule; +import com.google.domain.registry.request.RequestScope; +import com.google.domain.registry.tools.mapreduce.DeleteProberDataAction; +import com.google.domain.registry.tools.mapreduce.ResaveAllEppResourcesAction; +import com.google.domain.registry.tools.server.CreateGroupsTask; +import com.google.domain.registry.tools.server.CreatePremiumListAction; +import com.google.domain.registry.tools.server.DeleteEntityAction; +import com.google.domain.registry.tools.server.GenerateZoneFilesAction; +import com.google.domain.registry.tools.server.KillAllCommitLogsAction; +import com.google.domain.registry.tools.server.KillAllEppResourcesAction; +import com.google.domain.registry.tools.server.ListDomainsAction; +import com.google.domain.registry.tools.server.ListHostsAction; +import com.google.domain.registry.tools.server.ListPremiumListsAction; +import com.google.domain.registry.tools.server.ListRegistrarsAction; +import com.google.domain.registry.tools.server.ListReservedListsAction; +import com.google.domain.registry.tools.server.ListTldsAction; +import com.google.domain.registry.tools.server.ToolsServerModule; +import com.google.domain.registry.tools.server.UpdatePremiumListAction; +import com.google.domain.registry.tools.server.javascrap.AnnihilateNonDefaultNamespacesAction; + +import dagger.Subcomponent; + +/** Dagger component with per-request lifetime for "tools" App Engine module. */ +@RequestScope +@Subcomponent( + modules = { + LoadTestModule.class, + MapreduceModule.class, + RequestModule.class, + ToolsServerModule.class, + }) +interface ToolsRequestComponent { + AnnihilateNonDefaultNamespacesAction annihilateNonDefaultNamespacesAction(); + CreateGroupsTask createGroupsTask(); + CreatePremiumListAction createPremiumListAction(); + DeleteEntityAction deleteEntityAction(); + DeleteProberDataAction deleteProberDataAction(); + GenerateZoneFilesAction generateZoneFilesAction(); + KillAllCommitLogsAction killAllCommitLogsAction(); + KillAllEppResourcesAction killAllEppResourcesAction(); + ListDomainsAction listDomainsAction(); + ListHostsAction listHostsAction(); + ListPremiumListsAction listPremiumListsAction(); + ListRegistrarsAction listRegistrarsAction(); + ListReservedListsAction listReservedListsAction(); + ListTldsAction listTldsAction(); + LoadTestAction loadTestAction(); + PublishDetailReportAction publishDetailReportAction(); + ResaveAllEppResourcesAction resaveAllEppResourcesAction(); + UpdatePremiumListAction updatePremiumListAction(); +} diff --git a/java/com/google/domain/registry/module/tools/ToolsServlet.java b/java/com/google/domain/registry/module/tools/ToolsServlet.java new file mode 100644 index 000000000..6c5401983 --- /dev/null +++ b/java/com/google/domain/registry/module/tools/ToolsServlet.java @@ -0,0 +1,58 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.module.tools; + +import static java.util.Arrays.asList; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.domain.registry.request.RequestHandler; +import com.google.domain.registry.request.RequestModule; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.security.Security; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet that should handle all requests to our "tools" App Engine module. */ +public final class ToolsServlet extends HttpServlet { + + private static final ToolsComponent component = DaggerToolsComponent.create(); + + private static final RequestHandler requestHandler = + RequestHandler.create(ToolsRequestComponent.class, FluentIterable + .from(asList(ToolsRequestComponent.class.getMethods())) + .transform(new Function() { + @Override + public Method apply(Method method) { + method.setAccessible(true); // Make App Engine's security manager happy. + return method; + }})); + + @Override + public void init() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + requestHandler.handleRequest(req, rsp, component.startRequest(new RequestModule(req, rsp))); + } +} diff --git a/java/com/google/domain/registry/monitoring/whitebox/BUILD b/java/com/google/domain/registry/monitoring/whitebox/BUILD new file mode 100644 index 000000000..6c2ae6268 --- /dev/null +++ b/java/com/google/domain/registry/monitoring/whitebox/BUILD @@ -0,0 +1,31 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "whitebox", + srcs = glob(["*.java"]), + deps = [ + "//apiserving/discoverydata/bigquery:bigqueryv2", + "//java/com/google/api/client/extensions/appengine/http", + "//java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2", + "//java/com/google/api/client/json/jackson2", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/cache", + "//java/com/google/common/collect", + "//java/com/google/common/net", + "//java/com/google/domain/registry/bigquery", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/mapreduce", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_mapreduce2:appengine_mapreduce", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/monitoring/whitebox/EppMetrics.java b/java/com/google/domain/registry/monitoring/whitebox/EppMetrics.java new file mode 100644 index 000000000..e710607e3 --- /dev/null +++ b/java/com/google/domain/registry/monitoring/whitebox/EppMetrics.java @@ -0,0 +1,72 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.monitoring.whitebox; + +import com.google.api.services.bigquery.model.TableFieldSchema; +import com.google.common.collect.ImmutableList; +import com.google.domain.registry.bigquery.BigqueryUtils.FieldType; +import com.google.domain.registry.model.eppoutput.Result.Code; + +/** The EPP Metrics collector. See {@link Metrics}. */ +public class EppMetrics extends Metrics { + + public static final ImmutableList SCHEMA_FIELDS = + ImmutableList.of( + new TableFieldSchema().setName("requestId").setType(FieldType.STRING.name()), + new TableFieldSchema().setName("startTime").setType(FieldType.TIMESTAMP.name()), + new TableFieldSchema().setName("endTime").setType(FieldType.TIMESTAMP.name()), + new TableFieldSchema().setName("commandName").setType(FieldType.STRING.name()), + new TableFieldSchema().setName("clientId").setType(FieldType.STRING.name()), + new TableFieldSchema().setName("privilegeLevel").setType(FieldType.STRING.name()), + new TableFieldSchema().setName("eppTarget").setType(FieldType.STRING.name()), + new TableFieldSchema().setName("eppStatus").setType(FieldType.INTEGER.name()), + new TableFieldSchema().setName("attempts").setType(FieldType.INTEGER.name())); + + public static final String TABLE_ID = "eppMetrics"; + + public EppMetrics() { + setTableId(TABLE_ID); + fields.put("attempts", 0); + } + + public void setCommandName(String name) { + fields.put("commandName", name); + } + + public void setClientId(String clientId) { + fields.put("clientId", clientId); + } + + public void setPrivilegeLevel(String level) { + fields.put("privilegeLevel", level); + } + + public void setEppTarget(String eppTarget) { + fields.put("eppTarget", eppTarget); + } + + public void setRequestId(String requestId) { + fields.put("requestId", requestId); + } + + public void setEppStatus(Code status) { + fields.put("eppStatus", String.valueOf(status.code)); + } + + public void incrementAttempts() { + int attempts = (int) fields.get("attempts"); + fields.put("attempts", attempts + 1); + } +} diff --git a/java/com/google/domain/registry/monitoring/whitebox/Metrics.java b/java/com/google/domain/registry/monitoring/whitebox/Metrics.java new file mode 100644 index 000000000..bde36134d --- /dev/null +++ b/java/com/google/domain/registry/monitoring/whitebox/Metrics.java @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.monitoring.whitebox; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.domain.registry.bigquery.BigqueryUtils.toBigqueryTimestamp; + +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TransientFailureException; +import com.google.common.base.Supplier; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** A collector of metric information. */ +abstract class Metrics { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + public static final String QUEUE = "bigquery-streaming-metrics"; + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + @NonFinalForTesting + private static Supplier idGenerator = + new Supplier() { + @Override + public String get() { + return UUID.randomUUID().toString(); + }}; + + protected final Map fields = new HashMap<>(); + + private final long startTimeMillis = clock.nowUtc().getMillis(); + + public void setTableId(String tableId) { + fields.put("tableId", tableId); + } + + public void export() { + try { + TaskOptions opts = withUrl("/_dr/task/metrics") + .param("insertId", idGenerator.get()) + .param("startTime", toBigqueryTimestamp(startTimeMillis, TimeUnit.MILLISECONDS)) + .param("endTime", toBigqueryTimestamp(clock.nowUtc().getMillis(), TimeUnit.MILLISECONDS)); + for (Entry entry : fields.entrySet()) { + opts.param(entry.getKey(), String.valueOf(entry.getValue())); + } + getQueue(QUEUE).add(opts); + } catch (TransientFailureException e) { + // Log and swallow. We may drop some metrics here but this should be rare. + logger.info(e, e.getMessage()); + } + } +} diff --git a/java/com/google/domain/registry/monitoring/whitebox/MetricsTaskServlet.java b/java/com/google/domain/registry/monitoring/whitebox/MetricsTaskServlet.java new file mode 100644 index 000000000..743edb541 --- /dev/null +++ b/java/com/google/domain/registry/monitoring/whitebox/MetricsTaskServlet.java @@ -0,0 +1,158 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.monitoring.whitebox; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.domain.registry.util.HttpServletUtils.getRequiredParameterValue; + +import com.google.api.client.extensions.appengine.http.UrlFetchTransport; +import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.bigquery.Bigquery; +import com.google.api.services.bigquery.BigqueryScopes; +import com.google.api.services.bigquery.model.TableDataInsertAllRequest; +import com.google.api.services.bigquery.model.TableDataInsertAllResponse; +import com.google.api.services.bigquery.model.TableDataInsertAllResponse.InsertErrors; +import com.google.api.services.bigquery.model.TableFieldSchema; +import com.google.api.services.bigquery.model.TableReference; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.domain.registry.bigquery.BigqueryFactory; +import com.google.domain.registry.bigquery.BigqueryHelper; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet for exporting metrics to BigQuery. */ +public class MetricsTaskServlet extends HttpServlet { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + private static final String DATASET_ID = "metrics"; + private static final String PROJECT_ID = RegistryEnvironment.get().config().getProjectId(); + + private static final Set SPECIAL_PARAMS = ImmutableSet.of("tableId", "insertId"); + + // Add any concrete Metric classes to this map or doPost() will throw IllegalArgumentException. + private static final Map> KNOWN_TABLE_SCHEMAS = + ImmutableMap.of(EppMetrics.TABLE_ID, EppMetrics.SCHEMA_FIELDS); + + // servlet level cross-request caches to avoid unnecessary RPCs. + @NonFinalForTesting + private static Set knownTables = Sets.newConcurrentHashSet(); + + @NonFinalForTesting + private static Set datasets = Sets.newConcurrentHashSet(); + + @NonFinalForTesting + private static BigqueryFactory bigqueryFactory = new BigqueryFactory(); + + @NonFinalForTesting + private static BigqueryHelper bigqueryHelper = new BigqueryHelper(); + + /** Returns a filtered {@link ImmutableMap} from an {@link HttpServletRequest} */ + private static ImmutableMap getFiteredMapFromRequest( + HttpServletRequest req, + Set filter) { + ImmutableMap.Builder b = new ImmutableMap.Builder<>(); + + @SuppressWarnings({"cast", "unchecked"}) // Return type is always a Set. + Set parameterKeys = (Set) req.getParameterMap().keySet(); + + for (String key : Sets.difference(parameterKeys, filter)) { + b.put(key, req.getParameter(key)); + } + + return b.build(); + } + + /** Exports metrics to BigQuery. */ + @Override + public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + try { + final String tableId = getRequiredParameterValue(req, "tableId"); + ImmutableMap fields = getFiteredMapFromRequest(req, SPECIAL_PARAMS); + + + final Bigquery bigquery = bigqueryFactory.create( + getClass().getSimpleName(), + new UrlFetchTransport(), + new JacksonFactory(), + new AppIdentityCredential(BigqueryScopes.all())); + + + // Note: it's safe for multiple threads to call this as the dataset will + // only be created once. + if (!datasets.contains(DATASET_ID)) { + bigqueryHelper.ensureDataset(bigquery, PROJECT_ID, DATASET_ID); + datasets.add(DATASET_ID); + } + + checkArgument(KNOWN_TABLE_SCHEMAS.containsKey(tableId), "Unknown table ID: %s", tableId); + + if (!knownTables.contains(tableId)) { + bigqueryHelper.ensureTable( + bigquery, + new TableReference() + .setDatasetId(DATASET_ID) + .setProjectId(PROJECT_ID) + .setTableId(tableId), + KNOWN_TABLE_SCHEMAS.get(tableId)); + knownTables.add(tableId); + } + + TableDataInsertAllResponse response = bigquery.tabledata() + .insertAll( + PROJECT_ID, + DATASET_ID, + tableId, + new TableDataInsertAllRequest() + .setRows( + ImmutableList.of(new TableDataInsertAllRequest.Rows() + .setInsertId(req.getParameter("insertId")) + .setJson(fields)))) + .execute(); + + if (response.getInsertErrors() != null && !response.getInsertErrors().isEmpty()) { + throw new RuntimeException(FluentIterable + .from(response.getInsertErrors()) + .transform(new Function() { + @Override + public String apply(InsertErrors error) { + try { + return error.toPrettyString(); + } catch (IOException e) { + return error.toString(); + } + }}) + .join(Joiner.on('\n'))); + } + } catch (Throwable e) { + logger.warningfmt("Caught Unknown Exception: %s", e); + } + } +} diff --git a/java/com/google/domain/registry/monitoring/whitebox/package-info.java b/java/com/google/domain/registry/monitoring/whitebox/package-info.java new file mode 100644 index 000000000..11883f040 --- /dev/null +++ b/java/com/google/domain/registry/monitoring/whitebox/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.monitoring.whitebox; diff --git a/java/com/google/domain/registry/rdap/BUILD b/java/com/google/domain/registry/rdap/BUILD new file mode 100644 index 000000000..5dca14942 --- /dev/null +++ b/java/com/google/domain/registry/rdap/BUILD @@ -0,0 +1,30 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "rdap", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/common/primitives", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//third_party/java/auto:auto_value", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/rdap/RdapActionBase.java b/java/com/google/domain/registry/rdap/RdapActionBase.java new file mode 100644 index 000000000..1f3eb7c91 --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapActionBase.java @@ -0,0 +1,178 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.findTldForName; +import static com.google.domain.registry.model.registry.Registries.getTlds; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.net.InternetDomainName; +import com.google.common.net.MediaType; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.request.RequestMethod; +import com.google.domain.registry.request.RequestPath; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.cmd.Query; + +import org.json.simple.JSONValue; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.regex.Pattern; + +import javax.inject.Inject; + +/** + * Base RDAP (new WHOIS) action for single-item domain, nameserver and entity requests. + * + * @see + * RFC 7482: Registration Data Access Protocol (RDAP) Query Format + */ +public abstract class RdapActionBase implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * Pattern for checking LDH names, which must officially contains only alphanumeric plus dots and + * hyphens. In this case, allow the wildcard asterisk as well. + */ + static final Pattern LDH_PATTERN = Pattern.compile("[-.a-zA-Z0-9*]+"); + + private static final MediaType RESPONSE_MEDIA_TYPE = MediaType.create("application", "rdap+json"); + + @Inject Response response; + @Inject @RequestMethod Action.Method requestMethod; + @Inject @RequestPath String requestPath; + @Inject @Config("rdapLinkBase") String rdapLinkBase; + @Inject @Config("rdapWhoisServer") String rdapWhoisServer; + + /** Returns a string like "domain name" or "nameserver", used for error strings. */ + abstract String getHumanReadableObjectTypeName(); + + /** Returns the servlet action path; used to extract the search string from the incoming path. */ + abstract String getActionPath(); + + /** Does the actual search and returns an RDAP JSON object. */ + abstract ImmutableMap getJsonObjectForResource(String searchString) + throws HttpException; + + @Override + public void run() { + try { + // Extract what we're searching for from the request path. Some RDAP commands use trailing + // data in the path itself (e.g. /rdap/domain/mydomain.com), and some use the query string + // (e.g. /rdap/domains?name=mydomain); the query parameters are extracted by the subclasses + // directly as needed. + response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*"); + URI uri = new URI(requestPath); + String pathProper = uri.getPath(); + checkArgument( + pathProper.startsWith(getActionPath()), + "%s doesn't start with %s", pathProper, getActionPath()); + ImmutableMap rdapJson = + getJsonObjectForResource(pathProper.substring(getActionPath().length())); + response.setStatus(SC_OK); + if (requestMethod != Action.Method.HEAD) { + response.setPayload( + JSONValue.toJSONString(RdapJsonFormatter.makeFinalRdapJson(rdapJson))); + } + response.setContentType(MediaType.create("application", "rdap+json")); + } catch (HttpException e) { + setError(e.getResponseCode(), e.getResponseCodeString(), e.getMessage()); + } catch (URISyntaxException | IllegalArgumentException e) { + setError(SC_BAD_REQUEST, "Bad Request", "Not a valid " + getHumanReadableObjectTypeName()); + } catch (RuntimeException e) { + setError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error", "An error was encountered"); + logger.severe(e, "Exception encountered while processing RDAP command"); + } + } + + void setError(int status, String title, String description) { + response.setStatus(status); + try { + if (requestMethod != Action.Method.HEAD) { + response.setPayload( + JSONValue.toJSONString(RdapJsonFormatter.makeError(status, title, description))); + } + response.setContentType(RESPONSE_MEDIA_TYPE); + } catch (Exception ex) { + if (requestMethod != Action.Method.HEAD) { + response.setPayload(""); + } + } + } + + void validateDomainName(String name) { + try { + Optional tld = findTldForName(InternetDomainName.from(name)); + if (!tld.isPresent() || !getTlds().contains(tld.get().toString())) { + throw new NotFoundException(name + " not found"); + } + } catch (IllegalArgumentException e) { + throw new BadRequestException( + name + " is not a valid " + getHumanReadableObjectTypeName()); + } + } + + String canonicalizeName(String name) { + name = canonicalizeDomainName(name); + if (name.endsWith(".")) { + name = name.substring(0, name.length() - 1); + } + return name; + } + + /** + * Handles prefix searches in cases where there are no pending deletes. In such cases, it is + * sufficient to check whether {@code deletionTime} is equal to {@code END_OF_TIME}, because any + * other value means it has already been deleted. This allows us to use an equality query for the + * deletion time. + * + * @param clazz the type of resource to be queried + * @param filterField the database field of interest + * @param partialStringQuery the details of the search string + * @param resultSetMaxSize the maximum number of results to return + * @return the results of the query + */ + static Query queryUndeleted( + Class clazz, + String filterField, + RdapSearchPattern partialStringQuery, + int resultSetMaxSize) { + checkArgument(partialStringQuery.getHasWildcard(), "search string doesn't have wildcard"); + return ofy().load() + .type(clazz) + .filter(filterField + " >=", partialStringQuery.getInitialString()) + .filter(filterField + " <", partialStringQuery.getNextInitialString()) + .filter("sharedFields.deletionTime", END_OF_TIME) + .limit(resultSetMaxSize); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapAutnumAction.java b/java/com/google/domain/registry/rdap/RdapAutnumAction.java new file mode 100644 index 000000000..77c718a9a --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapAutnumAction.java @@ -0,0 +1,55 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.NotImplementedException; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for RDAP autonomous system number reuqests. + * + *

This feature is not implemented because it's only necessary for address registries like + * ARIN, not domain registries. + */ +@Action(path = RdapAutnumAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapAutnumAction extends RdapActionBase { + + public static final String PATH = "/rdap/autnum"; + + @Inject RdapAutnumAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "autnum"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource(String pathSearchString) + throws HttpException { + throw new NotImplementedException("Domain Name Registry information only"); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapDomainAction.java b/java/com/google/domain/registry/rdap/RdapDomainAction.java new file mode 100644 index 000000000..5bc4afcba --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapDomainAction.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.util.Clock; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for domain requests. + */ +@Action(path = RdapDomainAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapDomainAction extends RdapActionBase { + + public static final String PATH = "/rdap/domain/"; + + @Inject Clock clock; + @Inject RdapDomainAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "domain name"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource(String pathSearchString) + throws HttpException { + pathSearchString = canonicalizeName(pathSearchString); + validateDomainName(pathSearchString); + // The query string is not used; the RDAP syntax is /rdap/domain/mydomain.com. + DomainResource domainResource = + loadByUniqueId(DomainResource.class, pathSearchString, clock.nowUtc()); + if (domainResource == null) { + throw new NotFoundException(pathSearchString + " not found"); + } + return RdapJsonFormatter.makeRdapJsonForDomain(domainResource, rdapLinkBase, rdapWhoisServer); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapDomainSearchAction.java b/java/com/google/domain/registry/rdap/RdapDomainSearchAction.java new file mode 100644 index 000000000..23aa7b31e --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapDomainSearchAction.java @@ -0,0 +1,270 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.primitives.Booleans; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; +import com.googlecode.objectify.cmd.Query; +import com.googlecode.objectify.cmd.QueryKeys; + +import org.joda.time.DateTime; + +import java.net.IDN; +import java.net.InetAddress; +import java.util.List; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for domain search requests. + * + *

All commands and responses conform to the RDAP spec as defined in RFCs 7480 through 7485. + * + * @see + * RFC 7482: Registration Data Access Protocol (RDAP) Query Format + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ +@Action(path = RdapDomainSearchAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapDomainSearchAction extends RdapActionBase { + + public static final String PATH = "/rdap/domains"; + + @Inject Clock clock; + @Inject @Parameter("name") Optional nameParam; + @Inject @Parameter("nsLdhName") Optional nsLdhNameParam; + @Inject @Parameter("nsIp") Optional nsIpParam; + @Inject RdapDomainSearchAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "domain search"; + } + + @Override + public String getActionPath() { + return PATH; + } + + /** Parses the parameters and calls the appropriate search function. */ + @Override + public ImmutableMap + getJsonObjectForResource(final String pathSearchString) throws HttpException { + DateTime now = clock.nowUtc(); + // RDAP syntax example: /rdap/domains?name=exam*.com. + // The pathSearchString is not used by search commands. + if (pathSearchString.length() > 0) { + throw new BadRequestException("Unexpected path"); + } + if (Booleans.countTrue(nameParam.isPresent(), nsLdhNameParam.isPresent(), nsIpParam.isPresent()) + != 1) { + throw new BadRequestException( + "You must specify either name=XXXX, nsLdhName=YYYY or nsIp=ZZZZ"); + } + ImmutableList> results; + if (nameParam.isPresent()) { + // syntax: /rdap/domains?name=exam*.com + // TODO(b/24329745): improve IDN handling + String asciiName; + try { + asciiName = IDN.toASCII(nameParam.get()); + } catch (Exception e) { + throw new BadRequestException("Invalid value of nsLdhName parameter"); + } + results = searchByDomainName(RdapSearchPattern.create(asciiName, true), now); + } else if (nsLdhNameParam.isPresent()) { + // syntax: /rdap/domains?nsLdhName=ns1.exam*.com + // RFC 7482 appears to say that Unicode domains must be specified using punycode when + // passed to nsLdhName, so IDN.toASCII is not called here. + if (!LDH_PATTERN.matcher(nsLdhNameParam.get()).matches()) { + throw new BadRequestException("Invalid value of nsLdhName parameter"); + } + results = searchByNameserverLdhName( + RdapSearchPattern.create(nsLdhNameParam.get(), true), now); + } else { + // syntax: /rdap/domains?nsIp=1.2.3.4 + results = searchByNameserverIp(nsIpParam.get(), now); + } + if (results.isEmpty()) { + throw new NotFoundException("No domains found"); + } + return ImmutableMap.of("domainSearchResults", results); + } + + /** Searches for domains by domain name, returning a JSON array of domain info maps. */ + private ImmutableList> + searchByDomainName(final RdapSearchPattern partialStringQuery, final DateTime now) { + // Handle queries without a wildcard -- just load by foreign key. + if (!partialStringQuery.getHasWildcard()) { + DomainResource domainResource = + loadByUniqueId(DomainResource.class, partialStringQuery.getInitialString(), now); + if (domainResource == null) { + return ImmutableList.of(); + } + return ImmutableList.of( + RdapJsonFormatter.makeRdapJsonForDomain(domainResource, rdapLinkBase, rdapWhoisServer)); + // Handle queries with a wildcard. + } else { + Query query = ofy().load() + .type(DomainResource.class) + // TODO(b/24463238): figure out how to limit the size of these queries effectively + .filter("fullyQualifiedDomainName >=", partialStringQuery.getInitialString()) + .filter("fullyQualifiedDomainName <", partialStringQuery.getNextInitialString()) + .limit(1000); + if (partialStringQuery.getSuffix() != null) { + query = query.filter("tld", partialStringQuery.getSuffix()); + } + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (DomainResource domainResource : query) { + if (domainResource.getDeletionTime().isAfter(now)) { + builder.add( + RdapJsonFormatter.makeRdapJsonForDomain( + domainResource, rdapLinkBase, rdapWhoisServer)); + } + } + return builder.build(); + } + } + + /** Searches for domains by nameserver name, returning a JSON array of domain info maps. */ + private ImmutableList> + searchByNameserverLdhName(final RdapSearchPattern partialStringQuery, final DateTime now) + throws HttpException { + ImmutableList> hostRefs; + // Handle queries without a wildcard; just load the host by foreign key in the usual way. + if (!partialStringQuery.getHasWildcard()) { + Ref hostRef = loadAndGetReference( + HostResource.class, partialStringQuery.getInitialString(), clock.nowUtc()); + if (hostRef == null) { + return ImmutableList.of(); + } + hostRefs = ImmutableList.of(hostRef); + // Handle queries with a wildcard, but no suffix. Query the host resources themselves, rather + // than the foreign key index, because then we have an index on fully qualified host name and + // deletion time, so we can check the deletion status in the query itself. There are no pending + // deletes for hosts, so we can call queryUndeleted. + } else if (partialStringQuery.getSuffix() == null) { + // TODO (b/24463238): figure out how to limit the size of these queries effectively + Query query = queryUndeleted( + HostResource.class, + "fullyQualifiedHostName", + partialStringQuery, 1000); + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (Key hostResourceKey : query.keys()) { + builder.add(Ref.create(hostResourceKey)); + } + hostRefs = builder.build(); + if (hostRefs.isEmpty()) { + throw new NotFoundException("No matching nameservers found"); + } + // Handle queries with a wildcard and a suffix. In this case, it is more efficient to do things + // differently. We use the suffix to look up the domain, then loop through the subordinate hosts + // looking for matches. + } else { + DomainResource domainResource = loadByUniqueId( + DomainResource.class, partialStringQuery.getSuffix(), clock.nowUtc()); + if (domainResource == null) { + throw new NotFoundException("No domain found for specified nameserver suffix"); + } + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (String fqhn : ImmutableSortedSet.copyOf(domainResource.getSubordinateHosts())) { + // We can't just check that the host name starts with the initial query string, because then + // the query ns.exam*.example.com would match against nameserver ns.example.com. + if (partialStringQuery.matches(fqhn)) { + Ref hostRef = loadAndGetReference(HostResource.class, fqhn, clock.nowUtc()); + if (hostRef != null) { + builder.add(hostRef); + } + } + } + hostRefs = builder.build(); + if (hostRefs.isEmpty()) { + throw new NotFoundException("No matching nameservers found"); + } + } + // Find all domains that link to any of these hosts, and return information about them. + return searchByNameserverRefs(hostRefs, now); + } + + /** Searches for domains by nameserver address, returning a JSON array of domain info maps. */ + private ImmutableList> + searchByNameserverIp(final InetAddress inetAddress, final DateTime now) { + // In theory, we could filter on the deletion time being in the future. But we can't do that in + // the query on nameserver name (because we're already using an inequality query), and it seems + // dangerous and confusing to filter on deletion time differently between the two queries. + QueryKeys query = ofy() + .load() + .type(HostResource.class) + .filter("inetAddresses", inetAddress.getHostAddress()) + .filter("sharedFields.deletionTime", END_OF_TIME) + .limit(1000) + .keys(); + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (Key key : query) { + builder.add(Ref.create(key)); + } + ImmutableList> hostRefs = builder.build(); + if (hostRefs.isEmpty()) { + return ImmutableList.of(); + } + // Find all domains that link to any of these hosts, and return information about them. + return searchByNameserverRefs(hostRefs, now); + } + + /** + * Locates all domains which are linked to a set of host refs. This method is called by + * {@link #searchByNameserverLdhName} and {@link #searchByNameserverIp} after they assemble the + * relevant host refs. + */ + private ImmutableList> + searchByNameserverRefs(final Iterable> hostRefs, final DateTime now) { + // We must break the query up into chunks, because the in operator is limited to 30 subqueries. + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (List> chunk : Iterables.partition(hostRefs, 30)) { + Query query = ofy().load() + .type(DomainResource.class) + .filter("nameservers.linked in", chunk) + .filter("sharedFields.deletionTime >", now) + .limit(1000); + for (DomainResource domainResource : query) { + builder.add( + RdapJsonFormatter.makeRdapJsonForDomain(domainResource, rdapLinkBase, rdapWhoisServer)); + } + } + return builder.build(); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapEntityAction.java b/java/com/google/domain/registry/rdap/RdapEntityAction.java new file mode 100644 index 000000000..da5f93ba3 --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapEntityAction.java @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Key; + +import java.util.regex.Pattern; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for entity (contact and registrar) requests. + */ +@Action(path = RdapEntityAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapEntityAction extends RdapActionBase { + + public static final String PATH = "/rdap/entity/"; + + private static final Pattern ROID_PATTERN = Pattern.compile("[-.a-zA-Z0-9]+"); + + @Inject Clock clock; + @Inject RdapEntityAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "entity"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource(String pathSearchString) { + // The query string is not used; the RDAP syntax is /rdap/entity/handle (the handle is the roid + // for contacts and the client identifier for registrars). Since RDAP's concept of an entity + // includes both contacts and registrars, search for one first, then the other. + boolean wasValidKey = false; + if (ROID_PATTERN.matcher(pathSearchString).matches()) { + wasValidKey = true; + Key contactKey = Key.create(ContactResource.class, pathSearchString); + ContactResource contactResource = ofy().load().key(contactKey).now(); + if ((contactResource != null) && clock.nowUtc().isBefore(contactResource.getDeletionTime())) { + return RdapJsonFormatter.makeRdapJsonForContact( + contactResource, + Optional.absent(), + rdapLinkBase, + rdapWhoisServer); + } + } + String clientId = pathSearchString.trim(); + if ((clientId.length() >= 3) && (clientId.length() <= 16)) { + wasValidKey = true; + Registrar registrar = Registrar.loadByClientId(clientId); + if ((registrar != null) && registrar.isActiveAndPubliclyVisible()) { + return RdapJsonFormatter.makeRdapJsonForRegistrar(registrar, rdapLinkBase, rdapWhoisServer); + } + } + throw !wasValidKey + ? new BadRequestException(pathSearchString + " is not a valid entity handle") + : new NotFoundException(pathSearchString + " not found"); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapEntitySearchAction.java b/java/com/google/domain/registry/rdap/RdapEntitySearchAction.java new file mode 100644 index 000000000..4a117297f --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapEntitySearchAction.java @@ -0,0 +1,166 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.primitives.Booleans; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.request.HttpException.NotImplementedException; +import com.google.domain.registry.request.HttpException.UnprocessableEntityException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.cmd.Query; + +import java.net.IDN; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for entity (contact and registrar) search requests. + * + *

All commands and responses conform to the RDAP spec as defined in RFCs 7480 through 7485. + * + * @see + * RFC 7482: Registration Data Access Protocol (RDAP) Query Format + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ +@Action(path = RdapEntitySearchAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapEntitySearchAction extends RdapActionBase { + + public static final String PATH = "/rdap/entities"; + + @Inject Clock clock; + @Inject @Parameter("fn") Optional fnParam; + @Inject @Parameter("handle") Optional handleParam; + @Inject @Config("rdapResultSetMaxSize") int rdapResultSetMaxSize; + @Inject RdapEntitySearchAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "entity search"; + } + + @Override + public String getActionPath() { + return PATH; + } + + /** Parses the parameters and calls the appropriate search function. */ + @Override + public ImmutableMap + getJsonObjectForResource(final String pathSearchString) throws HttpException { + // RDAP syntax example: /rdap/entities?fn=Bobby%20Joe*. + // The pathSearchString is not used by search commands. + if (pathSearchString.length() > 0) { + throw new BadRequestException("Unexpected path"); + } + if (Booleans.countTrue(fnParam.isPresent(), handleParam.isPresent()) != 1) { + throw new BadRequestException("You must specify either fn=XXXX or handle=YYYY"); + } + ImmutableList> results; + if (fnParam.isPresent()) { + // syntax: /rdap/entities?fn=Bobby%20Joe* + throw new NotImplementedException("Entity name search not implemented"); + } else { + // syntax: /rdap/entities?handle=12345-* + results = searchByHandle(RdapSearchPattern.create(IDN.toASCII(handleParam.get()), false)); + } + if (results.isEmpty()) { + throw new NotFoundException("No entities found"); + } + return ImmutableMap.of("entitySearchResults", results); + } + + /** Searches for entities by handle, returning a JSON array of entity info maps. */ + private ImmutableList> + searchByHandle(final RdapSearchPattern partialStringQuery) throws HttpException { + // Handle queries without a wildcard -- load by ID. + if (!partialStringQuery.getHasWildcard()) { + ContactResource contactResource = ofy().load() + .type(ContactResource.class) + .id(partialStringQuery.getInitialString()) + .now(); + Registrar registrar = Registrar.loadByClientId(partialStringQuery.getInitialString()); + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + if ((contactResource != null) && contactResource.getDeletionTime().isEqual(END_OF_TIME)) { + builder.add(RdapJsonFormatter.makeRdapJsonForContact( + contactResource, + Optional.absent(), + rdapLinkBase, + rdapWhoisServer)); + } + if ((registrar != null) && registrar.isActiveAndPubliclyVisible()) { + builder.add(RdapJsonFormatter.makeRdapJsonForRegistrar( + registrar, rdapLinkBase, rdapWhoisServer)); + } + return builder.build(); + // Handle queries with a wildcard, but no suffix. For contact resources, the deletion time will + // always be END_OF_TIME for non-deleted records; unlike domain resources, we don't need to + // worry about deletion times in the future. That allows us to use an equality query for the + // deletion time. + } else if (partialStringQuery.getSuffix() == null) { + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + Query query = ofy().load() + .type(ContactResource.class) + .filterKey(">=", Key.create(ContactResource.class, partialStringQuery.getInitialString())) + .filterKey( + "<", Key.create(ContactResource.class, partialStringQuery.getNextInitialString())) + .filter("sharedFields.deletionTime", END_OF_TIME) + .limit(rdapResultSetMaxSize); + for (ContactResource contactResource : query) { + builder.add(RdapJsonFormatter.makeRdapJsonForContact( + contactResource, + Optional.absent(), + rdapLinkBase, + rdapWhoisServer)); + } + for (Registrar registrar + : Registrar.loadByClientIdRange( + partialStringQuery.getInitialString(), + partialStringQuery.getNextInitialString(), + rdapResultSetMaxSize)) { + if (registrar.isActiveAndPubliclyVisible()) { + builder.add(RdapJsonFormatter.makeRdapJsonForRegistrar( + registrar, rdapLinkBase, rdapWhoisServer)); + } + } + // In theory, there could be more results than our max size, so limit the size. + ImmutableList> resultSet = builder.build(); + return (resultSet.size() <= rdapResultSetMaxSize) + ? resultSet + : resultSet.subList(0, rdapResultSetMaxSize); + // Don't allow suffixes in entity handle search queries. + } else { + throw new UnprocessableEntityException("Suffixes not allowed in entity handle searches"); + } + } +} diff --git a/java/com/google/domain/registry/rdap/RdapHelpAction.java b/java/com/google/domain/registry/rdap/RdapHelpAction.java new file mode 100644 index 000000000..43b53ba7b --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapHelpAction.java @@ -0,0 +1,139 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.InternalServerErrorException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.util.Clock; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for help requests. + */ +@Action(path = RdapHelpAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapHelpAction extends RdapActionBase { + + public static final String PATH = "/rdap/help"; + + private static final ImmutableMap HELP_MAP = + ImmutableMap.of( + "/", + MakeRdapJsonNoticeParameters.builder() + .title("RDAP Help") + .description(ImmutableList.of( + "RDAP Help Topics (use /help/topic for information)", + "syntax", + "tos (Terms of Service)")) + .linkValueSuffix("help/") + .linkHrefUrlString("https://www.registry.google/about/rdap/index.html") + .build(), + "/index", + MakeRdapJsonNoticeParameters.builder() + .title("RDAP Help") + .description(ImmutableList.of( + "RDAP Help Topics (use /help/topic for information)", + "syntax", + "tos (Terms of Service)")) + .linkValueSuffix("help/index") + .linkHrefUrlString("https://www.registry.google/about/rdap/index.html") + .build(), + "/syntax", + MakeRdapJsonNoticeParameters.builder() + .title("RDAP Command Syntax") + .description(ImmutableList.of( + "domain/XXXX", + "nameserver/XXXX", + "entity/XXXX", + "domains?name=XXXX", + "domains?nsLdhName=XXXX", + "domains?nsIp=XXXX", + "nameservers?name=XXXX", + "nameservers?ip=XXXX", + "entities?fn=XXXX", + "entities?handle=XXXX", + "help/XXXX")) + .linkValueSuffix("help/syntax") + .linkHrefUrlString("https://www.registry.google/about/rdap/syntax.html") + .build(), + "/tos", + MakeRdapJsonNoticeParameters.builder() + .title("RDAP Terms of Service") + .description(ImmutableList.of( + "By querying our Domain Database, you are agreeing to comply with these terms so" + + " please read them carefully.", + "Any information provided is 'as is' without any guarantee of accuracy.", + "Please do not misuse the Domain Database. It is intended solely for" + + " query-based access.", + "Don't use the Domain Database to allow, enable, or otherwise support the" + + " transmission of mass unsolicited, commercial advertising or" + + " solicitations.", + "Don't access our Domain Database through the use of high volume, automated" + + " electronic processes that send queries or data to the systems of" + + " Charleston Road Registry or any ICANN-accredited registrar.", + "You may only use the information contained in the Domain Database for lawful" + + " purposes.", + "Do not compile, repackage, disseminate, or otherwise use the information" + + " contained in the Domain Database in its entirety, or in any substantial" + + " portion, without our prior written permission.", + "We may retain certain details about queries to our Domain Database for the" + + " purposes of detecting and preventing misuse.", + "We reserve the right to restrict or deny your access to the database if we" + + " suspect that you have failed to comply with these terms.", + "We reserve the right to modify this agreement at any time.")) + .linkValueSuffix("help/tos") + .linkHrefUrlString("https://www.registry.google/about/rdap/tos.html") + .build()); + + @Inject Clock clock; + @Inject RdapHelpAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "help"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource(String pathSearchString) + throws HttpException { + if (pathSearchString.isEmpty()) { + pathSearchString = "/"; + } + if (!HELP_MAP.containsKey(pathSearchString)) { + throw new NotFoundException("no help found for " + pathSearchString); + } + try { + return ImmutableMap.of( + "notices", + (Object) ImmutableList.of(RdapJsonFormatter.makeRdapJsonNotice( + HELP_MAP.get(pathSearchString), rdapLinkBase))); + } catch (Exception e) { + throw new InternalServerErrorException("unable to read help for " + pathSearchString); + } + } +} diff --git a/java/com/google/domain/registry/rdap/RdapIpAction.java b/java/com/google/domain/registry/rdap/RdapIpAction.java new file mode 100644 index 000000000..0ce0e8d1f --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapIpAction.java @@ -0,0 +1,56 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.NotImplementedException; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for RDAP IP address requests. + * + *

This feature is not implemented because it's only necessary for address registries like + * ARIN, not domain registries. + + */ +@Action(path = RdapIpAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapIpAction extends RdapActionBase { + + public static final String PATH = "/rdap/ip"; + + @Inject RdapIpAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "ip"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource(String pathSearchString) + throws HttpException { + throw new NotImplementedException("Domain Name Registry information only"); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapJsonFormatter.java b/java/com/google/domain/registry/rdap/RdapJsonFormatter.java new file mode 100644 index 000000000..f74de9e32 --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapJsonFormatter.java @@ -0,0 +1,721 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.net.InetAddresses; +import com.google.domain.registry.model.contact.ContactPhoneNumber; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.PostalInfo; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.domain.DesignatedContact.Type; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.eppcommon.Address; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarAddress; +import com.google.domain.registry.model.registrar.RegistrarContact; +import com.google.domain.registry.util.Idn; + +import com.googlecode.objectify.Key; +import com.googlecode.objectify.Ref; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.URI; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +/** + * Helper class to create RDAP JSON objects for various registry entities and objects. + * + *

The JSON format specifies that entities should be supplied with links indicating how to fetch + * them via RDAP, which requires the URL to the RDAP server. The linkBase parameter, passed to many + * of the methods, is used as the first part of the link URL. For instance, if linkBase is + * "http://rdap.org/dir/", the link URLs will look like "http://rdap.org/dir/domain/XXXX", etc. + * + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ +public class RdapJsonFormatter { + + private static final String RDAP_CONFORMANCE_LEVEL = "rdap_level_0"; + private static final String VCARD_VERSION_NUMBER = "4.0"; + + /** Status values specified in RFC 7483 10.2.2. */ + private enum RdapStatus { + VALIDATED("validated"), + RENEW_PROHIBITED("renew prohibited"), + UPDATE_PROHIBITED("update prohibited"), + TRANSFER_PROHIBITED("transfer prohibited"), + DELETE_PROHIBITED("delete prohibited"), + PROXY("proxy"), + PRIVATE("private"), + REMOVED("removed"), + OBSCURED("obscured"), + ASSOCIATED("associated"), + ACTIVE("active"), + INACTIVE("inactive"), + LOCKED("locked"), + PENDING_CREATE("pending create"), + PENDING_RENEW("pending renew"), + PENDING_TRANSFER("pending transfer"), + PENDING_UPDATE("pending update"), + PENDING_DELETE("pending delete"); + + /** Value as it appears in RDAP messages. */ + private final String rfc7483String; + + private RdapStatus(String rfc7483String) { + this.rfc7483String = rfc7483String; + } + + @Override + public String toString() { + return rfc7483String; + } + } + + /** Map of EPP status values to the RDAP equivalents. */ + private static final ImmutableMap statusToRdapStatusMap = + Maps.immutableEnumMap( + new ImmutableMap.Builder() + .put(StatusValue.CLIENT_DELETE_PROHIBITED, RdapStatus.DELETE_PROHIBITED) + .put(StatusValue.CLIENT_HOLD, RdapStatus.INACTIVE) + .put(StatusValue.CLIENT_RENEW_PROHIBITED, RdapStatus.RENEW_PROHIBITED) + .put(StatusValue.CLIENT_TRANSFER_PROHIBITED, RdapStatus.TRANSFER_PROHIBITED) + .put(StatusValue.CLIENT_UPDATE_PROHIBITED, RdapStatus.UPDATE_PROHIBITED) + .put(StatusValue.INACTIVE, RdapStatus.INACTIVE) + .put(StatusValue.LINKED, RdapStatus.ASSOCIATED) + .put(StatusValue.OK, RdapStatus.ACTIVE) + .put(StatusValue.PENDING_CREATE, RdapStatus.PENDING_CREATE) + .put(StatusValue.PENDING_DELETE, RdapStatus.PENDING_DELETE) + .put(StatusValue.PENDING_TRANSFER, RdapStatus.PENDING_TRANSFER) + .put(StatusValue.PENDING_UPDATE, RdapStatus.PENDING_UPDATE) + .put(StatusValue.SERVER_DELETE_PROHIBITED, RdapStatus.DELETE_PROHIBITED) + .put(StatusValue.SERVER_HOLD, RdapStatus.INACTIVE) + .put(StatusValue.SERVER_RENEW_PROHIBITED, RdapStatus.RENEW_PROHIBITED) + .put(StatusValue.SERVER_TRANSFER_PROHIBITED, RdapStatus.TRANSFER_PROHIBITED) + .put(StatusValue.SERVER_UPDATE_PROHIBITED, RdapStatus.UPDATE_PROHIBITED) + .build()); + + /** Role values specified in RFC 7483 10.2.4. */ + private enum RdapEntityRole { + REGISTRANT("registrant"), + TECH("technical"), + ADMIN("administrative"), + ABUSE("abuse"), + BILLING("billing"), + REGISTRAR("registrar"), + RESELLER("reseller"), + SPONSOR("sponsor"), + PROXY("proxy"), + NOTIFICATIONS("notifications"), + NOC("noc"); + + /** Value as it appears in RDAP messages. */ + final String rfc7483String; + + private RdapEntityRole(String rfc7483String) { + this.rfc7483String = rfc7483String; + } + } + + private static final ImmutableList CONFORMANCE_LIST = + ImmutableList.of(RDAP_CONFORMANCE_LEVEL); + + private static final ImmutableList STATUS_LIST_ACTIVE = + ImmutableList.of(RdapStatus.ACTIVE.rfc7483String); + private static final ImmutableMap> PHONE_TYPE_VOICE = + ImmutableMap.of("type", ImmutableList.of("voice")); + private static final ImmutableMap> PHONE_TYPE_FAX = + ImmutableMap.of("type", ImmutableList.of("fax")); + private static final ImmutableList VCARD_ENTRY_VERSION = + ImmutableList.of("version", ImmutableMap.of(), "text", VCARD_VERSION_NUMBER); + + /** Sets the ordering for hosts; just use the fully qualified host name. */ + private static final Ordering HOST_RESOURCE_ORDERING = + Ordering.natural().onResultOf(new Function() { + @Override + public String apply(HostResource host) { + return host.getFullyQualifiedHostName(); + }}); + + /** Sets the ordering for designated contacts; order them in a fixed order by contact type. */ + private static final Ordering DESIGNATED_CONTACT_ORDERING = + Ordering.natural().onResultOf(new Function() { + @Override + public DesignatedContact.Type apply(DesignatedContact designatedContact) { + return designatedContact.getType(); + }}); + + /** + * Takes an object returned by one of the other methods, and creates a final JSON object suitable + * for conversion and transmission. This involves adding one top-level entry, since RFC 7483 + * specifies that the top-level object should include an entry indicating the conformance level. + * + * @param rdapJson an RDAP JSON object created by one of the other methods + * @return an RDAP JSON object with same info as the input, with additional top-level fields + */ + public static ImmutableMap makeFinalRdapJson( + ImmutableMap rdapJson) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.putAll(rdapJson); + builder.put("rdapConformance", CONFORMANCE_LIST); + return builder.build(); + } + + /** AutoValue class to build parameters to {@link #makeRdapJsonNotice}. */ + @AutoValue + abstract static class MakeRdapJsonNoticeParameters { + static Builder builder() { + return new AutoValue_RdapJsonFormatter_MakeRdapJsonNoticeParameters.Builder(); + } + + @Nullable abstract String title(); + abstract ImmutableList description(); + @Nullable abstract String typeString(); + @Nullable abstract String linkValueSuffix(); + @Nullable abstract String linkHrefUrlString(); + + @AutoValue.Builder + abstract static class Builder { + abstract Builder title(@Nullable String title); + abstract Builder description(Iterable description); + abstract Builder typeString(@Nullable String typeString); + abstract Builder linkValueSuffix(@Nullable String linkValueSuffix); + abstract Builder linkHrefUrlString(@Nullable String linkHrefUrlString); + + abstract MakeRdapJsonNoticeParameters build(); + } + } + + /** + * Creates a JSON object containing a notice or remark object, as defined by RFC 7483 section 4.3. + * The object should then be inserted into a "notices" or "remarks" array. The builder fields are: + * + *

title: the title of the notice; if null, the notice will have no title + * + *

description: objects which will be converted to strings to form the description of the + * notice (this is the only required field; all others are optional) + * + *

typeString: the notice or remark type as defined in section 10.2.1; if null, no type + * + *

linkValueSuffix: the path at the end of the URL used in the value field of the link, + * without any initial slash (e.g. a suffix of help/toc equates to a URL of + * http://example.net/help/toc); if null, no link is created; if it is not null, a single link is + * created; this method never creates more than one link) + * + *

htmlUrlString: the path, if any, to be used in the href value of the link; if the URL is + * absolute, it is used as is; if it is relative, starting with a slash, it is appended to the + * protocol and host of the link base; if it is relative, not starting with a slash, it is + * appended to the complete link base; if null, a self link is generated instead, using the link + * link value + * + *

linkBase: the base for the link value and href; if null, it is assumed to be the empty + * string + * + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ + public static ImmutableMap + makeRdapJsonNotice(MakeRdapJsonNoticeParameters parameters, @Nullable String linkBase) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + if (parameters.title() != null) { + builder.put("title", parameters.title()); + } + ImmutableList.Builder descriptionBuilder = new ImmutableList.Builder<>(); + for (String line : parameters.description()) { + descriptionBuilder.add(nullToEmpty(line)); + } + builder.put("description", descriptionBuilder.build()); + if (parameters.typeString() != null) { + builder.put("typeString", parameters.typeString()); + } + String linkValueString = + nullToEmpty(linkBase) + nullToEmpty(parameters.linkValueSuffix()); + if (parameters.linkHrefUrlString() == null) { + builder.put("links", ImmutableList.of(ImmutableMap.of( + "value", linkValueString, + "rel", "self", + "href", linkValueString, + "type", "application/rdap+json"))); + } else { + URI htmlBaseURI = URI.create(nullToEmpty(linkBase)); + URI htmlUri = htmlBaseURI.resolve(parameters.linkHrefUrlString()); + builder.put("links", ImmutableList.of(ImmutableMap.of( + "value", linkValueString, + "rel", "alternate", + "href", htmlUri.toString(), + "type", "text/html"))); + } + return builder.build(); + } + + /** + * Creates a JSON object for a {@link DomainResource}. + * + * @param domainResource the domain resource object from which the JSON object should be created + * @param linkBase the URL base to be used when creating links + * @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the + * port43 field; if null, port43 is not added to the object + */ + public static ImmutableMap makeRdapJsonForDomain( + DomainResource domainResource, @Nullable String linkBase, @Nullable String whoisServer) { + // Kick off the database loads of the nameservers that we will need. + Set> hostRefs = new LinkedHashSet<>(); + for (ReferenceUnion hostReference : domainResource.getNameservers()) { + hostRefs.add(hostReference.getLinked()); + } + Map, HostResource> loadedHosts = ofy().load().refs(hostRefs); + // And the registrant and other contacts. + List allContacts = new ArrayList<>(); + if (domainResource.getRegistrant() != null) { + allContacts.add(DesignatedContact.create(Type.REGISTRANT, domainResource.getRegistrant())); + } + allContacts.addAll(domainResource.getContacts()); + Set> contactRefs = new LinkedHashSet<>(); + for (DesignatedContact designatedContact : allContacts) { + contactRefs.add(designatedContact.getContactId().getLinked()); + } + Map, ContactResource> loadedContacts = ofy().load().refs(contactRefs); + // Now, assemble the results, using the loaded objects as needed. + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("objectClassName", "domain"); + builder.put("handle", domainResource.getRepoId()); + builder.put("ldhName", domainResource.getFullyQualifiedDomainName()); + // Only include the unicodeName field if there are unicode characters. + if (hasUnicodeComponents(domainResource.getFullyQualifiedDomainName())) { + builder.put("unicodeName", Idn.toUnicode(domainResource.getFullyQualifiedDomainName())); + } + builder.put("status", makeStatusValueList(domainResource.getStatusValues())); + builder.put("links", ImmutableList.of( + makeLink("domain", domainResource.getFullyQualifiedDomainName(), linkBase))); + // nameservers + ImmutableList.Builder nsBuilder = new ImmutableList.Builder<>(); + for (HostResource hostResource + : HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts.values())) { + nsBuilder.add(makeRdapJsonForHost(hostResource, linkBase, null)); + } + ImmutableList ns = nsBuilder.build(); + if (!ns.isEmpty()) { + builder.put("nameservers", ns); + } + // contacts + ImmutableList.Builder entitiesBuilder = new ImmutableList.Builder<>(); + for (DesignatedContact designatedContact + : DESIGNATED_CONTACT_ORDERING.immutableSortedCopy(allContacts)) { + ContactResource loadedContact = + loadedContacts.get(designatedContact.getContactId().getLinked().key()); + entitiesBuilder.add(makeRdapJsonForContact( + loadedContact, Optional.of(designatedContact.getType()), linkBase, null)); + } + ImmutableList entities = entitiesBuilder.build(); + if (!entities.isEmpty()) { + builder.put("entities", entities); + } + if (whoisServer != null) { + builder.put("port43", whoisServer); + } + return builder.build(); + } + + /** + * Creates a JSON object for a {@link HostResource}. + * + * @param hostResource the host resource object from which the JSON object should be created + * @param linkBase the URL base to be used when creating links + * @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the + * port43 field; if null, port43 is not added to the object + */ + public static ImmutableMap makeRdapJsonForHost( + HostResource hostResource, @Nullable String linkBase, @Nullable String whoisServer) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("objectClassName", "nameserver"); + builder.put("handle", hostResource.getRepoId()); + builder.put("ldhName", hostResource.getFullyQualifiedHostName()); + // Only include the unicodeName field if there are unicode characters. + if (hasUnicodeComponents(hostResource.getFullyQualifiedHostName())) { + builder.put("unicodeName", Idn.toUnicode(hostResource.getFullyQualifiedHostName())); + } + builder.put("status", makeStatusValueList(hostResource.getStatusValues())); + builder.put("links", ImmutableList.of( + makeLink("nameserver", hostResource.getFullyQualifiedHostName(), linkBase))); + ImmutableSet inetAddresses = hostResource.getInetAddresses(); + if (!inetAddresses.isEmpty()) { + ImmutableList.Builder v4AddressesBuilder = new ImmutableList.Builder<>(); + ImmutableList.Builder v6AddressesBuilder = new ImmutableList.Builder<>(); + for (InetAddress inetAddress : inetAddresses) { + if (inetAddress instanceof Inet4Address) { + v4AddressesBuilder.add(InetAddresses.toAddrString(inetAddress)); + } else if (inetAddress instanceof Inet6Address) { + v6AddressesBuilder.add(InetAddresses.toAddrString(inetAddress)); + } + } + ImmutableMap.Builder> ipAddressesBuilder = + new ImmutableMap.Builder<>(); + ImmutableList v4Addresses = v4AddressesBuilder.build(); + if (!v4Addresses.isEmpty()) { + ipAddressesBuilder.put("v4", v4Addresses); + } + ImmutableList v6Addresses = v6AddressesBuilder.build(); + if (!v6Addresses.isEmpty()) { + ipAddressesBuilder.put("v6", v6Addresses); + } + ImmutableMap> ipAddresses = ipAddressesBuilder.build(); + if (!ipAddresses.isEmpty()) { + builder.put("ipAddresses", ipAddressesBuilder.build()); + } + } + if (whoisServer != null) { + builder.put("port43", whoisServer); + } + return builder.build(); + } + + /** + * Creates a JSON object for a {@link ContactResource} and associated contact type. + * + * @param contactResource the contact resource object from which the JSON object should be created + * @param contactType the contact type to map to an RDAP role; if absent, no role is listed + * @param linkBase the URL base to be used when creating links + * @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the + * port43 field; if null, port43 is not added to the object + */ + public static ImmutableMap makeRdapJsonForContact( + ContactResource contactResource, + Optional contactType, + @Nullable String linkBase, + @Nullable String whoisServer) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("objectClassName", "entity"); + builder.put("handle", contactResource.getRepoId()); + builder.put("status", makeStatusValueList(contactResource.getStatusValues())); + if (contactType.isPresent()) { + builder.put("roles", ImmutableList.of(convertContactTypeToRdapRole(contactType.get()))); + } + builder.put("links", + ImmutableList.of(makeLink("entity", contactResource.getRepoId(), linkBase))); + // Create the vCard. + ImmutableList.Builder vcardBuilder = new ImmutableList.Builder<>(); + vcardBuilder.add(VCARD_ENTRY_VERSION); + PostalInfo postalInfo = contactResource.getInternationalizedPostalInfo(); + if (postalInfo == null) { + postalInfo = contactResource.getLocalizedPostalInfo(); + } + if (postalInfo != null) { + if (postalInfo.getName() != null) { + vcardBuilder.add(ImmutableList.of("fn", ImmutableMap.of(), "text", postalInfo.getName())); + } + if (postalInfo.getOrg() != null) { + vcardBuilder.add(ImmutableList.of("org", ImmutableMap.of(), "text", postalInfo.getOrg())); + } + ImmutableList addressEntry = makeVCardAddressEntry(postalInfo.getAddress()); + if (addressEntry != null) { + vcardBuilder.add(addressEntry); + } + } + ContactPhoneNumber voicePhoneNumber = contactResource.getVoiceNumber(); + if (voicePhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_VOICE, makePhoneString(voicePhoneNumber))); + } + ContactPhoneNumber faxPhoneNumber = contactResource.getFaxNumber(); + if (faxPhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_FAX, makePhoneString(faxPhoneNumber))); + } + String emailAddress = contactResource.getEmailAddress(); + if (emailAddress != null) { + vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress)); + } + builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build())); + if (whoisServer != null) { + builder.put("port43", whoisServer); + } + return builder.build(); + } + + /** + * Creates a JSON object for a {@link Registrar}. + * + * @param registrar the registrar object from which the JSON object should be created + * @param linkBase the URL base to be used when creating links + * @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the + * port43 field; if null, port43 is not added to the object + */ + public static ImmutableMap makeRdapJsonForRegistrar( + Registrar registrar, @Nullable String linkBase, @Nullable String whoisServer) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("objectClassName", "entity"); + builder.put("handle", registrar.getClientIdentifier()); + builder.put("status", STATUS_LIST_ACTIVE); + builder.put("roles", ImmutableList.of(RdapEntityRole.REGISTRAR.rfc7483String)); + builder.put("links", + ImmutableList.of(makeLink("entity", registrar.getClientIdentifier(), linkBase))); + builder.put("publicIds", + ImmutableList.of( + ImmutableMap.of( + "type", "IANA Registrar ID", + "identifier", registrar.getIanaIdentifier().toString()))); + // Create the vCard. + ImmutableList.Builder vcardBuilder = new ImmutableList.Builder<>(); + vcardBuilder.add(VCARD_ENTRY_VERSION); + String registrarName = registrar.getRegistrarName(); + if (registrarName != null) { + vcardBuilder.add(ImmutableList.of("fn", ImmutableMap.of(), "text", registrarName)); + } + RegistrarAddress address = registrar.getInternationalizedAddress(); + if (address == null) { + address = registrar.getLocalizedAddress(); + } + if (address != null) { + ImmutableList addressEntry = makeVCardAddressEntry(address); + if (addressEntry != null) { + vcardBuilder.add(addressEntry); + } + } + String voicePhoneNumber = registrar.getPhoneNumber(); + if (voicePhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_VOICE, "tel:" + voicePhoneNumber)); + } + String faxPhoneNumber = registrar.getFaxNumber(); + if (faxPhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_FAX, "tel:" + faxPhoneNumber)); + } + String emailAddress = registrar.getEmailAddress(); + if (emailAddress != null) { + vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress)); + } + builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build())); + // include the registrar contacts as subentities + ImmutableList.Builder> registrarContactsBuilder = + new ImmutableList.Builder<>(); + for (RegistrarContact registrarContact : registrar.getContacts()) { + if (isVisible(registrarContact)) { + registrarContactsBuilder.add(makeRdapJsonForRegistrarContact(registrarContact, null)); + } + } + ImmutableList> registrarContacts = registrarContactsBuilder.build(); + if (!registrarContacts.isEmpty()) { + builder.put("entities", registrarContacts); + } + if (whoisServer != null) { + builder.put("port43", whoisServer); + } + return builder.build(); + } + + /** + * Creates a JSON object for a {@link RegistrarContact}. + * + * @param registrarContact the registrar contact for which the JSON object should be created + * @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the + * port43 field; if null, port43 is not added to the object + */ + public static ImmutableMap makeRdapJsonForRegistrarContact( + RegistrarContact registrarContact, @Nullable String whoisServer) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put("objectClassName", "entity"); + String gaeUserId = registrarContact.getGaeUserId(); + if (gaeUserId != null) { + builder.put("handle", registrarContact.getGaeUserId()); + } + builder.put("status", STATUS_LIST_ACTIVE); + builder.put("roles", makeRdapRoleList(registrarContact)); + // Create the vCard. + ImmutableList.Builder vcardBuilder = new ImmutableList.Builder<>(); + vcardBuilder.add(VCARD_ENTRY_VERSION); + String name = registrarContact.getName(); + if (name != null) { + vcardBuilder.add(ImmutableList.of("fn", ImmutableMap.of(), "text", name)); + } + String voicePhoneNumber = registrarContact.getPhoneNumber(); + if (voicePhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_VOICE, "tel:" + voicePhoneNumber)); + } + String faxPhoneNumber = registrarContact.getFaxNumber(); + if (faxPhoneNumber != null) { + vcardBuilder.add(makePhoneEntry(PHONE_TYPE_FAX, "tel:" + faxPhoneNumber)); + } + String emailAddress = registrarContact.getEmailAddress(); + if (emailAddress != null) { + vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress)); + } + builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build())); + if (whoisServer != null) { + builder.put("port43", whoisServer); + } + return builder.build(); + } + + /** Converts a domain registry contact type into a role as defined by RFC 7483. */ + private static String convertContactTypeToRdapRole(DesignatedContact.Type contactType) { + switch (contactType) { + case REGISTRANT: + return RdapEntityRole.REGISTRANT.rfc7483String; + case TECH: + return RdapEntityRole.TECH.rfc7483String; + case BILLING: + return RdapEntityRole.BILLING.rfc7483String; + case ADMIN: + return RdapEntityRole.ADMIN.rfc7483String; + default: + throw new AssertionError(); + } + } + + /** + * Creates the list of RDAP roles for a registrar contact, using the visibleInWhoisAs* flags. + */ + private static ImmutableList makeRdapRoleList(RegistrarContact registrarContact) { + ImmutableList.Builder rolesBuilder = new ImmutableList.Builder<>(); + if (registrarContact.getVisibleInWhoisAsAdmin()) { + rolesBuilder.add(RdapEntityRole.ADMIN.rfc7483String); + } + if (registrarContact.getVisibleInWhoisAsTech()) { + rolesBuilder.add(RdapEntityRole.TECH.rfc7483String); + } + return rolesBuilder.build(); + } + + /** Checks whether the registrar contact should be visible (because it has visible roles). */ + private static boolean isVisible(RegistrarContact registrarContact) { + return registrarContact.getVisibleInWhoisAsAdmin() + || registrarContact.getVisibleInWhoisAsTech(); + } + + /** + * Creates a vCard address entry: array of strings specifying the components of the address. + * + * @see + * RFC 7095: jCard: The JSON Format for vCard + */ + private static ImmutableList makeVCardAddressEntry(Address address) { + if (address == null) { + return null; + } + ImmutableList.Builder builder = new ImmutableList.Builder<>(); + builder.add(""); // PO box + builder.add(""); // extended address + ImmutableList street = address.getStreet(); + if (street.isEmpty()) { + builder.add(""); + } else if (street.size() == 1) { + builder.add(street.get(0)); + } else { + builder.add(street); + } + builder.add(nullToEmpty(address.getCity())); + builder.add(nullToEmpty(address.getState())); + builder.add(nullToEmpty(address.getZip())); + builder.add(new Locale("en", address.getCountryCode()).getDisplayCountry(new Locale("en"))); + return ImmutableList.of( + "adr", + ImmutableMap.of(), + "text", + builder.build()); + } + + /** Creates a vCard phone number entry. */ + private static ImmutableList makePhoneEntry( + ImmutableMap> type, String phoneNumber) { + return ImmutableList.of("tel", type, "uri", phoneNumber); + } + + /** Creates a phone string in URI format, as per the vCard spec. */ + private static String makePhoneString(ContactPhoneNumber phoneNumber) { + String phoneString = String.format("tel:%s", phoneNumber.getPhoneNumber()); + if (phoneNumber.getExtension() != null) { + phoneString = phoneString + ";ext=" + phoneNumber.getExtension(); + } + return phoneString; + } + + /** + * Creates a string array of status values; the spec indicates that OK should be listed as + * "active". + */ + private static ImmutableList makeStatusValueList(ImmutableSet statusValues) { + return FluentIterable + .from(statusValues) + .transform(Functions.forMap(statusToRdapStatusMap, RdapStatus.OBSCURED)) + .transform(Functions.toStringFunction()) + .toSortedSet(Ordering.natural()) + .asList(); + } + + /** + * Creates a self link as directed by the spec. + * + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ + private static ImmutableMap makeLink( + String type, String name, @Nullable String linkBase) { + String url; + if (linkBase == null) { + url = type + '/' + name; + } else if (linkBase.endsWith("/")) { + url = linkBase + type + '/' + name; + } else { + url = linkBase + '/' + type + '/' + name; + } + return ImmutableMap.of( + "value", url, + "rel", "self", + "href", url, + "type", "application/rdap+json"); + } + + /** + * Creates a JSON error indication. + * + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ + public static ImmutableMap makeError( + int status, String title, String description) { + return ImmutableMap.of( + "rdapConformance", CONFORMANCE_LIST, + "lang", "en", + "errorCode", (long) status, + "title", title, + "description", ImmutableList.of(description)); + } + + private static boolean hasUnicodeComponents(String fullyQualifiedName) { + return fullyQualifiedName.startsWith("xn--") || fullyQualifiedName.contains(".xn--"); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapModule.java b/java/com/google/domain/registry/rdap/RdapModule.java new file mode 100644 index 000000000..137e7995a --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapModule.java @@ -0,0 +1,67 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import com.google.common.base.Optional; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; + +import dagger.Module; +import dagger.Provides; + +import java.net.InetAddress; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for the RDAP package. */ +@Module +public final class RdapModule { + + @Provides + @Parameter("name") + static Optional provideName(HttpServletRequest req) { + return RequestParameters.extractOptionalParameter(req, "name"); + } + + @Provides + @Parameter("nsLdhName") + static Optional provideNsLdhName(HttpServletRequest req) { + return RequestParameters.extractOptionalParameter(req, "nsLdhName"); + } + + @Provides + @Parameter("nsIp") + static Optional provideNsIp(HttpServletRequest req) { + return RequestParameters.extractOptionalInetAddressParameter(req, "nsIp"); + } + + @Provides + @Parameter("ip") + static Optional provideIp(HttpServletRequest req) { + return RequestParameters.extractOptionalInetAddressParameter(req, "ip"); + } + + @Provides + @Parameter("fn") + static Optional provideFn(HttpServletRequest req) { + return RequestParameters.extractOptionalParameter(req, "fn"); + } + + @Provides + @Parameter("handle") + static Optional provideHandle(HttpServletRequest req) { + return RequestParameters.extractOptionalParameter(req, "handle"); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapNameserverAction.java b/java/com/google/domain/registry/rdap/RdapNameserverAction.java new file mode 100644 index 000000000..4f13e1393 --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapNameserverAction.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; + +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.util.Clock; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for nameserver requests. + */ +@Action(path = RdapNameserverAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapNameserverAction extends RdapActionBase { + + public static final String PATH = "/rdap/nameserver/"; + + @Inject Clock clock; + @Inject RdapNameserverAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "nameserver"; + } + + @Override + public String getActionPath() { + return PATH; + } + + @Override + public ImmutableMap getJsonObjectForResource( + String pathSearchString) throws HttpException { + pathSearchString = canonicalizeName(pathSearchString); + // The RDAP syntax is /rdap/nameserver/ns1.mydomain.com. + validateDomainName(pathSearchString); + HostResource hostResource = + loadByUniqueId(HostResource.class, pathSearchString, clock.nowUtc()); + if (hostResource == null) { + throw new NotFoundException(pathSearchString + " not found"); + } + return RdapJsonFormatter.makeRdapJsonForHost(hostResource, rdapLinkBase, rdapWhoisServer); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapNameserverSearchAction.java b/java/com/google/domain/registry/rdap/RdapNameserverSearchAction.java new file mode 100644 index 000000000..bcc58e6ac --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapNameserverSearchAction.java @@ -0,0 +1,181 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.request.Action.Method.GET; +import static com.google.domain.registry.request.Action.Method.HEAD; +import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.primitives.Booleans; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.NotFoundException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.cmd.Query; + +import org.joda.time.DateTime; + +import java.net.IDN; +import java.net.InetAddress; + +import javax.inject.Inject; + +/** + * RDAP (new WHOIS) action for nameserver search requests. + * + *

All commands and responses conform to the RDAP spec as defined in RFCs 7480 through 7485. + * + * @see + * RFC 7482: Registration Data Access Protocol (RDAP) Query Format + * @see + * RFC 7483: JSON Responses for the Registration Data Access Protocol (RDAP) + */ +@Action(path = RdapNameserverSearchAction.PATH, method = {GET, HEAD}, isPrefix = true) +public class RdapNameserverSearchAction extends RdapActionBase { + + public static final String PATH = "/rdap/nameservers"; + + @Inject Clock clock; + @Inject @Parameter("name") Optional nameParam; + @Inject @Parameter("ip") Optional ipParam; + @Inject @Config("rdapResultSetMaxSize") int rdapResultSetMaxSize; + @Inject RdapNameserverSearchAction() {} + + @Override + public String getHumanReadableObjectTypeName() { + return "nameserver search"; + } + + @Override + public String getActionPath() { + return PATH; + } + + /** Parses the parameters and calls the appropriate search function. */ + @Override + public ImmutableMap + getJsonObjectForResource(final String pathSearchString) throws HttpException { + DateTime now = clock.nowUtc(); + // RDAP syntax example: /rdap/nameservers?name=ns*.example.com. + // The pathSearchString is not used by search commands. + if (pathSearchString.length() > 0) { + throw new BadRequestException("Unexpected path"); + } + if (Booleans.countTrue(nameParam.isPresent(), ipParam.isPresent()) != 1) { + throw new BadRequestException("You must specify either name=XXXX or ip=YYYY"); + } + ImmutableList> results; + if (nameParam.isPresent()) { + // syntax: /rdap/nameservers?name=exam*.com + // TODO(b/24329745): improve IDN handling + if (!LDH_PATTERN.matcher(nameParam.get()).matches()) { + throw new BadRequestException( + "Name parameter must contain only letters, dots" + + " and hyphens, and an optional single wildcard"); + } + results = searchByName(RdapSearchPattern.create(IDN.toASCII(nameParam.get()), true), now); + } else { + // syntax: /rdap/nameservers?ip=1.2.3.4 + results = searchByIp(ipParam.get()); + } + if (results.isEmpty()) { + throw new NotFoundException("No nameservers found"); + } + return ImmutableMap.of("nameserverSearchResults", results); + } + + /** Searches for nameservers by name, returning a JSON array of nameserver info maps. */ + private ImmutableList> + searchByName(final RdapSearchPattern partialStringQuery, final DateTime now) + throws HttpException { + // Handle queries without a wildcard -- just load by foreign key. + if (!partialStringQuery.getHasWildcard()) { + HostResource hostResource = + loadByUniqueId(HostResource.class, partialStringQuery.getInitialString(), now); + if (hostResource == null) { + throw new NotFoundException("No nameservers found"); + } + return ImmutableList.of( + RdapJsonFormatter.makeRdapJsonForHost(hostResource, rdapLinkBase, rdapWhoisServer)); + // Handle queries with a wildcard, but no suffix. There are no pending deletes for hosts, so we + // can call queryUndeleted. + } else if (partialStringQuery.getSuffix() == null) { + Query query = queryUndeleted( + HostResource.class, + "fullyQualifiedHostName", + partialStringQuery, rdapResultSetMaxSize); + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (HostResource hostResource : query) { + builder.add( + RdapJsonFormatter.makeRdapJsonForHost(hostResource, rdapLinkBase, rdapWhoisServer)); + } + return builder.build(); + // Handle queries with a wildcard and a suffix. In this case, it is more efficient to do things + // differently. We use the suffix to look up the domain, then loop through the subordinate hosts + // looking for matches. + } else { + DomainResource domainResource = + loadByUniqueId(DomainResource.class, partialStringQuery.getSuffix(), clock.nowUtc()); + if (domainResource == null) { + throw new NotFoundException("No domain found for specified nameserver suffix"); + } + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (String fqhn : ImmutableSortedSet.copyOf(domainResource.getSubordinateHosts())) { + // We can't just check that the host name starts with the initial query string, because then + // the query ns.exam*.example.com would match against nameserver ns.example.com. + if (partialStringQuery.matches(fqhn)) { + HostResource hostResource = loadByUniqueId(HostResource.class, fqhn, clock.nowUtc()); + if (hostResource != null) { + builder.add( + RdapJsonFormatter.makeRdapJsonForHost(hostResource, rdapLinkBase, rdapWhoisServer)); + } + } + } + return builder.build(); + } + } + + /** Searches for nameservers by IP address, returning a JSON array of nameserver info maps. */ + private ImmutableList> + searchByIp(final InetAddress inetAddress) throws HttpException { + // In theory, we could filter on deletion time being in the future. But we can't do that in the + // name query above (because we already have an inequality filter), and filtering on deletion + // time differently in the two cases seems like a recipe for future confusion. + Query query = ofy() + .load() + .type(HostResource.class) + .filter("inetAddresses", inetAddress.getHostAddress()) + .filter("sharedFields.deletionTime", END_OF_TIME) + .limit(rdapResultSetMaxSize); + ImmutableList.Builder> builder = new ImmutableList.Builder<>(); + for (HostResource hostResource : query) { + builder.add( + RdapJsonFormatter.makeRdapJsonForHost(hostResource, rdapLinkBase, rdapWhoisServer)); + } + return builder.build(); + } +} diff --git a/java/com/google/domain/registry/rdap/RdapSearchPattern.java b/java/com/google/domain/registry/rdap/RdapSearchPattern.java new file mode 100644 index 000000000..6cd00213d --- /dev/null +++ b/java/com/google/domain/registry/rdap/RdapSearchPattern.java @@ -0,0 +1,155 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rdap; + +import com.google.domain.registry.request.HttpException.UnprocessableEntityException; + +import javax.annotation.Nullable; + +/** + * Object containing the results of parsing an RDAP partial match search pattern. Search patterns + * are of the form XXXX, XXXX* or XXXX*.YYYY. There can be at most one wildcard character, and it + * must be at the end, except for a possible suffix string on the end to restrict the search to a + * particular TLD (for domains) or domain (for nameservers). + * + * @see + * RFC 7482: Registration Data Access Protocol (RDAP) Query Format + */ +public final class RdapSearchPattern { + + /** String before the wildcard character. */ + private final String initialString; + + /** If false, initialString contains the entire search string. */ + private final boolean hasWildcard; + + /** + * Terminating suffix after the wildcard, or null if none was specified; for domains, it should be + * a TLD, for nameservers, a domain. RFC 7482 requires only that it be a sequence of domain + * labels, but this definition is stricter for efficiency purposes. + */ + @Nullable + private final String suffix; + + private RdapSearchPattern( + final String initialString, final boolean hasWildcard, @Nullable final String suffix) { + this.initialString = initialString; + this.hasWildcard = hasWildcard; + this.suffix = suffix; + } + + public String getInitialString() { + return initialString; + } + + public boolean getHasWildcard() { + return hasWildcard; + } + + @Nullable + public String getSuffix() { + return suffix; + } + + /** + * Attempts to return the next string in sort order after {@link #getInitialString() + * initialString}. This can be used to convert a wildcard query into a range query, by looking for + * strings greater than or equal to {@link #getInitialString() initialString} and less than {@link + * #getNextInitialString() nextInitialString}. + */ + public String getNextInitialString() { + return initialString.substring(0, initialString.length() - 1) + + (char) (initialString.charAt(initialString.length() - 1) + 1); + } + + /** + * Creates a SearchPattern using the provided search pattern string. + * + * @param pattern the string containing the partial match pattern + * @param allowSuffix true if a suffix is allowed after the wildcard + * + * @throws UnprocessableEntityException if {@code pattern} does not meet the requirements of RFC + * 7482 + */ + public static RdapSearchPattern create( + String pattern, boolean allowSuffix) throws UnprocessableEntityException { + String initialString; + boolean hasWildcard; + String suffix; + // If there's no wildcard character, just lump everything into the initial string. + int wildcardPos = pattern.indexOf('*'); + if (wildcardPos < 0) { + initialString = pattern; + hasWildcard = false; + suffix = null; + } else if (pattern.indexOf('*', wildcardPos + 1) >= 0) { + throw new UnprocessableEntityException("Only one wildcard allowed"); + } else { + hasWildcard = true; + // Check for a suffix (e.g. exam*.com or ns*.example.com). + if (pattern.length() > wildcardPos + 1) { + if (!allowSuffix) { + throw new UnprocessableEntityException("Suffix not allowed after wildcard"); + } + if ((pattern.length() == wildcardPos + 2) || (pattern.charAt(wildcardPos + 1) != '.')) { + throw new UnprocessableEntityException( + "Suffix after wildcard must be one or more domain" + + " name labels, e.g. exam*.tld, ns*.example.tld"); + } + suffix = pattern.substring(wildcardPos + 2); + } else { + suffix = null; + } + initialString = pattern.substring(0, wildcardPos); + } + if (initialString.length() < 2) { + throw new UnprocessableEntityException("At least two characters must be specified"); + } + if (initialString.startsWith("xn--") + && (initialString.length() < 7)) { + throw new UnprocessableEntityException( + "At least seven characters must be specified for punycode domain searches"); + } + return new RdapSearchPattern(initialString, hasWildcard, suffix); + } + + /** + * Checks a string to make sure that it matches the search pattern. + * + * @param string the string to be matched + * @return true if the pattern matches the string + */ + public boolean matches(@Nullable String string) { + if (string == null) { + return false; + } + int lengthAccountedFor = 0; + if (initialString != null) { + if (!string.startsWith(initialString)) { + return false; + } + lengthAccountedFor += initialString.length(); + } + if (suffix != null) { + if (!string.endsWith(suffix)) { + return false; + } + lengthAccountedFor += suffix.length(); + } + return hasWildcard + ? (lengthAccountedFor <= string.length()) + : (lengthAccountedFor == string.length()); + } +} diff --git a/java/com/google/domain/registry/rde/BUILD b/java/com/google/domain/registry/rde/BUILD new file mode 100644 index 000000000..e259cd8fd --- /dev/null +++ b/java/com/google/domain/registry/rde/BUILD @@ -0,0 +1,41 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "rde", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/gcs", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/mapreduce", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/tldconfig/idn", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/xjc", + "//java/com/google/domain/registry/xml", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_gcs_client", + "//third_party/java/appengine_mapreduce2:appengine_mapreduce", + "//third_party/java/auto:auto_factory", + "//third_party/java/auto:auto_value", + "//third_party/java/bouncycastle", + "//third_party/java/bouncycastle_bcpg", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsch", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/rde/BrdaCopyTask.java b/java/com/google/domain/registry/rde/BrdaCopyTask.java new file mode 100644 index 000000000..711ca4246 --- /dev/null +++ b/java/com/google/domain/registry/rde/BrdaCopyTask.java @@ -0,0 +1,130 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.model.rde.RdeMode.THIN; +import static com.google.domain.registry.request.Action.Method.POST; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.common.io.ByteStreams; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.gcs.GcsUtils; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.rde.RdeNamingUtils; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.FormattingLogger; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.joda.time.DateTime; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.inject.Inject; + +/** + * Task that re-encrypts a BRDA escrow deposit and puts it into the upload bucket. + * + *

This task is run by the mapreduce for each BRDA staging file it generates. The staging file is + * encrypted with our internal {@link Ghostryde} encryption. We then re-encrypt it as a RyDE file, + * which is what the third-party escrow provider understands. + * + *

Then we put the RyDE file (along with our digital signature) into the configured BRDA bucket. + * This bucket is special because a separate script will rsync it to the third party escrow provider + * SFTP server. This is why the internal staging files are stored in the separate RDE bucket. + * + * @see "http://newgtlds.icann.org/en/applicants/agb/agreement-approved-09jan14-en.htm" + */ +@Action(path = BrdaCopyTask.PATH, method = POST, automaticallyPrintOk = true) +public final class BrdaCopyTask implements Runnable { + + static final String PATH = "/_dr/task/brdaCopy"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject GcsUtils gcsUtils; + @Inject Ghostryde ghostryde; + @Inject RydePgpCompressionOutputStreamFactory pgpCompressionFactory; + @Inject RydePgpFileOutputStreamFactory pgpFileFactory; + @Inject RydePgpEncryptionOutputStreamFactory pgpEncryptionFactory; + @Inject RydePgpSigningOutputStreamFactory pgpSigningFactory; + @Inject RydeTarOutputStreamFactory tarFactory; + @Inject @Config("brdaBucket") String brdaBucket; + @Inject @Config("rdeBucket") String stagingBucket; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject @Parameter(RdeModule.PARAM_WATERMARK) DateTime watermark; + @Inject @Key("brdaReceiverKey") PGPPublicKey receiverKey; + @Inject @Key("brdaSigningKey") PGPKeyPair signingKey; + @Inject @Key("rdeStagingDecryptionKey") PGPPrivateKey stagingDecryptionKey; + @Inject BrdaCopyTask() {} + + @Override + public void run() { + try { + copyAsRyde(); + } catch (IOException | PGPException e) { + throw new RuntimeException(e); + } + } + + private void copyAsRyde() throws IOException, PGPException { + String prefix = RdeNamingUtils.makeRydeFilename(tld, watermark, THIN, 1, 0); + GcsFilename xmlFilename = new GcsFilename(stagingBucket, prefix + ".xml.ghostryde"); + GcsFilename xmlLengthFilename = new GcsFilename(stagingBucket, prefix + ".xml.length"); + GcsFilename rydeFile = new GcsFilename(brdaBucket, prefix + ".ryde"); + GcsFilename sigFile = new GcsFilename(brdaBucket, prefix + ".sig"); + + long xmlLength = readXmlLength(xmlLengthFilename); + + logger.infofmt("Writing %s", rydeFile); + byte[] signature; + try (InputStream gcsInput = gcsUtils.openInputStream(xmlFilename); + Ghostryde.Decryptor decryptor = ghostryde.openDecryptor(gcsInput, stagingDecryptionKey); + Ghostryde.Decompressor decompressor = ghostryde.openDecompressor(decryptor); + Ghostryde.Input ghostInput = ghostryde.openInput(decompressor); + BufferedInputStream xmlInput = new BufferedInputStream(ghostInput); + OutputStream gcsOutput = gcsUtils.openOutputStream(rydeFile); + RydePgpSigningOutputStream signLayer = pgpSigningFactory.create(gcsOutput, signingKey)) { + try (OutputStream encryptLayer = pgpEncryptionFactory.create(signLayer, receiverKey); + OutputStream compressLayer = pgpCompressionFactory.create(encryptLayer); + OutputStream fileLayer = pgpFileFactory.create(compressLayer, watermark, prefix + ".tar"); + OutputStream tarLayer = + tarFactory.create(fileLayer, xmlLength, watermark, prefix + ".xml")) { + ByteStreams.copy(xmlInput, tarLayer); + } + signature = signLayer.getSignature(); + } + + logger.infofmt("Writing %s", sigFile); + try (OutputStream gcsOutput = gcsUtils.openOutputStream(sigFile)) { + gcsOutput.write(signature); + } + } + + /** Reads the contents of a file from Cloud Storage that contains nothing but an integer. */ + private long readXmlLength(GcsFilename xmlLengthFilename) throws IOException { + try (InputStream input = gcsUtils.openInputStream(xmlLengthFilename)) { + return Long.parseLong(new String(ByteStreams.toByteArray(input), UTF_8).trim()); + } + } +} diff --git a/java/com/google/domain/registry/rde/ContactResourceToXjcConverter.java b/java/com/google/domain/registry/rde/ContactResourceToXjcConverter.java new file mode 100644 index 000000000..726cafed3 --- /dev/null +++ b/java/com/google/domain/registry/rde/ContactResourceToXjcConverter.java @@ -0,0 +1,193 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.util.XmlEnumUtils.enumToXml; + +import com.google.domain.registry.model.contact.ContactAddress; +import com.google.domain.registry.model.contact.ContactPhoneNumber; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.contact.Disclose; +import com.google.domain.registry.model.contact.Disclose.PostalInfoChoice; +import com.google.domain.registry.model.contact.PostalInfo; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.xjc.contact.XjcContactAddrType; +import com.google.domain.registry.xjc.contact.XjcContactDiscloseType; +import com.google.domain.registry.xjc.contact.XjcContactE164Type; +import com.google.domain.registry.xjc.contact.XjcContactIntLocType; +import com.google.domain.registry.xjc.contact.XjcContactPostalInfoEnumType; +import com.google.domain.registry.xjc.contact.XjcContactPostalInfoType; +import com.google.domain.registry.xjc.contact.XjcContactStatusType; +import com.google.domain.registry.xjc.contact.XjcContactStatusValueType; +import com.google.domain.registry.xjc.eppcom.XjcEppcomTrStatusType; +import com.google.domain.registry.xjc.rdecontact.XjcRdeContact; +import com.google.domain.registry.xjc.rdecontact.XjcRdeContactElement; +import com.google.domain.registry.xjc.rdecontact.XjcRdeContactTransferDataType; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** Utility class that turns {@link ContactResource} as {@link XjcRdeContactElement}. */ +final class ContactResourceToXjcConverter { + + /** Converts {@link ContactResource} to {@link XjcRdeContactElement}. */ + static XjcRdeContactElement convert(ContactResource host) { + return new XjcRdeContactElement(convertContact(host)); + } + + /** Converts {@link ContactResource} to {@link XjcRdeContact}. */ + static XjcRdeContact convertContact(ContactResource model) { + XjcRdeContact bean = new XjcRdeContact(); + bean.setRoid(model.getRepoId()); + for (StatusValue status : model.getStatusValues()) { + bean.getStatuses().add(convertStatusValue(status)); + } + PostalInfo localizedPostalInfo = model.getLocalizedPostalInfo(); + if (localizedPostalInfo != null) { + bean.getPostalInfos().add(convertPostalInfo(localizedPostalInfo)); + } + PostalInfo internationalizedPostalInfo = model.getInternationalizedPostalInfo(); + if (internationalizedPostalInfo != null) { + bean.getPostalInfos().add(convertPostalInfo(internationalizedPostalInfo)); + } + bean.setId(model.getContactId()); + bean.setClID(model.getCurrentSponsorClientId()); + bean.setCrRr(RdeAdapter.convertRr(model.getCreationClientId(), null)); + bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateClientId(), null)); + bean.setCrDate(model.getCreationTime()); + bean.setUpDate(model.getLastEppUpdateTime()); + bean.setTrDate(model.getLastTransferTime()); + bean.setVoice(convertPhoneNumber(model.getVoiceNumber())); + bean.setFax(convertPhoneNumber(model.getFaxNumber())); + bean.setEmail(model.getEmailAddress()); + bean.setDisclose(convertDisclose(model.getDisclose())); + + // o An OPTIONAL element that contains the following child + // elements related to the last transfer request of the contact + // object: + // + // * A element that contains the state of the most recent + // transfer request. + // + // * A element that contains the identifier of the registrar + // that requested the domain name object transfer. An OPTIONAL + // client attribute is used to specify the client that performed + // the operation. + // + // * An element that contains the identifier of the registrar + // that SHOULD act upon a PENDING transfer request. For all other + // status types, the value identifies the registrar that took the + // indicated action. An OPTIONAL client attribute is used to + // specify the client that performed the operation. + // + // * A element that contains the date and time that the + // transfer was requested. + // + // * An element that contains the date and time of a + // required or completed response. For a PENDING request, the + // value identifies the date and time by which a response is + // required before an automated response action will be taken by + // the registry. For all other status types, the value identifies + // the date and time when the request was completed. + if (model.getTransferData() != TransferData.EMPTY) { + bean.setTrnData(convertTransferData(model.getTransferData())); + } + + return bean; + } + + /** Converts {@link TransferData} to {@link XjcRdeContactTransferDataType}. */ + private static XjcRdeContactTransferDataType convertTransferData(TransferData model) { + XjcRdeContactTransferDataType bean = new XjcRdeContactTransferDataType(); + bean.setTrStatus(XjcEppcomTrStatusType.fromValue(model.getTransferStatus().getXmlName())); + bean.setReRr(RdeUtil.makeXjcRdeRrType(model.getGainingClientId())); + bean.setAcRr(RdeUtil.makeXjcRdeRrType(model.getLosingClientId())); + bean.setReDate(model.getTransferRequestTime()); + bean.setAcDate(model.getPendingTransferExpirationTime()); + return bean; + } + + /** Converts {@link ContactAddress} to {@link XjcContactAddrType}. */ + private static XjcContactAddrType convertAddress(ContactAddress model) { + XjcContactAddrType bean = new XjcContactAddrType(); + bean.getStreets().addAll(model.getStreet()); + bean.setCity(model.getCity()); + bean.setSp(model.getState()); + bean.setPc(model.getZip()); + bean.setCc(model.getCountryCode()); + return bean; + } + + /** Converts {@link Disclose} to {@link XjcContactDiscloseType}. */ + @Nullable + @CheckForNull + static XjcContactDiscloseType convertDisclose(@Nullable Disclose model) { + if (model == null) { + return null; + } + XjcContactDiscloseType bean = new XjcContactDiscloseType(); + bean.setFlag(model.getFlag()); + for (PostalInfoChoice loc : model.getNames()) { + bean.getNames().add(convertPostalInfoChoice(loc)); + } + for (PostalInfoChoice loc : model.getOrgs()) { + bean.getOrgs().add(convertPostalInfoChoice(loc)); + } + for (PostalInfoChoice loc : model.getAddrs()) { + bean.getAddrs().add(convertPostalInfoChoice(loc)); + } + return bean; + } + + /** Converts {@link ContactPhoneNumber} to {@link XjcContactE164Type}. */ + @Nullable + @CheckForNull + private static XjcContactE164Type convertPhoneNumber(@Nullable ContactPhoneNumber model) { + if (model == null) { + return null; + } + XjcContactE164Type bean = new XjcContactE164Type(); + bean.setValue(model.getPhoneNumber()); + bean.setX(model.getExtension()); + return bean; + } + + /** Converts {@link PostalInfoChoice} to {@link XjcContactIntLocType}. */ + private static XjcContactIntLocType convertPostalInfoChoice(PostalInfoChoice model) { + XjcContactIntLocType bean = new XjcContactIntLocType(); + bean.setType(XjcContactPostalInfoEnumType.fromValue(enumToXml(model.getType()))); + return bean; + } + + /** Converts {@link PostalInfo} to {@link XjcContactPostalInfoType}. */ + private static XjcContactPostalInfoType convertPostalInfo(PostalInfo model) { + XjcContactPostalInfoType bean = new XjcContactPostalInfoType(); + bean.setName(model.getName()); + bean.setOrg(model.getOrg()); + bean.setAddr(convertAddress(model.getAddress())); + bean.setType(XjcContactPostalInfoEnumType.fromValue(enumToXml(model.getType()))); + return bean; + } + + /** Converts {@link StatusValue} to {@link XjcContactStatusType}. */ + private static XjcContactStatusType convertStatusValue(StatusValue model) { + XjcContactStatusType bean = new XjcContactStatusType(); + bean.setS(XjcContactStatusValueType.fromValue(model.getXmlName())); + return bean; + } + + private ContactResourceToXjcConverter() {} +} diff --git a/java/com/google/domain/registry/rde/DepositFragment.java b/java/com/google/domain/registry/rde/DepositFragment.java new file mode 100644 index 000000000..80c9ceb92 --- /dev/null +++ b/java/com/google/domain/registry/rde/DepositFragment.java @@ -0,0 +1,36 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import com.google.auto.value.AutoValue; + +import java.io.Serializable; + +/** Container of datastore resource marshalled by {@link RdeMarshaller}. */ +@AutoValue +public abstract class DepositFragment implements Serializable { + + private static final long serialVersionUID = -5241410684255467454L; + + public abstract RdeResourceType type(); + public abstract String xml(); + public abstract String error(); + + public static DepositFragment create(RdeResourceType type, String xml, String error) { + return new AutoValue_DepositFragment(type, xml, error); + } + + DepositFragment() {} +} diff --git a/java/com/google/domain/registry/rde/DomainResourceToXjcConverter.java b/java/com/google/domain/registry/rde/DomainResourceToXjcConverter.java new file mode 100644 index 000000000..92ba8dd01 --- /dev/null +++ b/java/com/google/domain/registry/rde/DomainResourceToXjcConverter.java @@ -0,0 +1,291 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.domain.ReferenceUnion; +import com.google.domain.registry.model.domain.rgp.GracePeriodStatus; +import com.google.domain.registry.model.domain.secdns.DelegationSignerData; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.transfer.TransferData; +import com.google.domain.registry.model.transfer.TransferStatus; +import com.google.domain.registry.util.Idn; +import com.google.domain.registry.xjc.domain.XjcDomainContactAttrType; +import com.google.domain.registry.xjc.domain.XjcDomainContactType; +import com.google.domain.registry.xjc.domain.XjcDomainNsType; +import com.google.domain.registry.xjc.domain.XjcDomainStatusType; +import com.google.domain.registry.xjc.domain.XjcDomainStatusValueType; +import com.google.domain.registry.xjc.eppcom.XjcEppcomTrStatusType; +import com.google.domain.registry.xjc.rdedomain.XjcRdeDomain; +import com.google.domain.registry.xjc.rdedomain.XjcRdeDomainElement; +import com.google.domain.registry.xjc.rdedomain.XjcRdeDomainTransferDataType; +import com.google.domain.registry.xjc.rgp.XjcRgpStatusType; +import com.google.domain.registry.xjc.rgp.XjcRgpStatusValueType; +import com.google.domain.registry.xjc.secdns.XjcSecdnsDsDataType; +import com.google.domain.registry.xjc.secdns.XjcSecdnsDsOrKeyType; + +import org.joda.time.DateTime; + +/** Utility class that turns {@link DomainResource} as {@link XjcRdeDomainElement}. */ +final class DomainResourceToXjcConverter { + + /** Converts {@link DomainResource} to {@link XjcRdeDomainElement}. */ + static XjcRdeDomainElement convert(DomainResource domain, RdeMode mode) { + return new XjcRdeDomainElement(convertDomain(domain, mode)); + } + + /** Converts {@link DomainResource} to {@link XjcRdeDomain}. */ + static XjcRdeDomain convertDomain(DomainResource model, RdeMode mode) { + XjcRdeDomain bean = new XjcRdeDomain(); + + // o A element that contains the fully qualified name of the + // domain name object. + bean.setName(model.getFullyQualifiedDomainName()); + + // o A element that contains the repository object identifier + // assigned to the domain name object when it was created. + bean.setRoid(model.getRepoId()); + + // o An OPTIONAL element that contains the name of the domain + // name in Unicode character set. It MUST be provided if available. + bean.setUName(Idn.toUnicode(model.getFullyQualifiedDomainName())); + + // o An OPTIONAL element that references the IDN Table + // used for the IDN. This corresponds to the "id" attribute of the + // element. This element MUST be present if the domain + // name is an IDN. + // ✭ We have to add some code to determine the IDN table id at creation + // time, then either save it somewhere, or else re-derive it here. + bean.setIdnTableId(model.getIdnTableName()); + + // o An OPTIONAL element is used to indicate that the + // domain name is an IDN variant. This element contains the domain + // name used to generate the IDN variant. + // ☠ Not relevant for now. We may do some bundling of variants in the + // future, but right now we're going to be doing blocking - which + // means we won't canonicalize the IDN name at the present time. + // bean.setOriginalName(...); + + // o A element that contains the identifier of the sponsoring + // registrar. + bean.setClID(model.getCurrentSponsorClientId()); + + // o A element that contains the identifier of the registrar + // that created the domain name object. An OPTIONAL client attribute + // is used to specify the client that performed the operation. + bean.setCrRr(RdeAdapter.convertRr(model.getCreationClientId(), null)); + + // o An OPTIONAL element that contains the date and time of + // the domain name object creation. This element MUST be present if + // the domain name has been allocated. + bean.setCrDate(model.getCreationTime()); + + // o An OPTIONAL element that contains the date and time + // identifying the end (expiration) of the domain name object's + // registration period. This element MUST be present if the domain + // name has been allocated. + bean.setExDate(model.getRegistrationExpirationTime()); + + // o An OPTIONAL element that contains the date and time of + // the most recent domain-name-object modification. This element + // MUST NOT be present if the domain name object has never been + // modified. + bean.setUpDate(model.getLastEppUpdateTime()); + + // o An OPTIONAL element that contains the identifier of the + // registrar that last updated the domain name object. This element + // MUST NOT be present if the domain has never been modified. An + // OPTIONAL client attribute is used to specify the client that + // performed the operation. + bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateClientId(), null)); + + // o An OPTIONAL element that contains the date and time of + // the most recent domain object successful transfer. This element + // MUST NOT be present if the domain name object has never been + // transfered. + bean.setTrDate(model.getLastTransferTime()); + + // o One or more elements that contain the current status + // descriptors associated with the domain name. + for (StatusValue status : model.getStatusValues()) { + bean.getStatuses().add(convertStatusValue(status)); + } + + // o An OPTIONAL element that contains the fully qualified names + // of the delegated host objects or host attributes (name servers) + // associated with the domain name object. See Section 1.1 of + // [RFC5731] for a description of the elements used to specify host + // objects or host attributes. + // ✭ We don't support host attributes, only host objects. The RFC says + // you have to support one or the other, but not both. The gist of + // it is that with host attributes, you inline the nameserver data + // on each domain; with host objects, you normalize the nameserver + // data to a separate EPP object. + ImmutableSet linkedNameservers = model.loadNameservers(); + if (!linkedNameservers.isEmpty()) { + XjcDomainNsType nameservers = new XjcDomainNsType(); + for (HostResource host : linkedNameservers) { + nameservers.getHostObjs().add(host.getFullyQualifiedHostName()); + } + bean.setNs(nameservers); + } + + switch (mode) { + case FULL: + // o Zero or more OPTIONAL element to represent + // "pendingDelete" sub-statuses, including "redemptionPeriod", + // "pendingRestore", and "pendingDelete", that a domain name can be + // in as a result of grace period processing as specified in + // [RFC3915]. + for (GracePeriodStatus status : model.getGracePeriodStatuses()) { + bean.getRgpStatuses().add(convertGracePeriodStatus(status)); + } + + // o An OPTIONAL element that contain the identifier for + // the human or organizational social information object associated + // as the holder of the domain name object. + ReferenceUnion registrant = model.getRegistrant(); + if (registrant != null) { + bean.setRegistrant(registrant.getLinked().get().getContactId()); + } + + // o Zero or more OPTIONAL elements that contain identifiers + // for the human or organizational social information objects + // associated with the domain name object. + for (DesignatedContact contact : model.getContacts()) { + bean.getContacts().add(convertDesignatedContact(contact)); + } + + // o An OPTIONAL element that contains the public key + // information associated with Domain Name System security (DNSSEC) + // extensions for the domain name as specified in [RFC5910]. + // ☠ We don't set keyData because we use dsData. The RFCs offer us a + // choice between the two, similar to hostAttr vs. hostObj above. + // ☠ We're not going to support maxSigLife since it seems to be + // completely useless. + if (!model.getDsData().isEmpty()) { + XjcSecdnsDsOrKeyType secdns = new XjcSecdnsDsOrKeyType(); + for (DelegationSignerData ds : model.getDsData()) { + secdns.getDsDatas().add(convertDelegationSignerData(ds)); + } + bean.setSecDNS(secdns); + } + + // o An OPTIONAL element that contains the following child + // elements related to the last transfer request of the domain name + // object. This element MUST NOT be present if a transfer request + // for the domain name has never been created. + // + // * A element that contains the state of the most recent + // transfer request. + // + // * A element that contains the identifier of the registrar + // that requested the domain name object transfer. An OPTIONAL + // client attribute is used to specify the client that performed + // the operation. + // + // * A element that contains the date and time that the + // transfer was requested. + // + // * An element that contains the identifier of the registrar + // that SHOULD act upon a PENDING transfer request. For all other + // status types, the value identifies the registrar that took the + // indicated action. An OPTIONAL client attribute is used to + // specify the client that performed the operation. + // + // * An element that contains the date and time of a + // required or completed response. For a PENDING request, the + // value identifies the date and time by which a response is + // required before an automated response action will be taken by + // the registry. For all other status types, the value identifies + // the date and time when the request was completed. + // + // * An OPTIONAL element that contains the end of the + // domain name object's validity period (expiry date) if the + // transfer caused or causes a change in the validity period. + if (model.getTransferData() != TransferData.EMPTY) { + bean.setTrnData( + convertTransferData(model.getTransferData(), model.getRegistrationExpirationTime())); + } + + break; + case THIN: + break; + } + + return bean; + } + + /** Converts {@link TransferData} to {@link XjcRdeDomainTransferDataType}. */ + private static XjcRdeDomainTransferDataType convertTransferData( + TransferData model, DateTime domainExpires) { + XjcRdeDomainTransferDataType bean = new XjcRdeDomainTransferDataType(); + bean.setTrStatus( + XjcEppcomTrStatusType.fromValue(model.getTransferStatus().getXmlName())); + bean.setReRr(RdeUtil.makeXjcRdeRrType(model.getGainingClientId())); + bean.setAcRr(RdeUtil.makeXjcRdeRrType(model.getLosingClientId())); + bean.setReDate(model.getTransferRequestTime()); + bean.setAcDate(model.getPendingTransferExpirationTime()); + if (model.getTransferStatus() == TransferStatus.PENDING) { + int years = Optional.fromNullable(model.getExtendedRegistrationYears()).or(0); + bean.setExDate(domainExpires.plusYears(years)); + } else { + bean.setExDate(domainExpires); + } + return bean; + } + + /** Converts {@link GracePeriodStatus} to {@link XjcRgpStatusType}. */ + private static XjcRgpStatusType convertGracePeriodStatus(GracePeriodStatus model) { + XjcRgpStatusType bean = new XjcRgpStatusType(); + bean.setS(XjcRgpStatusValueType.fromValue(model.getXmlName())); + return bean; + } + + /** Converts {@link StatusValue} to {@link XjcDomainStatusType}. */ + private static XjcDomainStatusType convertStatusValue(StatusValue model) { + XjcDomainStatusType bean = new XjcDomainStatusType(); + bean.setS(XjcDomainStatusValueType.fromValue(model.getXmlName())); + return bean; + } + + /** Converts {@link DelegationSignerData} to {@link XjcSecdnsDsDataType}. */ + private static XjcSecdnsDsDataType convertDelegationSignerData(DelegationSignerData model) { + XjcSecdnsDsDataType bean = new XjcSecdnsDsDataType(); + bean.setKeyTag(model.getKeyTag()); + bean.setAlg((short) model.getAlgorithm()); + bean.setDigestType((short) model.getDigestType()); + bean.setDigest(model.getDigest()); + bean.setKeyData(null); + return bean; + } + + /** Converts {@link DesignatedContact} to {@link XjcDomainContactType}. */ + private static XjcDomainContactType convertDesignatedContact(DesignatedContact model) { + XjcDomainContactType bean = new XjcDomainContactType(); + ContactResource contact = model.getContactId().getLinked().get(); + bean.setType(XjcDomainContactAttrType.fromValue(model.getType().toString().toLowerCase())); + bean.setValue(contact.getContactId()); + return bean; + } + + private DomainResourceToXjcConverter() {} +} diff --git a/java/com/google/domain/registry/rde/EscrowTaskRunner.java b/java/com/google/domain/registry/rde/EscrowTaskRunner.java new file mode 100644 index 000000000..530d24a73 --- /dev/null +++ b/java/com/google/domain/registry/rde/EscrowTaskRunner.java @@ -0,0 +1,121 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; +import com.google.domain.registry.model.server.Lock; +import com.google.domain.registry.request.HttpException.NoContentException; +import com.google.domain.registry.request.HttpException.ServiceUnavailableException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; + +import com.googlecode.objectify.VoidWork; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.concurrent.Callable; + +import javax.inject.Inject; + +/** + * Runner applying guaranteed reliability to an {@link EscrowTask}. + * + *

This class implements the Locking Rolling Cursor pattern, which solves the problem of + * how to reliably execute App Engine tasks which can't be made idempotent. + * + *

{@link Lock} is used to ensure only one task executes at a time for a given + * {@code LockedCursorTask} subclass + TLD combination. This is necessary because App Engine tasks + * might double-execute. Normally tasks solve this by being idempotent, but that's not possible for + * RDE, which writes to a GCS filename with a deterministic name. So the datastore is used to to + * guarantee isolation. If we can't acquire the lock, it means the task is already running, so + * {@link NoContentException} is thrown to cancel the task. + * + *

The specific date for which the deposit is generated depends on the current position of the + * {@link RegistryCursor}. If the cursor is set to tomorrow, we do nothing and return 204 No + * Content. If the cursor is set to today, then we create a deposit for today and advance the + * cursor. If the cursor is set to yesterday or earlier, then we create a deposit for that date, + * advance the cursor, but we do not make any attempt to catch the cursor up to the current + * time. Therefore you must set the cron interval to something less than the desired + * interval, so the cursor can catch up. For example, if the task is supposed to run daily, you + * should configure cron to execute it every twelve hours, or possibly less. + */ +class EscrowTaskRunner { + + /** Callback interface for objects managed by {@link EscrowTaskRunner}. */ + public interface EscrowTask { + + /** + * Performs task logic while the lock is held. + * + * @param watermark the logical time for a point-in-time view of datastore + */ + abstract void runWithLock(DateTime watermark) throws Exception; + } + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject Clock clock; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject EscrowTaskRunner() {} + + /** + * Acquires lock, checks cursor, invokes {@code task}, and advances cursor. + * + * @param task the task to run + * @param registry the {@link Registry} that we are performing escrow for + * @param timeout time when we assume failure, kill the task (and instance) and release the lock + * @param cursorType the cursor to advance on success, indicating the next required runtime + * @param interval how far to advance the cursor (e.g. a day for RDE, a week for BRDA) + */ + void lockRunAndRollForward( + final EscrowTask task, + final Registry registry, + Duration timeout, + final CursorType cursorType, + final Duration interval) { + Callable lockRunner = new Callable() { + @Override + public Void call() throws Exception { + logger.info("tld=" + registry.getTld()); + DateTime startOfToday = clock.nowUtc().withTimeAtStartOfDay(); + final DateTime nextRequiredRun = RegistryCursor.load(registry, cursorType).or(startOfToday); + if (nextRequiredRun.isAfter(startOfToday)) { + throw new NoContentException("Already completed"); + } + logger.info("cursor=" + nextRequiredRun); + task.runWithLock(nextRequiredRun); + ofy().transact(new VoidWork() { + @Override + public void vrun() { + RegistryCursor.save(registry, cursorType, nextRequiredRun.plus(interval)); + }}); + return null; + }}; + String lockName = String.format("%s %s", task.getClass().getSimpleName(), registry.getTld()); + if (!Lock.executeWithLocks(lockRunner, null, tld, timeout, lockName)) { + // This will happen if either: a) the task is double-executed; b) the task takes a long time + // to run and the retry task got executed while the first one is still running. In both + // situations the safest thing to do is to just return 503 so the task gets retried later. + throw new ServiceUnavailableException("Lock in use: " + lockName); + } + } +} diff --git a/java/com/google/domain/registry/rde/Ghostryde.java b/java/com/google/domain/registry/rde/Ghostryde.java new file mode 100644 index 000000000..a9719d6f3 --- /dev/null +++ b/java/com/google/domain/registry/rde/Ghostryde.java @@ -0,0 +1,522 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.bouncycastle.bcpg.CompressionAlgorithmTags.ZLIB; +import static org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags.AES_128; +import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; +import static org.bouncycastle.openpgp.PGPLiteralData.BINARY; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.io.ByteStreams; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.ImprovedInputStream; +import com.google.domain.registry.util.ImprovedOutputStream; + +import org.bouncycastle.openpgp.PGPCompressedData; +import org.bouncycastle.openpgp.PGPCompressedDataGenerator; +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; +import org.bouncycastle.openpgp.PGPEncryptedDataList; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.joda.time.DateTime; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.NoSuchAlgorithmException; +import java.security.ProviderException; +import java.security.SecureRandom; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; +import javax.annotation.WillCloseWhenClosed; +import javax.annotation.WillNotClose; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.NotThreadSafe; +import javax.inject.Inject; + +/** + * Utility class for reading and writing data in the ghostryde container format. + * + *

Whenever we stage sensitive data to cloud storage (like XML RDE deposit data), we + * GHOST RYDE IT first to keep it safe from the prying + * eyes of anyone with access to the Google Cloud + * Console. + * + *

This class has an unusual API that's designed to take advantage of Java 7 try-with-resource + * statements to the greatest extent possible, while also maintaining security contracts at + * compile-time. + * + *

Here's how you write a file: + * + *

   {@code
+ *   File in = new File("lol.txt");
+ *   File out = new File("lol.txt.ghostryde");
+ *   Ghostryde ghost = new Ghostryde(1024);
+ *   try (OutputStream output = new FileOutputStream(out);
+ *       Ghostryde.Encryptor encryptor = ghost.openEncryptor(output, publicKey);
+ *       Ghostryde.Compressor kompressor = ghost.openCompressor(encryptor);
+ *       OutputStream go = ghost.openOutput(kompressor, in.getName(), DateTime.now());
+ *       InputStream input = new FileInputStream(in)) {
+ *     ByteStreams.copy(input, go);
+ *   }}
+ * + *

Here's how you read a file: + * + *

   {@code
+ *   File in = new File("lol.txt.ghostryde");
+ *   File out = new File("lol.txt");
+ *   Ghostryde ghost = new Ghostryde(1024);
+ *   try (InputStream fileInput = new FileInputStream(in);
+ *       Ghostryde.Decryptor decryptor = ghost.openDecryptor(fileInput, privateKey);
+ *       Ghostryde.Decompressor decompressor = ghost.openDecompressor(decryptor);
+ *       Ghostryde.Input input = ghost.openInput(decompressor);
+ *       OutputStream fileOutput = new FileOutputStream(out)) {
+ *     System.out.println("name = " + input.getName());
+ *     System.out.println("modified = " + input.getModified());
+ *     ByteStreams.copy(input, fileOutput);
+ *   }}
+ * + *

Simple API

+ * + *

If you're writing test code or are certain your data can fit in memory, you might find these + * static methods more convenient: + * + *

   {@code
+ *   byte[] data = "hello kitty".getBytes(UTF_8);
+ *   byte[] blob = Ghostryde.encode(data, publicKey, "lol.txt", DateTime.now());
+ *   Ghostryde.Result result = Ghostryde.decode(blob, privateKey);
+ *   }
+ * + *

GhostRYDE Format

+ * + *

A {@code .ghostryde} file is the exact same thing as a {@code .gpg} file, except the OpenPGP + * message layers will always be present and in a specific order. You can analyse the layers on the + * command-line using the {@code gpg --list-packets blah.ghostryde} command. + * + *

Ghostryde is different from RyDE in the sense that ghostryde is only used for internal + * storage; whereas RyDE is meant to protect data being stored by a third-party. + */ +@Immutable +public final class Ghostryde { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * Compression algorithm to use when creating ghostryde files. + * + *

We're going to use ZLIB since it's better than ZIP. + * + * @see org.bouncycastle.bcpg.CompressionAlgorithmTags + */ + static final int COMPRESSION_ALGORITHM = ZLIB; + + /** + * Symmetric encryption cipher to use when creating ghostryde files. + * + *

We're going to use AES-128 just like {@link RydePgpEncryptionOutputStream}, although we + * aren't forced to use this algorithm by the ICANN RFCs since this is an internal format. + * + * @see org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags + */ + static final int CIPHER = AES_128; + + /** + * Unlike {@link RydePgpEncryptionOutputStream}, we're going to enable the integrity packet + * because it makes GnuPG happy. It's also probably necessary to prevent tampering since we + * don't sign ghostryde files. + */ + static final boolean USE_INTEGRITY_PACKET = true; + + /** + * The source of random bits. You are strongly discouraged from changing this value because at + * Google it's configured to use {@code /dev/{,u}random} in production and somehow + * magically go fast and not drain entropy in the testing environment. + * + * @see SecureRandom#getInstance(String) + */ + static final String RANDOM_SOURCE = "NativePRNG"; + + /** + * Creates a ghostryde file from an in-memory byte array. + * + * @throws PGPException + * @throws IOException + */ + public static byte[] encode(byte[] data, PGPPublicKey key, String name, DateTime modified) + throws IOException, PGPException { + checkNotNull(data, "data"); + checkArgument(key.isEncryptionKey(), "not an encryption key"); + Ghostryde ghost = new Ghostryde(1024 * 64); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + try (Encryptor encryptor = ghost.openEncryptor(output, key); + Compressor kompressor = ghost.openCompressor(encryptor); + OutputStream go = ghost.openOutput(kompressor, name, modified)) { + go.write(data); + } + return output.toByteArray(); + } + + /** + * Deciphers a ghostryde file from an in-memory byte array. + * + * @throws PGPException + * @throws IOException + */ + public static DecodeResult decode(byte[] data, PGPPrivateKey key) + throws IOException, PGPException { + checkNotNull(data, "data"); + Ghostryde ghost = new Ghostryde(1024 * 64); + ByteArrayInputStream dataStream = new ByteArrayInputStream(data); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + String name; + DateTime modified; + try (Decryptor decryptor = ghost.openDecryptor(dataStream, key); + Decompressor decompressor = ghost.openDecompressor(decryptor); + Input input = ghost.openInput(decompressor)) { + name = input.getName(); + modified = input.getModified(); + ByteStreams.copy(input, output); + } + return new DecodeResult(output.toByteArray(), name, modified); + } + + /** Result class for the {@link Ghostryde#decode(byte[], PGPPrivateKey)} method. */ + @Immutable + public static final class DecodeResult { + private final byte[] data; + private final String name; + private final DateTime modified; + + DecodeResult(byte[] data, String name, DateTime modified) { + this.data = checkNotNull(data, "data"); + this.name = checkNotNull(name, "name"); + this.modified = checkNotNull(modified, "modified"); + } + + /** Returns the decoded ghostryde content bytes. */ + public byte[] getData() { + return data; + } + + /** Returns the name of the original file, taken from the literal data packet. */ + public String getName() { + return name; + } + + /** Returns the time this file was created or modified, take from the literal data packet. */ + public DateTime getModified() { + return modified; + } + } + + /** + * PGP literal file {@link InputStream}. + * + * @see Ghostryde#openInput(Decompressor) + */ + @NotThreadSafe + public static final class Input extends ImprovedInputStream { + private final String name; + private final DateTime modified; + + Input(@WillCloseWhenClosed InputStream input, String name, DateTime modified) { + super(input); + this.name = checkNotNull(name, "name"); + this.modified = checkNotNull(modified, "modified"); + } + + /** Returns the name of the original file, taken from the literal data packet. */ + public String getName() { + return name; + } + + /** Returns the time this file was created or modified, take from the literal data packet. */ + public DateTime getModified() { + return modified; + } + } + + /** + * PGP literal file {@link OutputStream}. + * + *

This class isn't needed for ordering safety, but is included regardless for consistency and + * to improve the appearance of log messages. + * + * @see Ghostryde#openOutput(Compressor, String, DateTime) + */ + @NotThreadSafe + public static final class Output extends ImprovedOutputStream { + Output(@WillCloseWhenClosed OutputStream os) { + super(os); + } + } + + /** + * Encryption {@link OutputStream}. + * + *

This type exists to guarantee {@code open*()} methods are called in the correct order. + * + * @see Ghostryde#openEncryptor(OutputStream, PGPPublicKey) + */ + @NotThreadSafe + public static final class Encryptor extends ImprovedOutputStream { + Encryptor(@WillCloseWhenClosed OutputStream os) { + super(os); + } + } + + /** + * Decryption {@link InputStream}. + * + *

This type exists to guarantee {@code open*()} methods are called in the correct order. + * + * @see Ghostryde#openDecryptor(InputStream, PGPPrivateKey) + */ + @NotThreadSafe + public static final class Decryptor extends ImprovedInputStream { + private final PGPPublicKeyEncryptedData crypt; + + Decryptor(@WillCloseWhenClosed InputStream input, PGPPublicKeyEncryptedData crypt) { + super(input); + this.crypt = checkNotNull(crypt, "crypt"); + } + + /** + * Verifies that the ciphertext wasn't corrupted or tampered with. + * + *

Note: If {@link Ghostryde#USE_INTEGRITY_PACKET} is {@code true}, any ghostryde file + * without an integrity packet will be considered invalid and an exception will be thrown. + * + * @throws IllegalStateException to propagate {@link PGPException} + * @throws IOException + */ + @Override + protected void onClose() throws IOException { + if (USE_INTEGRITY_PACKET) { + try { + if (!crypt.verify()) { + throw new PGPException("ghostryde integrity check failed: possible tampering D:"); + } + } catch (PGPException e) { + throw new IllegalStateException(e); + } + } + } + } + + /** + * Compression {@link OutputStream}. + * + *

This type exists to guarantee {@code open*()} methods are called in the correct order. + * + * @see Ghostryde#openCompressor(Encryptor) + */ + @NotThreadSafe + public static final class Compressor extends ImprovedOutputStream { + Compressor(@WillCloseWhenClosed OutputStream os) { + super(os); + } + } + + /** + * Decompression {@link InputStream}. + * + *

This type exists to guarantee {@code open*()} methods are called in the correct order. + * + * @see Ghostryde#openDecompressor(Decryptor) + */ + @NotThreadSafe + public static final class Decompressor extends ImprovedInputStream { + Decompressor(@WillCloseWhenClosed InputStream input) { + super(input); + } + } + + private final int bufferSize; + + /** Constructs a new {@link Ghostryde} object. */ + @Inject + public Ghostryde( + @Config("rdeGhostrydeBufferSize") int bufferSize) { + checkArgument(bufferSize > 0, "bufferSize"); + this.bufferSize = bufferSize; + } + + /** + * Opens a new {@link Encryptor} (Writing Step 1/3) + * + *

This is the first step in creating a ghostryde file. After this method, you'll want to + * call {@link #openCompressor(Encryptor)}. + * + * @param os is the upstream {@link OutputStream} to which the result is written. + * @param publicKey is the public encryption key of the recipient. + * @throws IOException + * @throws PGPException + */ + @CheckReturnValue + public Encryptor openEncryptor(@WillNotClose OutputStream os, PGPPublicKey publicKey) + throws IOException, PGPException { + PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator( + new JcePGPDataEncryptorBuilder(CIPHER) + .setWithIntegrityPacket(USE_INTEGRITY_PACKET) + .setSecureRandom(getRandom()) + .setProvider(PROVIDER_NAME)); + encryptor.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey)); + return new Encryptor(encryptor.open(os, new byte[bufferSize])); + } + + /** Does stuff. */ + private SecureRandom getRandom() { + SecureRandom random; + try { + random = SecureRandom.getInstance(RANDOM_SOURCE); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException(e); + } + return random; + } + + /** + * Opens a new {@link Compressor} (Writing Step 2/3) + * + *

This is the second step in creating a ghostryde file. After this method, you'll want to + * call {@link #openOutput(Compressor, String, DateTime)}. + * + * @param os is the value returned by {@link #openEncryptor(OutputStream, PGPPublicKey)}. + * @throws IOException + * @throws PGPException + */ + @CheckReturnValue + public Compressor openCompressor(@WillNotClose Encryptor os) throws IOException, PGPException { + PGPCompressedDataGenerator kompressor = new PGPCompressedDataGenerator(COMPRESSION_ALGORITHM); + return new Compressor(kompressor.open(os, new byte[bufferSize])); + } + + /** + * Opens an {@link OutputStream} to which the actual data should be written (Writing Step 3/3) + * + *

This is the third and final step in creating a ghostryde file. You'll want to write data + * to the returned object. + * + * @param os is the value returned by {@link #openCompressor(Encryptor)}. + * @param name is a filename for your data which gets written in the literal tag. + * @param modified is a timestamp for your data which gets written to the literal tags. + * @throws IOException + */ + @CheckReturnValue + public Output openOutput(@WillNotClose Compressor os, String name, DateTime modified) + throws IOException { + return new Output(new PGPLiteralDataGenerator().open( + os, BINARY, name, modified.toDate(), new byte[bufferSize])); + } + + /** + * Opens a new {@link Decryptor} (Reading Step 1/3) + * + *

This is the first step in opening a ghostryde file. After this method, you'll want to + * call {@link #openDecompressor(Decryptor)}. + * + * @param input is an {@link InputStream} of the ghostryde file data. + * @param privateKey is the private encryption key of the recipient (which is us!) + * @throws IOException + * @throws PGPException + */ + @CheckReturnValue + public Decryptor openDecryptor(@WillNotClose InputStream input, PGPPrivateKey privateKey) + throws IOException, PGPException { + checkNotNull(privateKey, "privateKey"); + PGPObjectFactory fact = new BcPGPObjectFactory(checkNotNull(input, "input")); + PGPEncryptedDataList crypts = pgpCast(fact.nextObject(), PGPEncryptedDataList.class); + checkState(crypts.size() > 0); + if (crypts.size() > 1) { + logger.warningfmt("crypts.size() is %d (should be 1)", crypts.size()); + } + PGPPublicKeyEncryptedData crypt = pgpCast(crypts.get(0), PGPPublicKeyEncryptedData.class); + if (crypt.getKeyID() != privateKey.getKeyID()) { + throw new PGPException(String.format( + "Message was encrypted for keyid %x but ours is %x", + crypt.getKeyID(), privateKey.getKeyID())); + } + return new Decryptor( + crypt.getDataStream(new BcPublicKeyDataDecryptorFactory(privateKey)), + crypt); + } + + /** + * Opens a new {@link Decompressor} (Reading Step 2/3) + * + *

This is the second step in reading a ghostryde file. After this method, you'll want to + * call {@link #openInput(Decompressor)}. + * + * @param input is the value returned by {@link #openDecryptor}. + * @throws IOException + * @throws PGPException + */ + @CheckReturnValue + public Decompressor openDecompressor(@WillNotClose Decryptor input) + throws IOException, PGPException { + PGPObjectFactory fact = new BcPGPObjectFactory(checkNotNull(input, "input")); + PGPCompressedData compressed = pgpCast(fact.nextObject(), PGPCompressedData.class); + return new Decompressor(compressed.getDataStream()); + } + + /** + * Opens a new {@link Input} for reading the original contents (Reading Step 3/3) + * + *

This is the final step in reading a ghostryde file. After calling this method, you should + * call the read methods on the returned {@link InputStream}. + * + * @param input is the value returned by {@link #openDecompressor}. + * @throws IOException + * @throws PGPException + */ + @CheckReturnValue + public Input openInput(@WillNotClose Decompressor input) throws IOException, PGPException { + PGPObjectFactory fact = new BcPGPObjectFactory(checkNotNull(input, "input")); + PGPLiteralData literal = pgpCast(fact.nextObject(), PGPLiteralData.class); + DateTime modified = new DateTime(literal.getModificationTime(), UTC); + return new Input(literal.getDataStream(), literal.getFileName(), modified); + } + + /** Safely extracts an object from an OpenPGP message. */ + private static T pgpCast(@Nullable Object object, Class expect) throws PGPException { + if (object == null) { + throw new PGPException(String.format( + "Expected %s but out of objects", expect.getSimpleName())); + } + if (!expect.isAssignableFrom(object.getClass())) { + throw new PGPException(String.format( + "Expected %s but got %s", expect.getSimpleName(), object.getClass().getSimpleName())); + } + return expect.cast(object); + } +} diff --git a/java/com/google/domain/registry/rde/HostResourceToXjcConverter.java b/java/com/google/domain/registry/rde/HostResourceToXjcConverter.java new file mode 100644 index 000000000..8075075e1 --- /dev/null +++ b/java/com/google/domain/registry/rde/HostResourceToXjcConverter.java @@ -0,0 +1,75 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import com.google.common.net.InetAddresses; +import com.google.domain.registry.model.eppcommon.StatusValue; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.xjc.host.XjcHostAddrType; +import com.google.domain.registry.xjc.host.XjcHostIpType; +import com.google.domain.registry.xjc.host.XjcHostStatusType; +import com.google.domain.registry.xjc.host.XjcHostStatusValueType; +import com.google.domain.registry.xjc.rdehost.XjcRdeHost; +import com.google.domain.registry.xjc.rdehost.XjcRdeHostElement; + +import java.net.Inet6Address; +import java.net.InetAddress; + +/** Utility class that turns {@link HostResource} as {@link XjcRdeHostElement}. */ +final class HostResourceToXjcConverter { + + /** Converts {@link HostResource} to {@link XjcRdeHostElement}. */ + static XjcRdeHostElement convert(HostResource host) { + return new XjcRdeHostElement(convertHost(host)); + } + + /** Converts {@link HostResource} to {@link XjcRdeHost}. */ + static XjcRdeHost convertHost(HostResource model) { + XjcRdeHost bean = new XjcRdeHost(); + bean.setName(model.getFullyQualifiedHostName()); + bean.setRoid(model.getRepoId()); + bean.setClID(model.getCurrentSponsorClientId()); + bean.setTrDate(model.getLastTransferTime()); + bean.setCrDate(model.getCreationTime()); + bean.setUpDate(model.getLastEppUpdateTime()); + bean.setCrRr(RdeAdapter.convertRr(model.getCreationClientId(), null)); + bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateClientId(), null)); + bean.setCrRr(RdeAdapter.convertRr(model.getCreationClientId(), null)); + for (StatusValue status : model.getStatusValues()) { + bean.getStatuses().add(convertStatusValue(status)); + } + for (InetAddress addr : model.getInetAddresses()) { + bean.getAddrs().add(convertInetAddress(addr)); + } + return bean; + } + + /** Converts {@link StatusValue} to {@link XjcHostStatusType}. */ + private static XjcHostStatusType convertStatusValue(StatusValue model) { + XjcHostStatusType bean = new XjcHostStatusType(); + bean.setS(XjcHostStatusValueType.fromValue(model.getXmlName())); + return bean; + } + + /** Converts {@link InetAddress} to {@link XjcHostAddrType}. */ + private static XjcHostAddrType convertInetAddress(InetAddress model) { + XjcHostAddrType bean = new XjcHostAddrType(); + bean.setIp(model instanceof Inet6Address ? XjcHostIpType.V_6 : XjcHostIpType.V_4); + bean.setValue(InetAddresses.toAddrString(model)); + return bean; + } + + private HostResourceToXjcConverter() {} +} diff --git a/java/com/google/domain/registry/rde/JSchModule.java b/java/com/google/domain/registry/rde/JSchModule.java new file mode 100644 index 000000000..e1d204a91 --- /dev/null +++ b/java/com/google/domain/registry/rde/JSchModule.java @@ -0,0 +1,61 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.appengine.api.ThreadManager; +import com.google.domain.registry.keyring.api.KeyModule.Key; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module for {@link JSch} which provides SSH/SFTP connectivity. */ +@Module +public final class JSchModule { + + @Provides + static JSch provideJSch( + @Key("rdeSshClientPrivateKey") String privateKey, + @Key("rdeSshClientPublicKey") String publicKey) { + applyAppEngineKludge(); + JSch jsch = new JSch(); + try { + jsch.addIdentity( + "rde@charlestonroadregistry.com", + privateKey.getBytes(UTF_8), + publicKey.getBytes(UTF_8), + null); + } catch (JSchException e) { + throw new RuntimeException(e); + } + // TODO(b/13028224): Implement known hosts checking. + JSch.setConfig("StrictHostKeyChecking", "no"); + return jsch; + } + + /** + * Overrides the threadFactory used in JSch and disable {@link Thread#setName(String)} in order to + * ensure GAE compatibility. By default it uses the default executor, which fails under GAE. This + * is currently a Google-specific patch that needs to be sent upstream. + */ + private static void applyAppEngineKludge() { + JSch.threadFactory = ThreadManager.currentRequestThreadFactory(); + JSch.useThreadNames = false; + } +} diff --git a/java/com/google/domain/registry/rde/JSchSftpChannel.java b/java/com/google/domain/registry/rde/JSchSftpChannel.java new file mode 100644 index 000000000..09e7d7617 --- /dev/null +++ b/java/com/google/domain/registry/rde/JSchSftpChannel.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.jcraft.jsch.ChannelSftp; + +import java.io.Closeable; +import java.io.IOException; + +/** + * {@link ChannelSftp} wrapper that implements {@link Closeable}. + * + *

This class acts as syntactic sugar for JSch so we can open and close SFTP connections in a + * way that's friendlier to Java 7 try-resource statements. + * + * @see JSchSshSession#openSftpChannel() + */ +final class JSchSftpChannel implements Closeable { + private final ChannelSftp channel; + + JSchSftpChannel(ChannelSftp channel) { + this.channel = checkNotNull(channel, "channel"); + } + + /** Returns {@link ChannelSftp} instance wrapped by this object. */ + public ChannelSftp get() { + return channel; + } + + @Override + public void close() throws IOException { + channel.disconnect(); + } +} diff --git a/java/com/google/domain/registry/rde/JSchSshSession.java b/java/com/google/domain/registry/rde/JSchSshSession.java new file mode 100644 index 000000000..ba0230f9c --- /dev/null +++ b/java/com/google/domain/registry/rde/JSchSshSession.java @@ -0,0 +1,128 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import com.google.common.base.Splitter; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.FormattingLogger; + +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.SftpException; + +import org.joda.time.Duration; + +import java.io.Closeable; +import java.io.IOException; +import java.net.URI; + +import javax.inject.Inject; + +/** + * SFTP connection {@link Session} delegate that implements {@link Closeable}. + * + *

This class acts as syntactic sugar for JSch so we can open and close SFTP connections in a + * way that's friendlier to Java 7 try-resource statements. Delegate methods are provided on an + * as-needed basis. + * + * @see JSchSftpChannel + * @see RdeUploadTask + * @see com.jcraft.jsch.Session + */ +final class JSchSshSession implements Closeable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** Factory for {@link JSchSshSession}. */ + static final class JSchSshSessionFactory { + + private final Duration sshTimeout; + + @Inject + JSchSshSessionFactory(@Config("sshTimeout") Duration sshTimeout) { + this.sshTimeout = sshTimeout; + } + + /** + * Connect to remote SSH endpoint specified by {@code url}. + * + * @throws JSchException if we fail to open the connection. + */ + JSchSshSession create(JSch jsch, URI uri) throws JSchException { + RdeUploadUrl url = RdeUploadUrl.create(uri); + logger.info("Connecting to SSH endpoint: " + url); + Session session = jsch.getSession( + url.getUser().or("domain-registry"), + url.getHost(), + url.getPort()); + if (url.getPass().isPresent()) { + session.setPassword(url.getPass().get()); + } + session.setTimeout((int) sshTimeout.getMillis()); + session.connect((int) sshTimeout.getMillis()); + return new JSchSshSession(session, url, (int) sshTimeout.getMillis()); + } + } + + private final Session session; + private final RdeUploadUrl url; + private final int timeout; + + private JSchSshSession(Session session, RdeUploadUrl url, int timeout) { + this.session = session; + this.url = url; + this.timeout = timeout; + } + + /** + * Opens a new SFTP channel over this SSH session. + * + * @throws JSchException + * @throws SftpException + * @see JSchSftpChannel + */ + public JSchSftpChannel openSftpChannel() throws JSchException, SftpException { + ChannelSftp chan = (ChannelSftp) session.openChannel("sftp"); + chan.connect(timeout); + if (url.getPath().isPresent()) { + String dir = url.getPath().get(); + try { + chan.cd(dir); + } catch (SftpException e) { + logger.warning(e.toString()); + mkdirs(chan, dir); + chan.cd(dir); + } + } + return new JSchSftpChannel(chan); + } + + private void mkdirs(ChannelSftp chan, String dir) throws SftpException { + StringBuilder pathBuilder = new StringBuilder(dir.length()); + for (String part : Splitter.on('/').omitEmptyStrings().split(dir)) { + pathBuilder.append(part); + chan.mkdir(pathBuilder.toString()); + pathBuilder.append('/'); + } + } + + /** @see com.jcraft.jsch.Session#disconnect() */ + @Override + public void close() throws IOException { + session.disconnect(); + } +} diff --git a/java/com/google/domain/registry/rde/PendingDeposit.java b/java/com/google/domain/registry/rde/PendingDeposit.java new file mode 100644 index 000000000..6a74d85b1 --- /dev/null +++ b/java/com/google/domain/registry/rde/PendingDeposit.java @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import com.google.auto.value.AutoValue; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.Serializable; + +/** Container representing a single RDE or BRDA XML escrow deposit that needs to be created. */ +@AutoValue +public abstract class PendingDeposit implements Serializable { + + private static final long serialVersionUID = 3141095605225904433L; + + public abstract String tld(); + public abstract DateTime watermark(); + public abstract RdeMode mode(); + public abstract CursorType cursor(); + public abstract Duration interval(); + + static PendingDeposit create( + String tld, DateTime watermark, RdeMode mode, CursorType cursor, Duration interval) { + return new AutoValue_PendingDeposit(tld, watermark, mode, cursor, interval); + } + + PendingDeposit() {} +} diff --git a/java/com/google/domain/registry/rde/PendingDepositChecker.java b/java/com/google/domain/registry/rde/PendingDepositChecker.java new file mode 100644 index 000000000..c7529e2ef --- /dev/null +++ b/java/com/google/domain/registry/rde/PendingDepositChecker.java @@ -0,0 +1,133 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.registry.Registries; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldType; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; +import com.google.domain.registry.util.Clock; + +import com.googlecode.objectify.Work; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import javax.inject.Inject; + +/** + * Utility class that determines which RDE or BRDA deposits need to be created. + * + *

This class is called by {@link RdeStagingAction} at the beginning of its execution. Since it + * stages everything in a single run, it needs to know what's awaiting deposit. + * + *

We start off by getting the list of TLDs with escrow enabled. We then check {@code cursor} + * to see when it when it was due for a deposit. If that's in the past, then we know that we need + * to generate a deposit. If it's really far in the past, we might have to generate multiple + * deposits for that TLD, based on the configured interval. + * + *

However we will only generate one interval forward per mapreduce, since the reduce + * phase rolls forward a TLD's cursor, and we can't have that happening in parallel. + * + *

If no deposits have been made so far, then {@code startingPoint} is used as the watermark + * of the next deposit. If that's a day in the future, then escrow won't start until that date. + * This first deposit time will be set to datastore in a transaction. + */ +public final class PendingDepositChecker { + + @Inject Clock clock; + @Inject @Config("brdaDayOfWeek") int brdaDayOfWeek; + @Inject @Config("brdaInterval") Duration brdaInterval; + @Inject @Config("rdeInterval") Duration rdeInterval; + @Inject PendingDepositChecker() {} + + /** Returns multimap of TLDs to all RDE and BRDA deposits that need to happen. */ + public ImmutableSetMultimap + getTldsAndWatermarksPendingDepositForRdeAndBrda() { + return new ImmutableSetMultimap.Builder() + .putAll( + getTldsAndWatermarksPendingDeposit( + RdeMode.FULL, + CursorType.RDE_STAGING, + rdeInterval, + clock.nowUtc().withTimeAtStartOfDay())) + .putAll( + getTldsAndWatermarksPendingDeposit( + RdeMode.THIN, + CursorType.BRDA, + brdaInterval, + advanceToDayOfWeek(clock.nowUtc().withTimeAtStartOfDay(), brdaDayOfWeek))) + .build(); + } + + private ImmutableSetMultimap getTldsAndWatermarksPendingDeposit( + RdeMode mode, CursorType cursor, Duration interval, DateTime startingPoint) { + checkArgument(interval.isLongerThan(Duration.ZERO)); + ImmutableSetMultimap.Builder builder = + new ImmutableSetMultimap.Builder<>(); + DateTime now = clock.nowUtc(); + for (String tld : Registries.getTldsOfType(TldType.REAL)) { + Registry registry = Registry.get(tld); + if (!registry.getEscrowEnabled()) { + continue; + } + // Avoid creating a transaction unless absolutely necessary. + Optional cursorValue = RegistryCursor.load(registry, cursor); + if (isBeforeOrAt(cursorValue.or(startingPoint), now)) { + DateTime watermark; + if (cursorValue.isPresent()) { + watermark = cursorValue.get(); + } else { + watermark = transactionallyInitializeCursor(registry, cursor, startingPoint); + } + if (isBeforeOrAt(watermark, now)) { + builder.put(tld, PendingDeposit.create(tld, watermark, mode, cursor, interval)); + } + } + } + return builder.build(); + } + + private DateTime transactionallyInitializeCursor( + final Registry registry, + final CursorType cursor, + final DateTime initialValue) { + return ofy().transact(new Work() { + @Override + public DateTime run() { + for (DateTime value : RegistryCursor.load(registry, cursor).asSet()) { + return value; + } + RegistryCursor.save(registry, cursor, initialValue); + return initialValue; + }}); + } + + private static DateTime advanceToDayOfWeek(DateTime date, int dayOfWeek) { + while (date.getDayOfWeek() != dayOfWeek) { + date = date.plusDays(1); + } + return date; + } +} diff --git a/java/com/google/domain/registry/rde/RdeAdapter.java b/java/com/google/domain/registry/rde/RdeAdapter.java new file mode 100644 index 000000000..87c23a385 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeAdapter.java @@ -0,0 +1,40 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.google.domain.registry.xjc.rde.XjcRdeRrType; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** Utility class that converts database objects to RDE XML objects. */ +final class RdeAdapter { + + /** Create {@link XjcRdeRrType} with optional {@code client} attribute. */ + @Nullable + @CheckForNull + static XjcRdeRrType convertRr(@Nullable String value, @Nullable String client) { + if (isNullOrEmpty(value)) { + return null; + } + XjcRdeRrType rrType = new XjcRdeRrType(); + rrType.setValue(value); + rrType.setClient(emptyToNull(client)); + return rrType; + } +} diff --git a/java/com/google/domain/registry/rde/RdeCounter.java b/java/com/google/domain/registry/rde/RdeCounter.java new file mode 100644 index 000000000..dbd492ba5 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeCounter.java @@ -0,0 +1,97 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.filter; + +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.xjc.rde.XjcRdeDepositTypeType; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeader; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeaderCount; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeaderElement; +import com.google.domain.registry.xjc.rdereport.XjcRdeReport; + +import org.joda.time.DateTime; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.concurrent.atomic.AtomicLong; + +import javax.annotation.concurrent.NotThreadSafe; +import javax.inject.Inject; + +/** Utility class for generating a single {@link XjcRdeHeader} while marshalling a deposit. */ +@NotThreadSafe +public final class RdeCounter { + + private static final String URI_ESCROW = "draft-arias-noguchi-registry-data-escrow-06"; + private static final String URI_MAPPING = "draft-arias-noguchi-dnrd-objects-mapping-05"; + private static final int ICANN_REPORT_SPEC_VERSION = 1; + + private final EnumMap counts = new EnumMap<>(RdeResourceType.class); + + @Inject + public RdeCounter() { + for (RdeResourceType resourceType : getResourceTypesExcludingHeader()) { + counts.put(resourceType, new AtomicLong()); + } + } + + /** Increment the count on a given resource. */ + public void increment(RdeResourceType type) { + counts.get(type).incrementAndGet(); + } + + /** Constructs a header containing the sum of {@link #increment(RdeResourceType)} calls. */ + public XjcRdeHeader makeHeader(String tld, RdeMode mode) { + XjcRdeHeader header = new XjcRdeHeader(); + header.setTld(tld); + for (RdeResourceType resourceType : getResourceTypesExcludingHeader()) { + if (resourceType.getModes().contains(mode)) { + header.getCounts().add(makeCount(resourceType.getUri(), counts.get(resourceType).get())); + } + } + return header; + } + + /** Returns an ICANN notification report as a JAXB object. */ + public XjcRdeReport + makeReport(String id, DateTime watermark, XjcRdeHeader header, int revision) { + XjcRdeReport report = new XjcRdeReport(); + report.setId(id); + report.setKind(XjcRdeDepositTypeType.FULL); + report.setCrDate(watermark); + report.setWatermark(watermark); + report.setVersion(ICANN_REPORT_SPEC_VERSION); + report.setRydeSpecEscrow(URI_ESCROW); + report.setRydeSpecMapping(URI_MAPPING); + report.setResend(revision); + report.setHeader(new XjcRdeHeaderElement(header)); + return report; + } + + private Iterable getResourceTypesExcludingHeader() { + return filter(EnumSet.allOf(RdeResourceType.class), not(equalTo(RdeResourceType.HEADER))); + } + + private static XjcRdeHeaderCount makeCount(String uri, long count) { + XjcRdeHeaderCount bean = new XjcRdeHeaderCount(); + bean.setUri(uri); + bean.setValue(count); + return bean; + } +} diff --git a/java/com/google/domain/registry/rde/RdeMarshaller.java b/java/com/google/domain/registry/rde/RdeMarshaller.java new file mode 100644 index 000000000..a4b6912b9 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeMarshaller.java @@ -0,0 +1,165 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Verify.verify; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.domain.registry.model.ImmutableObject; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.tldconfig.idn.IdnTable; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.xjc.XjcXmlTransformer; +import com.google.domain.registry.xjc.rde.XjcRdeContentsType; +import com.google.domain.registry.xjc.rde.XjcRdeDeposit; +import com.google.domain.registry.xjc.rde.XjcRdeDepositTypeType; +import com.google.domain.registry.xjc.rde.XjcRdeMenuType; +import com.google.domain.registry.xjc.rdeidn.XjcRdeIdn; +import com.google.domain.registry.xjc.rdeidn.XjcRdeIdnElement; +import com.google.domain.registry.xjc.rdepolicy.XjcRdePolicy; +import com.google.domain.registry.xjc.rdepolicy.XjcRdePolicyElement; +import com.google.domain.registry.xml.XmlException; +import com.google.domain.registry.xml.XmlFragmentMarshaller; + +import com.googlecode.objectify.Key; + +import org.joda.time.DateTime; + +import java.io.ByteArrayOutputStream; +import java.io.Serializable; +import java.util.Collection; + +import javax.annotation.concurrent.NotThreadSafe; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.MarshalException; + +/** XML document fragment marshaller for RDE. */ +@NotThreadSafe +public final class RdeMarshaller implements Serializable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final long serialVersionUID = 202890386611768455L; + + private transient XmlFragmentMarshaller memoizedMarshaller; + + /** Returns top-portion of XML document. */ + public String makeHeader( + String depositId, DateTime watermark, Collection uris, int revision) { + // We can't make JAXB marshal half an element. So we're going to use a kludge where we provide + // it with the minimum data necessary to marshal a deposit, and then cut it up by manually. + XjcRdeMenuType menu = new XjcRdeMenuType(); + menu.setVersion("1.0"); + menu.getObjURIs().addAll(uris); + XjcRdePolicy policy = new XjcRdePolicy(); + policy.setScope("this-will-be-trimmed"); + policy.setElement("/make/strict/validation/pass"); + XjcRdeContentsType contents = new XjcRdeContentsType(); + contents.getContents().add(new XjcRdePolicyElement(policy)); + XjcRdeDeposit deposit = new XjcRdeDeposit(); + deposit.setId(depositId); + deposit.setWatermark(watermark); + deposit.setType(XjcRdeDepositTypeType.FULL); + if (revision > 0) { + deposit.setResend(revision); + } + deposit.setRdeMenu(menu); + deposit.setContents(contents); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + XjcXmlTransformer.marshalStrict(deposit, os, UTF_8); + } catch (XmlException e) { + throw new RuntimeException(e); + } + String rdeDocument = os.toString(); + String marker = "\n"; + int startOfContents = rdeDocument.indexOf(marker); + verify(startOfContents > 0, "Bad RDE document:\n%s", rdeDocument); + return rdeDocument.substring(0, startOfContents + marker.length()); + } + + /** Returns bottom-portion of XML document. */ + public String makeFooter() { + return "\n\n\n"; + } + + /** Turns XJC element into XML fragment, with schema validation. */ + public String marshalStrictlyOrDie(JAXBElement element) { + try { + return getMarshaller().marshal(element); + } catch (MarshalException e) { + throw new RuntimeException(e); + } + } + + /** Turns {@link ContactResource} object into an XML fragment. */ + public DepositFragment marshalContact(ContactResource contact) { + return marshalResource(RdeResourceType.CONTACT, contact, + ContactResourceToXjcConverter.convert(contact)); + } + + /** Turns {@link DomainResource} object into an XML fragment. */ + public DepositFragment marshalDomain(DomainResource domain, RdeMode mode) { + return marshalResource(RdeResourceType.DOMAIN, domain, + DomainResourceToXjcConverter.convert(domain, mode)); + } + + /** Turns {@link HostResource} object into an XML fragment. */ + public DepositFragment marshalHost(HostResource host) { + return marshalResource(RdeResourceType.HOST, host, + HostResourceToXjcConverter.convert(host)); + } + + /** Turns {@link Registrar} object into an XML fragment. */ + public DepositFragment marshalRegistrar(Registrar registrar) { + return marshalResource(RdeResourceType.REGISTRAR, registrar, + RegistrarToXjcConverter.convert(registrar)); + } + + /** Turns {@link IdnTable} object into an XML fragment. */ + public String marshalIdn(IdnTable idn) { + XjcRdeIdn bean = new XjcRdeIdn(); + bean.setId(idn.getName()); + bean.setUrl(idn.getUrl().toString()); + bean.setUrlPolicy(idn.getPolicy().toString()); + return marshalStrictlyOrDie(new XjcRdeIdnElement(bean)); + } + + private DepositFragment marshalResource( + RdeResourceType type, ImmutableObject resource, JAXBElement element) { + String xml = ""; + String error = ""; + try { + xml = getMarshaller().marshal(element); + } catch (MarshalException e) { + error = String.format("RDE XML schema validation failed: %s\n%s%s\n", + Key.create(resource), + e.getLinkedException(), + getMarshaller().marshalLenient(element)); + logger.severe(error); + } + return DepositFragment.create(type, xml, error); + } + + private XmlFragmentMarshaller getMarshaller() { + return memoizedMarshaller != null + ? memoizedMarshaller + : (memoizedMarshaller = XjcXmlTransformer.get().createFragmentMarshaller()); + } +} diff --git a/java/com/google/domain/registry/rde/RdeModule.java b/java/com/google/domain/registry/rde/RdeModule.java new file mode 100644 index 000000000..9fec81c55 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeModule.java @@ -0,0 +1,70 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; + +import dagger.Module; +import dagger.Provides; + +import org.joda.time.DateTime; + +import javax.inject.Named; +import javax.servlet.http.HttpServletRequest; + +/** + * Dagger module for RDE package. + * + * @see "com.google.domain.registry.module.backend.BackendComponent" + */ +@Module +public final class RdeModule { + + static final String PARAM_WATERMARK = "watermark"; + + @Provides + @Parameter(PARAM_WATERMARK) + static DateTime provideWatermark(HttpServletRequest req) { + return DateTime.parse(RequestParameters.extractRequiredParameter(req, PARAM_WATERMARK)); + } + + @Provides + @Named("brda") + static Queue provideQueueBrda() { + return getQueue("brda"); + } + + @Provides + @Named("rde-report") + static Queue provideQueueRdeReport() { + return getQueue("rde-report"); + } + + @Provides + @Named("rde-staging") + static Queue provideQueueRdeStaging() { + return getQueue("rde-staging"); + } + + @Provides + @Named("rde-upload") + static Queue provideQueueRdeUpload() { + return getQueue("rde-upload"); + } +} diff --git a/java/com/google/domain/registry/rde/RdeReportTask.java b/java/com/google/domain/registry/rde/RdeReportTask.java new file mode 100644 index 000000000..a4573264c --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeReportTask.java @@ -0,0 +1,102 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Verify.verify; +import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; +import static com.google.domain.registry.model.rde.RdeMode.FULL; +import static com.google.domain.registry.request.Action.Method.POST; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; + +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.common.io.ByteStreams; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.gcs.GcsUtils; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.rde.RdeNamingUtils; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; +import com.google.domain.registry.rde.EscrowTaskRunner.EscrowTask; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.NoContentException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.FormattingLogger; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.IOException; +import java.io.InputStream; + +import javax.inject.Inject; + +/** + * Uploads a small XML RDE report to ICANN after {@link RdeUploadTask} has finished. + */ +@Action(path = RdeReportTask.PATH, method = POST) +public final class RdeReportTask implements Runnable, EscrowTask { + + static final String PATH = "/_dr/task/rdeReport"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject GcsUtils gcsUtils; + @Inject Ghostryde ghostryde; + @Inject EscrowTaskRunner runner; + @Inject Response response; + @Inject RdeReporter reporter; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject @Config("rdeBucket") String bucket; + @Inject @Config("rdeInterval") Duration interval; + @Inject @Config("rdeReportLockTimeout") Duration timeout; + @Inject @Key("rdeStagingDecryptionKey") PGPPrivateKey stagingDecryptionKey; + @Inject RdeReportTask() {} + + @Override + public void run() { + runner.lockRunAndRollForward(this, Registry.get(tld), timeout, CursorType.RDE_REPORT, interval); + } + + @Override + public void runWithLock(DateTime watermark) throws Exception { + DateTime stagingCursor = + RegistryCursor.load(Registry.get(tld), CursorType.RDE_UPLOAD).or(START_OF_TIME); + if (!stagingCursor.isAfter(watermark)) { + logger.infofmt("tld=%s reportCursor=%s uploadCursor=%s", tld, watermark, stagingCursor); + throw new NoContentException("Waiting for RdeUploadTask to complete"); + } + String prefix = RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, 0); + GcsFilename reportFilename = new GcsFilename(bucket, prefix + "-report.xml.ghostryde"); + verify(gcsUtils.existsAndNotEmpty(reportFilename), "Missing file: %s", reportFilename); + reporter.send(readReportFromGcs(reportFilename)); + response.setContentType(PLAIN_TEXT_UTF_8); + response.setPayload(String.format("OK %s %s\n", tld, watermark)); + } + + /** Reads and decrypts the XML file from cloud storage. */ + private byte[] readReportFromGcs(GcsFilename reportFilename) throws IOException, PGPException { + try (InputStream gcsInput = gcsUtils.openInputStream(reportFilename); + Ghostryde.Decryptor decryptor = ghostryde.openDecryptor(gcsInput, stagingDecryptionKey); + Ghostryde.Decompressor decompressor = ghostryde.openDecompressor(decryptor); + Ghostryde.Input xmlInput = ghostryde.openInput(decompressor)) { + return ByteStreams.toByteArray(xmlInput); + } + } +} diff --git a/java/com/google/domain/registry/rde/RdeReporter.java b/java/com/google/domain/registry/rde/RdeReporter.java new file mode 100644 index 000000000..4a005833c --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeReporter.java @@ -0,0 +1,124 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.appengine.api.urlfetch.FetchOptions.Builder.validateCertificate; +import static com.google.appengine.api.urlfetch.HTTPMethod.PUT; +import static com.google.common.io.BaseEncoding.base64; +import static com.google.common.net.HttpHeaders.AUTHORIZATION; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; +import static java.nio.charset.StandardCharsets.UTF_8; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.appengine.api.urlfetch.HTTPHeader; +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.config.RegistryConfig; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.request.HttpException.InternalServerErrorException; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.UrlFetchException; +import com.google.domain.registry.xjc.XjcXmlTransformer; +import com.google.domain.registry.xjc.iirdea.XjcIirdeaResponseElement; +import com.google.domain.registry.xjc.iirdea.XjcIirdeaResult; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeader; +import com.google.domain.registry.xjc.rdereport.XjcRdeReportReport; +import com.google.domain.registry.xml.XmlException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.inject.Inject; + +/** + * Class that uploads a decrypted XML deposit report to ICANN's webserver. + * + * @see RdeReportTask + */ +public class RdeReporter { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** @see "http://tools.ietf.org/html/draft-lozano-icann-registry-interfaces-05#section-4" */ + private static final String REPORT_MIME = "text/xml"; + + @Inject RegistryConfig config; + @Inject URLFetchService urlFetchService; + @Inject @Config("rdeReportUrlPrefix") String reportUrlPrefix; + @Inject @Key("icannReportingPassword") String password; + @Inject RdeReporter() {} + + /** Uploads {@code reportBytes} to ICANN. */ + public void send(byte[] reportBytes) throws IOException, XmlException { + XjcRdeReportReport report = XjcXmlTransformer.unmarshal(new ByteArrayInputStream(reportBytes)); + XjcRdeHeader header = report.getHeader().getValue(); + + // Send a PUT request to ICANN's HTTPS server. + URL url = makeReportUrl(header.getTld(), report.getId()); + String username = header.getTld() + "_ry"; + String token = base64().encode(String.format("%s:%s", username, password).getBytes(UTF_8)); + HTTPRequest req = new HTTPRequest(url, PUT, validateCertificate().setDeadline(60d)); + req.addHeader(new HTTPHeader(CONTENT_TYPE, REPORT_MIME)); + req.addHeader(new HTTPHeader(AUTHORIZATION, "Basic " + token)); + req.setPayload(reportBytes); + logger.infofmt("Sending report:\n%s", new String(reportBytes, UTF_8)); + HTTPResponse rsp = urlFetchService.fetch(req); + switch (rsp.getResponseCode()) { + case SC_OK: + case SC_BAD_REQUEST: + break; + default: + throw new UrlFetchException("PUT failed", req, rsp); + } + + // Ensure the XML response is valid. + XjcIirdeaResult result = parseResult(rsp); + if (result.getCode().getValue() != 1000) { + logger.warningfmt("PUT rejected: %d %s\n%s", + result.getCode().getValue(), + result.getMsg(), + result.getDescription()); + throw new InternalServerErrorException(result.getMsg()); + } + } + + /** + * Unmarshals IIRDEA XML result object from {@link HTTPResponse} payload. + * + * @see "http://tools.ietf.org/html/draft-lozano-icann-registry-interfaces-05#section-4.1" + */ + private XjcIirdeaResult parseResult(HTTPResponse rsp) throws XmlException { + byte[] responseBytes = rsp.getContent(); + logger.infofmt("Received response:\n%s", new String(responseBytes, UTF_8)); + XjcIirdeaResponseElement response = + XjcXmlTransformer.unmarshal(new ByteArrayInputStream(responseBytes)); + XjcIirdeaResult result = response.getResult(); + return result; + } + + private URL makeReportUrl(String tld, String id) { + try { + return new URL(String.format("%s/%s/%s", reportUrlPrefix, canonicalizeDomainName(tld), id)); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/rde/RdeResourceType.java b/java/com/google/domain/registry/rde/RdeResourceType.java new file mode 100644 index 000000000..6768452b8 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeResourceType.java @@ -0,0 +1,66 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.model.rde.RdeMode.FULL; +import static com.google.domain.registry.model.rde.RdeMode.THIN; + +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import com.google.domain.registry.model.rde.RdeMode; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; + +/** Types of objects that get embedded in an escrow deposit. */ +public enum RdeResourceType { + CONTACT("urn:ietf:params:xml:ns:rdeContact-1.0", EnumSet.of(FULL)), + DOMAIN("urn:ietf:params:xml:ns:rdeDomain-1.0", EnumSet.of(FULL, THIN)), + HOST("urn:ietf:params:xml:ns:rdeHost-1.0", EnumSet.of(FULL)), + REGISTRAR("urn:ietf:params:xml:ns:rdeRegistrar-1.0", EnumSet.of(FULL, THIN)), + IDN("urn:ietf:params:xml:ns:rdeIDN-1.0", EnumSet.of(FULL, THIN)), + HEADER("urn:ietf:params:xml:ns:rdeHeader-1.0", EnumSet.of(FULL, THIN)); + + private final String uri; + private final Set modes; + + private RdeResourceType(String uri, EnumSet modes) { + this.uri = uri; + this.modes = Collections.unmodifiableSet(modes); + } + + /** Returns RDE XML schema URI specifying resource. */ + public String getUri() { + return uri; + } + + /** Returns set indicating if resource is stored in BRDA thin deposits. */ + public Set getModes() { + return modes; + } + + /** Returns set of resource type URIs included in a deposit {@code mode}. */ + public static ImmutableSortedSet getUris(RdeMode mode) { + ImmutableSortedSet.Builder builder = + new ImmutableSortedSet.Builder<>(Ordering.natural()); + for (RdeResourceType resourceType : RdeResourceType.values()) { + if (resourceType.getModes().contains(mode)) { + builder.add(resourceType.getUri()); + } + } + return builder.build(); + } +} diff --git a/java/com/google/domain/registry/rde/RdeStagingAction.java b/java/com/google/domain/registry/rde/RdeStagingAction.java new file mode 100644 index 000000000..3c7076502 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeStagingAction.java @@ -0,0 +1,208 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.util.PipelineUtils.createJobPath; +import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimaps; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.mapreduce.EppResourceInputs; +import com.google.domain.registry.mapreduce.MapreduceRunner; +import com.google.domain.registry.mapreduce.NullInput; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.index.EppResourceIndex; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; + +import org.joda.time.Duration; + +import javax.inject.Inject; + +/** + * MapReduce that idempotently stages escrow deposit XML files on GCS for RDE/BRDA for all TLDs. + * + *

MapReduce Operation

+ * + *

This task starts by asking {@link PendingDepositChecker} which deposits need to be generated. + * If there's nothing to deposit, we return 204 No Content; otherwise, we fire off a MapReduce job + * and redirect to its status GUI. + * + *

The mapreduce job scans every {@link EppResource} in datastore. It maps a point-in-time + * representation of each entity to the escrow XML files in which it should appear. + * + *

There is one map worker for each {@code EppResourceIndexBucket} entity group shard. There is + * one reduce worker for each deposit being generated. + * + *

{@link ContactResource} and {@link HostResource} are emitted on all TLDs, even when the + * domains on a TLD don't reference them. BRDA {@link RdeMode#THIN thin} deposits exclude contacts + * and hosts entirely. + * + *

{@link Registrar} entities, both active and inactive, are included in all deposits. They are + * not rewinded point-in-time. + * + *

The XML deposit files generated by this job are humongous. A tiny XML report file is generated + * for each deposit, telling us how much of what it contains. + * + *

Once a deposit is successfully generated, an {@link RdeUploadTask} is enqueued which will + * upload it via SFTP to the third-party escrow provider. + * + *

To generate escrow deposits manually and locally, use the {@code registry_tool} command + * {@code GenerateEscrowDepositCommand}. + * + *

Logging

+ * + *

To identify the reduce worker request for a deposit in App Engine's log viewer, you can use + * search text like {@code tld=soy}, {@code watermark=2015-01-01}, and {@code mode=FULL}. + * + *

Error Handling

+ * + *

Valid model objects might not be valid to the RDE XML schema. A single invalid object will + * cause the whole deposit to fail. You need to check the logs, find out which entities are broken, + * and perform datastore surgery. + * + *

If a deposit fails, an error is emitted to the logs for each broken entity. It tells you the + * key and shows you its representation in lenient XML. + * + *

Failed deposits will be retried indefinitely. This is because RDE and BRDA each have a + * {@link RegistryCursor} for each TLD. Even if the cursor lags for days, it'll catch up gradually + * on its own, once the data becomes valid. + * + *

The third-party escrow provider will validate each deposit we send them. They do both schema + * validation and reference checking. + * + *

This job does not perform reference checking. Administrators can do this locally with the + * {@code ValidateEscrowDepositCommand} command in {@code registry_tool}. + * + *

Cursors

+ * + *

Deposits are generated serially for a given (tld, mode) pair. A deposit is never started + * beyond the cursor. Once a deposit is completed, its cursor is rolled forward transactionally. + * + *

The mode determines which cursor is used. {@link CursorType#RDE_STAGING} is used for thick + * deposits and {@link CursorType#BRDA} is used for thin deposits. + * + *

Use the {@code ListCursorsCommand} and {@code UpdateCursorsCommand} commands to administrate + * with these cursors. + * + *

Security

+ * + *

The deposit and report are encrypted using {@link Ghostryde}. Administrators can use the + * {@code GhostrydeCommand} command in {@code registry_tool} to view them. + * + *

Unencrypted XML fragments are stored temporarily between the map and reduce steps. The + * ghostryde encryption on the full archived deposits makes life a little more difficult for an + * attacker. But security ultimately depends on the bucket. + * + *

Idempotency

+ * + *

We lock the reduce tasks. This is necessary because: a) App Engine tasks might get double + * executed; and b) Cloud Storage file handles get committed on close even if our code throws an + * exception. + * + *

Deposits are generated serially for a given (watermark, mode) pair. A deposit is never started + * beyond the cursor. Once a deposit is completed, its cursor is rolled forward transactionally. + * Duplicate jobs may exist {@code <=cursor}. So a transaction will not bother changing the cursor + * if it's already been rolled forward. + * + *

Enqueueing {@code RdeUploadTask} is also part of the cursor transaction. This is necessary + * because the first thing the upload task does is check the staging cursor to verify it's been + * completed, so we can't enqueue before we roll. We also can't enqueue after the roll, because then + * if enqueueing fails, the upload might never be enqueued. + * + *

Determinism

+ * + *

The filename of an escrow deposit is determistic for a given (TLD, watermark, + * {@linkplain RdeMode mode}) triplet. Its generated contents is deterministic in all the ways that + * we care about. Its view of the database is strongly consistent. + * + *

This is because: + *

    + *
  1. {@code EppResource} queries are strongly consistent thanks to {@link EppResourceIndex} + *
  2. {@code EppResource} entities are rewinded to the point-in-time of the watermark + *
+ * + *

Here's what's not deterministic: + *

    + *
  • Ordering of XML fragments. We don't care about this. + *
  • Information about registrars. There's no point-in-time for these objects. So in order to + * guarantee referential correctness of your deposits, you must never delete a registrar entity. + *
+ * + * @see "https://tools.ietf.org/html/draft-arias-noguchi-registry-data-escrow-06" + * @see "https://tools.ietf.org/html/draft-arias-noguchi-dnrd-objects-mapping-05" + */ +@Action(path = "/_dr/task/rdeStaging") +public final class RdeStagingAction implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject Clock clock; + @Inject PendingDepositChecker pendingDepositChecker; + @Inject RdeStagingReducer reducer; + @Inject Response response; + @Inject MapreduceRunner mrRunner; + @Inject @Config("transactionCooldown") Duration transactionCooldown; + @Inject RdeStagingAction() {} + + @Override + public void run() { + ImmutableSetMultimap pendings = ImmutableSetMultimap.copyOf( + Multimaps.filterValues( + pendingDepositChecker.getTldsAndWatermarksPendingDepositForRdeAndBrda(), + new Predicate() { + @Override + public boolean apply(PendingDeposit pending) { + if (clock.nowUtc().isBefore(pending.watermark().plus(transactionCooldown))) { + logger.infofmt("Ignoring within %s cooldown: %s", transactionCooldown, pending); + return false; + } else { + return true; + } + }})); + if (pendings.isEmpty()) { + String message = "Nothing needs to be deposited"; + logger.info(message); + response.setStatus(SC_NO_CONTENT); + response.setPayload(message); + return; + } + for (PendingDeposit pending : pendings.values()) { + logger.infofmt("%s", pending); + } + response.sendJavaScriptRedirect(createJobPath(mrRunner + .setJobName("Stage escrow deposits for all TLDs") + .setModuleName("backend") + .setDefaultReduceShards(pendings.size()) + .runMapreduce( + new RdeStagingMapper(pendings), + reducer, + ImmutableList.of( + // Add an extra shard that maps over a null resource. See the mapper code for why. + new NullInput(), + EppResourceInputs.createEntityInput(EppResource.class))))); + } +} diff --git a/java/com/google/domain/registry/rde/RdeStagingMapper.java b/java/com/google/domain/registry/rde/RdeStagingMapper.java new file mode 100644 index 000000000..1ed70f024 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeStagingMapper.java @@ -0,0 +1,193 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.auto.value.AutoValue; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Maps; +import com.google.domain.registry.model.EppResource; +import com.google.domain.registry.model.EppResourceUtils; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.registrar.Registrar; + +import com.googlecode.objectify.Result; + +import org.joda.time.DateTime; + +import java.util.HashMap; +import java.util.Map; + +/** Mapper for {@link RdeStagingAction}. */ +public final class RdeStagingMapper extends Mapper { + + private static final long serialVersionUID = -1518185703789372524L; + + private final ImmutableSetMultimap pendings; + private final RdeMarshaller marshaller = new RdeMarshaller(); + + RdeStagingMapper(ImmutableSetMultimap pendings) { + this.pendings = pendings; + } + + @Override + public final void map(final EppResource resource) { + // The mapreduce has one special input that provides a null resource. This is used as a sentinel + // to indicate that we should emit the Registrar objects on this map shard, as these need to be + // added to every deposit. It is important that these be emitted as part of the mapreduce and + // not added in a separate stage, because the reducer only runs if there is at least one value + // emitted from the mapper. Without this, a cursor might never advance because no EppResource + // entity exists at the watermark. + if (resource == null) { + for (Registrar registrar : Registrar.loadAll()) { + DepositFragment fragment = marshaller.marshalRegistrar(registrar); + for (PendingDeposit pending : pendings.values()) { + emit(pending, fragment); + } + } + return; + } + + // Skip polymorphic entities that share datastore kind. + if (!(resource instanceof ContactResource + || resource instanceof DomainResource + || resource instanceof HostResource)) { + return; + } + + // Skip prober data. + if (nullToEmpty(resource.getCreationClientId()).startsWith("prober-") + || nullToEmpty(resource.getCurrentSponsorClientId()).startsWith("prober-") + || nullToEmpty(resource.getLastEppUpdateClientId()).startsWith("prober-")) { + return; + } + + // Contacts and hosts get emitted on all TLDs, even if domains don't reference them. + boolean shouldEmitOnAllTlds = !(resource instanceof DomainResource); + + // Get the set of all TLDs to which this resource should be emitted. + ImmutableSet tlds = + shouldEmitOnAllTlds + ? pendings.keySet() + : ImmutableSet.of(((DomainResource) resource).getTld()); + + // Get the set of all point-in-time watermarks we need, to minimize rewinding. + ImmutableSet dates = + FluentIterable + .from(shouldEmitOnAllTlds + ? pendings.values() + : pendings.get(((DomainResource) resource).getTld())) + .transform(new Function() { + @Override + public DateTime apply(PendingDeposit pending) { + return pending.watermark(); + }}) + .toSet(); + + // Launch asynchronous fetches of point-in-time representations of resource. + ImmutableMap> resourceAtTimes = + ImmutableMap.copyOf(Maps.asMap(dates, + new Function>() { + @Override + public Result apply(DateTime input) { + return EppResourceUtils.loadAtPointInTime(resource, input); + }})); + + // Convert resource to an XML fragment for each watermark/mode pair lazily and cache the result. + Fragmenter fragmenter = new Fragmenter(resourceAtTimes); + + // Emit resource as an XML fragment for all TLDs and modes pending deposit. + for (String tld : tlds) { + for (PendingDeposit pending : pendings.get(tld)) { + // Hosts and contacts don't get included in BRDA deposits. + if (pending.mode() == RdeMode.THIN + && (resource instanceof ContactResource + || resource instanceof HostResource)) { + continue; + } + for (DepositFragment fragment + : fragmenter.marshal(pending.watermark(), pending.mode()).asSet()) { + emit(pending, fragment); + } + } + } + + // Avoid running out of memory. + ofy().clearSessionCache(); + } + + /** Loading cache that turns a resource into XML for the various points in time and modes. */ + private class Fragmenter { + private final Map> cache = new HashMap<>(); + private final ImmutableMap> resourceAtTimes; + + Fragmenter(ImmutableMap> resourceAtTimes) { + this.resourceAtTimes = resourceAtTimes; + } + + Optional marshal(DateTime watermark, RdeMode mode) { + Optional result = cache.get(WatermarkModePair.create(watermark, mode)); + if (result != null) { + return result; + } + EppResource resource = resourceAtTimes.get(watermark).now(); + if (resource == null) { + result = Optional.absent(); + cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result); + cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result); + return result; + } + if (resource instanceof DomainResource) { + result = Optional.of(marshaller.marshalDomain((DomainResource) resource, mode)); + cache.put(WatermarkModePair.create(watermark, mode), result); + return result; + } else if (resource instanceof ContactResource) { + result = Optional.of(marshaller.marshalContact((ContactResource) resource)); + cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result); + cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result); + return result; + } else if (resource instanceof HostResource) { + result = Optional.of(marshaller.marshalHost((HostResource) resource)); + cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result); + cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result); + return result; + } else { + throw new AssertionError(resource.toString()); + } + } + } + + /** Map key for {@link Fragmenter} cache. */ + @AutoValue + abstract static class WatermarkModePair { + abstract DateTime watermark(); + abstract RdeMode mode(); + + static WatermarkModePair create(DateTime watermark, RdeMode mode) { + return new AutoValue_RdeStagingMapper_WatermarkModePair(watermark, mode); + } + } +} diff --git a/java/com/google/domain/registry/rde/RdeStagingReducer.java b/java/com/google/domain/registry/rde/RdeStagingReducer.java new file mode 100644 index 000000000..686bf5b27 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeStagingReducer.java @@ -0,0 +1,226 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.appengine.tools.cloudstorage.GcsServiceFactory.createGcsService; +import static com.google.common.base.Verify.verify; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.appengine.tools.cloudstorage.RetryParams; +import com.google.appengine.tools.mapreduce.Reducer; +import com.google.appengine.tools.mapreduce.ReducerInput; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.gcs.GcsUtils; +import com.google.domain.registry.keyring.api.KeyModule; +import com.google.domain.registry.keyring.api.PgpHelper; +import com.google.domain.registry.model.rde.RdeMode; +import com.google.domain.registry.model.rde.RdeNamingUtils; +import com.google.domain.registry.model.rde.RdeRevision; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.server.Lock; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.tldconfig.idn.IdnTableEnum; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.TaskEnqueuer; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeader; +import com.google.domain.registry.xjc.rdeheader.XjcRdeHeaderElement; +import com.google.domain.registry.xml.XmlException; + +import com.googlecode.objectify.VoidWork; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.security.Security; +import java.util.Iterator; +import java.util.concurrent.Callable; + +import javax.inject.Inject; + +/** Reducer for {@link RdeStagingAction}. */ +public final class RdeStagingReducer extends Reducer { + + private static final long serialVersionUID = -3366189042770402345L; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private final RdeMarshaller marshaller = new RdeMarshaller(); + + @Inject TaskEnqueuer taskEnqueuer; + @Inject @Config("gcsBufferSize") int gcsBufferSize; + @Inject @Config("rdeBucket") String bucket; + @Inject @Config("rdeGhostrydeBufferSize") int ghostrydeBufferSize; + @Inject @Config("rdeStagingLockTimeout") Duration lockTimeout; + @Inject @KeyModule.Key("rdeStagingEncryptionKey") byte[] stagingKeyBytes; + @Inject RdeStagingReducer() {} + + @Override + public void reduce(final PendingDeposit key, final ReducerInput fragments) { + Callable lockRunner = new Callable() { + @Override + public Void call() throws Exception { + reduceWithLock(key, fragments); + return null; + }}; + String lockName = String.format("RdeStaging %s", key.tld()); + if (!Lock.executeWithLocks(lockRunner, null, null, lockTimeout, lockName)) { + logger.warningfmt("Lock in use: %s", lockName); + } + } + + private void reduceWithLock(final PendingDeposit key, Iterator fragments) { + logger.infofmt("RdeStagingReducer %s", key); + + // Normally this is done by BackendServlet but it's not present in MapReduceServlet. + Security.addProvider(new BouncyCastleProvider()); + + // Construct things that Dagger would inject if this wasn't serialized. + Ghostryde ghostryde = new Ghostryde(ghostrydeBufferSize); + PGPPublicKey stagingKey = PgpHelper.loadPublicKeyBytes(stagingKeyBytes); + GcsUtils cloudStorage = + new GcsUtils(createGcsService(RetryParams.getDefaultInstance()), gcsBufferSize); + RdeCounter counter = new RdeCounter(); + + // Determine some basic things about the deposit. + final RdeMode mode = key.mode(); + final String tld = key.tld(); + final DateTime watermark = key.watermark(); + final int revision = RdeRevision.getNextRevision(tld, watermark, mode); + String id = RdeUtil.timestampToId(watermark); + String prefix = RdeNamingUtils.makeRydeFilename(tld, watermark, mode, 1, revision); + GcsFilename xmlFilename = new GcsFilename(bucket, prefix + ".xml.ghostryde"); + GcsFilename xmlLengthFilename = new GcsFilename(bucket, prefix + ".xml.length"); + GcsFilename reportFilename = new GcsFilename(bucket, prefix + "-report.xml.ghostryde"); + + // These variables will be populated as we write the deposit XML and used for other files. + boolean failed = false; + long xmlLength; + XjcRdeHeader header; + + // Write a gigantic XML file to GCS. We'll start by opening encrypted out/err file handles. + logger.infofmt("Writing %s", xmlFilename); + try (OutputStream gcsOutput = cloudStorage.openOutputStream(xmlFilename); + Ghostryde.Encryptor encryptor = ghostryde.openEncryptor(gcsOutput, stagingKey); + Ghostryde.Compressor kompressor = ghostryde.openCompressor(encryptor); + Ghostryde.Output gOutput = ghostryde.openOutput(kompressor, prefix + ".xml", watermark); + Writer output = new OutputStreamWriter(gOutput, UTF_8)) { + + // Output the top portion of the XML document. + output.write(marshaller.makeHeader(id, watermark, RdeResourceType.getUris(mode), revision)); + + // Output XML fragments emitted to us by RdeStagingMapper while counting them. + while (fragments.hasNext()) { + DepositFragment fragment = fragments.next(); + if (!fragment.xml().isEmpty()) { + output.write(fragment.xml()); + counter.increment(fragment.type()); + } + if (!fragment.error().isEmpty()) { + failed = true; + logger.severe(fragment.error()); + } + } + for (IdnTableEnum idn : IdnTableEnum.values()) { + output.write(marshaller.marshalIdn(idn.getTable())); + counter.increment(RdeResourceType.IDN); + } + + // Output XML that says how many resources were emitted. + header = counter.makeHeader(tld, mode); + output.write(marshaller.marshalStrictlyOrDie(new XjcRdeHeaderElement(header))); + + // Output the bottom of the XML document. + output.write(marshaller.makeFooter()); + + // And we're done! How many raw XML bytes did we write? + output.flush(); + xmlLength = gOutput.getBytesWritten(); + } catch (IOException | PGPException e) { + throw new RuntimeException(e); + } + + // If an entity was broken, abort after writing as much logs/deposit data as possible. + verify(!failed); + + // Write a file to GCS containing the byte length (ASCII) of the raw unencrypted XML. + // + // This is necessary because RdeUploadTask creates a tar file which requires that the length + // be outputted. We don't want to have to decrypt the entire ghostryde file to determine the + // length, so we just save it separately. + logger.infofmt("Writing %s", xmlLengthFilename); + try (OutputStream gcsOutput = cloudStorage.openOutputStream(xmlLengthFilename)) { + gcsOutput.write(Long.toString(xmlLength).getBytes(US_ASCII)); + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Write a tiny XML file to GCS containing some information about the deposit. + // + // This will be sent to ICANN once we're done uploading the big XML to the escrow provider. + if (mode == RdeMode.FULL) { + logger.infofmt("Writing %s", reportFilename); + String innerName = prefix + "-report.xml"; + try (OutputStream gcsOutput = cloudStorage.openOutputStream(reportFilename); + Ghostryde.Encryptor encryptor = ghostryde.openEncryptor(gcsOutput, stagingKey); + Ghostryde.Compressor kompressor = ghostryde.openCompressor(encryptor); + Ghostryde.Output output = ghostryde.openOutput(kompressor, innerName, watermark)) { + counter.makeReport(id, watermark, header, revision).marshal(output, UTF_8); + } catch (IOException | PGPException | XmlException e) { + throw new RuntimeException(e); + } + } + + // Now that we're done, kick off RdeUploadTask and roll forward the cursor transactionally. + ofy().transact(new VoidWork() { + @Override + public void vrun() { + Registry registry = Registry.get(tld); + DateTime position = RegistryCursor.load(registry, key.cursor()).get(); + DateTime newPosition = key.watermark().plus(key.interval()); + if (!position.isBefore(newPosition)) { + logger.warning("Cursor has already been rolled forward."); + return; + } + verify(position.equals(key.watermark()), + "Partial ordering of RDE deposits broken: %s %s", position, key); + RegistryCursor.save(registry, key.cursor(), newPosition); + logger.infofmt("Rolled forward %s on %s cursor to %s", key.cursor(), tld, newPosition); + RdeRevision.saveRevision(tld, watermark, mode, revision); + if (mode == RdeMode.FULL) { + taskEnqueuer.enqueue(getQueue("rde-upload"), + withUrl(RdeUploadTask.PATH) + .param(RequestParameters.PARAM_TLD, tld)); + } else { + taskEnqueuer.enqueue(getQueue("brda"), + withUrl(BrdaCopyTask.PATH) + .param(RequestParameters.PARAM_TLD, tld) + .param(RdeModule.PARAM_WATERMARK, watermark.toString())); + } + }}); + } +} diff --git a/java/com/google/domain/registry/rde/RdeUploadTask.java b/java/com/google/domain/registry/rde/RdeUploadTask.java new file mode 100644 index 000000000..a6c84614d --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeUploadTask.java @@ -0,0 +1,221 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.common.base.Verify.verify; +import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.rde.RdeMode.FULL; +import static com.google.domain.registry.request.Action.Method.POST; +import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME; +import static com.jcraft.jsch.ChannelSftp.OVERWRITE; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.asList; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.common.io.ByteStreams; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.gcs.GcsUtils; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.rde.RdeNamingUtils; +import com.google.domain.registry.model.rde.RdeRevision; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.RegistryCursor; +import com.google.domain.registry.model.registry.RegistryCursor.CursorType; +import com.google.domain.registry.rde.EscrowTaskRunner.EscrowTask; +import com.google.domain.registry.rde.JSchSshSession.JSchSshSessionFactory; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.HttpException.ServiceUnavailableException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.TaskEnqueuer; +import com.google.domain.registry.util.TeeOutputStream; + +import com.googlecode.objectify.VoidWork; +import com.jcraft.jsch.JSch; + +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Task that securely uploads an RDE XML file from Cloud Storage to a trusted third party (such as + * Iron Mountain) via SFTP. + * + *

This task is invoked by {@link RdeStagingAction} once it's created the files we need. The date + * is calculated from {@link CursorType#RDE_UPLOAD}. + * + *

Once this task completes, it rolls the cursor forward a day and triggers + * {@link RdeReportTask}. + */ +@Action(path = RdeUploadTask.PATH, method = POST) +public final class RdeUploadTask implements Runnable, EscrowTask { + + static final String PATH = "/_dr/task/rdeUpload"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject Clock clock; + @Inject GcsUtils gcsUtils; + @Inject Ghostryde ghostryde; + @Inject EscrowTaskRunner runner; + @Inject JSch jsch; + @Inject JSchSshSessionFactory jschSshSessionFactory; + @Inject Response response; + @Inject RydePgpCompressionOutputStreamFactory pgpCompressionFactory; + @Inject RydePgpEncryptionOutputStreamFactory pgpEncryptionFactory; + @Inject RydePgpFileOutputStreamFactory pgpFileFactory; + @Inject RydePgpSigningOutputStreamFactory pgpSigningFactory; + @Inject RydeTarOutputStreamFactory tarFactory; + @Inject TaskEnqueuer taskEnqueuer; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject @Config("rdeBucket") String bucket; + @Inject @Config("rdeInterval") Duration interval; + @Inject @Config("rdeUploadLockTimeout") Duration timeout; + @Inject @Config("rdeUploadSftpCooldown") Duration sftpCooldown; + @Inject @Config("rdeUploadUrl") URI uploadUrl; + @Inject @Key("rdeReceiverKey") PGPPublicKey receiverKey; + @Inject @Key("rdeSigningKey") PGPKeyPair signingKey; + @Inject @Key("rdeStagingDecryptionKey") PGPPrivateKey stagingDecryptionKey; + @Inject @Named("rde-report") Queue reportQueue; + @Inject RdeUploadTask() {} + + @Override + public void run() { + runner.lockRunAndRollForward(this, Registry.get(tld), timeout, CursorType.RDE_UPLOAD, interval); + taskEnqueuer.enqueue( + reportQueue, + withUrl(RdeReportTask.PATH).param(RequestParameters.PARAM_TLD, tld)); + } + + @Override + public void runWithLock(DateTime watermark) throws Exception { + DateTime stagingCursor = + RegistryCursor.load(Registry.get(tld), CursorType.RDE_STAGING).or(START_OF_TIME); + if (!stagingCursor.isAfter(watermark)) { + logger.infofmt("tld=%s uploadCursor=%s stagingCursor=%s", tld, watermark, stagingCursor); + throw new ServiceUnavailableException("Waiting for RdeStagingTask to complete"); + } + DateTime sftpCursor = + RegistryCursor.load(Registry.get(tld), CursorType.RDE_UPLOAD_SFTP).or(START_OF_TIME); + if (sftpCursor.plus(sftpCooldown).isAfter(clock.nowUtc())) { + // Fail the task good and hard so it retries until the cooldown passes. + logger.infofmt("tld=%s cursor=%s sftpCursor=%s", tld, watermark, sftpCursor); + throw new ServiceUnavailableException("SFTP cooldown has not yet passed"); + } + int revision = RdeRevision.getNextRevision(tld, watermark, FULL) - 1; + verify(revision >= 0, "RdeRevision was not set on generated deposit"); + String name = RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, revision); + GcsFilename xmlFilename = new GcsFilename(bucket, name + ".xml.ghostryde"); + GcsFilename xmlLengthFilename = new GcsFilename(bucket, name + ".xml.length"); + GcsFilename reportFilename = new GcsFilename(bucket, name + "-report.xml.ghostryde"); + verifyFileExists(xmlFilename); + verifyFileExists(xmlLengthFilename); + verifyFileExists(reportFilename); + upload(xmlFilename, readXmlLength(xmlLengthFilename), watermark, name); + ofy().transact(new VoidWork() { + @Override + public void vrun() { + RegistryCursor.save( + Registry.get(tld), CursorType.RDE_UPLOAD_SFTP, ofy().getTransactionTime()); + } + }); + response.setContentType(PLAIN_TEXT_UTF_8); + response.setPayload(String.format("OK %s %s\n", tld, watermark)); + } + + /** + * Performs a blocking upload of a cloud storage XML file to escrow provider, converting + * it to the RyDE format along the way by applying tar+compress+encrypt+sign, and saving the + * created RyDE file on GCS for future reference. + * + *

This is done by layering a bunch of {@link java.io.FilterOutputStream FilterOutputStreams} + * on top of each other in reverse order that turn XML bytes into a RyDE file while + * simultaneously uploading it to the SFTP endpoint, and then using {@link ByteStreams#copy} to + * blocking-copy bytes from the cloud storage {@code InputStream} to the RyDE/SFTP pipeline. + * + *

In psuedoshell, the whole process looks like the following: + * + *

   {@code
+   *   gcs read $xmlFile \                                   # Get GhostRyDE from cloud storage.
+   *     | decrypt | decompress \                            # Convert it to XML.
+   *     | tar | file | compress | encrypt | sign /tmp/sig \ # Convert it to a RyDE file.
+   *     | tee gs://bucket/$rydeFilename.ryde \              # Save a copy of the RyDE file to GCS.
+   *     | sftp put $dstUrl/$rydeFilename.ryde \             # Upload to SFTP server.
+   *    && sftp put $dstUrl/$rydeFilename.sig  gs://bucket/$rydeFilename.sig      # Save a copy of signature to GCS.
+   *   }
+ */ + private void upload( + GcsFilename xmlFile, long xmlLength, DateTime watermark, String name) throws Exception { + logger.infofmt("Uploading %s to %s", xmlFile, uploadUrl); + try (InputStream gcsInput = gcsUtils.openInputStream(xmlFile); + Ghostryde.Decryptor decryptor = ghostryde.openDecryptor(gcsInput, stagingDecryptionKey); + Ghostryde.Decompressor decompressor = ghostryde.openDecompressor(decryptor); + Ghostryde.Input xmlInput = ghostryde.openInput(decompressor)) { + try (JSchSshSession session = jschSshSessionFactory.create(jsch, uploadUrl); + JSchSftpChannel ftpChan = session.openSftpChannel()) { + byte[] signature; + String rydeFilename = name + ".ryde"; + GcsFilename rydeGcsFilename = new GcsFilename(bucket, rydeFilename); + try (OutputStream ftpOutput = ftpChan.get().put(rydeFilename, OVERWRITE); + OutputStream gcsOutput = gcsUtils.openOutputStream(rydeGcsFilename); + TeeOutputStream teeOutput = new TeeOutputStream(asList(ftpOutput, gcsOutput)); + RydePgpSigningOutputStream signer = pgpSigningFactory.create(teeOutput, signingKey)) { + try (OutputStream encryptLayer = pgpEncryptionFactory.create(signer, receiverKey); + OutputStream kompressor = pgpCompressionFactory.create(encryptLayer); + OutputStream fileLayer = pgpFileFactory.create(kompressor, watermark, name + ".tar"); + OutputStream tarLayer = + tarFactory.create(fileLayer, xmlLength, watermark, name + ".xml")) { + ByteStreams.copy(xmlInput, tarLayer); + } + signature = signer.getSignature(); + logger.infofmt("uploaded %,d bytes: %s.ryde", signer.getBytesWritten(), name); + } + String sigFilename = name + ".sig"; + gcsUtils.createFromBytes(new GcsFilename(bucket, sigFilename), signature); + ftpChan.get().put(new ByteArrayInputStream(signature), sigFilename); + logger.infofmt("uploaded %,d bytes: %s.sig", signature.length, name); + } + } + } + + /** Reads the contents of a file from Cloud Storage that contains nothing but an integer. */ + private long readXmlLength(GcsFilename xmlLengthFilename) throws IOException { + try (InputStream input = gcsUtils.openInputStream(xmlLengthFilename)) { + return Long.parseLong(new String(ByteStreams.toByteArray(input), UTF_8).trim()); + } + } + + private void verifyFileExists(GcsFilename filename) { + verify(gcsUtils.existsAndNotEmpty(filename), "Missing file: %s", filename); + } +} diff --git a/java/com/google/domain/registry/rde/RdeUploadUrl.java b/java/com/google/domain/registry/rde/RdeUploadUrl.java new file mode 100644 index 000000000..316a2db55 --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeUploadUrl.java @@ -0,0 +1,216 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.util.Map; +import java.util.Objects; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Class representing the remote destination for a deposit upload (like an SFTP server). + * + *

This class provides validity contracts, default values, and syntactic sugar which make it + * preferable to using a plain {@link URI}. + * + * @see java.net.URI + * @see RdeUploadTask + */ +@Immutable +final class RdeUploadUrl implements Comparable { + + public static final Protocol SFTP = new Protocol("sftp", 22); + private static final Map ALLOWED_PROTOCOLS = ImmutableMap.of("sftp", SFTP); + + private final Protocol protocol; + private final URI uri; + + /** + * Constructs and validates a new {@link RdeUploadUrl} instance. + * + * @see java.net.URI#create(String) + */ + public static RdeUploadUrl create(URI uri) { + checkArgument(!isNullOrEmpty(uri.getScheme()) && !isNullOrEmpty(uri.getHost()), + "Incomplete url: %s", uri); + Protocol protocol = ALLOWED_PROTOCOLS.get(uri.getScheme()); + checkArgument(protocol != null, "Unsupported scheme: %s", uri); + return new RdeUploadUrl(protocol, uri); + } + + /** @see #create(URI) */ + private RdeUploadUrl(Protocol protocol, URI uri) { + this.protocol = checkNotNull(protocol, "protocol"); + this.uri = checkNotNull(uri, "uri"); + } + + /** Returns username from URL userinfo. */ + public Optional getUser() { + String userInfo = uri.getUserInfo(); + if (isNullOrEmpty(userInfo)) { + return Optional.absent(); + } + int idx = userInfo.indexOf(':'); + if (idx != -1) { + return Optional.of(userInfo.substring(0, idx)); + } else { + return Optional.of(userInfo); + } + } + + /** Returns password from URL userinfo (if specified). */ + public Optional getPass() { + String userInfo = uri.getUserInfo(); + if (isNullOrEmpty(userInfo)) { + return Optional.absent(); + } + int idx = userInfo.indexOf(':'); + if (idx != -1) { + return Optional.of(userInfo.substring(idx + 1)); + } else { + return Optional.absent(); + } + } + + /** Returns hostname or IP without port. */ + public String getHost() { + return uri.getHost(); + } + + /** Returns network port or default for protocol if not specified. */ + public int getPort() { + return uri.getPort() != -1 ? uri.getPort() : getProtocol().getPort(); + } + + /** Returns the protocol of this URL. */ + public Protocol getProtocol() { + return protocol; + } + + /** Returns path element of URL (if present). */ + public Optional getPath() { + String path = uri.getPath(); + if (isNullOrEmpty(path) || path.equals("/")) { + return Optional.absent(); + } else { + return Optional.of(path.substring(1)); + } + } + + /** Returns URL as ASCII text with password concealed (if any). */ + @Override + public String toString() { + String result = getProtocol().getName() + "://"; + if (getUser().isPresent()) { + result += urlencode(getUser().get()); + if (getPass().isPresent()) { + result += ":****"; + } + result += "@"; + } + result += getHost(); + if (getPort() != getProtocol().getPort()) { + result += String.format(":%d", getPort()); + } + result += "/"; + result += getPath().or(""); + return result; + } + + /** + * Simplified wrapper around Java's daft URL encoding API. + * + * @return an ASCII string that's escaped in a conservative manner for safe storage within any + * component of a URL. Non-ASCII characters are converted to UTF-8 bytes before being + * encoded. No choice of charset is provided because the W3C says we should use UTF-8. + * @see URLEncoder#encode(String, String) + */ + private static String urlencode(String str) { + try { + return URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + /** @see java.net.URI#compareTo(java.net.URI) */ + @Override + public int compareTo(RdeUploadUrl rhs) { + return uri.compareTo(checkNotNull(rhs).uri); + } + + /** @see java.net.URI#equals(Object) */ + @Override + public boolean equals(@Nullable Object object) { + return object == this + || object instanceof RdeUploadUrl + && Objects.equals(uri, ((RdeUploadUrl) object).uri); + } + + /** @see java.net.URI#hashCode() */ + @Override + public int hashCode() { + return Objects.hashCode(uri); + } + + /** Used to store default settings for {@link #ALLOWED_PROTOCOLS}. */ + @Immutable + public static final class Protocol { + private final String name; + private final int port; + + public Protocol(String name, int port) { + checkArgument(0 < port && port < 65536, "bad port: %s", port); + this.name = checkNotNull(name, "name"); + this.port = port; + } + + /** Returns lowercase name of protocol. */ + public String getName() { + return name; + } + + /** Returns the standardized port number assigned to this protocol. */ + public int getPort() { + return port; + } + + /** @see Object#equals(Object) */ + @Override + public boolean equals(@Nullable Object object) { + return object == this + || object instanceof Protocol + && port == ((Protocol) object).port + && Objects.equals(name, ((Protocol) object).name); + } + + /** @see Object#hashCode() */ + @Override + public int hashCode() { + return Objects.hash(name, port); + } + } +} diff --git a/java/com/google/domain/registry/rde/RdeUtil.java b/java/com/google/domain/registry/rde/RdeUtil.java new file mode 100644 index 000000000..103babcff --- /dev/null +++ b/java/com/google/domain/registry/rde/RdeUtil.java @@ -0,0 +1,99 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.domain.registry.util.HexDumper.dumpHex; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.io.BaseEncoding; +import com.google.domain.registry.xjc.rde.XjcRdeRrType; +import com.google.domain.registry.xml.XmlException; + +import org.joda.time.DateTime; +import org.joda.time.ReadableInstant; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Helper methods for RDE. */ +public final class RdeUtil { + + /** Number of bytes in head of XML deposit that will contain the information we want. */ + private static final int PEEK_SIZE = 2048; + + /** Regular expression for extracting creation timestamp from a raw XML deposit. */ + private static final Pattern WATERMARK_PATTERN = Pattern.compile("[<:]watermark>\\s*([^<\\s]+)"); + + /** Standard ISO date/time formatter without milliseconds. Used for watermarks. */ + private static final DateTimeFormatter DATETIME_FORMATTER = + ISODateTimeFormat.dateTimeNoMillis().withZoneUTC(); + + /** + * Look at some bytes from {@code xmlInput} to ensure it appears to be a FULL XML deposit and + * then use a regular expression to extract the watermark timestamp which is returned. + * + * @throws IOException + * @throws XmlException + */ + public static DateTime peekWatermark(BufferedInputStream xmlInput) + throws IOException, XmlException { + xmlInput.mark(PEEK_SIZE); + byte[] peek = new byte[PEEK_SIZE]; + if (xmlInput.read(peek) != PEEK_SIZE) { + throw new IOException(String.format("Failed to peek %,d bytes on input file", PEEK_SIZE)); + } + xmlInput.reset(); + String peekStr = new String(peek, UTF_8); + if (!peekStr.contains("urn:ietf:params:xml:ns:rde-1.0")) { + throw new XmlException(String.format( + "Does not appear to be an XML RDE deposit\n%s", dumpHex(peek))); + } + if (!peekStr.contains("type=\"FULL\"")) { + throw new XmlException("Only FULL XML RDE deposits suppported at this time"); + } + Matcher watermarkMatcher = WATERMARK_PATTERN.matcher(peekStr); + if (!watermarkMatcher.find()) { + throw new XmlException("Could not find RDE watermark in XML"); + } + DateTime watermark = DATETIME_FORMATTER.parseDateTime(watermarkMatcher.group(1)); + return watermark; + } + + /** + * Generates an ID matching the regex {@code \w{1,13} } from a millisecond + * timestamp. + * + *

This routine works by turning the number of UTC milliseconds from the UNIX epoch into a + * big-endian byte-array which is then converted to a base32 string without padding that's no + * longer than 13 chars because {@code 13 = Ceiling[Log[32, 2^64]]}. How lucky! + */ + public static String timestampToId(ReadableInstant timestamp) { + byte[] bytes = ByteBuffer.allocate(8).putLong(timestamp.getMillis()).array(); + return BaseEncoding.base32().omitPadding().encode(bytes); + } + + static XjcRdeRrType makeXjcRdeRrType(String clientId) { + XjcRdeRrType bean = new XjcRdeRrType(); + bean.setValue(clientId); + return bean; + } + + private RdeUtil() {} +} diff --git a/java/com/google/domain/registry/rde/RegistrarToXjcConverter.java b/java/com/google/domain/registry/rde/RegistrarToXjcConverter.java new file mode 100644 index 000000000..79f83c9cc --- /dev/null +++ b/java/com/google/domain/registry/rde/RegistrarToXjcConverter.java @@ -0,0 +1,187 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.MoreObjects.firstNonNull; + +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.RegistrarAddress; +import com.google.domain.registry.xjc.contact.XjcContactE164Type; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrar; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarAddrType; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarElement; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarPostalInfoEnumType; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarPostalInfoType; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarStatusType; +import com.google.domain.registry.xjc.rderegistrar.XjcRdeRegistrarWhoisInfoType; + +import java.math.BigInteger; + +/** Utility class that turns {@link Registrar} as {@link XjcRdeRegistrarElement}. */ +final class RegistrarToXjcConverter { + + private static final String UNKNOWN_EMAIL = "unknown@crr.com"; + private static final String UNKNOWN_CITY = "Unknown"; + private static final String UNKNOWN_ZIP = "00000"; + private static final String UNKNOWN_CC = "US"; + + /** Converts {@link Registrar} to {@link XjcRdeRegistrarElement}. */ + static XjcRdeRegistrarElement convert(Registrar registrar) { + return new XjcRdeRegistrarElement(convertRegistrar(registrar)); + } + + /** Converts {@link Registrar} to {@link XjcRdeRegistrar}. */ + static XjcRdeRegistrar convertRegistrar(Registrar model) { + XjcRdeRegistrar bean = new XjcRdeRegistrar(); + + // o An element that contains the Registry-unique identifier of + // the registrar object. This has a superordinate relationship + // to a subordinate , or of domain, contact and + // host objects. + bean.setId(model.getClientIdentifier()); + + // o An element that contains the name of the registrar. + bean.setName(model.getRegistrarName()); + + // o An OPTIONAL element that contains the ID assigned by + // ICANN. + Long ianaId = model.getIanaIdentifier(); + if (ianaId != null) { + bean.setGurid(BigInteger.valueOf(ianaId)); + } + + // o A element that contains the operational status of the + // registrar. Possible values are: ok, readonly and terminated. + switch (model.getState()) { + case ACTIVE: + bean.setStatus(XjcRdeRegistrarStatusType.OK); + break; + case PENDING: + case SUSPENDED: + bean.setStatus(XjcRdeRegistrarStatusType.READONLY); + break; + default: + throw new IllegalStateException(String.format("Bad state: %s", model.getState())); + } + + // o One or two elements that contain postal- address + // information. Two elements are provided so that address + // information can be provided in both internationalized and + // localized forms; a "type" attribute is used to identify the two + // forms. If an internationalized form (type="int") is provided, + // element content MUST be represented in a subset of UTF-8 that can + // be represented in the 7-bit US-ASCII character set. If a + // localized form (type="loc") is provided, element content MAY be + // represented in unrestricted UTF-8. + RegistrarAddress localizedAddress = model.getLocalizedAddress(); + if (localizedAddress != null) { + bean.getPostalInfos().add(convertPostalInfo(false, localizedAddress)); + } + RegistrarAddress internationalizedAddress = model.getInternationalizedAddress(); + if (internationalizedAddress != null) { + bean.getPostalInfos().add(convertPostalInfo(true, internationalizedAddress)); + } + + // o An OPTIONAL element that contains the registrar's voice + // telephone number. + // XXX: Make Registrar use PhoneNumber. + if (model.getPhoneNumber() != null) { + XjcContactE164Type phone = new XjcContactE164Type(); + phone.setValue(model.getPhoneNumber()); + bean.setVoice(phone); + } + + // o An OPTIONAL element that contains the registrar's facsimile + // telephone number. + if (model.getFaxNumber() != null) { + XjcContactE164Type fax = new XjcContactE164Type(); + fax.setValue(model.getFaxNumber()); + bean.setFax(fax); + } + + // o An element that contains the registrar's email address. + bean.setEmail(firstNonNull(model.getEmailAddress(), UNKNOWN_EMAIL)); + + // o An OPTIONAL element that contains the registrar's URL. + bean.setUrl(model.getUrl()); + + // o An OPTIONAL elements that contains whois information. + // The element contains the following child elements: + // + // * An OPTIONAL element that contains the name of the + // registrar WHOIS server listening on TCP port 43 as specified in + // [RFC3912]. + // + // * An OPTIONAL element that contains the name of the + // registrar WHOIS server listening on TCP port 80/443. + if (model.getWhoisServer() != null) { + XjcRdeRegistrarWhoisInfoType whoisInfo = new XjcRdeRegistrarWhoisInfoType(); + whoisInfo.setName(model.getWhoisServer()); + bean.setWhoisInfo(whoisInfo); + } + + // o A element that contains the date and time of registrar- + // object creation. + bean.setCrDate(model.getCreationTime()); + + // o An OPTIONAL element that contains the date and time of + // the most recent RDE registrar-object modification. This element + // MUST NOT be present if the rdeRegistrar object has never been + // modified. + bean.setUpDate(model.getLastUpdateTime()); + + return bean; + } + + private static XjcRdeRegistrarPostalInfoType convertPostalInfo( + boolean isInt, RegistrarAddress model) { + XjcRdeRegistrarPostalInfoType bean = new XjcRdeRegistrarPostalInfoType(); + bean.setType(isInt + ? XjcRdeRegistrarPostalInfoEnumType.INT + : XjcRdeRegistrarPostalInfoEnumType.LOC); + bean.setAddr(convertAddress(model)); + return bean; + } + + private static XjcRdeRegistrarAddrType convertAddress(RegistrarAddress model) { + XjcRdeRegistrarAddrType bean = new XjcRdeRegistrarAddrType(); + + // * A element that contains address information associated + // with the registrar. The element contains the following + // child elements: + // + // + One, two, or three OPTIONAL elements that contain + // the registrar's street address. + bean.getStreets().addAll(model.getStreet()); + + // + A element that contains the registrar's city. + bean.setCity(firstNonNull(model.getCity(), UNKNOWN_CITY)); + + // + An OPTIONAL element that contains the registrar's state + // or province. + bean.setSp(model.getState()); + + // + An OPTIONAL element that contains the registrar's + // postal code. + bean.setPc(firstNonNull(model.getZip(), UNKNOWN_ZIP)); + + // + A element that contains the registrar's country code. + bean.setCc(firstNonNull(model.getCountryCode(), UNKNOWN_CC)); + + return bean; + } + + private RegistrarToXjcConverter() {} +} diff --git a/java/com/google/domain/registry/rde/RydePgpCompressionOutputStream.java b/java/com/google/domain/registry/rde/RydePgpCompressionOutputStream.java new file mode 100644 index 000000000..7faae41af --- /dev/null +++ b/java/com/google/domain/registry/rde/RydePgpCompressionOutputStream.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static org.bouncycastle.bcpg.CompressionAlgorithmTags.ZIP; + +import com.google.auto.factory.AutoFactory; +import com.google.auto.factory.Provided; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.ImprovedOutputStream; + +import org.bouncycastle.openpgp.PGPCompressedDataGenerator; +import org.bouncycastle.openpgp.PGPException; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.annotation.WillNotClose; + +/** + * OpenPGP compression service that wraps an {@link OutputStream}. + * + *

This uses the ZIP compression algorithm per the ICANN escrow specification. + */ +@AutoFactory(allowSubclasses = true) +public class RydePgpCompressionOutputStream extends ImprovedOutputStream { + + /** + * Creates a new instance that compresses data. + * + * @param os is the upstream {@link OutputStream} which is not closed by this object + * @throws RuntimeException to rethrow {@link PGPException} and {@link IOException} + */ + public RydePgpCompressionOutputStream( + @Provided @Config("rdeRydeBufferSize") Integer bufferSize, + @WillNotClose OutputStream os) { + super(createDelegate(bufferSize, os)); + } + + private static OutputStream createDelegate(int bufferSize, OutputStream os) { + try { + return new PGPCompressedDataGenerator(ZIP).open(os, new byte[bufferSize]); + } catch (IOException | PGPException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/rde/RydePgpEncryptionOutputStream.java b/java/com/google/domain/registry/rde/RydePgpEncryptionOutputStream.java new file mode 100644 index 000000000..c4cd35362 --- /dev/null +++ b/java/com/google/domain/registry/rde/RydePgpEncryptionOutputStream.java @@ -0,0 +1,120 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags.AES_128; +import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; + +import com.google.auto.factory.AutoFactory; +import com.google.auto.factory.Provided; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.ImprovedOutputStream; + +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; + +import java.io.IOException; +import java.io.OutputStream; +import java.security.NoSuchAlgorithmException; +import java.security.ProviderException; +import java.security.SecureRandom; + +import javax.annotation.WillNotClose; + +/** + * OpenPGP encryption service that wraps an {@link OutputStream}. + * + *

This uses 128-bit AES (Rijndael) as the symmetric encryption algorithm. This is the only key + * strength ICANN allows. The other valid algorithms are TripleDES and CAST5 per RFC 4880. It's + * probably for the best that we're not using AES-256 since it's been weakened over the years to + * potentially being worse than AES-128. + * + *

The key for the symmetric algorithm is generated by a random number generator which SHOULD + * come from {@code /dev/random} (see: {@link sun.security.provider.NativePRNG}) but Java doesn't + * offer any guarantees that {@link SecureRandom} isn't pseudo-random. + * + *

The asymmetric algorithm is whatever one is associated with the {@link PGPPublicKey} object + * you provide. That should be either RSA or DSA, per the ICANN escrow spec. The underlying + * {@link PGPEncryptedDataGenerator} class uses PGP Cipher Feedback Mode to chain blocks. No + * integrity packet is used. + * + * @see RFC 4880 (OpenPGP Message Format) + * @see AES (Wikipedia) + */ +@AutoFactory(allowSubclasses = true) +public class RydePgpEncryptionOutputStream extends ImprovedOutputStream { + + /** + * The symmetric encryption algorithm to use. Do not change this value without checking the + * RFCs to make sure the encryption algorithm and strength combination is allowed. + * + * @see org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags + */ + private static final int CIPHER = AES_128; + + /** + * This option adds an additional checksum to the OpenPGP message. From what I can tell, this is + * meant to fix a bug that made a certain type of message tampering possible. GPG will actually + * complain on the command line when decrypting a message without this feature. + * + *

However I'm reasonably certain that this is not required if you have a signature (and + * remember to use it!) and the ICANN requirements document do not mention this. So we're going + * to leave it out. + */ + private static final boolean USE_INTEGRITY_PACKET = false; + + /** + * The source of random bits. This should not be changed at Google because it uses dev random + * in production, and the testing environment is configured to make this go fast and not drain + * system entropy. + * + * @see SecureRandom#getInstance(String) + */ + private static final String RANDOM_SOURCE = "NativePRNG"; + + /** + * Creates a new instance that encrypts data for the owner of {@code receiverKey}. + * + * @param os is the upstream {@link OutputStream} which is not closed by this object + * @throws IllegalArgumentException if {@code publicKey} is invalid + * @throws RuntimeException to rethrow {@link PGPException} and {@link IOException} + */ + public RydePgpEncryptionOutputStream( + @Provided @Config("rdeRydeBufferSize") Integer bufferSize, + @WillNotClose OutputStream os, + PGPPublicKey receiverKey) { + super(createDelegate(bufferSize, os, receiverKey)); + } + + private static + OutputStream createDelegate(int bufferSize, OutputStream os, PGPPublicKey receiverKey) { + try { + PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator( + new JcePGPDataEncryptorBuilder(CIPHER) + .setWithIntegrityPacket(USE_INTEGRITY_PACKET) + .setSecureRandom(SecureRandom.getInstance(RANDOM_SOURCE)) + .setProvider(PROVIDER_NAME)); + encryptor.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(receiverKey)); + return encryptor.open(os, new byte[bufferSize]); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException(e); + } catch (IOException | PGPException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/rde/RydePgpFileOutputStream.java b/java/com/google/domain/registry/rde/RydePgpFileOutputStream.java new file mode 100644 index 000000000..c8871463a --- /dev/null +++ b/java/com/google/domain/registry/rde/RydePgpFileOutputStream.java @@ -0,0 +1,71 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.bouncycastle.openpgp.PGPLiteralData.BINARY; + +import com.google.auto.factory.AutoFactory; +import com.google.auto.factory.Provided; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.util.ImprovedOutputStream; + +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.joda.time.DateTime; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.annotation.WillNotClose; + +/** + * OpenPGP literal data layer generator that wraps {@link OutputStream}. + * + *

OpenPGP messages are like an onion; there can be many layers like compression and encryption. + * It's important to wrap out plaintext in a literal data layer such as this so the code that's + * unwrapping the onion knows when to stop. + * + *

According to escrow spec, the PGP message should contain a single tar file. + */ +@AutoFactory(allowSubclasses = true) +public class RydePgpFileOutputStream extends ImprovedOutputStream { + + /** + * Creates a new instance for a particular file. + * + * @param os is the upstream {@link OutputStream} which is not closed by this object + * @throws IllegalArgumentException if {@code filename} isn't a {@code .tar} file + * @throws RuntimeException to rethrow {@link IOException} + */ + public RydePgpFileOutputStream( + @Provided @Config("rdeRydeBufferSize") Integer bufferSize, + @WillNotClose OutputStream os, + DateTime modified, + String filename) { + super(createDelegate(bufferSize, os, modified, filename)); + } + + private static OutputStream + createDelegate(int bufferSize, OutputStream os, DateTime modified, String filename) { + try { + checkArgument(filename.endsWith(".tar"), + "Ryde PGP message should contain a tar file."); + return new PGPLiteralDataGenerator().open( + os, BINARY, filename, modified.toDate(), new byte[bufferSize]); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/rde/RydePgpSigningOutputStream.java b/java/com/google/domain/registry/rde/RydePgpSigningOutputStream.java new file mode 100644 index 000000000..0871caa81 --- /dev/null +++ b/java/com/google/domain/registry/rde/RydePgpSigningOutputStream.java @@ -0,0 +1,112 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static org.bouncycastle.bcpg.HashAlgorithmTags.SHA256; +import static org.bouncycastle.bcpg.PublicKeyAlgorithmTags.RSA_GENERAL; +import static org.bouncycastle.openpgp.PGPSignature.BINARY_DOCUMENT; + +import com.google.auto.factory.AutoFactory; +import com.google.domain.registry.util.ImprovedOutputStream; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; + +import javax.annotation.WillNotClose; + +/** + * OpenPGP detached signing service that wraps an {@link OutputStream}. + * + *

This is the outermost layer. It signs the resulting file without modifying its bytes, + * instead generating an out-of-band {@code .asc} signature file. This is basically a SHA-256 + * checksum of the deposit file that's signed with our RSA private key. This allows the people + * who receive a deposit to check the signature against our public key so they can know the + * data hasn't been forged. + */ +@AutoFactory(allowSubclasses = true) +public class RydePgpSigningOutputStream extends ImprovedOutputStream { + + private final PGPSignatureGenerator signer; + + /** + * Create a signer that wraps {@code os} and generates a detached signature using + * {@code signingKey}. After closing, you should call {@link #getSignature()} to get the detached + * signature. + * + * @param os is the upstream {@link OutputStream} which is not closed by this object + * @throws RuntimeException to rethrow {@link PGPException} + */ + public RydePgpSigningOutputStream( + @WillNotClose OutputStream os, + PGPKeyPair signingKey) { + super(os, false, -1); + try { + signer = new PGPSignatureGenerator( + new BcPGPContentSignerBuilder(RSA_GENERAL, SHA256)); + signer.init(BINARY_DOCUMENT, signingKey.getPrivateKey()); + } catch (PGPException e) { + throw new RuntimeException(e); + } + addUserInfoToSignature(signingKey.getPublicKey(), signer); + } + + /** Returns the byte contents for the detached {@code .asc} signature file. */ + public byte[] getSignature() throws IOException, PGPException { + return signer.generate().getEncoded(); + } + + /** @see ImprovedOutputStream#write(int) */ + @Override + public void write(int b) throws IOException { + super.write(b); + signer.update((byte) b); + } + + /** @see ImprovedOutputStream#write(byte[], int, int) */ + @Override + public void write(byte[] b, int off, int len) throws IOException { + super.write(b, off, len); + signer.update(b, off, len); + } + + /** + * Add user ID to signature file. + * + *

This adds information about the identity of the signer to the signature file. It's not + * required, but I'm guessing it could be a lifesaver if somewhere down the road, people lose + * track of the public keys and need to figure out how to verify a couple blobs. This would at + * least tell them which key to download from the MIT keyserver. + * + *

But the main reason why I'm using this is because I copied it from the code of another + * googler who was also uncertain about the precise reason why it's needed. + */ + private static void addUserInfoToSignature(PGPPublicKey publicKey, PGPSignatureGenerator signer) { + @SuppressWarnings("unchecked") // safe by specification. + Iterator uidIter = publicKey.getUserIDs(); + if (uidIter.hasNext()) { + PGPSignatureSubpacketGenerator spg = new PGPSignatureSubpacketGenerator(); + spg.setSignerUserID(false, uidIter.next()); + signer.setHashedSubpackets(spg.generate()); + } + } +} diff --git a/java/com/google/domain/registry/rde/RydeTarOutputStream.java b/java/com/google/domain/registry/rde/RydeTarOutputStream.java new file mode 100644 index 000000000..e7c5cd96a --- /dev/null +++ b/java/com/google/domain/registry/rde/RydeTarOutputStream.java @@ -0,0 +1,70 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.rde; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.factory.AutoFactory; +import com.google.domain.registry.util.ImprovedOutputStream; +import com.google.domain.registry.util.PosixTarHeader; + +import org.joda.time.DateTime; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.annotation.WillNotClose; + +/** + * Single-file POSIX tar archive creator that wraps an {@link OutputStream}. + */ +@AutoFactory(allowSubclasses = true) +public class RydeTarOutputStream extends ImprovedOutputStream { + + /** + * Creates a new instance that outputs a tar archive. + * + * @param os is the upstream {@link OutputStream} which is not closed by this object + * @param size is the length in bytes of the one file, which you will write to this object + * @param modified is the {@link PosixTarHeader.Builder#setMtime mtime} you want to set + * @param filename is the name of the one file that will be contained in this archive + * @throws RuntimeException to rethrow {@link IOException} + * @throws IllegalArgumentException if {@code size} is negative + */ + public RydeTarOutputStream( + @WillNotClose OutputStream os, long size, DateTime modified, String filename) { + super(os, false, size); + checkArgument(size >= 0); + checkArgument(filename.endsWith(".xml"), + "Ryde expects tar archive to contain a filename with an '.xml' extension."); + try { + os.write(new PosixTarHeader.Builder() + .setName(filename) + .setSize(size) + .setMtime(modified) + .build() + .getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** Writes the end of archive marker. */ + @Override + public void onClose() throws IOException { + // Round up to a 512-byte boundary and another 1024-bytes to indicate end of archive. + write(new byte[1024 + 512 - (int) (getBytesWritten() % 512L)]); + } +} diff --git a/java/com/google/domain/registry/rde/package-info.java b/java/com/google/domain/registry/rde/package-info.java new file mode 100644 index 000000000..e057272fb --- /dev/null +++ b/java/com/google/domain/registry/rde/package-info.java @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +/** + * Registry Data Escrow + * + *

This is a cron job that puts our database in a giant XML file and uploads it to a third party. + * Read the {@link com.google.domain.registry.rde.RdeStagingAction RdeStagingAction} javadoc to + * learn more. + */ +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.rde; diff --git a/java/com/google/domain/registry/request/Action.java b/java/com/google/domain/registry/request/Action.java new file mode 100644 index 000000000..a2006c249 --- /dev/null +++ b/java/com/google/domain/registry/request/Action.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotation for {@link Runnable} actions accepting HTTP requests from {@link RequestHandler}. */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Action { + + /** HTTP methods recognized by the request processor. */ + public enum Method { GET, HEAD, POST } + + /** HTTP path to serve the action from. The path components must be percent-escaped. */ + String path(); + + /** Indicates all paths starting with this path should be accepted. */ + boolean isPrefix() default false; + + /** HTTP methods that request processor should allow. */ + Method[] method() default Method.GET; + + /** + * Indicates request processor should print "OK" to the HTTP client on success. + * + *

This is important because it's confusing to manually invoke a backend task and have a blank + * page show up. And it's not worth injecting a {@link Response} object just to do something so + * trivial. + */ + boolean automaticallyPrintOk() default false; + + // TODO(b/26304887): Flip default to true. + /** Enables XSRF protection on all HTTP methods except GET and HEAD. */ + boolean xsrfProtection() default false; + + /** Arbitrary value included in the XSRF token hash. */ + String xsrfScope() default "app"; + + /** + * Require user be logged-in or 302 redirect to the Google auth login page. + * + *

Warning: DO NOT use this for cron and task queue endpoints. + * + *

Note: Logged-in actions should also be guarded by a {@code } in + * {@code web.xml} with {@code *}. + */ + boolean requireLogin() default false; +} diff --git a/java/com/google/domain/registry/request/Actions.java b/java/com/google/domain/registry/request/Actions.java new file mode 100644 index 000000000..6b2c87c74 --- /dev/null +++ b/java/com/google/domain/registry/request/Actions.java @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.base.Preconditions.checkArgument; + +/** Helper methods for working with {@link Action @Action}-annotated classes. */ +public final class Actions { + + /** Extracts the action path from the {@link Action @Action} annotation. */ + public static String getPathForAction(Class action) { + checkArgument( + action.isAnnotationPresent(Action.class), + "Cannot get path of class without @Action annotation: %s", action); + return action.getAnnotation(Action.class).path(); + } + + private Actions() {} +} diff --git a/java/com/google/domain/registry/request/BUILD b/java/com/google/domain/registry/request/BUILD new file mode 100644 index 000000000..9cffb1691 --- /dev/null +++ b/java/com/google/domain/registry/request/BUILD @@ -0,0 +1,46 @@ +package(default_visibility = ["//java/com/google/domain/registry:registry_project"]) + + +java_library( + name = "request", + srcs = glob( + ["*.java"], + exclude = ["Modules.java"], + ), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/security", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/auto:auto_value", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/servlet/servlet_api", + ], +) + +java_library( + name = "modules", + srcs = ["Modules.java"], + deps = [ + ":request", + "//java/com/google/api/client/extensions/appengine/http", + "//java/com/google/api/client/googleapis/auth/oauth2", + "//java/com/google/api/client/googleapis/extensions/appengine/auth/oauth2", + "//java/com/google/api/client/http", + "//java/com/google/api/client/json", + "//java/com/google/api/client/json/jackson2", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/keyring/api", + "//third_party/java/appengine:appengine-api", + "//third_party/java/dagger", + ], +) diff --git a/java/com/google/domain/registry/request/DelegatedOAuthScopes.java b/java/com/google/domain/registry/request/DelegatedOAuthScopes.java new file mode 100644 index 000000000..b920b637d --- /dev/null +++ b/java/com/google/domain/registry/request/DelegatedOAuthScopes.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; +import java.util.Set; + +import javax.inject.Qualifier; + +/** + * Dagger qualifier for the {@link Set} of OAuth2 scope strings used for authorization on APIs that + * are connected to using a delegated user account (the serviceAccountUser in GoogleCredential). + */ +@Qualifier +@Documented +public @interface DelegatedOAuthScopes {} diff --git a/java/com/google/domain/registry/request/Header.java b/java/com/google/domain/registry/request/Header.java new file mode 100644 index 000000000..6b9de9ebc --- /dev/null +++ b/java/com/google/domain/registry/request/Header.java @@ -0,0 +1,26 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** Dagger qualifier for HTTP headers. */ +@Qualifier +@Documented +public @interface Header { + String value(); +} diff --git a/java/com/google/domain/registry/request/HttpException.java b/java/com/google/domain/registry/request/HttpException.java new file mode 100644 index 000000000..6388335d6 --- /dev/null +++ b/java/com/google/domain/registry/request/HttpException.java @@ -0,0 +1,229 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.html.HtmlEscapers.htmlEscaper; + +import com.google.domain.registry.util.FormattingLogger; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +/** Base for exceptions that cause an HTTP error response. */ +public abstract class HttpException extends RuntimeException { + + // as per https://tools.ietf.org/html/rfc4918 + private static final int SC_UNPROCESSABLE_ENTITY = 422; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private final int responseCode; + + protected HttpException(int responseCode, String message, Throwable cause) { + super(message, cause); + this.responseCode = responseCode; + } + + public final int getResponseCode() { + return responseCode; + } + + /** + * Returns the string associated with a particular response code. Unlike {@link #getMessage()}, + * which is meant to describe the circumstances under which this particular exception occurred, + * this method always returns the same string (e.g. "Not Found" for a 400 error), and so should + * always be the same for a given subclass of {@link HttpException}. + */ + public String getResponseCodeString() { + return "Response Code " + responseCode; + } + + /** + * Transmits the error response to the client. + * + *

{@link #getMessage()} will be sent to the browser, whereas {@link #toString()} and + * {@link #getCause()} will be logged. + */ + public final void send(HttpServletResponse rsp) throws IOException { + rsp.sendError(getResponseCode(), htmlEscaper().escape(getMessage())); + logger.infofmt(getCause(), "%s", this); + } + + /** + * Exception that causes a 204 response. + * + *

This is useful for App Engine task queue handlers that want to display an error, but don't + * want the task to automatically retry, since the status code is less than 300. + */ + public static final class NoContentException extends HttpException { + public NoContentException(String message) { + super(HttpServletResponse.SC_NO_CONTENT, message, null); + } + + @Override + public String getResponseCodeString() { + return "No Content"; + } + } + + /** Exception that causes a 304 response. */ + public static final class NotModifiedException extends HttpException { + public NotModifiedException() { + this("Not Modified"); + } + + public NotModifiedException(String message) { + super(HttpServletResponse.SC_NOT_FOUND, message, null); + } + + @Override + public String getResponseCodeString() { + return "Not Modified"; + } + } + + /** Exception that causes a 400 response. */ + public static final class BadRequestException extends HttpException { + public BadRequestException(String message) { + this(message, null); + } + + public BadRequestException(String message, Throwable cause) { + super(HttpServletResponse.SC_BAD_REQUEST, message, cause); + } + + @Override + public String getResponseCodeString() { + return "Bad Request"; + } + } + + /** Exception that causes a 403 response. */ + public static final class ForbiddenException extends HttpException { + public ForbiddenException(String message) { + super(HttpServletResponse.SC_FORBIDDEN, message, null); + } + + @Override + public String getResponseCodeString() { + return "Forbidden"; + } + } + + /** Exception that causes a 404 response. */ + public static final class NotFoundException extends HttpException { + public NotFoundException() { + this("Not found"); + } + + public NotFoundException(String message) { + super(HttpServletResponse.SC_NOT_FOUND, message, null); + } + + @Override + public String getResponseCodeString() { + return "Not Found"; + } + } + + /** Exception that causes a 405 response. */ + public static final class MethodNotAllowedException extends HttpException { + public MethodNotAllowedException() { + super(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method not allowed", null); + } + + @Override + public String getResponseCodeString() { + return "Method Not Allowed"; + } + } + + /** Exception that causes a 409 response. */ + public static final class ConflictException extends HttpException { + public ConflictException(String message) { + super(HttpServletResponse.SC_CONFLICT, message, null); + } + + @Override + public String getResponseCodeString() { + return "Conflict"; + } + } + + /** Exception that causes a 415 response. */ + public static final class UnsupportedMediaTypeException extends HttpException { + public UnsupportedMediaTypeException(String message) { + super(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, null); + } + + public UnsupportedMediaTypeException(String message, Throwable cause) { + super(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, cause); + } + + @Override + public String getResponseCodeString() { + return "Unsupported Media Type"; + } + } + + /** Exception that causes a 422 response. */ + public static final class UnprocessableEntityException extends HttpException { + public UnprocessableEntityException(String message) { + super(SC_UNPROCESSABLE_ENTITY, message, null); + } + + @Override + public String getResponseCodeString() { + return "Unprocessable Entity"; + } + } + + /** Exception that causes a 500 response. */ + public static final class InternalServerErrorException extends HttpException { + public InternalServerErrorException(String message) { + super(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message, null); + } + + @Override + public String getResponseCodeString() { + return "Internal Server Error"; + } + } + + /** Exception that causes a 501 response. */ + public static final class NotImplementedException extends HttpException { + public NotImplementedException(String message) { + super(HttpServletResponse.SC_NOT_IMPLEMENTED, message, null); + } + + @Override + public String getResponseCodeString() { + return "Not Implemented"; + } + } + + /** Exception that causes a 503 response. */ + public static final class ServiceUnavailableException extends HttpException { + public ServiceUnavailableException(String message) { + super(HttpServletResponse.SC_SERVICE_UNAVAILABLE, message, null); + } + + @Override + public String getResponseCodeString() { + return "Service Unavailable"; + } + } +} diff --git a/java/com/google/domain/registry/request/JsonActionRunner.java b/java/com/google/domain/registry/request/JsonActionRunner.java new file mode 100644 index 000000000..d9b9c4022 --- /dev/null +++ b/java/com/google/domain/registry/request/JsonActionRunner.java @@ -0,0 +1,50 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.base.Verify.verifyNotNull; + +import java.util.Map; + +import javax.inject.Inject; + +/** Runner for actions that read and write JSON objects. */ +public final class JsonActionRunner { + + /** Interface for actions that read and write JSON objects. */ + public interface JsonAction { + + /** + * Handles JSON HTTP request. + * + * @param json object extracted from request body + * @return an arbitrary JSON object, which is never {@code null} + * @throws HttpException to send a non-200 status code / message to client + */ + Map handleJsonRequest(Map json); + } + + @Inject @JsonPayload Map payload; + @Inject JsonResponse response; + @Inject JsonActionRunner() {} + + /** Delegates request to {@code action}. */ + public void run(JsonAction action) { + response.setPayload( + verifyNotNull( + action.handleJsonRequest(payload), + "handleJsonRequest() returned null")); + } +} diff --git a/java/com/google/domain/registry/request/JsonPayload.java b/java/com/google/domain/registry/request/JsonPayload.java new file mode 100644 index 000000000..c921e41e4 --- /dev/null +++ b/java/com/google/domain/registry/request/JsonPayload.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** + * Dagger qualifier for the HTTP request payload as parsed JSON. + * + * @see RequestModule + */ +@Qualifier +@Documented +public @interface JsonPayload {} diff --git a/java/com/google/domain/registry/request/JsonResponse.java b/java/com/google/domain/registry/request/JsonResponse.java new file mode 100644 index 000000000..d78a25e92 --- /dev/null +++ b/java/com/google/domain/registry/request/JsonResponse.java @@ -0,0 +1,68 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.X_CONTENT_TYPE_OPTIONS; +import static com.google.common.net.MediaType.JSON_UTF_8; +import static org.json.simple.JSONValue.toJSONString; + +import org.joda.time.DateTime; + +import java.util.Map; + +import javax.inject.Inject; + +/** JSON response object. */ +public class JsonResponse { + + /** String prefixed to all JSON-like responses to break {@code eval()}. */ + public static final String JSON_SAFETY_PREFIX = ")]}'\n"; + + protected final Response response; + + @Inject + public JsonResponse(Response rsp) { + this.response = rsp; + } + + /** @see Response#setStatus */ + public void setStatus(int status) { + response.setStatus(status); + } + + /** Writes the JSON map to the HTTP payload; call this exactly once. */ + public void setPayload(Map responseMap) { + response.setContentType(JSON_UTF_8); + // This prevents IE from MIME-sniffing a response away from the declared Content-Type. + response.setHeader(X_CONTENT_TYPE_OPTIONS, "nosniff"); + // This is a defense in depth that prevents browsers from trying to render the content of the + // response, even if all else fails. It's basically another anti-sniffing mechanism in the sense + // that if you hit this url directly, it would try to download the file instead of showing it. + response.setHeader(CONTENT_DISPOSITION, "attachment"); + response.setPayload(JSON_SAFETY_PREFIX + toJSONString(checkNotNull(responseMap))); + } + + /** @see Response#setHeader */ + public void setHeader(String header, String value) { + response.setHeader(header, value); + } + + /** @see Response#setDateHeader */ + public void setDateHeader(String header, DateTime timestamp) { + response.setDateHeader(header, timestamp); + } +} diff --git a/java/com/google/domain/registry/request/Modules.java b/java/com/google/domain/registry/request/Modules.java new file mode 100644 index 000000000..4320207d1 --- /dev/null +++ b/java/com/google/domain/registry/request/Modules.java @@ -0,0 +1,202 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.api.client.extensions.appengine.http.UrlFetchTransport; +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.appengine.api.datastore.DatastoreService; +import com.google.appengine.api.modules.ModulesService; +import com.google.appengine.api.modules.ModulesServiceFactory; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.appengine.api.urlfetch.URLFetchServiceFactory; +import com.google.appengine.api.users.UserService; +import com.google.appengine.api.users.UserServiceFactory; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.keyring.api.KeyModule.Key; + +import dagger.Module; +import dagger.Provides; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Set; + +import javax.inject.Named; +import javax.inject.Singleton; + +/** Dagger modules for App Engine services and other vendor classes. */ +public final class Modules { + + /** Dagger module for {@link DatastoreService}. */ + @Module + public static final class DatastoreServiceModule { + private static final DatastoreService datastoreService = getDatastoreService(); + + @Provides + static DatastoreService provideDatastoreService() { + return datastoreService; + } + } + + /** Dagger module for {@link ModulesService}. */ + @Module + public static final class ModulesServiceModule { + private static final ModulesService modulesService = ModulesServiceFactory.getModulesService(); + + @Provides + static ModulesService provideModulesService() { + return modulesService; + } + } + + /** Dagger module for {@link URLFetchService}. */ + @Module + public static final class URLFetchServiceModule { + private static final URLFetchService fetchService = URLFetchServiceFactory.getURLFetchService(); + + @Provides + static URLFetchService provideURLFetchService() { + return fetchService; + } + } + + /** Dagger module for {@link UserService}. */ + @Module + public static final class UserServiceModule { + private static final UserService userService = UserServiceFactory.getUserService(); + + @Provides + static UserService provideUserService() { + return userService; + } + } + + /** + * Dagger module that causes the Jackson2 JSON parser to be used for Google APIs requests. + * + *

Jackson1 and GSON can also satisfy the {@link JsonFactory} interface, but we've decided to + * go with Jackson2, since it's what's used in the public examples for using Google APIs. + */ + @Module + public static final class Jackson2Module { + @Provides + static JsonFactory provideJsonFactory() { + return JacksonFactory.getDefaultInstance(); + } + } + + /** Dagger module that causes the App Engine's URL fetcher to be used for Google APIs requests. */ + @Module + public static final class UrlFetchTransportModule { + private static final UrlFetchTransport HTTP_TRANSPORT = new UrlFetchTransport(); + + @Provides + static HttpTransport provideHttpTransport() { + return HTTP_TRANSPORT; + } + } + + /** + * Dagger module providing {@link AppIdentityCredential}. + * + *

This can be used to authenticate to Google APIs using the identity of your GAE app. + * + * @see UseAppIdentityCredentialForGoogleApisModule + */ + @Module + public static final class AppIdentityCredentialModule { + @Provides + static AppIdentityCredential provideAppIdentityCredential(@OAuthScopes Set scopes) { + return new AppIdentityCredential(scopes); + } + } + + /** + * Dagger module causing Google APIs requests to be authorized with your GAE app identity. + * + *

You must also use the {@link AppIdentityCredential} module. + */ + @Module + public static final class UseAppIdentityCredentialForGoogleApisModule { + @Provides + static HttpRequestInitializer provideHttpRequestInitializer(AppIdentityCredential credential) { + return credential; + } + } + + /** + * Dagger module providing {@link GoogleCredential} from a JSON key file contents. + * + *

This satisfies the {@link HttpRequestInitializer} interface for authenticating Google APIs + * requests, just like {@link AppIdentityCredential}. + * + *

But we consider GAE authentication more desirable and easier to manage operations-wise. So + * this authentication method should only be used for the following situations: + * + *

    + *
  1. Locally-running programs (which aren't executing on the App Engine platform) + *
  2. Spreadsheet service (which can't use {@link AppIdentityCredential} due to an old library) + *
+ * + * @see com.google.domain.registry.keyring.api.Keyring#getJsonCredential() + */ + @Module + public static final class GoogleCredentialModule { + + @Provides + static GoogleCredential provideGoogleCredential( + HttpTransport httpTransport, + JsonFactory jsonFactory, + @Key("jsonCredential") String jsonCredential) { + try { + return GoogleCredential.fromStream( + new ByteArrayInputStream(jsonCredential.getBytes(UTF_8)), httpTransport, jsonFactory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Provides a GoogleCredential that will connect to GAE using delegated admin access. This is + * needed for API calls requiring domain admin access to the relevant GAFYD using delegated + * scopes, e.g. the Directory API and the Groupssettings API. + */ + @Provides + @Singleton + @Named("delegatedAdmin") + static GoogleCredential provideDelegatedAdminGoogleCredential( + GoogleCredential googleCredential, + HttpTransport httpTransport, + @DelegatedOAuthScopes Set scopes, + @Config("googleAppsAdminEmailAddress") String googleAppsAdminEmailAddress) { + return new GoogleCredential.Builder() + .setTransport(httpTransport) + .setJsonFactory(googleCredential.getJsonFactory()) + .setServiceAccountId(googleCredential.getServiceAccountId()) + .setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey()) + .setServiceAccountScopes(scopes) + .setServiceAccountUser(googleAppsAdminEmailAddress) + .build(); + } + } +} diff --git a/java/com/google/domain/registry/request/OAuthScopes.java b/java/com/google/domain/registry/request/OAuthScopes.java new file mode 100644 index 000000000..62b472466 --- /dev/null +++ b/java/com/google/domain/registry/request/OAuthScopes.java @@ -0,0 +1,25 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; +import java.util.Set; + +import javax.inject.Qualifier; + +/** Dagger qualifier for the {@link Set} of OAuth2 scope strings, used for API authorization. */ +@Qualifier +@Documented +public @interface OAuthScopes {} diff --git a/java/com/google/domain/registry/request/Parameter.java b/java/com/google/domain/registry/request/Parameter.java new file mode 100644 index 000000000..c573ff624 --- /dev/null +++ b/java/com/google/domain/registry/request/Parameter.java @@ -0,0 +1,26 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** Dagger qualifier for HTTP parameters. */ +@Qualifier +@Documented +public @interface Parameter { + String value(); +} diff --git a/java/com/google/domain/registry/request/ParameterMap.java b/java/com/google/domain/registry/request/ParameterMap.java new file mode 100644 index 000000000..535e4bcad --- /dev/null +++ b/java/com/google/domain/registry/request/ParameterMap.java @@ -0,0 +1,24 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** Dagger qualifier for {@link com.google.common.collect.ImmutableListMultimap} of HTTP params. */ +@Qualifier +@Documented +public @interface ParameterMap {} diff --git a/java/com/google/domain/registry/request/Payload.java b/java/com/google/domain/registry/request/Payload.java new file mode 100644 index 000000000..bb43e806c --- /dev/null +++ b/java/com/google/domain/registry/request/Payload.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** + * Dagger qualifier for the HTTP request payload. + * + * @see RequestModule + */ +@Qualifier +@Documented +public @interface Payload {} diff --git a/java/com/google/domain/registry/request/RequestHandler.java b/java/com/google/domain/registry/request/RequestHandler.java new file mode 100644 index 000000000..191ddd3aa --- /dev/null +++ b/java/com/google/domain/registry/request/RequestHandler.java @@ -0,0 +1,158 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.common.net.HttpHeaders.LOCATION; +import static com.google.domain.registry.security.XsrfTokenManager.X_CSRF_TOKEN; +import static com.google.domain.registry.security.XsrfTokenManager.validateToken; +import static com.google.domain.registry.util.HttpServletUtils.sendOk; +import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static javax.servlet.http.HttpServletResponse.SC_METHOD_NOT_ALLOWED; +import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; +import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; + +import com.google.appengine.api.users.UserService; +import com.google.appengine.api.users.UserServiceFactory; +import com.google.common.base.Optional; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; + +import org.joda.time.Duration; + +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Dagger request processor for Domain Registry. + * + *

This class creates an HTTP request processor from a Dagger component. It routes requests from + * your servlet to an {@link Action @Action} annotated handler class. + * + *

Component Definition

+ * + *

Action instances are supplied on a per-request basis by invoking the methods on {@code C}. + * For example: + *

+ * {@literal @Component}
+ * interface ServerComponent {
+ *   HelloAction helloAction();
+ * }
+ * + *

The rules for component methods are as follows: + *

    + *
  1. Methods whose raw return type does not implement {@code Runnable} will be ignored + *
  2. Methods whose raw return type does not have an {@code @Action} annotation are ignored + *
+ * + *

Security Features

+ * + *

XSRF protection is built into this class. It can be enabled or disabled on individual actions + * using {@link Action#xsrfProtection() xsrfProtection} setting. + * + *

This class also enforces the {@link Action#requireLogin() requireLogin} setting. + * + * @param component type + */ +public final class RequestHandler { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + private static final Duration XSRF_VALIDITY = Duration.standardDays(1); + + @NonFinalForTesting + private static UserService userService = UserServiceFactory.getUserService(); + + /** + * Creates a new request processor based off your component methods. + * + *

Warning: When using the App Engine platform, you must call + * {@link Method#setAccessible(boolean) setAccessible(true)} on all your component {@link Method} + * instances, from within the same package as the component. This is due to cross-package + * reflection restrictions. + * + * @param methods is the result of calling {@link Class#getMethods()} on {@code component}, which + * are filtered to only include those with no arguments returning a {@link Runnable} with an + * {@link Action} annotation + */ + public static RequestHandler create(Class component, Iterable methods) { + return new RequestHandler<>(component, Router.create(methods)); + } + + private final Router router; + + private RequestHandler(Class component, Router router) { + checkNotNull(component); + this.router = router; + } + + /** + * Runs the appropriate action for a servlet request. + * + * @param component is an instance of the component type whose methods were passed to + * {@link #create(Class, Iterable)} + */ + public void handleRequest(HttpServletRequest req, HttpServletResponse rsp, C component) + throws IOException { + checkNotNull(component); + checkNotNull(rsp); + Action.Method method; + try { + method = Action.Method.valueOf(req.getMethod()); + } catch (IllegalArgumentException e) { + logger.infofmt("Unsupported method: %s", req.getMethod()); + rsp.sendError(SC_METHOD_NOT_ALLOWED); + return; + } + String path = req.getRequestURI(); + Optional route = router.route(path); + if (!route.isPresent()) { + logger.infofmt("No action found for: %s", path); + rsp.sendError(SC_NOT_FOUND); + return; + } + if (!route.get().isMethodAllowed(method)) { + logger.infofmt("Method %s not allowed for: %s", method, path); + rsp.sendError(SC_METHOD_NOT_ALLOWED); + return; + } + if (route.get().action().requireLogin() && !userService.isUserLoggedIn()) { + logger.info("not logged in"); + rsp.setStatus(SC_MOVED_TEMPORARILY); + rsp.setHeader(LOCATION, userService.createLoginURL(req.getRequestURI())); + return; + } + if (route.get().shouldXsrfProtect(method) + && !validateToken( + nullToEmpty(req.getHeader(X_CSRF_TOKEN)), + route.get().action().xsrfScope(), + XSRF_VALIDITY)) { + rsp.sendError(SC_FORBIDDEN, "Invalid " + X_CSRF_TOKEN); + return; + } + try { + route.get().instantiator().apply(component).run(); + if (route.get().action().automaticallyPrintOk()) { + sendOk(rsp); + } + } catch (HttpException e) { + e.send(rsp); + } + } +} diff --git a/java/com/google/domain/registry/request/RequestMethod.java b/java/com/google/domain/registry/request/RequestMethod.java new file mode 100644 index 000000000..6d91216ea --- /dev/null +++ b/java/com/google/domain/registry/request/RequestMethod.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** + * Dagger qualifier for the HTTP request method. + * + * @see javax.servlet.http.HttpServletRequest#getMethod() + */ +@Qualifier +@Documented +public @interface RequestMethod {} diff --git a/java/com/google/domain/registry/request/RequestModule.java b/java/com/google/domain/registry/request/RequestModule.java new file mode 100644 index 000000000..d4f5a81f3 --- /dev/null +++ b/java/com/google/domain/registry/request/RequestModule.java @@ -0,0 +1,154 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.net.MediaType.JSON_UTF_8; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.VerifyException; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.io.ByteStreams; +import com.google.common.io.CharStreams; +import com.google.common.net.MediaType; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.UnsupportedMediaTypeException; + +import dagger.Module; +import dagger.Provides; + +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Dagger module for servlets. */ +@Module +public final class RequestModule { + + private final HttpServletRequest req; + private final HttpServletResponse rsp; + + public RequestModule(HttpServletRequest req, HttpServletResponse rsp) { + this.req = req; + this.rsp = rsp; + } + + @Provides + static Response provideResponse(ResponseImpl response) { + return response; + } + + @Provides + HttpServletRequest provideHttpServletRequest() { + return req; + } + + @Provides + HttpServletResponse provideHttpServletResponse() { + return rsp; + } + + @Provides + @RequestPath + static String provideRequestPath(HttpServletRequest req) { + return req.getRequestURI(); + } + + @Provides + @RequestMethod + static Action.Method provideRequestMethod(HttpServletRequest req) { + return Action.Method.valueOf(req.getMethod()); + } + + @Provides + @Header("Content-Type") + static MediaType provideContentType(HttpServletRequest req) { + try { + return MediaType.parse(req.getContentType()); + } catch (IllegalArgumentException | NullPointerException e) { + throw new UnsupportedMediaTypeException("Bad Content-Type header", e); + } + } + + @Provides + @Payload + static String providePayloadAsString(HttpServletRequest req) { + try { + return CharStreams.toString(req.getReader()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Provides + @Payload + static byte[] providePayloadAsBytes(HttpServletRequest req) { + try { + return ByteStreams.toByteArray(req.getInputStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Provides + @JsonPayload + @SuppressWarnings("unchecked") + static Map provideJsonPayload( + @Header("Content-Type") MediaType contentType, + @Payload String payload) { + if (!JSON_UTF_8.is(contentType.withCharset(UTF_8))) { + throw new UnsupportedMediaTypeException( + String.format("Expected %s Content-Type", JSON_UTF_8.withoutParameters())); + } + try { + return (Map) JSONValue.parseWithException(payload); + } catch (ParseException e) { + throw new BadRequestException( + "Malformed JSON", new VerifyException("Malformed JSON:\n" + payload, e)); + } + } + + /** + * Provides an immutable representation of the servlet request parameters. + * + *

This performs a shallow copy of the {@code Map} data structure from the + * servlets API, each time this is provided. This is almost certainly less expensive than the + * thread synchronization expense of {@link javax.inject.Singleton @Singleton}. + * + *

Note: If a parameter is specified without a value, e.g. {@code /foo?lol} then an + * empty string value is assumed, since Guava's multimap doesn't permit {@code null} mappings. + * + * @see HttpServletRequest#getParameterMap() + */ + @Provides + @ParameterMap + static ImmutableListMultimap provideParameterMap(HttpServletRequest req) { + ImmutableListMultimap.Builder params = new ImmutableListMultimap.Builder<>(); + @SuppressWarnings("unchecked") // Safe by specification. + Map original = req.getParameterMap(); + for (Map.Entry param : original.entrySet()) { + if (param.getValue().length == 0) { + params.put(param.getKey(), ""); + } else { + params.putAll(param.getKey(), param.getValue()); + } + } + return params.build(); + } +} diff --git a/java/com/google/domain/registry/request/RequestParameters.java b/java/com/google/domain/registry/request/RequestParameters.java new file mode 100644 index 000000000..6f8a4aba2 --- /dev/null +++ b/java/com/google/domain/registry/request/RequestParameters.java @@ -0,0 +1,201 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.base.Strings.nullToEmpty; + +import com.google.common.base.Ascii; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.InetAddresses; +import com.google.domain.registry.request.HttpException.BadRequestException; + +import org.joda.time.DateTime; + +import java.net.InetAddress; + +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; + +/** Utilities for extracting parameters from HTTP requests. */ +public final class RequestParameters { + + /** The standardized request parameter name used by any servlet that takes a tld parameter. */ + public static final String PARAM_TLD = "tld"; + + /** + * Returns first GET or POST parameter associated with {@code name}. + * + *

For example, assume {@code name} is "bar". The following request URIs would cause this + * method to yield the following results: + * + *

    + *
  • /foo?bar=hello → hello + *
  • /foo?bar=hello&bar=there → hello + *
  • /foo?bar= → 400 error (empty) + *
  • /foo?bar=&bar=there → 400 error (empty) + *
  • /foo → 400 error (absent) + *
+ * + * @throws BadRequestException if request parameter is absent or empty + */ + public static String extractRequiredParameter(HttpServletRequest req, String name) { + String result = req.getParameter(name); + if (isNullOrEmpty(result)) { + throw new BadRequestException("Missing parameter: " + name); + } + return result; + } + + /** + * Returns first GET or POST parameter associated with {@code name}. + * + * @throws BadRequestException if request parameter is absent (but not if empty) + */ + public static String extractRequiredMaybeEmptyParameter(HttpServletRequest req, String name) { + String result = req.getParameter(name); + if (result == null) { + throw new BadRequestException("Missing parameter: " + name); + } + return result; + } + + /** Returns the first GET or POST parameter associated with {@code name}. */ + public static Optional extractOptionalParameter(HttpServletRequest req, String name) { + return Optional.fromNullable(emptyToNull(req.getParameter(name))); + } + + /** + * Returns first GET or POST parameter associated with {@code name} as an integer. + * + * @throws BadRequestException if request parameter is present but not a valid integer + */ + public static Optional extractOptionalIntParameter(HttpServletRequest req, String name) { + String stringParam = req.getParameter(name); + try { + return isNullOrEmpty(stringParam) + ? Optional.absent() + : Optional.of(Integer.valueOf(stringParam)); + } catch (NumberFormatException e) { + throw new BadRequestException("Expected integer: " + name); + } + } + + /** + * Returns first GET or POST parameter associated with {@code name} as an integer. + * + * @throws BadRequestException if request parameter is absent, empty, or not a valid integer + */ + public static int extractIntParameter(HttpServletRequest req, String name) { + try { + return Integer.valueOf(nullToEmpty(req.getParameter(name))); + } catch (NumberFormatException e) { + throw new BadRequestException("Expected integer: " + name); + } + } + + /** Returns all GET or POST parameters associated with {@code name}. */ + public static ImmutableSet extractSetOfParameters(HttpServletRequest req, String name) { + String[] parameters = req.getParameterValues(name); + return parameters == null ? ImmutableSet.of() : ImmutableSet.copyOf(parameters); + } + + /** + * Returns the first GET or POST parameter associated with {@code name}. + * + * @throws BadRequestException if request parameter named {@code name} is absent, empty, or not + * equal to any of the values in {@code enumClass} + */ + public static > + C extractEnumParameter(HttpServletRequest req, Class enumClass, String name) { + try { + return Enum.valueOf(enumClass, Ascii.toUpperCase(extractRequiredParameter(req, name))); + } catch (IllegalArgumentException e) { + throw new BadRequestException( + String.format("Invalid %s parameter: %s", enumClass.getSimpleName(), name)); + } + } + + /** + * Returns {@code true} if parameter is present and not empty and not {@code "false"}. + * + *

This considers a parameter with a non-existent value true, for situations where the request + * URI is something like {@code /foo?bar}, where the mere presence of the {@code bar} parameter + * without a value indicates that it's true. + */ + public static boolean extractBooleanParameter(HttpServletRequest req, String name) { + return req.getParameterMap().containsKey(name) + && !equalsFalse(req.getParameter(name)); + } + + /** + * Returns first request parameter associated with {@code name} parsed as an + * ISO 8601 timestamp, e.g. {@code 1984-12-18TZ}, + * {@code 2000-01-01T16:20:00Z}. + * + * @throws BadRequestException if request parameter named {@code name} is absent, empty, or could + * not be parsed as an ISO 8601 timestamp + */ + public static DateTime extractRequiredDatetimeParameter(HttpServletRequest req, String name) { + String stringValue = extractRequiredParameter(req, name); + try { + return DateTime.parse(stringValue); + } catch (IllegalArgumentException e) { + throw new BadRequestException("Bad ISO 8601 timestamp: " + name); + } + } + + /** + * Returns first request parameter associated with {@code name} parsed as an optional + * {@link InetAddress} (which might be IPv6). + * + * @throws BadRequestException if request parameter named {@code name} is present but could not + * be parsed as an {@link InetAddress} + */ + public static Optional extractOptionalInetAddressParameter( + HttpServletRequest req, String name) { + Optional paramVal = extractOptionalParameter(req, name); + if (!paramVal.isPresent()) { + return Optional.absent(); + } + try { + return Optional.of(InetAddresses.forString(paramVal.get())); + } catch (IllegalArgumentException e) { + throw new BadRequestException("Not an IPv4 or IPv6 address: " + name); + } + } + + private static boolean equalsFalse(@Nullable String value) { + return nullToEmpty(value).equalsIgnoreCase("false"); + } + + /** + * Returns first HTTP header associated with {@code name}. + * + * @param name case insensitive header name + * @throws BadRequestException if request header is absent or empty + */ + public static String extractRequiredHeader(HttpServletRequest req, String name) { + String result = req.getHeader(name); + if (isNullOrEmpty(result)) { + throw new BadRequestException("Missing header: " + name); + } + return result; + } + + private RequestParameters() {} +} diff --git a/java/com/google/domain/registry/request/RequestPath.java b/java/com/google/domain/registry/request/RequestPath.java new file mode 100644 index 000000000..0e6e5f39a --- /dev/null +++ b/java/com/google/domain/registry/request/RequestPath.java @@ -0,0 +1,28 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; + +import javax.inject.Qualifier; + +/** + * Dagger qualifier for the HTTP request path. + * + * @see javax.servlet.http.HttpServletRequest#getRequestURI() + */ +@Qualifier +@Documented +public @interface RequestPath {} diff --git a/java/com/google/domain/registry/request/RequestScope.java b/java/com/google/domain/registry/request/RequestScope.java new file mode 100644 index 000000000..99ea06229 --- /dev/null +++ b/java/com/google/domain/registry/request/RequestScope.java @@ -0,0 +1,30 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Scope; + +/** Dagger annotation for request-scoped components that depend on a global component. */ +@Scope +@Documented +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestScope {} diff --git a/java/com/google/domain/registry/request/Response.java b/java/com/google/domain/registry/request/Response.java new file mode 100644 index 000000000..0d388776a --- /dev/null +++ b/java/com/google/domain/registry/request/Response.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import com.google.common.net.MediaType; + +import org.joda.time.DateTime; + +import javax.servlet.http.HttpServletResponse; + +/** + * HTTP request response object. + * + * @see ResponseImpl + */ +public interface Response { + + /** Sets the HTTP status code. */ + void setStatus(int status); + + /** Sets the HTTP Content-Type and possibly encoding. */ + void setContentType(MediaType contentType); + + /** + * Writes the HTTP payload. + * + * @throws IllegalStateException if you've already written the payload + */ + void setPayload(String payload); + + /** + * Writes an HTTP header to the response. + * + * @see HttpServletResponse#setHeader(String, String) + */ + void setHeader(String header, String value); + + /** + * Writes an HTTP header with a timestamp value. + * + * @see HttpServletResponse#setDateHeader(String, long) + */ + void setDateHeader(String header, DateTime timestamp); + + /** + * Sends a JavaScript redirect HTTP response. + * + * GAE handles a HTTP 302 status as an error, so using this is helpful for responses that might + * sometimes be consumed by GAE code, since it performs a redirect while also returning HTTP 200. + */ + void sendJavaScriptRedirect(String redirectUrl); +} diff --git a/java/com/google/domain/registry/request/ResponseImpl.java b/java/com/google/domain/registry/request/ResponseImpl.java new file mode 100644 index 000000000..f3d776675 --- /dev/null +++ b/java/com/google/domain/registry/request/ResponseImpl.java @@ -0,0 +1,73 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import com.google.common.net.MediaType; + +import org.joda.time.DateTime; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletResponse; + +/** HTTP response object. */ +public final class ResponseImpl implements Response { + + /** Code for a JavaScript redirect. */ + private static final String REDIRECT_PAYLOAD_FORMAT = + "%1$s"; + + private final HttpServletResponse rsp; + + @Inject + public ResponseImpl(HttpServletResponse rsp) { + this.rsp = rsp; + } + + @Override + public void setStatus(int status) { + rsp.setStatus(status); + } + + @Override + public void setContentType(MediaType contentType) { + rsp.setContentType(contentType.toString()); + } + + @Override + public void setPayload(String payload) { + try { + rsp.getWriter().write(payload); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void setHeader(String header, String value) { + rsp.setHeader(header, value); + } + + @Override + public void setDateHeader(String header, DateTime timestamp) { + rsp.setDateHeader(header, timestamp.getMillis()); + } + + @Override + public void sendJavaScriptRedirect(String redirectUrl) { + setPayload(String.format(REDIRECT_PAYLOAD_FORMAT, redirectUrl)); + } +} diff --git a/java/com/google/domain/registry/request/Route.java b/java/com/google/domain/registry/request/Route.java new file mode 100644 index 000000000..715ced86b --- /dev/null +++ b/java/com/google/domain/registry/request/Route.java @@ -0,0 +1,47 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Function; + +/** + * Mapping of an {@link Action} to a {@link Runnable} instantiator for request handling. + * + * @see Router + */ +@AutoValue +abstract class Route { + + static Route create(Action action, Function instantiator) { + return new AutoValue_Route(action, instantiator); + } + + abstract Action action(); + abstract Function instantiator(); + + boolean isMethodAllowed(Action.Method requestMethod) { + for (Action.Method method : action().method()) { + if (method == requestMethod) { + return true; + } + } + return false; + } + + boolean shouldXsrfProtect(Action.Method requestMethod) { + return action().xsrfProtection() && requestMethod != Action.Method.GET; + } +} diff --git a/java/com/google/domain/registry/request/Router.java b/java/com/google/domain/registry/request/Router.java new file mode 100644 index 000000000..4a8637637 --- /dev/null +++ b/java/com/google/domain/registry/request/Router.java @@ -0,0 +1,107 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Ordering; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.TreeMap; + +/** + * Path prefix request router for Domain Registry. + * + *

See the documentation of {@link RequestHandler} for more information. + * + *

Implementation Details

+ * + *

Request routing is O(logn) because {@link ImmutableSortedMap} performs a binary search over a + * contiguous array, which makes it faster than a {@link TreeMap}. However a prefix trie search in + * generated code would be the ideal approach. + */ +final class Router { + + static Router create(Iterable componentMethods) { + return new Router(extractRoutesFromComponent(componentMethods)); + } + + private final ImmutableSortedMap routes; + + private Router(ImmutableSortedMap routes) { + this.routes = routes; + } + + /** Returns the appropriate action route for a request. */ + Optional route(String path) { + Map.Entry floor = routes.floorEntry(path); + if (floor != null) { + if (floor.getValue().action().isPrefix() + ? path.startsWith(floor.getKey()) + : path.equals(floor.getKey())) { + return Optional.of(floor.getValue()); + } + } + return Optional.absent(); + } + + private static + ImmutableSortedMap extractRoutesFromComponent(Iterable methods) { + ImmutableSortedMap.Builder routes = + new ImmutableSortedMap.Builder<>(Ordering.natural()); + for (Method method : methods) { + if (!isDaggerInstantiatorOfType(Runnable.class, method)) { + continue; + } + Action action = method.getReturnType().getAnnotation(Action.class); + if (action == null) { + continue; + } + @SuppressWarnings("unchecked") // Safe due to previous checks. + Route route = + Route.create(action, (Function) newInstantiator(method)); + routes.put(action.path(), route); + } + return routes.build(); + } + + private static boolean isDaggerInstantiatorOfType(Class type, Method method) { + return method.getParameterTypes().length == 0 + && type.isAssignableFrom(method.getReturnType()); + } + + private static Function newInstantiator(final Method method) { + return new Function() { + @Override + public Object apply(Object component) { + try { + return method.invoke(component); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Error reflectively accessing component's @Action factory method", e); + } catch (InvocationTargetException e) { + // This means an exception was thrown during the injection process while instantiating + // the @Action class; we should propagate that underlying exception. + Throwables.propagateIfPossible(e.getCause()); + throw new AssertionError( + "Component's @Action factory method somehow threw checked exception", e); + } + }}; + } +} diff --git a/java/com/google/domain/registry/request/ServletDelegate.java b/java/com/google/domain/registry/request/ServletDelegate.java new file mode 100644 index 000000000..ea18372b8 --- /dev/null +++ b/java/com/google/domain/registry/request/ServletDelegate.java @@ -0,0 +1,51 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.request; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Action that delegates to a servlet. + * + *

This is a transitory solution for using legacy servlets inside the new injection action + * framework. + * + * @param servlet type, which must have an {@link Inject @Inject} constructor + */ +public abstract class ServletDelegate implements Runnable { + + @Inject T servlet; + @Inject HttpServletRequest req; + @Inject HttpServletResponse rsp; + + protected ServletDelegate() {} + + @Override + public final void run() { + try { + servlet.init(); + servlet.service(req, rsp); + servlet.destroy(); + } catch (ServletException | IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/com/google/domain/registry/request/package-info.java b/java/com/google/domain/registry/request/package-info.java new file mode 100644 index 000000000..a777a097f --- /dev/null +++ b/java/com/google/domain/registry/request/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.request; diff --git a/java/com/google/domain/registry/security/BUILD b/java/com/google/domain/registry/security/BUILD new file mode 100644 index 000000000..3f6131782 --- /dev/null +++ b/java/com/google/domain/registry/security/BUILD @@ -0,0 +1,41 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "security", + srcs = glob( + ["*.java"], + exclude = glob(["*Servlet.java"]), + ), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/hash", + "//java/com/google/common/html", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/util", + "//third_party/java/appengine:appengine-api", + "//third_party/java/joda_time", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) + +java_library( + name = "servlets", + srcs = glob(["*Servlet.java"]), + deps = [ + ":security", + "//java/com/google/common/base", + "//java/com/google/domain/registry/request", + "//third_party/java/appengine:appengine-api", + "//third_party/java/joda_time", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/security/JsonHttp.java b/java/com/google/domain/registry/security/JsonHttp.java new file mode 100644 index 000000000..4ec001c20 --- /dev/null +++ b/java/com/google/domain/registry/security/JsonHttp.java @@ -0,0 +1,97 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.security; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.X_CONTENT_TYPE_OPTIONS; +import static com.google.common.net.MediaType.JSON_UTF_8; +import static org.json.simple.JSONValue.writeJSONString; + +import com.google.common.net.MediaType; +import com.google.domain.registry.util.FormattingLogger; + +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Helper class for servlets that read or write JSON. + * + * @see JsonResponseHelper + */ +public final class JsonHttp { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** String prefixed to all JSON-like responses. */ + public static final String JSON_SAFETY_PREFIX = ")]}'\n"; + + /** + * Extracts a JSON object from a servlet request. + * + * @return JSON object or {@code null} on error, in which case servlet should return. + * @throws IOException if we failed to read from {@code req}. + */ + @Nullable + @SuppressWarnings("unchecked") + public static Map read(HttpServletRequest req) throws IOException { + if (!"POST".equals(req.getMethod()) + && !"PUT".equals(req.getMethod())) { + logger.warning("JSON request payload only allowed for POST/PUT"); + return null; + } + if (!JSON_UTF_8.is(MediaType.parse(req.getContentType()))) { + logger.warningfmt("Invalid JSON Content-Type: %s", req.getContentType()); + return null; + } + try (Reader jsonReader = req.getReader()) { + try { + return checkNotNull((Map) JSONValue.parseWithException(jsonReader)); + } catch (ParseException | NullPointerException | ClassCastException e) { + logger.warning(e, "Malformed JSON"); + return null; + } + } + } + + /** + * Writes a JSON servlet response securely with a parser breaker. + * + * @throws IOException if we failed to write to {@code rsp}. + */ + public static void write(HttpServletResponse rsp, Map jsonObject) throws IOException { + checkNotNull(jsonObject); + rsp.setContentType(JSON_UTF_8.toString()); + // This prevents IE from MIME-sniffing a response away from the declared Content-Type. + rsp.setHeader(X_CONTENT_TYPE_OPTIONS, "nosniff"); + // This is a defense in depth that prevents browsers from trying to render the content of the + // response, even if all else fails. It's basically another anti-sniffing mechanism in the sense + // that if you hit this url directly, it would try to download the file instead of showing it. + rsp.setHeader(CONTENT_DISPOSITION, "attachment"); + try (Writer writer = rsp.getWriter()) { + writer.write(JSON_SAFETY_PREFIX); + writeJSONString(jsonObject, writer); + } + } +} diff --git a/java/com/google/domain/registry/security/JsonResponseHelper.java b/java/com/google/domain/registry/security/JsonResponseHelper.java new file mode 100644 index 000000000..9e9e4df2e --- /dev/null +++ b/java/com/google/domain/registry/security/JsonResponseHelper.java @@ -0,0 +1,63 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.security; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +/** + * Helper class for JSON API servlets to send response messages. + * + * @see JsonHttp + */ +public final class JsonResponseHelper { + + /** Possible results of an RPC operation. */ + public enum Status { SUCCESS, ERROR } + + /** Creates a JSON response message securely to the browser client with a parser breaker. */ + public static ImmutableMap create( + Status status, String message, Iterable> results) { + return ImmutableMap.of( + "status", status.toString(), + "message", checkNotNull(message, "message"), + "results", ImmutableList.copyOf(results)); + } + + /** Same as {@link #create(Status, String, Iterable)} but with zero results. */ + public static ImmutableMap create(Status status, String message) { + return create(status, message, ImmutableList.>of()); + } + + /** Same as {@link #create(Status, String, Iterable)} but with only one results. */ + public static ImmutableMap create( + Status status, String message, Map result) { + return create(status, message, ImmutableList.>of(result)); + } + + /** Creates a JSON response message when a submitted form field is invalid. */ + public static ImmutableMap createFormFieldError( + String message, String formFieldName) { + return ImmutableMap.of( + "status", Status.ERROR.toString(), + "message", checkNotNull(message, "message"), + "field", checkNotNull(formFieldName, "formFieldName"), + "results", ImmutableList.of()); + } +} diff --git a/java/com/google/domain/registry/security/JsonTransportServlet.java b/java/com/google/domain/registry/security/JsonTransportServlet.java new file mode 100644 index 000000000..e6085376f --- /dev/null +++ b/java/com/google/domain/registry/security/JsonTransportServlet.java @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.security; + +import static com.google.common.base.Preconditions.checkNotNull; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.domain.registry.request.HttpException; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Secure servlet that speaks JSON for both input and output. + * + *

This servlet accepts only JSON inputs (using the payload) and returns only JSON + * responses, using and various security best practices such as a parser breaker, + * {@code Content-Disposition: attachment}, etc. + * + * @see JsonHttp + */ +public abstract class JsonTransportServlet extends XsrfProtectedServlet { + + protected JsonTransportServlet(String xsrfScope, boolean requireAdmin) { + super(xsrfScope, requireAdmin); + } + + /** + * Verify that this is a well-formed request and then execute it. A well-formed request will have + * either a JSON string in the "json" param that evaluates to a map, or nothing in "json". + */ + @Override + protected final void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { + Map input = JsonHttp.read(req); + if (input == null) { + rsp.sendError(SC_BAD_REQUEST, "Malformed JSON"); + return; + } + Map output; + try { + output = doJsonPost(req, input); + } catch (HttpException e) { + e.send(rsp); + return; + } + checkNotNull(output, "doJsonPost() returned null"); + rsp.setStatus(SC_OK); + JsonHttp.write(rsp, output); + } + + /** + * Handler for HTTP POST requests. + * + * @param req Servlet request object. + * @param input JSON request object or empty if none was provided. + * @return an arbitrary JSON object. Must not be {@code null}. + * @throws HttpException in order to send a non-200 status code / message to the client. + */ + public abstract Map doJsonPost(HttpServletRequest req, Map input); +} diff --git a/java/com/google/domain/registry/security/XsrfProtectedServlet.java b/java/com/google/domain/registry/security/XsrfProtectedServlet.java new file mode 100644 index 000000000..fda7509af --- /dev/null +++ b/java/com/google/domain/registry/security/XsrfProtectedServlet.java @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.security; + +import static com.google.appengine.api.users.UserServiceFactory.getUserService; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.nullToEmpty; +import static com.google.domain.registry.security.XsrfTokenManager.X_CSRF_TOKEN; +import static com.google.domain.registry.security.XsrfTokenManager.validateToken; +import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; + +import com.google.appengine.api.users.UserService; + +import org.joda.time.Duration; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet with Cross-Site Request Forgery (XSRF) protection. + * + *

This servlet enforces XSRF protection on all requests by checking the value provided in the + * "X-CSRF-Token" header. It can also optionally enforce that only admin users can call it. + * + *

All servlets that handle client requests should use XSRF protection. + */ +public abstract class XsrfProtectedServlet extends HttpServlet { + + private static final Duration XSRF_VALIDITY = Duration.standardDays(1); + + /** Used to validate XSRF tokens. */ + private String xsrfScope; + + /** Whether to do a security check for admin status. */ + private boolean requireAdmin; + + /** Gets the XSRF scope for this servlet. */ + public String getScope() { + return xsrfScope; + } + + protected XsrfProtectedServlet(String xsrfScope, boolean requireAdmin) { + this.xsrfScope = checkNotNull(xsrfScope); + this.requireAdmin = requireAdmin; + } + + @Override + public final void service(HttpServletRequest req, HttpServletResponse rsp) + throws IOException, ServletException { + if (!validateToken(nullToEmpty(req.getHeader(X_CSRF_TOKEN)), xsrfScope, XSRF_VALIDITY)) { + rsp.sendError(SC_FORBIDDEN, "Invalid " + X_CSRF_TOKEN); + return; + } + if (!validateAdmin()) { + rsp.sendError(SC_FORBIDDEN, "Administrator access only"); + return; + } + doPost(req, rsp); + } + + /** + * If this is an admin-only servlet, require admin permissions or being in development mode. Such + * servlets should primarily be defended by being marked internal-only in web.xml, but it's worth + * adding a defense-in-depth. + */ + private boolean validateAdmin() { + UserService userService = getUserService(); + return requireAdmin ? (userService.isUserLoggedIn() && userService.isUserAdmin()) : true; + } +} diff --git a/java/com/google/domain/registry/security/XsrfTokenManager.java b/java/com/google/domain/registry/security/XsrfTokenManager.java new file mode 100644 index 000000000..16f64b685 --- /dev/null +++ b/java/com/google/domain/registry/security/XsrfTokenManager.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.security; + +import static com.google.appengine.api.users.UserServiceFactory.getUserService; +import static com.google.common.io.BaseEncoding.base64Url; +import static com.google.domain.registry.model.server.ServerSecret.getServerSecret; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.appengine.api.users.UserService; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.hash.Hashing; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.List; + +/** Helper class for generating and validate XSRF tokens. */ +public final class XsrfTokenManager { + + /** HTTP header used for transmitting XSRF tokens. */ + public static final String X_CSRF_TOKEN = "X-CSRF-Token"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + private static String encodeToken(long creationTime, String scope, String userEmail) { + String token = Joiner.on('\t').join(getServerSecret(), userEmail, scope, creationTime); + return base64Url().encode(Hashing.sha256() + .newHasher(token.length()) + .putString(token, UTF_8) + .hash() + .asBytes()); + } + + /** + * Generate an xsrf token for a given scope using the logged in user or else no user. + *

+ * If there is no user, the entire xsrf check becomes basically a no-op, but that's ok because any + * callback that doesn't have a user shouldn't be able to access any per-user resources anyways. + */ + public static String generateToken(String scope) { + return generateToken(scope, getLoggedInEmailOrEmpty()); + } + + /** Generate an xsrf token for a given scope and user. */ + public static String generateToken(String scope, String email) { + long now = clock.nowUtc().getMillis(); + return Joiner.on(':').join(encodeToken(now, scope, email), now); + } + + private static String getLoggedInEmailOrEmpty() { + UserService userService = getUserService(); + return userService.isUserLoggedIn() ? userService.getCurrentUser().getEmail() : ""; + } + + /** Validate an xsrf token, given the scope it was used for and an expiration duration. */ + public static boolean validateToken(String token, String scope, Duration validLifetime) { + List tokenParts = Splitter.on(':').splitToList(token); + if (tokenParts.size() != 2) { + logger.warningfmt("Malformed XSRF token: %s", token); + return false; + } + String encodedPart = tokenParts.get(0); + String timePart = tokenParts.get(1); + long creationTime; + try { + creationTime = Long.parseLong(timePart); + } catch (NumberFormatException e) { + logger.warningfmt("Bad timestamp in XSRF token: %s", token); + return false; + } + if (new DateTime(creationTime).plus(validLifetime).isBefore(clock.nowUtc())) { + logger.infofmt("Expired timestamp in XSRF token: %s", token); + return false; + } + String reconstructedToken = encodeToken(creationTime, scope, getLoggedInEmailOrEmpty()); + if (!reconstructedToken.equals(encodedPart)) { + logger.warningfmt("Reconstructed XSRF mismatch: %s != %s", encodedPart, reconstructedToken); + return false; + } + return true; + } + + private XsrfTokenManager() {} +} diff --git a/java/com/google/domain/registry/security/package-info.java b/java/com/google/domain/registry/security/package-info.java new file mode 100644 index 000000000..9c2b469e1 --- /dev/null +++ b/java/com/google/domain/registry/security/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.security; diff --git a/java/com/google/domain/registry/storage/drive/BUILD b/java/com/google/domain/registry/storage/drive/BUILD new file mode 100644 index 000000000..3c27d8e8a --- /dev/null +++ b/java/com/google/domain/registry/storage/drive/BUILD @@ -0,0 +1,23 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "drive", + srcs = glob(["*.java"]), + deps = [ + "//apiserving/discoverydata/drive", + "//java/com/google/api/client/http", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/common/util/concurrent", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + ], +) diff --git a/java/com/google/domain/registry/storage/drive/DriveConnection.java b/java/com/google/domain/registry/storage/drive/DriveConnection.java new file mode 100644 index 000000000..57c16b95c --- /dev/null +++ b/java/com/google/domain/registry/storage/drive/DriveConnection.java @@ -0,0 +1,151 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.storage.drive; + +import com.google.api.client.http.ByteArrayContent; +import com.google.api.services.drive.Drive; +import com.google.api.services.drive.Drive.Children; +import com.google.api.services.drive.model.ChildList; +import com.google.api.services.drive.model.ChildReference; +import com.google.api.services.drive.model.File; +import com.google.api.services.drive.model.ParentReference; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.net.MediaType; + +import java.io.IOException; +import java.util.List; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +/** Class encapsulating parameters and state for accessing the Drive API. */ +public class DriveConnection { + + private static final MediaType GOOGLE_FOLDER = + MediaType.create("application", "vnd.google-apps.folder"); + + /** Drive client instance wrapped by this class. */ + @Inject Drive drive; + @Inject public DriveConnection() {} + + /** + * Creates a folder with the given parent. + * + * @returns the folder id. + */ + public String createFolder(String title, String parentFolderId) throws IOException { + return drive.files() + .insert(createFileReference(title, GOOGLE_FOLDER, parentFolderId)) + .execute() + .getId(); + } + + /** + * Creates a file with the given parent. + * + * @returns the file id. + */ + public String createFile(String title, MediaType mimeType, String parentFolderId, byte[] bytes) + throws IOException { + return drive.files() + .insert( + createFileReference(title, mimeType, parentFolderId), + new ByteArrayContent(mimeType.toString(), bytes)) + .execute() + .getId(); + } + + /** + * Creates a file with the given parent or updates the existing one if a file already exists with + * that same title and parent. + * + * @throws IllegalStateException if multiple files with that name exist in the given folder. + * @throws IOException if communication with Google Drive fails for any reason. + * @returns the file id. + */ + public String createOrUpdateFile( + String title, + MediaType mimeType, + String parentFolderId, + byte[] bytes) throws IOException { + List existingFiles = listFiles(parentFolderId, String.format("title = '%s'", title)); + if (existingFiles.size() > 1) { + throw new IllegalStateException(String.format( + "Could not update file '%s' in Drive folder id '%s' because multiple files with that " + + "name already exist.", + title, + parentFolderId)); + } + return existingFiles.isEmpty() + ? createFile(title, mimeType, parentFolderId, bytes) + : updateFile(existingFiles.get(0), title, mimeType, bytes); + } + + /** + * Updates the file with the given id in place, setting the title, content, and mime type to + * the newly specified values. + * + * @returns the file id. + */ + public String updateFile(String fileId, String title, MediaType mimeType, byte[] bytes) + throws IOException { + File file = new File().setTitle(title); + return drive.files() + .update(fileId, file, new ByteArrayContent(mimeType.toString(), bytes)) + .execute() + .getId(); + } + /** + * Returns a list of Drive file ids for all files in Google Drive in the folder with the + * specified id. + */ + public List listFiles(String parentFolderId) throws IOException { + return listFiles(parentFolderId, null); + } + + /** + * Returns a list of Drive file ids for all files in Google Drive in the folder with the + * specified id and matching the given Drive query. + * + * @see The query format + */ + public List listFiles(String parentFolderId, String query) throws IOException { + ImmutableList.Builder result = new ImmutableList.Builder<>(); + Children.List req = drive.children().list(parentFolderId); + if (!Strings.isNullOrEmpty(query)) { + req.setQ(query); + } + do { + ChildList files = req.execute(); + for (ChildReference child : files.getItems()) { + result.add(child.getId()); + } + req.setPageToken(files.getNextPageToken()); + } while (!Strings.isNullOrEmpty(req.getPageToken())); + return result.build(); + } + + /** Constructs an object representing a file (or folder) with a given title and parent. */ + private File createFileReference( + String title, MediaType mimeType, @Nullable String parentFolderId) { + return new File() + .setTitle(title) + .setMimeType(mimeType.toString()) + .setParents(parentFolderId == null + ? null + : ImmutableList.of(new ParentReference().setId(parentFolderId))); + } +} diff --git a/java/com/google/domain/registry/tldconfig/idn/BUILD b/java/com/google/domain/registry/tldconfig/idn/BUILD new file mode 100644 index 000000000..59159bbb7 --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/BUILD @@ -0,0 +1,21 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "idn", + srcs = glob(["*.java"]), + resources = glob(["*.txt"]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/domain/registry/util", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/tldconfig/idn/IdnLabelValidator.java b/java/com/google/domain/registry/tldconfig/idn/IdnLabelValidator.java new file mode 100644 index 000000000..187e366b7 --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/IdnLabelValidator.java @@ -0,0 +1,56 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tldconfig.idn; + +import static com.google.domain.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN; +import static com.google.domain.registry.tldconfig.idn.IdnTableEnum.JA; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.util.Idn; +import com.google.domain.registry.util.NonFinalForTesting; + +/** Validates whether a given IDN label can be provisioned for a particular TLD. */ +public final class IdnLabelValidator { + + /** Most TLDs will use this generic list of IDN tables. */ + private static final ImmutableList DEFAULT_IDN_TABLES = + ImmutableList.of(EXTENDED_LATIN, JA); + + /** Some TLDs have their own IDN tables, configured here. */ + @NonFinalForTesting + private static ImmutableMap> idnTableListsPerTld = + ImmutableMap.of("xn--q9jyb4c", ImmutableList.of(EXTENDED_LATIN, JA)); + + /** + * Returns name of first matching {@link IdnTable} if domain label is valid for the given TLD. + * + *

A label is valid if it is considered valid by at least one configured IDN table for that + * TLD. If no match is found, an absent value is returned. + */ + public static Optional findValidIdnTableForTld(String label, String tld) { + String unicodeString = Idn.toUnicode(label); + for (IdnTableEnum idnTable + : Optional.fromNullable(idnTableListsPerTld.get(tld)).or(DEFAULT_IDN_TABLES)) { + if (idnTable.getTable().isValidLabel(unicodeString)) { + return Optional.of(idnTable.getTable().getName()); + } + } + return Optional.absent(); + } + + private IdnLabelValidator() {} +} diff --git a/java/com/google/domain/registry/tldconfig/idn/IdnTable.java b/java/com/google/domain/registry/tldconfig/idn/IdnTable.java new file mode 100644 index 000000000..c789bd19d --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/IdnTable.java @@ -0,0 +1,142 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tldconfig.idn; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableRangeSet; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; + +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** An IDN table for a particular TLD. */ +public final class IdnTable { + + /** Regular expression to match a line of an IDN table. */ + private static final Pattern LINE_PATTERN = Pattern.compile("^U\\+([0-9a-fA-F]{4,6})"); + + private static final String URL_LINE_PREFIX = "# URL: "; + private static final String POLICY_LINE_PREFIX = "# Policy: "; + + /** Language name for this table (corresponds to filename.) */ + private final String name; + + /** + * Public URL of this IDN table, which is needed by RDE. + * + * @see "https://tools.ietf.org/html/draft-arias-noguchi-dnrd-objects-mapping-05#section-5.5.1.1" + */ + private final URI url; + + /** Public URL of policy for this IDN table, which is needed by RDE. */ + private final URI policy; + + /** {@link RangeSet} containing the valid codepoints in this table. */ + private final RangeSet validCodepoints; + + /** Validates the language rules associated with this IDN table. */ + private final Optional languageValidator; + + private IdnTable( + String name, + URI url, + URI policy, + RangeSet validCodepoints, + Optional languageValidator) { + this.name = name; + this.url = checkNotNull(url, "%s missing '# URL: http://foo.example/page' line", name); + this.policy = checkNotNull(policy, "%s missing '# Policy: http://foo.example/page' line", name); + this.validCodepoints = checkNotNull(validCodepoints); + this.languageValidator = languageValidator; + } + + public String getName() { + return name; + } + + public URI getUrl() { + return url; + } + + public URI getPolicy() { + return policy; + } + + /** + * Returns true if the given label is valid for this IDN table. A label is considered valid if all + * of its codepoints are in the IDN table. + */ + boolean isValidLabel(String label) { + final int length = label.length(); + for (int i = 0; i < length; ) { + int codepoint = label.codePointAt(i); + if (!validCodepoints.contains(codepoint)) { + return false; + } + + // Some codepoints take up more than one character in Java strings (e.g. high and low + // surrogates). + i += Character.charCount(codepoint); + } + return !(languageValidator.isPresent() + && !languageValidator.get().isValidLabelForLanguage(label)); + } + + /** Creates an IDN table given the lines from text file. */ + static IdnTable createFrom( + String language, Iterable data, Optional languageValidator) { + ImmutableRangeSet.Builder rangeSet = new ImmutableRangeSet.Builder<>(); + URI url = null; + URI policy = null; + for (String line : data) { + // Remove leading and trailing whitespace. + line = line.trim(); + + // Handle special comment lines. + if (line.startsWith(URL_LINE_PREFIX)) { + url = URI.create(line.substring(URL_LINE_PREFIX.length())); + } else if (line.startsWith(POLICY_LINE_PREFIX)) { + policy = URI.create(line.substring(POLICY_LINE_PREFIX.length())); + } + + // Skip empty and comment lines. + if (line.isEmpty() || line.startsWith("#")) { + continue; + } + + int codepoint = readCodepoint(line); + rangeSet.add(Range.singleton(codepoint)); + } + return new IdnTable(language, url, policy, rangeSet.build(), languageValidator); + } + + /** + * Read the codepoint from a single line. The expected format of each line is: + * {@code U+XXXX} + * Where {@code XXXX} holds the hex value of the codepoint. + */ + private static int readCodepoint(String line) { + Matcher matcher = LINE_PATTERN.matcher(line); + checkArgument(matcher.lookingAt(), "Can't parse line: %s", line); + + String hexString = matcher.group(1); + return Integer.valueOf(hexString, 16); + } +} diff --git a/java/com/google/domain/registry/tldconfig/idn/IdnTableEnum.java b/java/com/google/domain/registry/tldconfig/idn/IdnTableEnum.java new file mode 100644 index 000000000..c82decc7d --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/IdnTableEnum.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tldconfig.idn; + +import static com.google.common.io.Resources.readLines; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Ascii; +import com.google.common.io.Resources; + +import java.io.IOException; +import java.net.URL; + +/** Wrapper enum that loads all {@link IdnTable} resources into memory. */ +public enum IdnTableEnum { + EXTENDED_LATIN, + JA; + + private final IdnTable table; + + private IdnTableEnum() { + this.table = load(Ascii.toLowerCase(name())); + } + + public IdnTable getTable() { + return table; + } + + private static IdnTable load(String name) { + try { + URL resource = Resources.getResource(IdnTableEnum.class, name + ".txt"); + return IdnTable.createFrom(name, readLines(resource, UTF_8), LanguageValidator.get(name)); + } catch (IOException e) { + throw new RuntimeException(e); // should never happen + } + } +} diff --git a/java/com/google/domain/registry/tldconfig/idn/JapaneseLanguageValidator.java b/java/com/google/domain/registry/tldconfig/idn/JapaneseLanguageValidator.java new file mode 100644 index 000000000..792a7b527 --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/JapaneseLanguageValidator.java @@ -0,0 +1,122 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tldconfig.idn; + +import static java.lang.Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION; +import static java.lang.Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS; +import static java.lang.Character.UnicodeBlock.HIRAGANA; +import static java.lang.Character.UnicodeBlock.KATAKANA; + +import com.google.common.collect.ImmutableRangeSet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Range; + +import java.lang.Character.UnicodeBlock; + +/** + * Validates Japanese language domain labels. This class should only be used with a Japanese + * language IDN table. + */ +class JapaneseLanguageValidator extends LanguageValidator { + + /** Any string with Japanese characters can have at most 15 characters. */ + private static final int MAX_LENGTH_JAPANESE_STRING = 15; + + /** Equals the codepoint for the character '〆'. */ + private static final int IDEOGRAPHIC_CLOSING_MARK = 0x3006; + + /** Equals the codepoint for the character '・'. */ + private static final int KATAKANA_MIDDLE_DOT = 0x30FB; + + /** Equals the codepoint for the character 'ー'. */ + private static final int KATAKANA_HIRAGANA_PROLONGED_SOUND_MARK = 0x30FC; + + /** The set of {@link UnicodeBlock} objects containing valid Japanese codepoints. */ + private static final ImmutableSet JAPANESE_UNICODE_BLOCKS = ImmutableSet.of( + CJK_SYMBOLS_AND_PUNCTUATION, HIRAGANA, KATAKANA, CJK_UNIFIED_IDEOGRAPHS); + + /** + * Codepoints which are technically considered to be in the Japanese language, but are + * "exceptions" in that they can not appear in a label with a KATAKANA MIDDLE DOT or + * IDEOGRAPHIC_CLOSING_MARK unless other Japanese non-exception codepoints are also present. + */ + private static final ImmutableRangeSet JAPANESE_EXCEPTION_CODEPOINTS = + new ImmutableRangeSet.Builder() + .add(Range.singleton(IDEOGRAPHIC_CLOSING_MARK)) + .add(Range.singleton(KATAKANA_MIDDLE_DOT)) + .add(Range.singleton(KATAKANA_HIRAGANA_PROLONGED_SOUND_MARK)) + .build(); + + @Override + boolean isValidLabelForLanguage(String label) { + boolean requiresJapaneseNonExceptionCodepoint = false; + boolean hasJapaneseCodepoint = false; + boolean hasJapaneseNonExceptionCodepoint = false; + + final int length = label.length(); + int codepoints = 0; + UnicodeBlock precedingUnicodeBlock = null; + for (int i = 0; i < length; ) { + int codepoint = label.codePointAt(i); + UnicodeBlock unicodeBlock = UnicodeBlock.of(codepoint); + boolean isException = JAPANESE_EXCEPTION_CODEPOINTS.contains(codepoint); + boolean isJapanese = JAPANESE_UNICODE_BLOCKS.contains(unicodeBlock); + + // A label containing KATAKANA_MIDDLE_DOT or IDEOGRAPHIC_CLOSING_MARK requires a Japanese + // language codepoint to also appear in the label. + if (codepoint == KATAKANA_MIDDLE_DOT || codepoint == IDEOGRAPHIC_CLOSING_MARK) { + requiresJapaneseNonExceptionCodepoint = true; + } + + // The KATAKANA_HIRAGANA_PROLONGED_SOUND_MARK can only occur after a HIRAGANA or KATAKANA + // character. + if (codepoint == KATAKANA_HIRAGANA_PROLONGED_SOUND_MARK + && precedingUnicodeBlock != HIRAGANA && precedingUnicodeBlock != KATAKANA) { + return false; + } + + // If a codepoint is Japanese but not an "exception" codepoint, then it must a non-exception + // Japanese codepoint. + if (isJapanese && !isException) { + hasJapaneseNonExceptionCodepoint = true; + } + + // Make a note if we've seen any Japanese codepoint. Note that this object should really only + // be used on a Japanese IDN table, and thus any non-ASCII codepoint should really be + // Japanese. But we do the additional check again the characters UnicodeBlock just in case. + if (isJapanese) { + hasJapaneseCodepoint = true; + } + + // Some codepoints take up more than one character in Java strings (e.g. high and low + // surrogates). + i += Character.charCount(codepoint); + ++codepoints; + precedingUnicodeBlock = unicodeBlock; + } + + // A label with the KATAKANA MIDDLE DOT or IDEOGRAPHIC_CLOSING_MARK codepoint must also have + // some Japanese character in the label. The Japanese "exception" characters do not count in + // this regard. + if (requiresJapaneseNonExceptionCodepoint && !hasJapaneseNonExceptionCodepoint) { + return false; + } + + // Any label with Japanese characters (including "exception" characters) can only be 15 + // codepoints long. + return !(hasJapaneseCodepoint && (codepoints > MAX_LENGTH_JAPANESE_STRING)); + + } +} diff --git a/java/com/google/domain/registry/tldconfig/idn/LanguageValidator.java b/java/com/google/domain/registry/tldconfig/idn/LanguageValidator.java new file mode 100644 index 000000000..517e4d351 --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/LanguageValidator.java @@ -0,0 +1,33 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tldconfig.idn; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; + +abstract class LanguageValidator { + + /** A registry of all known language validators keyed by their language code. */ + private static final ImmutableMap LANGUAGE_VALIDATORS = + ImmutableMap.of("ja", new JapaneseLanguageValidator()); + + /** Return the language validator for the given language code (if one exists). */ + static Optional get(String language) { + return Optional.fromNullable(LANGUAGE_VALIDATORS.get(language)); + } + + /** Returns true if the label meets the context rules for this language. */ + abstract boolean isValidLabelForLanguage(String label); +} diff --git a/java/com/google/domain/registry/tldconfig/idn/extended_latin.txt b/java/com/google/domain/registry/tldconfig/idn/extended_latin.txt new file mode 100644 index 000000000..ea035c6d1 --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/extended_latin.txt @@ -0,0 +1,133 @@ +# URL: https://www.iana.org/domains/idn-tables/tables/google_latn_1.0.txt +# Policy: https://www.registry.google/about/policies/domainabuse/ +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0061 # LATIN SMALL LETTER A +U+00E1 # LATIN SMALL LETTER A WITH ACUTE +U+00E0 # LATIN SMALL LETTER A WITH GRAVE +U+0103 # LATIN SMALL LETTER A WITH BREVE +U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX +U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE +U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS +U+00E3 # LATIN SMALL LETTER A WITH TILDE +U+0105 # LATIN SMALL LETTER A WITH OGONEK +U+0101 # LATIN SMALL LETTER A WITH MACRON +U+01CE # LATIN SMALL LETTER A WITH CARON +U+00E6 # LATIN SMALL LETTER AE +U+0062 # LATIN SMALL LETTER B +U+0063 # LATIN SMALL LETTER C +U+0107 # LATIN SMALL LETTER C WITH ACUTE +U+010D # LATIN SMALL LETTER C WITH CARON +U+010B # LATIN SMALL LETTER C WITH DOT ABOVE +U+00E7 # LATIN SMALL LETTER C WITH CEDILLA +U+0064 # LATIN SMALL LETTER D +U+010F # LATIN SMALL LETTER D WITH CARON +U+0111 # LATIN SMALL LETTER D WITH STROKE +U+00F0 # LATIN SMALL LETTER ETH +U+0065 # LATIN SMALL LETTER E +U+00E9 # LATIN SMALL LETTER E WITH ACUTE +U+00E8 # LATIN SMALL LETTER E WITH GRAVE +U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX +U+011B # LATIN SMALL LETTER E WITH CARON +U+00EB # LATIN SMALL LETTER E WITH DIAERESIS +U+0119 # LATIN SMALL LETTER E WITH OGONEK +U+0113 # LATIN SMALL LETTER E WITH MACRON +U+0117 # LATIN SMALL LETTER E WITH DOT ABOVE +U+0259 # LATIN SMALL LETTER SCHWA +U+0066 # LATIN SMALL LETTER F +U+0067 # LATIN SMALL LETTER G +U+011F # LATIN SMALL LETTER G WITH BREVE +U+01E7 # LATIN SMALL LETTER G WITH CARON +U+0121 # LATIN SMALL LETTER G WITH DOT ABOVE +U+0123 # LATIN SMALL LETTER G WITH CEDILLA +U+01E5 # LATIN SMALL LETTER G WITH STROKE +U+0068 # LATIN SMALL LETTER H +U+0127 # LATIN SMALL LETTER H WITH STROKE +U+0069 # LATIN SMALL LETTER I +U+0131 # LATIN SMALL LETTER DOTLESS I +U+00ED # LATIN SMALL LETTER I WITH ACUTE +U+00EC # LATIN SMALL LETTER I WITH GRAVE +U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX +U+00EF # LATIN SMALL LETTER I WITH DIAERESIS +U+012F # LATIN SMALL LETTER I WITH OGONEK +U+012B # LATIN SMALL LETTER I WITH MACRON +U+01D0 # LATIN SMALL LETTER I WITH CARON +U+006A # LATIN SMALL LETTER J +U+006B # LATIN SMALL LETTER K +U+01E9 # LATIN SMALL LETTER K WITH CARON +U+0137 # LATIN SMALL LETTER K WITH CEDILLA +U+006C # LATIN SMALL LETTER L +U+013A # LATIN SMALL LETTER L WITH ACUTE +U+013E # LATIN SMALL LETTER L WITH CARON +U+013C # LATIN SMALL LETTER L WITH CEDILLA +U+0142 # LATIN SMALL LETTER L WITH STROKE +U+006D # LATIN SMALL LETTER M +U+006E # LATIN SMALL LETTER N +U+0144 # LATIN SMALL LETTER N WITH ACUTE +U+0148 # LATIN SMALL LETTER N WITH CARON +U+00F1 # LATIN SMALL LETTER N WITH TILDE +U+0146 # LATIN SMALL LETTER N WITH CEDILLA +U+014B # LATIN SMALL LETTER ENG +U+006F # LATIN SMALL LETTER O +U+00F3 # LATIN SMALL LETTER O WITH ACUTE +U+00F2 # LATIN SMALL LETTER O WITH GRAVE +U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX +U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS +U+0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE +U+00F5 # LATIN SMALL LETTER O WITH TILDE +U+014D # LATIN SMALL LETTER O WITH MACRON +U+01D2 # LATIN SMALL LETTER O WITH CARON +U+00F8 # LATIN SMALL LETTER O WITH STROKE +U+0153 # LATIN SMALL LIGATURE OE +U+0070 # LATIN SMALL LETTER P +U+0071 # LATIN SMALL LETTER Q +U+0072 # LATIN SMALL LETTER R +U+0155 # LATIN SMALL LETTER R WITH ACUTE +U+0159 # LATIN SMALL LETTER R WITH CARON +U+0157 # LATIN SMALL LETTER R WITH CEDILLA +U+0073 # LATIN SMALL LETTER S +U+015B # LATIN SMALL LETTER S WITH ACUTE +U+0161 # LATIN SMALL LETTER S WITH CARON +U+015F # LATIN SMALL LETTER S WITH CEDILLA +U+0074 # LATIN SMALL LETTER T +U+0165 # LATIN SMALL LETTER T WITH CARON +U+0163 # LATIN SMALL LETTER T WITH CEDILLA +U+0167 # LATIN SMALL LETTER T WITH STROKE +U+0075 # LATIN SMALL LETTER U +U+00FA # LATIN SMALL LETTER U WITH ACUTE +U+00F9 # LATIN SMALL LETTER U WITH GRAVE +U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX +U+016F # LATIN SMALL LETTER U WITH RING ABOVE +U+00FC # LATIN SMALL LETTER U WITH DIAERESIS +U+0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE +U+0173 # LATIN SMALL LETTER U WITH OGONEK +U+016B # LATIN SMALL LETTER U WITH MACRON +U+01D4 # LATIN SMALL LETTER U WITH CARON +U+0076 # LATIN SMALL LETTER V +U+0077 # LATIN SMALL LETTER W +U+1E83 # LATIN SMALL LETTER W WITH ACUTE +U+1E81 # LATIN SMALL LETTER W WITH GRAVE +U+0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX +U+1E85 # LATIN SMALL LETTER W WITH DIAERESIS +U+0078 # LATIN SMALL LETTER X +U+0079 # LATIN SMALL LETTER Y +U+00FD # LATIN SMALL LETTER Y WITH ACUTE +U+1EF3 # LATIN SMALL LETTER Y WITH GRAVE +U+0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX +U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS +U+007A # LATIN SMALL LETTER Z +U+017A # LATIN SMALL LETTER Z WITH ACUTE +U+017E # LATIN SMALL LETTER Z WITH CARON +U+017C # LATIN SMALL LETTER Z WITH DOT ABOVE +U+0292 # LATIN SMALL LETTER EZH +U+01EF # LATIN SMALL LETTER EZH WITH CARON +U+00FE # LATIN SMALL LETTER THORN diff --git a/java/com/google/domain/registry/tldconfig/idn/ja.txt b/java/com/google/domain/registry/tldconfig/idn/ja.txt new file mode 100644 index 000000000..322f831eb --- /dev/null +++ b/java/com/google/domain/registry/tldconfig/idn/ja.txt @@ -0,0 +1,6573 @@ +# URL: https://www.iana.org/domains/idn-tables/tables/google_ja_1.0.txt +# Policy: https://www.registry.google/about/policies/domainabuse/ +U+002D # HYPHEN-MINUS +U+0030 # DIGIT ZERO +U+0031 # DIGIT ONE +U+0032 # DIGIT TWO +U+0033 # DIGIT THREE +U+0034 # DIGIT FOUR +U+0035 # DIGIT FIVE +U+0036 # DIGIT SIX +U+0037 # DIGIT SEVEN +U+0038 # DIGIT EIGHT +U+0039 # DIGIT NINE +U+0061 # LATIN SMALL LETTER A +U+0062 # LATIN SMALL LETTER B +U+0063 # LATIN SMALL LETTER C +U+0064 # LATIN SMALL LETTER D +U+0065 # LATIN SMALL LETTER E +U+0066 # LATIN SMALL LETTER F +U+0067 # LATIN SMALL LETTER G +U+0068 # LATIN SMALL LETTER H +U+0069 # LATIN SMALL LETTER I +U+006A # LATIN SMALL LETTER J +U+006B # LATIN SMALL LETTER K +U+006C # LATIN SMALL LETTER L +U+006D # LATIN SMALL LETTER M +U+006E # LATIN SMALL LETTER N +U+006F # LATIN SMALL LETTER O +U+0070 # LATIN SMALL LETTER P +U+0071 # LATIN SMALL LETTER Q +U+0072 # LATIN SMALL LETTER R +U+0073 # LATIN SMALL LETTER S +U+0074 # LATIN SMALL LETTER T +U+0075 # LATIN SMALL LETTER U +U+0076 # LATIN SMALL LETTER V +U+0077 # LATIN SMALL LETTER W +U+0078 # LATIN SMALL LETTER X +U+0079 # LATIN SMALL LETTER Y +U+007A # LATIN SMALL LETTER Z +U+3005 # 01-25, IDEOGRAPHIC ITERATION MARK +U+3006 # 01-26, IDEOGRAPHIC CLOSING MARK +U+3007 # 01-27, IDEOGRAPHIC NUMBER ZERO +U+3041 # 04-01, HIRAGANA LETTER SMALL A +U+3042 # 04-02, HIRAGANA LETTER A +U+3043 # 04-03, HIRAGANA LETTER SMALL I +U+3044 # 04-04, HIRAGANA LETTER I +U+3045 # 04-05, HIRAGANA LETTER SMALL U +U+3046 # 04-06, HIRAGANA LETTER U +U+3047 # 04-07, HIRAGANA LETTER SMALL E +U+3048 # 04-08, HIRAGANA LETTER E +U+3049 # 04-09, HIRAGANA LETTER SMALL O +U+304A # 04-10, HIRAGANA LETTER O +U+304B # 04-11, HIRAGANA LETTER KA +U+304C # 04-12, HIRAGANA LETTER GA +U+304D # 04-13, HIRAGANA LETTER KI +U+304E # 04-14, HIRAGANA LETTER GI +U+304F # 04-15, HIRAGANA LETTER KU +U+3050 # 04-16, HIRAGANA LETTER GU +U+3051 # 04-17, HIRAGANA LETTER KE +U+3052 # 04-18, HIRAGANA LETTER GE +U+3053 # 04-19, HIRAGANA LETTER KO +U+3054 # 04-20, HIRAGANA LETTER GO +U+3055 # 04-21, HIRAGANA LETTER SA +U+3056 # 04-22, HIRAGANA LETTER ZA +U+3057 # 04-23, HIRAGANA LETTER SI +U+3058 # 04-24, HIRAGANA LETTER ZI +U+3059 # 04-25, HIRAGANA LETTER SU +U+305A # 04-26, HIRAGANA LETTER ZU +U+305B # 04-27, HIRAGANA LETTER SE +U+305C # 04-28, HIRAGANA LETTER ZE +U+305D # 04-29, HIRAGANA LETTER SO +U+305E # 04-30, HIRAGANA LETTER ZO +U+305F # 04-31, HIRAGANA LETTER TA +U+3060 # 04-32, HIRAGANA LETTER DA +U+3061 # 04-33, HIRAGANA LETTER TI +U+3062 # 04-34, HIRAGANA LETTER DI +U+3063 # 04-35, HIRAGANA LETTER SMALL TU +U+3064 # 04-36, HIRAGANA LETTER TU +U+3065 # 04-37, HIRAGANA LETTER DU +U+3066 # 04-38, HIRAGANA LETTER TE +U+3067 # 04-39, HIRAGANA LETTER DE +U+3068 # 04-40, HIRAGANA LETTER TO +U+3069 # 04-41, HIRAGANA LETTER DO +U+306A # 04-42, HIRAGANA LETTER NA +U+306B # 04-43, HIRAGANA LETTER NI +U+306C # 04-44, HIRAGANA LETTER NU +U+306D # 04-45, HIRAGANA LETTER NE +U+306E # 04-46, HIRAGANA LETTER NO +U+306F # 04-47, HIRAGANA LETTER HA +U+3070 # 04-48, HIRAGANA LETTER BA +U+3071 # 04-49, HIRAGANA LETTER PA +U+3072 # 04-50, HIRAGANA LETTER HI +U+3073 # 04-51, HIRAGANA LETTER BI +U+3074 # 04-52, HIRAGANA LETTER PI +U+3075 # 04-53, HIRAGANA LETTER HU +U+3076 # 04-54, HIRAGANA LETTER BU +U+3077 # 04-55, HIRAGANA LETTER PU +U+3078 # 04-56, HIRAGANA LETTER HE +U+3079 # 04-57, HIRAGANA LETTER BE +U+307A # 04-58, HIRAGANA LETTER PE +U+307B # 04-59, HIRAGANA LETTER HO +U+307C # 04-60, HIRAGANA LETTER BO +U+307D # 04-61, HIRAGANA LETTER PO +U+307E # 04-62, HIRAGANA LETTER MA +U+307F # 04-63, HIRAGANA LETTER MI +U+3080 # 04-64, HIRAGANA LETTER MU +U+3081 # 04-65, HIRAGANA LETTER ME +U+3082 # 04-66, HIRAGANA LETTER MO +U+3083 # 04-67, HIRAGANA LETTER SMALL YA +U+3084 # 04-68, HIRAGANA LETTER YA +U+3085 # 04-69, HIRAGANA LETTER SMALL YU +U+3086 # 04-70, HIRAGANA LETTER YU +U+3087 # 04-71, HIRAGANA LETTER SMALL YO +U+3088 # 04-72, HIRAGANA LETTER YO +U+3089 # 04-73, HIRAGANA LETTER RA +U+308A # 04-74, HIRAGANA LETTER RI +U+308B # 04-75, HIRAGANA LETTER RU +U+308C # 04-76, HIRAGANA LETTER RE +U+308D # 04-77, HIRAGANA LETTER RO +U+308E # 04-78, HIRAGANA LETTER SMALL WA +U+308F # 04-79, HIRAGANA LETTER WA +U+3090 # 04-80, HIRAGANA LETTER WI +U+3091 # 04-81, HIRAGANA LETTER WE +U+3092 # 04-82, HIRAGANA LETTER WO +U+3093 # 04-83, HIRAGANA LETTER N +U+309D # 01-21, HIRAGANA ITERATION MARK +U+309E # 01-22, HIRAGANA VOICED ITERATION MARK +U+30A1 # 05-01, KATAKANA LETTER SMALL A +U+30A2 # 05-02, KATAKANA LETTER A +U+30A3 # 05-03, KATAKANA LETTER SMALL I +U+30A4 # 05-04, KATAKANA LETTER I +U+30A5 # 05-05, KATAKANA LETTER SMALL U +U+30A6 # 05-06, KATAKANA LETTER U +U+30A7 # 05-07, KATAKANA LETTER SMALL E +U+30A8 # 05-08, KATAKANA LETTER E +U+30A9 # 05-09, KATAKANA LETTER SMALL O +U+30AA # 05-10, KATAKANA LETTER O +U+30AB # 05-11, KATAKANA LETTER KA +U+30AC # 05-12, KATAKANA LETTER GA +U+30AD # 05-13, KATAKANA LETTER KI +U+30AE # 05-14, KATAKANA LETTER GI +U+30AF # 05-15, KATAKANA LETTER KU +U+30B0 # 05-16, KATAKANA LETTER GU +U+30B1 # 05-17, KATAKANA LETTER KE +U+30B2 # 05-18, KATAKANA LETTER GE +U+30B3 # 05-19, KATAKANA LETTER KO +U+30B4 # 05-20, KATAKANA LETTER GO +U+30B5 # 05-21, KATAKANA LETTER SA +U+30B6 # 05-22, KATAKANA LETTER ZA +U+30B7 # 05-23, KATAKANA LETTER SI +U+30B8 # 05-24, KATAKANA LETTER ZI +U+30B9 # 05-25, KATAKANA LETTER SU +U+30BA # 05-26, KATAKANA LETTER ZU +U+30BB # 05-27, KATAKANA LETTER SE +U+30BC # 05-28, KATAKANA LETTER ZE +U+30BD # 05-29, KATAKANA LETTER SO +U+30BE # 05-30, KATAKANA LETTER ZO +U+30BF # 05-31, KATAKANA LETTER TA +U+30C0 # 05-32, KATAKANA LETTER DA +U+30C1 # 05-33, KATAKANA LETTER TI +U+30C2 # 05-34, KATAKANA LETTER DI +U+30C3 # 05-35, KATAKANA LETTER SMALL TU +U+30C4 # 05-36, KATAKANA LETTER TU +U+30C5 # 05-37, KATAKANA LETTER DU +U+30C6 # 05-38, KATAKANA LETTER TE +U+30C7 # 05-39, KATAKANA LETTER DE +U+30C8 # 05-40, KATAKANA LETTER TO +U+30C9 # 05-41, KATAKANA LETTER DO +U+30CA # 05-42, KATAKANA LETTER NA +U+30CB # 05-43, KATAKANA LETTER NI +U+30CC # 05-44, KATAKANA LETTER NU +U+30CD # 05-45, KATAKANA LETTER NE +U+30CE # 05-46, KATAKANA LETTER NO +U+30CF # 05-47, KATAKANA LETTER HA +U+30D0 # 05-48, KATAKANA LETTER BA +U+30D1 # 05-49, KATAKANA LETTER PA +U+30D2 # 05-50, KATAKANA LETTER HI +U+30D3 # 05-51, KATAKANA LETTER BI +U+30D4 # 05-52, KATAKANA LETTER PI +U+30D5 # 05-53, KATAKANA LETTER HU +U+30D6 # 05-54, KATAKANA LETTER BU +U+30D7 # 05-55, KATAKANA LETTER PU +U+30D8 # 05-56, KATAKANA LETTER HE +U+30D9 # 05-57, KATAKANA LETTER BE +U+30DA # 05-58, KATAKANA LETTER PE +U+30DB # 05-59, KATAKANA LETTER HO +U+30DC # 05-60, KATAKANA LETTER BO +U+30DD # 05-61, KATAKANA LETTER PO +U+30DE # 05-62, KATAKANA LETTER MA +U+30DF # 05-63, KATAKANA LETTER MI +U+30E0 # 05-64, KATAKANA LETTER MU +U+30E1 # 05-65, KATAKANA LETTER ME +U+30E2 # 05-66, KATAKANA LETTER MO +U+30E3 # 05-67, KATAKANA LETTER SMALL YA +U+30E4 # 05-68, KATAKANA LETTER YA +U+30E5 # 05-69, KATAKANA LETTER SMALL YU +U+30E6 # 05-70, KATAKANA LETTER YU +U+30E7 # 05-71, KATAKANA LETTER SMALL YO +U+30E8 # 05-72, KATAKANA LETTER YO +U+30E9 # 05-73, KATAKANA LETTER RA +U+30EA # 05-74, KATAKANA LETTER RI +U+30EB # 05-75, KATAKANA LETTER RU +U+30EC # 05-76, KATAKANA LETTER RE +U+30ED # 05-77, KATAKANA LETTER RO +U+30EE # 05-78, KATAKANA LETTER SMALL WA +U+30EF # 05-79, KATAKANA LETTER WA +U+30F0 # 05-80, KATAKANA LETTER WI +U+30F1 # 05-81, KATAKANA LETTER WE +U+30F2 # 05-82, KATAKANA LETTER WO +U+30F3 # 05-83, KATAKANA LETTER N +U+30F4 # 05-84, KATAKANA LETTER VU +U+30F5 # 05-85, KATAKANA LETTER SMALL KA +U+30F6 # 05-86, KATAKANA LETTER SMALL KE +U+30FB # 01-06, KATAKANA MIDDLE DOT +U+30FC # 01-28, KATAKANA-HIRAGANA PROLONGED SOUND MARK +U+30FD # 01-19, KATAKANA ITERATION MARK +U+30FE # 01-20, KATAKANA VOICED ITERATION MARK +U+4E00 # 16-76, CJK UNIFIED IDEOGRAPH-4E00 +U+4E01 # 35-90, CJK UNIFIED IDEOGRAPH-4E01 +U+4E03 # 28-23, CJK UNIFIED IDEOGRAPH-4E03 +U+4E07 # 43-92, CJK UNIFIED IDEOGRAPH-4E07 +U+4E08 # 30-70, CJK UNIFIED IDEOGRAPH-4E08 +U+4E09 # 27-16, CJK UNIFIED IDEOGRAPH-4E09 +U+4E0A # 30-69, CJK UNIFIED IDEOGRAPH-4E0A +U+4E0B # 18-28, CJK UNIFIED IDEOGRAPH-4E0B +U+4E0D # 41-52, CJK UNIFIED IDEOGRAPH-4E0D +U+4E0E # 45-31, CJK UNIFIED IDEOGRAPH-4E0E +U+4E10 # 48-02, CJK UNIFIED IDEOGRAPH-4E10 +U+4E11 # 17-15, CJK UNIFIED IDEOGRAPH-4E11 +U+4E14 # 19-78, CJK UNIFIED IDEOGRAPH-4E14 +U+4E15 # 48-03, CJK UNIFIED IDEOGRAPH-4E15 +U+4E16 # 32-04, CJK UNIFIED IDEOGRAPH-4E16 +U+4E17 # 50-34, CJK UNIFIED IDEOGRAPH-4E17 +U+4E18 # 21-54, CJK UNIFIED IDEOGRAPH-4E18 +U+4E19 # 42-26, CJK UNIFIED IDEOGRAPH-4E19 +U+4E1E # 30-71, CJK UNIFIED IDEOGRAPH-4E1E +U+4E21 # 46-30, CJK UNIFIED IDEOGRAPH-4E21 +U+4E26 # 42-34, CJK UNIFIED IDEOGRAPH-4E26 +U+4E2A # 48-04, CJK UNIFIED IDEOGRAPH-4E2A +U+4E2D # 35-70, CJK UNIFIED IDEOGRAPH-4E2D +U+4E31 # 48-05, CJK UNIFIED IDEOGRAPH-4E31 +U+4E32 # 22-90, CJK UNIFIED IDEOGRAPH-4E32 +U+4E36 # 48-06, CJK UNIFIED IDEOGRAPH-4E36 +U+4E38 # 20-61, CJK UNIFIED IDEOGRAPH-4E38 +U+4E39 # 35-16, CJK UNIFIED IDEOGRAPH-4E39 +U+4E3B # 28-71, CJK UNIFIED IDEOGRAPH-4E3B +U+4E3C # 48-07, CJK UNIFIED IDEOGRAPH-4E3C +U+4E3F # 48-08, CJK UNIFIED IDEOGRAPH-4E3F +U+4E42 # 48-09, CJK UNIFIED IDEOGRAPH-4E42 +U+4E43 # 39-21, CJK UNIFIED IDEOGRAPH-4E43 +U+4E45 # 21-55, CJK UNIFIED IDEOGRAPH-4E45 +U+4E4B # 39-23, CJK UNIFIED IDEOGRAPH-4E4B +U+4E4D # 38-67, CJK UNIFIED IDEOGRAPH-4E4D +U+4E4E # 24-35, CJK UNIFIED IDEOGRAPH-4E4E +U+4E4F # 43-19, CJK UNIFIED IDEOGRAPH-4E4F +U+4E55 # 73-41, CJK UNIFIED IDEOGRAPH-4E55 +U+4E56 # 48-10, CJK UNIFIED IDEOGRAPH-4E56 +U+4E57 # 30-72, CJK UNIFIED IDEOGRAPH-4E57 +U+4E58 # 48-11, CJK UNIFIED IDEOGRAPH-4E58 +U+4E59 # 18-21, CJK UNIFIED IDEOGRAPH-4E59 +U+4E5D # 22-69, CJK UNIFIED IDEOGRAPH-4E5D +U+4E5E # 24-80, CJK UNIFIED IDEOGRAPH-4E5E +U+4E5F # 44-73, CJK UNIFIED IDEOGRAPH-4E5F +U+4E62 # 54-06, CJK UNIFIED IDEOGRAPH-4E62 +U+4E71 # 45-80, CJK UNIFIED IDEOGRAPH-4E71 +U+4E73 # 38-93, CJK UNIFIED IDEOGRAPH-4E73 +U+4E7E # 20-05, CJK UNIFIED IDEOGRAPH-4E7E +U+4E80 # 21-21, CJK UNIFIED IDEOGRAPH-4E80 +U+4E82 # 48-12, CJK UNIFIED IDEOGRAPH-4E82 +U+4E85 # 48-13, CJK UNIFIED IDEOGRAPH-4E85 +U+4E86 # 46-27, CJK UNIFIED IDEOGRAPH-4E86 +U+4E88 # 45-29, CJK UNIFIED IDEOGRAPH-4E88 +U+4E89 # 33-72, CJK UNIFIED IDEOGRAPH-4E89 +U+4E8A # 48-15, CJK UNIFIED IDEOGRAPH-4E8A +U+4E8B # 27-86, CJK UNIFIED IDEOGRAPH-4E8B +U+4E8C # 38-83, CJK UNIFIED IDEOGRAPH-4E8C +U+4E8E # 48-18, CJK UNIFIED IDEOGRAPH-4E8E +U+4E91 # 17-30, CJK UNIFIED IDEOGRAPH-4E91 +U+4E92 # 24-63, CJK UNIFIED IDEOGRAPH-4E92 +U+4E94 # 24-62, CJK UNIFIED IDEOGRAPH-4E94 +U+4E95 # 16-70, CJK UNIFIED IDEOGRAPH-4E95 +U+4E98 # 47-43, CJK UNIFIED IDEOGRAPH-4E98 +U+4E99 # 47-42, CJK UNIFIED IDEOGRAPH-4E99 +U+4E9B # 26-19, CJK UNIFIED IDEOGRAPH-4E9B +U+4E9C # 16-01, CJK UNIFIED IDEOGRAPH-4E9C +U+4E9E # 48-19, CJK UNIFIED IDEOGRAPH-4E9E +U+4E9F # 48-20, CJK UNIFIED IDEOGRAPH-4E9F +U+4EA0 # 48-21, CJK UNIFIED IDEOGRAPH-4EA0 +U+4EA1 # 43-20, CJK UNIFIED IDEOGRAPH-4EA1 +U+4EA2 # 48-22, CJK UNIFIED IDEOGRAPH-4EA2 +U+4EA4 # 24-82, CJK UNIFIED IDEOGRAPH-4EA4 +U+4EA5 # 16-71, CJK UNIFIED IDEOGRAPH-4EA5 +U+4EA6 # 43-82, CJK UNIFIED IDEOGRAPH-4EA6 +U+4EA8 # 21-92, CJK UNIFIED IDEOGRAPH-4EA8 +U+4EAB # 21-93, CJK UNIFIED IDEOGRAPH-4EAB +U+4EAC # 21-94, CJK UNIFIED IDEOGRAPH-4EAC +U+4EAD # 36-66, CJK UNIFIED IDEOGRAPH-4EAD +U+4EAE # 46-28, CJK UNIFIED IDEOGRAPH-4EAE +U+4EB0 # 48-23, CJK UNIFIED IDEOGRAPH-4EB0 +U+4EB3 # 48-24, CJK UNIFIED IDEOGRAPH-4EB3 +U+4EB6 # 48-25, CJK UNIFIED IDEOGRAPH-4EB6 +U+4EBA # 31-45, CJK UNIFIED IDEOGRAPH-4EBA +U+4EC0 # 29-26, CJK UNIFIED IDEOGRAPH-4EC0 +U+4EC1 # 31-46, CJK UNIFIED IDEOGRAPH-4EC1 +U+4EC2 # 48-30, CJK UNIFIED IDEOGRAPH-4EC2 +U+4EC4 # 48-28, CJK UNIFIED IDEOGRAPH-4EC4 +U+4EC6 # 48-29, CJK UNIFIED IDEOGRAPH-4EC6 +U+4EC7 # 21-56, CJK UNIFIED IDEOGRAPH-4EC7 +U+4ECA # 26-03, CJK UNIFIED IDEOGRAPH-4ECA +U+4ECB # 18-80, CJK UNIFIED IDEOGRAPH-4ECB +U+4ECD # 48-27, CJK UNIFIED IDEOGRAPH-4ECD +U+4ECE # 48-26, CJK UNIFIED IDEOGRAPH-4ECE +U+4ECF # 42-09, CJK UNIFIED IDEOGRAPH-4ECF +U+4ED4 # 27-38, CJK UNIFIED IDEOGRAPH-4ED4 +U+4ED5 # 27-37, CJK UNIFIED IDEOGRAPH-4ED5 +U+4ED6 # 34-30, CJK UNIFIED IDEOGRAPH-4ED6 +U+4ED7 # 48-31, CJK UNIFIED IDEOGRAPH-4ED7 +U+4ED8 # 41-53, CJK UNIFIED IDEOGRAPH-4ED8 +U+4ED9 # 32-71, CJK UNIFIED IDEOGRAPH-4ED9 +U+4EDD # 01-24, CJK UNIFIED IDEOGRAPH-4EDD +U+4EDE # 48-32, CJK UNIFIED IDEOGRAPH-4EDE +U+4EDF # 48-34, CJK UNIFIED IDEOGRAPH-4EDF +U+4EE3 # 34-69, CJK UNIFIED IDEOGRAPH-4EE3 +U+4EE4 # 46-65, CJK UNIFIED IDEOGRAPH-4EE4 +U+4EE5 # 16-42, CJK UNIFIED IDEOGRAPH-4EE5 +U+4EED # 48-33, CJK UNIFIED IDEOGRAPH-4EED +U+4EEE # 18-30, CJK UNIFIED IDEOGRAPH-4EEE +U+4EF0 # 22-36, CJK UNIFIED IDEOGRAPH-4EF0 +U+4EF2 # 35-71, CJK UNIFIED IDEOGRAPH-4EF2 +U+4EF6 # 23-79, CJK UNIFIED IDEOGRAPH-4EF6 +U+4EF7 # 48-35, CJK UNIFIED IDEOGRAPH-4EF7 +U+4EFB # 39-04, CJK UNIFIED IDEOGRAPH-4EFB +U+4F01 # 20-75, CJK UNIFIED IDEOGRAPH-4F01 +U+4F09 # 48-36, CJK UNIFIED IDEOGRAPH-4F09 +U+4F0A # 16-43, CJK UNIFIED IDEOGRAPH-4F0A +U+4F0D # 24-64, CJK UNIFIED IDEOGRAPH-4F0D +U+4F0E # 20-76, CJK UNIFIED IDEOGRAPH-4F0E +U+4F0F # 41-90, CJK UNIFIED IDEOGRAPH-4F0F +U+4F10 # 40-18, CJK UNIFIED IDEOGRAPH-4F10 +U+4F11 # 21-57, CJK UNIFIED IDEOGRAPH-4F11 +U+4F1A # 18-81, CJK UNIFIED IDEOGRAPH-4F1A +U+4F1C # 48-71, CJK UNIFIED IDEOGRAPH-4F1C +U+4F1D # 37-33, CJK UNIFIED IDEOGRAPH-4F1D +U+4F2F # 39-76, CJK UNIFIED IDEOGRAPH-4F2F +U+4F30 # 48-38, CJK UNIFIED IDEOGRAPH-4F30 +U+4F34 # 40-28, CJK UNIFIED IDEOGRAPH-4F34 +U+4F36 # 46-66, CJK UNIFIED IDEOGRAPH-4F36 +U+4F38 # 31-13, CJK UNIFIED IDEOGRAPH-4F38 +U+4F3A # 27-39, CJK UNIFIED IDEOGRAPH-4F3A +U+4F3C # 27-87, CJK UNIFIED IDEOGRAPH-4F3C +U+4F3D # 18-32, CJK UNIFIED IDEOGRAPH-4F3D +U+4F43 # 36-49, CJK UNIFIED IDEOGRAPH-4F43 +U+4F46 # 35-02, CJK UNIFIED IDEOGRAPH-4F46 +U+4F47 # 48-42, CJK UNIFIED IDEOGRAPH-4F47 +U+4F4D # 16-44, CJK UNIFIED IDEOGRAPH-4F4D +U+4F4E # 36-67, CJK UNIFIED IDEOGRAPH-4F4E +U+4F4F # 29-27, CJK UNIFIED IDEOGRAPH-4F4F +U+4F50 # 26-20, CJK UNIFIED IDEOGRAPH-4F50 +U+4F51 # 45-04, CJK UNIFIED IDEOGRAPH-4F51 +U+4F53 # 34-46, CJK UNIFIED IDEOGRAPH-4F53 +U+4F55 # 18-31, CJK UNIFIED IDEOGRAPH-4F55 +U+4F57 # 48-41, CJK UNIFIED IDEOGRAPH-4F57 +U+4F59 # 45-30, CJK UNIFIED IDEOGRAPH-4F59 +U+4F5A # 48-37, CJK UNIFIED IDEOGRAPH-4F5A +U+4F5B # 48-39, CJK UNIFIED IDEOGRAPH-4F5B +U+4F5C # 26-78, CJK UNIFIED IDEOGRAPH-4F5C +U+4F5D # 48-40, CJK UNIFIED IDEOGRAPH-4F5D +U+4F5E # 53-04, CJK UNIFIED IDEOGRAPH-4F5E +U+4F69 # 48-48, CJK UNIFIED IDEOGRAPH-4F69 +U+4F6F # 48-51, CJK UNIFIED IDEOGRAPH-4F6F +U+4F70 # 48-49, CJK UNIFIED IDEOGRAPH-4F70 +U+4F73 # 18-34, CJK UNIFIED IDEOGRAPH-4F73 +U+4F75 # 42-27, CJK UNIFIED IDEOGRAPH-4F75 +U+4F76 # 48-43, CJK UNIFIED IDEOGRAPH-4F76 +U+4F7B # 48-47, CJK UNIFIED IDEOGRAPH-4F7B +U+4F7C # 24-83, CJK UNIFIED IDEOGRAPH-4F7C +U+4F7F # 27-40, CJK UNIFIED IDEOGRAPH-4F7F +U+4F83 # 20-06, CJK UNIFIED IDEOGRAPH-4F83 +U+4F86 # 48-52, CJK UNIFIED IDEOGRAPH-4F86 +U+4F88 # 48-44, CJK UNIFIED IDEOGRAPH-4F88 +U+4F8B # 46-67, CJK UNIFIED IDEOGRAPH-4F8B +U+4F8D # 27-88, CJK UNIFIED IDEOGRAPH-4F8D +U+4F8F # 48-45, CJK UNIFIED IDEOGRAPH-4F8F +U+4F91 # 48-50, CJK UNIFIED IDEOGRAPH-4F91 +U+4F96 # 48-53, CJK UNIFIED IDEOGRAPH-4F96 +U+4F98 # 48-46, CJK UNIFIED IDEOGRAPH-4F98 +U+4F9B # 22-01, CJK UNIFIED IDEOGRAPH-4F9B +U+4F9D # 16-45, CJK UNIFIED IDEOGRAPH-4F9D +U+4FA0 # 22-02, CJK UNIFIED IDEOGRAPH-4FA0 +U+4FA1 # 18-33, CJK UNIFIED IDEOGRAPH-4FA1 +U+4FAB # 53-05, CJK UNIFIED IDEOGRAPH-4FAB +U+4FAD # 43-89, CJK UNIFIED IDEOGRAPH-4FAD +U+4FAE # 41-78, CJK UNIFIED IDEOGRAPH-4FAE +U+4FAF # 24-84, CJK UNIFIED IDEOGRAPH-4FAF +U+4FB5 # 31-15, CJK UNIFIED IDEOGRAPH-4FB5 +U+4FB6 # 46-23, CJK UNIFIED IDEOGRAPH-4FB6 +U+4FBF # 42-56, CJK UNIFIED IDEOGRAPH-4FBF +U+4FC2 # 23-24, CJK UNIFIED IDEOGRAPH-4FC2 +U+4FC3 # 34-05, CJK UNIFIED IDEOGRAPH-4FC3 +U+4FC4 # 18-68, CJK UNIFIED IDEOGRAPH-4FC4 +U+4FCA # 29-51, CJK UNIFIED IDEOGRAPH-4FCA +U+4FCE # 48-57, CJK UNIFIED IDEOGRAPH-4FCE +U+4FD0 # 48-62, CJK UNIFIED IDEOGRAPH-4FD0 +U+4FD1 # 48-60, CJK UNIFIED IDEOGRAPH-4FD1 +U+4FD4 # 48-55, CJK UNIFIED IDEOGRAPH-4FD4 +U+4FD7 # 34-15, CJK UNIFIED IDEOGRAPH-4FD7 +U+4FD8 # 48-58, CJK UNIFIED IDEOGRAPH-4FD8 +U+4FDA # 48-61, CJK UNIFIED IDEOGRAPH-4FDA +U+4FDB # 48-59, CJK UNIFIED IDEOGRAPH-4FDB +U+4FDD # 42-61, CJK UNIFIED IDEOGRAPH-4FDD +U+4FDF # 48-56, CJK UNIFIED IDEOGRAPH-4FDF +U+4FE1 # 31-14, CJK UNIFIED IDEOGRAPH-4FE1 +U+4FE3 # 43-83, CJK UNIFIED IDEOGRAPH-4FE3 +U+4FE4 # 48-63, CJK UNIFIED IDEOGRAPH-4FE4 +U+4FE5 # 48-64, CJK UNIFIED IDEOGRAPH-4FE5 +U+4FEE # 29-04, CJK UNIFIED IDEOGRAPH-4FEE +U+4FEF # 48-77, CJK UNIFIED IDEOGRAPH-4FEF +U+4FF3 # 39-48, CJK UNIFIED IDEOGRAPH-4FF3 +U+4FF5 # 41-22, CJK UNIFIED IDEOGRAPH-4FF5 +U+4FF6 # 48-72, CJK UNIFIED IDEOGRAPH-4FF6 +U+4FF8 # 42-80, CJK UNIFIED IDEOGRAPH-4FF8 +U+4FFA # 18-22, CJK UNIFIED IDEOGRAPH-4FFA +U+4FFE # 48-76, CJK UNIFIED IDEOGRAPH-4FFE +U+5005 # 48-70, CJK UNIFIED IDEOGRAPH-5005 +U+5006 # 48-79, CJK UNIFIED IDEOGRAPH-5006 +U+5009 # 33-50, CJK UNIFIED IDEOGRAPH-5009 +U+500B # 24-36, CJK UNIFIED IDEOGRAPH-500B +U+500D # 39-60, CJK UNIFIED IDEOGRAPH-500D +U+500F # 64-39, CJK UNIFIED IDEOGRAPH-500F +U+5011 # 48-78, CJK UNIFIED IDEOGRAPH-5011 +U+5012 # 37-61, CJK UNIFIED IDEOGRAPH-5012 +U+5014 # 48-67, CJK UNIFIED IDEOGRAPH-5014 +U+5016 # 24-86, CJK UNIFIED IDEOGRAPH-5016 +U+5019 # 24-85, CJK UNIFIED IDEOGRAPH-5019 +U+501A # 48-65, CJK UNIFIED IDEOGRAPH-501A +U+501F # 28-58, CJK UNIFIED IDEOGRAPH-501F +U+5021 # 48-73, CJK UNIFIED IDEOGRAPH-5021 +U+5023 # 42-79, CJK UNIFIED IDEOGRAPH-5023 +U+5024 # 35-45, CJK UNIFIED IDEOGRAPH-5024 +U+5025 # 48-69, CJK UNIFIED IDEOGRAPH-5025 +U+5026 # 23-81, CJK UNIFIED IDEOGRAPH-5026 +U+5028 # 48-66, CJK UNIFIED IDEOGRAPH-5028 +U+5029 # 48-74, CJK UNIFIED IDEOGRAPH-5029 +U+502A # 48-68, CJK UNIFIED IDEOGRAPH-502A +U+502B # 46-49, CJK UNIFIED IDEOGRAPH-502B +U+502C # 48-75, CJK UNIFIED IDEOGRAPH-502C +U+502D # 47-33, CJK UNIFIED IDEOGRAPH-502D +U+5036 # 22-70, CJK UNIFIED IDEOGRAPH-5036 +U+5039 # 23-80, CJK UNIFIED IDEOGRAPH-5039 +U+5043 # 48-80, CJK UNIFIED IDEOGRAPH-5043 +U+5047 # 48-81, CJK UNIFIED IDEOGRAPH-5047 +U+5048 # 48-85, CJK UNIFIED IDEOGRAPH-5048 +U+5049 # 16-46, CJK UNIFIED IDEOGRAPH-5049 +U+504F # 42-48, CJK UNIFIED IDEOGRAPH-504F +U+5050 # 48-84, CJK UNIFIED IDEOGRAPH-5050 +U+5055 # 48-83, CJK UNIFIED IDEOGRAPH-5055 +U+5056 # 48-87, CJK UNIFIED IDEOGRAPH-5056 +U+505A # 48-86, CJK UNIFIED IDEOGRAPH-505A +U+505C # 36-68, CJK UNIFIED IDEOGRAPH-505C +U+5065 # 23-82, CJK UNIFIED IDEOGRAPH-5065 +U+506C # 48-88, CJK UNIFIED IDEOGRAPH-506C +U+5072 # 28-37, CJK UNIFIED IDEOGRAPH-5072 +U+5074 # 34-06, CJK UNIFIED IDEOGRAPH-5074 +U+5075 # 36-69, CJK UNIFIED IDEOGRAPH-5075 +U+5076 # 22-86, CJK UNIFIED IDEOGRAPH-5076 +U+5078 # 48-89, CJK UNIFIED IDEOGRAPH-5078 +U+507D # 21-22, CJK UNIFIED IDEOGRAPH-507D +U+5080 # 48-90, CJK UNIFIED IDEOGRAPH-5080 +U+5085 # 48-92, CJK UNIFIED IDEOGRAPH-5085 +U+508D # 43-21, CJK UNIFIED IDEOGRAPH-508D +U+5091 # 23-70, CJK UNIFIED IDEOGRAPH-5091 +U+5098 # 27-17, CJK UNIFIED IDEOGRAPH-5098 +U+5099 # 40-87, CJK UNIFIED IDEOGRAPH-5099 +U+509A # 48-91, CJK UNIFIED IDEOGRAPH-509A +U+50AC # 26-37, CJK UNIFIED IDEOGRAPH-50AC +U+50AD # 45-35, CJK UNIFIED IDEOGRAPH-50AD +U+50B2 # 48-94, CJK UNIFIED IDEOGRAPH-50B2 +U+50B3 # 49-03, CJK UNIFIED IDEOGRAPH-50B3 +U+50B4 # 48-93, CJK UNIFIED IDEOGRAPH-50B4 +U+50B5 # 26-36, CJK UNIFIED IDEOGRAPH-50B5 +U+50B7 # 29-93, CJK UNIFIED IDEOGRAPH-50B7 +U+50BE # 23-25, CJK UNIFIED IDEOGRAPH-50BE +U+50C2 # 49-04, CJK UNIFIED IDEOGRAPH-50C2 +U+50C5 # 22-47, CJK UNIFIED IDEOGRAPH-50C5 +U+50C9 # 49-01, CJK UNIFIED IDEOGRAPH-50C9 +U+50CA # 49-02, CJK UNIFIED IDEOGRAPH-50CA +U+50CD # 38-15, CJK UNIFIED IDEOGRAPH-50CD +U+50CF # 33-92, CJK UNIFIED IDEOGRAPH-50CF +U+50D1 # 22-03, CJK UNIFIED IDEOGRAPH-50D1 +U+50D5 # 43-45, CJK UNIFIED IDEOGRAPH-50D5 +U+50D6 # 49-05, CJK UNIFIED IDEOGRAPH-50D6 +U+50DA # 46-29, CJK UNIFIED IDEOGRAPH-50DA +U+50DE # 49-06, CJK UNIFIED IDEOGRAPH-50DE +U+50E3 # 49-09, CJK UNIFIED IDEOGRAPH-50E3 +U+50E5 # 49-07, CJK UNIFIED IDEOGRAPH-50E5 +U+50E7 # 33-46, CJK UNIFIED IDEOGRAPH-50E7 +U+50ED # 49-08, CJK UNIFIED IDEOGRAPH-50ED +U+50EE # 49-10, CJK UNIFIED IDEOGRAPH-50EE +U+50F5 # 49-12, CJK UNIFIED IDEOGRAPH-50F5 +U+50F9 # 49-11, CJK UNIFIED IDEOGRAPH-50F9 +U+50FB # 42-40, CJK UNIFIED IDEOGRAPH-50FB +U+5100 # 21-23, CJK UNIFIED IDEOGRAPH-5100 +U+5101 # 49-14, CJK UNIFIED IDEOGRAPH-5101 +U+5102 # 49-15, CJK UNIFIED IDEOGRAPH-5102 +U+5104 # 18-15, CJK UNIFIED IDEOGRAPH-5104 +U+5109 # 49-13, CJK UNIFIED IDEOGRAPH-5109 +U+5112 # 28-84, CJK UNIFIED IDEOGRAPH-5112 +U+5114 # 49-18, CJK UNIFIED IDEOGRAPH-5114 +U+5115 # 49-17, CJK UNIFIED IDEOGRAPH-5115 +U+5116 # 49-16, CJK UNIFIED IDEOGRAPH-5116 +U+5118 # 48-54, CJK UNIFIED IDEOGRAPH-5118 +U+511A # 49-19, CJK UNIFIED IDEOGRAPH-511A +U+511F # 29-94, CJK UNIFIED IDEOGRAPH-511F +U+5121 # 49-20, CJK UNIFIED IDEOGRAPH-5121 +U+512A # 45-05, CJK UNIFIED IDEOGRAPH-512A +U+5132 # 44-57, CJK UNIFIED IDEOGRAPH-5132 +U+5137 # 49-22, CJK UNIFIED IDEOGRAPH-5137 +U+513A # 49-21, CJK UNIFIED IDEOGRAPH-513A +U+513B # 49-24, CJK UNIFIED IDEOGRAPH-513B +U+513C # 49-23, CJK UNIFIED IDEOGRAPH-513C +U+513F # 49-25, CJK UNIFIED IDEOGRAPH-513F +U+5140 # 49-26, CJK UNIFIED IDEOGRAPH-5140 +U+5141 # 16-84, CJK UNIFIED IDEOGRAPH-5141 +U+5143 # 24-21, CJK UNIFIED IDEOGRAPH-5143 +U+5144 # 23-27, CJK UNIFIED IDEOGRAPH-5144 +U+5145 # 29-28, CJK UNIFIED IDEOGRAPH-5145 +U+5146 # 35-91, CJK UNIFIED IDEOGRAPH-5146 +U+5147 # 22-04, CJK UNIFIED IDEOGRAPH-5147 +U+5148 # 32-72, CJK UNIFIED IDEOGRAPH-5148 +U+5149 # 24-87, CJK UNIFIED IDEOGRAPH-5149 +U+514B # 25-78, CJK UNIFIED IDEOGRAPH-514B +U+514C # 49-28, CJK UNIFIED IDEOGRAPH-514C +U+514D # 44-40, CJK UNIFIED IDEOGRAPH-514D +U+514E # 37-38, CJK UNIFIED IDEOGRAPH-514E +U+5150 # 27-89, CJK UNIFIED IDEOGRAPH-5150 +U+5152 # 49-27, CJK UNIFIED IDEOGRAPH-5152 +U+5154 # 49-29, CJK UNIFIED IDEOGRAPH-5154 +U+515A # 37-62, CJK UNIFIED IDEOGRAPH-515A +U+515C # 19-85, CJK UNIFIED IDEOGRAPH-515C +U+5162 # 49-30, CJK UNIFIED IDEOGRAPH-5162 +U+5165 # 38-94, CJK UNIFIED IDEOGRAPH-5165 +U+5168 # 33-20, CJK UNIFIED IDEOGRAPH-5168 +U+5169 # 49-32, CJK UNIFIED IDEOGRAPH-5169 +U+516A # 49-33, CJK UNIFIED IDEOGRAPH-516A +U+516B # 40-12, CJK UNIFIED IDEOGRAPH-516B +U+516C # 24-88, CJK UNIFIED IDEOGRAPH-516C +U+516D # 47-27, CJK UNIFIED IDEOGRAPH-516D +U+516E # 49-34, CJK UNIFIED IDEOGRAPH-516E +U+5171 # 22-06, CJK UNIFIED IDEOGRAPH-5171 +U+5175 # 42-28, CJK UNIFIED IDEOGRAPH-5175 +U+5176 # 34-22, CJK UNIFIED IDEOGRAPH-5176 +U+5177 # 22-81, CJK UNIFIED IDEOGRAPH-5177 +U+5178 # 37-21, CJK UNIFIED IDEOGRAPH-5178 +U+517C # 23-83, CJK UNIFIED IDEOGRAPH-517C +U+5180 # 49-35, CJK UNIFIED IDEOGRAPH-5180 +U+5182 # 49-36, CJK UNIFIED IDEOGRAPH-5182 +U+5185 # 38-66, CJK UNIFIED IDEOGRAPH-5185 +U+5186 # 17-63, CJK UNIFIED IDEOGRAPH-5186 +U+5189 # 49-39, CJK UNIFIED IDEOGRAPH-5189 +U+518A # 26-93, CJK UNIFIED IDEOGRAPH-518A +U+518C # 49-38, CJK UNIFIED IDEOGRAPH-518C +U+518D # 26-38, CJK UNIFIED IDEOGRAPH-518D +U+518F # 49-40, CJK UNIFIED IDEOGRAPH-518F +U+5190 # 70-78, CJK UNIFIED IDEOGRAPH-5190 +U+5191 # 49-41, CJK UNIFIED IDEOGRAPH-5191 +U+5192 # 43-33, CJK UNIFIED IDEOGRAPH-5192 +U+5193 # 49-42, CJK UNIFIED IDEOGRAPH-5193 +U+5195 # 49-43, CJK UNIFIED IDEOGRAPH-5195 +U+5196 # 49-44, CJK UNIFIED IDEOGRAPH-5196 +U+5197 # 30-73, CJK UNIFIED IDEOGRAPH-5197 +U+5199 # 28-44, CJK UNIFIED IDEOGRAPH-5199 +U+51A0 # 20-07, CJK UNIFIED IDEOGRAPH-51A0 +U+51A2 # 49-47, CJK UNIFIED IDEOGRAPH-51A2 +U+51A4 # 49-45, CJK UNIFIED IDEOGRAPH-51A4 +U+51A5 # 44-29, CJK UNIFIED IDEOGRAPH-51A5 +U+51A6 # 49-46, CJK UNIFIED IDEOGRAPH-51A6 +U+51A8 # 41-58, CJK UNIFIED IDEOGRAPH-51A8 +U+51A9 # 49-48, CJK UNIFIED IDEOGRAPH-51A9 +U+51AA # 49-49, CJK UNIFIED IDEOGRAPH-51AA +U+51AB # 49-50, CJK UNIFIED IDEOGRAPH-51AB +U+51AC # 37-63, CJK UNIFIED IDEOGRAPH-51AC +U+51B0 # 49-54, CJK UNIFIED IDEOGRAPH-51B0 +U+51B1 # 49-52, CJK UNIFIED IDEOGRAPH-51B1 +U+51B2 # 49-53, CJK UNIFIED IDEOGRAPH-51B2 +U+51B3 # 49-51, CJK UNIFIED IDEOGRAPH-51B3 +U+51B4 # 26-67, CJK UNIFIED IDEOGRAPH-51B4 +U+51B5 # 49-55, CJK UNIFIED IDEOGRAPH-51B5 +U+51B6 # 44-74, CJK UNIFIED IDEOGRAPH-51B6 +U+51B7 # 46-68, CJK UNIFIED IDEOGRAPH-51B7 +U+51BD # 49-56, CJK UNIFIED IDEOGRAPH-51BD +U+51C4 # 32-08, CJK UNIFIED IDEOGRAPH-51C4 +U+51C5 # 49-57, CJK UNIFIED IDEOGRAPH-51C5 +U+51C6 # 29-58, CJK UNIFIED IDEOGRAPH-51C6 +U+51C9 # 49-58, CJK UNIFIED IDEOGRAPH-51C9 +U+51CB # 35-92, CJK UNIFIED IDEOGRAPH-51CB +U+51CC # 46-31, CJK UNIFIED IDEOGRAPH-51CC +U+51CD # 37-64, CJK UNIFIED IDEOGRAPH-51CD +U+51D6 # 50-37, CJK UNIFIED IDEOGRAPH-51D6 +U+51DB # 49-59, CJK UNIFIED IDEOGRAPH-51DB +U+51DC # 84-05, CJK UNIFIED IDEOGRAPH-51DC +U+51DD # 22-37, CJK UNIFIED IDEOGRAPH-51DD +U+51E0 # 49-60, CJK UNIFIED IDEOGRAPH-51E0 +U+51E1 # 43-62, CJK UNIFIED IDEOGRAPH-51E1 +U+51E6 # 29-72, CJK UNIFIED IDEOGRAPH-51E6 +U+51E7 # 34-92, CJK UNIFIED IDEOGRAPH-51E7 +U+51E9 # 49-62, CJK UNIFIED IDEOGRAPH-51E9 +U+51EA # 38-68, CJK UNIFIED IDEOGRAPH-51EA +U+51ED # 49-63, CJK UNIFIED IDEOGRAPH-51ED +U+51F0 # 49-64, CJK UNIFIED IDEOGRAPH-51F0 +U+51F1 # 19-14, CJK UNIFIED IDEOGRAPH-51F1 +U+51F5 # 49-65, CJK UNIFIED IDEOGRAPH-51F5 +U+51F6 # 22-07, CJK UNIFIED IDEOGRAPH-51F6 +U+51F8 # 38-44, CJK UNIFIED IDEOGRAPH-51F8 +U+51F9 # 17-90, CJK UNIFIED IDEOGRAPH-51F9 +U+51FA # 29-48, CJK UNIFIED IDEOGRAPH-51FA +U+51FD # 40-01, CJK UNIFIED IDEOGRAPH-51FD +U+51FE # 49-66, CJK UNIFIED IDEOGRAPH-51FE +U+5200 # 37-65, CJK UNIFIED IDEOGRAPH-5200 +U+5203 # 31-47, CJK UNIFIED IDEOGRAPH-5203 +U+5204 # 49-67, CJK UNIFIED IDEOGRAPH-5204 +U+5206 # 42-12, CJK UNIFIED IDEOGRAPH-5206 +U+5207 # 32-58, CJK UNIFIED IDEOGRAPH-5207 +U+5208 # 20-02, CJK UNIFIED IDEOGRAPH-5208 +U+520A # 20-09, CJK UNIFIED IDEOGRAPH-520A +U+520B # 49-68, CJK UNIFIED IDEOGRAPH-520B +U+520E # 49-70, CJK UNIFIED IDEOGRAPH-520E +U+5211 # 23-26, CJK UNIFIED IDEOGRAPH-5211 +U+5214 # 49-69, CJK UNIFIED IDEOGRAPH-5214 +U+5217 # 46-83, CJK UNIFIED IDEOGRAPH-5217 +U+521D # 29-73, CJK UNIFIED IDEOGRAPH-521D +U+5224 # 40-29, CJK UNIFIED IDEOGRAPH-5224 +U+5225 # 42-44, CJK UNIFIED IDEOGRAPH-5225 +U+5227 # 49-71, CJK UNIFIED IDEOGRAPH-5227 +U+5229 # 45-88, CJK UNIFIED IDEOGRAPH-5229 +U+522A # 49-72, CJK UNIFIED IDEOGRAPH-522A +U+522E # 49-73, CJK UNIFIED IDEOGRAPH-522E +U+5230 # 37-94, CJK UNIFIED IDEOGRAPH-5230 +U+5233 # 49-74, CJK UNIFIED IDEOGRAPH-5233 +U+5236 # 32-09, CJK UNIFIED IDEOGRAPH-5236 +U+5237 # 26-94, CJK UNIFIED IDEOGRAPH-5237 +U+5238 # 23-84, CJK UNIFIED IDEOGRAPH-5238 +U+5239 # 49-75, CJK UNIFIED IDEOGRAPH-5239 +U+523A # 27-41, CJK UNIFIED IDEOGRAPH-523A +U+523B # 25-79, CJK UNIFIED IDEOGRAPH-523B +U+5243 # 36-70, CJK UNIFIED IDEOGRAPH-5243 +U+5244 # 49-77, CJK UNIFIED IDEOGRAPH-5244 +U+5247 # 34-07, CJK UNIFIED IDEOGRAPH-5247 +U+524A # 26-79, CJK UNIFIED IDEOGRAPH-524A +U+524B # 49-78, CJK UNIFIED IDEOGRAPH-524B +U+524C # 49-79, CJK UNIFIED IDEOGRAPH-524C +U+524D # 33-16, CJK UNIFIED IDEOGRAPH-524D +U+524F # 49-76, CJK UNIFIED IDEOGRAPH-524F +U+5254 # 49-81, CJK UNIFIED IDEOGRAPH-5254 +U+5256 # 43-22, CJK UNIFIED IDEOGRAPH-5256 +U+525B # 25-68, CJK UNIFIED IDEOGRAPH-525B +U+525E # 49-80, CJK UNIFIED IDEOGRAPH-525E +U+5263 # 23-85, CJK UNIFIED IDEOGRAPH-5263 +U+5264 # 26-62, CJK UNIFIED IDEOGRAPH-5264 +U+5265 # 39-77, CJK UNIFIED IDEOGRAPH-5265 +U+5269 # 49-84, CJK UNIFIED IDEOGRAPH-5269 +U+526A # 49-82, CJK UNIFIED IDEOGRAPH-526A +U+526F # 41-91, CJK UNIFIED IDEOGRAPH-526F +U+5270 # 30-74, CJK UNIFIED IDEOGRAPH-5270 +U+5271 # 49-91, CJK UNIFIED IDEOGRAPH-5271 +U+5272 # 19-68, CJK UNIFIED IDEOGRAPH-5272 +U+5273 # 49-85, CJK UNIFIED IDEOGRAPH-5273 +U+5274 # 49-83, CJK UNIFIED IDEOGRAPH-5274 +U+5275 # 33-47, CJK UNIFIED IDEOGRAPH-5275 +U+527D # 49-87, CJK UNIFIED IDEOGRAPH-527D +U+527F # 49-86, CJK UNIFIED IDEOGRAPH-527F +U+5283 # 19-36, CJK UNIFIED IDEOGRAPH-5283 +U+5287 # 23-64, CJK UNIFIED IDEOGRAPH-5287 +U+5288 # 49-92, CJK UNIFIED IDEOGRAPH-5288 +U+5289 # 46-13, CJK UNIFIED IDEOGRAPH-5289 +U+528D # 49-88, CJK UNIFIED IDEOGRAPH-528D +U+5291 # 49-93, CJK UNIFIED IDEOGRAPH-5291 +U+5292 # 49-90, CJK UNIFIED IDEOGRAPH-5292 +U+5294 # 49-89, CJK UNIFIED IDEOGRAPH-5294 +U+529B # 46-47, CJK UNIFIED IDEOGRAPH-529B +U+529F # 24-89, CJK UNIFIED IDEOGRAPH-529F +U+52A0 # 18-35, CJK UNIFIED IDEOGRAPH-52A0 +U+52A3 # 46-84, CJK UNIFIED IDEOGRAPH-52A3 +U+52A9 # 29-85, CJK UNIFIED IDEOGRAPH-52A9 +U+52AA # 37-56, CJK UNIFIED IDEOGRAPH-52AA +U+52AB # 25-69, CJK UNIFIED IDEOGRAPH-52AB +U+52AC # 50-02, CJK UNIFIED IDEOGRAPH-52AC +U+52AD # 50-03, CJK UNIFIED IDEOGRAPH-52AD +U+52B1 # 46-69, CJK UNIFIED IDEOGRAPH-52B1 +U+52B4 # 47-11, CJK UNIFIED IDEOGRAPH-52B4 +U+52B5 # 50-05, CJK UNIFIED IDEOGRAPH-52B5 +U+52B9 # 24-90, CJK UNIFIED IDEOGRAPH-52B9 +U+52BC # 50-04, CJK UNIFIED IDEOGRAPH-52BC +U+52BE # 19-15, CJK UNIFIED IDEOGRAPH-52BE +U+52C1 # 50-06, CJK UNIFIED IDEOGRAPH-52C1 +U+52C3 # 43-54, CJK UNIFIED IDEOGRAPH-52C3 +U+52C5 # 36-28, CJK UNIFIED IDEOGRAPH-52C5 +U+52C7 # 45-06, CJK UNIFIED IDEOGRAPH-52C7 +U+52C9 # 42-57, CJK UNIFIED IDEOGRAPH-52C9 +U+52CD # 50-07, CJK UNIFIED IDEOGRAPH-52CD +U+52D2 # 80-53, CJK UNIFIED IDEOGRAPH-52D2 +U+52D5 # 38-16, CJK UNIFIED IDEOGRAPH-52D5 +U+52D7 # 50-08, CJK UNIFIED IDEOGRAPH-52D7 +U+52D8 # 20-10, CJK UNIFIED IDEOGRAPH-52D8 +U+52D9 # 44-19, CJK UNIFIED IDEOGRAPH-52D9 +U+52DD # 30-01, CJK UNIFIED IDEOGRAPH-52DD +U+52DE # 50-09, CJK UNIFIED IDEOGRAPH-52DE +U+52DF # 42-71, CJK UNIFIED IDEOGRAPH-52DF +U+52E0 # 50-13, CJK UNIFIED IDEOGRAPH-52E0 +U+52E2 # 32-10, CJK UNIFIED IDEOGRAPH-52E2 +U+52E3 # 50-10, CJK UNIFIED IDEOGRAPH-52E3 +U+52E4 # 22-48, CJK UNIFIED IDEOGRAPH-52E4 +U+52E6 # 50-11, CJK UNIFIED IDEOGRAPH-52E6 +U+52E7 # 20-11, CJK UNIFIED IDEOGRAPH-52E7 +U+52F2 # 23-14, CJK UNIFIED IDEOGRAPH-52F2 +U+52F3 # 50-14, CJK UNIFIED IDEOGRAPH-52F3 +U+52F5 # 50-15, CJK UNIFIED IDEOGRAPH-52F5 +U+52F8 # 50-16, CJK UNIFIED IDEOGRAPH-52F8 +U+52F9 # 50-17, CJK UNIFIED IDEOGRAPH-52F9 +U+52FA # 28-59, CJK UNIFIED IDEOGRAPH-52FA +U+52FE # 24-91, CJK UNIFIED IDEOGRAPH-52FE +U+52FF # 44-62, CJK UNIFIED IDEOGRAPH-52FF +U+5301 # 44-72, CJK UNIFIED IDEOGRAPH-5301 +U+5302 # 38-87, CJK UNIFIED IDEOGRAPH-5302 +U+5305 # 42-81, CJK UNIFIED IDEOGRAPH-5305 +U+5306 # 50-18, CJK UNIFIED IDEOGRAPH-5306 +U+5308 # 50-19, CJK UNIFIED IDEOGRAPH-5308 +U+530D # 50-21, CJK UNIFIED IDEOGRAPH-530D +U+530F # 50-23, CJK UNIFIED IDEOGRAPH-530F +U+5310 # 50-22, CJK UNIFIED IDEOGRAPH-5310 +U+5315 # 50-24, CJK UNIFIED IDEOGRAPH-5315 +U+5316 # 18-29, CJK UNIFIED IDEOGRAPH-5316 +U+5317 # 43-44, CJK UNIFIED IDEOGRAPH-5317 +U+5319 # 26-92, CJK UNIFIED IDEOGRAPH-5319 +U+531A # 50-25, CJK UNIFIED IDEOGRAPH-531A +U+531D # 33-57, CJK UNIFIED IDEOGRAPH-531D +U+5320 # 30-02, CJK UNIFIED IDEOGRAPH-5320 +U+5321 # 22-09, CJK UNIFIED IDEOGRAPH-5321 +U+5323 # 50-26, CJK UNIFIED IDEOGRAPH-5323 +U+532A # 40-59, CJK UNIFIED IDEOGRAPH-532A +U+532F # 50-27, CJK UNIFIED IDEOGRAPH-532F +U+5331 # 50-28, CJK UNIFIED IDEOGRAPH-5331 +U+5333 # 50-29, CJK UNIFIED IDEOGRAPH-5333 +U+5338 # 50-30, CJK UNIFIED IDEOGRAPH-5338 +U+5339 # 41-04, CJK UNIFIED IDEOGRAPH-5339 +U+533A # 22-72, CJK UNIFIED IDEOGRAPH-533A +U+533B # 16-69, CJK UNIFIED IDEOGRAPH-533B +U+533F # 38-31, CJK UNIFIED IDEOGRAPH-533F +U+5340 # 50-31, CJK UNIFIED IDEOGRAPH-5340 +U+5341 # 29-29, CJK UNIFIED IDEOGRAPH-5341 +U+5343 # 32-73, CJK UNIFIED IDEOGRAPH-5343 +U+5345 # 50-33, CJK UNIFIED IDEOGRAPH-5345 +U+5346 # 50-32, CJK UNIFIED IDEOGRAPH-5346 +U+5347 # 30-03, CJK UNIFIED IDEOGRAPH-5347 +U+5348 # 24-65, CJK UNIFIED IDEOGRAPH-5348 +U+5349 # 50-35, CJK UNIFIED IDEOGRAPH-5349 +U+534A # 40-30, CJK UNIFIED IDEOGRAPH-534A +U+534D # 50-36, CJK UNIFIED IDEOGRAPH-534D +U+5351 # 40-60, CJK UNIFIED IDEOGRAPH-5351 +U+5352 # 34-20, CJK UNIFIED IDEOGRAPH-5352 +U+5353 # 34-78, CJK UNIFIED IDEOGRAPH-5353 +U+5354 # 22-08, CJK UNIFIED IDEOGRAPH-5354 +U+5357 # 38-78, CJK UNIFIED IDEOGRAPH-5357 +U+5358 # 35-17, CJK UNIFIED IDEOGRAPH-5358 +U+535A # 39-78, CJK UNIFIED IDEOGRAPH-535A +U+535C # 43-46, CJK UNIFIED IDEOGRAPH-535C +U+535E # 50-38, CJK UNIFIED IDEOGRAPH-535E +U+5360 # 32-74, CJK UNIFIED IDEOGRAPH-5360 +U+5366 # 23-21, CJK UNIFIED IDEOGRAPH-5366 +U+5369 # 50-39, CJK UNIFIED IDEOGRAPH-5369 +U+536E # 50-40, CJK UNIFIED IDEOGRAPH-536E +U+536F # 17-12, CJK UNIFIED IDEOGRAPH-536F +U+5370 # 16-85, CJK UNIFIED IDEOGRAPH-5370 +U+5371 # 20-77, CJK UNIFIED IDEOGRAPH-5371 +U+5373 # 34-08, CJK UNIFIED IDEOGRAPH-5373 +U+5374 # 21-49, CJK UNIFIED IDEOGRAPH-5374 +U+5375 # 45-81, CJK UNIFIED IDEOGRAPH-5375 +U+5377 # 50-43, CJK UNIFIED IDEOGRAPH-5377 +U+5378 # 18-23, CJK UNIFIED IDEOGRAPH-5378 +U+537B # 50-42, CJK UNIFIED IDEOGRAPH-537B +U+537F # 22-10, CJK UNIFIED IDEOGRAPH-537F +U+5382 # 50-44, CJK UNIFIED IDEOGRAPH-5382 +U+5384 # 44-81, CJK UNIFIED IDEOGRAPH-5384 +U+5396 # 50-45, CJK UNIFIED IDEOGRAPH-5396 +U+5398 # 46-50, CJK UNIFIED IDEOGRAPH-5398 +U+539A # 24-92, CJK UNIFIED IDEOGRAPH-539A +U+539F # 24-22, CJK UNIFIED IDEOGRAPH-539F +U+53A0 # 50-46, CJK UNIFIED IDEOGRAPH-53A0 +U+53A5 # 50-48, CJK UNIFIED IDEOGRAPH-53A5 +U+53A6 # 50-47, CJK UNIFIED IDEOGRAPH-53A6 +U+53A8 # 31-63, CJK UNIFIED IDEOGRAPH-53A8 +U+53A9 # 17-25, CJK UNIFIED IDEOGRAPH-53A9 +U+53AD # 17-62, CJK UNIFIED IDEOGRAPH-53AD +U+53AE # 50-49, CJK UNIFIED IDEOGRAPH-53AE +U+53B0 # 50-50, CJK UNIFIED IDEOGRAPH-53B0 +U+53B3 # 24-23, CJK UNIFIED IDEOGRAPH-53B3 +U+53B6 # 50-51, CJK UNIFIED IDEOGRAPH-53B6 +U+53BB # 21-78, CJK UNIFIED IDEOGRAPH-53BB +U+53C2 # 27-18, CJK UNIFIED IDEOGRAPH-53C2 +U+53C3 # 50-52, CJK UNIFIED IDEOGRAPH-53C3 +U+53C8 # 43-84, CJK UNIFIED IDEOGRAPH-53C8 +U+53C9 # 26-21, CJK UNIFIED IDEOGRAPH-53C9 +U+53CA # 21-58, CJK UNIFIED IDEOGRAPH-53CA +U+53CB # 45-07, CJK UNIFIED IDEOGRAPH-53CB +U+53CC # 33-48, CJK UNIFIED IDEOGRAPH-53CC +U+53CD # 40-31, CJK UNIFIED IDEOGRAPH-53CD +U+53CE # 28-93, CJK UNIFIED IDEOGRAPH-53CE +U+53D4 # 29-39, CJK UNIFIED IDEOGRAPH-53D4 +U+53D6 # 28-72, CJK UNIFIED IDEOGRAPH-53D6 +U+53D7 # 28-85, CJK UNIFIED IDEOGRAPH-53D7 +U+53D9 # 29-86, CJK UNIFIED IDEOGRAPH-53D9 +U+53DB # 40-32, CJK UNIFIED IDEOGRAPH-53DB +U+53DF # 50-55, CJK UNIFIED IDEOGRAPH-53DF +U+53E1 # 17-35, CJK UNIFIED IDEOGRAPH-53E1 +U+53E2 # 33-49, CJK UNIFIED IDEOGRAPH-53E2 +U+53E3 # 24-93, CJK UNIFIED IDEOGRAPH-53E3 +U+53E4 # 24-37, CJK UNIFIED IDEOGRAPH-53E4 +U+53E5 # 22-71, CJK UNIFIED IDEOGRAPH-53E5 +U+53E8 # 50-59, CJK UNIFIED IDEOGRAPH-53E8 +U+53E9 # 35-01, CJK UNIFIED IDEOGRAPH-53E9 +U+53EA # 34-94, CJK UNIFIED IDEOGRAPH-53EA +U+53EB # 22-11, CJK UNIFIED IDEOGRAPH-53EB +U+53EC # 30-04, CJK UNIFIED IDEOGRAPH-53EC +U+53ED # 50-60, CJK UNIFIED IDEOGRAPH-53ED +U+53EE # 50-58, CJK UNIFIED IDEOGRAPH-53EE +U+53EF # 18-36, CJK UNIFIED IDEOGRAPH-53EF +U+53F0 # 34-70, CJK UNIFIED IDEOGRAPH-53F0 +U+53F1 # 28-24, CJK UNIFIED IDEOGRAPH-53F1 +U+53F2 # 27-43, CJK UNIFIED IDEOGRAPH-53F2 +U+53F3 # 17-06, CJK UNIFIED IDEOGRAPH-53F3 +U+53F6 # 19-80, CJK UNIFIED IDEOGRAPH-53F6 +U+53F7 # 25-70, CJK UNIFIED IDEOGRAPH-53F7 +U+53F8 # 27-42, CJK UNIFIED IDEOGRAPH-53F8 +U+53FA # 50-61, CJK UNIFIED IDEOGRAPH-53FA +U+5401 # 50-62, CJK UNIFIED IDEOGRAPH-5401 +U+5403 # 21-41, CJK UNIFIED IDEOGRAPH-5403 +U+5404 # 19-38, CJK UNIFIED IDEOGRAPH-5404 +U+5408 # 25-71, CJK UNIFIED IDEOGRAPH-5408 +U+5409 # 21-40, CJK UNIFIED IDEOGRAPH-5409 +U+540A # 36-63, CJK UNIFIED IDEOGRAPH-540A +U+540B # 17-05, CJK UNIFIED IDEOGRAPH-540B +U+540C # 38-17, CJK UNIFIED IDEOGRAPH-540C +U+540D # 44-30, CJK UNIFIED IDEOGRAPH-540D +U+540E # 25-01, CJK UNIFIED IDEOGRAPH-540E +U+540F # 45-89, CJK UNIFIED IDEOGRAPH-540F +U+5410 # 37-39, CJK UNIFIED IDEOGRAPH-5410 +U+5411 # 24-94, CJK UNIFIED IDEOGRAPH-5411 +U+541B # 23-15, CJK UNIFIED IDEOGRAPH-541B +U+541D # 50-71, CJK UNIFIED IDEOGRAPH-541D +U+541F # 22-67, CJK UNIFIED IDEOGRAPH-541F +U+5420 # 43-42, CJK UNIFIED IDEOGRAPH-5420 +U+5426 # 40-61, CJK UNIFIED IDEOGRAPH-5426 +U+5429 # 50-70, CJK UNIFIED IDEOGRAPH-5429 +U+542B # 20-62, CJK UNIFIED IDEOGRAPH-542B +U+542C # 50-65, CJK UNIFIED IDEOGRAPH-542C +U+542D # 50-66, CJK UNIFIED IDEOGRAPH-542D +U+542E # 50-68, CJK UNIFIED IDEOGRAPH-542E +U+5436 # 50-69, CJK UNIFIED IDEOGRAPH-5436 +U+5438 # 21-59, CJK UNIFIED IDEOGRAPH-5438 +U+5439 # 31-65, CJK UNIFIED IDEOGRAPH-5439 +U+543B # 42-13, CJK UNIFIED IDEOGRAPH-543B +U+543C # 50-67, CJK UNIFIED IDEOGRAPH-543C +U+543D # 50-63, CJK UNIFIED IDEOGRAPH-543D +U+543E # 24-67, CJK UNIFIED IDEOGRAPH-543E +U+5440 # 50-64, CJK UNIFIED IDEOGRAPH-5440 +U+5442 # 47-04, CJK UNIFIED IDEOGRAPH-5442 +U+5446 # 42-82, CJK UNIFIED IDEOGRAPH-5446 +U+5448 # 36-72, CJK UNIFIED IDEOGRAPH-5448 +U+5449 # 24-66, CJK UNIFIED IDEOGRAPH-5449 +U+544A # 25-80, CJK UNIFIED IDEOGRAPH-544A +U+544E # 50-72, CJK UNIFIED IDEOGRAPH-544E +U+5451 # 38-61, CJK UNIFIED IDEOGRAPH-5451 +U+545F # 50-76, CJK UNIFIED IDEOGRAPH-545F +U+5468 # 28-94, CJK UNIFIED IDEOGRAPH-5468 +U+546A # 28-86, CJK UNIFIED IDEOGRAPH-546A +U+5470 # 50-79, CJK UNIFIED IDEOGRAPH-5470 +U+5471 # 50-77, CJK UNIFIED IDEOGRAPH-5471 +U+5473 # 44-03, CJK UNIFIED IDEOGRAPH-5473 +U+5475 # 50-74, CJK UNIFIED IDEOGRAPH-5475 +U+5476 # 50-83, CJK UNIFIED IDEOGRAPH-5476 +U+5477 # 50-78, CJK UNIFIED IDEOGRAPH-5477 +U+547B # 50-81, CJK UNIFIED IDEOGRAPH-547B +U+547C # 24-38, CJK UNIFIED IDEOGRAPH-547C +U+547D # 44-31, CJK UNIFIED IDEOGRAPH-547D +U+5480 # 50-82, CJK UNIFIED IDEOGRAPH-5480 +U+5484 # 50-84, CJK UNIFIED IDEOGRAPH-5484 +U+5486 # 50-86, CJK UNIFIED IDEOGRAPH-5486 +U+548B # 26-80, CJK UNIFIED IDEOGRAPH-548B +U+548C # 47-34, CJK UNIFIED IDEOGRAPH-548C +U+548E # 50-75, CJK UNIFIED IDEOGRAPH-548E +U+548F # 50-73, CJK UNIFIED IDEOGRAPH-548F +U+5490 # 50-85, CJK UNIFIED IDEOGRAPH-5490 +U+5492 # 50-80, CJK UNIFIED IDEOGRAPH-5492 +U+54A2 # 50-88, CJK UNIFIED IDEOGRAPH-54A2 +U+54A4 # 51-03, CJK UNIFIED IDEOGRAPH-54A4 +U+54A5 # 50-90, CJK UNIFIED IDEOGRAPH-54A5 +U+54A8 # 50-94, CJK UNIFIED IDEOGRAPH-54A8 +U+54AB # 51-01, CJK UNIFIED IDEOGRAPH-54AB +U+54AC # 50-91, CJK UNIFIED IDEOGRAPH-54AC +U+54AF # 51-30, CJK UNIFIED IDEOGRAPH-54AF +U+54B2 # 26-73, CJK UNIFIED IDEOGRAPH-54B2 +U+54B3 # 19-17, CJK UNIFIED IDEOGRAPH-54B3 +U+54B8 # 50-89, CJK UNIFIED IDEOGRAPH-54B8 +U+54BC # 51-05, CJK UNIFIED IDEOGRAPH-54BC +U+54BD # 16-86, CJK UNIFIED IDEOGRAPH-54BD +U+54BE # 51-04, CJK UNIFIED IDEOGRAPH-54BE +U+54C0 # 16-05, CJK UNIFIED IDEOGRAPH-54C0 +U+54C1 # 41-42, CJK UNIFIED IDEOGRAPH-54C1 +U+54C2 # 51-02, CJK UNIFIED IDEOGRAPH-54C2 +U+54C4 # 50-92, CJK UNIFIED IDEOGRAPH-54C4 +U+54C7 # 50-87, CJK UNIFIED IDEOGRAPH-54C7 +U+54C8 # 50-93, CJK UNIFIED IDEOGRAPH-54C8 +U+54C9 # 26-40, CJK UNIFIED IDEOGRAPH-54C9 +U+54D8 # 51-06, CJK UNIFIED IDEOGRAPH-54D8 +U+54E1 # 16-87, CJK UNIFIED IDEOGRAPH-54E1 +U+54E2 # 51-15, CJK UNIFIED IDEOGRAPH-54E2 +U+54E5 # 51-07, CJK UNIFIED IDEOGRAPH-54E5 +U+54E6 # 51-08, CJK UNIFIED IDEOGRAPH-54E6 +U+54E8 # 30-05, CJK UNIFIED IDEOGRAPH-54E8 +U+54E9 # 43-73, CJK UNIFIED IDEOGRAPH-54E9 +U+54ED # 51-13, CJK UNIFIED IDEOGRAPH-54ED +U+54EE # 51-12, CJK UNIFIED IDEOGRAPH-54EE +U+54F2 # 37-15, CJK UNIFIED IDEOGRAPH-54F2 +U+54FA # 51-14, CJK UNIFIED IDEOGRAPH-54FA +U+54FD # 51-11, CJK UNIFIED IDEOGRAPH-54FD +U+5504 # 17-20, CJK UNIFIED IDEOGRAPH-5504 +U+5506 # 26-22, CJK UNIFIED IDEOGRAPH-5506 +U+5507 # 31-16, CJK UNIFIED IDEOGRAPH-5507 +U+550F # 51-09, CJK UNIFIED IDEOGRAPH-550F +U+5510 # 37-66, CJK UNIFIED IDEOGRAPH-5510 +U+5514 # 51-10, CJK UNIFIED IDEOGRAPH-5514 +U+5516 # 16-02, CJK UNIFIED IDEOGRAPH-5516 +U+552E # 51-20, CJK UNIFIED IDEOGRAPH-552E +U+552F # 45-03, CJK UNIFIED IDEOGRAPH-552F +U+5531 # 30-07, CJK UNIFIED IDEOGRAPH-5531 +U+5533 # 51-26, CJK UNIFIED IDEOGRAPH-5533 +U+5538 # 51-25, CJK UNIFIED IDEOGRAPH-5538 +U+5539 # 51-16, CJK UNIFIED IDEOGRAPH-5539 +U+553E # 34-35, CJK UNIFIED IDEOGRAPH-553E +U+5540 # 51-17, CJK UNIFIED IDEOGRAPH-5540 +U+5544 # 34-79, CJK UNIFIED IDEOGRAPH-5544 +U+5545 # 51-22, CJK UNIFIED IDEOGRAPH-5545 +U+5546 # 30-06, CJK UNIFIED IDEOGRAPH-5546 +U+554C # 51-19, CJK UNIFIED IDEOGRAPH-554C +U+554F # 44-68, CJK UNIFIED IDEOGRAPH-554F +U+5553 # 23-28, CJK UNIFIED IDEOGRAPH-5553 +U+5556 # 51-23, CJK UNIFIED IDEOGRAPH-5556 +U+5557 # 51-24, CJK UNIFIED IDEOGRAPH-5557 +U+555C # 51-21, CJK UNIFIED IDEOGRAPH-555C +U+555D # 51-27, CJK UNIFIED IDEOGRAPH-555D +U+5563 # 51-18, CJK UNIFIED IDEOGRAPH-5563 +U+557B # 51-33, CJK UNIFIED IDEOGRAPH-557B +U+557C # 51-38, CJK UNIFIED IDEOGRAPH-557C +U+557E # 51-34, CJK UNIFIED IDEOGRAPH-557E +U+5580 # 51-29, CJK UNIFIED IDEOGRAPH-5580 +U+5583 # 51-39, CJK UNIFIED IDEOGRAPH-5583 +U+5584 # 33-17, CJK UNIFIED IDEOGRAPH-5584 +U+5587 # 51-41, CJK UNIFIED IDEOGRAPH-5587 +U+5589 # 25-02, CJK UNIFIED IDEOGRAPH-5589 +U+558A # 51-31, CJK UNIFIED IDEOGRAPH-558A +U+558B # 35-93, CJK UNIFIED IDEOGRAPH-558B +U+5598 # 51-35, CJK UNIFIED IDEOGRAPH-5598 +U+5599 # 51-28, CJK UNIFIED IDEOGRAPH-5599 +U+559A # 20-13, CJK UNIFIED IDEOGRAPH-559A +U+559C # 20-78, CJK UNIFIED IDEOGRAPH-559C +U+559D # 19-69, CJK UNIFIED IDEOGRAPH-559D +U+559E # 51-36, CJK UNIFIED IDEOGRAPH-559E +U+559F # 51-32, CJK UNIFIED IDEOGRAPH-559F +U+55A7 # 23-86, CJK UNIFIED IDEOGRAPH-55A7 +U+55A8 # 51-42, CJK UNIFIED IDEOGRAPH-55A8 +U+55A9 # 51-40, CJK UNIFIED IDEOGRAPH-55A9 +U+55AA # 33-51, CJK UNIFIED IDEOGRAPH-55AA +U+55AB # 21-42, CJK UNIFIED IDEOGRAPH-55AB +U+55AC # 22-12, CJK UNIFIED IDEOGRAPH-55AC +U+55AE # 51-37, CJK UNIFIED IDEOGRAPH-55AE +U+55B0 # 22-84, CJK UNIFIED IDEOGRAPH-55B0 +U+55B6 # 17-36, CJK UNIFIED IDEOGRAPH-55B6 +U+55C4 # 51-46, CJK UNIFIED IDEOGRAPH-55C4 +U+55C5 # 51-44, CJK UNIFIED IDEOGRAPH-55C5 +U+55C7 # 52-07, CJK UNIFIED IDEOGRAPH-55C7 +U+55D4 # 51-49, CJK UNIFIED IDEOGRAPH-55D4 +U+55DA # 51-43, CJK UNIFIED IDEOGRAPH-55DA +U+55DC # 51-47, CJK UNIFIED IDEOGRAPH-55DC +U+55DF # 51-45, CJK UNIFIED IDEOGRAPH-55DF +U+55E3 # 27-44, CJK UNIFIED IDEOGRAPH-55E3 +U+55E4 # 51-48, CJK UNIFIED IDEOGRAPH-55E4 +U+55F7 # 51-51, CJK UNIFIED IDEOGRAPH-55F7 +U+55F9 # 51-56, CJK UNIFIED IDEOGRAPH-55F9 +U+55FD # 51-54, CJK UNIFIED IDEOGRAPH-55FD +U+55FE # 51-53, CJK UNIFIED IDEOGRAPH-55FE +U+5606 # 35-18, CJK UNIFIED IDEOGRAPH-5606 +U+5609 # 18-37, CJK UNIFIED IDEOGRAPH-5609 +U+5614 # 51-50, CJK UNIFIED IDEOGRAPH-5614 +U+5616 # 51-52, CJK UNIFIED IDEOGRAPH-5616 +U+5617 # 30-08, CJK UNIFIED IDEOGRAPH-5617 +U+5618 # 17-19, CJK UNIFIED IDEOGRAPH-5618 +U+561B # 51-55, CJK UNIFIED IDEOGRAPH-561B +U+5629 # 18-62, CJK UNIFIED IDEOGRAPH-5629 +U+562F # 51-66, CJK UNIFIED IDEOGRAPH-562F +U+5631 # 30-92, CJK UNIFIED IDEOGRAPH-5631 +U+5632 # 51-62, CJK UNIFIED IDEOGRAPH-5632 +U+5634 # 51-60, CJK UNIFIED IDEOGRAPH-5634 +U+5636 # 51-61, CJK UNIFIED IDEOGRAPH-5636 +U+5638 # 51-63, CJK UNIFIED IDEOGRAPH-5638 +U+5642 # 17-29, CJK UNIFIED IDEOGRAPH-5642 +U+564C # 33-25, CJK UNIFIED IDEOGRAPH-564C +U+564E # 51-57, CJK UNIFIED IDEOGRAPH-564E +U+5650 # 51-58, CJK UNIFIED IDEOGRAPH-5650 +U+565B # 19-90, CJK UNIFIED IDEOGRAPH-565B +U+5664 # 51-65, CJK UNIFIED IDEOGRAPH-5664 +U+5668 # 20-79, CJK UNIFIED IDEOGRAPH-5668 +U+566A # 51-68, CJK UNIFIED IDEOGRAPH-566A +U+566B # 51-64, CJK UNIFIED IDEOGRAPH-566B +U+566C # 51-67, CJK UNIFIED IDEOGRAPH-566C +U+5674 # 42-14, CJK UNIFIED IDEOGRAPH-5674 +U+5678 # 38-53, CJK UNIFIED IDEOGRAPH-5678 +U+567A # 40-24, CJK UNIFIED IDEOGRAPH-567A +U+5680 # 51-70, CJK UNIFIED IDEOGRAPH-5680 +U+5686 # 51-69, CJK UNIFIED IDEOGRAPH-5686 +U+5687 # 19-37, CJK UNIFIED IDEOGRAPH-5687 +U+568A # 51-71, CJK UNIFIED IDEOGRAPH-568A +U+568F # 51-74, CJK UNIFIED IDEOGRAPH-568F +U+5694 # 51-73, CJK UNIFIED IDEOGRAPH-5694 +U+56A0 # 51-72, CJK UNIFIED IDEOGRAPH-56A0 +U+56A2 # 39-25, CJK UNIFIED IDEOGRAPH-56A2 +U+56A5 # 51-75, CJK UNIFIED IDEOGRAPH-56A5 +U+56AE # 51-76, CJK UNIFIED IDEOGRAPH-56AE +U+56B4 # 51-78, CJK UNIFIED IDEOGRAPH-56B4 +U+56B6 # 51-77, CJK UNIFIED IDEOGRAPH-56B6 +U+56BC # 51-80, CJK UNIFIED IDEOGRAPH-56BC +U+56C0 # 51-83, CJK UNIFIED IDEOGRAPH-56C0 +U+56C1 # 51-81, CJK UNIFIED IDEOGRAPH-56C1 +U+56C2 # 51-79, CJK UNIFIED IDEOGRAPH-56C2 +U+56C3 # 51-82, CJK UNIFIED IDEOGRAPH-56C3 +U+56C8 # 51-84, CJK UNIFIED IDEOGRAPH-56C8 +U+56CE # 51-85, CJK UNIFIED IDEOGRAPH-56CE +U+56D1 # 51-86, CJK UNIFIED IDEOGRAPH-56D1 +U+56D3 # 51-87, CJK UNIFIED IDEOGRAPH-56D3 +U+56D7 # 51-88, CJK UNIFIED IDEOGRAPH-56D7 +U+56D8 # 49-37, CJK UNIFIED IDEOGRAPH-56D8 +U+56DA # 28-92, CJK UNIFIED IDEOGRAPH-56DA +U+56DB # 27-45, CJK UNIFIED IDEOGRAPH-56DB +U+56DE # 18-83, CJK UNIFIED IDEOGRAPH-56DE +U+56E0 # 16-88, CJK UNIFIED IDEOGRAPH-56E0 +U+56E3 # 35-36, CJK UNIFIED IDEOGRAPH-56E3 +U+56EE # 51-89, CJK UNIFIED IDEOGRAPH-56EE +U+56F0 # 26-04, CJK UNIFIED IDEOGRAPH-56F0 +U+56F2 # 16-47, CJK UNIFIED IDEOGRAPH-56F2 +U+56F3 # 31-62, CJK UNIFIED IDEOGRAPH-56F3 +U+56F9 # 51-90, CJK UNIFIED IDEOGRAPH-56F9 +U+56FA # 24-39, CJK UNIFIED IDEOGRAPH-56FA +U+56FD # 25-81, CJK UNIFIED IDEOGRAPH-56FD +U+56FF # 51-92, CJK UNIFIED IDEOGRAPH-56FF +U+5700 # 51-91, CJK UNIFIED IDEOGRAPH-5700 +U+5703 # 42-64, CJK UNIFIED IDEOGRAPH-5703 +U+5704 # 51-93, CJK UNIFIED IDEOGRAPH-5704 +U+5708 # 52-01, CJK UNIFIED IDEOGRAPH-5708 +U+5709 # 51-94, CJK UNIFIED IDEOGRAPH-5709 +U+570B # 52-02, CJK UNIFIED IDEOGRAPH-570B +U+570D # 52-03, CJK UNIFIED IDEOGRAPH-570D +U+570F # 23-87, CJK UNIFIED IDEOGRAPH-570F +U+5712 # 17-64, CJK UNIFIED IDEOGRAPH-5712 +U+5713 # 52-04, CJK UNIFIED IDEOGRAPH-5713 +U+5716 # 52-06, CJK UNIFIED IDEOGRAPH-5716 +U+5718 # 52-05, CJK UNIFIED IDEOGRAPH-5718 +U+571C # 52-08, CJK UNIFIED IDEOGRAPH-571C +U+571F # 37-58, CJK UNIFIED IDEOGRAPH-571F +U+5726 # 52-09, CJK UNIFIED IDEOGRAPH-5726 +U+5727 # 16-21, CJK UNIFIED IDEOGRAPH-5727 +U+5728 # 26-63, CJK UNIFIED IDEOGRAPH-5728 +U+572D # 23-29, CJK UNIFIED IDEOGRAPH-572D +U+5730 # 35-47, CJK UNIFIED IDEOGRAPH-5730 +U+5737 # 52-10, CJK UNIFIED IDEOGRAPH-5737 +U+5738 # 52-11, CJK UNIFIED IDEOGRAPH-5738 +U+573B # 52-13, CJK UNIFIED IDEOGRAPH-573B +U+5740 # 52-14, CJK UNIFIED IDEOGRAPH-5740 +U+5742 # 26-68, CJK UNIFIED IDEOGRAPH-5742 +U+5747 # 22-49, CJK UNIFIED IDEOGRAPH-5747 +U+574A # 43-23, CJK UNIFIED IDEOGRAPH-574A +U+574E # 52-12, CJK UNIFIED IDEOGRAPH-574E +U+574F # 52-15, CJK UNIFIED IDEOGRAPH-574F +U+5750 # 26-33, CJK UNIFIED IDEOGRAPH-5750 +U+5751 # 25-03, CJK UNIFIED IDEOGRAPH-5751 +U+5761 # 52-19, CJK UNIFIED IDEOGRAPH-5761 +U+5764 # 26-05, CJK UNIFIED IDEOGRAPH-5764 +U+5766 # 35-19, CJK UNIFIED IDEOGRAPH-5766 +U+5769 # 52-16, CJK UNIFIED IDEOGRAPH-5769 +U+576A # 36-58, CJK UNIFIED IDEOGRAPH-576A +U+577F # 52-20, CJK UNIFIED IDEOGRAPH-577F +U+5782 # 31-66, CJK UNIFIED IDEOGRAPH-5782 +U+5788 # 52-18, CJK UNIFIED IDEOGRAPH-5788 +U+5789 # 52-21, CJK UNIFIED IDEOGRAPH-5789 +U+578B # 23-31, CJK UNIFIED IDEOGRAPH-578B +U+5793 # 52-22, CJK UNIFIED IDEOGRAPH-5793 +U+57A0 # 52-23, CJK UNIFIED IDEOGRAPH-57A0 +U+57A2 # 25-04, CJK UNIFIED IDEOGRAPH-57A2 +U+57A3 # 19-32, CJK UNIFIED IDEOGRAPH-57A3 +U+57A4 # 52-25, CJK UNIFIED IDEOGRAPH-57A4 +U+57AA # 52-26, CJK UNIFIED IDEOGRAPH-57AA +U+57B0 # 52-27, CJK UNIFIED IDEOGRAPH-57B0 +U+57B3 # 52-24, CJK UNIFIED IDEOGRAPH-57B3 +U+57C0 # 52-17, CJK UNIFIED IDEOGRAPH-57C0 +U+57C3 # 52-28, CJK UNIFIED IDEOGRAPH-57C3 +U+57C6 # 52-29, CJK UNIFIED IDEOGRAPH-57C6 +U+57CB # 43-68, CJK UNIFIED IDEOGRAPH-57CB +U+57CE # 30-75, CJK UNIFIED IDEOGRAPH-57CE +U+57D2 # 52-31, CJK UNIFIED IDEOGRAPH-57D2 +U+57D3 # 52-32, CJK UNIFIED IDEOGRAPH-57D3 +U+57D4 # 52-30, CJK UNIFIED IDEOGRAPH-57D4 +U+57D6 # 52-34, CJK UNIFIED IDEOGRAPH-57D6 +U+57DC # 39-24, CJK UNIFIED IDEOGRAPH-57DC +U+57DF # 16-72, CJK UNIFIED IDEOGRAPH-57DF +U+57E0 # 41-54, CJK UNIFIED IDEOGRAPH-57E0 +U+57E3 # 52-35, CJK UNIFIED IDEOGRAPH-57E3 +U+57F4 # 30-93, CJK UNIFIED IDEOGRAPH-57F4 +U+57F7 # 28-25, CJK UNIFIED IDEOGRAPH-57F7 +U+57F9 # 39-61, CJK UNIFIED IDEOGRAPH-57F9 +U+57FA # 20-80, CJK UNIFIED IDEOGRAPH-57FA +U+57FC # 26-75, CJK UNIFIED IDEOGRAPH-57FC +U+5800 # 43-57, CJK UNIFIED IDEOGRAPH-5800 +U+5802 # 38-18, CJK UNIFIED IDEOGRAPH-5802 +U+5805 # 23-88, CJK UNIFIED IDEOGRAPH-5805 +U+5806 # 34-47, CJK UNIFIED IDEOGRAPH-5806 +U+580A # 52-33, CJK UNIFIED IDEOGRAPH-580A +U+580B # 52-36, CJK UNIFIED IDEOGRAPH-580B +U+5815 # 34-36, CJK UNIFIED IDEOGRAPH-5815 +U+5819 # 52-37, CJK UNIFIED IDEOGRAPH-5819 +U+581D # 52-38, CJK UNIFIED IDEOGRAPH-581D +U+5821 # 52-40, CJK UNIFIED IDEOGRAPH-5821 +U+5824 # 36-73, CJK UNIFIED IDEOGRAPH-5824 +U+582A # 20-14, CJK UNIFIED IDEOGRAPH-582A +U+582F # 84-01, CJK UNIFIED IDEOGRAPH-582F +U+5830 # 17-65, CJK UNIFIED IDEOGRAPH-5830 +U+5831 # 42-83, CJK UNIFIED IDEOGRAPH-5831 +U+5834 # 30-76, CJK UNIFIED IDEOGRAPH-5834 +U+5835 # 37-40, CJK UNIFIED IDEOGRAPH-5835 +U+583A # 26-70, CJK UNIFIED IDEOGRAPH-583A +U+583D # 52-46, CJK UNIFIED IDEOGRAPH-583D +U+5840 # 42-29, CJK UNIFIED IDEOGRAPH-5840 +U+5841 # 46-61, CJK UNIFIED IDEOGRAPH-5841 +U+584A # 18-84, CJK UNIFIED IDEOGRAPH-584A +U+584B # 52-42, CJK UNIFIED IDEOGRAPH-584B +U+5851 # 33-26, CJK UNIFIED IDEOGRAPH-5851 +U+5852 # 52-45, CJK UNIFIED IDEOGRAPH-5852 +U+5854 # 37-67, CJK UNIFIED IDEOGRAPH-5854 +U+5857 # 37-41, CJK UNIFIED IDEOGRAPH-5857 +U+5858 # 37-68, CJK UNIFIED IDEOGRAPH-5858 +U+5859 # 40-25, CJK UNIFIED IDEOGRAPH-5859 +U+585A # 36-45, CJK UNIFIED IDEOGRAPH-585A +U+585E # 26-41, CJK UNIFIED IDEOGRAPH-585E +U+5862 # 52-41, CJK UNIFIED IDEOGRAPH-5862 +U+5869 # 17-86, CJK UNIFIED IDEOGRAPH-5869 +U+586B # 37-22, CJK UNIFIED IDEOGRAPH-586B +U+5870 # 52-43, CJK UNIFIED IDEOGRAPH-5870 +U+5872 # 52-39, CJK UNIFIED IDEOGRAPH-5872 +U+5875 # 31-48, CJK UNIFIED IDEOGRAPH-5875 +U+5879 # 52-47, CJK UNIFIED IDEOGRAPH-5879 +U+587E # 29-46, CJK UNIFIED IDEOGRAPH-587E +U+5883 # 22-13, CJK UNIFIED IDEOGRAPH-5883 +U+5885 # 52-48, CJK UNIFIED IDEOGRAPH-5885 +U+5893 # 42-72, CJK UNIFIED IDEOGRAPH-5893 +U+5897 # 33-93, CJK UNIFIED IDEOGRAPH-5897 +U+589C # 36-38, CJK UNIFIED IDEOGRAPH-589C +U+589F # 52-50, CJK UNIFIED IDEOGRAPH-589F +U+58A8 # 43-47, CJK UNIFIED IDEOGRAPH-58A8 +U+58AB # 52-51, CJK UNIFIED IDEOGRAPH-58AB +U+58AE # 52-56, CJK UNIFIED IDEOGRAPH-58AE +U+58B3 # 42-15, CJK UNIFIED IDEOGRAPH-58B3 +U+58B8 # 52-55, CJK UNIFIED IDEOGRAPH-58B8 +U+58B9 # 52-49, CJK UNIFIED IDEOGRAPH-58B9 +U+58BA # 52-52, CJK UNIFIED IDEOGRAPH-58BA +U+58BB # 52-54, CJK UNIFIED IDEOGRAPH-58BB +U+58BE # 26-06, CJK UNIFIED IDEOGRAPH-58BE +U+58C1 # 42-41, CJK UNIFIED IDEOGRAPH-58C1 +U+58C5 # 52-57, CJK UNIFIED IDEOGRAPH-58C5 +U+58C7 # 35-37, CJK UNIFIED IDEOGRAPH-58C7 +U+58CA # 18-85, CJK UNIFIED IDEOGRAPH-58CA +U+58CC # 30-77, CJK UNIFIED IDEOGRAPH-58CC +U+58D1 # 52-59, CJK UNIFIED IDEOGRAPH-58D1 +U+58D3 # 52-58, CJK UNIFIED IDEOGRAPH-58D3 +U+58D5 # 25-72, CJK UNIFIED IDEOGRAPH-58D5 +U+58D7 # 52-60, CJK UNIFIED IDEOGRAPH-58D7 +U+58D8 # 52-62, CJK UNIFIED IDEOGRAPH-58D8 +U+58D9 # 52-61, CJK UNIFIED IDEOGRAPH-58D9 +U+58DC # 52-64, CJK UNIFIED IDEOGRAPH-58DC +U+58DE # 52-53, CJK UNIFIED IDEOGRAPH-58DE +U+58DF # 52-66, CJK UNIFIED IDEOGRAPH-58DF +U+58E4 # 52-65, CJK UNIFIED IDEOGRAPH-58E4 +U+58E5 # 52-63, CJK UNIFIED IDEOGRAPH-58E5 +U+58EB # 27-46, CJK UNIFIED IDEOGRAPH-58EB +U+58EC # 31-49, CJK UNIFIED IDEOGRAPH-58EC +U+58EE # 33-52, CJK UNIFIED IDEOGRAPH-58EE +U+58EF # 52-67, CJK UNIFIED IDEOGRAPH-58EF +U+58F0 # 32-28, CJK UNIFIED IDEOGRAPH-58F0 +U+58F1 # 16-77, CJK UNIFIED IDEOGRAPH-58F1 +U+58F2 # 39-68, CJK UNIFIED IDEOGRAPH-58F2 +U+58F7 # 36-59, CJK UNIFIED IDEOGRAPH-58F7 +U+58F9 # 52-69, CJK UNIFIED IDEOGRAPH-58F9 +U+58FA # 52-68, CJK UNIFIED IDEOGRAPH-58FA +U+58FB # 52-70, CJK UNIFIED IDEOGRAPH-58FB +U+58FC # 52-71, CJK UNIFIED IDEOGRAPH-58FC +U+58FD # 52-72, CJK UNIFIED IDEOGRAPH-58FD +U+5902 # 52-73, CJK UNIFIED IDEOGRAPH-5902 +U+5909 # 42-49, CJK UNIFIED IDEOGRAPH-5909 +U+590A # 52-74, CJK UNIFIED IDEOGRAPH-590A +U+590F # 18-38, CJK UNIFIED IDEOGRAPH-590F +U+5910 # 52-75, CJK UNIFIED IDEOGRAPH-5910 +U+5915 # 45-28, CJK UNIFIED IDEOGRAPH-5915 +U+5916 # 19-16, CJK UNIFIED IDEOGRAPH-5916 +U+5918 # 50-41, CJK UNIFIED IDEOGRAPH-5918 +U+5919 # 29-40, CJK UNIFIED IDEOGRAPH-5919 +U+591A # 34-31, CJK UNIFIED IDEOGRAPH-591A +U+591B # 52-76, CJK UNIFIED IDEOGRAPH-591B +U+591C # 44-75, CJK UNIFIED IDEOGRAPH-591C +U+5922 # 44-20, CJK UNIFIED IDEOGRAPH-5922 +U+5925 # 52-78, CJK UNIFIED IDEOGRAPH-5925 +U+5927 # 34-71, CJK UNIFIED IDEOGRAPH-5927 +U+5929 # 37-23, CJK UNIFIED IDEOGRAPH-5929 +U+592A # 34-32, CJK UNIFIED IDEOGRAPH-592A +U+592B # 41-55, CJK UNIFIED IDEOGRAPH-592B +U+592C # 52-79, CJK UNIFIED IDEOGRAPH-592C +U+592D # 52-80, CJK UNIFIED IDEOGRAPH-592D +U+592E # 17-91, CJK UNIFIED IDEOGRAPH-592E +U+5931 # 28-26, CJK UNIFIED IDEOGRAPH-5931 +U+5932 # 52-81, CJK UNIFIED IDEOGRAPH-5932 +U+5937 # 16-48, CJK UNIFIED IDEOGRAPH-5937 +U+5938 # 52-82, CJK UNIFIED IDEOGRAPH-5938 +U+593E # 52-83, CJK UNIFIED IDEOGRAPH-593E +U+5944 # 17-66, CJK UNIFIED IDEOGRAPH-5944 +U+5947 # 20-81, CJK UNIFIED IDEOGRAPH-5947 +U+5948 # 38-64, CJK UNIFIED IDEOGRAPH-5948 +U+5949 # 42-84, CJK UNIFIED IDEOGRAPH-5949 +U+594E # 52-87, CJK UNIFIED IDEOGRAPH-594E +U+594F # 33-53, CJK UNIFIED IDEOGRAPH-594F +U+5950 # 52-86, CJK UNIFIED IDEOGRAPH-5950 +U+5951 # 23-32, CJK UNIFIED IDEOGRAPH-5951 +U+5954 # 43-59, CJK UNIFIED IDEOGRAPH-5954 +U+5955 # 52-85, CJK UNIFIED IDEOGRAPH-5955 +U+5957 # 37-69, CJK UNIFIED IDEOGRAPH-5957 +U+5958 # 52-89, CJK UNIFIED IDEOGRAPH-5958 +U+595A # 52-88, CJK UNIFIED IDEOGRAPH-595A +U+5960 # 52-91, CJK UNIFIED IDEOGRAPH-5960 +U+5962 # 52-90, CJK UNIFIED IDEOGRAPH-5962 +U+5965 # 17-92, CJK UNIFIED IDEOGRAPH-5965 +U+5967 # 52-92, CJK UNIFIED IDEOGRAPH-5967 +U+5968 # 30-09, CJK UNIFIED IDEOGRAPH-5968 +U+5969 # 52-94, CJK UNIFIED IDEOGRAPH-5969 +U+596A # 35-05, CJK UNIFIED IDEOGRAPH-596A +U+596C # 52-93, CJK UNIFIED IDEOGRAPH-596C +U+596E # 42-19, CJK UNIFIED IDEOGRAPH-596E +U+5973 # 29-87, CJK UNIFIED IDEOGRAPH-5973 +U+5974 # 37-59, CJK UNIFIED IDEOGRAPH-5974 +U+5978 # 53-01, CJK UNIFIED IDEOGRAPH-5978 +U+597D # 25-05, CJK UNIFIED IDEOGRAPH-597D +U+5981 # 53-02, CJK UNIFIED IDEOGRAPH-5981 +U+5982 # 39-01, CJK UNIFIED IDEOGRAPH-5982 +U+5983 # 40-62, CJK UNIFIED IDEOGRAPH-5983 +U+5984 # 44-49, CJK UNIFIED IDEOGRAPH-5984 +U+598A # 39-05, CJK UNIFIED IDEOGRAPH-598A +U+598D # 53-11, CJK UNIFIED IDEOGRAPH-598D +U+5993 # 21-24, CJK UNIFIED IDEOGRAPH-5993 +U+5996 # 45-37, CJK UNIFIED IDEOGRAPH-5996 +U+5999 # 44-15, CJK UNIFIED IDEOGRAPH-5999 +U+599B # 54-12, CJK UNIFIED IDEOGRAPH-599B +U+599D # 53-03, CJK UNIFIED IDEOGRAPH-599D +U+59A3 # 53-06, CJK UNIFIED IDEOGRAPH-59A3 +U+59A5 # 34-37, CJK UNIFIED IDEOGRAPH-59A5 +U+59A8 # 43-24, CJK UNIFIED IDEOGRAPH-59A8 +U+59AC # 37-42, CJK UNIFIED IDEOGRAPH-59AC +U+59B2 # 53-07, CJK UNIFIED IDEOGRAPH-59B2 +U+59B9 # 43-69, CJK UNIFIED IDEOGRAPH-59B9 +U+59BB # 26-42, CJK UNIFIED IDEOGRAPH-59BB +U+59BE # 30-10, CJK UNIFIED IDEOGRAPH-59BE +U+59C6 # 53-08, CJK UNIFIED IDEOGRAPH-59C6 +U+59C9 # 27-48, CJK UNIFIED IDEOGRAPH-59C9 +U+59CB # 27-47, CJK UNIFIED IDEOGRAPH-59CB +U+59D0 # 16-25, CJK UNIFIED IDEOGRAPH-59D0 +U+59D1 # 24-40, CJK UNIFIED IDEOGRAPH-59D1 +U+59D3 # 32-11, CJK UNIFIED IDEOGRAPH-59D3 +U+59D4 # 16-49, CJK UNIFIED IDEOGRAPH-59D4 +U+59D9 # 53-12, CJK UNIFIED IDEOGRAPH-59D9 +U+59DA # 53-13, CJK UNIFIED IDEOGRAPH-59DA +U+59DC # 53-10, CJK UNIFIED IDEOGRAPH-59DC +U+59E5 # 17-24, CJK UNIFIED IDEOGRAPH-59E5 +U+59E6 # 20-15, CJK UNIFIED IDEOGRAPH-59E6 +U+59E8 # 53-09, CJK UNIFIED IDEOGRAPH-59E8 +U+59EA # 44-37, CJK UNIFIED IDEOGRAPH-59EA +U+59EB # 41-17, CJK UNIFIED IDEOGRAPH-59EB +U+59F6 # 16-08, CJK UNIFIED IDEOGRAPH-59F6 +U+59FB # 16-89, CJK UNIFIED IDEOGRAPH-59FB +U+59FF # 27-49, CJK UNIFIED IDEOGRAPH-59FF +U+5A01 # 16-50, CJK UNIFIED IDEOGRAPH-5A01 +U+5A03 # 16-03, CJK UNIFIED IDEOGRAPH-5A03 +U+5A09 # 53-18, CJK UNIFIED IDEOGRAPH-5A09 +U+5A11 # 53-16, CJK UNIFIED IDEOGRAPH-5A11 +U+5A18 # 44-28, CJK UNIFIED IDEOGRAPH-5A18 +U+5A1A # 53-19, CJK UNIFIED IDEOGRAPH-5A1A +U+5A1C # 53-17, CJK UNIFIED IDEOGRAPH-5A1C +U+5A1F # 53-15, CJK UNIFIED IDEOGRAPH-5A1F +U+5A20 # 31-17, CJK UNIFIED IDEOGRAPH-5A20 +U+5A25 # 53-14, CJK UNIFIED IDEOGRAPH-5A25 +U+5A29 # 42-58, CJK UNIFIED IDEOGRAPH-5A29 +U+5A2F # 24-68, CJK UNIFIED IDEOGRAPH-5A2F +U+5A35 # 53-23, CJK UNIFIED IDEOGRAPH-5A35 +U+5A36 # 53-24, CJK UNIFIED IDEOGRAPH-5A36 +U+5A3C # 30-11, CJK UNIFIED IDEOGRAPH-5A3C +U+5A40 # 53-20, CJK UNIFIED IDEOGRAPH-5A40 +U+5A41 # 47-12, CJK UNIFIED IDEOGRAPH-5A41 +U+5A46 # 39-44, CJK UNIFIED IDEOGRAPH-5A46 +U+5A49 # 53-22, CJK UNIFIED IDEOGRAPH-5A49 +U+5A5A # 26-07, CJK UNIFIED IDEOGRAPH-5A5A +U+5A62 # 53-25, CJK UNIFIED IDEOGRAPH-5A62 +U+5A66 # 41-56, CJK UNIFIED IDEOGRAPH-5A66 +U+5A6A # 53-26, CJK UNIFIED IDEOGRAPH-5A6A +U+5A6C # 53-21, CJK UNIFIED IDEOGRAPH-5A6C +U+5A7F # 44-27, CJK UNIFIED IDEOGRAPH-5A7F +U+5A92 # 39-62, CJK UNIFIED IDEOGRAPH-5A92 +U+5A9A # 53-27, CJK UNIFIED IDEOGRAPH-5A9A +U+5A9B # 41-18, CJK UNIFIED IDEOGRAPH-5A9B +U+5ABC # 53-28, CJK UNIFIED IDEOGRAPH-5ABC +U+5ABD # 53-32, CJK UNIFIED IDEOGRAPH-5ABD +U+5ABE # 53-29, CJK UNIFIED IDEOGRAPH-5ABE +U+5AC1 # 18-39, CJK UNIFIED IDEOGRAPH-5AC1 +U+5AC2 # 53-31, CJK UNIFIED IDEOGRAPH-5AC2 +U+5AC9 # 28-27, CJK UNIFIED IDEOGRAPH-5AC9 +U+5ACB # 53-30, CJK UNIFIED IDEOGRAPH-5ACB +U+5ACC # 23-89, CJK UNIFIED IDEOGRAPH-5ACC +U+5AD0 # 53-44, CJK UNIFIED IDEOGRAPH-5AD0 +U+5AD6 # 53-37, CJK UNIFIED IDEOGRAPH-5AD6 +U+5AD7 # 53-34, CJK UNIFIED IDEOGRAPH-5AD7 +U+5AE1 # 35-68, CJK UNIFIED IDEOGRAPH-5AE1 +U+5AE3 # 53-33, CJK UNIFIED IDEOGRAPH-5AE3 +U+5AE6 # 53-35, CJK UNIFIED IDEOGRAPH-5AE6 +U+5AE9 # 53-36, CJK UNIFIED IDEOGRAPH-5AE9 +U+5AFA # 53-38, CJK UNIFIED IDEOGRAPH-5AFA +U+5AFB # 53-39, CJK UNIFIED IDEOGRAPH-5AFB +U+5B09 # 20-82, CJK UNIFIED IDEOGRAPH-5B09 +U+5B0B # 53-41, CJK UNIFIED IDEOGRAPH-5B0B +U+5B0C # 53-40, CJK UNIFIED IDEOGRAPH-5B0C +U+5B16 # 53-42, CJK UNIFIED IDEOGRAPH-5B16 +U+5B22 # 30-78, CJK UNIFIED IDEOGRAPH-5B22 +U+5B2A # 53-45, CJK UNIFIED IDEOGRAPH-5B2A +U+5B2C # 36-60, CJK UNIFIED IDEOGRAPH-5B2C +U+5B30 # 17-37, CJK UNIFIED IDEOGRAPH-5B30 +U+5B32 # 53-43, CJK UNIFIED IDEOGRAPH-5B32 +U+5B36 # 53-46, CJK UNIFIED IDEOGRAPH-5B36 +U+5B3E # 53-47, CJK UNIFIED IDEOGRAPH-5B3E +U+5B40 # 53-50, CJK UNIFIED IDEOGRAPH-5B40 +U+5B43 # 53-48, CJK UNIFIED IDEOGRAPH-5B43 +U+5B45 # 53-49, CJK UNIFIED IDEOGRAPH-5B45 +U+5B50 # 27-50, CJK UNIFIED IDEOGRAPH-5B50 +U+5B51 # 53-51, CJK UNIFIED IDEOGRAPH-5B51 +U+5B54 # 25-06, CJK UNIFIED IDEOGRAPH-5B54 +U+5B55 # 53-52, CJK UNIFIED IDEOGRAPH-5B55 +U+5B57 # 27-90, CJK UNIFIED IDEOGRAPH-5B57 +U+5B58 # 34-24, CJK UNIFIED IDEOGRAPH-5B58 +U+5B5A # 53-53, CJK UNIFIED IDEOGRAPH-5B5A +U+5B5B # 53-54, CJK UNIFIED IDEOGRAPH-5B5B +U+5B5C # 27-58, CJK UNIFIED IDEOGRAPH-5B5C +U+5B5D # 25-07, CJK UNIFIED IDEOGRAPH-5B5D +U+5B5F # 44-50, CJK UNIFIED IDEOGRAPH-5B5F +U+5B63 # 21-08, CJK UNIFIED IDEOGRAPH-5B63 +U+5B64 # 24-41, CJK UNIFIED IDEOGRAPH-5B64 +U+5B65 # 53-55, CJK UNIFIED IDEOGRAPH-5B65 +U+5B66 # 19-56, CJK UNIFIED IDEOGRAPH-5B66 +U+5B69 # 53-56, CJK UNIFIED IDEOGRAPH-5B69 +U+5B6B # 34-25, CJK UNIFIED IDEOGRAPH-5B6B +U+5B70 # 53-57, CJK UNIFIED IDEOGRAPH-5B70 +U+5B71 # 54-03, CJK UNIFIED IDEOGRAPH-5B71 +U+5B73 # 53-58, CJK UNIFIED IDEOGRAPH-5B73 +U+5B75 # 53-59, CJK UNIFIED IDEOGRAPH-5B75 +U+5B78 # 53-60, CJK UNIFIED IDEOGRAPH-5B78 +U+5B7A # 53-62, CJK UNIFIED IDEOGRAPH-5B7A +U+5B80 # 53-63, CJK UNIFIED IDEOGRAPH-5B80 +U+5B83 # 53-64, CJK UNIFIED IDEOGRAPH-5B83 +U+5B85 # 34-80, CJK UNIFIED IDEOGRAPH-5B85 +U+5B87 # 17-07, CJK UNIFIED IDEOGRAPH-5B87 +U+5B88 # 28-73, CJK UNIFIED IDEOGRAPH-5B88 +U+5B89 # 16-34, CJK UNIFIED IDEOGRAPH-5B89 +U+5B8B # 33-55, CJK UNIFIED IDEOGRAPH-5B8B +U+5B8C # 20-16, CJK UNIFIED IDEOGRAPH-5B8C +U+5B8D # 28-21, CJK UNIFIED IDEOGRAPH-5B8D +U+5B8F # 25-08, CJK UNIFIED IDEOGRAPH-5B8F +U+5B95 # 37-70, CJK UNIFIED IDEOGRAPH-5B95 +U+5B97 # 29-01, CJK UNIFIED IDEOGRAPH-5B97 +U+5B98 # 20-17, CJK UNIFIED IDEOGRAPH-5B98 +U+5B99 # 35-72, CJK UNIFIED IDEOGRAPH-5B99 +U+5B9A # 36-74, CJK UNIFIED IDEOGRAPH-5B9A +U+5B9B # 16-24, CJK UNIFIED IDEOGRAPH-5B9B +U+5B9C # 21-25, CJK UNIFIED IDEOGRAPH-5B9C +U+5B9D # 42-85, CJK UNIFIED IDEOGRAPH-5B9D +U+5B9F # 28-34, CJK UNIFIED IDEOGRAPH-5B9F +U+5BA2 # 21-50, CJK UNIFIED IDEOGRAPH-5BA2 +U+5BA3 # 32-75, CJK UNIFIED IDEOGRAPH-5BA3 +U+5BA4 # 28-28, CJK UNIFIED IDEOGRAPH-5BA4 +U+5BA5 # 45-08, CJK UNIFIED IDEOGRAPH-5BA5 +U+5BA6 # 53-65, CJK UNIFIED IDEOGRAPH-5BA6 +U+5BAE # 21-60, CJK UNIFIED IDEOGRAPH-5BAE +U+5BB0 # 26-43, CJK UNIFIED IDEOGRAPH-5BB0 +U+5BB3 # 19-18, CJK UNIFIED IDEOGRAPH-5BB3 +U+5BB4 # 17-67, CJK UNIFIED IDEOGRAPH-5BB4 +U+5BB5 # 30-12, CJK UNIFIED IDEOGRAPH-5BB5 +U+5BB6 # 18-40, CJK UNIFIED IDEOGRAPH-5BB6 +U+5BB8 # 53-66, CJK UNIFIED IDEOGRAPH-5BB8 +U+5BB9 # 45-38, CJK UNIFIED IDEOGRAPH-5BB9 +U+5BBF # 29-41, CJK UNIFIED IDEOGRAPH-5BBF +U+5BC2 # 28-68, CJK UNIFIED IDEOGRAPH-5BC2 +U+5BC3 # 53-67, CJK UNIFIED IDEOGRAPH-5BC3 +U+5BC4 # 20-83, CJK UNIFIED IDEOGRAPH-5BC4 +U+5BC5 # 38-50, CJK UNIFIED IDEOGRAPH-5BC5 +U+5BC6 # 44-09, CJK UNIFIED IDEOGRAPH-5BC6 +U+5BC7 # 53-68, CJK UNIFIED IDEOGRAPH-5BC7 +U+5BC9 # 53-69, CJK UNIFIED IDEOGRAPH-5BC9 +U+5BCC # 41-57, CJK UNIFIED IDEOGRAPH-5BCC +U+5BD0 # 53-71, CJK UNIFIED IDEOGRAPH-5BD0 +U+5BD2 # 20-08, CJK UNIFIED IDEOGRAPH-5BD2 +U+5BD3 # 22-87, CJK UNIFIED IDEOGRAPH-5BD3 +U+5BD4 # 53-70, CJK UNIFIED IDEOGRAPH-5BD4 +U+5BDB # 20-18, CJK UNIFIED IDEOGRAPH-5BDB +U+5BDD # 31-18, CJK UNIFIED IDEOGRAPH-5BDD +U+5BDE # 53-75, CJK UNIFIED IDEOGRAPH-5BDE +U+5BDF # 27-01, CJK UNIFIED IDEOGRAPH-5BDF +U+5BE1 # 18-41, CJK UNIFIED IDEOGRAPH-5BE1 +U+5BE2 # 53-74, CJK UNIFIED IDEOGRAPH-5BE2 +U+5BE4 # 53-72, CJK UNIFIED IDEOGRAPH-5BE4 +U+5BE5 # 53-76, CJK UNIFIED IDEOGRAPH-5BE5 +U+5BE6 # 53-73, CJK UNIFIED IDEOGRAPH-5BE6 +U+5BE7 # 39-11, CJK UNIFIED IDEOGRAPH-5BE7 +U+5BE8 # 60-45, CJK UNIFIED IDEOGRAPH-5BE8 +U+5BE9 # 31-19, CJK UNIFIED IDEOGRAPH-5BE9 +U+5BEB # 53-77, CJK UNIFIED IDEOGRAPH-5BEB +U+5BEE # 46-32, CJK UNIFIED IDEOGRAPH-5BEE +U+5BF0 # 53-78, CJK UNIFIED IDEOGRAPH-5BF0 +U+5BF3 # 53-80, CJK UNIFIED IDEOGRAPH-5BF3 +U+5BF5 # 35-94, CJK UNIFIED IDEOGRAPH-5BF5 +U+5BF6 # 53-79, CJK UNIFIED IDEOGRAPH-5BF6 +U+5BF8 # 32-03, CJK UNIFIED IDEOGRAPH-5BF8 +U+5BFA # 27-91, CJK UNIFIED IDEOGRAPH-5BFA +U+5BFE # 34-48, CJK UNIFIED IDEOGRAPH-5BFE +U+5BFF # 28-87, CJK UNIFIED IDEOGRAPH-5BFF +U+5C01 # 41-85, CJK UNIFIED IDEOGRAPH-5C01 +U+5C02 # 32-76, CJK UNIFIED IDEOGRAPH-5C02 +U+5C04 # 28-45, CJK UNIFIED IDEOGRAPH-5C04 +U+5C05 # 53-81, CJK UNIFIED IDEOGRAPH-5C05 +U+5C06 # 30-13, CJK UNIFIED IDEOGRAPH-5C06 +U+5C07 # 53-82, CJK UNIFIED IDEOGRAPH-5C07 +U+5C08 # 53-83, CJK UNIFIED IDEOGRAPH-5C08 +U+5C09 # 16-51, CJK UNIFIED IDEOGRAPH-5C09 +U+5C0A # 34-26, CJK UNIFIED IDEOGRAPH-5C0A +U+5C0B # 31-50, CJK UNIFIED IDEOGRAPH-5C0B +U+5C0D # 53-84, CJK UNIFIED IDEOGRAPH-5C0D +U+5C0E # 38-19, CJK UNIFIED IDEOGRAPH-5C0E +U+5C0F # 30-14, CJK UNIFIED IDEOGRAPH-5C0F +U+5C11 # 30-15, CJK UNIFIED IDEOGRAPH-5C11 +U+5C13 # 53-85, CJK UNIFIED IDEOGRAPH-5C13 +U+5C16 # 32-77, CJK UNIFIED IDEOGRAPH-5C16 +U+5C1A # 30-16, CJK UNIFIED IDEOGRAPH-5C1A +U+5C20 # 53-86, CJK UNIFIED IDEOGRAPH-5C20 +U+5C22 # 53-87, CJK UNIFIED IDEOGRAPH-5C22 +U+5C24 # 44-64, CJK UNIFIED IDEOGRAPH-5C24 +U+5C28 # 53-88, CJK UNIFIED IDEOGRAPH-5C28 +U+5C2D # 22-38, CJK UNIFIED IDEOGRAPH-5C2D +U+5C31 # 29-02, CJK UNIFIED IDEOGRAPH-5C31 +U+5C38 # 53-89, CJK UNIFIED IDEOGRAPH-5C38 +U+5C39 # 53-90, CJK UNIFIED IDEOGRAPH-5C39 +U+5C3A # 28-60, CJK UNIFIED IDEOGRAPH-5C3A +U+5C3B # 31-12, CJK UNIFIED IDEOGRAPH-5C3B +U+5C3C # 38-84, CJK UNIFIED IDEOGRAPH-5C3C +U+5C3D # 31-52, CJK UNIFIED IDEOGRAPH-5C3D +U+5C3E # 40-88, CJK UNIFIED IDEOGRAPH-5C3E +U+5C3F # 39-02, CJK UNIFIED IDEOGRAPH-5C3F +U+5C40 # 22-41, CJK UNIFIED IDEOGRAPH-5C40 +U+5C41 # 53-91, CJK UNIFIED IDEOGRAPH-5C41 +U+5C45 # 21-79, CJK UNIFIED IDEOGRAPH-5C45 +U+5C46 # 53-92, CJK UNIFIED IDEOGRAPH-5C46 +U+5C48 # 22-94, CJK UNIFIED IDEOGRAPH-5C48 +U+5C4A # 38-47, CJK UNIFIED IDEOGRAPH-5C4A +U+5C4B # 18-16, CJK UNIFIED IDEOGRAPH-5C4B +U+5C4D # 27-51, CJK UNIFIED IDEOGRAPH-5C4D +U+5C4E # 53-93, CJK UNIFIED IDEOGRAPH-5C4E +U+5C4F # 54-02, CJK UNIFIED IDEOGRAPH-5C4F +U+5C50 # 54-01, CJK UNIFIED IDEOGRAPH-5C50 +U+5C51 # 22-93, CJK UNIFIED IDEOGRAPH-5C51 +U+5C53 # 53-94, CJK UNIFIED IDEOGRAPH-5C53 +U+5C55 # 37-24, CJK UNIFIED IDEOGRAPH-5C55 +U+5C5E # 34-16, CJK UNIFIED IDEOGRAPH-5C5E +U+5C60 # 37-43, CJK UNIFIED IDEOGRAPH-5C60 +U+5C61 # 28-40, CJK UNIFIED IDEOGRAPH-5C61 +U+5C64 # 33-56, CJK UNIFIED IDEOGRAPH-5C64 +U+5C65 # 45-90, CJK UNIFIED IDEOGRAPH-5C65 +U+5C6C # 54-04, CJK UNIFIED IDEOGRAPH-5C6C +U+5C6E # 54-05, CJK UNIFIED IDEOGRAPH-5C6E +U+5C6F # 38-54, CJK UNIFIED IDEOGRAPH-5C6F +U+5C71 # 27-19, CJK UNIFIED IDEOGRAPH-5C71 +U+5C76 # 54-07, CJK UNIFIED IDEOGRAPH-5C76 +U+5C79 # 54-08, CJK UNIFIED IDEOGRAPH-5C79 +U+5C8C # 54-09, CJK UNIFIED IDEOGRAPH-5C8C +U+5C90 # 20-84, CJK UNIFIED IDEOGRAPH-5C90 +U+5C91 # 54-10, CJK UNIFIED IDEOGRAPH-5C91 +U+5C94 # 54-11, CJK UNIFIED IDEOGRAPH-5C94 +U+5CA1 # 18-12, CJK UNIFIED IDEOGRAPH-5CA1 +U+5CA8 # 33-27, CJK UNIFIED IDEOGRAPH-5CA8 +U+5CA9 # 20-68, CJK UNIFIED IDEOGRAPH-5CA9 +U+5CAB # 54-13, CJK UNIFIED IDEOGRAPH-5CAB +U+5CAC # 44-08, CJK UNIFIED IDEOGRAPH-5CAC +U+5CB1 # 34-50, CJK UNIFIED IDEOGRAPH-5CB1 +U+5CB3 # 19-57, CJK UNIFIED IDEOGRAPH-5CB3 +U+5CB6 # 54-15, CJK UNIFIED IDEOGRAPH-5CB6 +U+5CB7 # 54-17, CJK UNIFIED IDEOGRAPH-5CB7 +U+5CB8 # 20-63, CJK UNIFIED IDEOGRAPH-5CB8 +U+5CBB # 54-14, CJK UNIFIED IDEOGRAPH-5CBB +U+5CBC # 54-16, CJK UNIFIED IDEOGRAPH-5CBC +U+5CBE # 54-19, CJK UNIFIED IDEOGRAPH-5CBE +U+5CC5 # 54-18, CJK UNIFIED IDEOGRAPH-5CC5 +U+5CC7 # 54-20, CJK UNIFIED IDEOGRAPH-5CC7 +U+5CD9 # 54-21, CJK UNIFIED IDEOGRAPH-5CD9 +U+5CE0 # 38-29, CJK UNIFIED IDEOGRAPH-5CE0 +U+5CE1 # 22-14, CJK UNIFIED IDEOGRAPH-5CE1 +U+5CE8 # 18-69, CJK UNIFIED IDEOGRAPH-5CE8 +U+5CE9 # 54-22, CJK UNIFIED IDEOGRAPH-5CE9 +U+5CEA # 54-27, CJK UNIFIED IDEOGRAPH-5CEA +U+5CED # 54-25, CJK UNIFIED IDEOGRAPH-5CED +U+5CEF # 42-87, CJK UNIFIED IDEOGRAPH-5CEF +U+5CF0 # 42-86, CJK UNIFIED IDEOGRAPH-5CF0 +U+5CF6 # 37-71, CJK UNIFIED IDEOGRAPH-5CF6 +U+5CFA # 54-24, CJK UNIFIED IDEOGRAPH-5CFA +U+5CFB # 29-52, CJK UNIFIED IDEOGRAPH-5CFB +U+5CFD # 54-23, CJK UNIFIED IDEOGRAPH-5CFD +U+5D07 # 31-82, CJK UNIFIED IDEOGRAPH-5D07 +U+5D0B # 54-28, CJK UNIFIED IDEOGRAPH-5D0B +U+5D0E # 26-74, CJK UNIFIED IDEOGRAPH-5D0E +U+5D11 # 54-34, CJK UNIFIED IDEOGRAPH-5D11 +U+5D14 # 54-35, CJK UNIFIED IDEOGRAPH-5D14 +U+5D15 # 54-29, CJK UNIFIED IDEOGRAPH-5D15 +U+5D16 # 19-19, CJK UNIFIED IDEOGRAPH-5D16 +U+5D17 # 54-30, CJK UNIFIED IDEOGRAPH-5D17 +U+5D18 # 54-39, CJK UNIFIED IDEOGRAPH-5D18 +U+5D19 # 54-38, CJK UNIFIED IDEOGRAPH-5D19 +U+5D1A # 54-37, CJK UNIFIED IDEOGRAPH-5D1A +U+5D1B # 54-33, CJK UNIFIED IDEOGRAPH-5D1B +U+5D1F # 54-32, CJK UNIFIED IDEOGRAPH-5D1F +U+5D22 # 54-36, CJK UNIFIED IDEOGRAPH-5D22 +U+5D29 # 42-88, CJK UNIFIED IDEOGRAPH-5D29 +U+5D4B # 54-43, CJK UNIFIED IDEOGRAPH-5D4B +U+5D4C # 54-40, CJK UNIFIED IDEOGRAPH-5D4C +U+5D4E # 54-42, CJK UNIFIED IDEOGRAPH-5D4E +U+5D50 # 45-82, CJK UNIFIED IDEOGRAPH-5D50 +U+5D52 # 54-41, CJK UNIFIED IDEOGRAPH-5D52 +U+5D5C # 54-31, CJK UNIFIED IDEOGRAPH-5D5C +U+5D69 # 31-83, CJK UNIFIED IDEOGRAPH-5D69 +U+5D6C # 54-44, CJK UNIFIED IDEOGRAPH-5D6C +U+5D6F # 26-23, CJK UNIFIED IDEOGRAPH-5D6F +U+5D73 # 54-45, CJK UNIFIED IDEOGRAPH-5D73 +U+5D76 # 54-46, CJK UNIFIED IDEOGRAPH-5D76 +U+5D82 # 54-49, CJK UNIFIED IDEOGRAPH-5D82 +U+5D84 # 54-48, CJK UNIFIED IDEOGRAPH-5D84 +U+5D87 # 54-47, CJK UNIFIED IDEOGRAPH-5D87 +U+5D8B # 37-72, CJK UNIFIED IDEOGRAPH-5D8B +U+5D8C # 54-26, CJK UNIFIED IDEOGRAPH-5D8C +U+5D90 # 54-55, CJK UNIFIED IDEOGRAPH-5D90 +U+5D9D # 54-51, CJK UNIFIED IDEOGRAPH-5D9D +U+5DA2 # 54-50, CJK UNIFIED IDEOGRAPH-5DA2 +U+5DAC # 54-52, CJK UNIFIED IDEOGRAPH-5DAC +U+5DAE # 54-53, CJK UNIFIED IDEOGRAPH-5DAE +U+5DB7 # 54-56, CJK UNIFIED IDEOGRAPH-5DB7 +U+5DBA # 46-70, CJK UNIFIED IDEOGRAPH-5DBA +U+5DBC # 54-57, CJK UNIFIED IDEOGRAPH-5DBC +U+5DBD # 54-54, CJK UNIFIED IDEOGRAPH-5DBD +U+5DC9 # 54-58, CJK UNIFIED IDEOGRAPH-5DC9 +U+5DCC # 20-64, CJK UNIFIED IDEOGRAPH-5DCC +U+5DCD # 54-59, CJK UNIFIED IDEOGRAPH-5DCD +U+5DD2 # 54-61, CJK UNIFIED IDEOGRAPH-5DD2 +U+5DD3 # 54-60, CJK UNIFIED IDEOGRAPH-5DD3 +U+5DD6 # 54-62, CJK UNIFIED IDEOGRAPH-5DD6 +U+5DDB # 54-63, CJK UNIFIED IDEOGRAPH-5DDB +U+5DDD # 32-78, CJK UNIFIED IDEOGRAPH-5DDD +U+5DDE # 29-03, CJK UNIFIED IDEOGRAPH-5DDE +U+5DE1 # 29-68, CJK UNIFIED IDEOGRAPH-5DE1 +U+5DE3 # 33-67, CJK UNIFIED IDEOGRAPH-5DE3 +U+5DE5 # 25-09, CJK UNIFIED IDEOGRAPH-5DE5 +U+5DE6 # 26-24, CJK UNIFIED IDEOGRAPH-5DE6 +U+5DE7 # 25-10, CJK UNIFIED IDEOGRAPH-5DE7 +U+5DE8 # 21-80, CJK UNIFIED IDEOGRAPH-5DE8 +U+5DEB # 54-64, CJK UNIFIED IDEOGRAPH-5DEB +U+5DEE # 26-25, CJK UNIFIED IDEOGRAPH-5DEE +U+5DF1 # 24-42, CJK UNIFIED IDEOGRAPH-5DF1 +U+5DF2 # 54-65, CJK UNIFIED IDEOGRAPH-5DF2 +U+5DF3 # 44-06, CJK UNIFIED IDEOGRAPH-5DF3 +U+5DF4 # 39-35, CJK UNIFIED IDEOGRAPH-5DF4 +U+5DF5 # 54-66, CJK UNIFIED IDEOGRAPH-5DF5 +U+5DF7 # 25-11, CJK UNIFIED IDEOGRAPH-5DF7 +U+5DFB # 20-12, CJK UNIFIED IDEOGRAPH-5DFB +U+5DFD # 35-07, CJK UNIFIED IDEOGRAPH-5DFD +U+5DFE # 22-50, CJK UNIFIED IDEOGRAPH-5DFE +U+5E02 # 27-52, CJK UNIFIED IDEOGRAPH-5E02 +U+5E03 # 41-59, CJK UNIFIED IDEOGRAPH-5E03 +U+5E06 # 40-33, CJK UNIFIED IDEOGRAPH-5E06 +U+5E0B # 54-67, CJK UNIFIED IDEOGRAPH-5E0B +U+5E0C # 20-85, CJK UNIFIED IDEOGRAPH-5E0C +U+5E11 # 54-70, CJK UNIFIED IDEOGRAPH-5E11 +U+5E16 # 36-01, CJK UNIFIED IDEOGRAPH-5E16 +U+5E19 # 54-69, CJK UNIFIED IDEOGRAPH-5E19 +U+5E1A # 54-68, CJK UNIFIED IDEOGRAPH-5E1A +U+5E1B # 54-71, CJK UNIFIED IDEOGRAPH-5E1B +U+5E1D # 36-75, CJK UNIFIED IDEOGRAPH-5E1D +U+5E25 # 31-67, CJK UNIFIED IDEOGRAPH-5E25 +U+5E2B # 27-53, CJK UNIFIED IDEOGRAPH-5E2B +U+5E2D # 32-42, CJK UNIFIED IDEOGRAPH-5E2D +U+5E2F # 34-51, CJK UNIFIED IDEOGRAPH-5E2F +U+5E30 # 21-02, CJK UNIFIED IDEOGRAPH-5E30 +U+5E33 # 36-02, CJK UNIFIED IDEOGRAPH-5E33 +U+5E36 # 54-72, CJK UNIFIED IDEOGRAPH-5E36 +U+5E37 # 54-73, CJK UNIFIED IDEOGRAPH-5E37 +U+5E38 # 30-79, CJK UNIFIED IDEOGRAPH-5E38 +U+5E3D # 43-25, CJK UNIFIED IDEOGRAPH-5E3D +U+5E40 # 54-76, CJK UNIFIED IDEOGRAPH-5E40 +U+5E43 # 54-75, CJK UNIFIED IDEOGRAPH-5E43 +U+5E44 # 54-74, CJK UNIFIED IDEOGRAPH-5E44 +U+5E45 # 41-93, CJK UNIFIED IDEOGRAPH-5E45 +U+5E47 # 54-83, CJK UNIFIED IDEOGRAPH-5E47 +U+5E4C # 43-58, CJK UNIFIED IDEOGRAPH-5E4C +U+5E4E # 54-77, CJK UNIFIED IDEOGRAPH-5E4E +U+5E54 # 54-79, CJK UNIFIED IDEOGRAPH-5E54 +U+5E55 # 43-75, CJK UNIFIED IDEOGRAPH-5E55 +U+5E57 # 54-78, CJK UNIFIED IDEOGRAPH-5E57 +U+5E5F # 54-80, CJK UNIFIED IDEOGRAPH-5E5F +U+5E61 # 40-08, CJK UNIFIED IDEOGRAPH-5E61 +U+5E62 # 54-81, CJK UNIFIED IDEOGRAPH-5E62 +U+5E63 # 42-30, CJK UNIFIED IDEOGRAPH-5E63 +U+5E64 # 54-82, CJK UNIFIED IDEOGRAPH-5E64 +U+5E72 # 20-19, CJK UNIFIED IDEOGRAPH-5E72 +U+5E73 # 42-31, CJK UNIFIED IDEOGRAPH-5E73 +U+5E74 # 39-15, CJK UNIFIED IDEOGRAPH-5E74 +U+5E75 # 54-84, CJK UNIFIED IDEOGRAPH-5E75 +U+5E76 # 54-85, CJK UNIFIED IDEOGRAPH-5E76 +U+5E78 # 25-12, CJK UNIFIED IDEOGRAPH-5E78 +U+5E79 # 20-20, CJK UNIFIED IDEOGRAPH-5E79 +U+5E7A # 54-86, CJK UNIFIED IDEOGRAPH-5E7A +U+5E7B # 24-24, CJK UNIFIED IDEOGRAPH-5E7B +U+5E7C # 45-36, CJK UNIFIED IDEOGRAPH-5E7C +U+5E7D # 45-09, CJK UNIFIED IDEOGRAPH-5E7D +U+5E7E # 20-86, CJK UNIFIED IDEOGRAPH-5E7E +U+5E7F # 54-88, CJK UNIFIED IDEOGRAPH-5E7F +U+5E81 # 36-03, CJK UNIFIED IDEOGRAPH-5E81 +U+5E83 # 25-13, CJK UNIFIED IDEOGRAPH-5E83 +U+5E84 # 30-17, CJK UNIFIED IDEOGRAPH-5E84 +U+5E87 # 40-63, CJK UNIFIED IDEOGRAPH-5E87 +U+5E8A # 30-18, CJK UNIFIED IDEOGRAPH-5E8A +U+5E8F # 29-88, CJK UNIFIED IDEOGRAPH-5E8F +U+5E95 # 36-76, CJK UNIFIED IDEOGRAPH-5E95 +U+5E96 # 42-89, CJK UNIFIED IDEOGRAPH-5E96 +U+5E97 # 37-25, CJK UNIFIED IDEOGRAPH-5E97 +U+5E9A # 25-14, CJK UNIFIED IDEOGRAPH-5E9A +U+5E9C # 41-60, CJK UNIFIED IDEOGRAPH-5E9C +U+5EA0 # 54-89, CJK UNIFIED IDEOGRAPH-5EA0 +U+5EA6 # 37-57, CJK UNIFIED IDEOGRAPH-5EA6 +U+5EA7 # 26-34, CJK UNIFIED IDEOGRAPH-5EA7 +U+5EAB # 24-43, CJK UNIFIED IDEOGRAPH-5EAB +U+5EAD # 36-77, CJK UNIFIED IDEOGRAPH-5EAD +U+5EB5 # 16-35, CJK UNIFIED IDEOGRAPH-5EB5 +U+5EB6 # 29-78, CJK UNIFIED IDEOGRAPH-5EB6 +U+5EB7 # 25-15, CJK UNIFIED IDEOGRAPH-5EB7 +U+5EB8 # 45-39, CJK UNIFIED IDEOGRAPH-5EB8 +U+5EC1 # 54-90, CJK UNIFIED IDEOGRAPH-5EC1 +U+5EC2 # 54-91, CJK UNIFIED IDEOGRAPH-5EC2 +U+5EC3 # 39-49, CJK UNIFIED IDEOGRAPH-5EC3 +U+5EC8 # 54-92, CJK UNIFIED IDEOGRAPH-5EC8 +U+5EC9 # 46-87, CJK UNIFIED IDEOGRAPH-5EC9 +U+5ECA # 47-13, CJK UNIFIED IDEOGRAPH-5ECA +U+5ECF # 54-94, CJK UNIFIED IDEOGRAPH-5ECF +U+5ED0 # 54-93, CJK UNIFIED IDEOGRAPH-5ED0 +U+5ED3 # 19-39, CJK UNIFIED IDEOGRAPH-5ED3 +U+5ED6 # 55-01, CJK UNIFIED IDEOGRAPH-5ED6 +U+5EDA # 55-04, CJK UNIFIED IDEOGRAPH-5EDA +U+5EDB # 55-05, CJK UNIFIED IDEOGRAPH-5EDB +U+5EDD # 55-03, CJK UNIFIED IDEOGRAPH-5EDD +U+5EDF # 41-32, CJK UNIFIED IDEOGRAPH-5EDF +U+5EE0 # 30-19, CJK UNIFIED IDEOGRAPH-5EE0 +U+5EE1 # 55-07, CJK UNIFIED IDEOGRAPH-5EE1 +U+5EE2 # 55-06, CJK UNIFIED IDEOGRAPH-5EE2 +U+5EE3 # 55-02, CJK UNIFIED IDEOGRAPH-5EE3 +U+5EE8 # 55-08, CJK UNIFIED IDEOGRAPH-5EE8 +U+5EE9 # 55-09, CJK UNIFIED IDEOGRAPH-5EE9 +U+5EEC # 55-10, CJK UNIFIED IDEOGRAPH-5EEC +U+5EF0 # 55-13, CJK UNIFIED IDEOGRAPH-5EF0 +U+5EF1 # 55-11, CJK UNIFIED IDEOGRAPH-5EF1 +U+5EF3 # 55-12, CJK UNIFIED IDEOGRAPH-5EF3 +U+5EF4 # 55-14, CJK UNIFIED IDEOGRAPH-5EF4 +U+5EF6 # 17-68, CJK UNIFIED IDEOGRAPH-5EF6 +U+5EF7 # 36-78, CJK UNIFIED IDEOGRAPH-5EF7 +U+5EF8 # 55-15, CJK UNIFIED IDEOGRAPH-5EF8 +U+5EFA # 23-90, CJK UNIFIED IDEOGRAPH-5EFA +U+5EFB # 18-86, CJK UNIFIED IDEOGRAPH-5EFB +U+5EFC # 39-22, CJK UNIFIED IDEOGRAPH-5EFC +U+5EFE # 55-16, CJK UNIFIED IDEOGRAPH-5EFE +U+5EFF # 38-91, CJK UNIFIED IDEOGRAPH-5EFF +U+5F01 # 42-59, CJK UNIFIED IDEOGRAPH-5F01 +U+5F03 # 55-17, CJK UNIFIED IDEOGRAPH-5F03 +U+5F04 # 47-14, CJK UNIFIED IDEOGRAPH-5F04 +U+5F09 # 55-18, CJK UNIFIED IDEOGRAPH-5F09 +U+5F0A # 42-32, CJK UNIFIED IDEOGRAPH-5F0A +U+5F0B # 55-21, CJK UNIFIED IDEOGRAPH-5F0B +U+5F0C # 48-01, CJK UNIFIED IDEOGRAPH-5F0C +U+5F0D # 48-17, CJK UNIFIED IDEOGRAPH-5F0D +U+5F0F # 28-16, CJK UNIFIED IDEOGRAPH-5F0F +U+5F10 # 38-85, CJK UNIFIED IDEOGRAPH-5F10 +U+5F11 # 55-22, CJK UNIFIED IDEOGRAPH-5F11 +U+5F13 # 21-61, CJK UNIFIED IDEOGRAPH-5F13 +U+5F14 # 36-04, CJK UNIFIED IDEOGRAPH-5F14 +U+5F15 # 16-90, CJK UNIFIED IDEOGRAPH-5F15 +U+5F16 # 55-23, CJK UNIFIED IDEOGRAPH-5F16 +U+5F17 # 42-06, CJK UNIFIED IDEOGRAPH-5F17 +U+5F18 # 25-16, CJK UNIFIED IDEOGRAPH-5F18 +U+5F1B # 35-48, CJK UNIFIED IDEOGRAPH-5F1B +U+5F1F # 36-79, CJK UNIFIED IDEOGRAPH-5F1F +U+5F25 # 44-79, CJK UNIFIED IDEOGRAPH-5F25 +U+5F26 # 24-25, CJK UNIFIED IDEOGRAPH-5F26 +U+5F27 # 24-44, CJK UNIFIED IDEOGRAPH-5F27 +U+5F29 # 55-24, CJK UNIFIED IDEOGRAPH-5F29 +U+5F2D # 55-25, CJK UNIFIED IDEOGRAPH-5F2D +U+5F2F # 55-31, CJK UNIFIED IDEOGRAPH-5F2F +U+5F31 # 28-69, CJK UNIFIED IDEOGRAPH-5F31 +U+5F35 # 36-05, CJK UNIFIED IDEOGRAPH-5F35 +U+5F37 # 22-15, CJK UNIFIED IDEOGRAPH-5F37 +U+5F38 # 55-26, CJK UNIFIED IDEOGRAPH-5F38 +U+5F3C # 41-11, CJK UNIFIED IDEOGRAPH-5F3C +U+5F3E # 35-38, CJK UNIFIED IDEOGRAPH-5F3E +U+5F41 # 55-27, CJK UNIFIED IDEOGRAPH-5F41 +U+5F48 # 55-28, CJK UNIFIED IDEOGRAPH-5F48 +U+5F4A # 22-16, CJK UNIFIED IDEOGRAPH-5F4A +U+5F4C # 55-29, CJK UNIFIED IDEOGRAPH-5F4C +U+5F4E # 55-30, CJK UNIFIED IDEOGRAPH-5F4E +U+5F51 # 55-32, CJK UNIFIED IDEOGRAPH-5F51 +U+5F53 # 37-86, CJK UNIFIED IDEOGRAPH-5F53 +U+5F56 # 55-33, CJK UNIFIED IDEOGRAPH-5F56 +U+5F57 # 55-34, CJK UNIFIED IDEOGRAPH-5F57 +U+5F59 # 55-35, CJK UNIFIED IDEOGRAPH-5F59 +U+5F5C # 55-20, CJK UNIFIED IDEOGRAPH-5F5C +U+5F5D # 55-19, CJK UNIFIED IDEOGRAPH-5F5D +U+5F61 # 55-36, CJK UNIFIED IDEOGRAPH-5F61 +U+5F62 # 23-33, CJK UNIFIED IDEOGRAPH-5F62 +U+5F66 # 41-07, CJK UNIFIED IDEOGRAPH-5F66 +U+5F69 # 26-44, CJK UNIFIED IDEOGRAPH-5F69 +U+5F6A # 41-23, CJK UNIFIED IDEOGRAPH-5F6A +U+5F6B # 36-06, CJK UNIFIED IDEOGRAPH-5F6B +U+5F6C # 41-43, CJK UNIFIED IDEOGRAPH-5F6C +U+5F6D # 55-37, CJK UNIFIED IDEOGRAPH-5F6D +U+5F70 # 30-20, CJK UNIFIED IDEOGRAPH-5F70 +U+5F71 # 17-38, CJK UNIFIED IDEOGRAPH-5F71 +U+5F73 # 55-38, CJK UNIFIED IDEOGRAPH-5F73 +U+5F77 # 55-39, CJK UNIFIED IDEOGRAPH-5F77 +U+5F79 # 44-82, CJK UNIFIED IDEOGRAPH-5F79 +U+5F7C # 40-64, CJK UNIFIED IDEOGRAPH-5F7C +U+5F7F # 55-42, CJK UNIFIED IDEOGRAPH-5F7F +U+5F80 # 17-93, CJK UNIFIED IDEOGRAPH-5F80 +U+5F81 # 32-12, CJK UNIFIED IDEOGRAPH-5F81 +U+5F82 # 55-41, CJK UNIFIED IDEOGRAPH-5F82 +U+5F83 # 55-40, CJK UNIFIED IDEOGRAPH-5F83 +U+5F84 # 23-34, CJK UNIFIED IDEOGRAPH-5F84 +U+5F85 # 34-52, CJK UNIFIED IDEOGRAPH-5F85 +U+5F87 # 55-46, CJK UNIFIED IDEOGRAPH-5F87 +U+5F88 # 55-44, CJK UNIFIED IDEOGRAPH-5F88 +U+5F8A # 55-43, CJK UNIFIED IDEOGRAPH-5F8A +U+5F8B # 46-07, CJK UNIFIED IDEOGRAPH-5F8B +U+5F8C # 24-69, CJK UNIFIED IDEOGRAPH-5F8C +U+5F90 # 29-89, CJK UNIFIED IDEOGRAPH-5F90 +U+5F91 # 55-45, CJK UNIFIED IDEOGRAPH-5F91 +U+5F92 # 37-44, CJK UNIFIED IDEOGRAPH-5F92 +U+5F93 # 29-30, CJK UNIFIED IDEOGRAPH-5F93 +U+5F97 # 38-32, CJK UNIFIED IDEOGRAPH-5F97 +U+5F98 # 55-49, CJK UNIFIED IDEOGRAPH-5F98 +U+5F99 # 55-48, CJK UNIFIED IDEOGRAPH-5F99 +U+5F9E # 55-47, CJK UNIFIED IDEOGRAPH-5F9E +U+5FA0 # 55-50, CJK UNIFIED IDEOGRAPH-5FA0 +U+5FA1 # 24-70, CJK UNIFIED IDEOGRAPH-5FA1 +U+5FA8 # 55-51, CJK UNIFIED IDEOGRAPH-5FA8 +U+5FA9 # 41-92, CJK UNIFIED IDEOGRAPH-5FA9 +U+5FAA # 29-59, CJK UNIFIED IDEOGRAPH-5FAA +U+5FAD # 55-52, CJK UNIFIED IDEOGRAPH-5FAD +U+5FAE # 40-89, CJK UNIFIED IDEOGRAPH-5FAE +U+5FB3 # 38-33, CJK UNIFIED IDEOGRAPH-5FB3 +U+5FB4 # 36-07, CJK UNIFIED IDEOGRAPH-5FB4 +U+5FB9 # 37-16, CJK UNIFIED IDEOGRAPH-5FB9 +U+5FBC # 55-53, CJK UNIFIED IDEOGRAPH-5FBC +U+5FBD # 21-11, CJK UNIFIED IDEOGRAPH-5FBD +U+5FC3 # 31-20, CJK UNIFIED IDEOGRAPH-5FC3 +U+5FC5 # 41-12, CJK UNIFIED IDEOGRAPH-5FC5 +U+5FCC # 20-87, CJK UNIFIED IDEOGRAPH-5FCC +U+5FCD # 39-06, CJK UNIFIED IDEOGRAPH-5FCD +U+5FD6 # 55-54, CJK UNIFIED IDEOGRAPH-5FD6 +U+5FD7 # 27-54, CJK UNIFIED IDEOGRAPH-5FD7 +U+5FD8 # 43-26, CJK UNIFIED IDEOGRAPH-5FD8 +U+5FD9 # 43-27, CJK UNIFIED IDEOGRAPH-5FD9 +U+5FDC # 17-94, CJK UNIFIED IDEOGRAPH-5FDC +U+5FDD # 55-59, CJK UNIFIED IDEOGRAPH-5FDD +U+5FE0 # 35-73, CJK UNIFIED IDEOGRAPH-5FE0 +U+5FE4 # 55-56, CJK UNIFIED IDEOGRAPH-5FE4 +U+5FEB # 18-87, CJK UNIFIED IDEOGRAPH-5FEB +U+5FF0 # 56-13, CJK UNIFIED IDEOGRAPH-5FF0 +U+5FF1 # 55-58, CJK UNIFIED IDEOGRAPH-5FF1 +U+5FF5 # 39-16, CJK UNIFIED IDEOGRAPH-5FF5 +U+5FF8 # 55-57, CJK UNIFIED IDEOGRAPH-5FF8 +U+5FFB # 55-55, CJK UNIFIED IDEOGRAPH-5FFB +U+5FFD # 25-90, CJK UNIFIED IDEOGRAPH-5FFD +U+5FFF # 55-61, CJK UNIFIED IDEOGRAPH-5FFF +U+600E # 55-67, CJK UNIFIED IDEOGRAPH-600E +U+600F # 55-73, CJK UNIFIED IDEOGRAPH-600F +U+6010 # 55-65, CJK UNIFIED IDEOGRAPH-6010 +U+6012 # 37-60, CJK UNIFIED IDEOGRAPH-6012 +U+6015 # 55-70, CJK UNIFIED IDEOGRAPH-6015 +U+6016 # 41-61, CJK UNIFIED IDEOGRAPH-6016 +U+6019 # 55-64, CJK UNIFIED IDEOGRAPH-6019 +U+601B # 55-69, CJK UNIFIED IDEOGRAPH-601B +U+601C # 46-71, CJK UNIFIED IDEOGRAPH-601C +U+601D # 27-55, CJK UNIFIED IDEOGRAPH-601D +U+6020 # 34-53, CJK UNIFIED IDEOGRAPH-6020 +U+6021 # 55-62, CJK UNIFIED IDEOGRAPH-6021 +U+6025 # 21-62, CJK UNIFIED IDEOGRAPH-6025 +U+6026 # 55-72, CJK UNIFIED IDEOGRAPH-6026 +U+6027 # 32-13, CJK UNIFIED IDEOGRAPH-6027 +U+6028 # 17-69, CJK UNIFIED IDEOGRAPH-6028 +U+6029 # 55-66, CJK UNIFIED IDEOGRAPH-6029 +U+602A # 18-88, CJK UNIFIED IDEOGRAPH-602A +U+602B # 55-71, CJK UNIFIED IDEOGRAPH-602B +U+602F # 22-17, CJK UNIFIED IDEOGRAPH-602F +U+6031 # 55-68, CJK UNIFIED IDEOGRAPH-6031 +U+603A # 55-74, CJK UNIFIED IDEOGRAPH-603A +U+6041 # 55-76, CJK UNIFIED IDEOGRAPH-6041 +U+6042 # 55-86, CJK UNIFIED IDEOGRAPH-6042 +U+6043 # 55-84, CJK UNIFIED IDEOGRAPH-6043 +U+6046 # 55-81, CJK UNIFIED IDEOGRAPH-6046 +U+604A # 55-80, CJK UNIFIED IDEOGRAPH-604A +U+604B # 46-88, CJK UNIFIED IDEOGRAPH-604B +U+604D # 55-82, CJK UNIFIED IDEOGRAPH-604D +U+6050 # 22-18, CJK UNIFIED IDEOGRAPH-6050 +U+6052 # 25-17, CJK UNIFIED IDEOGRAPH-6052 +U+6055 # 29-90, CJK UNIFIED IDEOGRAPH-6055 +U+6059 # 55-89, CJK UNIFIED IDEOGRAPH-6059 +U+605A # 55-75, CJK UNIFIED IDEOGRAPH-605A +U+605F # 55-79, CJK UNIFIED IDEOGRAPH-605F +U+6060 # 55-63, CJK UNIFIED IDEOGRAPH-6060 +U+6062 # 18-90, CJK UNIFIED IDEOGRAPH-6062 +U+6063 # 55-83, CJK UNIFIED IDEOGRAPH-6063 +U+6064 # 55-85, CJK UNIFIED IDEOGRAPH-6064 +U+6065 # 35-49, CJK UNIFIED IDEOGRAPH-6065 +U+6068 # 26-08, CJK UNIFIED IDEOGRAPH-6068 +U+6069 # 18-24, CJK UNIFIED IDEOGRAPH-6069 +U+606A # 55-77, CJK UNIFIED IDEOGRAPH-606A +U+606B # 55-88, CJK UNIFIED IDEOGRAPH-606B +U+606C # 55-87, CJK UNIFIED IDEOGRAPH-606C +U+606D # 22-19, CJK UNIFIED IDEOGRAPH-606D +U+606F # 34-09, CJK UNIFIED IDEOGRAPH-606F +U+6070 # 19-70, CJK UNIFIED IDEOGRAPH-6070 +U+6075 # 23-35, CJK UNIFIED IDEOGRAPH-6075 +U+6077 # 55-78, CJK UNIFIED IDEOGRAPH-6077 +U+6081 # 55-90, CJK UNIFIED IDEOGRAPH-6081 +U+6083 # 55-93, CJK UNIFIED IDEOGRAPH-6083 +U+6084 # 56-01, CJK UNIFIED IDEOGRAPH-6084 +U+6089 # 28-29, CJK UNIFIED IDEOGRAPH-6089 +U+608B # 56-07, CJK UNIFIED IDEOGRAPH-608B +U+608C # 36-80, CJK UNIFIED IDEOGRAPH-608C +U+608D # 55-91, CJK UNIFIED IDEOGRAPH-608D +U+6092 # 56-05, CJK UNIFIED IDEOGRAPH-6092 +U+6094 # 18-89, CJK UNIFIED IDEOGRAPH-6094 +U+6096 # 56-03, CJK UNIFIED IDEOGRAPH-6096 +U+6097 # 56-04, CJK UNIFIED IDEOGRAPH-6097 +U+609A # 55-94, CJK UNIFIED IDEOGRAPH-609A +U+609B # 56-02, CJK UNIFIED IDEOGRAPH-609B +U+609F # 24-71, CJK UNIFIED IDEOGRAPH-609F +U+60A0 # 45-10, CJK UNIFIED IDEOGRAPH-60A0 +U+60A3 # 20-21, CJK UNIFIED IDEOGRAPH-60A3 +U+60A6 # 17-57, CJK UNIFIED IDEOGRAPH-60A6 +U+60A7 # 56-06, CJK UNIFIED IDEOGRAPH-60A7 +U+60A9 # 39-26, CJK UNIFIED IDEOGRAPH-60A9 +U+60AA # 16-13, CJK UNIFIED IDEOGRAPH-60AA +U+60B2 # 40-65, CJK UNIFIED IDEOGRAPH-60B2 +U+60B3 # 55-60, CJK UNIFIED IDEOGRAPH-60B3 +U+60B4 # 56-12, CJK UNIFIED IDEOGRAPH-60B4 +U+60B5 # 56-16, CJK UNIFIED IDEOGRAPH-60B5 +U+60B6 # 44-69, CJK UNIFIED IDEOGRAPH-60B6 +U+60B8 # 56-09, CJK UNIFIED IDEOGRAPH-60B8 +U+60BC # 37-73, CJK UNIFIED IDEOGRAPH-60BC +U+60BD # 56-14, CJK UNIFIED IDEOGRAPH-60BD +U+60C5 # 30-80, CJK UNIFIED IDEOGRAPH-60C5 +U+60C6 # 56-15, CJK UNIFIED IDEOGRAPH-60C6 +U+60C7 # 38-55, CJK UNIFIED IDEOGRAPH-60C7 +U+60D1 # 47-39, CJK UNIFIED IDEOGRAPH-60D1 +U+60D3 # 56-11, CJK UNIFIED IDEOGRAPH-60D3 +U+60D8 # 56-17, CJK UNIFIED IDEOGRAPH-60D8 +U+60DA # 25-91, CJK UNIFIED IDEOGRAPH-60DA +U+60DC # 32-43, CJK UNIFIED IDEOGRAPH-60DC +U+60DF # 16-52, CJK UNIFIED IDEOGRAPH-60DF +U+60E0 # 56-10, CJK UNIFIED IDEOGRAPH-60E0 +U+60E1 # 56-08, CJK UNIFIED IDEOGRAPH-60E1 +U+60E3 # 33-58, CJK UNIFIED IDEOGRAPH-60E3 +U+60E7 # 55-92, CJK UNIFIED IDEOGRAPH-60E7 +U+60E8 # 27-20, CJK UNIFIED IDEOGRAPH-60E8 +U+60F0 # 34-38, CJK UNIFIED IDEOGRAPH-60F0 +U+60F1 # 56-29, CJK UNIFIED IDEOGRAPH-60F1 +U+60F3 # 33-59, CJK UNIFIED IDEOGRAPH-60F3 +U+60F4 # 56-24, CJK UNIFIED IDEOGRAPH-60F4 +U+60F6 # 56-21, CJK UNIFIED IDEOGRAPH-60F6 +U+60F7 # 56-22, CJK UNIFIED IDEOGRAPH-60F7 +U+60F9 # 28-70, CJK UNIFIED IDEOGRAPH-60F9 +U+60FA # 56-25, CJK UNIFIED IDEOGRAPH-60FA +U+60FB # 56-28, CJK UNIFIED IDEOGRAPH-60FB +U+6100 # 56-23, CJK UNIFIED IDEOGRAPH-6100 +U+6101 # 29-05, CJK UNIFIED IDEOGRAPH-6101 +U+6103 # 56-26, CJK UNIFIED IDEOGRAPH-6103 +U+6106 # 56-20, CJK UNIFIED IDEOGRAPH-6106 +U+6108 # 44-92, CJK UNIFIED IDEOGRAPH-6108 +U+6109 # 44-91, CJK UNIFIED IDEOGRAPH-6109 +U+610D # 56-30, CJK UNIFIED IDEOGRAPH-610D +U+610E # 56-31, CJK UNIFIED IDEOGRAPH-610E +U+610F # 16-53, CJK UNIFIED IDEOGRAPH-610F +U+6115 # 56-19, CJK UNIFIED IDEOGRAPH-6115 +U+611A # 22-82, CJK UNIFIED IDEOGRAPH-611A +U+611B # 16-06, CJK UNIFIED IDEOGRAPH-611B +U+611F # 20-22, CJK UNIFIED IDEOGRAPH-611F +U+6121 # 56-27, CJK UNIFIED IDEOGRAPH-6121 +U+6127 # 56-35, CJK UNIFIED IDEOGRAPH-6127 +U+6128 # 56-34, CJK UNIFIED IDEOGRAPH-6128 +U+612C # 56-39, CJK UNIFIED IDEOGRAPH-612C +U+6134 # 56-40, CJK UNIFIED IDEOGRAPH-6134 +U+613C # 56-38, CJK UNIFIED IDEOGRAPH-613C +U+613D # 56-41, CJK UNIFIED IDEOGRAPH-613D +U+613E # 56-33, CJK UNIFIED IDEOGRAPH-613E +U+613F # 56-37, CJK UNIFIED IDEOGRAPH-613F +U+6142 # 56-42, CJK UNIFIED IDEOGRAPH-6142 +U+6144 # 56-43, CJK UNIFIED IDEOGRAPH-6144 +U+6147 # 56-32, CJK UNIFIED IDEOGRAPH-6147 +U+6148 # 27-92, CJK UNIFIED IDEOGRAPH-6148 +U+614A # 56-36, CJK UNIFIED IDEOGRAPH-614A +U+614B # 34-54, CJK UNIFIED IDEOGRAPH-614B +U+614C # 25-18, CJK UNIFIED IDEOGRAPH-614C +U+614D # 56-18, CJK UNIFIED IDEOGRAPH-614D +U+614E # 31-21, CJK UNIFIED IDEOGRAPH-614E +U+6153 # 56-56, CJK UNIFIED IDEOGRAPH-6153 +U+6155 # 42-73, CJK UNIFIED IDEOGRAPH-6155 +U+6158 # 56-46, CJK UNIFIED IDEOGRAPH-6158 +U+6159 # 56-47, CJK UNIFIED IDEOGRAPH-6159 +U+615A # 56-48, CJK UNIFIED IDEOGRAPH-615A +U+615D # 56-55, CJK UNIFIED IDEOGRAPH-615D +U+615F # 56-54, CJK UNIFIED IDEOGRAPH-615F +U+6162 # 43-93, CJK UNIFIED IDEOGRAPH-6162 +U+6163 # 20-23, CJK UNIFIED IDEOGRAPH-6163 +U+6165 # 56-52, CJK UNIFIED IDEOGRAPH-6165 +U+6167 # 23-37, CJK UNIFIED IDEOGRAPH-6167 +U+6168 # 19-20, CJK UNIFIED IDEOGRAPH-6168 +U+616B # 56-49, CJK UNIFIED IDEOGRAPH-616B +U+616E # 46-24, CJK UNIFIED IDEOGRAPH-616E +U+616F # 56-51, CJK UNIFIED IDEOGRAPH-616F +U+6170 # 16-54, CJK UNIFIED IDEOGRAPH-6170 +U+6171 # 56-53, CJK UNIFIED IDEOGRAPH-6171 +U+6173 # 56-44, CJK UNIFIED IDEOGRAPH-6173 +U+6174 # 56-50, CJK UNIFIED IDEOGRAPH-6174 +U+6175 # 56-57, CJK UNIFIED IDEOGRAPH-6175 +U+6176 # 23-36, CJK UNIFIED IDEOGRAPH-6176 +U+6177 # 56-45, CJK UNIFIED IDEOGRAPH-6177 +U+617E # 45-61, CJK UNIFIED IDEOGRAPH-617E +U+6182 # 45-11, CJK UNIFIED IDEOGRAPH-6182 +U+6187 # 56-60, CJK UNIFIED IDEOGRAPH-6187 +U+618A # 56-64, CJK UNIFIED IDEOGRAPH-618A +U+618E # 33-94, CJK UNIFIED IDEOGRAPH-618E +U+6190 # 46-89, CJK UNIFIED IDEOGRAPH-6190 +U+6191 # 56-65, CJK UNIFIED IDEOGRAPH-6191 +U+6194 # 56-62, CJK UNIFIED IDEOGRAPH-6194 +U+6196 # 56-59, CJK UNIFIED IDEOGRAPH-6196 +U+6199 # 56-58, CJK UNIFIED IDEOGRAPH-6199 +U+619A # 56-63, CJK UNIFIED IDEOGRAPH-619A +U+61A4 # 42-16, CJK UNIFIED IDEOGRAPH-61A4 +U+61A7 # 38-20, CJK UNIFIED IDEOGRAPH-61A7 +U+61A9 # 23-38, CJK UNIFIED IDEOGRAPH-61A9 +U+61AB # 56-66, CJK UNIFIED IDEOGRAPH-61AB +U+61AC # 56-61, CJK UNIFIED IDEOGRAPH-61AC +U+61AE # 56-67, CJK UNIFIED IDEOGRAPH-61AE +U+61B2 # 23-91, CJK UNIFIED IDEOGRAPH-61B2 +U+61B6 # 18-17, CJK UNIFIED IDEOGRAPH-61B6 +U+61BA # 56-75, CJK UNIFIED IDEOGRAPH-61BA +U+61BE # 20-24, CJK UNIFIED IDEOGRAPH-61BE +U+61C3 # 56-73, CJK UNIFIED IDEOGRAPH-61C3 +U+61C6 # 56-74, CJK UNIFIED IDEOGRAPH-61C6 +U+61C7 # 26-09, CJK UNIFIED IDEOGRAPH-61C7 +U+61C8 # 56-72, CJK UNIFIED IDEOGRAPH-61C8 +U+61C9 # 56-70, CJK UNIFIED IDEOGRAPH-61C9 +U+61CA # 56-69, CJK UNIFIED IDEOGRAPH-61CA +U+61CB # 56-76, CJK UNIFIED IDEOGRAPH-61CB +U+61CC # 56-68, CJK UNIFIED IDEOGRAPH-61CC +U+61CD # 56-78, CJK UNIFIED IDEOGRAPH-61CD +U+61D0 # 18-91, CJK UNIFIED IDEOGRAPH-61D0 +U+61E3 # 56-80, CJK UNIFIED IDEOGRAPH-61E3 +U+61E6 # 56-79, CJK UNIFIED IDEOGRAPH-61E6 +U+61F2 # 36-08, CJK UNIFIED IDEOGRAPH-61F2 +U+61F4 # 56-83, CJK UNIFIED IDEOGRAPH-61F4 +U+61F6 # 56-81, CJK UNIFIED IDEOGRAPH-61F6 +U+61F7 # 56-71, CJK UNIFIED IDEOGRAPH-61F7 +U+61F8 # 23-92, CJK UNIFIED IDEOGRAPH-61F8 +U+61FA # 56-82, CJK UNIFIED IDEOGRAPH-61FA +U+61FC # 56-86, CJK UNIFIED IDEOGRAPH-61FC +U+61FD # 56-85, CJK UNIFIED IDEOGRAPH-61FD +U+61FE # 56-87, CJK UNIFIED IDEOGRAPH-61FE +U+61FF # 56-84, CJK UNIFIED IDEOGRAPH-61FF +U+6200 # 56-88, CJK UNIFIED IDEOGRAPH-6200 +U+6208 # 56-89, CJK UNIFIED IDEOGRAPH-6208 +U+6209 # 56-90, CJK UNIFIED IDEOGRAPH-6209 +U+620A # 42-74, CJK UNIFIED IDEOGRAPH-620A +U+620C # 56-92, CJK UNIFIED IDEOGRAPH-620C +U+620D # 56-91, CJK UNIFIED IDEOGRAPH-620D +U+620E # 29-31, CJK UNIFIED IDEOGRAPH-620E +U+6210 # 32-14, CJK UNIFIED IDEOGRAPH-6210 +U+6211 # 18-70, CJK UNIFIED IDEOGRAPH-6211 +U+6212 # 18-92, CJK UNIFIED IDEOGRAPH-6212 +U+6214 # 56-93, CJK UNIFIED IDEOGRAPH-6214 +U+6216 # 16-31, CJK UNIFIED IDEOGRAPH-6216 +U+621A # 32-44, CJK UNIFIED IDEOGRAPH-621A +U+621B # 56-94, CJK UNIFIED IDEOGRAPH-621B +U+621D # 76-35, CJK UNIFIED IDEOGRAPH-621D +U+621E # 57-01, CJK UNIFIED IDEOGRAPH-621E +U+621F # 23-65, CJK UNIFIED IDEOGRAPH-621F +U+6221 # 57-02, CJK UNIFIED IDEOGRAPH-6221 +U+6226 # 32-79, CJK UNIFIED IDEOGRAPH-6226 +U+622A # 57-03, CJK UNIFIED IDEOGRAPH-622A +U+622E # 57-04, CJK UNIFIED IDEOGRAPH-622E +U+622F # 21-26, CJK UNIFIED IDEOGRAPH-622F +U+6230 # 57-05, CJK UNIFIED IDEOGRAPH-6230 +U+6232 # 57-06, CJK UNIFIED IDEOGRAPH-6232 +U+6233 # 57-07, CJK UNIFIED IDEOGRAPH-6233 +U+6234 # 34-55, CJK UNIFIED IDEOGRAPH-6234 +U+6238 # 24-45, CJK UNIFIED IDEOGRAPH-6238 +U+623B # 44-65, CJK UNIFIED IDEOGRAPH-623B +U+623F # 43-28, CJK UNIFIED IDEOGRAPH-623F +U+6240 # 29-74, CJK UNIFIED IDEOGRAPH-6240 +U+6241 # 57-08, CJK UNIFIED IDEOGRAPH-6241 +U+6247 # 32-80, CJK UNIFIED IDEOGRAPH-6247 +U+6248 # 78-29, CJK UNIFIED IDEOGRAPH-6248 +U+6249 # 40-66, CJK UNIFIED IDEOGRAPH-6249 +U+624B # 28-74, CJK UNIFIED IDEOGRAPH-624B +U+624D # 26-45, CJK UNIFIED IDEOGRAPH-624D +U+624E # 57-09, CJK UNIFIED IDEOGRAPH-624E +U+6253 # 34-39, CJK UNIFIED IDEOGRAPH-6253 +U+6255 # 42-07, CJK UNIFIED IDEOGRAPH-6255 +U+6258 # 34-81, CJK UNIFIED IDEOGRAPH-6258 +U+625B # 57-12, CJK UNIFIED IDEOGRAPH-625B +U+625E # 57-10, CJK UNIFIED IDEOGRAPH-625E +U+6260 # 57-13, CJK UNIFIED IDEOGRAPH-6260 +U+6263 # 57-11, CJK UNIFIED IDEOGRAPH-6263 +U+6268 # 57-14, CJK UNIFIED IDEOGRAPH-6268 +U+626E # 42-17, CJK UNIFIED IDEOGRAPH-626E +U+6271 # 16-23, CJK UNIFIED IDEOGRAPH-6271 +U+6276 # 41-62, CJK UNIFIED IDEOGRAPH-6276 +U+6279 # 40-67, CJK UNIFIED IDEOGRAPH-6279 +U+627C # 57-15, CJK UNIFIED IDEOGRAPH-627C +U+627E # 57-18, CJK UNIFIED IDEOGRAPH-627E +U+627F # 30-21, CJK UNIFIED IDEOGRAPH-627F +U+6280 # 21-27, CJK UNIFIED IDEOGRAPH-6280 +U+6282 # 57-16, CJK UNIFIED IDEOGRAPH-6282 +U+6283 # 57-23, CJK UNIFIED IDEOGRAPH-6283 +U+6284 # 30-22, CJK UNIFIED IDEOGRAPH-6284 +U+6289 # 57-17, CJK UNIFIED IDEOGRAPH-6289 +U+628A # 39-36, CJK UNIFIED IDEOGRAPH-628A +U+6291 # 45-62, CJK UNIFIED IDEOGRAPH-6291 +U+6292 # 57-19, CJK UNIFIED IDEOGRAPH-6292 +U+6293 # 57-20, CJK UNIFIED IDEOGRAPH-6293 +U+6294 # 57-24, CJK UNIFIED IDEOGRAPH-6294 +U+6295 # 37-74, CJK UNIFIED IDEOGRAPH-6295 +U+6296 # 57-21, CJK UNIFIED IDEOGRAPH-6296 +U+6297 # 25-19, CJK UNIFIED IDEOGRAPH-6297 +U+6298 # 32-62, CJK UNIFIED IDEOGRAPH-6298 +U+629B # 57-38, CJK UNIFIED IDEOGRAPH-629B +U+629C # 40-20, CJK UNIFIED IDEOGRAPH-629C +U+629E # 34-82, CJK UNIFIED IDEOGRAPH-629E +U+62AB # 40-68, CJK UNIFIED IDEOGRAPH-62AB +U+62AC # 58-13, CJK UNIFIED IDEOGRAPH-62AC +U+62B1 # 42-90, CJK UNIFIED IDEOGRAPH-62B1 +U+62B5 # 36-81, CJK UNIFIED IDEOGRAPH-62B5 +U+62B9 # 43-85, CJK UNIFIED IDEOGRAPH-62B9 +U+62BB # 57-27, CJK UNIFIED IDEOGRAPH-62BB +U+62BC # 18-01, CJK UNIFIED IDEOGRAPH-62BC +U+62BD # 35-74, CJK UNIFIED IDEOGRAPH-62BD +U+62C2 # 57-36, CJK UNIFIED IDEOGRAPH-62C2 +U+62C5 # 35-20, CJK UNIFIED IDEOGRAPH-62C5 +U+62C6 # 57-30, CJK UNIFIED IDEOGRAPH-62C6 +U+62C7 # 57-37, CJK UNIFIED IDEOGRAPH-62C7 +U+62C8 # 57-32, CJK UNIFIED IDEOGRAPH-62C8 +U+62C9 # 57-39, CJK UNIFIED IDEOGRAPH-62C9 +U+62CA # 57-35, CJK UNIFIED IDEOGRAPH-62CA +U+62CC # 57-34, CJK UNIFIED IDEOGRAPH-62CC +U+62CD # 39-79, CJK UNIFIED IDEOGRAPH-62CD +U+62CF # 57-28, CJK UNIFIED IDEOGRAPH-62CF +U+62D0 # 18-93, CJK UNIFIED IDEOGRAPH-62D0 +U+62D1 # 57-26, CJK UNIFIED IDEOGRAPH-62D1 +U+62D2 # 21-81, CJK UNIFIED IDEOGRAPH-62D2 +U+62D3 # 34-83, CJK UNIFIED IDEOGRAPH-62D3 +U+62D4 # 57-22, CJK UNIFIED IDEOGRAPH-62D4 +U+62D7 # 57-25, CJK UNIFIED IDEOGRAPH-62D7 +U+62D8 # 25-20, CJK UNIFIED IDEOGRAPH-62D8 +U+62D9 # 32-59, CJK UNIFIED IDEOGRAPH-62D9 +U+62DB # 30-23, CJK UNIFIED IDEOGRAPH-62DB +U+62DC # 57-33, CJK UNIFIED IDEOGRAPH-62DC +U+62DD # 39-50, CJK UNIFIED IDEOGRAPH-62DD +U+62E0 # 21-82, CJK UNIFIED IDEOGRAPH-62E0 +U+62E1 # 19-40, CJK UNIFIED IDEOGRAPH-62E1 +U+62EC # 19-71, CJK UNIFIED IDEOGRAPH-62EC +U+62ED # 31-01, CJK UNIFIED IDEOGRAPH-62ED +U+62EE # 57-41, CJK UNIFIED IDEOGRAPH-62EE +U+62EF # 57-46, CJK UNIFIED IDEOGRAPH-62EF +U+62F1 # 57-42, CJK UNIFIED IDEOGRAPH-62F1 +U+62F3 # 23-93, CJK UNIFIED IDEOGRAPH-62F3 +U+62F5 # 57-47, CJK UNIFIED IDEOGRAPH-62F5 +U+62F6 # 27-02, CJK UNIFIED IDEOGRAPH-62F6 +U+62F7 # 25-73, CJK UNIFIED IDEOGRAPH-62F7 +U+62FE # 29-06, CJK UNIFIED IDEOGRAPH-62FE +U+62FF # 57-29, CJK UNIFIED IDEOGRAPH-62FF +U+6301 # 27-93, CJK UNIFIED IDEOGRAPH-6301 +U+6302 # 57-44, CJK UNIFIED IDEOGRAPH-6302 +U+6307 # 27-56, CJK UNIFIED IDEOGRAPH-6307 +U+6308 # 57-45, CJK UNIFIED IDEOGRAPH-6308 +U+6309 # 16-36, CJK UNIFIED IDEOGRAPH-6309 +U+630C # 57-40, CJK UNIFIED IDEOGRAPH-630C +U+6311 # 36-09, CJK UNIFIED IDEOGRAPH-6311 +U+6319 # 21-83, CJK UNIFIED IDEOGRAPH-6319 +U+631F # 22-20, CJK UNIFIED IDEOGRAPH-631F +U+6327 # 57-43, CJK UNIFIED IDEOGRAPH-6327 +U+6328 # 16-07, CJK UNIFIED IDEOGRAPH-6328 +U+632B # 26-35, CJK UNIFIED IDEOGRAPH-632B +U+632F # 31-22, CJK UNIFIED IDEOGRAPH-632F +U+633A # 36-82, CJK UNIFIED IDEOGRAPH-633A +U+633D # 40-52, CJK UNIFIED IDEOGRAPH-633D +U+633E # 57-49, CJK UNIFIED IDEOGRAPH-633E +U+633F # 33-62, CJK UNIFIED IDEOGRAPH-633F +U+6349 # 34-10, CJK UNIFIED IDEOGRAPH-6349 +U+634C # 27-11, CJK UNIFIED IDEOGRAPH-634C +U+634D # 57-50, CJK UNIFIED IDEOGRAPH-634D +U+634F # 57-52, CJK UNIFIED IDEOGRAPH-634F +U+6350 # 57-48, CJK UNIFIED IDEOGRAPH-6350 +U+6355 # 42-65, CJK UNIFIED IDEOGRAPH-6355 +U+6357 # 36-29, CJK UNIFIED IDEOGRAPH-6357 +U+635C # 33-60, CJK UNIFIED IDEOGRAPH-635C +U+6367 # 42-91, CJK UNIFIED IDEOGRAPH-6367 +U+6368 # 28-46, CJK UNIFIED IDEOGRAPH-6368 +U+6369 # 57-64, CJK UNIFIED IDEOGRAPH-6369 +U+636B # 57-63, CJK UNIFIED IDEOGRAPH-636B +U+636E # 31-88, CJK UNIFIED IDEOGRAPH-636E +U+6372 # 23-94, CJK UNIFIED IDEOGRAPH-6372 +U+6376 # 57-57, CJK UNIFIED IDEOGRAPH-6376 +U+6377 # 30-25, CJK UNIFIED IDEOGRAPH-6377 +U+637A # 38-72, CJK UNIFIED IDEOGRAPH-637A +U+637B # 39-17, CJK UNIFIED IDEOGRAPH-637B +U+6380 # 57-55, CJK UNIFIED IDEOGRAPH-6380 +U+6383 # 33-61, CJK UNIFIED IDEOGRAPH-6383 +U+6388 # 28-88, CJK UNIFIED IDEOGRAPH-6388 +U+6389 # 57-60, CJK UNIFIED IDEOGRAPH-6389 +U+638C # 30-24, CJK UNIFIED IDEOGRAPH-638C +U+638E # 57-54, CJK UNIFIED IDEOGRAPH-638E +U+638F # 57-59, CJK UNIFIED IDEOGRAPH-638F +U+6392 # 39-51, CJK UNIFIED IDEOGRAPH-6392 +U+6396 # 57-53, CJK UNIFIED IDEOGRAPH-6396 +U+6398 # 23-01, CJK UNIFIED IDEOGRAPH-6398 +U+639B # 19-61, CJK UNIFIED IDEOGRAPH-639B +U+639F # 57-61, CJK UNIFIED IDEOGRAPH-639F +U+63A0 # 46-11, CJK UNIFIED IDEOGRAPH-63A0 +U+63A1 # 26-46, CJK UNIFIED IDEOGRAPH-63A1 +U+63A2 # 35-21, CJK UNIFIED IDEOGRAPH-63A2 +U+63A3 # 57-58, CJK UNIFIED IDEOGRAPH-63A3 +U+63A5 # 32-60, CJK UNIFIED IDEOGRAPH-63A5 +U+63A7 # 25-21, CJK UNIFIED IDEOGRAPH-63A7 +U+63A8 # 31-68, CJK UNIFIED IDEOGRAPH-63A8 +U+63A9 # 17-70, CJK UNIFIED IDEOGRAPH-63A9 +U+63AA # 33-28, CJK UNIFIED IDEOGRAPH-63AA +U+63AB # 57-56, CJK UNIFIED IDEOGRAPH-63AB +U+63AC # 21-37, CJK UNIFIED IDEOGRAPH-63AC +U+63B2 # 23-39, CJK UNIFIED IDEOGRAPH-63B2 +U+63B4 # 36-47, CJK UNIFIED IDEOGRAPH-63B4 +U+63B5 # 57-62, CJK UNIFIED IDEOGRAPH-63B5 +U+63BB # 33-63, CJK UNIFIED IDEOGRAPH-63BB +U+63BE # 57-65, CJK UNIFIED IDEOGRAPH-63BE +U+63C0 # 57-67, CJK UNIFIED IDEOGRAPH-63C0 +U+63C3 # 34-23, CJK UNIFIED IDEOGRAPH-63C3 +U+63C4 # 57-73, CJK UNIFIED IDEOGRAPH-63C4 +U+63C6 # 57-68, CJK UNIFIED IDEOGRAPH-63C6 +U+63C9 # 57-70, CJK UNIFIED IDEOGRAPH-63C9 +U+63CF # 41-33, CJK UNIFIED IDEOGRAPH-63CF +U+63D0 # 36-83, CJK UNIFIED IDEOGRAPH-63D0 +U+63D2 # 57-71, CJK UNIFIED IDEOGRAPH-63D2 +U+63D6 # 45-12, CJK UNIFIED IDEOGRAPH-63D6 +U+63DA # 45-40, CJK UNIFIED IDEOGRAPH-63DA +U+63DB # 20-25, CJK UNIFIED IDEOGRAPH-63DB +U+63E1 # 16-14, CJK UNIFIED IDEOGRAPH-63E1 +U+63E3 # 57-69, CJK UNIFIED IDEOGRAPH-63E3 +U+63E9 # 57-66, CJK UNIFIED IDEOGRAPH-63E9 +U+63EE # 20-88, CJK UNIFIED IDEOGRAPH-63EE +U+63F4 # 17-71, CJK UNIFIED IDEOGRAPH-63F4 +U+63F6 # 57-72, CJK UNIFIED IDEOGRAPH-63F6 +U+63FA # 45-41, CJK UNIFIED IDEOGRAPH-63FA +U+6406 # 57-76, CJK UNIFIED IDEOGRAPH-6406 +U+640D # 34-27, CJK UNIFIED IDEOGRAPH-640D +U+640F # 57-83, CJK UNIFIED IDEOGRAPH-640F +U+6413 # 57-77, CJK UNIFIED IDEOGRAPH-6413 +U+6416 # 57-74, CJK UNIFIED IDEOGRAPH-6416 +U+6417 # 57-81, CJK UNIFIED IDEOGRAPH-6417 +U+641C # 57-51, CJK UNIFIED IDEOGRAPH-641C +U+6426 # 57-78, CJK UNIFIED IDEOGRAPH-6426 +U+6428 # 57-82, CJK UNIFIED IDEOGRAPH-6428 +U+642C # 40-34, CJK UNIFIED IDEOGRAPH-642C +U+642D # 37-75, CJK UNIFIED IDEOGRAPH-642D +U+6434 # 57-75, CJK UNIFIED IDEOGRAPH-6434 +U+6436 # 57-79, CJK UNIFIED IDEOGRAPH-6436 +U+643A # 23-40, CJK UNIFIED IDEOGRAPH-643A +U+643E # 26-81, CJK UNIFIED IDEOGRAPH-643E +U+6442 # 32-61, CJK UNIFIED IDEOGRAPH-6442 +U+644E # 57-87, CJK UNIFIED IDEOGRAPH-644E +U+6458 # 37-06, CJK UNIFIED IDEOGRAPH-6458 +U+6467 # 57-84, CJK UNIFIED IDEOGRAPH-6467 +U+6469 # 43-64, CJK UNIFIED IDEOGRAPH-6469 +U+646F # 57-85, CJK UNIFIED IDEOGRAPH-646F +U+6476 # 57-86, CJK UNIFIED IDEOGRAPH-6476 +U+6478 # 44-46, CJK UNIFIED IDEOGRAPH-6478 +U+647A # 32-02, CJK UNIFIED IDEOGRAPH-647A +U+6483 # 23-66, CJK UNIFIED IDEOGRAPH-6483 +U+6488 # 57-93, CJK UNIFIED IDEOGRAPH-6488 +U+6492 # 27-21, CJK UNIFIED IDEOGRAPH-6492 +U+6493 # 57-90, CJK UNIFIED IDEOGRAPH-6493 +U+6495 # 57-89, CJK UNIFIED IDEOGRAPH-6495 +U+649A # 39-18, CJK UNIFIED IDEOGRAPH-649A +U+649E # 38-21, CJK UNIFIED IDEOGRAPH-649E +U+64A4 # 37-17, CJK UNIFIED IDEOGRAPH-64A4 +U+64A5 # 57-91, CJK UNIFIED IDEOGRAPH-64A5 +U+64A9 # 57-92, CJK UNIFIED IDEOGRAPH-64A9 +U+64AB # 41-79, CJK UNIFIED IDEOGRAPH-64AB +U+64AD # 39-37, CJK UNIFIED IDEOGRAPH-64AD +U+64AE # 27-03, CJK UNIFIED IDEOGRAPH-64AE +U+64B0 # 32-81, CJK UNIFIED IDEOGRAPH-64B0 +U+64B2 # 43-48, CJK UNIFIED IDEOGRAPH-64B2 +U+64B9 # 19-41, CJK UNIFIED IDEOGRAPH-64B9 +U+64BB # 58-05, CJK UNIFIED IDEOGRAPH-64BB +U+64BC # 57-94, CJK UNIFIED IDEOGRAPH-64BC +U+64C1 # 45-42, CJK UNIFIED IDEOGRAPH-64C1 +U+64C2 # 58-07, CJK UNIFIED IDEOGRAPH-64C2 +U+64C5 # 58-03, CJK UNIFIED IDEOGRAPH-64C5 +U+64C7 # 58-04, CJK UNIFIED IDEOGRAPH-64C7 +U+64CD # 33-64, CJK UNIFIED IDEOGRAPH-64CD +U+64D2 # 58-02, CJK UNIFIED IDEOGRAPH-64D2 +U+64D4 # 57-31, CJK UNIFIED IDEOGRAPH-64D4 +U+64D8 # 58-06, CJK UNIFIED IDEOGRAPH-64D8 +U+64DA # 58-01, CJK UNIFIED IDEOGRAPH-64DA +U+64E0 # 58-11, CJK UNIFIED IDEOGRAPH-64E0 +U+64E1 # 58-12, CJK UNIFIED IDEOGRAPH-64E1 +U+64E2 # 37-07, CJK UNIFIED IDEOGRAPH-64E2 +U+64E3 # 58-14, CJK UNIFIED IDEOGRAPH-64E3 +U+64E6 # 27-04, CJK UNIFIED IDEOGRAPH-64E6 +U+64E7 # 58-09, CJK UNIFIED IDEOGRAPH-64E7 +U+64EC # 21-28, CJK UNIFIED IDEOGRAPH-64EC +U+64EF # 58-15, CJK UNIFIED IDEOGRAPH-64EF +U+64F1 # 58-08, CJK UNIFIED IDEOGRAPH-64F1 +U+64F2 # 58-19, CJK UNIFIED IDEOGRAPH-64F2 +U+64F4 # 58-18, CJK UNIFIED IDEOGRAPH-64F4 +U+64F6 # 58-17, CJK UNIFIED IDEOGRAPH-64F6 +U+64FA # 58-20, CJK UNIFIED IDEOGRAPH-64FA +U+64FD # 58-22, CJK UNIFIED IDEOGRAPH-64FD +U+64FE # 30-81, CJK UNIFIED IDEOGRAPH-64FE +U+6500 # 58-21, CJK UNIFIED IDEOGRAPH-6500 +U+6505 # 58-25, CJK UNIFIED IDEOGRAPH-6505 +U+6518 # 58-23, CJK UNIFIED IDEOGRAPH-6518 +U+651C # 58-24, CJK UNIFIED IDEOGRAPH-651C +U+651D # 57-80, CJK UNIFIED IDEOGRAPH-651D +U+6523 # 58-27, CJK UNIFIED IDEOGRAPH-6523 +U+6524 # 58-26, CJK UNIFIED IDEOGRAPH-6524 +U+652A # 57-88, CJK UNIFIED IDEOGRAPH-652A +U+652B # 58-28, CJK UNIFIED IDEOGRAPH-652B +U+652C # 58-16, CJK UNIFIED IDEOGRAPH-652C +U+652F # 27-57, CJK UNIFIED IDEOGRAPH-652F +U+6534 # 58-29, CJK UNIFIED IDEOGRAPH-6534 +U+6535 # 58-30, CJK UNIFIED IDEOGRAPH-6535 +U+6536 # 58-32, CJK UNIFIED IDEOGRAPH-6536 +U+6537 # 58-31, CJK UNIFIED IDEOGRAPH-6537 +U+6538 # 58-33, CJK UNIFIED IDEOGRAPH-6538 +U+6539 # 18-94, CJK UNIFIED IDEOGRAPH-6539 +U+653B # 25-22, CJK UNIFIED IDEOGRAPH-653B +U+653E # 42-92, CJK UNIFIED IDEOGRAPH-653E +U+653F # 32-15, CJK UNIFIED IDEOGRAPH-653F +U+6545 # 24-46, CJK UNIFIED IDEOGRAPH-6545 +U+6548 # 58-35, CJK UNIFIED IDEOGRAPH-6548 +U+654D # 58-38, CJK UNIFIED IDEOGRAPH-654D +U+654F # 41-50, CJK UNIFIED IDEOGRAPH-654F +U+6551 # 21-63, CJK UNIFIED IDEOGRAPH-6551 +U+6555 # 58-37, CJK UNIFIED IDEOGRAPH-6555 +U+6556 # 58-36, CJK UNIFIED IDEOGRAPH-6556 +U+6557 # 39-52, CJK UNIFIED IDEOGRAPH-6557 +U+6558 # 58-39, CJK UNIFIED IDEOGRAPH-6558 +U+6559 # 22-21, CJK UNIFIED IDEOGRAPH-6559 +U+655D # 58-41, CJK UNIFIED IDEOGRAPH-655D +U+655E # 58-40, CJK UNIFIED IDEOGRAPH-655E +U+6562 # 20-26, CJK UNIFIED IDEOGRAPH-6562 +U+6563 # 27-22, CJK UNIFIED IDEOGRAPH-6563 +U+6566 # 38-56, CJK UNIFIED IDEOGRAPH-6566 +U+656C # 23-41, CJK UNIFIED IDEOGRAPH-656C +U+6570 # 31-84, CJK UNIFIED IDEOGRAPH-6570 +U+6572 # 58-42, CJK UNIFIED IDEOGRAPH-6572 +U+6574 # 32-16, CJK UNIFIED IDEOGRAPH-6574 +U+6575 # 37-08, CJK UNIFIED IDEOGRAPH-6575 +U+6577 # 41-63, CJK UNIFIED IDEOGRAPH-6577 +U+6578 # 58-43, CJK UNIFIED IDEOGRAPH-6578 +U+6582 # 58-44, CJK UNIFIED IDEOGRAPH-6582 +U+6583 # 58-45, CJK UNIFIED IDEOGRAPH-6583 +U+6587 # 42-24, CJK UNIFIED IDEOGRAPH-6587 +U+6588 # 53-61, CJK UNIFIED IDEOGRAPH-6588 +U+6589 # 32-38, CJK UNIFIED IDEOGRAPH-6589 +U+658C # 41-44, CJK UNIFIED IDEOGRAPH-658C +U+658E # 26-56, CJK UNIFIED IDEOGRAPH-658E +U+6590 # 40-69, CJK UNIFIED IDEOGRAPH-6590 +U+6591 # 40-35, CJK UNIFIED IDEOGRAPH-6591 +U+6597 # 37-45, CJK UNIFIED IDEOGRAPH-6597 +U+6599 # 46-33, CJK UNIFIED IDEOGRAPH-6599 +U+659B # 58-47, CJK UNIFIED IDEOGRAPH-659B +U+659C # 28-48, CJK UNIFIED IDEOGRAPH-659C +U+659F # 58-48, CJK UNIFIED IDEOGRAPH-659F +U+65A1 # 16-22, CJK UNIFIED IDEOGRAPH-65A1 +U+65A4 # 22-52, CJK UNIFIED IDEOGRAPH-65A4 +U+65A5 # 32-45, CJK UNIFIED IDEOGRAPH-65A5 +U+65A7 # 41-64, CJK UNIFIED IDEOGRAPH-65A7 +U+65AB # 58-49, CJK UNIFIED IDEOGRAPH-65AB +U+65AC # 27-34, CJK UNIFIED IDEOGRAPH-65AC +U+65AD # 35-39, CJK UNIFIED IDEOGRAPH-65AD +U+65AF # 27-59, CJK UNIFIED IDEOGRAPH-65AF +U+65B0 # 31-23, CJK UNIFIED IDEOGRAPH-65B0 +U+65B7 # 58-50, CJK UNIFIED IDEOGRAPH-65B7 +U+65B9 # 42-93, CJK UNIFIED IDEOGRAPH-65B9 +U+65BC # 17-87, CJK UNIFIED IDEOGRAPH-65BC +U+65BD # 27-60, CJK UNIFIED IDEOGRAPH-65BD +U+65C1 # 58-53, CJK UNIFIED IDEOGRAPH-65C1 +U+65C3 # 58-51, CJK UNIFIED IDEOGRAPH-65C3 +U+65C4 # 58-54, CJK UNIFIED IDEOGRAPH-65C4 +U+65C5 # 46-25, CJK UNIFIED IDEOGRAPH-65C5 +U+65C6 # 58-52, CJK UNIFIED IDEOGRAPH-65C6 +U+65CB # 32-91, CJK UNIFIED IDEOGRAPH-65CB +U+65CC # 58-55, CJK UNIFIED IDEOGRAPH-65CC +U+65CF # 34-18, CJK UNIFIED IDEOGRAPH-65CF +U+65D2 # 58-56, CJK UNIFIED IDEOGRAPH-65D2 +U+65D7 # 20-90, CJK UNIFIED IDEOGRAPH-65D7 +U+65D9 # 58-58, CJK UNIFIED IDEOGRAPH-65D9 +U+65DB # 58-57, CJK UNIFIED IDEOGRAPH-65DB +U+65E0 # 58-59, CJK UNIFIED IDEOGRAPH-65E0 +U+65E1 # 58-60, CJK UNIFIED IDEOGRAPH-65E1 +U+65E2 # 20-91, CJK UNIFIED IDEOGRAPH-65E2 +U+65E5 # 38-92, CJK UNIFIED IDEOGRAPH-65E5 +U+65E6 # 35-22, CJK UNIFIED IDEOGRAPH-65E6 +U+65E7 # 21-76, CJK UNIFIED IDEOGRAPH-65E7 +U+65E8 # 27-61, CJK UNIFIED IDEOGRAPH-65E8 +U+65E9 # 33-65, CJK UNIFIED IDEOGRAPH-65E9 +U+65EC # 29-60, CJK UNIFIED IDEOGRAPH-65EC +U+65ED # 16-16, CJK UNIFIED IDEOGRAPH-65ED +U+65F1 # 58-61, CJK UNIFIED IDEOGRAPH-65F1 +U+65FA # 18-02, CJK UNIFIED IDEOGRAPH-65FA +U+65FB # 58-65, CJK UNIFIED IDEOGRAPH-65FB +U+6602 # 25-23, CJK UNIFIED IDEOGRAPH-6602 +U+6603 # 58-64, CJK UNIFIED IDEOGRAPH-6603 +U+6606 # 26-11, CJK UNIFIED IDEOGRAPH-6606 +U+6607 # 30-26, CJK UNIFIED IDEOGRAPH-6607 +U+660A # 58-63, CJK UNIFIED IDEOGRAPH-660A +U+660C # 30-27, CJK UNIFIED IDEOGRAPH-660C +U+660E # 44-32, CJK UNIFIED IDEOGRAPH-660E +U+660F # 26-10, CJK UNIFIED IDEOGRAPH-660F +U+6613 # 16-55, CJK UNIFIED IDEOGRAPH-6613 +U+6614 # 32-46, CJK UNIFIED IDEOGRAPH-6614 +U+661C # 58-70, CJK UNIFIED IDEOGRAPH-661C +U+661F # 32-17, CJK UNIFIED IDEOGRAPH-661F +U+6620 # 17-39, CJK UNIFIED IDEOGRAPH-6620 +U+6625 # 29-53, CJK UNIFIED IDEOGRAPH-6625 +U+6627 # 43-70, CJK UNIFIED IDEOGRAPH-6627 +U+6628 # 26-82, CJK UNIFIED IDEOGRAPH-6628 +U+662D # 30-28, CJK UNIFIED IDEOGRAPH-662D +U+662F # 32-07, CJK UNIFIED IDEOGRAPH-662F +U+6634 # 58-69, CJK UNIFIED IDEOGRAPH-6634 +U+6635 # 58-67, CJK UNIFIED IDEOGRAPH-6635 +U+6636 # 58-68, CJK UNIFIED IDEOGRAPH-6636 +U+663C # 35-75, CJK UNIFIED IDEOGRAPH-663C +U+663F # 59-06, CJK UNIFIED IDEOGRAPH-663F +U+6641 # 58-74, CJK UNIFIED IDEOGRAPH-6641 +U+6642 # 27-94, CJK UNIFIED IDEOGRAPH-6642 +U+6643 # 25-24, CJK UNIFIED IDEOGRAPH-6643 +U+6644 # 58-72, CJK UNIFIED IDEOGRAPH-6644 +U+6649 # 58-73, CJK UNIFIED IDEOGRAPH-6649 +U+664B # 31-24, CJK UNIFIED IDEOGRAPH-664B +U+664F # 58-71, CJK UNIFIED IDEOGRAPH-664F +U+6652 # 27-15, CJK UNIFIED IDEOGRAPH-6652 +U+665D # 58-76, CJK UNIFIED IDEOGRAPH-665D +U+665E # 58-75, CJK UNIFIED IDEOGRAPH-665E +U+665F # 58-80, CJK UNIFIED IDEOGRAPH-665F +U+6662 # 58-81, CJK UNIFIED IDEOGRAPH-6662 +U+6664 # 58-77, CJK UNIFIED IDEOGRAPH-6664 +U+6666 # 19-02, CJK UNIFIED IDEOGRAPH-6666 +U+6667 # 58-78, CJK UNIFIED IDEOGRAPH-6667 +U+6668 # 58-79, CJK UNIFIED IDEOGRAPH-6668 +U+6669 # 40-53, CJK UNIFIED IDEOGRAPH-6669 +U+666E # 41-65, CJK UNIFIED IDEOGRAPH-666E +U+666F # 23-42, CJK UNIFIED IDEOGRAPH-666F +U+6670 # 58-82, CJK UNIFIED IDEOGRAPH-6670 +U+6674 # 32-18, CJK UNIFIED IDEOGRAPH-6674 +U+6676 # 30-29, CJK UNIFIED IDEOGRAPH-6676 +U+667A # 35-50, CJK UNIFIED IDEOGRAPH-667A +U+6681 # 22-39, CJK UNIFIED IDEOGRAPH-6681 +U+6683 # 58-83, CJK UNIFIED IDEOGRAPH-6683 +U+6684 # 58-87, CJK UNIFIED IDEOGRAPH-6684 +U+6687 # 18-43, CJK UNIFIED IDEOGRAPH-6687 +U+6688 # 58-84, CJK UNIFIED IDEOGRAPH-6688 +U+6689 # 58-86, CJK UNIFIED IDEOGRAPH-6689 +U+668E # 58-85, CJK UNIFIED IDEOGRAPH-668E +U+6691 # 29-75, CJK UNIFIED IDEOGRAPH-6691 +U+6696 # 35-40, CJK UNIFIED IDEOGRAPH-6696 +U+6697 # 16-37, CJK UNIFIED IDEOGRAPH-6697 +U+6698 # 58-88, CJK UNIFIED IDEOGRAPH-6698 +U+669D # 58-89, CJK UNIFIED IDEOGRAPH-669D +U+66A2 # 36-10, CJK UNIFIED IDEOGRAPH-66A2 +U+66A6 # 46-81, CJK UNIFIED IDEOGRAPH-66A6 +U+66AB # 27-35, CJK UNIFIED IDEOGRAPH-66AB +U+66AE # 42-75, CJK UNIFIED IDEOGRAPH-66AE +U+66B4 # 43-29, CJK UNIFIED IDEOGRAPH-66B4 +U+66B8 # 59-02, CJK UNIFIED IDEOGRAPH-66B8 +U+66B9 # 58-91, CJK UNIFIED IDEOGRAPH-66B9 +U+66BC # 58-94, CJK UNIFIED IDEOGRAPH-66BC +U+66BE # 58-93, CJK UNIFIED IDEOGRAPH-66BE +U+66C1 # 58-90, CJK UNIFIED IDEOGRAPH-66C1 +U+66C4 # 59-01, CJK UNIFIED IDEOGRAPH-66C4 +U+66C7 # 38-62, CJK UNIFIED IDEOGRAPH-66C7 +U+66C9 # 58-92, CJK UNIFIED IDEOGRAPH-66C9 +U+66D6 # 59-03, CJK UNIFIED IDEOGRAPH-66D6 +U+66D9 # 29-76, CJK UNIFIED IDEOGRAPH-66D9 +U+66DA # 59-04, CJK UNIFIED IDEOGRAPH-66DA +U+66DC # 45-43, CJK UNIFIED IDEOGRAPH-66DC +U+66DD # 39-88, CJK UNIFIED IDEOGRAPH-66DD +U+66E0 # 59-05, CJK UNIFIED IDEOGRAPH-66E0 +U+66E6 # 59-07, CJK UNIFIED IDEOGRAPH-66E6 +U+66E9 # 59-08, CJK UNIFIED IDEOGRAPH-66E9 +U+66F0 # 59-09, CJK UNIFIED IDEOGRAPH-66F0 +U+66F2 # 22-42, CJK UNIFIED IDEOGRAPH-66F2 +U+66F3 # 17-40, CJK UNIFIED IDEOGRAPH-66F3 +U+66F4 # 25-25, CJK UNIFIED IDEOGRAPH-66F4 +U+66F5 # 59-10, CJK UNIFIED IDEOGRAPH-66F5 +U+66F7 # 59-11, CJK UNIFIED IDEOGRAPH-66F7 +U+66F8 # 29-81, CJK UNIFIED IDEOGRAPH-66F8 +U+66F9 # 33-66, CJK UNIFIED IDEOGRAPH-66F9 +U+66FC # 50-56, CJK UNIFIED IDEOGRAPH-66FC +U+66FD # 33-30, CJK UNIFIED IDEOGRAPH-66FD +U+66FE # 33-29, CJK UNIFIED IDEOGRAPH-66FE +U+66FF # 34-56, CJK UNIFIED IDEOGRAPH-66FF +U+6700 # 26-39, CJK UNIFIED IDEOGRAPH-6700 +U+6703 # 48-82, CJK UNIFIED IDEOGRAPH-6703 +U+6708 # 23-78, CJK UNIFIED IDEOGRAPH-6708 +U+6709 # 45-13, CJK UNIFIED IDEOGRAPH-6709 +U+670B # 42-94, CJK UNIFIED IDEOGRAPH-670B +U+670D # 41-94, CJK UNIFIED IDEOGRAPH-670D +U+670F # 59-12, CJK UNIFIED IDEOGRAPH-670F +U+6714 # 26-83, CJK UNIFIED IDEOGRAPH-6714 +U+6715 # 36-31, CJK UNIFIED IDEOGRAPH-6715 +U+6716 # 59-13, CJK UNIFIED IDEOGRAPH-6716 +U+6717 # 47-15, CJK UNIFIED IDEOGRAPH-6717 +U+671B # 43-30, CJK UNIFIED IDEOGRAPH-671B +U+671D # 36-11, CJK UNIFIED IDEOGRAPH-671D +U+671E # 59-14, CJK UNIFIED IDEOGRAPH-671E +U+671F # 20-92, CJK UNIFIED IDEOGRAPH-671F +U+6726 # 59-15, CJK UNIFIED IDEOGRAPH-6726 +U+6727 # 59-16, CJK UNIFIED IDEOGRAPH-6727 +U+6728 # 44-58, CJK UNIFIED IDEOGRAPH-6728 +U+672A # 44-04, CJK UNIFIED IDEOGRAPH-672A +U+672B # 43-86, CJK UNIFIED IDEOGRAPH-672B +U+672C # 43-60, CJK UNIFIED IDEOGRAPH-672C +U+672D # 27-05, CJK UNIFIED IDEOGRAPH-672D +U+672E # 59-18, CJK UNIFIED IDEOGRAPH-672E +U+6731 # 28-75, CJK UNIFIED IDEOGRAPH-6731 +U+6734 # 43-49, CJK UNIFIED IDEOGRAPH-6734 +U+6736 # 59-20, CJK UNIFIED IDEOGRAPH-6736 +U+6737 # 59-23, CJK UNIFIED IDEOGRAPH-6737 +U+6738 # 59-22, CJK UNIFIED IDEOGRAPH-6738 +U+673A # 20-89, CJK UNIFIED IDEOGRAPH-673A +U+673D # 21-64, CJK UNIFIED IDEOGRAPH-673D +U+673F # 59-19, CJK UNIFIED IDEOGRAPH-673F +U+6741 # 59-21, CJK UNIFIED IDEOGRAPH-6741 +U+6746 # 59-24, CJK UNIFIED IDEOGRAPH-6746 +U+6749 # 31-89, CJK UNIFIED IDEOGRAPH-6749 +U+674E # 45-91, CJK UNIFIED IDEOGRAPH-674E +U+674F # 16-41, CJK UNIFIED IDEOGRAPH-674F +U+6750 # 26-64, CJK UNIFIED IDEOGRAPH-6750 +U+6751 # 34-28, CJK UNIFIED IDEOGRAPH-6751 +U+6753 # 28-61, CJK UNIFIED IDEOGRAPH-6753 +U+6756 # 30-83, CJK UNIFIED IDEOGRAPH-6756 +U+6759 # 59-27, CJK UNIFIED IDEOGRAPH-6759 +U+675C # 37-46, CJK UNIFIED IDEOGRAPH-675C +U+675E # 59-25, CJK UNIFIED IDEOGRAPH-675E +U+675F # 34-11, CJK UNIFIED IDEOGRAPH-675F +U+6760 # 59-26, CJK UNIFIED IDEOGRAPH-6760 +U+6761 # 30-82, CJK UNIFIED IDEOGRAPH-6761 +U+6762 # 44-61, CJK UNIFIED IDEOGRAPH-6762 +U+6763 # 59-28, CJK UNIFIED IDEOGRAPH-6763 +U+6764 # 59-29, CJK UNIFIED IDEOGRAPH-6764 +U+6765 # 45-72, CJK UNIFIED IDEOGRAPH-6765 +U+676A # 59-34, CJK UNIFIED IDEOGRAPH-676A +U+676D # 25-26, CJK UNIFIED IDEOGRAPH-676D +U+676F # 39-53, CJK UNIFIED IDEOGRAPH-676F +U+6770 # 59-31, CJK UNIFIED IDEOGRAPH-6770 +U+6771 # 37-76, CJK UNIFIED IDEOGRAPH-6771 +U+6772 # 58-62, CJK UNIFIED IDEOGRAPH-6772 +U+6773 # 58-66, CJK UNIFIED IDEOGRAPH-6773 +U+6775 # 21-47, CJK UNIFIED IDEOGRAPH-6775 +U+6777 # 39-39, CJK UNIFIED IDEOGRAPH-6777 +U+677C # 59-33, CJK UNIFIED IDEOGRAPH-677C +U+677E # 30-30, CJK UNIFIED IDEOGRAPH-677E +U+677F # 40-36, CJK UNIFIED IDEOGRAPH-677F +U+6785 # 59-39, CJK UNIFIED IDEOGRAPH-6785 +U+6787 # 40-90, CJK UNIFIED IDEOGRAPH-6787 +U+6789 # 59-30, CJK UNIFIED IDEOGRAPH-6789 +U+678B # 59-36, CJK UNIFIED IDEOGRAPH-678B +U+678C # 59-35, CJK UNIFIED IDEOGRAPH-678C +U+6790 # 32-47, CJK UNIFIED IDEOGRAPH-6790 +U+6795 # 43-77, CJK UNIFIED IDEOGRAPH-6795 +U+6797 # 46-51, CJK UNIFIED IDEOGRAPH-6797 +U+679A # 43-71, CJK UNIFIED IDEOGRAPH-679A +U+679C # 18-44, CJK UNIFIED IDEOGRAPH-679C +U+679D # 27-62, CJK UNIFIED IDEOGRAPH-679D +U+67A0 # 47-40, CJK UNIFIED IDEOGRAPH-67A0 +U+67A1 # 59-38, CJK UNIFIED IDEOGRAPH-67A1 +U+67A2 # 31-85, CJK UNIFIED IDEOGRAPH-67A2 +U+67A6 # 59-37, CJK UNIFIED IDEOGRAPH-67A6 +U+67A9 # 59-32, CJK UNIFIED IDEOGRAPH-67A9 +U+67AF # 24-47, CJK UNIFIED IDEOGRAPH-67AF +U+67B3 # 59-44, CJK UNIFIED IDEOGRAPH-67B3 +U+67B4 # 59-42, CJK UNIFIED IDEOGRAPH-67B4 +U+67B6 # 18-45, CJK UNIFIED IDEOGRAPH-67B6 +U+67B7 # 59-40, CJK UNIFIED IDEOGRAPH-67B7 +U+67B8 # 59-46, CJK UNIFIED IDEOGRAPH-67B8 +U+67B9 # 59-52, CJK UNIFIED IDEOGRAPH-67B9 +U+67C1 # 34-40, CJK UNIFIED IDEOGRAPH-67C1 +U+67C4 # 42-33, CJK UNIFIED IDEOGRAPH-67C4 +U+67C6 # 59-54, CJK UNIFIED IDEOGRAPH-67C6 +U+67CA # 41-02, CJK UNIFIED IDEOGRAPH-67CA +U+67CE # 59-53, CJK UNIFIED IDEOGRAPH-67CE +U+67CF # 39-80, CJK UNIFIED IDEOGRAPH-67CF +U+67D0 # 43-31, CJK UNIFIED IDEOGRAPH-67D0 +U+67D1 # 20-27, CJK UNIFIED IDEOGRAPH-67D1 +U+67D3 # 32-87, CJK UNIFIED IDEOGRAPH-67D3 +U+67D4 # 29-32, CJK UNIFIED IDEOGRAPH-67D4 +U+67D8 # 36-51, CJK UNIFIED IDEOGRAPH-67D8 +U+67DA # 45-14, CJK UNIFIED IDEOGRAPH-67DA +U+67DD # 59-49, CJK UNIFIED IDEOGRAPH-67DD +U+67DE # 59-48, CJK UNIFIED IDEOGRAPH-67DE +U+67E2 # 59-50, CJK UNIFIED IDEOGRAPH-67E2 +U+67E4 # 59-47, CJK UNIFIED IDEOGRAPH-67E4 +U+67E7 # 59-55, CJK UNIFIED IDEOGRAPH-67E7 +U+67E9 # 59-45, CJK UNIFIED IDEOGRAPH-67E9 +U+67EC # 59-43, CJK UNIFIED IDEOGRAPH-67EC +U+67EE # 59-51, CJK UNIFIED IDEOGRAPH-67EE +U+67EF # 59-41, CJK UNIFIED IDEOGRAPH-67EF +U+67F1 # 35-76, CJK UNIFIED IDEOGRAPH-67F1 +U+67F3 # 44-88, CJK UNIFIED IDEOGRAPH-67F3 +U+67F4 # 28-38, CJK UNIFIED IDEOGRAPH-67F4 +U+67F5 # 26-84, CJK UNIFIED IDEOGRAPH-67F5 +U+67FB # 26-26, CJK UNIFIED IDEOGRAPH-67FB +U+67FE # 43-79, CJK UNIFIED IDEOGRAPH-67FE +U+67FF # 19-33, CJK UNIFIED IDEOGRAPH-67FF +U+6802 # 36-46, CJK UNIFIED IDEOGRAPH-6802 +U+6803 # 38-42, CJK UNIFIED IDEOGRAPH-6803 +U+6804 # 17-41, CJK UNIFIED IDEOGRAPH-6804 +U+6813 # 32-82, CJK UNIFIED IDEOGRAPH-6813 +U+6816 # 32-20, CJK UNIFIED IDEOGRAPH-6816 +U+6817 # 23-10, CJK UNIFIED IDEOGRAPH-6817 +U+681E # 59-57, CJK UNIFIED IDEOGRAPH-681E +U+6821 # 25-27, CJK UNIFIED IDEOGRAPH-6821 +U+6822 # 19-92, CJK UNIFIED IDEOGRAPH-6822 +U+6829 # 59-59, CJK UNIFIED IDEOGRAPH-6829 +U+682A # 19-84, CJK UNIFIED IDEOGRAPH-682A +U+682B # 59-65, CJK UNIFIED IDEOGRAPH-682B +U+6832 # 59-62, CJK UNIFIED IDEOGRAPH-6832 +U+6834 # 32-83, CJK UNIFIED IDEOGRAPH-6834 +U+6838 # 19-43, CJK UNIFIED IDEOGRAPH-6838 +U+6839 # 26-12, CJK UNIFIED IDEOGRAPH-6839 +U+683C # 19-42, CJK UNIFIED IDEOGRAPH-683C +U+683D # 26-47, CJK UNIFIED IDEOGRAPH-683D +U+6840 # 59-60, CJK UNIFIED IDEOGRAPH-6840 +U+6841 # 23-69, CJK UNIFIED IDEOGRAPH-6841 +U+6842 # 23-43, CJK UNIFIED IDEOGRAPH-6842 +U+6843 # 37-77, CJK UNIFIED IDEOGRAPH-6843 +U+6846 # 59-58, CJK UNIFIED IDEOGRAPH-6846 +U+6848 # 16-38, CJK UNIFIED IDEOGRAPH-6848 +U+684D # 59-61, CJK UNIFIED IDEOGRAPH-684D +U+684E # 59-63, CJK UNIFIED IDEOGRAPH-684E +U+6850 # 22-45, CJK UNIFIED IDEOGRAPH-6850 +U+6851 # 23-12, CJK UNIFIED IDEOGRAPH-6851 +U+6853 # 20-28, CJK UNIFIED IDEOGRAPH-6853 +U+6854 # 21-43, CJK UNIFIED IDEOGRAPH-6854 +U+6859 # 59-66, CJK UNIFIED IDEOGRAPH-6859 +U+685C # 26-89, CJK UNIFIED IDEOGRAPH-685C +U+685D # 43-81, CJK UNIFIED IDEOGRAPH-685D +U+685F # 27-23, CJK UNIFIED IDEOGRAPH-685F +U+6863 # 59-67, CJK UNIFIED IDEOGRAPH-6863 +U+6867 # 41-16, CJK UNIFIED IDEOGRAPH-6867 +U+6874 # 59-79, CJK UNIFIED IDEOGRAPH-6874 +U+6876 # 18-19, CJK UNIFIED IDEOGRAPH-6876 +U+6877 # 59-68, CJK UNIFIED IDEOGRAPH-6877 +U+687E # 59-85, CJK UNIFIED IDEOGRAPH-687E +U+687F # 59-69, CJK UNIFIED IDEOGRAPH-687F +U+6881 # 46-34, CJK UNIFIED IDEOGRAPH-6881 +U+6883 # 59-76, CJK UNIFIED IDEOGRAPH-6883 +U+6885 # 39-63, CJK UNIFIED IDEOGRAPH-6885 +U+688D # 59-84, CJK UNIFIED IDEOGRAPH-688D +U+688F # 59-71, CJK UNIFIED IDEOGRAPH-688F +U+6893 # 16-20, CJK UNIFIED IDEOGRAPH-6893 +U+6894 # 59-73, CJK UNIFIED IDEOGRAPH-6894 +U+6897 # 25-28, CJK UNIFIED IDEOGRAPH-6897 +U+689B # 59-75, CJK UNIFIED IDEOGRAPH-689B +U+689D # 59-74, CJK UNIFIED IDEOGRAPH-689D +U+689F # 59-70, CJK UNIFIED IDEOGRAPH-689F +U+68A0 # 59-81, CJK UNIFIED IDEOGRAPH-68A0 +U+68A2 # 30-31, CJK UNIFIED IDEOGRAPH-68A2 +U+68A6 # 52-77, CJK UNIFIED IDEOGRAPH-68A6 +U+68A7 # 24-72, CJK UNIFIED IDEOGRAPH-68A7 +U+68A8 # 45-92, CJK UNIFIED IDEOGRAPH-68A8 +U+68AD # 59-72, CJK UNIFIED IDEOGRAPH-68AD +U+68AF # 36-84, CJK UNIFIED IDEOGRAPH-68AF +U+68B0 # 19-03, CJK UNIFIED IDEOGRAPH-68B0 +U+68B1 # 26-13, CJK UNIFIED IDEOGRAPH-68B1 +U+68B3 # 59-64, CJK UNIFIED IDEOGRAPH-68B3 +U+68B5 # 59-80, CJK UNIFIED IDEOGRAPH-68B5 +U+68B6 # 19-65, CJK UNIFIED IDEOGRAPH-68B6 +U+68B9 # 59-78, CJK UNIFIED IDEOGRAPH-68B9 +U+68BA # 59-82, CJK UNIFIED IDEOGRAPH-68BA +U+68BC # 37-78, CJK UNIFIED IDEOGRAPH-68BC +U+68C4 # 20-94, CJK UNIFIED IDEOGRAPH-68C4 +U+68C6 # 60-18, CJK UNIFIED IDEOGRAPH-68C6 +U+68C9 # 44-41, CJK UNIFIED IDEOGRAPH-68C9 +U+68CA # 59-87, CJK UNIFIED IDEOGRAPH-68CA +U+68CB # 20-93, CJK UNIFIED IDEOGRAPH-68CB +U+68CD # 59-94, CJK UNIFIED IDEOGRAPH-68CD +U+68D2 # 43-32, CJK UNIFIED IDEOGRAPH-68D2 +U+68D4 # 60-01, CJK UNIFIED IDEOGRAPH-68D4 +U+68D5 # 60-03, CJK UNIFIED IDEOGRAPH-68D5 +U+68D7 # 60-07, CJK UNIFIED IDEOGRAPH-68D7 +U+68D8 # 59-89, CJK UNIFIED IDEOGRAPH-68D8 +U+68DA # 35-10, CJK UNIFIED IDEOGRAPH-68DA +U+68DF # 37-79, CJK UNIFIED IDEOGRAPH-68DF +U+68E0 # 60-11, CJK UNIFIED IDEOGRAPH-68E0 +U+68E1 # 59-92, CJK UNIFIED IDEOGRAPH-68E1 +U+68E3 # 60-08, CJK UNIFIED IDEOGRAPH-68E3 +U+68E7 # 60-02, CJK UNIFIED IDEOGRAPH-68E7 +U+68EE # 31-25, CJK UNIFIED IDEOGRAPH-68EE +U+68EF # 60-12, CJK UNIFIED IDEOGRAPH-68EF +U+68F2 # 32-19, CJK UNIFIED IDEOGRAPH-68F2 +U+68F9 # 60-10, CJK UNIFIED IDEOGRAPH-68F9 +U+68FA # 20-29, CJK UNIFIED IDEOGRAPH-68FA +U+6900 # 47-48, CJK UNIFIED IDEOGRAPH-6900 +U+6901 # 59-86, CJK UNIFIED IDEOGRAPH-6901 +U+6904 # 60-06, CJK UNIFIED IDEOGRAPH-6904 +U+6905 # 16-56, CJK UNIFIED IDEOGRAPH-6905 +U+6908 # 59-88, CJK UNIFIED IDEOGRAPH-6908 +U+690B # 44-26, CJK UNIFIED IDEOGRAPH-690B +U+690C # 59-93, CJK UNIFIED IDEOGRAPH-690C +U+690D # 31-02, CJK UNIFIED IDEOGRAPH-690D +U+690E # 36-39, CJK UNIFIED IDEOGRAPH-690E +U+690F # 59-83, CJK UNIFIED IDEOGRAPH-690F +U+6912 # 60-05, CJK UNIFIED IDEOGRAPH-6912 +U+6919 # 31-90, CJK UNIFIED IDEOGRAPH-6919 +U+691A # 60-15, CJK UNIFIED IDEOGRAPH-691A +U+691B # 19-81, CJK UNIFIED IDEOGRAPH-691B +U+691C # 24-01, CJK UNIFIED IDEOGRAPH-691C +U+6921 # 60-17, CJK UNIFIED IDEOGRAPH-6921 +U+6922 # 59-90, CJK UNIFIED IDEOGRAPH-6922 +U+6923 # 60-16, CJK UNIFIED IDEOGRAPH-6923 +U+6925 # 60-09, CJK UNIFIED IDEOGRAPH-6925 +U+6926 # 59-91, CJK UNIFIED IDEOGRAPH-6926 +U+6928 # 60-13, CJK UNIFIED IDEOGRAPH-6928 +U+692A # 60-14, CJK UNIFIED IDEOGRAPH-692A +U+6930 # 60-31, CJK UNIFIED IDEOGRAPH-6930 +U+6934 # 38-46, CJK UNIFIED IDEOGRAPH-6934 +U+6936 # 60-04, CJK UNIFIED IDEOGRAPH-6936 +U+6939 # 60-27, CJK UNIFIED IDEOGRAPH-6939 +U+693D # 60-29, CJK UNIFIED IDEOGRAPH-693D +U+693F # 36-56, CJK UNIFIED IDEOGRAPH-693F +U+694A # 45-44, CJK UNIFIED IDEOGRAPH-694A +U+6953 # 41-86, CJK UNIFIED IDEOGRAPH-6953 +U+6954 # 60-24, CJK UNIFIED IDEOGRAPH-6954 +U+6955 # 34-42, CJK UNIFIED IDEOGRAPH-6955 +U+6959 # 60-30, CJK UNIFIED IDEOGRAPH-6959 +U+695A # 33-31, CJK UNIFIED IDEOGRAPH-695A +U+695C # 60-21, CJK UNIFIED IDEOGRAPH-695C +U+695D # 60-34, CJK UNIFIED IDEOGRAPH-695D +U+695E # 60-33, CJK UNIFIED IDEOGRAPH-695E +U+6960 # 38-79, CJK UNIFIED IDEOGRAPH-6960 +U+6961 # 60-32, CJK UNIFIED IDEOGRAPH-6961 +U+6962 # 38-74, CJK UNIFIED IDEOGRAPH-6962 +U+696A # 60-36, CJK UNIFIED IDEOGRAPH-696A +U+696B # 60-23, CJK UNIFIED IDEOGRAPH-696B +U+696D # 22-40, CJK UNIFIED IDEOGRAPH-696D +U+696E # 60-26, CJK UNIFIED IDEOGRAPH-696E +U+696F # 29-61, CJK UNIFIED IDEOGRAPH-696F +U+6973 # 39-64, CJK UNIFIED IDEOGRAPH-6973 +U+6974 # 60-28, CJK UNIFIED IDEOGRAPH-6974 +U+6975 # 22-43, CJK UNIFIED IDEOGRAPH-6975 +U+6977 # 60-20, CJK UNIFIED IDEOGRAPH-6977 +U+6978 # 60-22, CJK UNIFIED IDEOGRAPH-6978 +U+6979 # 60-19, CJK UNIFIED IDEOGRAPH-6979 +U+697C # 47-16, CJK UNIFIED IDEOGRAPH-697C +U+697D # 19-58, CJK UNIFIED IDEOGRAPH-697D +U+697E # 60-25, CJK UNIFIED IDEOGRAPH-697E +U+6981 # 60-35, CJK UNIFIED IDEOGRAPH-6981 +U+6982 # 19-21, CJK UNIFIED IDEOGRAPH-6982 +U+698A # 26-71, CJK UNIFIED IDEOGRAPH-698A +U+698E # 17-61, CJK UNIFIED IDEOGRAPH-698E +U+6991 # 60-52, CJK UNIFIED IDEOGRAPH-6991 +U+6994 # 47-17, CJK UNIFIED IDEOGRAPH-6994 +U+6995 # 60-55, CJK UNIFIED IDEOGRAPH-6995 +U+699B # 31-26, CJK UNIFIED IDEOGRAPH-699B +U+699C # 60-54, CJK UNIFIED IDEOGRAPH-699C +U+69A0 # 60-53, CJK UNIFIED IDEOGRAPH-69A0 +U+69A7 # 60-50, CJK UNIFIED IDEOGRAPH-69A7 +U+69AE # 60-38, CJK UNIFIED IDEOGRAPH-69AE +U+69B1 # 60-67, CJK UNIFIED IDEOGRAPH-69B1 +U+69B2 # 60-37, CJK UNIFIED IDEOGRAPH-69B2 +U+69B4 # 60-56, CJK UNIFIED IDEOGRAPH-69B4 +U+69BB # 60-48, CJK UNIFIED IDEOGRAPH-69BB +U+69BE # 60-43, CJK UNIFIED IDEOGRAPH-69BE +U+69BF # 60-40, CJK UNIFIED IDEOGRAPH-69BF +U+69C1 # 60-41, CJK UNIFIED IDEOGRAPH-69C1 +U+69C3 # 60-49, CJK UNIFIED IDEOGRAPH-69C3 +U+69C7 # 84-02, CJK UNIFIED IDEOGRAPH-69C7 +U+69CA # 60-46, CJK UNIFIED IDEOGRAPH-69CA +U+69CB # 25-29, CJK UNIFIED IDEOGRAPH-69CB +U+69CC # 36-40, CJK UNIFIED IDEOGRAPH-69CC +U+69CD # 33-68, CJK UNIFIED IDEOGRAPH-69CD +U+69CE # 60-44, CJK UNIFIED IDEOGRAPH-69CE +U+69D0 # 60-39, CJK UNIFIED IDEOGRAPH-69D0 +U+69D3 # 60-42, CJK UNIFIED IDEOGRAPH-69D3 +U+69D8 # 45-45, CJK UNIFIED IDEOGRAPH-69D8 +U+69D9 # 43-74, CJK UNIFIED IDEOGRAPH-69D9 +U+69DD # 60-47, CJK UNIFIED IDEOGRAPH-69DD +U+69DE # 60-57, CJK UNIFIED IDEOGRAPH-69DE +U+69E7 # 60-65, CJK UNIFIED IDEOGRAPH-69E7 +U+69E8 # 60-58, CJK UNIFIED IDEOGRAPH-69E8 +U+69EB # 60-71, CJK UNIFIED IDEOGRAPH-69EB +U+69ED # 60-69, CJK UNIFIED IDEOGRAPH-69ED +U+69F2 # 60-64, CJK UNIFIED IDEOGRAPH-69F2 +U+69F9 # 60-63, CJK UNIFIED IDEOGRAPH-69F9 +U+69FB # 36-48, CJK UNIFIED IDEOGRAPH-69FB +U+69FD # 33-69, CJK UNIFIED IDEOGRAPH-69FD +U+69FF # 60-61, CJK UNIFIED IDEOGRAPH-69FF +U+6A02 # 60-59, CJK UNIFIED IDEOGRAPH-6A02 +U+6A05 # 60-66, CJK UNIFIED IDEOGRAPH-6A05 +U+6A0A # 60-72, CJK UNIFIED IDEOGRAPH-6A0A +U+6A0B # 40-85, CJK UNIFIED IDEOGRAPH-6A0B +U+6A0C # 60-78, CJK UNIFIED IDEOGRAPH-6A0C +U+6A12 # 60-73, CJK UNIFIED IDEOGRAPH-6A12 +U+6A13 # 60-76, CJK UNIFIED IDEOGRAPH-6A13 +U+6A14 # 60-70, CJK UNIFIED IDEOGRAPH-6A14 +U+6A17 # 35-84, CJK UNIFIED IDEOGRAPH-6A17 +U+6A19 # 41-24, CJK UNIFIED IDEOGRAPH-6A19 +U+6A1B # 60-60, CJK UNIFIED IDEOGRAPH-6A1B +U+6A1E # 60-68, CJK UNIFIED IDEOGRAPH-6A1E +U+6A1F # 30-32, CJK UNIFIED IDEOGRAPH-6A1F +U+6A21 # 44-47, CJK UNIFIED IDEOGRAPH-6A21 +U+6A22 # 60-88, CJK UNIFIED IDEOGRAPH-6A22 +U+6A23 # 60-75, CJK UNIFIED IDEOGRAPH-6A23 +U+6A29 # 24-02, CJK UNIFIED IDEOGRAPH-6A29 +U+6A2A # 18-03, CJK UNIFIED IDEOGRAPH-6A2A +U+6A2B # 19-63, CJK UNIFIED IDEOGRAPH-6A2B +U+6A2E # 60-51, CJK UNIFIED IDEOGRAPH-6A2E +U+6A35 # 30-33, CJK UNIFIED IDEOGRAPH-6A35 +U+6A36 # 60-80, CJK UNIFIED IDEOGRAPH-6A36 +U+6A38 # 60-87, CJK UNIFIED IDEOGRAPH-6A38 +U+6A39 # 28-89, CJK UNIFIED IDEOGRAPH-6A39 +U+6A3A # 19-82, CJK UNIFIED IDEOGRAPH-6A3A +U+6A3D # 35-14, CJK UNIFIED IDEOGRAPH-6A3D +U+6A44 # 60-77, CJK UNIFIED IDEOGRAPH-6A44 +U+6A47 # 60-82, CJK UNIFIED IDEOGRAPH-6A47 +U+6A48 # 60-86, CJK UNIFIED IDEOGRAPH-6A48 +U+6A4B # 22-22, CJK UNIFIED IDEOGRAPH-6A4B +U+6A58 # 21-44, CJK UNIFIED IDEOGRAPH-6A58 +U+6A59 # 60-84, CJK UNIFIED IDEOGRAPH-6A59 +U+6A5F # 21-01, CJK UNIFIED IDEOGRAPH-6A5F +U+6A61 # 38-43, CJK UNIFIED IDEOGRAPH-6A61 +U+6A62 # 60-83, CJK UNIFIED IDEOGRAPH-6A62 +U+6A66 # 60-85, CJK UNIFIED IDEOGRAPH-6A66 +U+6A72 # 60-79, CJK UNIFIED IDEOGRAPH-6A72 +U+6A78 # 60-81, CJK UNIFIED IDEOGRAPH-6A78 +U+6A7F # 19-64, CJK UNIFIED IDEOGRAPH-6A7F +U+6A80 # 35-41, CJK UNIFIED IDEOGRAPH-6A80 +U+6A84 # 60-92, CJK UNIFIED IDEOGRAPH-6A84 +U+6A8D # 60-90, CJK UNIFIED IDEOGRAPH-6A8D +U+6A8E # 24-73, CJK UNIFIED IDEOGRAPH-6A8E +U+6A90 # 60-89, CJK UNIFIED IDEOGRAPH-6A90 +U+6A97 # 61-01, CJK UNIFIED IDEOGRAPH-6A97 +U+6A9C # 59-56, CJK UNIFIED IDEOGRAPH-6A9C +U+6AA0 # 60-91, CJK UNIFIED IDEOGRAPH-6AA0 +U+6AA2 # 60-93, CJK UNIFIED IDEOGRAPH-6AA2 +U+6AA3 # 60-94, CJK UNIFIED IDEOGRAPH-6AA3 +U+6AAA # 61-12, CJK UNIFIED IDEOGRAPH-6AAA +U+6AAC # 61-08, CJK UNIFIED IDEOGRAPH-6AAC +U+6AAE # 59-77, CJK UNIFIED IDEOGRAPH-6AAE +U+6AB3 # 61-07, CJK UNIFIED IDEOGRAPH-6AB3 +U+6AB8 # 61-06, CJK UNIFIED IDEOGRAPH-6AB8 +U+6ABB # 61-03, CJK UNIFIED IDEOGRAPH-6ABB +U+6AC1 # 60-74, CJK UNIFIED IDEOGRAPH-6AC1 +U+6AC2 # 61-05, CJK UNIFIED IDEOGRAPH-6AC2 +U+6AC3 # 61-04, CJK UNIFIED IDEOGRAPH-6AC3 +U+6AD1 # 61-10, CJK UNIFIED IDEOGRAPH-6AD1 +U+6AD3 # 47-06, CJK UNIFIED IDEOGRAPH-6AD3 +U+6ADA # 61-13, CJK UNIFIED IDEOGRAPH-6ADA +U+6ADB # 22-91, CJK UNIFIED IDEOGRAPH-6ADB +U+6ADE # 61-09, CJK UNIFIED IDEOGRAPH-6ADE +U+6ADF # 61-11, CJK UNIFIED IDEOGRAPH-6ADF +U+6AE8 # 40-07, CJK UNIFIED IDEOGRAPH-6AE8 +U+6AEA # 61-14, CJK UNIFIED IDEOGRAPH-6AEA +U+6AFA # 61-18, CJK UNIFIED IDEOGRAPH-6AFA +U+6AFB # 61-15, CJK UNIFIED IDEOGRAPH-6AFB +U+6B04 # 45-83, CJK UNIFIED IDEOGRAPH-6B04 +U+6B05 # 61-16, CJK UNIFIED IDEOGRAPH-6B05 +U+6B0A # 60-62, CJK UNIFIED IDEOGRAPH-6B0A +U+6B12 # 61-19, CJK UNIFIED IDEOGRAPH-6B12 +U+6B16 # 61-20, CJK UNIFIED IDEOGRAPH-6B16 +U+6B1D # 17-21, CJK UNIFIED IDEOGRAPH-6B1D +U+6B1F # 61-22, CJK UNIFIED IDEOGRAPH-6B1F +U+6B20 # 23-71, CJK UNIFIED IDEOGRAPH-6B20 +U+6B21 # 28-01, CJK UNIFIED IDEOGRAPH-6B21 +U+6B23 # 22-53, CJK UNIFIED IDEOGRAPH-6B23 +U+6B27 # 18-04, CJK UNIFIED IDEOGRAPH-6B27 +U+6B32 # 45-63, CJK UNIFIED IDEOGRAPH-6B32 +U+6B37 # 61-24, CJK UNIFIED IDEOGRAPH-6B37 +U+6B38 # 61-23, CJK UNIFIED IDEOGRAPH-6B38 +U+6B39 # 61-26, CJK UNIFIED IDEOGRAPH-6B39 +U+6B3A # 21-29, CJK UNIFIED IDEOGRAPH-6B3A +U+6B3D # 22-54, CJK UNIFIED IDEOGRAPH-6B3D +U+6B3E # 20-30, CJK UNIFIED IDEOGRAPH-6B3E +U+6B43 # 61-29, CJK UNIFIED IDEOGRAPH-6B43 +U+6B47 # 61-28, CJK UNIFIED IDEOGRAPH-6B47 +U+6B49 # 61-30, CJK UNIFIED IDEOGRAPH-6B49 +U+6B4C # 18-46, CJK UNIFIED IDEOGRAPH-6B4C +U+6B4E # 35-23, CJK UNIFIED IDEOGRAPH-6B4E +U+6B50 # 61-31, CJK UNIFIED IDEOGRAPH-6B50 +U+6B53 # 20-31, CJK UNIFIED IDEOGRAPH-6B53 +U+6B54 # 61-33, CJK UNIFIED IDEOGRAPH-6B54 +U+6B59 # 61-32, CJK UNIFIED IDEOGRAPH-6B59 +U+6B5B # 61-34, CJK UNIFIED IDEOGRAPH-6B5B +U+6B5F # 61-35, CJK UNIFIED IDEOGRAPH-6B5F +U+6B61 # 61-36, CJK UNIFIED IDEOGRAPH-6B61 +U+6B62 # 27-63, CJK UNIFIED IDEOGRAPH-6B62 +U+6B63 # 32-21, CJK UNIFIED IDEOGRAPH-6B63 +U+6B64 # 26-01, CJK UNIFIED IDEOGRAPH-6B64 +U+6B66 # 41-80, CJK UNIFIED IDEOGRAPH-6B66 +U+6B69 # 42-66, CJK UNIFIED IDEOGRAPH-6B69 +U+6B6A # 47-36, CJK UNIFIED IDEOGRAPH-6B6A +U+6B6F # 27-85, CJK UNIFIED IDEOGRAPH-6B6F +U+6B73 # 26-48, CJK UNIFIED IDEOGRAPH-6B73 +U+6B74 # 46-82, CJK UNIFIED IDEOGRAPH-6B74 +U+6B78 # 61-37, CJK UNIFIED IDEOGRAPH-6B78 +U+6B79 # 61-38, CJK UNIFIED IDEOGRAPH-6B79 +U+6B7B # 27-64, CJK UNIFIED IDEOGRAPH-6B7B +U+6B7F # 61-39, CJK UNIFIED IDEOGRAPH-6B7F +U+6B80 # 61-40, CJK UNIFIED IDEOGRAPH-6B80 +U+6B83 # 61-42, CJK UNIFIED IDEOGRAPH-6B83 +U+6B84 # 61-41, CJK UNIFIED IDEOGRAPH-6B84 +U+6B86 # 43-56, CJK UNIFIED IDEOGRAPH-6B86 +U+6B89 # 29-62, CJK UNIFIED IDEOGRAPH-6B89 +U+6B8A # 28-76, CJK UNIFIED IDEOGRAPH-6B8A +U+6B8B # 27-36, CJK UNIFIED IDEOGRAPH-6B8B +U+6B8D # 61-43, CJK UNIFIED IDEOGRAPH-6B8D +U+6B95 # 61-45, CJK UNIFIED IDEOGRAPH-6B95 +U+6B96 # 31-03, CJK UNIFIED IDEOGRAPH-6B96 +U+6B98 # 61-44, CJK UNIFIED IDEOGRAPH-6B98 +U+6B9E # 61-46, CJK UNIFIED IDEOGRAPH-6B9E +U+6BA4 # 61-47, CJK UNIFIED IDEOGRAPH-6BA4 +U+6BAA # 61-48, CJK UNIFIED IDEOGRAPH-6BAA +U+6BAB # 61-49, CJK UNIFIED IDEOGRAPH-6BAB +U+6BAF # 61-50, CJK UNIFIED IDEOGRAPH-6BAF +U+6BB1 # 61-52, CJK UNIFIED IDEOGRAPH-6BB1 +U+6BB2 # 61-51, CJK UNIFIED IDEOGRAPH-6BB2 +U+6BB3 # 61-53, CJK UNIFIED IDEOGRAPH-6BB3 +U+6BB4 # 18-05, CJK UNIFIED IDEOGRAPH-6BB4 +U+6BB5 # 35-42, CJK UNIFIED IDEOGRAPH-6BB5 +U+6BB7 # 61-54, CJK UNIFIED IDEOGRAPH-6BB7 +U+6BBA # 27-06, CJK UNIFIED IDEOGRAPH-6BBA +U+6BBB # 19-44, CJK UNIFIED IDEOGRAPH-6BBB +U+6BBC # 61-55, CJK UNIFIED IDEOGRAPH-6BBC +U+6BBF # 37-34, CJK UNIFIED IDEOGRAPH-6BBF +U+6BC0 # 52-44, CJK UNIFIED IDEOGRAPH-6BC0 +U+6BC5 # 21-03, CJK UNIFIED IDEOGRAPH-6BC5 +U+6BC6 # 61-56, CJK UNIFIED IDEOGRAPH-6BC6 +U+6BCB # 61-57, CJK UNIFIED IDEOGRAPH-6BCB +U+6BCD # 42-76, CJK UNIFIED IDEOGRAPH-6BCD +U+6BCE # 43-72, CJK UNIFIED IDEOGRAPH-6BCE +U+6BD2 # 38-39, CJK UNIFIED IDEOGRAPH-6BD2 +U+6BD3 # 61-58, CJK UNIFIED IDEOGRAPH-6BD3 +U+6BD4 # 40-70, CJK UNIFIED IDEOGRAPH-6BD4 +U+6BD8 # 40-91, CJK UNIFIED IDEOGRAPH-6BD8 +U+6BDB # 44-51, CJK UNIFIED IDEOGRAPH-6BDB +U+6BDF # 61-59, CJK UNIFIED IDEOGRAPH-6BDF +U+6BEB # 61-61, CJK UNIFIED IDEOGRAPH-6BEB +U+6BEC # 61-60, CJK UNIFIED IDEOGRAPH-6BEC +U+6BEF # 61-63, CJK UNIFIED IDEOGRAPH-6BEF +U+6BF3 # 61-62, CJK UNIFIED IDEOGRAPH-6BF3 +U+6C08 # 61-65, CJK UNIFIED IDEOGRAPH-6C08 +U+6C0F # 27-65, CJK UNIFIED IDEOGRAPH-6C0F +U+6C11 # 44-17, CJK UNIFIED IDEOGRAPH-6C11 +U+6C13 # 61-66, CJK UNIFIED IDEOGRAPH-6C13 +U+6C14 # 61-67, CJK UNIFIED IDEOGRAPH-6C14 +U+6C17 # 21-04, CJK UNIFIED IDEOGRAPH-6C17 +U+6C1B # 61-68, CJK UNIFIED IDEOGRAPH-6C1B +U+6C23 # 61-70, CJK UNIFIED IDEOGRAPH-6C23 +U+6C24 # 61-69, CJK UNIFIED IDEOGRAPH-6C24 +U+6C34 # 31-69, CJK UNIFIED IDEOGRAPH-6C34 +U+6C37 # 41-25, CJK UNIFIED IDEOGRAPH-6C37 +U+6C38 # 17-42, CJK UNIFIED IDEOGRAPH-6C38 +U+6C3E # 40-37, CJK UNIFIED IDEOGRAPH-6C3E +U+6C40 # 36-85, CJK UNIFIED IDEOGRAPH-6C40 +U+6C41 # 29-33, CJK UNIFIED IDEOGRAPH-6C41 +U+6C42 # 21-65, CJK UNIFIED IDEOGRAPH-6C42 +U+6C4E # 40-38, CJK UNIFIED IDEOGRAPH-6C4E +U+6C50 # 28-14, CJK UNIFIED IDEOGRAPH-6C50 +U+6C55 # 61-72, CJK UNIFIED IDEOGRAPH-6C55 +U+6C57 # 20-32, CJK UNIFIED IDEOGRAPH-6C57 +U+6C5A # 17-88, CJK UNIFIED IDEOGRAPH-6C5A +U+6C5D # 38-82, CJK UNIFIED IDEOGRAPH-6C5D +U+6C5E # 61-71, CJK UNIFIED IDEOGRAPH-6C5E +U+6C5F # 25-30, CJK UNIFIED IDEOGRAPH-6C5F +U+6C60 # 35-51, CJK UNIFIED IDEOGRAPH-6C60 +U+6C62 # 61-73, CJK UNIFIED IDEOGRAPH-6C62 +U+6C68 # 61-81, CJK UNIFIED IDEOGRAPH-6C68 +U+6C6A # 61-74, CJK UNIFIED IDEOGRAPH-6C6A +U+6C70 # 34-33, CJK UNIFIED IDEOGRAPH-6C70 +U+6C72 # 21-66, CJK UNIFIED IDEOGRAPH-6C72 +U+6C73 # 61-82, CJK UNIFIED IDEOGRAPH-6C73 +U+6C7A # 23-72, CJK UNIFIED IDEOGRAPH-6C7A +U+6C7D # 21-05, CJK UNIFIED IDEOGRAPH-6C7D +U+6C7E # 61-80, CJK UNIFIED IDEOGRAPH-6C7E +U+6C81 # 61-78, CJK UNIFIED IDEOGRAPH-6C81 +U+6C82 # 61-75, CJK UNIFIED IDEOGRAPH-6C82 +U+6C83 # 45-64, CJK UNIFIED IDEOGRAPH-6C83 +U+6C88 # 36-32, CJK UNIFIED IDEOGRAPH-6C88 +U+6C8C # 38-57, CJK UNIFIED IDEOGRAPH-6C8C +U+6C8D # 61-76, CJK UNIFIED IDEOGRAPH-6C8D +U+6C90 # 61-84, CJK UNIFIED IDEOGRAPH-6C90 +U+6C92 # 61-83, CJK UNIFIED IDEOGRAPH-6C92 +U+6C93 # 23-03, CJK UNIFIED IDEOGRAPH-6C93 +U+6C96 # 18-13, CJK UNIFIED IDEOGRAPH-6C96 +U+6C99 # 26-27, CJK UNIFIED IDEOGRAPH-6C99 +U+6C9A # 61-77, CJK UNIFIED IDEOGRAPH-6C9A +U+6C9B # 61-79, CJK UNIFIED IDEOGRAPH-6C9B +U+6CA1 # 43-55, CJK UNIFIED IDEOGRAPH-6CA1 +U+6CA2 # 34-84, CJK UNIFIED IDEOGRAPH-6CA2 +U+6CAB # 43-87, CJK UNIFIED IDEOGRAPH-6CAB +U+6CAE # 61-92, CJK UNIFIED IDEOGRAPH-6CAE +U+6CB1 # 61-93, CJK UNIFIED IDEOGRAPH-6CB1 +U+6CB3 # 18-47, CJK UNIFIED IDEOGRAPH-6CB3 +U+6CB8 # 42-08, CJK UNIFIED IDEOGRAPH-6CB8 +U+6CB9 # 44-93, CJK UNIFIED IDEOGRAPH-6CB9 +U+6CBA # 62-01, CJK UNIFIED IDEOGRAPH-6CBA +U+6CBB # 28-03, CJK UNIFIED IDEOGRAPH-6CBB +U+6CBC # 30-34, CJK UNIFIED IDEOGRAPH-6CBC +U+6CBD # 61-88, CJK UNIFIED IDEOGRAPH-6CBD +U+6CBE # 61-94, CJK UNIFIED IDEOGRAPH-6CBE +U+6CBF # 17-72, CJK UNIFIED IDEOGRAPH-6CBF +U+6CC1 # 22-23, CJK UNIFIED IDEOGRAPH-6CC1 +U+6CC4 # 61-85, CJK UNIFIED IDEOGRAPH-6CC4 +U+6CC5 # 61-90, CJK UNIFIED IDEOGRAPH-6CC5 +U+6CC9 # 32-84, CJK UNIFIED IDEOGRAPH-6CC9 +U+6CCA # 39-81, CJK UNIFIED IDEOGRAPH-6CCA +U+6CCC # 40-71, CJK UNIFIED IDEOGRAPH-6CCC +U+6CD3 # 61-87, CJK UNIFIED IDEOGRAPH-6CD3 +U+6CD5 # 43-01, CJK UNIFIED IDEOGRAPH-6CD5 +U+6CD7 # 61-89, CJK UNIFIED IDEOGRAPH-6CD7 +U+6CD9 # 62-04, CJK UNIFIED IDEOGRAPH-6CD9 +U+6CDB # 62-02, CJK UNIFIED IDEOGRAPH-6CDB +U+6CDD # 61-91, CJK UNIFIED IDEOGRAPH-6CDD +U+6CE1 # 43-02, CJK UNIFIED IDEOGRAPH-6CE1 +U+6CE2 # 39-40, CJK UNIFIED IDEOGRAPH-6CE2 +U+6CE3 # 21-67, CJK UNIFIED IDEOGRAPH-6CE3 +U+6CE5 # 37-05, CJK UNIFIED IDEOGRAPH-6CE5 +U+6CE8 # 35-77, CJK UNIFIED IDEOGRAPH-6CE8 +U+6CEA # 62-05, CJK UNIFIED IDEOGRAPH-6CEA +U+6CEF # 62-03, CJK UNIFIED IDEOGRAPH-6CEF +U+6CF0 # 34-57, CJK UNIFIED IDEOGRAPH-6CF0 +U+6CF1 # 61-86, CJK UNIFIED IDEOGRAPH-6CF1 +U+6CF3 # 17-43, CJK UNIFIED IDEOGRAPH-6CF3 +U+6D0B # 45-46, CJK UNIFIED IDEOGRAPH-6D0B +U+6D0C # 62-16, CJK UNIFIED IDEOGRAPH-6D0C +U+6D12 # 62-15, CJK UNIFIED IDEOGRAPH-6D12 +U+6D17 # 32-86, CJK UNIFIED IDEOGRAPH-6D17 +U+6D19 # 62-12, CJK UNIFIED IDEOGRAPH-6D19 +U+6D1B # 45-76, CJK UNIFIED IDEOGRAPH-6D1B +U+6D1E # 38-22, CJK UNIFIED IDEOGRAPH-6D1E +U+6D1F # 62-06, CJK UNIFIED IDEOGRAPH-6D1F +U+6D25 # 36-37, CJK UNIFIED IDEOGRAPH-6D25 +U+6D29 # 17-44, CJK UNIFIED IDEOGRAPH-6D29 +U+6D2A # 25-31, CJK UNIFIED IDEOGRAPH-6D2A +U+6D2B # 62-09, CJK UNIFIED IDEOGRAPH-6D2B +U+6D32 # 29-07, CJK UNIFIED IDEOGRAPH-6D32 +U+6D33 # 62-14, CJK UNIFIED IDEOGRAPH-6D33 +U+6D35 # 62-13, CJK UNIFIED IDEOGRAPH-6D35 +U+6D36 # 62-08, CJK UNIFIED IDEOGRAPH-6D36 +U+6D38 # 62-11, CJK UNIFIED IDEOGRAPH-6D38 +U+6D3B # 19-72, CJK UNIFIED IDEOGRAPH-6D3B +U+6D3D # 62-10, CJK UNIFIED IDEOGRAPH-6D3D +U+6D3E # 39-41, CJK UNIFIED IDEOGRAPH-6D3E +U+6D41 # 46-14, CJK UNIFIED IDEOGRAPH-6D41 +U+6D44 # 30-84, CJK UNIFIED IDEOGRAPH-6D44 +U+6D45 # 32-85, CJK UNIFIED IDEOGRAPH-6D45 +U+6D59 # 62-22, CJK UNIFIED IDEOGRAPH-6D59 +U+6D5A # 62-20, CJK UNIFIED IDEOGRAPH-6D5A +U+6D5C # 41-45, CJK UNIFIED IDEOGRAPH-6D5C +U+6D63 # 62-17, CJK UNIFIED IDEOGRAPH-6D63 +U+6D64 # 62-19, CJK UNIFIED IDEOGRAPH-6D64 +U+6D66 # 17-26, CJK UNIFIED IDEOGRAPH-6D66 +U+6D69 # 25-32, CJK UNIFIED IDEOGRAPH-6D69 +U+6D6A # 47-18, CJK UNIFIED IDEOGRAPH-6D6A +U+6D6C # 19-29, CJK UNIFIED IDEOGRAPH-6D6C +U+6D6E # 41-66, CJK UNIFIED IDEOGRAPH-6D6E +U+6D74 # 45-65, CJK UNIFIED IDEOGRAPH-6D74 +U+6D77 # 19-04, CJK UNIFIED IDEOGRAPH-6D77 +U+6D78 # 31-27, CJK UNIFIED IDEOGRAPH-6D78 +U+6D79 # 62-21, CJK UNIFIED IDEOGRAPH-6D79 +U+6D85 # 62-26, CJK UNIFIED IDEOGRAPH-6D85 +U+6D88 # 30-35, CJK UNIFIED IDEOGRAPH-6D88 +U+6D8C # 45-16, CJK UNIFIED IDEOGRAPH-6D8C +U+6D8E # 62-23, CJK UNIFIED IDEOGRAPH-6D8E +U+6D93 # 62-18, CJK UNIFIED IDEOGRAPH-6D93 +U+6D95 # 62-24, CJK UNIFIED IDEOGRAPH-6D95 +U+6D99 # 46-62, CJK UNIFIED IDEOGRAPH-6D99 +U+6D9B # 37-83, CJK UNIFIED IDEOGRAPH-6D9B +U+6D9C # 38-34, CJK UNIFIED IDEOGRAPH-6D9C +U+6DAF # 19-22, CJK UNIFIED IDEOGRAPH-6DAF +U+6DB2 # 17-53, CJK UNIFIED IDEOGRAPH-6DB2 +U+6DB5 # 62-30, CJK UNIFIED IDEOGRAPH-6DB5 +U+6DB8 # 62-33, CJK UNIFIED IDEOGRAPH-6DB8 +U+6DBC # 46-35, CJK UNIFIED IDEOGRAPH-6DBC +U+6DC0 # 45-68, CJK UNIFIED IDEOGRAPH-6DC0 +U+6DC5 # 62-40, CJK UNIFIED IDEOGRAPH-6DC5 +U+6DC6 # 62-34, CJK UNIFIED IDEOGRAPH-6DC6 +U+6DC7 # 62-31, CJK UNIFIED IDEOGRAPH-6DC7 +U+6DCB # 46-52, CJK UNIFIED IDEOGRAPH-6DCB +U+6DCC # 62-37, CJK UNIFIED IDEOGRAPH-6DCC +U+6DD1 # 29-42, CJK UNIFIED IDEOGRAPH-6DD1 +U+6DD2 # 62-39, CJK UNIFIED IDEOGRAPH-6DD2 +U+6DD5 # 62-44, CJK UNIFIED IDEOGRAPH-6DD5 +U+6DD8 # 37-81, CJK UNIFIED IDEOGRAPH-6DD8 +U+6DD9 # 62-42, CJK UNIFIED IDEOGRAPH-6DD9 +U+6DDE # 62-36, CJK UNIFIED IDEOGRAPH-6DDE +U+6DE1 # 35-24, CJK UNIFIED IDEOGRAPH-6DE1 +U+6DE4 # 62-43, CJK UNIFIED IDEOGRAPH-6DE4 +U+6DE6 # 62-32, CJK UNIFIED IDEOGRAPH-6DE6 +U+6DE8 # 62-38, CJK UNIFIED IDEOGRAPH-6DE8 +U+6DEA # 62-45, CJK UNIFIED IDEOGRAPH-6DEA +U+6DEB # 16-92, CJK UNIFIED IDEOGRAPH-6DEB +U+6DEC # 62-35, CJK UNIFIED IDEOGRAPH-6DEC +U+6DEE # 62-46, CJK UNIFIED IDEOGRAPH-6DEE +U+6DF1 # 31-28, CJK UNIFIED IDEOGRAPH-6DF1 +U+6DF3 # 29-63, CJK UNIFIED IDEOGRAPH-6DF3 +U+6DF5 # 42-05, CJK UNIFIED IDEOGRAPH-6DF5 +U+6DF7 # 26-14, CJK UNIFIED IDEOGRAPH-6DF7 +U+6DF9 # 62-27, CJK UNIFIED IDEOGRAPH-6DF9 +U+6DFA # 62-41, CJK UNIFIED IDEOGRAPH-6DFA +U+6DFB # 37-26, CJK UNIFIED IDEOGRAPH-6DFB +U+6E05 # 32-22, CJK UNIFIED IDEOGRAPH-6E05 +U+6E07 # 19-73, CJK UNIFIED IDEOGRAPH-6E07 +U+6E08 # 26-49, CJK UNIFIED IDEOGRAPH-6E08 +U+6E09 # 30-36, CJK UNIFIED IDEOGRAPH-6E09 +U+6E0A # 62-29, CJK UNIFIED IDEOGRAPH-6E0A +U+6E0B # 29-34, CJK UNIFIED IDEOGRAPH-6E0B +U+6E13 # 23-44, CJK UNIFIED IDEOGRAPH-6E13 +U+6E15 # 62-28, CJK UNIFIED IDEOGRAPH-6E15 +U+6E19 # 62-50, CJK UNIFIED IDEOGRAPH-6E19 +U+6E1A # 29-77, CJK UNIFIED IDEOGRAPH-6E1A +U+6E1B # 24-26, CJK UNIFIED IDEOGRAPH-6E1B +U+6E1D # 62-65, CJK UNIFIED IDEOGRAPH-6E1D +U+6E1F # 62-59, CJK UNIFIED IDEOGRAPH-6E1F +U+6E20 # 21-84, CJK UNIFIED IDEOGRAPH-6E20 +U+6E21 # 37-47, CJK UNIFIED IDEOGRAPH-6E21 +U+6E23 # 62-54, CJK UNIFIED IDEOGRAPH-6E23 +U+6E24 # 62-63, CJK UNIFIED IDEOGRAPH-6E24 +U+6E25 # 16-15, CJK UNIFIED IDEOGRAPH-6E25 +U+6E26 # 17-18, CJK UNIFIED IDEOGRAPH-6E26 +U+6E29 # 18-25, CJK UNIFIED IDEOGRAPH-6E29 +U+6E2B # 62-56, CJK UNIFIED IDEOGRAPH-6E2B +U+6E2C # 34-12, CJK UNIFIED IDEOGRAPH-6E2C +U+6E2D # 62-47, CJK UNIFIED IDEOGRAPH-6E2D +U+6E2E # 62-49, CJK UNIFIED IDEOGRAPH-6E2E +U+6E2F # 25-33, CJK UNIFIED IDEOGRAPH-6E2F +U+6E38 # 62-66, CJK UNIFIED IDEOGRAPH-6E38 +U+6E3A # 62-61, CJK UNIFIED IDEOGRAPH-6E3A +U+6E3E # 62-53, CJK UNIFIED IDEOGRAPH-6E3E +U+6E43 # 62-60, CJK UNIFIED IDEOGRAPH-6E43 +U+6E4A # 44-11, CJK UNIFIED IDEOGRAPH-6E4A +U+6E4D # 62-58, CJK UNIFIED IDEOGRAPH-6E4D +U+6E4E # 62-62, CJK UNIFIED IDEOGRAPH-6E4E +U+6E56 # 24-48, CJK UNIFIED IDEOGRAPH-6E56 +U+6E58 # 30-37, CJK UNIFIED IDEOGRAPH-6E58 +U+6E5B # 35-25, CJK UNIFIED IDEOGRAPH-6E5B +U+6E5F # 62-52, CJK UNIFIED IDEOGRAPH-6E5F +U+6E67 # 45-15, CJK UNIFIED IDEOGRAPH-6E67 +U+6E6B # 62-55, CJK UNIFIED IDEOGRAPH-6E6B +U+6E6E # 62-48, CJK UNIFIED IDEOGRAPH-6E6E +U+6E6F # 37-82, CJK UNIFIED IDEOGRAPH-6E6F +U+6E72 # 62-51, CJK UNIFIED IDEOGRAPH-6E72 +U+6E76 # 62-57, CJK UNIFIED IDEOGRAPH-6E76 +U+6E7E # 47-49, CJK UNIFIED IDEOGRAPH-6E7E +U+6E7F # 28-30, CJK UNIFIED IDEOGRAPH-6E7F +U+6E80 # 43-94, CJK UNIFIED IDEOGRAPH-6E80 +U+6E82 # 62-67, CJK UNIFIED IDEOGRAPH-6E82 +U+6E8C # 40-14, CJK UNIFIED IDEOGRAPH-6E8C +U+6E8F # 62-79, CJK UNIFIED IDEOGRAPH-6E8F +U+6E90 # 24-27, CJK UNIFIED IDEOGRAPH-6E90 +U+6E96 # 29-64, CJK UNIFIED IDEOGRAPH-6E96 +U+6E98 # 62-69, CJK UNIFIED IDEOGRAPH-6E98 +U+6E9C # 46-15, CJK UNIFIED IDEOGRAPH-6E9C +U+6E9D # 25-34, CJK UNIFIED IDEOGRAPH-6E9D +U+6E9F # 62-82, CJK UNIFIED IDEOGRAPH-6E9F +U+6EA2 # 16-78, CJK UNIFIED IDEOGRAPH-6EA2 +U+6EA5 # 62-80, CJK UNIFIED IDEOGRAPH-6EA5 +U+6EAA # 62-68, CJK UNIFIED IDEOGRAPH-6EAA +U+6EAF # 62-74, CJK UNIFIED IDEOGRAPH-6EAF +U+6EB2 # 62-76, CJK UNIFIED IDEOGRAPH-6EB2 +U+6EB6 # 45-47, CJK UNIFIED IDEOGRAPH-6EB6 +U+6EB7 # 62-71, CJK UNIFIED IDEOGRAPH-6EB7 +U+6EBA # 37-14, CJK UNIFIED IDEOGRAPH-6EBA +U+6EBD # 62-73, CJK UNIFIED IDEOGRAPH-6EBD +U+6EC2 # 62-81, CJK UNIFIED IDEOGRAPH-6EC2 +U+6EC4 # 62-75, CJK UNIFIED IDEOGRAPH-6EC4 +U+6EC5 # 44-39, CJK UNIFIED IDEOGRAPH-6EC5 +U+6EC9 # 62-70, CJK UNIFIED IDEOGRAPH-6EC9 +U+6ECB # 28-02, CJK UNIFIED IDEOGRAPH-6ECB +U+6ECC # 62-94, CJK UNIFIED IDEOGRAPH-6ECC +U+6ED1 # 19-74, CJK UNIFIED IDEOGRAPH-6ED1 +U+6ED3 # 62-72, CJK UNIFIED IDEOGRAPH-6ED3 +U+6ED4 # 62-77, CJK UNIFIED IDEOGRAPH-6ED4 +U+6ED5 # 62-78, CJK UNIFIED IDEOGRAPH-6ED5 +U+6EDD # 34-76, CJK UNIFIED IDEOGRAPH-6EDD +U+6EDE # 34-58, CJK UNIFIED IDEOGRAPH-6EDE +U+6EEC # 62-86, CJK UNIFIED IDEOGRAPH-6EEC +U+6EEF # 62-92, CJK UNIFIED IDEOGRAPH-6EEF +U+6EF2 # 62-90, CJK UNIFIED IDEOGRAPH-6EF2 +U+6EF4 # 37-09, CJK UNIFIED IDEOGRAPH-6EF4 +U+6EF7 # 63-03, CJK UNIFIED IDEOGRAPH-6EF7 +U+6EF8 # 62-87, CJK UNIFIED IDEOGRAPH-6EF8 +U+6EFE # 62-88, CJK UNIFIED IDEOGRAPH-6EFE +U+6EFF # 62-64, CJK UNIFIED IDEOGRAPH-6EFF +U+6F01 # 21-89, CJK UNIFIED IDEOGRAPH-6F01 +U+6F02 # 41-26, CJK UNIFIED IDEOGRAPH-6F02 +U+6F06 # 28-31, CJK UNIFIED IDEOGRAPH-6F06 +U+6F09 # 25-87, CJK UNIFIED IDEOGRAPH-6F09 +U+6F0F # 47-19, CJK UNIFIED IDEOGRAPH-6F0F +U+6F11 # 62-84, CJK UNIFIED IDEOGRAPH-6F11 +U+6F13 # 63-02, CJK UNIFIED IDEOGRAPH-6F13 +U+6F14 # 17-73, CJK UNIFIED IDEOGRAPH-6F14 +U+6F15 # 33-70, CJK UNIFIED IDEOGRAPH-6F15 +U+6F20 # 39-89, CJK UNIFIED IDEOGRAPH-6F20 +U+6F22 # 20-33, CJK UNIFIED IDEOGRAPH-6F22 +U+6F23 # 46-90, CJK UNIFIED IDEOGRAPH-6F23 +U+6F2B # 44-01, CJK UNIFIED IDEOGRAPH-6F2B +U+6F2C # 36-50, CJK UNIFIED IDEOGRAPH-6F2C +U+6F31 # 62-91, CJK UNIFIED IDEOGRAPH-6F31 +U+6F32 # 62-93, CJK UNIFIED IDEOGRAPH-6F32 +U+6F38 # 33-18, CJK UNIFIED IDEOGRAPH-6F38 +U+6F3E # 63-01, CJK UNIFIED IDEOGRAPH-6F3E +U+6F3F # 62-89, CJK UNIFIED IDEOGRAPH-6F3F +U+6F41 # 62-83, CJK UNIFIED IDEOGRAPH-6F41 +U+6F45 # 20-35, CJK UNIFIED IDEOGRAPH-6F45 +U+6F54 # 23-73, CJK UNIFIED IDEOGRAPH-6F54 +U+6F58 # 63-15, CJK UNIFIED IDEOGRAPH-6F58 +U+6F5B # 63-10, CJK UNIFIED IDEOGRAPH-6F5B +U+6F5C # 32-88, CJK UNIFIED IDEOGRAPH-6F5C +U+6F5F # 19-67, CJK UNIFIED IDEOGRAPH-6F5F +U+6F64 # 29-65, CJK UNIFIED IDEOGRAPH-6F64 +U+6F66 # 63-19, CJK UNIFIED IDEOGRAPH-6F66 +U+6F6D # 63-12, CJK UNIFIED IDEOGRAPH-6F6D +U+6F6E # 36-12, CJK UNIFIED IDEOGRAPH-6F6E +U+6F6F # 63-09, CJK UNIFIED IDEOGRAPH-6F6F +U+6F70 # 36-57, CJK UNIFIED IDEOGRAPH-6F70 +U+6F74 # 63-44, CJK UNIFIED IDEOGRAPH-6F74 +U+6F78 # 63-06, CJK UNIFIED IDEOGRAPH-6F78 +U+6F7A # 63-05, CJK UNIFIED IDEOGRAPH-6F7A +U+6F7C # 63-14, CJK UNIFIED IDEOGRAPH-6F7C +U+6F80 # 63-08, CJK UNIFIED IDEOGRAPH-6F80 +U+6F81 # 63-07, CJK UNIFIED IDEOGRAPH-6F81 +U+6F82 # 63-13, CJK UNIFIED IDEOGRAPH-6F82 +U+6F84 # 32-01, CJK UNIFIED IDEOGRAPH-6F84 +U+6F86 # 63-04, CJK UNIFIED IDEOGRAPH-6F86 +U+6F8E # 63-16, CJK UNIFIED IDEOGRAPH-6F8E +U+6F91 # 63-17, CJK UNIFIED IDEOGRAPH-6F91 +U+6F97 # 20-34, CJK UNIFIED IDEOGRAPH-6F97 +U+6FA1 # 63-22, CJK UNIFIED IDEOGRAPH-6FA1 +U+6FA3 # 63-21, CJK UNIFIED IDEOGRAPH-6FA3 +U+6FA4 # 63-23, CJK UNIFIED IDEOGRAPH-6FA4 +U+6FAA # 63-26, CJK UNIFIED IDEOGRAPH-6FAA +U+6FB1 # 37-35, CJK UNIFIED IDEOGRAPH-6FB1 +U+6FB3 # 63-20, CJK UNIFIED IDEOGRAPH-6FB3 +U+6FB9 # 63-24, CJK UNIFIED IDEOGRAPH-6FB9 +U+6FC0 # 23-67, CJK UNIFIED IDEOGRAPH-6FC0 +U+6FC1 # 34-89, CJK UNIFIED IDEOGRAPH-6FC1 +U+6FC2 # 63-18, CJK UNIFIED IDEOGRAPH-6FC2 +U+6FC3 # 39-27, CJK UNIFIED IDEOGRAPH-6FC3 +U+6FC6 # 63-25, CJK UNIFIED IDEOGRAPH-6FC6 +U+6FD4 # 63-30, CJK UNIFIED IDEOGRAPH-6FD4 +U+6FD5 # 63-28, CJK UNIFIED IDEOGRAPH-6FD5 +U+6FD8 # 63-31, CJK UNIFIED IDEOGRAPH-6FD8 +U+6FDB # 63-34, CJK UNIFIED IDEOGRAPH-6FDB +U+6FDF # 63-27, CJK UNIFIED IDEOGRAPH-6FDF +U+6FE0 # 25-74, CJK UNIFIED IDEOGRAPH-6FE0 +U+6FE1 # 39-08, CJK UNIFIED IDEOGRAPH-6FE1 +U+6FE4 # 62-25, CJK UNIFIED IDEOGRAPH-6FE4 +U+6FEB # 45-84, CJK UNIFIED IDEOGRAPH-6FEB +U+6FEC # 63-29, CJK UNIFIED IDEOGRAPH-6FEC +U+6FEE # 63-33, CJK UNIFIED IDEOGRAPH-6FEE +U+6FEF # 34-85, CJK UNIFIED IDEOGRAPH-6FEF +U+6FF1 # 63-32, CJK UNIFIED IDEOGRAPH-6FF1 +U+6FF3 # 63-11, CJK UNIFIED IDEOGRAPH-6FF3 +U+6FF6 # 79-73, CJK UNIFIED IDEOGRAPH-6FF6 +U+6FFA # 63-37, CJK UNIFIED IDEOGRAPH-6FFA +U+6FFE # 63-41, CJK UNIFIED IDEOGRAPH-6FFE +U+7001 # 63-39, CJK UNIFIED IDEOGRAPH-7001 +U+7009 # 63-35, CJK UNIFIED IDEOGRAPH-7009 +U+700B # 63-36, CJK UNIFIED IDEOGRAPH-700B +U+700F # 63-40, CJK UNIFIED IDEOGRAPH-700F +U+7011 # 63-38, CJK UNIFIED IDEOGRAPH-7011 +U+7015 # 41-46, CJK UNIFIED IDEOGRAPH-7015 +U+7018 # 63-46, CJK UNIFIED IDEOGRAPH-7018 +U+701A # 63-43, CJK UNIFIED IDEOGRAPH-701A +U+701B # 63-42, CJK UNIFIED IDEOGRAPH-701B +U+701D # 63-45, CJK UNIFIED IDEOGRAPH-701D +U+701E # 38-52, CJK UNIFIED IDEOGRAPH-701E +U+701F # 63-47, CJK UNIFIED IDEOGRAPH-701F +U+7026 # 35-85, CJK UNIFIED IDEOGRAPH-7026 +U+7027 # 34-77, CJK UNIFIED IDEOGRAPH-7027 +U+702C # 32-05, CJK UNIFIED IDEOGRAPH-702C +U+7030 # 63-48, CJK UNIFIED IDEOGRAPH-7030 +U+7032 # 63-50, CJK UNIFIED IDEOGRAPH-7032 +U+703E # 63-49, CJK UNIFIED IDEOGRAPH-703E +U+704C # 62-85, CJK UNIFIED IDEOGRAPH-704C +U+7051 # 63-51, CJK UNIFIED IDEOGRAPH-7051 +U+7058 # 38-71, CJK UNIFIED IDEOGRAPH-7058 +U+7063 # 63-52, CJK UNIFIED IDEOGRAPH-7063 +U+706B # 18-48, CJK UNIFIED IDEOGRAPH-706B +U+706F # 37-84, CJK UNIFIED IDEOGRAPH-706F +U+7070 # 19-05, CJK UNIFIED IDEOGRAPH-7070 +U+7078 # 21-68, CJK UNIFIED IDEOGRAPH-7078 +U+707C # 28-62, CJK UNIFIED IDEOGRAPH-707C +U+707D # 26-50, CJK UNIFIED IDEOGRAPH-707D +U+7089 # 47-07, CJK UNIFIED IDEOGRAPH-7089 +U+708A # 31-70, CJK UNIFIED IDEOGRAPH-708A +U+708E # 17-74, CJK UNIFIED IDEOGRAPH-708E +U+7092 # 63-54, CJK UNIFIED IDEOGRAPH-7092 +U+7099 # 63-53, CJK UNIFIED IDEOGRAPH-7099 +U+70AC # 63-57, CJK UNIFIED IDEOGRAPH-70AC +U+70AD # 35-26, CJK UNIFIED IDEOGRAPH-70AD +U+70AE # 63-60, CJK UNIFIED IDEOGRAPH-70AE +U+70AF # 63-55, CJK UNIFIED IDEOGRAPH-70AF +U+70B3 # 63-59, CJK UNIFIED IDEOGRAPH-70B3 +U+70B8 # 63-58, CJK UNIFIED IDEOGRAPH-70B8 +U+70B9 # 37-32, CJK UNIFIED IDEOGRAPH-70B9 +U+70BA # 16-57, CJK UNIFIED IDEOGRAPH-70BA +U+70C8 # 46-85, CJK UNIFIED IDEOGRAPH-70C8 +U+70CB # 63-62, CJK UNIFIED IDEOGRAPH-70CB +U+70CF # 17-08, CJK UNIFIED IDEOGRAPH-70CF +U+70D9 # 63-64, CJK UNIFIED IDEOGRAPH-70D9 +U+70DD # 63-63, CJK UNIFIED IDEOGRAPH-70DD +U+70DF # 63-61, CJK UNIFIED IDEOGRAPH-70DF +U+70F1 # 63-56, CJK UNIFIED IDEOGRAPH-70F1 +U+70F9 # 43-03, CJK UNIFIED IDEOGRAPH-70F9 +U+70FD # 63-66, CJK UNIFIED IDEOGRAPH-70FD +U+7109 # 63-65, CJK UNIFIED IDEOGRAPH-7109 +U+7114 # 17-75, CJK UNIFIED IDEOGRAPH-7114 +U+7119 # 63-68, CJK UNIFIED IDEOGRAPH-7119 +U+711A # 42-18, CJK UNIFIED IDEOGRAPH-711A +U+711C # 63-67, CJK UNIFIED IDEOGRAPH-711C +U+7121 # 44-21, CJK UNIFIED IDEOGRAPH-7121 +U+7126 # 30-39, CJK UNIFIED IDEOGRAPH-7126 +U+7136 # 33-19, CJK UNIFIED IDEOGRAPH-7136 +U+713C # 30-38, CJK UNIFIED IDEOGRAPH-713C +U+7149 # 46-91, CJK UNIFIED IDEOGRAPH-7149 +U+714C # 63-74, CJK UNIFIED IDEOGRAPH-714C +U+714E # 32-89, CJK UNIFIED IDEOGRAPH-714E +U+7155 # 63-70, CJK UNIFIED IDEOGRAPH-7155 +U+7156 # 63-75, CJK UNIFIED IDEOGRAPH-7156 +U+7159 # 17-76, CJK UNIFIED IDEOGRAPH-7159 +U+7162 # 63-73, CJK UNIFIED IDEOGRAPH-7162 +U+7164 # 39-65, CJK UNIFIED IDEOGRAPH-7164 +U+7165 # 63-69, CJK UNIFIED IDEOGRAPH-7165 +U+7166 # 63-72, CJK UNIFIED IDEOGRAPH-7166 +U+7167 # 30-40, CJK UNIFIED IDEOGRAPH-7167 +U+7169 # 40-49, CJK UNIFIED IDEOGRAPH-7169 +U+716C # 63-76, CJK UNIFIED IDEOGRAPH-716C +U+716E # 28-49, CJK UNIFIED IDEOGRAPH-716E +U+717D # 32-90, CJK UNIFIED IDEOGRAPH-717D +U+7184 # 63-79, CJK UNIFIED IDEOGRAPH-7184 +U+7188 # 63-71, CJK UNIFIED IDEOGRAPH-7188 +U+718A # 23-07, CJK UNIFIED IDEOGRAPH-718A +U+718F # 63-77, CJK UNIFIED IDEOGRAPH-718F +U+7194 # 45-48, CJK UNIFIED IDEOGRAPH-7194 +U+7195 # 63-80, CJK UNIFIED IDEOGRAPH-7195 +U+7199 # 84-06, CJK UNIFIED IDEOGRAPH-7199 +U+719F # 29-47, CJK UNIFIED IDEOGRAPH-719F +U+71A8 # 63-81, CJK UNIFIED IDEOGRAPH-71A8 +U+71AC # 63-82, CJK UNIFIED IDEOGRAPH-71AC +U+71B1 # 39-14, CJK UNIFIED IDEOGRAPH-71B1 +U+71B9 # 63-84, CJK UNIFIED IDEOGRAPH-71B9 +U+71BE # 63-85, CJK UNIFIED IDEOGRAPH-71BE +U+71C3 # 39-19, CJK UNIFIED IDEOGRAPH-71C3 +U+71C8 # 37-85, CJK UNIFIED IDEOGRAPH-71C8 +U+71C9 # 63-87, CJK UNIFIED IDEOGRAPH-71C9 +U+71CE # 63-89, CJK UNIFIED IDEOGRAPH-71CE +U+71D0 # 46-53, CJK UNIFIED IDEOGRAPH-71D0 +U+71D2 # 63-86, CJK UNIFIED IDEOGRAPH-71D2 +U+71D4 # 63-88, CJK UNIFIED IDEOGRAPH-71D4 +U+71D5 # 17-77, CJK UNIFIED IDEOGRAPH-71D5 +U+71D7 # 63-83, CJK UNIFIED IDEOGRAPH-71D7 +U+71DF # 51-59, CJK UNIFIED IDEOGRAPH-71DF +U+71E0 # 63-90, CJK UNIFIED IDEOGRAPH-71E0 +U+71E5 # 33-71, CJK UNIFIED IDEOGRAPH-71E5 +U+71E6 # 27-24, CJK UNIFIED IDEOGRAPH-71E6 +U+71E7 # 63-92, CJK UNIFIED IDEOGRAPH-71E7 +U+71EC # 63-91, CJK UNIFIED IDEOGRAPH-71EC +U+71ED # 31-04, CJK UNIFIED IDEOGRAPH-71ED +U+71EE # 50-57, CJK UNIFIED IDEOGRAPH-71EE +U+71F5 # 63-93, CJK UNIFIED IDEOGRAPH-71F5 +U+71F9 # 64-01, CJK UNIFIED IDEOGRAPH-71F9 +U+71FB # 63-78, CJK UNIFIED IDEOGRAPH-71FB +U+71FC # 63-94, CJK UNIFIED IDEOGRAPH-71FC +U+71FF # 64-02, CJK UNIFIED IDEOGRAPH-71FF +U+7206 # 39-90, CJK UNIFIED IDEOGRAPH-7206 +U+720D # 64-03, CJK UNIFIED IDEOGRAPH-720D +U+7210 # 64-04, CJK UNIFIED IDEOGRAPH-7210 +U+721B # 64-05, CJK UNIFIED IDEOGRAPH-721B +U+7228 # 64-06, CJK UNIFIED IDEOGRAPH-7228 +U+722A # 36-62, CJK UNIFIED IDEOGRAPH-722A +U+722C # 64-08, CJK UNIFIED IDEOGRAPH-722C +U+722D # 64-07, CJK UNIFIED IDEOGRAPH-722D +U+7230 # 64-09, CJK UNIFIED IDEOGRAPH-7230 +U+7232 # 64-10, CJK UNIFIED IDEOGRAPH-7232 +U+7235 # 28-63, CJK UNIFIED IDEOGRAPH-7235 +U+7236 # 41-67, CJK UNIFIED IDEOGRAPH-7236 +U+723A # 44-76, CJK UNIFIED IDEOGRAPH-723A +U+723B # 64-11, CJK UNIFIED IDEOGRAPH-723B +U+723C # 64-12, CJK UNIFIED IDEOGRAPH-723C +U+723D # 33-54, CJK UNIFIED IDEOGRAPH-723D +U+723E # 28-04, CJK UNIFIED IDEOGRAPH-723E +U+723F # 64-13, CJK UNIFIED IDEOGRAPH-723F +U+7240 # 64-14, CJK UNIFIED IDEOGRAPH-7240 +U+7246 # 64-15, CJK UNIFIED IDEOGRAPH-7246 +U+7247 # 42-50, CJK UNIFIED IDEOGRAPH-7247 +U+7248 # 40-39, CJK UNIFIED IDEOGRAPH-7248 +U+724B # 64-16, CJK UNIFIED IDEOGRAPH-724B +U+724C # 39-55, CJK UNIFIED IDEOGRAPH-724C +U+7252 # 36-13, CJK UNIFIED IDEOGRAPH-7252 +U+7258 # 64-17, CJK UNIFIED IDEOGRAPH-7258 +U+7259 # 18-71, CJK UNIFIED IDEOGRAPH-7259 +U+725B # 21-77, CJK UNIFIED IDEOGRAPH-725B +U+725D # 44-38, CJK UNIFIED IDEOGRAPH-725D +U+725F # 44-22, CJK UNIFIED IDEOGRAPH-725F +U+7261 # 18-20, CJK UNIFIED IDEOGRAPH-7261 +U+7262 # 47-20, CJK UNIFIED IDEOGRAPH-7262 +U+7267 # 43-50, CJK UNIFIED IDEOGRAPH-7267 +U+7269 # 42-10, CJK UNIFIED IDEOGRAPH-7269 +U+7272 # 32-23, CJK UNIFIED IDEOGRAPH-7272 +U+7274 # 64-18, CJK UNIFIED IDEOGRAPH-7274 +U+7279 # 38-35, CJK UNIFIED IDEOGRAPH-7279 +U+727D # 24-03, CJK UNIFIED IDEOGRAPH-727D +U+727E # 64-19, CJK UNIFIED IDEOGRAPH-727E +U+7280 # 26-52, CJK UNIFIED IDEOGRAPH-7280 +U+7281 # 64-21, CJK UNIFIED IDEOGRAPH-7281 +U+7282 # 64-20, CJK UNIFIED IDEOGRAPH-7282 +U+7287 # 64-22, CJK UNIFIED IDEOGRAPH-7287 +U+7292 # 64-23, CJK UNIFIED IDEOGRAPH-7292 +U+7296 # 64-24, CJK UNIFIED IDEOGRAPH-7296 +U+72A0 # 21-30, CJK UNIFIED IDEOGRAPH-72A0 +U+72A2 # 64-25, CJK UNIFIED IDEOGRAPH-72A2 +U+72A7 # 64-26, CJK UNIFIED IDEOGRAPH-72A7 +U+72AC # 24-04, CJK UNIFIED IDEOGRAPH-72AC +U+72AF # 40-40, CJK UNIFIED IDEOGRAPH-72AF +U+72B2 # 64-28, CJK UNIFIED IDEOGRAPH-72B2 +U+72B6 # 30-85, CJK UNIFIED IDEOGRAPH-72B6 +U+72B9 # 64-27, CJK UNIFIED IDEOGRAPH-72B9 +U+72C2 # 22-24, CJK UNIFIED IDEOGRAPH-72C2 +U+72C3 # 64-29, CJK UNIFIED IDEOGRAPH-72C3 +U+72C4 # 64-31, CJK UNIFIED IDEOGRAPH-72C4 +U+72C6 # 64-30, CJK UNIFIED IDEOGRAPH-72C6 +U+72CE # 64-32, CJK UNIFIED IDEOGRAPH-72CE +U+72D0 # 24-49, CJK UNIFIED IDEOGRAPH-72D0 +U+72D2 # 64-33, CJK UNIFIED IDEOGRAPH-72D2 +U+72D7 # 22-73, CJK UNIFIED IDEOGRAPH-72D7 +U+72D9 # 33-32, CJK UNIFIED IDEOGRAPH-72D9 +U+72DB # 25-93, CJK UNIFIED IDEOGRAPH-72DB +U+72E0 # 64-35, CJK UNIFIED IDEOGRAPH-72E0 +U+72E1 # 64-36, CJK UNIFIED IDEOGRAPH-72E1 +U+72E2 # 64-34, CJK UNIFIED IDEOGRAPH-72E2 +U+72E9 # 28-77, CJK UNIFIED IDEOGRAPH-72E9 +U+72EC # 38-40, CJK UNIFIED IDEOGRAPH-72EC +U+72ED # 22-25, CJK UNIFIED IDEOGRAPH-72ED +U+72F7 # 64-38, CJK UNIFIED IDEOGRAPH-72F7 +U+72F8 # 35-12, CJK UNIFIED IDEOGRAPH-72F8 +U+72F9 # 64-37, CJK UNIFIED IDEOGRAPH-72F9 +U+72FC # 47-21, CJK UNIFIED IDEOGRAPH-72FC +U+72FD # 39-66, CJK UNIFIED IDEOGRAPH-72FD +U+730A # 64-41, CJK UNIFIED IDEOGRAPH-730A +U+7316 # 64-43, CJK UNIFIED IDEOGRAPH-7316 +U+7317 # 64-40, CJK UNIFIED IDEOGRAPH-7317 +U+731B # 44-52, CJK UNIFIED IDEOGRAPH-731B +U+731C # 64-42, CJK UNIFIED IDEOGRAPH-731C +U+731D # 64-44, CJK UNIFIED IDEOGRAPH-731D +U+731F # 46-36, CJK UNIFIED IDEOGRAPH-731F +U+7325 # 64-48, CJK UNIFIED IDEOGRAPH-7325 +U+7329 # 64-47, CJK UNIFIED IDEOGRAPH-7329 +U+732A # 35-86, CJK UNIFIED IDEOGRAPH-732A +U+732B # 39-13, CJK UNIFIED IDEOGRAPH-732B +U+732E # 24-05, CJK UNIFIED IDEOGRAPH-732E +U+732F # 64-46, CJK UNIFIED IDEOGRAPH-732F +U+7334 # 64-45, CJK UNIFIED IDEOGRAPH-7334 +U+7336 # 45-17, CJK UNIFIED IDEOGRAPH-7336 +U+7337 # 45-18, CJK UNIFIED IDEOGRAPH-7337 +U+733E # 64-49, CJK UNIFIED IDEOGRAPH-733E +U+733F # 17-78, CJK UNIFIED IDEOGRAPH-733F +U+7344 # 25-86, CJK UNIFIED IDEOGRAPH-7344 +U+7345 # 27-66, CJK UNIFIED IDEOGRAPH-7345 +U+734E # 64-50, CJK UNIFIED IDEOGRAPH-734E +U+734F # 64-51, CJK UNIFIED IDEOGRAPH-734F +U+7357 # 64-53, CJK UNIFIED IDEOGRAPH-7357 +U+7363 # 29-35, CJK UNIFIED IDEOGRAPH-7363 +U+7368 # 64-55, CJK UNIFIED IDEOGRAPH-7368 +U+736A # 64-54, CJK UNIFIED IDEOGRAPH-736A +U+7370 # 64-56, CJK UNIFIED IDEOGRAPH-7370 +U+7372 # 19-45, CJK UNIFIED IDEOGRAPH-7372 +U+7375 # 64-58, CJK UNIFIED IDEOGRAPH-7375 +U+7378 # 64-57, CJK UNIFIED IDEOGRAPH-7378 +U+737A # 64-60, CJK UNIFIED IDEOGRAPH-737A +U+737B # 64-59, CJK UNIFIED IDEOGRAPH-737B +U+7384 # 24-28, CJK UNIFIED IDEOGRAPH-7384 +U+7387 # 46-08, CJK UNIFIED IDEOGRAPH-7387 +U+7389 # 22-44, CJK UNIFIED IDEOGRAPH-7389 +U+738B # 18-06, CJK UNIFIED IDEOGRAPH-738B +U+7396 # 22-74, CJK UNIFIED IDEOGRAPH-7396 +U+73A9 # 20-65, CJK UNIFIED IDEOGRAPH-73A9 +U+73B2 # 46-72, CJK UNIFIED IDEOGRAPH-73B2 +U+73B3 # 64-62, CJK UNIFIED IDEOGRAPH-73B3 +U+73BB # 64-64, CJK UNIFIED IDEOGRAPH-73BB +U+73C0 # 64-65, CJK UNIFIED IDEOGRAPH-73C0 +U+73C2 # 18-49, CJK UNIFIED IDEOGRAPH-73C2 +U+73C8 # 64-61, CJK UNIFIED IDEOGRAPH-73C8 +U+73CA # 27-25, CJK UNIFIED IDEOGRAPH-73CA +U+73CD # 36-33, CJK UNIFIED IDEOGRAPH-73CD +U+73CE # 64-63, CJK UNIFIED IDEOGRAPH-73CE +U+73DE # 64-68, CJK UNIFIED IDEOGRAPH-73DE +U+73E0 # 28-78, CJK UNIFIED IDEOGRAPH-73E0 +U+73E5 # 64-66, CJK UNIFIED IDEOGRAPH-73E5 +U+73EA # 23-30, CJK UNIFIED IDEOGRAPH-73EA +U+73ED # 40-41, CJK UNIFIED IDEOGRAPH-73ED +U+73EE # 64-67, CJK UNIFIED IDEOGRAPH-73EE +U+73F1 # 64-94, CJK UNIFIED IDEOGRAPH-73F1 +U+73F8 # 64-73, CJK UNIFIED IDEOGRAPH-73F8 +U+73FE # 24-29, CJK UNIFIED IDEOGRAPH-73FE +U+7403 # 21-69, CJK UNIFIED IDEOGRAPH-7403 +U+7405 # 64-70, CJK UNIFIED IDEOGRAPH-7405 +U+7406 # 45-93, CJK UNIFIED IDEOGRAPH-7406 +U+7409 # 46-16, CJK UNIFIED IDEOGRAPH-7409 +U+7422 # 34-86, CJK UNIFIED IDEOGRAPH-7422 +U+7425 # 64-72, CJK UNIFIED IDEOGRAPH-7425 +U+7432 # 64-74, CJK UNIFIED IDEOGRAPH-7432 +U+7433 # 46-54, CJK UNIFIED IDEOGRAPH-7433 +U+7434 # 22-55, CJK UNIFIED IDEOGRAPH-7434 +U+7435 # 40-92, CJK UNIFIED IDEOGRAPH-7435 +U+7436 # 39-42, CJK UNIFIED IDEOGRAPH-7436 +U+743A # 64-75, CJK UNIFIED IDEOGRAPH-743A +U+743F # 64-77, CJK UNIFIED IDEOGRAPH-743F +U+7441 # 64-80, CJK UNIFIED IDEOGRAPH-7441 +U+7455 # 64-76, CJK UNIFIED IDEOGRAPH-7455 +U+7459 # 64-79, CJK UNIFIED IDEOGRAPH-7459 +U+745A # 24-74, CJK UNIFIED IDEOGRAPH-745A +U+745B # 17-45, CJK UNIFIED IDEOGRAPH-745B +U+745C # 64-81, CJK UNIFIED IDEOGRAPH-745C +U+745E # 31-80, CJK UNIFIED IDEOGRAPH-745E +U+745F # 64-78, CJK UNIFIED IDEOGRAPH-745F +U+7460 # 46-60, CJK UNIFIED IDEOGRAPH-7460 +U+7463 # 64-84, CJK UNIFIED IDEOGRAPH-7463 +U+7464 # 84-04, CJK UNIFIED IDEOGRAPH-7464 +U+7469 # 64-82, CJK UNIFIED IDEOGRAPH-7469 +U+746A # 64-85, CJK UNIFIED IDEOGRAPH-746A +U+746F # 64-71, CJK UNIFIED IDEOGRAPH-746F +U+7470 # 64-83, CJK UNIFIED IDEOGRAPH-7470 +U+7473 # 26-28, CJK UNIFIED IDEOGRAPH-7473 +U+7476 # 64-86, CJK UNIFIED IDEOGRAPH-7476 +U+747E # 64-87, CJK UNIFIED IDEOGRAPH-747E +U+7483 # 45-94, CJK UNIFIED IDEOGRAPH-7483 +U+748B # 64-88, CJK UNIFIED IDEOGRAPH-748B +U+749E # 64-89, CJK UNIFIED IDEOGRAPH-749E +U+74A2 # 64-69, CJK UNIFIED IDEOGRAPH-74A2 +U+74A7 # 64-90, CJK UNIFIED IDEOGRAPH-74A7 +U+74B0 # 20-36, CJK UNIFIED IDEOGRAPH-74B0 +U+74BD # 28-05, CJK UNIFIED IDEOGRAPH-74BD +U+74CA # 64-91, CJK UNIFIED IDEOGRAPH-74CA +U+74CF # 64-92, CJK UNIFIED IDEOGRAPH-74CF +U+74D4 # 64-93, CJK UNIFIED IDEOGRAPH-74D4 +U+74DC # 17-27, CJK UNIFIED IDEOGRAPH-74DC +U+74E0 # 65-01, CJK UNIFIED IDEOGRAPH-74E0 +U+74E2 # 41-27, CJK UNIFIED IDEOGRAPH-74E2 +U+74E3 # 65-02, CJK UNIFIED IDEOGRAPH-74E3 +U+74E6 # 20-04, CJK UNIFIED IDEOGRAPH-74E6 +U+74E7 # 65-03, CJK UNIFIED IDEOGRAPH-74E7 +U+74E9 # 65-04, CJK UNIFIED IDEOGRAPH-74E9 +U+74EE # 65-05, CJK UNIFIED IDEOGRAPH-74EE +U+74F0 # 65-07, CJK UNIFIED IDEOGRAPH-74F0 +U+74F1 # 65-08, CJK UNIFIED IDEOGRAPH-74F1 +U+74F2 # 65-06, CJK UNIFIED IDEOGRAPH-74F2 +U+74F6 # 41-51, CJK UNIFIED IDEOGRAPH-74F6 +U+74F7 # 65-10, CJK UNIFIED IDEOGRAPH-74F7 +U+74F8 # 65-09, CJK UNIFIED IDEOGRAPH-74F8 +U+7503 # 65-12, CJK UNIFIED IDEOGRAPH-7503 +U+7504 # 65-11, CJK UNIFIED IDEOGRAPH-7504 +U+7505 # 65-13, CJK UNIFIED IDEOGRAPH-7505 +U+750C # 65-14, CJK UNIFIED IDEOGRAPH-750C +U+750D # 65-16, CJK UNIFIED IDEOGRAPH-750D +U+750E # 65-15, CJK UNIFIED IDEOGRAPH-750E +U+7511 # 25-89, CJK UNIFIED IDEOGRAPH-7511 +U+7513 # 65-18, CJK UNIFIED IDEOGRAPH-7513 +U+7515 # 65-17, CJK UNIFIED IDEOGRAPH-7515 +U+7518 # 20-37, CJK UNIFIED IDEOGRAPH-7518 +U+751A # 31-51, CJK UNIFIED IDEOGRAPH-751A +U+751C # 37-28, CJK UNIFIED IDEOGRAPH-751C +U+751E # 65-19, CJK UNIFIED IDEOGRAPH-751E +U+751F # 32-24, CJK UNIFIED IDEOGRAPH-751F +U+7523 # 27-26, CJK UNIFIED IDEOGRAPH-7523 +U+7525 # 17-89, CJK UNIFIED IDEOGRAPH-7525 +U+7526 # 65-20, CJK UNIFIED IDEOGRAPH-7526 +U+7528 # 45-49, CJK UNIFIED IDEOGRAPH-7528 +U+752B # 42-67, CJK UNIFIED IDEOGRAPH-752B +U+752C # 65-21, CJK UNIFIED IDEOGRAPH-752C +U+7530 # 37-36, CJK UNIFIED IDEOGRAPH-7530 +U+7531 # 45-19, CJK UNIFIED IDEOGRAPH-7531 +U+7532 # 25-35, CJK UNIFIED IDEOGRAPH-7532 +U+7533 # 31-29, CJK UNIFIED IDEOGRAPH-7533 +U+7537 # 35-43, CJK UNIFIED IDEOGRAPH-7537 +U+7538 # 50-20, CJK UNIFIED IDEOGRAPH-7538 +U+753A # 36-14, CJK UNIFIED IDEOGRAPH-753A +U+753B # 18-72, CJK UNIFIED IDEOGRAPH-753B +U+753C # 65-22, CJK UNIFIED IDEOGRAPH-753C +U+7544 # 65-23, CJK UNIFIED IDEOGRAPH-7544 +U+7546 # 65-28, CJK UNIFIED IDEOGRAPH-7546 +U+7549 # 65-26, CJK UNIFIED IDEOGRAPH-7549 +U+754A # 65-25, CJK UNIFIED IDEOGRAPH-754A +U+754B # 58-34, CJK UNIFIED IDEOGRAPH-754B +U+754C # 19-06, CJK UNIFIED IDEOGRAPH-754C +U+754D # 65-24, CJK UNIFIED IDEOGRAPH-754D +U+754F # 16-58, CJK UNIFIED IDEOGRAPH-754F +U+7551 # 40-10, CJK UNIFIED IDEOGRAPH-7551 +U+7554 # 40-42, CJK UNIFIED IDEOGRAPH-7554 +U+7559 # 46-17, CJK UNIFIED IDEOGRAPH-7559 +U+755A # 65-29, CJK UNIFIED IDEOGRAPH-755A +U+755B # 65-27, CJK UNIFIED IDEOGRAPH-755B +U+755C # 35-60, CJK UNIFIED IDEOGRAPH-755C +U+755D # 32-06, CJK UNIFIED IDEOGRAPH-755D +U+7560 # 40-11, CJK UNIFIED IDEOGRAPH-7560 +U+7562 # 41-13, CJK UNIFIED IDEOGRAPH-7562 +U+7564 # 65-31, CJK UNIFIED IDEOGRAPH-7564 +U+7565 # 46-12, CJK UNIFIED IDEOGRAPH-7565 +U+7566 # 23-45, CJK UNIFIED IDEOGRAPH-7566 +U+7567 # 65-32, CJK UNIFIED IDEOGRAPH-7567 +U+7569 # 65-30, CJK UNIFIED IDEOGRAPH-7569 +U+756A # 40-54, CJK UNIFIED IDEOGRAPH-756A +U+756B # 65-33, CJK UNIFIED IDEOGRAPH-756B +U+756D # 65-34, CJK UNIFIED IDEOGRAPH-756D +U+7570 # 16-59, CJK UNIFIED IDEOGRAPH-7570 +U+7573 # 30-86, CJK UNIFIED IDEOGRAPH-7573 +U+7574 # 65-39, CJK UNIFIED IDEOGRAPH-7574 +U+7576 # 65-36, CJK UNIFIED IDEOGRAPH-7576 +U+7577 # 38-77, CJK UNIFIED IDEOGRAPH-7577 +U+7578 # 65-35, CJK UNIFIED IDEOGRAPH-7578 +U+757F # 21-06, CJK UNIFIED IDEOGRAPH-757F +U+7582 # 65-42, CJK UNIFIED IDEOGRAPH-7582 +U+7586 # 65-37, CJK UNIFIED IDEOGRAPH-7586 +U+7587 # 65-38, CJK UNIFIED IDEOGRAPH-7587 +U+7589 # 65-41, CJK UNIFIED IDEOGRAPH-7589 +U+758A # 65-40, CJK UNIFIED IDEOGRAPH-758A +U+758B # 41-05, CJK UNIFIED IDEOGRAPH-758B +U+758E # 33-34, CJK UNIFIED IDEOGRAPH-758E +U+758F # 33-33, CJK UNIFIED IDEOGRAPH-758F +U+7591 # 21-31, CJK UNIFIED IDEOGRAPH-7591 +U+7594 # 65-43, CJK UNIFIED IDEOGRAPH-7594 +U+759A # 65-44, CJK UNIFIED IDEOGRAPH-759A +U+759D # 65-45, CJK UNIFIED IDEOGRAPH-759D +U+75A3 # 65-47, CJK UNIFIED IDEOGRAPH-75A3 +U+75A5 # 65-46, CJK UNIFIED IDEOGRAPH-75A5 +U+75AB # 17-54, CJK UNIFIED IDEOGRAPH-75AB +U+75B1 # 65-55, CJK UNIFIED IDEOGRAPH-75B1 +U+75B2 # 40-72, CJK UNIFIED IDEOGRAPH-75B2 +U+75B3 # 65-49, CJK UNIFIED IDEOGRAPH-75B3 +U+75B5 # 65-51, CJK UNIFIED IDEOGRAPH-75B5 +U+75B8 # 65-53, CJK UNIFIED IDEOGRAPH-75B8 +U+75B9 # 31-30, CJK UNIFIED IDEOGRAPH-75B9 +U+75BC # 65-54, CJK UNIFIED IDEOGRAPH-75BC +U+75BD # 65-52, CJK UNIFIED IDEOGRAPH-75BD +U+75BE # 28-32, CJK UNIFIED IDEOGRAPH-75BE +U+75C2 # 65-48, CJK UNIFIED IDEOGRAPH-75C2 +U+75C3 # 65-50, CJK UNIFIED IDEOGRAPH-75C3 +U+75C5 # 41-34, CJK UNIFIED IDEOGRAPH-75C5 +U+75C7 # 30-41, CJK UNIFIED IDEOGRAPH-75C7 +U+75CA # 65-57, CJK UNIFIED IDEOGRAPH-75CA +U+75CD # 65-56, CJK UNIFIED IDEOGRAPH-75CD +U+75D2 # 65-58, CJK UNIFIED IDEOGRAPH-75D2 +U+75D4 # 28-06, CJK UNIFIED IDEOGRAPH-75D4 +U+75D5 # 26-15, CJK UNIFIED IDEOGRAPH-75D5 +U+75D8 # 37-87, CJK UNIFIED IDEOGRAPH-75D8 +U+75D9 # 65-59, CJK UNIFIED IDEOGRAPH-75D9 +U+75DB # 36-43, CJK UNIFIED IDEOGRAPH-75DB +U+75DE # 65-61, CJK UNIFIED IDEOGRAPH-75DE +U+75E2 # 46-01, CJK UNIFIED IDEOGRAPH-75E2 +U+75E3 # 65-60, CJK UNIFIED IDEOGRAPH-75E3 +U+75E9 # 33-73, CJK UNIFIED IDEOGRAPH-75E9 +U+75F0 # 65-66, CJK UNIFIED IDEOGRAPH-75F0 +U+75F2 # 65-68, CJK UNIFIED IDEOGRAPH-75F2 +U+75F3 # 65-69, CJK UNIFIED IDEOGRAPH-75F3 +U+75F4 # 35-52, CJK UNIFIED IDEOGRAPH-75F4 +U+75FA # 65-67, CJK UNIFIED IDEOGRAPH-75FA +U+75FC # 65-64, CJK UNIFIED IDEOGRAPH-75FC +U+75FE # 65-62, CJK UNIFIED IDEOGRAPH-75FE +U+75FF # 65-63, CJK UNIFIED IDEOGRAPH-75FF +U+7601 # 65-65, CJK UNIFIED IDEOGRAPH-7601 +U+7609 # 65-72, CJK UNIFIED IDEOGRAPH-7609 +U+760B # 65-70, CJK UNIFIED IDEOGRAPH-760B +U+760D # 65-71, CJK UNIFIED IDEOGRAPH-760D +U+761F # 65-73, CJK UNIFIED IDEOGRAPH-761F +U+7620 # 65-75, CJK UNIFIED IDEOGRAPH-7620 +U+7621 # 65-76, CJK UNIFIED IDEOGRAPH-7621 +U+7622 # 65-77, CJK UNIFIED IDEOGRAPH-7622 +U+7624 # 65-78, CJK UNIFIED IDEOGRAPH-7624 +U+7627 # 65-74, CJK UNIFIED IDEOGRAPH-7627 +U+7630 # 65-80, CJK UNIFIED IDEOGRAPH-7630 +U+7634 # 65-79, CJK UNIFIED IDEOGRAPH-7634 +U+763B # 65-81, CJK UNIFIED IDEOGRAPH-763B +U+7642 # 46-37, CJK UNIFIED IDEOGRAPH-7642 +U+7646 # 65-84, CJK UNIFIED IDEOGRAPH-7646 +U+7647 # 65-82, CJK UNIFIED IDEOGRAPH-7647 +U+7648 # 65-83, CJK UNIFIED IDEOGRAPH-7648 +U+764C # 20-66, CJK UNIFIED IDEOGRAPH-764C +U+7652 # 44-94, CJK UNIFIED IDEOGRAPH-7652 +U+7656 # 42-42, CJK UNIFIED IDEOGRAPH-7656 +U+7658 # 65-86, CJK UNIFIED IDEOGRAPH-7658 +U+765C # 65-85, CJK UNIFIED IDEOGRAPH-765C +U+7661 # 65-87, CJK UNIFIED IDEOGRAPH-7661 +U+7662 # 65-88, CJK UNIFIED IDEOGRAPH-7662 +U+7667 # 65-92, CJK UNIFIED IDEOGRAPH-7667 +U+7668 # 65-89, CJK UNIFIED IDEOGRAPH-7668 +U+7669 # 65-90, CJK UNIFIED IDEOGRAPH-7669 +U+766A # 65-91, CJK UNIFIED IDEOGRAPH-766A +U+766C # 65-93, CJK UNIFIED IDEOGRAPH-766C +U+7670 # 65-94, CJK UNIFIED IDEOGRAPH-7670 +U+7672 # 66-01, CJK UNIFIED IDEOGRAPH-7672 +U+7676 # 66-02, CJK UNIFIED IDEOGRAPH-7676 +U+7678 # 66-03, CJK UNIFIED IDEOGRAPH-7678 +U+767A # 40-15, CJK UNIFIED IDEOGRAPH-767A +U+767B # 37-48, CJK UNIFIED IDEOGRAPH-767B +U+767C # 66-04, CJK UNIFIED IDEOGRAPH-767C +U+767D # 39-82, CJK UNIFIED IDEOGRAPH-767D +U+767E # 41-20, CJK UNIFIED IDEOGRAPH-767E +U+7680 # 66-05, CJK UNIFIED IDEOGRAPH-7680 +U+7683 # 66-06, CJK UNIFIED IDEOGRAPH-7683 +U+7684 # 37-10, CJK UNIFIED IDEOGRAPH-7684 +U+7686 # 19-07, CJK UNIFIED IDEOGRAPH-7686 +U+7687 # 25-36, CJK UNIFIED IDEOGRAPH-7687 +U+7688 # 66-07, CJK UNIFIED IDEOGRAPH-7688 +U+768B # 66-08, CJK UNIFIED IDEOGRAPH-768B +U+768E # 66-09, CJK UNIFIED IDEOGRAPH-768E +U+7690 # 27-09, CJK UNIFIED IDEOGRAPH-7690 +U+7693 # 66-11, CJK UNIFIED IDEOGRAPH-7693 +U+7696 # 66-10, CJK UNIFIED IDEOGRAPH-7696 +U+7699 # 66-12, CJK UNIFIED IDEOGRAPH-7699 +U+769A # 66-13, CJK UNIFIED IDEOGRAPH-769A +U+76AE # 40-73, CJK UNIFIED IDEOGRAPH-76AE +U+76B0 # 66-14, CJK UNIFIED IDEOGRAPH-76B0 +U+76B4 # 66-15, CJK UNIFIED IDEOGRAPH-76B4 +U+76B7 # 83-73, CJK UNIFIED IDEOGRAPH-76B7 +U+76B8 # 66-16, CJK UNIFIED IDEOGRAPH-76B8 +U+76B9 # 66-17, CJK UNIFIED IDEOGRAPH-76B9 +U+76BA # 66-18, CJK UNIFIED IDEOGRAPH-76BA +U+76BF # 27-14, CJK UNIFIED IDEOGRAPH-76BF +U+76C2 # 66-19, CJK UNIFIED IDEOGRAPH-76C2 +U+76C3 # 39-54, CJK UNIFIED IDEOGRAPH-76C3 +U+76C6 # 43-63, CJK UNIFIED IDEOGRAPH-76C6 +U+76C8 # 17-46, CJK UNIFIED IDEOGRAPH-76C8 +U+76CA # 17-55, CJK UNIFIED IDEOGRAPH-76CA +U+76CD # 66-20, CJK UNIFIED IDEOGRAPH-76CD +U+76D2 # 66-22, CJK UNIFIED IDEOGRAPH-76D2 +U+76D6 # 66-21, CJK UNIFIED IDEOGRAPH-76D6 +U+76D7 # 37-80, CJK UNIFIED IDEOGRAPH-76D7 +U+76DB # 32-25, CJK UNIFIED IDEOGRAPH-76DB +U+76DC # 61-25, CJK UNIFIED IDEOGRAPH-76DC +U+76DE # 66-23, CJK UNIFIED IDEOGRAPH-76DE +U+76DF # 44-33, CJK UNIFIED IDEOGRAPH-76DF +U+76E1 # 66-24, CJK UNIFIED IDEOGRAPH-76E1 +U+76E3 # 20-38, CJK UNIFIED IDEOGRAPH-76E3 +U+76E4 # 40-55, CJK UNIFIED IDEOGRAPH-76E4 +U+76E5 # 66-25, CJK UNIFIED IDEOGRAPH-76E5 +U+76E7 # 66-26, CJK UNIFIED IDEOGRAPH-76E7 +U+76EA # 66-27, CJK UNIFIED IDEOGRAPH-76EA +U+76EE # 44-60, CJK UNIFIED IDEOGRAPH-76EE +U+76F2 # 44-53, CJK UNIFIED IDEOGRAPH-76F2 +U+76F4 # 36-30, CJK UNIFIED IDEOGRAPH-76F4 +U+76F8 # 33-74, CJK UNIFIED IDEOGRAPH-76F8 +U+76FB # 66-29, CJK UNIFIED IDEOGRAPH-76FB +U+76FE # 29-66, CJK UNIFIED IDEOGRAPH-76FE +U+7701 # 30-42, CJK UNIFIED IDEOGRAPH-7701 +U+7704 # 66-32, CJK UNIFIED IDEOGRAPH-7704 +U+7707 # 66-31, CJK UNIFIED IDEOGRAPH-7707 +U+7708 # 66-30, CJK UNIFIED IDEOGRAPH-7708 +U+7709 # 40-93, CJK UNIFIED IDEOGRAPH-7709 +U+770B # 20-39, CJK UNIFIED IDEOGRAPH-770B +U+770C # 24-09, CJK UNIFIED IDEOGRAPH-770C +U+771B # 66-38, CJK UNIFIED IDEOGRAPH-771B +U+771E # 66-35, CJK UNIFIED IDEOGRAPH-771E +U+771F # 31-31, CJK UNIFIED IDEOGRAPH-771F +U+7720 # 44-18, CJK UNIFIED IDEOGRAPH-7720 +U+7724 # 66-34, CJK UNIFIED IDEOGRAPH-7724 +U+7725 # 66-36, CJK UNIFIED IDEOGRAPH-7725 +U+7726 # 66-37, CJK UNIFIED IDEOGRAPH-7726 +U+7729 # 66-33, CJK UNIFIED IDEOGRAPH-7729 +U+7737 # 66-39, CJK UNIFIED IDEOGRAPH-7737 +U+7738 # 66-40, CJK UNIFIED IDEOGRAPH-7738 +U+773A # 36-15, CJK UNIFIED IDEOGRAPH-773A +U+773C # 20-67, CJK UNIFIED IDEOGRAPH-773C +U+7740 # 35-69, CJK UNIFIED IDEOGRAPH-7740 +U+7747 # 66-41, CJK UNIFIED IDEOGRAPH-7747 +U+775A # 66-42, CJK UNIFIED IDEOGRAPH-775A +U+775B # 66-45, CJK UNIFIED IDEOGRAPH-775B +U+7761 # 31-71, CJK UNIFIED IDEOGRAPH-7761 +U+7763 # 38-36, CJK UNIFIED IDEOGRAPH-7763 +U+7765 # 66-46, CJK UNIFIED IDEOGRAPH-7765 +U+7766 # 43-51, CJK UNIFIED IDEOGRAPH-7766 +U+7768 # 66-43, CJK UNIFIED IDEOGRAPH-7768 +U+776B # 66-44, CJK UNIFIED IDEOGRAPH-776B +U+7779 # 66-49, CJK UNIFIED IDEOGRAPH-7779 +U+777E # 66-48, CJK UNIFIED IDEOGRAPH-777E +U+777F # 66-47, CJK UNIFIED IDEOGRAPH-777F +U+778B # 66-51, CJK UNIFIED IDEOGRAPH-778B +U+778E # 66-50, CJK UNIFIED IDEOGRAPH-778E +U+7791 # 66-52, CJK UNIFIED IDEOGRAPH-7791 +U+779E # 66-54, CJK UNIFIED IDEOGRAPH-779E +U+77A0 # 66-53, CJK UNIFIED IDEOGRAPH-77A0 +U+77A5 # 42-45, CJK UNIFIED IDEOGRAPH-77A5 +U+77AC # 29-54, CJK UNIFIED IDEOGRAPH-77AC +U+77AD # 46-38, CJK UNIFIED IDEOGRAPH-77AD +U+77B0 # 66-55, CJK UNIFIED IDEOGRAPH-77B0 +U+77B3 # 38-23, CJK UNIFIED IDEOGRAPH-77B3 +U+77B6 # 66-56, CJK UNIFIED IDEOGRAPH-77B6 +U+77B9 # 66-57, CJK UNIFIED IDEOGRAPH-77B9 +U+77BB # 66-61, CJK UNIFIED IDEOGRAPH-77BB +U+77BC # 66-59, CJK UNIFIED IDEOGRAPH-77BC +U+77BD # 66-60, CJK UNIFIED IDEOGRAPH-77BD +U+77BF # 66-58, CJK UNIFIED IDEOGRAPH-77BF +U+77C7 # 66-62, CJK UNIFIED IDEOGRAPH-77C7 +U+77CD # 66-63, CJK UNIFIED IDEOGRAPH-77CD +U+77D7 # 66-64, CJK UNIFIED IDEOGRAPH-77D7 +U+77DA # 66-65, CJK UNIFIED IDEOGRAPH-77DA +U+77DB # 44-23, CJK UNIFIED IDEOGRAPH-77DB +U+77DC # 66-66, CJK UNIFIED IDEOGRAPH-77DC +U+77E2 # 44-80, CJK UNIFIED IDEOGRAPH-77E2 +U+77E3 # 66-67, CJK UNIFIED IDEOGRAPH-77E3 +U+77E5 # 35-46, CJK UNIFIED IDEOGRAPH-77E5 +U+77E7 # 39-74, CJK UNIFIED IDEOGRAPH-77E7 +U+77E9 # 22-75, CJK UNIFIED IDEOGRAPH-77E9 +U+77ED # 35-27, CJK UNIFIED IDEOGRAPH-77ED +U+77EE # 66-68, CJK UNIFIED IDEOGRAPH-77EE +U+77EF # 22-26, CJK UNIFIED IDEOGRAPH-77EF +U+77F3 # 32-48, CJK UNIFIED IDEOGRAPH-77F3 +U+77FC # 66-69, CJK UNIFIED IDEOGRAPH-77FC +U+7802 # 26-29, CJK UNIFIED IDEOGRAPH-7802 +U+780C # 66-70, CJK UNIFIED IDEOGRAPH-780C +U+7812 # 66-71, CJK UNIFIED IDEOGRAPH-7812 +U+7814 # 24-06, CJK UNIFIED IDEOGRAPH-7814 +U+7815 # 26-53, CJK UNIFIED IDEOGRAPH-7815 +U+7820 # 66-73, CJK UNIFIED IDEOGRAPH-7820 +U+7825 # 37-54, CJK UNIFIED IDEOGRAPH-7825 +U+7826 # 26-54, CJK UNIFIED IDEOGRAPH-7826 +U+7827 # 21-46, CJK UNIFIED IDEOGRAPH-7827 +U+7832 # 43-04, CJK UNIFIED IDEOGRAPH-7832 +U+7834 # 39-43, CJK UNIFIED IDEOGRAPH-7834 +U+783A # 37-55, CJK UNIFIED IDEOGRAPH-783A +U+783F # 25-60, CJK UNIFIED IDEOGRAPH-783F +U+7845 # 66-75, CJK UNIFIED IDEOGRAPH-7845 +U+785D # 30-43, CJK UNIFIED IDEOGRAPH-785D +U+786B # 46-18, CJK UNIFIED IDEOGRAPH-786B +U+786C # 25-37, CJK UNIFIED IDEOGRAPH-786C +U+786F # 24-07, CJK UNIFIED IDEOGRAPH-786F +U+7872 # 40-03, CJK UNIFIED IDEOGRAPH-7872 +U+7874 # 66-77, CJK UNIFIED IDEOGRAPH-7874 +U+787C # 66-79, CJK UNIFIED IDEOGRAPH-787C +U+7881 # 24-75, CJK UNIFIED IDEOGRAPH-7881 +U+7886 # 66-78, CJK UNIFIED IDEOGRAPH-7886 +U+7887 # 36-86, CJK UNIFIED IDEOGRAPH-7887 +U+788C # 66-81, CJK UNIFIED IDEOGRAPH-788C +U+788D # 19-23, CJK UNIFIED IDEOGRAPH-788D +U+788E # 66-76, CJK UNIFIED IDEOGRAPH-788E +U+7891 # 40-74, CJK UNIFIED IDEOGRAPH-7891 +U+7893 # 17-16, CJK UNIFIED IDEOGRAPH-7893 +U+7895 # 26-76, CJK UNIFIED IDEOGRAPH-7895 +U+7897 # 47-50, CJK UNIFIED IDEOGRAPH-7897 +U+789A # 66-80, CJK UNIFIED IDEOGRAPH-789A +U+78A3 # 66-82, CJK UNIFIED IDEOGRAPH-78A3 +U+78A7 # 42-43, CJK UNIFIED IDEOGRAPH-78A7 +U+78A9 # 32-57, CJK UNIFIED IDEOGRAPH-78A9 +U+78AA # 66-84, CJK UNIFIED IDEOGRAPH-78AA +U+78AF # 66-85, CJK UNIFIED IDEOGRAPH-78AF +U+78B5 # 66-83, CJK UNIFIED IDEOGRAPH-78B5 +U+78BA # 19-46, CJK UNIFIED IDEOGRAPH-78BA +U+78BC # 66-91, CJK UNIFIED IDEOGRAPH-78BC +U+78BE # 66-90, CJK UNIFIED IDEOGRAPH-78BE +U+78C1 # 28-07, CJK UNIFIED IDEOGRAPH-78C1 +U+78C5 # 66-92, CJK UNIFIED IDEOGRAPH-78C5 +U+78C6 # 66-87, CJK UNIFIED IDEOGRAPH-78C6 +U+78CA # 66-93, CJK UNIFIED IDEOGRAPH-78CA +U+78CB # 66-88, CJK UNIFIED IDEOGRAPH-78CB +U+78D0 # 40-56, CJK UNIFIED IDEOGRAPH-78D0 +U+78D1 # 66-86, CJK UNIFIED IDEOGRAPH-78D1 +U+78D4 # 66-89, CJK UNIFIED IDEOGRAPH-78D4 +U+78DA # 67-02, CJK UNIFIED IDEOGRAPH-78DA +U+78E7 # 67-01, CJK UNIFIED IDEOGRAPH-78E7 +U+78E8 # 43-65, CJK UNIFIED IDEOGRAPH-78E8 +U+78EC # 66-94, CJK UNIFIED IDEOGRAPH-78EC +U+78EF # 16-75, CJK UNIFIED IDEOGRAPH-78EF +U+78F4 # 67-04, CJK UNIFIED IDEOGRAPH-78F4 +U+78FD # 67-03, CJK UNIFIED IDEOGRAPH-78FD +U+7901 # 30-44, CJK UNIFIED IDEOGRAPH-7901 +U+7907 # 67-05, CJK UNIFIED IDEOGRAPH-7907 +U+790E # 33-35, CJK UNIFIED IDEOGRAPH-790E +U+7911 # 67-07, CJK UNIFIED IDEOGRAPH-7911 +U+7912 # 67-06, CJK UNIFIED IDEOGRAPH-7912 +U+7919 # 67-08, CJK UNIFIED IDEOGRAPH-7919 +U+7926 # 66-72, CJK UNIFIED IDEOGRAPH-7926 +U+792A # 66-74, CJK UNIFIED IDEOGRAPH-792A +U+792B # 67-10, CJK UNIFIED IDEOGRAPH-792B +U+792C # 67-09, CJK UNIFIED IDEOGRAPH-792C +U+793A # 28-08, CJK UNIFIED IDEOGRAPH-793A +U+793C # 46-73, CJK UNIFIED IDEOGRAPH-793C +U+793E # 28-50, CJK UNIFIED IDEOGRAPH-793E +U+7940 # 67-11, CJK UNIFIED IDEOGRAPH-7940 +U+7941 # 23-23, CJK UNIFIED IDEOGRAPH-7941 +U+7947 # 21-32, CJK UNIFIED IDEOGRAPH-7947 +U+7948 # 21-07, CJK UNIFIED IDEOGRAPH-7948 +U+7949 # 27-67, CJK UNIFIED IDEOGRAPH-7949 +U+7950 # 45-20, CJK UNIFIED IDEOGRAPH-7950 +U+7953 # 67-17, CJK UNIFIED IDEOGRAPH-7953 +U+7955 # 67-16, CJK UNIFIED IDEOGRAPH-7955 +U+7956 # 33-36, CJK UNIFIED IDEOGRAPH-7956 +U+7957 # 67-13, CJK UNIFIED IDEOGRAPH-7957 +U+795A # 67-15, CJK UNIFIED IDEOGRAPH-795A +U+795D # 29-43, CJK UNIFIED IDEOGRAPH-795D +U+795E # 31-32, CJK UNIFIED IDEOGRAPH-795E +U+795F # 67-14, CJK UNIFIED IDEOGRAPH-795F +U+7960 # 67-12, CJK UNIFIED IDEOGRAPH-7960 +U+7962 # 39-10, CJK UNIFIED IDEOGRAPH-7962 +U+7965 # 30-45, CJK UNIFIED IDEOGRAPH-7965 +U+7968 # 41-28, CJK UNIFIED IDEOGRAPH-7968 +U+796D # 26-55, CJK UNIFIED IDEOGRAPH-796D +U+7977 # 37-88, CJK UNIFIED IDEOGRAPH-7977 +U+797A # 67-18, CJK UNIFIED IDEOGRAPH-797A +U+797F # 67-19, CJK UNIFIED IDEOGRAPH-797F +U+7980 # 67-41, CJK UNIFIED IDEOGRAPH-7980 +U+7981 # 22-56, CJK UNIFIED IDEOGRAPH-7981 +U+7984 # 47-29, CJK UNIFIED IDEOGRAPH-7984 +U+7985 # 33-21, CJK UNIFIED IDEOGRAPH-7985 +U+798A # 67-20, CJK UNIFIED IDEOGRAPH-798A +U+798D # 18-50, CJK UNIFIED IDEOGRAPH-798D +U+798E # 36-87, CJK UNIFIED IDEOGRAPH-798E +U+798F # 42-01, CJK UNIFIED IDEOGRAPH-798F +U+799D # 67-21, CJK UNIFIED IDEOGRAPH-799D +U+79A6 # 21-90, CJK UNIFIED IDEOGRAPH-79A6 +U+79A7 # 67-22, CJK UNIFIED IDEOGRAPH-79A7 +U+79AA # 67-24, CJK UNIFIED IDEOGRAPH-79AA +U+79AE # 67-25, CJK UNIFIED IDEOGRAPH-79AE +U+79B0 # 39-09, CJK UNIFIED IDEOGRAPH-79B0 +U+79B3 # 67-26, CJK UNIFIED IDEOGRAPH-79B3 +U+79B9 # 67-27, CJK UNIFIED IDEOGRAPH-79B9 +U+79BA # 67-28, CJK UNIFIED IDEOGRAPH-79BA +U+79BD # 22-57, CJK UNIFIED IDEOGRAPH-79BD +U+79BE # 18-51, CJK UNIFIED IDEOGRAPH-79BE +U+79BF # 38-37, CJK UNIFIED IDEOGRAPH-79BF +U+79C0 # 29-08, CJK UNIFIED IDEOGRAPH-79C0 +U+79C1 # 27-68, CJK UNIFIED IDEOGRAPH-79C1 +U+79C9 # 67-29, CJK UNIFIED IDEOGRAPH-79C9 +U+79CB # 29-09, CJK UNIFIED IDEOGRAPH-79CB +U+79D1 # 18-42, CJK UNIFIED IDEOGRAPH-79D1 +U+79D2 # 41-35, CJK UNIFIED IDEOGRAPH-79D2 +U+79D5 # 67-30, CJK UNIFIED IDEOGRAPH-79D5 +U+79D8 # 40-75, CJK UNIFIED IDEOGRAPH-79D8 +U+79DF # 33-37, CJK UNIFIED IDEOGRAPH-79DF +U+79E1 # 67-33, CJK UNIFIED IDEOGRAPH-79E1 +U+79E3 # 67-34, CJK UNIFIED IDEOGRAPH-79E3 +U+79E4 # 39-73, CJK UNIFIED IDEOGRAPH-79E4 +U+79E6 # 31-33, CJK UNIFIED IDEOGRAPH-79E6 +U+79E7 # 67-31, CJK UNIFIED IDEOGRAPH-79E7 +U+79E9 # 35-65, CJK UNIFIED IDEOGRAPH-79E9 +U+79EC # 67-32, CJK UNIFIED IDEOGRAPH-79EC +U+79F0 # 30-46, CJK UNIFIED IDEOGRAPH-79F0 +U+79FB # 16-60, CJK UNIFIED IDEOGRAPH-79FB +U+7A00 # 21-09, CJK UNIFIED IDEOGRAPH-7A00 +U+7A08 # 67-35, CJK UNIFIED IDEOGRAPH-7A08 +U+7A0B # 36-88, CJK UNIFIED IDEOGRAPH-7A0B +U+7A0D # 67-36, CJK UNIFIED IDEOGRAPH-7A0D +U+7A0E # 32-39, CJK UNIFIED IDEOGRAPH-7A0E +U+7A14 # 44-13, CJK UNIFIED IDEOGRAPH-7A14 +U+7A17 # 41-03, CJK UNIFIED IDEOGRAPH-7A17 +U+7A18 # 67-37, CJK UNIFIED IDEOGRAPH-7A18 +U+7A19 # 67-38, CJK UNIFIED IDEOGRAPH-7A19 +U+7A1A # 35-53, CJK UNIFIED IDEOGRAPH-7A1A +U+7A1C # 46-39, CJK UNIFIED IDEOGRAPH-7A1C +U+7A1F # 67-40, CJK UNIFIED IDEOGRAPH-7A1F +U+7A20 # 67-39, CJK UNIFIED IDEOGRAPH-7A20 +U+7A2E # 28-79, CJK UNIFIED IDEOGRAPH-7A2E +U+7A31 # 67-42, CJK UNIFIED IDEOGRAPH-7A31 +U+7A32 # 16-80, CJK UNIFIED IDEOGRAPH-7A32 +U+7A37 # 67-45, CJK UNIFIED IDEOGRAPH-7A37 +U+7A3B # 67-43, CJK UNIFIED IDEOGRAPH-7A3B +U+7A3C # 18-52, CJK UNIFIED IDEOGRAPH-7A3C +U+7A3D # 23-46, CJK UNIFIED IDEOGRAPH-7A3D +U+7A3E # 67-44, CJK UNIFIED IDEOGRAPH-7A3E +U+7A3F # 25-38, CJK UNIFIED IDEOGRAPH-7A3F +U+7A40 # 25-82, CJK UNIFIED IDEOGRAPH-7A40 +U+7A42 # 42-70, CJK UNIFIED IDEOGRAPH-7A42 +U+7A43 # 67-46, CJK UNIFIED IDEOGRAPH-7A43 +U+7A46 # 43-52, CJK UNIFIED IDEOGRAPH-7A46 +U+7A49 # 67-48, CJK UNIFIED IDEOGRAPH-7A49 +U+7A4D # 32-49, CJK UNIFIED IDEOGRAPH-7A4D +U+7A4E # 17-47, CJK UNIFIED IDEOGRAPH-7A4E +U+7A4F # 18-26, CJK UNIFIED IDEOGRAPH-7A4F +U+7A50 # 16-12, CJK UNIFIED IDEOGRAPH-7A50 +U+7A57 # 67-47, CJK UNIFIED IDEOGRAPH-7A57 +U+7A61 # 67-49, CJK UNIFIED IDEOGRAPH-7A61 +U+7A62 # 67-50, CJK UNIFIED IDEOGRAPH-7A62 +U+7A63 # 30-87, CJK UNIFIED IDEOGRAPH-7A63 +U+7A69 # 67-51, CJK UNIFIED IDEOGRAPH-7A69 +U+7A6B # 19-47, CJK UNIFIED IDEOGRAPH-7A6B +U+7A70 # 67-53, CJK UNIFIED IDEOGRAPH-7A70 +U+7A74 # 23-74, CJK UNIFIED IDEOGRAPH-7A74 +U+7A76 # 21-70, CJK UNIFIED IDEOGRAPH-7A76 +U+7A79 # 67-54, CJK UNIFIED IDEOGRAPH-7A79 +U+7A7A # 22-85, CJK UNIFIED IDEOGRAPH-7A7A +U+7A7D # 67-55, CJK UNIFIED IDEOGRAPH-7A7D +U+7A7F # 32-92, CJK UNIFIED IDEOGRAPH-7A7F +U+7A81 # 38-45, CJK UNIFIED IDEOGRAPH-7A81 +U+7A83 # 32-64, CJK UNIFIED IDEOGRAPH-7A83 +U+7A84 # 26-85, CJK UNIFIED IDEOGRAPH-7A84 +U+7A88 # 67-56, CJK UNIFIED IDEOGRAPH-7A88 +U+7A92 # 35-66, CJK UNIFIED IDEOGRAPH-7A92 +U+7A93 # 33-75, CJK UNIFIED IDEOGRAPH-7A93 +U+7A95 # 67-58, CJK UNIFIED IDEOGRAPH-7A95 +U+7A96 # 67-60, CJK UNIFIED IDEOGRAPH-7A96 +U+7A97 # 67-57, CJK UNIFIED IDEOGRAPH-7A97 +U+7A98 # 67-59, CJK UNIFIED IDEOGRAPH-7A98 +U+7A9F # 23-02, CJK UNIFIED IDEOGRAPH-7A9F +U+7AA9 # 67-61, CJK UNIFIED IDEOGRAPH-7AA9 +U+7AAA # 23-06, CJK UNIFIED IDEOGRAPH-7AAA +U+7AAE # 21-71, CJK UNIFIED IDEOGRAPH-7AAE +U+7AAF # 45-50, CJK UNIFIED IDEOGRAPH-7AAF +U+7AB0 # 67-63, CJK UNIFIED IDEOGRAPH-7AB0 +U+7AB6 # 67-64, CJK UNIFIED IDEOGRAPH-7AB6 +U+7ABA # 17-14, CJK UNIFIED IDEOGRAPH-7ABA +U+7ABF # 67-67, CJK UNIFIED IDEOGRAPH-7ABF +U+7AC3 # 19-86, CJK UNIFIED IDEOGRAPH-7AC3 +U+7AC4 # 67-66, CJK UNIFIED IDEOGRAPH-7AC4 +U+7AC5 # 67-65, CJK UNIFIED IDEOGRAPH-7AC5 +U+7AC7 # 67-69, CJK UNIFIED IDEOGRAPH-7AC7 +U+7AC8 # 67-62, CJK UNIFIED IDEOGRAPH-7AC8 +U+7ACA # 67-70, CJK UNIFIED IDEOGRAPH-7ACA +U+7ACB # 46-09, CJK UNIFIED IDEOGRAPH-7ACB +U+7ACD # 67-71, CJK UNIFIED IDEOGRAPH-7ACD +U+7ACF # 67-72, CJK UNIFIED IDEOGRAPH-7ACF +U+7AD2 # 52-84, CJK UNIFIED IDEOGRAPH-7AD2 +U+7AD3 # 67-74, CJK UNIFIED IDEOGRAPH-7AD3 +U+7AD5 # 67-73, CJK UNIFIED IDEOGRAPH-7AD5 +U+7AD9 # 67-75, CJK UNIFIED IDEOGRAPH-7AD9 +U+7ADA # 67-76, CJK UNIFIED IDEOGRAPH-7ADA +U+7ADC # 46-21, CJK UNIFIED IDEOGRAPH-7ADC +U+7ADD # 67-77, CJK UNIFIED IDEOGRAPH-7ADD +U+7ADF # 80-79, CJK UNIFIED IDEOGRAPH-7ADF +U+7AE0 # 30-47, CJK UNIFIED IDEOGRAPH-7AE0 +U+7AE1 # 67-78, CJK UNIFIED IDEOGRAPH-7AE1 +U+7AE2 # 67-79, CJK UNIFIED IDEOGRAPH-7AE2 +U+7AE3 # 29-55, CJK UNIFIED IDEOGRAPH-7AE3 +U+7AE5 # 38-24, CJK UNIFIED IDEOGRAPH-7AE5 +U+7AE6 # 67-80, CJK UNIFIED IDEOGRAPH-7AE6 +U+7AEA # 35-08, CJK UNIFIED IDEOGRAPH-7AEA +U+7AED # 67-81, CJK UNIFIED IDEOGRAPH-7AED +U+7AEF # 35-28, CJK UNIFIED IDEOGRAPH-7AEF +U+7AF0 # 67-82, CJK UNIFIED IDEOGRAPH-7AF0 +U+7AF6 # 22-05, CJK UNIFIED IDEOGRAPH-7AF6 +U+7AF8 # 49-31, CJK UNIFIED IDEOGRAPH-7AF8 +U+7AF9 # 35-61, CJK UNIFIED IDEOGRAPH-7AF9 +U+7AFA # 28-19, CJK UNIFIED IDEOGRAPH-7AFA +U+7AFF # 20-40, CJK UNIFIED IDEOGRAPH-7AFF +U+7B02 # 67-83, CJK UNIFIED IDEOGRAPH-7B02 +U+7B04 # 68-02, CJK UNIFIED IDEOGRAPH-7B04 +U+7B06 # 67-86, CJK UNIFIED IDEOGRAPH-7B06 +U+7B08 # 21-72, CJK UNIFIED IDEOGRAPH-7B08 +U+7B0A # 67-85, CJK UNIFIED IDEOGRAPH-7B0A +U+7B0B # 68-04, CJK UNIFIED IDEOGRAPH-7B0B +U+7B0F # 67-84, CJK UNIFIED IDEOGRAPH-7B0F +U+7B11 # 30-48, CJK UNIFIED IDEOGRAPH-7B11 +U+7B18 # 67-88, CJK UNIFIED IDEOGRAPH-7B18 +U+7B19 # 67-89, CJK UNIFIED IDEOGRAPH-7B19 +U+7B1B # 37-11, CJK UNIFIED IDEOGRAPH-7B1B +U+7B1E # 67-90, CJK UNIFIED IDEOGRAPH-7B1E +U+7B20 # 19-62, CJK UNIFIED IDEOGRAPH-7B20 +U+7B25 # 31-58, CJK UNIFIED IDEOGRAPH-7B25 +U+7B26 # 41-68, CJK UNIFIED IDEOGRAPH-7B26 +U+7B28 # 67-92, CJK UNIFIED IDEOGRAPH-7B28 +U+7B2C # 34-72, CJK UNIFIED IDEOGRAPH-7B2C +U+7B33 # 67-87, CJK UNIFIED IDEOGRAPH-7B33 +U+7B35 # 67-91, CJK UNIFIED IDEOGRAPH-7B35 +U+7B36 # 67-93, CJK UNIFIED IDEOGRAPH-7B36 +U+7B39 # 26-91, CJK UNIFIED IDEOGRAPH-7B39 +U+7B45 # 68-06, CJK UNIFIED IDEOGRAPH-7B45 +U+7B46 # 41-14, CJK UNIFIED IDEOGRAPH-7B46 +U+7B48 # 40-06, CJK UNIFIED IDEOGRAPH-7B48 +U+7B49 # 37-89, CJK UNIFIED IDEOGRAPH-7B49 +U+7B4B # 22-58, CJK UNIFIED IDEOGRAPH-7B4B +U+7B4C # 68-05, CJK UNIFIED IDEOGRAPH-7B4C +U+7B4D # 68-03, CJK UNIFIED IDEOGRAPH-7B4D +U+7B4F # 40-21, CJK UNIFIED IDEOGRAPH-7B4F +U+7B50 # 67-94, CJK UNIFIED IDEOGRAPH-7B50 +U+7B51 # 35-62, CJK UNIFIED IDEOGRAPH-7B51 +U+7B52 # 37-91, CJK UNIFIED IDEOGRAPH-7B52 +U+7B54 # 37-90, CJK UNIFIED IDEOGRAPH-7B54 +U+7B56 # 26-86, CJK UNIFIED IDEOGRAPH-7B56 +U+7B5D # 68-24, CJK UNIFIED IDEOGRAPH-7B5D +U+7B65 # 68-08, CJK UNIFIED IDEOGRAPH-7B65 +U+7B67 # 68-10, CJK UNIFIED IDEOGRAPH-7B67 +U+7B6C # 68-13, CJK UNIFIED IDEOGRAPH-7B6C +U+7B6E # 68-14, CJK UNIFIED IDEOGRAPH-7B6E +U+7B70 # 68-11, CJK UNIFIED IDEOGRAPH-7B70 +U+7B71 # 68-12, CJK UNIFIED IDEOGRAPH-7B71 +U+7B74 # 68-09, CJK UNIFIED IDEOGRAPH-7B74 +U+7B75 # 68-07, CJK UNIFIED IDEOGRAPH-7B75 +U+7B7A # 68-01, CJK UNIFIED IDEOGRAPH-7B7A +U+7B86 # 42-47, CJK UNIFIED IDEOGRAPH-7B86 +U+7B87 # 18-53, CJK UNIFIED IDEOGRAPH-7B87 +U+7B8B # 68-21, CJK UNIFIED IDEOGRAPH-7B8B +U+7B8D # 68-18, CJK UNIFIED IDEOGRAPH-7B8D +U+7B8F # 68-23, CJK UNIFIED IDEOGRAPH-7B8F +U+7B92 # 68-22, CJK UNIFIED IDEOGRAPH-7B92 +U+7B94 # 39-83, CJK UNIFIED IDEOGRAPH-7B94 +U+7B95 # 44-07, CJK UNIFIED IDEOGRAPH-7B95 +U+7B97 # 27-27, CJK UNIFIED IDEOGRAPH-7B97 +U+7B98 # 68-16, CJK UNIFIED IDEOGRAPH-7B98 +U+7B99 # 68-25, CJK UNIFIED IDEOGRAPH-7B99 +U+7B9A # 68-20, CJK UNIFIED IDEOGRAPH-7B9A +U+7B9C # 68-19, CJK UNIFIED IDEOGRAPH-7B9C +U+7B9D # 68-15, CJK UNIFIED IDEOGRAPH-7B9D +U+7B9F # 68-17, CJK UNIFIED IDEOGRAPH-7B9F +U+7BA1 # 20-41, CJK UNIFIED IDEOGRAPH-7BA1 +U+7BAA # 35-29, CJK UNIFIED IDEOGRAPH-7BAA +U+7BAD # 32-93, CJK UNIFIED IDEOGRAPH-7BAD +U+7BB1 # 40-02, CJK UNIFIED IDEOGRAPH-7BB1 +U+7BB4 # 68-30, CJK UNIFIED IDEOGRAPH-7BB4 +U+7BB8 # 40-04, CJK UNIFIED IDEOGRAPH-7BB8 +U+7BC0 # 32-65, CJK UNIFIED IDEOGRAPH-7BC0 +U+7BC1 # 68-27, CJK UNIFIED IDEOGRAPH-7BC1 +U+7BC4 # 40-47, CJK UNIFIED IDEOGRAPH-7BC4 +U+7BC6 # 68-31, CJK UNIFIED IDEOGRAPH-7BC6 +U+7BC7 # 42-51, CJK UNIFIED IDEOGRAPH-7BC7 +U+7BC9 # 35-59, CJK UNIFIED IDEOGRAPH-7BC9 +U+7BCB # 68-26, CJK UNIFIED IDEOGRAPH-7BCB +U+7BCC # 68-28, CJK UNIFIED IDEOGRAPH-7BCC +U+7BCF # 68-29, CJK UNIFIED IDEOGRAPH-7BCF +U+7BDD # 68-32, CJK UNIFIED IDEOGRAPH-7BDD +U+7BE0 # 28-36, CJK UNIFIED IDEOGRAPH-7BE0 +U+7BE4 # 38-38, CJK UNIFIED IDEOGRAPH-7BE4 +U+7BE5 # 68-37, CJK UNIFIED IDEOGRAPH-7BE5 +U+7BE6 # 68-36, CJK UNIFIED IDEOGRAPH-7BE6 +U+7BE9 # 68-33, CJK UNIFIED IDEOGRAPH-7BE9 +U+7BED # 47-22, CJK UNIFIED IDEOGRAPH-7BED +U+7BF3 # 68-42, CJK UNIFIED IDEOGRAPH-7BF3 +U+7BF6 # 68-46, CJK UNIFIED IDEOGRAPH-7BF6 +U+7BF7 # 68-43, CJK UNIFIED IDEOGRAPH-7BF7 +U+7C00 # 68-39, CJK UNIFIED IDEOGRAPH-7C00 +U+7C07 # 68-40, CJK UNIFIED IDEOGRAPH-7C07 +U+7C0D # 68-45, CJK UNIFIED IDEOGRAPH-7C0D +U+7C11 # 68-34, CJK UNIFIED IDEOGRAPH-7C11 +U+7C12 # 50-53, CJK UNIFIED IDEOGRAPH-7C12 +U+7C13 # 68-41, CJK UNIFIED IDEOGRAPH-7C13 +U+7C14 # 68-35, CJK UNIFIED IDEOGRAPH-7C14 +U+7C17 # 68-44, CJK UNIFIED IDEOGRAPH-7C17 +U+7C1F # 68-50, CJK UNIFIED IDEOGRAPH-7C1F +U+7C21 # 20-42, CJK UNIFIED IDEOGRAPH-7C21 +U+7C23 # 68-47, CJK UNIFIED IDEOGRAPH-7C23 +U+7C27 # 68-48, CJK UNIFIED IDEOGRAPH-7C27 +U+7C2A # 68-49, CJK UNIFIED IDEOGRAPH-7C2A +U+7C2B # 68-52, CJK UNIFIED IDEOGRAPH-7C2B +U+7C37 # 68-51, CJK UNIFIED IDEOGRAPH-7C37 +U+7C38 # 40-86, CJK UNIFIED IDEOGRAPH-7C38 +U+7C3D # 68-53, CJK UNIFIED IDEOGRAPH-7C3D +U+7C3E # 46-92, CJK UNIFIED IDEOGRAPH-7C3E +U+7C3F # 42-77, CJK UNIFIED IDEOGRAPH-7C3F +U+7C40 # 68-58, CJK UNIFIED IDEOGRAPH-7C40 +U+7C43 # 68-55, CJK UNIFIED IDEOGRAPH-7C43 +U+7C4C # 68-54, CJK UNIFIED IDEOGRAPH-7C4C +U+7C4D # 32-50, CJK UNIFIED IDEOGRAPH-7C4D +U+7C4F # 68-57, CJK UNIFIED IDEOGRAPH-7C4F +U+7C50 # 68-59, CJK UNIFIED IDEOGRAPH-7C50 +U+7C54 # 68-56, CJK UNIFIED IDEOGRAPH-7C54 +U+7C56 # 68-63, CJK UNIFIED IDEOGRAPH-7C56 +U+7C58 # 68-60, CJK UNIFIED IDEOGRAPH-7C58 +U+7C5F # 68-61, CJK UNIFIED IDEOGRAPH-7C5F +U+7C60 # 68-38, CJK UNIFIED IDEOGRAPH-7C60 +U+7C64 # 68-62, CJK UNIFIED IDEOGRAPH-7C64 +U+7C65 # 68-64, CJK UNIFIED IDEOGRAPH-7C65 +U+7C6C # 68-65, CJK UNIFIED IDEOGRAPH-7C6C +U+7C73 # 42-38, CJK UNIFIED IDEOGRAPH-7C73 +U+7C75 # 68-66, CJK UNIFIED IDEOGRAPH-7C75 +U+7C7E # 44-66, CJK UNIFIED IDEOGRAPH-7C7E +U+7C81 # 22-46, CJK UNIFIED IDEOGRAPH-7C81 +U+7C82 # 23-09, CJK UNIFIED IDEOGRAPH-7C82 +U+7C83 # 68-67, CJK UNIFIED IDEOGRAPH-7C83 +U+7C89 # 42-20, CJK UNIFIED IDEOGRAPH-7C89 +U+7C8B # 31-72, CJK UNIFIED IDEOGRAPH-7C8B +U+7C8D # 44-16, CJK UNIFIED IDEOGRAPH-7C8D +U+7C90 # 68-68, CJK UNIFIED IDEOGRAPH-7C90 +U+7C92 # 46-19, CJK UNIFIED IDEOGRAPH-7C92 +U+7C95 # 39-84, CJK UNIFIED IDEOGRAPH-7C95 +U+7C97 # 33-38, CJK UNIFIED IDEOGRAPH-7C97 +U+7C98 # 39-20, CJK UNIFIED IDEOGRAPH-7C98 +U+7C9B # 29-45, CJK UNIFIED IDEOGRAPH-7C9B +U+7C9F # 16-32, CJK UNIFIED IDEOGRAPH-7C9F +U+7CA1 # 68-73, CJK UNIFIED IDEOGRAPH-7CA1 +U+7CA2 # 68-71, CJK UNIFIED IDEOGRAPH-7CA2 +U+7CA4 # 68-69, CJK UNIFIED IDEOGRAPH-7CA4 +U+7CA5 # 20-01, CJK UNIFIED IDEOGRAPH-7CA5 +U+7CA7 # 30-49, CJK UNIFIED IDEOGRAPH-7CA7 +U+7CA8 # 68-74, CJK UNIFIED IDEOGRAPH-7CA8 +U+7CAB # 68-72, CJK UNIFIED IDEOGRAPH-7CAB +U+7CAD # 68-70, CJK UNIFIED IDEOGRAPH-7CAD +U+7CAE # 68-78, CJK UNIFIED IDEOGRAPH-7CAE +U+7CB1 # 68-77, CJK UNIFIED IDEOGRAPH-7CB1 +U+7CB2 # 68-76, CJK UNIFIED IDEOGRAPH-7CB2 +U+7CB3 # 68-75, CJK UNIFIED IDEOGRAPH-7CB3 +U+7CB9 # 68-79, CJK UNIFIED IDEOGRAPH-7CB9 +U+7CBD # 68-80, CJK UNIFIED IDEOGRAPH-7CBD +U+7CBE # 32-26, CJK UNIFIED IDEOGRAPH-7CBE +U+7CC0 # 68-81, CJK UNIFIED IDEOGRAPH-7CC0 +U+7CC2 # 68-83, CJK UNIFIED IDEOGRAPH-7CC2 +U+7CC5 # 68-82, CJK UNIFIED IDEOGRAPH-7CC5 +U+7CCA # 24-50, CJK UNIFIED IDEOGRAPH-7CCA +U+7CCE # 33-24, CJK UNIFIED IDEOGRAPH-7CCE +U+7CD2 # 68-85, CJK UNIFIED IDEOGRAPH-7CD2 +U+7CD6 # 37-92, CJK UNIFIED IDEOGRAPH-7CD6 +U+7CD8 # 68-84, CJK UNIFIED IDEOGRAPH-7CD8 +U+7CDC # 68-86, CJK UNIFIED IDEOGRAPH-7CDC +U+7CDE # 42-21, CJK UNIFIED IDEOGRAPH-7CDE +U+7CDF # 33-76, CJK UNIFIED IDEOGRAPH-7CDF +U+7CE0 # 25-39, CJK UNIFIED IDEOGRAPH-7CE0 +U+7CE2 # 68-87, CJK UNIFIED IDEOGRAPH-7CE2 +U+7CE7 # 46-40, CJK UNIFIED IDEOGRAPH-7CE7 +U+7CEF # 68-89, CJK UNIFIED IDEOGRAPH-7CEF +U+7CF2 # 68-90, CJK UNIFIED IDEOGRAPH-7CF2 +U+7CF4 # 68-91, CJK UNIFIED IDEOGRAPH-7CF4 +U+7CF6 # 68-92, CJK UNIFIED IDEOGRAPH-7CF6 +U+7CF8 # 27-69, CJK UNIFIED IDEOGRAPH-7CF8 +U+7CFA # 68-93, CJK UNIFIED IDEOGRAPH-7CFA +U+7CFB # 23-47, CJK UNIFIED IDEOGRAPH-7CFB +U+7CFE # 21-74, CJK UNIFIED IDEOGRAPH-7CFE +U+7D00 # 21-10, CJK UNIFIED IDEOGRAPH-7D00 +U+7D02 # 69-01, CJK UNIFIED IDEOGRAPH-7D02 +U+7D04 # 44-83, CJK UNIFIED IDEOGRAPH-7D04 +U+7D05 # 25-40, CJK UNIFIED IDEOGRAPH-7D05 +U+7D06 # 68-94, CJK UNIFIED IDEOGRAPH-7D06 +U+7D0A # 69-04, CJK UNIFIED IDEOGRAPH-7D0A +U+7D0B # 44-70, CJK UNIFIED IDEOGRAPH-7D0B +U+7D0D # 39-28, CJK UNIFIED IDEOGRAPH-7D0D +U+7D10 # 41-19, CJK UNIFIED IDEOGRAPH-7D10 +U+7D14 # 29-67, CJK UNIFIED IDEOGRAPH-7D14 +U+7D15 # 69-03, CJK UNIFIED IDEOGRAPH-7D15 +U+7D17 # 28-51, CJK UNIFIED IDEOGRAPH-7D17 +U+7D18 # 25-41, CJK UNIFIED IDEOGRAPH-7D18 +U+7D19 # 27-70, CJK UNIFIED IDEOGRAPH-7D19 +U+7D1A # 21-73, CJK UNIFIED IDEOGRAPH-7D1A +U+7D1B # 42-22, CJK UNIFIED IDEOGRAPH-7D1B +U+7D1C # 69-02, CJK UNIFIED IDEOGRAPH-7D1C +U+7D20 # 33-39, CJK UNIFIED IDEOGRAPH-7D20 +U+7D21 # 43-34, CJK UNIFIED IDEOGRAPH-7D21 +U+7D22 # 26-87, CJK UNIFIED IDEOGRAPH-7D22 +U+7D2B # 27-71, CJK UNIFIED IDEOGRAPH-7D2B +U+7D2C # 36-61, CJK UNIFIED IDEOGRAPH-7D2C +U+7D2E # 69-07, CJK UNIFIED IDEOGRAPH-7D2E +U+7D2F # 46-63, CJK UNIFIED IDEOGRAPH-7D2F +U+7D30 # 26-57, CJK UNIFIED IDEOGRAPH-7D30 +U+7D32 # 69-08, CJK UNIFIED IDEOGRAPH-7D32 +U+7D33 # 31-34, CJK UNIFIED IDEOGRAPH-7D33 +U+7D35 # 69-10, CJK UNIFIED IDEOGRAPH-7D35 +U+7D39 # 30-50, CJK UNIFIED IDEOGRAPH-7D39 +U+7D3A # 26-16, CJK UNIFIED IDEOGRAPH-7D3A +U+7D3F # 69-09, CJK UNIFIED IDEOGRAPH-7D3F +U+7D42 # 29-10, CJK UNIFIED IDEOGRAPH-7D42 +U+7D43 # 24-30, CJK UNIFIED IDEOGRAPH-7D43 +U+7D44 # 33-40, CJK UNIFIED IDEOGRAPH-7D44 +U+7D45 # 69-05, CJK UNIFIED IDEOGRAPH-7D45 +U+7D46 # 69-11, CJK UNIFIED IDEOGRAPH-7D46 +U+7D4B # 69-06, CJK UNIFIED IDEOGRAPH-7D4B +U+7D4C # 23-48, CJK UNIFIED IDEOGRAPH-7D4C +U+7D4E # 69-14, CJK UNIFIED IDEOGRAPH-7D4E +U+7D4F # 69-18, CJK UNIFIED IDEOGRAPH-7D4F +U+7D50 # 23-75, CJK UNIFIED IDEOGRAPH-7D50 +U+7D56 # 69-13, CJK UNIFIED IDEOGRAPH-7D56 +U+7D5B # 69-22, CJK UNIFIED IDEOGRAPH-7D5B +U+7D5E # 25-42, CJK UNIFIED IDEOGRAPH-7D5E +U+7D61 # 45-77, CJK UNIFIED IDEOGRAPH-7D61 +U+7D62 # 16-28, CJK UNIFIED IDEOGRAPH-7D62 +U+7D63 # 69-19, CJK UNIFIED IDEOGRAPH-7D63 +U+7D66 # 21-75, CJK UNIFIED IDEOGRAPH-7D66 +U+7D68 # 69-16, CJK UNIFIED IDEOGRAPH-7D68 +U+7D6E # 69-17, CJK UNIFIED IDEOGRAPH-7D6E +U+7D71 # 37-93, CJK UNIFIED IDEOGRAPH-7D71 +U+7D72 # 69-15, CJK UNIFIED IDEOGRAPH-7D72 +U+7D73 # 69-12, CJK UNIFIED IDEOGRAPH-7D73 +U+7D75 # 19-08, CJK UNIFIED IDEOGRAPH-7D75 +U+7D76 # 32-68, CJK UNIFIED IDEOGRAPH-7D76 +U+7D79 # 24-08, CJK UNIFIED IDEOGRAPH-7D79 +U+7D7D # 69-24, CJK UNIFIED IDEOGRAPH-7D7D +U+7D89 # 69-21, CJK UNIFIED IDEOGRAPH-7D89 +U+7D8F # 69-23, CJK UNIFIED IDEOGRAPH-7D8F +U+7D93 # 69-20, CJK UNIFIED IDEOGRAPH-7D93 +U+7D99 # 23-49, CJK UNIFIED IDEOGRAPH-7D99 +U+7D9A # 34-19, CJK UNIFIED IDEOGRAPH-7D9A +U+7D9B # 69-25, CJK UNIFIED IDEOGRAPH-7D9B +U+7D9C # 33-78, CJK UNIFIED IDEOGRAPH-7D9C +U+7D9F # 69-38, CJK UNIFIED IDEOGRAPH-7D9F +U+7DA2 # 69-34, CJK UNIFIED IDEOGRAPH-7DA2 +U+7DA3 # 69-28, CJK UNIFIED IDEOGRAPH-7DA3 +U+7DAB # 69-32, CJK UNIFIED IDEOGRAPH-7DAB +U+7DAC # 28-90, CJK UNIFIED IDEOGRAPH-7DAC +U+7DAD # 16-61, CJK UNIFIED IDEOGRAPH-7DAD +U+7DAE # 69-27, CJK UNIFIED IDEOGRAPH-7DAE +U+7DAF # 69-35, CJK UNIFIED IDEOGRAPH-7DAF +U+7DB0 # 69-39, CJK UNIFIED IDEOGRAPH-7DB0 +U+7DB1 # 25-43, CJK UNIFIED IDEOGRAPH-7DB1 +U+7DB2 # 44-54, CJK UNIFIED IDEOGRAPH-7DB2 +U+7DB4 # 36-54, CJK UNIFIED IDEOGRAPH-7DB4 +U+7DB5 # 69-29, CJK UNIFIED IDEOGRAPH-7DB5 +U+7DB8 # 69-37, CJK UNIFIED IDEOGRAPH-7DB8 +U+7DBA # 69-26, CJK UNIFIED IDEOGRAPH-7DBA +U+7DBB # 35-30, CJK UNIFIED IDEOGRAPH-7DBB +U+7DBD # 69-31, CJK UNIFIED IDEOGRAPH-7DBD +U+7DBE # 16-29, CJK UNIFIED IDEOGRAPH-7DBE +U+7DBF # 44-42, CJK UNIFIED IDEOGRAPH-7DBF +U+7DC7 # 69-30, CJK UNIFIED IDEOGRAPH-7DC7 +U+7DCA # 22-59, CJK UNIFIED IDEOGRAPH-7DCA +U+7DCB # 40-76, CJK UNIFIED IDEOGRAPH-7DCB +U+7DCF # 33-77, CJK UNIFIED IDEOGRAPH-7DCF +U+7DD1 # 46-48, CJK UNIFIED IDEOGRAPH-7DD1 +U+7DD2 # 29-79, CJK UNIFIED IDEOGRAPH-7DD2 +U+7DD5 # 69-78, CJK UNIFIED IDEOGRAPH-7DD5 +U+7DD8 # 69-40, CJK UNIFIED IDEOGRAPH-7DD8 +U+7DDA # 32-94, CJK UNIFIED IDEOGRAPH-7DDA +U+7DDC # 69-36, CJK UNIFIED IDEOGRAPH-7DDC +U+7DDD # 69-41, CJK UNIFIED IDEOGRAPH-7DDD +U+7DDE # 69-43, CJK UNIFIED IDEOGRAPH-7DDE +U+7DE0 # 36-89, CJK UNIFIED IDEOGRAPH-7DE0 +U+7DE1 # 69-46, CJK UNIFIED IDEOGRAPH-7DE1 +U+7DE4 # 69-42, CJK UNIFIED IDEOGRAPH-7DE4 +U+7DE8 # 42-52, CJK UNIFIED IDEOGRAPH-7DE8 +U+7DE9 # 20-43, CJK UNIFIED IDEOGRAPH-7DE9 +U+7DEC # 44-43, CJK UNIFIED IDEOGRAPH-7DEC +U+7DEF # 16-62, CJK UNIFIED IDEOGRAPH-7DEF +U+7DF2 # 69-45, CJK UNIFIED IDEOGRAPH-7DF2 +U+7DF4 # 46-93, CJK UNIFIED IDEOGRAPH-7DF4 +U+7DFB # 69-44, CJK UNIFIED IDEOGRAPH-7DFB +U+7E01 # 17-79, CJK UNIFIED IDEOGRAPH-7E01 +U+7E04 # 38-76, CJK UNIFIED IDEOGRAPH-7E04 +U+7E05 # 69-47, CJK UNIFIED IDEOGRAPH-7E05 +U+7E09 # 69-54, CJK UNIFIED IDEOGRAPH-7E09 +U+7E0A # 69-48, CJK UNIFIED IDEOGRAPH-7E0A +U+7E0B # 69-55, CJK UNIFIED IDEOGRAPH-7E0B +U+7E12 # 69-51, CJK UNIFIED IDEOGRAPH-7E12 +U+7E1B # 39-91, CJK UNIFIED IDEOGRAPH-7E1B +U+7E1E # 28-42, CJK UNIFIED IDEOGRAPH-7E1E +U+7E1F # 69-53, CJK UNIFIED IDEOGRAPH-7E1F +U+7E21 # 69-50, CJK UNIFIED IDEOGRAPH-7E21 +U+7E22 # 69-56, CJK UNIFIED IDEOGRAPH-7E22 +U+7E23 # 69-49, CJK UNIFIED IDEOGRAPH-7E23 +U+7E26 # 29-36, CJK UNIFIED IDEOGRAPH-7E26 +U+7E2B # 43-05, CJK UNIFIED IDEOGRAPH-7E2B +U+7E2E # 29-44, CJK UNIFIED IDEOGRAPH-7E2E +U+7E31 # 69-52, CJK UNIFIED IDEOGRAPH-7E31 +U+7E32 # 69-64, CJK UNIFIED IDEOGRAPH-7E32 +U+7E35 # 69-60, CJK UNIFIED IDEOGRAPH-7E35 +U+7E37 # 69-63, CJK UNIFIED IDEOGRAPH-7E37 +U+7E39 # 69-61, CJK UNIFIED IDEOGRAPH-7E39 +U+7E3A # 69-65, CJK UNIFIED IDEOGRAPH-7E3A +U+7E3B # 69-59, CJK UNIFIED IDEOGRAPH-7E3B +U+7E3D # 69-33, CJK UNIFIED IDEOGRAPH-7E3D +U+7E3E # 32-51, CJK UNIFIED IDEOGRAPH-7E3E +U+7E41 # 40-43, CJK UNIFIED IDEOGRAPH-7E41 +U+7E43 # 69-62, CJK UNIFIED IDEOGRAPH-7E43 +U+7E46 # 69-57, CJK UNIFIED IDEOGRAPH-7E46 +U+7E4A # 33-01, CJK UNIFIED IDEOGRAPH-7E4A +U+7E4B # 23-50, CJK UNIFIED IDEOGRAPH-7E4B +U+7E4D # 29-11, CJK UNIFIED IDEOGRAPH-7E4D +U+7E54 # 31-05, CJK UNIFIED IDEOGRAPH-7E54 +U+7E55 # 33-22, CJK UNIFIED IDEOGRAPH-7E55 +U+7E56 # 69-68, CJK UNIFIED IDEOGRAPH-7E56 +U+7E59 # 69-70, CJK UNIFIED IDEOGRAPH-7E59 +U+7E5A # 69-71, CJK UNIFIED IDEOGRAPH-7E5A +U+7E5D # 69-67, CJK UNIFIED IDEOGRAPH-7E5D +U+7E5E # 69-69, CJK UNIFIED IDEOGRAPH-7E5E +U+7E66 # 69-58, CJK UNIFIED IDEOGRAPH-7E66 +U+7E67 # 69-66, CJK UNIFIED IDEOGRAPH-7E67 +U+7E69 # 69-74, CJK UNIFIED IDEOGRAPH-7E69 +U+7E6A # 69-73, CJK UNIFIED IDEOGRAPH-7E6A +U+7E6D # 43-90, CJK UNIFIED IDEOGRAPH-7E6D +U+7E70 # 23-11, CJK UNIFIED IDEOGRAPH-7E70 +U+7E79 # 69-72, CJK UNIFIED IDEOGRAPH-7E79 +U+7E7B # 69-76, CJK UNIFIED IDEOGRAPH-7E7B +U+7E7C # 69-75, CJK UNIFIED IDEOGRAPH-7E7C +U+7E7D # 69-79, CJK UNIFIED IDEOGRAPH-7E7D +U+7E7F # 69-81, CJK UNIFIED IDEOGRAPH-7E7F +U+7E82 # 27-28, CJK UNIFIED IDEOGRAPH-7E82 +U+7E83 # 69-77, CJK UNIFIED IDEOGRAPH-7E83 +U+7E88 # 69-82, CJK UNIFIED IDEOGRAPH-7E88 +U+7E89 # 69-83, CJK UNIFIED IDEOGRAPH-7E89 +U+7E8C # 69-84, CJK UNIFIED IDEOGRAPH-7E8C +U+7E8E # 69-90, CJK UNIFIED IDEOGRAPH-7E8E +U+7E8F # 37-27, CJK UNIFIED IDEOGRAPH-7E8F +U+7E90 # 69-86, CJK UNIFIED IDEOGRAPH-7E90 +U+7E92 # 69-85, CJK UNIFIED IDEOGRAPH-7E92 +U+7E93 # 69-87, CJK UNIFIED IDEOGRAPH-7E93 +U+7E94 # 69-88, CJK UNIFIED IDEOGRAPH-7E94 +U+7E96 # 69-89, CJK UNIFIED IDEOGRAPH-7E96 +U+7E9B # 69-91, CJK UNIFIED IDEOGRAPH-7E9B +U+7E9C # 69-92, CJK UNIFIED IDEOGRAPH-7E9C +U+7F36 # 20-44, CJK UNIFIED IDEOGRAPH-7F36 +U+7F38 # 69-93, CJK UNIFIED IDEOGRAPH-7F38 +U+7F3A # 69-94, CJK UNIFIED IDEOGRAPH-7F3A +U+7F45 # 70-01, CJK UNIFIED IDEOGRAPH-7F45 +U+7F4C # 70-02, CJK UNIFIED IDEOGRAPH-7F4C +U+7F4D # 70-03, CJK UNIFIED IDEOGRAPH-7F4D +U+7F4E # 70-04, CJK UNIFIED IDEOGRAPH-7F4E +U+7F50 # 70-05, CJK UNIFIED IDEOGRAPH-7F50 +U+7F51 # 70-06, CJK UNIFIED IDEOGRAPH-7F51 +U+7F54 # 70-08, CJK UNIFIED IDEOGRAPH-7F54 +U+7F55 # 70-07, CJK UNIFIED IDEOGRAPH-7F55 +U+7F58 # 70-09, CJK UNIFIED IDEOGRAPH-7F58 +U+7F5F # 70-10, CJK UNIFIED IDEOGRAPH-7F5F +U+7F60 # 70-11, CJK UNIFIED IDEOGRAPH-7F60 +U+7F67 # 70-14, CJK UNIFIED IDEOGRAPH-7F67 +U+7F68 # 70-12, CJK UNIFIED IDEOGRAPH-7F68 +U+7F69 # 70-13, CJK UNIFIED IDEOGRAPH-7F69 +U+7F6A # 26-65, CJK UNIFIED IDEOGRAPH-7F6A +U+7F6B # 23-51, CJK UNIFIED IDEOGRAPH-7F6B +U+7F6E # 35-54, CJK UNIFIED IDEOGRAPH-7F6E +U+7F70 # 40-19, CJK UNIFIED IDEOGRAPH-7F70 +U+7F72 # 29-80, CJK UNIFIED IDEOGRAPH-7F72 +U+7F75 # 39-45, CJK UNIFIED IDEOGRAPH-7F75 +U+7F77 # 40-77, CJK UNIFIED IDEOGRAPH-7F77 +U+7F78 # 70-15, CJK UNIFIED IDEOGRAPH-7F78 +U+7F79 # 56-77, CJK UNIFIED IDEOGRAPH-7F79 +U+7F82 # 70-16, CJK UNIFIED IDEOGRAPH-7F82 +U+7F83 # 70-18, CJK UNIFIED IDEOGRAPH-7F83 +U+7F85 # 45-69, CJK UNIFIED IDEOGRAPH-7F85 +U+7F86 # 70-17, CJK UNIFIED IDEOGRAPH-7F86 +U+7F87 # 70-20, CJK UNIFIED IDEOGRAPH-7F87 +U+7F88 # 70-19, CJK UNIFIED IDEOGRAPH-7F88 +U+7F8A # 45-51, CJK UNIFIED IDEOGRAPH-7F8A +U+7F8C # 70-21, CJK UNIFIED IDEOGRAPH-7F8C +U+7F8E # 40-94, CJK UNIFIED IDEOGRAPH-7F8E +U+7F94 # 70-22, CJK UNIFIED IDEOGRAPH-7F94 +U+7F9A # 70-25, CJK UNIFIED IDEOGRAPH-7F9A +U+7F9D # 70-24, CJK UNIFIED IDEOGRAPH-7F9D +U+7F9E # 70-23, CJK UNIFIED IDEOGRAPH-7F9E +U+7FA3 # 70-26, CJK UNIFIED IDEOGRAPH-7FA3 +U+7FA4 # 23-18, CJK UNIFIED IDEOGRAPH-7FA4 +U+7FA8 # 33-02, CJK UNIFIED IDEOGRAPH-7FA8 +U+7FA9 # 21-33, CJK UNIFIED IDEOGRAPH-7FA9 +U+7FAE # 70-30, CJK UNIFIED IDEOGRAPH-7FAE +U+7FAF # 70-27, CJK UNIFIED IDEOGRAPH-7FAF +U+7FB2 # 70-28, CJK UNIFIED IDEOGRAPH-7FB2 +U+7FB6 # 70-31, CJK UNIFIED IDEOGRAPH-7FB6 +U+7FB8 # 70-32, CJK UNIFIED IDEOGRAPH-7FB8 +U+7FB9 # 70-29, CJK UNIFIED IDEOGRAPH-7FB9 +U+7FBD # 17-09, CJK UNIFIED IDEOGRAPH-7FBD +U+7FC1 # 18-07, CJK UNIFIED IDEOGRAPH-7FC1 +U+7FC5 # 70-34, CJK UNIFIED IDEOGRAPH-7FC5 +U+7FC6 # 70-35, CJK UNIFIED IDEOGRAPH-7FC6 +U+7FCA # 70-36, CJK UNIFIED IDEOGRAPH-7FCA +U+7FCC # 45-66, CJK UNIFIED IDEOGRAPH-7FCC +U+7FD2 # 29-12, CJK UNIFIED IDEOGRAPH-7FD2 +U+7FD4 # 70-38, CJK UNIFIED IDEOGRAPH-7FD4 +U+7FD5 # 70-37, CJK UNIFIED IDEOGRAPH-7FD5 +U+7FE0 # 31-73, CJK UNIFIED IDEOGRAPH-7FE0 +U+7FE1 # 70-39, CJK UNIFIED IDEOGRAPH-7FE1 +U+7FE6 # 70-40, CJK UNIFIED IDEOGRAPH-7FE6 +U+7FE9 # 70-41, CJK UNIFIED IDEOGRAPH-7FE9 +U+7FEB # 20-69, CJK UNIFIED IDEOGRAPH-7FEB +U+7FF0 # 20-45, CJK UNIFIED IDEOGRAPH-7FF0 +U+7FF3 # 70-42, CJK UNIFIED IDEOGRAPH-7FF3 +U+7FF9 # 70-43, CJK UNIFIED IDEOGRAPH-7FF9 +U+7FFB # 43-61, CJK UNIFIED IDEOGRAPH-7FFB +U+7FFC # 45-67, CJK UNIFIED IDEOGRAPH-7FFC +U+8000 # 45-52, CJK UNIFIED IDEOGRAPH-8000 +U+8001 # 47-23, CJK UNIFIED IDEOGRAPH-8001 +U+8003 # 25-45, CJK UNIFIED IDEOGRAPH-8003 +U+8004 # 70-46, CJK UNIFIED IDEOGRAPH-8004 +U+8005 # 28-52, CJK UNIFIED IDEOGRAPH-8005 +U+8006 # 70-45, CJK UNIFIED IDEOGRAPH-8006 +U+800B # 70-47, CJK UNIFIED IDEOGRAPH-800B +U+800C # 28-09, CJK UNIFIED IDEOGRAPH-800C +U+8010 # 34-49, CJK UNIFIED IDEOGRAPH-8010 +U+8012 # 70-48, CJK UNIFIED IDEOGRAPH-8012 +U+8015 # 25-44, CJK UNIFIED IDEOGRAPH-8015 +U+8017 # 44-55, CJK UNIFIED IDEOGRAPH-8017 +U+8018 # 70-49, CJK UNIFIED IDEOGRAPH-8018 +U+8019 # 70-50, CJK UNIFIED IDEOGRAPH-8019 +U+801C # 70-51, CJK UNIFIED IDEOGRAPH-801C +U+8021 # 70-52, CJK UNIFIED IDEOGRAPH-8021 +U+8028 # 70-53, CJK UNIFIED IDEOGRAPH-8028 +U+8033 # 28-10, CJK UNIFIED IDEOGRAPH-8033 +U+8036 # 44-77, CJK UNIFIED IDEOGRAPH-8036 +U+803B # 70-55, CJK UNIFIED IDEOGRAPH-803B +U+803D # 35-31, CJK UNIFIED IDEOGRAPH-803D +U+803F # 70-54, CJK UNIFIED IDEOGRAPH-803F +U+8046 # 70-57, CJK UNIFIED IDEOGRAPH-8046 +U+804A # 70-56, CJK UNIFIED IDEOGRAPH-804A +U+8052 # 70-58, CJK UNIFIED IDEOGRAPH-8052 +U+8056 # 32-27, CJK UNIFIED IDEOGRAPH-8056 +U+8058 # 70-59, CJK UNIFIED IDEOGRAPH-8058 +U+805A # 70-60, CJK UNIFIED IDEOGRAPH-805A +U+805E # 42-25, CJK UNIFIED IDEOGRAPH-805E +U+805F # 70-61, CJK UNIFIED IDEOGRAPH-805F +U+8061 # 33-79, CJK UNIFIED IDEOGRAPH-8061 +U+8062 # 70-62, CJK UNIFIED IDEOGRAPH-8062 +U+8068 # 70-63, CJK UNIFIED IDEOGRAPH-8068 +U+806F # 46-94, CJK UNIFIED IDEOGRAPH-806F +U+8070 # 70-66, CJK UNIFIED IDEOGRAPH-8070 +U+8072 # 70-65, CJK UNIFIED IDEOGRAPH-8072 +U+8073 # 70-64, CJK UNIFIED IDEOGRAPH-8073 +U+8074 # 36-16, CJK UNIFIED IDEOGRAPH-8074 +U+8076 # 70-67, CJK UNIFIED IDEOGRAPH-8076 +U+8077 # 31-06, CJK UNIFIED IDEOGRAPH-8077 +U+8079 # 70-68, CJK UNIFIED IDEOGRAPH-8079 +U+807D # 70-69, CJK UNIFIED IDEOGRAPH-807D +U+807E # 47-24, CJK UNIFIED IDEOGRAPH-807E +U+807F # 70-70, CJK UNIFIED IDEOGRAPH-807F +U+8084 # 70-71, CJK UNIFIED IDEOGRAPH-8084 +U+8085 # 70-73, CJK UNIFIED IDEOGRAPH-8085 +U+8086 # 70-72, CJK UNIFIED IDEOGRAPH-8086 +U+8087 # 40-05, CJK UNIFIED IDEOGRAPH-8087 +U+8089 # 38-89, CJK UNIFIED IDEOGRAPH-8089 +U+808B # 47-30, CJK UNIFIED IDEOGRAPH-808B +U+808C # 40-09, CJK UNIFIED IDEOGRAPH-808C +U+8093 # 70-75, CJK UNIFIED IDEOGRAPH-8093 +U+8096 # 30-51, CJK UNIFIED IDEOGRAPH-8096 +U+8098 # 41-10, CJK UNIFIED IDEOGRAPH-8098 +U+809A # 70-76, CJK UNIFIED IDEOGRAPH-809A +U+809B # 70-74, CJK UNIFIED IDEOGRAPH-809B +U+809D # 20-46, CJK UNIFIED IDEOGRAPH-809D +U+80A1 # 24-52, CJK UNIFIED IDEOGRAPH-80A1 +U+80A2 # 27-72, CJK UNIFIED IDEOGRAPH-80A2 +U+80A5 # 40-78, CJK UNIFIED IDEOGRAPH-80A5 +U+80A9 # 24-10, CJK UNIFIED IDEOGRAPH-80A9 +U+80AA # 43-35, CJK UNIFIED IDEOGRAPH-80AA +U+80AC # 70-79, CJK UNIFIED IDEOGRAPH-80AC +U+80AD # 70-77, CJK UNIFIED IDEOGRAPH-80AD +U+80AF # 25-46, CJK UNIFIED IDEOGRAPH-80AF +U+80B1 # 25-47, CJK UNIFIED IDEOGRAPH-80B1 +U+80B2 # 16-73, CJK UNIFIED IDEOGRAPH-80B2 +U+80B4 # 26-72, CJK UNIFIED IDEOGRAPH-80B4 +U+80BA # 39-57, CJK UNIFIED IDEOGRAPH-80BA +U+80C3 # 16-63, CJK UNIFIED IDEOGRAPH-80C3 +U+80C4 # 70-84, CJK UNIFIED IDEOGRAPH-80C4 +U+80C6 # 35-32, CJK UNIFIED IDEOGRAPH-80C6 +U+80CC # 39-56, CJK UNIFIED IDEOGRAPH-80CC +U+80CE # 34-59, CJK UNIFIED IDEOGRAPH-80CE +U+80D6 # 70-86, CJK UNIFIED IDEOGRAPH-80D6 +U+80D9 # 70-82, CJK UNIFIED IDEOGRAPH-80D9 +U+80DA # 70-85, CJK UNIFIED IDEOGRAPH-80DA +U+80DB # 70-80, CJK UNIFIED IDEOGRAPH-80DB +U+80DD # 70-83, CJK UNIFIED IDEOGRAPH-80DD +U+80DE # 43-06, CJK UNIFIED IDEOGRAPH-80DE +U+80E1 # 24-53, CJK UNIFIED IDEOGRAPH-80E1 +U+80E4 # 16-93, CJK UNIFIED IDEOGRAPH-80E4 +U+80E5 # 70-81, CJK UNIFIED IDEOGRAPH-80E5 +U+80EF # 70-88, CJK UNIFIED IDEOGRAPH-80EF +U+80F1 # 70-89, CJK UNIFIED IDEOGRAPH-80F1 +U+80F4 # 38-25, CJK UNIFIED IDEOGRAPH-80F4 +U+80F8 # 22-27, CJK UNIFIED IDEOGRAPH-80F8 +U+80FC # 71-06, CJK UNIFIED IDEOGRAPH-80FC +U+80FD # 39-29, CJK UNIFIED IDEOGRAPH-80FD +U+8102 # 27-73, CJK UNIFIED IDEOGRAPH-8102 +U+8105 # 22-28, CJK UNIFIED IDEOGRAPH-8105 +U+8106 # 32-40, CJK UNIFIED IDEOGRAPH-8106 +U+8107 # 47-38, CJK UNIFIED IDEOGRAPH-8107 +U+8108 # 44-14, CJK UNIFIED IDEOGRAPH-8108 +U+8109 # 70-87, CJK UNIFIED IDEOGRAPH-8109 +U+810A # 32-52, CJK UNIFIED IDEOGRAPH-810A +U+811A # 21-51, CJK UNIFIED IDEOGRAPH-811A +U+811B # 70-90, CJK UNIFIED IDEOGRAPH-811B +U+8123 # 70-92, CJK UNIFIED IDEOGRAPH-8123 +U+8129 # 70-91, CJK UNIFIED IDEOGRAPH-8129 +U+812F # 70-93, CJK UNIFIED IDEOGRAPH-812F +U+8131 # 35-06, CJK UNIFIED IDEOGRAPH-8131 +U+8133 # 39-30, CJK UNIFIED IDEOGRAPH-8133 +U+8139 # 36-17, CJK UNIFIED IDEOGRAPH-8139 +U+813E # 71-03, CJK UNIFIED IDEOGRAPH-813E +U+8146 # 71-02, CJK UNIFIED IDEOGRAPH-8146 +U+814B # 70-94, CJK UNIFIED IDEOGRAPH-814B +U+814E # 31-53, CJK UNIFIED IDEOGRAPH-814E +U+8150 # 41-69, CJK UNIFIED IDEOGRAPH-8150 +U+8151 # 71-05, CJK UNIFIED IDEOGRAPH-8151 +U+8153 # 71-04, CJK UNIFIED IDEOGRAPH-8153 +U+8154 # 25-48, CJK UNIFIED IDEOGRAPH-8154 +U+8155 # 47-51, CJK UNIFIED IDEOGRAPH-8155 +U+815F # 71-21, CJK UNIFIED IDEOGRAPH-815F +U+8165 # 71-09, CJK UNIFIED IDEOGRAPH-8165 +U+8166 # 71-10, CJK UNIFIED IDEOGRAPH-8166 +U+816B # 28-80, CJK UNIFIED IDEOGRAPH-816B +U+816E # 71-08, CJK UNIFIED IDEOGRAPH-816E +U+8170 # 25-88, CJK UNIFIED IDEOGRAPH-8170 +U+8171 # 71-07, CJK UNIFIED IDEOGRAPH-8171 +U+8174 # 71-11, CJK UNIFIED IDEOGRAPH-8174 +U+8178 # 36-18, CJK UNIFIED IDEOGRAPH-8178 +U+8179 # 42-02, CJK UNIFIED IDEOGRAPH-8179 +U+817A # 33-03, CJK UNIFIED IDEOGRAPH-817A +U+817F # 34-60, CJK UNIFIED IDEOGRAPH-817F +U+8180 # 71-15, CJK UNIFIED IDEOGRAPH-8180 +U+8182 # 71-16, CJK UNIFIED IDEOGRAPH-8182 +U+8183 # 71-12, CJK UNIFIED IDEOGRAPH-8183 +U+8188 # 71-13, CJK UNIFIED IDEOGRAPH-8188 +U+818A # 71-14, CJK UNIFIED IDEOGRAPH-818A +U+818F # 25-49, CJK UNIFIED IDEOGRAPH-818F +U+8193 # 71-22, CJK UNIFIED IDEOGRAPH-8193 +U+8195 # 71-18, CJK UNIFIED IDEOGRAPH-8195 +U+819A # 41-70, CJK UNIFIED IDEOGRAPH-819A +U+819C # 43-76, CJK UNIFIED IDEOGRAPH-819C +U+819D # 41-08, CJK UNIFIED IDEOGRAPH-819D +U+81A0 # 71-17, CJK UNIFIED IDEOGRAPH-81A0 +U+81A3 # 71-20, CJK UNIFIED IDEOGRAPH-81A3 +U+81A4 # 71-19, CJK UNIFIED IDEOGRAPH-81A4 +U+81A8 # 43-36, CJK UNIFIED IDEOGRAPH-81A8 +U+81A9 # 71-23, CJK UNIFIED IDEOGRAPH-81A9 +U+81B0 # 71-24, CJK UNIFIED IDEOGRAPH-81B0 +U+81B3 # 33-23, CJK UNIFIED IDEOGRAPH-81B3 +U+81B5 # 71-25, CJK UNIFIED IDEOGRAPH-81B5 +U+81B8 # 71-27, CJK UNIFIED IDEOGRAPH-81B8 +U+81BA # 71-31, CJK UNIFIED IDEOGRAPH-81BA +U+81BD # 71-28, CJK UNIFIED IDEOGRAPH-81BD +U+81BE # 71-26, CJK UNIFIED IDEOGRAPH-81BE +U+81BF # 39-31, CJK UNIFIED IDEOGRAPH-81BF +U+81C0 # 71-29, CJK UNIFIED IDEOGRAPH-81C0 +U+81C2 # 71-30, CJK UNIFIED IDEOGRAPH-81C2 +U+81C6 # 18-18, CJK UNIFIED IDEOGRAPH-81C6 +U+81C8 # 71-37, CJK UNIFIED IDEOGRAPH-81C8 +U+81C9 # 71-32, CJK UNIFIED IDEOGRAPH-81C9 +U+81CD # 71-33, CJK UNIFIED IDEOGRAPH-81CD +U+81D1 # 71-34, CJK UNIFIED IDEOGRAPH-81D1 +U+81D3 # 34-01, CJK UNIFIED IDEOGRAPH-81D3 +U+81D8 # 71-36, CJK UNIFIED IDEOGRAPH-81D8 +U+81D9 # 71-35, CJK UNIFIED IDEOGRAPH-81D9 +U+81DA # 71-38, CJK UNIFIED IDEOGRAPH-81DA +U+81DF # 71-39, CJK UNIFIED IDEOGRAPH-81DF +U+81E0 # 71-40, CJK UNIFIED IDEOGRAPH-81E0 +U+81E3 # 31-35, CJK UNIFIED IDEOGRAPH-81E3 +U+81E5 # 18-73, CJK UNIFIED IDEOGRAPH-81E5 +U+81E7 # 71-41, CJK UNIFIED IDEOGRAPH-81E7 +U+81E8 # 46-55, CJK UNIFIED IDEOGRAPH-81E8 +U+81EA # 28-11, CJK UNIFIED IDEOGRAPH-81EA +U+81ED # 29-13, CJK UNIFIED IDEOGRAPH-81ED +U+81F3 # 27-74, CJK UNIFIED IDEOGRAPH-81F3 +U+81F4 # 35-55, CJK UNIFIED IDEOGRAPH-81F4 +U+81FA # 71-42, CJK UNIFIED IDEOGRAPH-81FA +U+81FB # 71-43, CJK UNIFIED IDEOGRAPH-81FB +U+81FC # 17-17, CJK UNIFIED IDEOGRAPH-81FC +U+81FE # 71-44, CJK UNIFIED IDEOGRAPH-81FE +U+8201 # 71-45, CJK UNIFIED IDEOGRAPH-8201 +U+8202 # 71-46, CJK UNIFIED IDEOGRAPH-8202 +U+8205 # 71-47, CJK UNIFIED IDEOGRAPH-8205 +U+8207 # 71-48, CJK UNIFIED IDEOGRAPH-8207 +U+8208 # 22-29, CJK UNIFIED IDEOGRAPH-8208 +U+8209 # 58-10, CJK UNIFIED IDEOGRAPH-8209 +U+820A # 71-49, CJK UNIFIED IDEOGRAPH-820A +U+820C # 32-69, CJK UNIFIED IDEOGRAPH-820C +U+820D # 71-50, CJK UNIFIED IDEOGRAPH-820D +U+820E # 28-43, CJK UNIFIED IDEOGRAPH-820E +U+8210 # 71-51, CJK UNIFIED IDEOGRAPH-8210 +U+8212 # 48-16, CJK UNIFIED IDEOGRAPH-8212 +U+8216 # 71-52, CJK UNIFIED IDEOGRAPH-8216 +U+8217 # 42-62, CJK UNIFIED IDEOGRAPH-8217 +U+8218 # 20-60, CJK UNIFIED IDEOGRAPH-8218 +U+821B # 33-04, CJK UNIFIED IDEOGRAPH-821B +U+821C # 29-56, CJK UNIFIED IDEOGRAPH-821C +U+821E # 41-81, CJK UNIFIED IDEOGRAPH-821E +U+821F # 29-14, CJK UNIFIED IDEOGRAPH-821F +U+8229 # 71-53, CJK UNIFIED IDEOGRAPH-8229 +U+822A # 25-50, CJK UNIFIED IDEOGRAPH-822A +U+822B # 71-54, CJK UNIFIED IDEOGRAPH-822B +U+822C # 40-44, CJK UNIFIED IDEOGRAPH-822C +U+822E # 71-68, CJK UNIFIED IDEOGRAPH-822E +U+8233 # 71-56, CJK UNIFIED IDEOGRAPH-8233 +U+8235 # 34-41, CJK UNIFIED IDEOGRAPH-8235 +U+8236 # 39-85, CJK UNIFIED IDEOGRAPH-8236 +U+8237 # 24-31, CJK UNIFIED IDEOGRAPH-8237 +U+8238 # 71-55, CJK UNIFIED IDEOGRAPH-8238 +U+8239 # 33-05, CJK UNIFIED IDEOGRAPH-8239 +U+8240 # 71-57, CJK UNIFIED IDEOGRAPH-8240 +U+8247 # 36-90, CJK UNIFIED IDEOGRAPH-8247 +U+8258 # 71-59, CJK UNIFIED IDEOGRAPH-8258 +U+8259 # 71-58, CJK UNIFIED IDEOGRAPH-8259 +U+825A # 71-61, CJK UNIFIED IDEOGRAPH-825A +U+825D # 71-60, CJK UNIFIED IDEOGRAPH-825D +U+825F # 71-62, CJK UNIFIED IDEOGRAPH-825F +U+8262 # 71-64, CJK UNIFIED IDEOGRAPH-8262 +U+8264 # 71-63, CJK UNIFIED IDEOGRAPH-8264 +U+8266 # 20-47, CJK UNIFIED IDEOGRAPH-8266 +U+8268 # 71-65, CJK UNIFIED IDEOGRAPH-8268 +U+826A # 71-66, CJK UNIFIED IDEOGRAPH-826A +U+826B # 71-67, CJK UNIFIED IDEOGRAPH-826B +U+826E # 26-17, CJK UNIFIED IDEOGRAPH-826E +U+826F # 46-41, CJK UNIFIED IDEOGRAPH-826F +U+8271 # 71-69, CJK UNIFIED IDEOGRAPH-8271 +U+8272 # 31-07, CJK UNIFIED IDEOGRAPH-8272 +U+8276 # 17-80, CJK UNIFIED IDEOGRAPH-8276 +U+8277 # 71-70, CJK UNIFIED IDEOGRAPH-8277 +U+8278 # 71-71, CJK UNIFIED IDEOGRAPH-8278 +U+827E # 71-72, CJK UNIFIED IDEOGRAPH-827E +U+828B # 16-82, CJK UNIFIED IDEOGRAPH-828B +U+828D # 71-73, CJK UNIFIED IDEOGRAPH-828D +U+8292 # 71-74, CJK UNIFIED IDEOGRAPH-8292 +U+8299 # 41-71, CJK UNIFIED IDEOGRAPH-8299 +U+829D # 28-39, CJK UNIFIED IDEOGRAPH-829D +U+829F # 71-76, CJK UNIFIED IDEOGRAPH-829F +U+82A5 # 19-09, CJK UNIFIED IDEOGRAPH-82A5 +U+82A6 # 16-18, CJK UNIFIED IDEOGRAPH-82A6 +U+82AB # 71-75, CJK UNIFIED IDEOGRAPH-82AB +U+82AC # 71-78, CJK UNIFIED IDEOGRAPH-82AC +U+82AD # 39-46, CJK UNIFIED IDEOGRAPH-82AD +U+82AF # 31-36, CJK UNIFIED IDEOGRAPH-82AF +U+82B1 # 18-54, CJK UNIFIED IDEOGRAPH-82B1 +U+82B3 # 43-07, CJK UNIFIED IDEOGRAPH-82B3 +U+82B8 # 23-61, CJK UNIFIED IDEOGRAPH-82B8 +U+82B9 # 22-60, CJK UNIFIED IDEOGRAPH-82B9 +U+82BB # 71-77, CJK UNIFIED IDEOGRAPH-82BB +U+82BD # 18-74, CJK UNIFIED IDEOGRAPH-82BD +U+82C5 # 20-03, CJK UNIFIED IDEOGRAPH-82C5 +U+82D1 # 17-81, CJK UNIFIED IDEOGRAPH-82D1 +U+82D2 # 71-82, CJK UNIFIED IDEOGRAPH-82D2 +U+82D3 # 46-74, CJK UNIFIED IDEOGRAPH-82D3 +U+82D4 # 34-61, CJK UNIFIED IDEOGRAPH-82D4 +U+82D7 # 41-36, CJK UNIFIED IDEOGRAPH-82D7 +U+82D9 # 71-94, CJK UNIFIED IDEOGRAPH-82D9 +U+82DB # 18-55, CJK UNIFIED IDEOGRAPH-82DB +U+82DC # 71-92, CJK UNIFIED IDEOGRAPH-82DC +U+82DE # 71-90, CJK UNIFIED IDEOGRAPH-82DE +U+82DF # 71-81, CJK UNIFIED IDEOGRAPH-82DF +U+82E1 # 71-79, CJK UNIFIED IDEOGRAPH-82E1 +U+82E3 # 71-80, CJK UNIFIED IDEOGRAPH-82E3 +U+82E5 # 28-67, CJK UNIFIED IDEOGRAPH-82E5 +U+82E6 # 22-76, CJK UNIFIED IDEOGRAPH-82E6 +U+82E7 # 35-87, CJK UNIFIED IDEOGRAPH-82E7 +U+82EB # 38-49, CJK UNIFIED IDEOGRAPH-82EB +U+82F1 # 17-49, CJK UNIFIED IDEOGRAPH-82F1 +U+82F3 # 71-84, CJK UNIFIED IDEOGRAPH-82F3 +U+82F4 # 71-83, CJK UNIFIED IDEOGRAPH-82F4 +U+82F9 # 71-89, CJK UNIFIED IDEOGRAPH-82F9 +U+82FA # 71-85, CJK UNIFIED IDEOGRAPH-82FA +U+82FB # 71-88, CJK UNIFIED IDEOGRAPH-82FB +U+8302 # 44-48, CJK UNIFIED IDEOGRAPH-8302 +U+8303 # 71-87, CJK UNIFIED IDEOGRAPH-8303 +U+8304 # 18-56, CJK UNIFIED IDEOGRAPH-8304 +U+8305 # 19-93, CJK UNIFIED IDEOGRAPH-8305 +U+8306 # 71-91, CJK UNIFIED IDEOGRAPH-8306 +U+8309 # 71-93, CJK UNIFIED IDEOGRAPH-8309 +U+830E # 23-52, CJK UNIFIED IDEOGRAPH-830E +U+8316 # 72-03, CJK UNIFIED IDEOGRAPH-8316 +U+8317 # 72-12, CJK UNIFIED IDEOGRAPH-8317 +U+8318 # 72-13, CJK UNIFIED IDEOGRAPH-8318 +U+831C # 16-11, CJK UNIFIED IDEOGRAPH-831C +U+8323 # 72-20, CJK UNIFIED IDEOGRAPH-8323 +U+8328 # 16-81, CJK UNIFIED IDEOGRAPH-8328 +U+832B # 72-11, CJK UNIFIED IDEOGRAPH-832B +U+832F # 72-10, CJK UNIFIED IDEOGRAPH-832F +U+8331 # 72-05, CJK UNIFIED IDEOGRAPH-8331 +U+8332 # 72-04, CJK UNIFIED IDEOGRAPH-8332 +U+8334 # 72-02, CJK UNIFIED IDEOGRAPH-8334 +U+8335 # 72-01, CJK UNIFIED IDEOGRAPH-8335 +U+8336 # 35-67, CJK UNIFIED IDEOGRAPH-8336 +U+8338 # 34-91, CJK UNIFIED IDEOGRAPH-8338 +U+8339 # 72-07, CJK UNIFIED IDEOGRAPH-8339 +U+8340 # 72-06, CJK UNIFIED IDEOGRAPH-8340 +U+8345 # 72-09, CJK UNIFIED IDEOGRAPH-8345 +U+8349 # 33-80, CJK UNIFIED IDEOGRAPH-8349 +U+834A # 23-53, CJK UNIFIED IDEOGRAPH-834A +U+834F # 17-33, CJK UNIFIED IDEOGRAPH-834F +U+8350 # 72-08, CJK UNIFIED IDEOGRAPH-8350 +U+8352 # 25-51, CJK UNIFIED IDEOGRAPH-8352 +U+8358 # 33-81, CJK UNIFIED IDEOGRAPH-8358 +U+8373 # 72-26, CJK UNIFIED IDEOGRAPH-8373 +U+8375 # 72-27, CJK UNIFIED IDEOGRAPH-8375 +U+8377 # 18-57, CJK UNIFIED IDEOGRAPH-8377 +U+837B # 18-14, CJK UNIFIED IDEOGRAPH-837B +U+837C # 72-24, CJK UNIFIED IDEOGRAPH-837C +U+8385 # 72-14, CJK UNIFIED IDEOGRAPH-8385 +U+8387 # 72-22, CJK UNIFIED IDEOGRAPH-8387 +U+8389 # 72-29, CJK UNIFIED IDEOGRAPH-8389 +U+838A # 72-23, CJK UNIFIED IDEOGRAPH-838A +U+838E # 72-21, CJK UNIFIED IDEOGRAPH-838E +U+8393 # 71-86, CJK UNIFIED IDEOGRAPH-8393 +U+8396 # 72-19, CJK UNIFIED IDEOGRAPH-8396 +U+839A # 72-15, CJK UNIFIED IDEOGRAPH-839A +U+839E # 20-48, CJK UNIFIED IDEOGRAPH-839E +U+839F # 72-17, CJK UNIFIED IDEOGRAPH-839F +U+83A0 # 72-28, CJK UNIFIED IDEOGRAPH-83A0 +U+83A2 # 72-18, CJK UNIFIED IDEOGRAPH-83A2 +U+83A8 # 72-30, CJK UNIFIED IDEOGRAPH-83A8 +U+83AA # 72-16, CJK UNIFIED IDEOGRAPH-83AA +U+83AB # 39-92, CJK UNIFIED IDEOGRAPH-83AB +U+83B1 # 45-73, CJK UNIFIED IDEOGRAPH-83B1 +U+83B5 # 72-25, CJK UNIFIED IDEOGRAPH-83B5 +U+83BD # 72-47, CJK UNIFIED IDEOGRAPH-83BD +U+83C1 # 72-39, CJK UNIFIED IDEOGRAPH-83C1 +U+83C5 # 31-91, CJK UNIFIED IDEOGRAPH-83C5 +U+83CA # 21-38, CJK UNIFIED IDEOGRAPH-83CA +U+83CC # 22-61, CJK UNIFIED IDEOGRAPH-83CC +U+83CE # 72-34, CJK UNIFIED IDEOGRAPH-83CE +U+83D3 # 18-59, CJK UNIFIED IDEOGRAPH-83D3 +U+83D6 # 30-52, CJK UNIFIED IDEOGRAPH-83D6 +U+83D8 # 72-37, CJK UNIFIED IDEOGRAPH-83D8 +U+83DC # 26-58, CJK UNIFIED IDEOGRAPH-83DC +U+83DF # 37-49, CJK UNIFIED IDEOGRAPH-83DF +U+83E0 # 72-42, CJK UNIFIED IDEOGRAPH-83E0 +U+83E9 # 42-78, CJK UNIFIED IDEOGRAPH-83E9 +U+83EB # 72-33, CJK UNIFIED IDEOGRAPH-83EB +U+83EF # 18-58, CJK UNIFIED IDEOGRAPH-83EF +U+83F0 # 24-54, CJK UNIFIED IDEOGRAPH-83F0 +U+83F1 # 41-09, CJK UNIFIED IDEOGRAPH-83F1 +U+83F2 # 72-43, CJK UNIFIED IDEOGRAPH-83F2 +U+83F4 # 72-31, CJK UNIFIED IDEOGRAPH-83F4 +U+83F7 # 72-40, CJK UNIFIED IDEOGRAPH-83F7 +U+83FB # 72-50, CJK UNIFIED IDEOGRAPH-83FB +U+83FD # 72-35, CJK UNIFIED IDEOGRAPH-83FD +U+8403 # 72-36, CJK UNIFIED IDEOGRAPH-8403 +U+8404 # 38-26, CJK UNIFIED IDEOGRAPH-8404 +U+8407 # 72-41, CJK UNIFIED IDEOGRAPH-8407 +U+840B # 72-38, CJK UNIFIED IDEOGRAPH-840B +U+840C # 43-08, CJK UNIFIED IDEOGRAPH-840C +U+840D # 72-44, CJK UNIFIED IDEOGRAPH-840D +U+840E # 16-64, CJK UNIFIED IDEOGRAPH-840E +U+8413 # 72-32, CJK UNIFIED IDEOGRAPH-8413 +U+8420 # 72-46, CJK UNIFIED IDEOGRAPH-8420 +U+8422 # 72-45, CJK UNIFIED IDEOGRAPH-8422 +U+8429 # 39-75, CJK UNIFIED IDEOGRAPH-8429 +U+842A # 72-52, CJK UNIFIED IDEOGRAPH-842A +U+842C # 72-63, CJK UNIFIED IDEOGRAPH-842C +U+8431 # 19-94, CJK UNIFIED IDEOGRAPH-8431 +U+8435 # 72-66, CJK UNIFIED IDEOGRAPH-8435 +U+8438 # 72-48, CJK UNIFIED IDEOGRAPH-8438 +U+843C # 72-53, CJK UNIFIED IDEOGRAPH-843C +U+843D # 45-78, CJK UNIFIED IDEOGRAPH-843D +U+8446 # 72-62, CJK UNIFIED IDEOGRAPH-8446 +U+8449 # 45-53, CJK UNIFIED IDEOGRAPH-8449 +U+844E # 46-10, CJK UNIFIED IDEOGRAPH-844E +U+8457 # 35-88, CJK UNIFIED IDEOGRAPH-8457 +U+845B # 19-75, CJK UNIFIED IDEOGRAPH-845B +U+8461 # 41-82, CJK UNIFIED IDEOGRAPH-8461 +U+8462 # 72-68, CJK UNIFIED IDEOGRAPH-8462 +U+8463 # 38-01, CJK UNIFIED IDEOGRAPH-8463 +U+8466 # 16-17, CJK UNIFIED IDEOGRAPH-8466 +U+8469 # 72-61, CJK UNIFIED IDEOGRAPH-8469 +U+846B # 72-57, CJK UNIFIED IDEOGRAPH-846B +U+846C # 33-82, CJK UNIFIED IDEOGRAPH-846C +U+846D # 72-51, CJK UNIFIED IDEOGRAPH-846D +U+846E # 72-59, CJK UNIFIED IDEOGRAPH-846E +U+846F # 72-64, CJK UNIFIED IDEOGRAPH-846F +U+8471 # 39-12, CJK UNIFIED IDEOGRAPH-8471 +U+8475 # 16-10, CJK UNIFIED IDEOGRAPH-8475 +U+8477 # 72-56, CJK UNIFIED IDEOGRAPH-8477 +U+8479 # 72-65, CJK UNIFIED IDEOGRAPH-8479 +U+847A # 41-88, CJK UNIFIED IDEOGRAPH-847A +U+8482 # 72-60, CJK UNIFIED IDEOGRAPH-8482 +U+8484 # 72-55, CJK UNIFIED IDEOGRAPH-8484 +U+848B # 30-53, CJK UNIFIED IDEOGRAPH-848B +U+8490 # 29-15, CJK UNIFIED IDEOGRAPH-8490 +U+8494 # 28-12, CJK UNIFIED IDEOGRAPH-8494 +U+8499 # 44-56, CJK UNIFIED IDEOGRAPH-8499 +U+849C # 41-39, CJK UNIFIED IDEOGRAPH-849C +U+849F # 72-71, CJK UNIFIED IDEOGRAPH-849F +U+84A1 # 72-80, CJK UNIFIED IDEOGRAPH-84A1 +U+84AD # 72-58, CJK UNIFIED IDEOGRAPH-84AD +U+84B2 # 19-87, CJK UNIFIED IDEOGRAPH-84B2 +U+84B8 # 30-88, CJK UNIFIED IDEOGRAPH-84B8 +U+84B9 # 72-69, CJK UNIFIED IDEOGRAPH-84B9 +U+84BB # 72-74, CJK UNIFIED IDEOGRAPH-84BB +U+84BC # 33-83, CJK UNIFIED IDEOGRAPH-84BC +U+84BF # 72-70, CJK UNIFIED IDEOGRAPH-84BF +U+84C1 # 72-77, CJK UNIFIED IDEOGRAPH-84C1 +U+84C4 # 35-63, CJK UNIFIED IDEOGRAPH-84C4 +U+84C6 # 72-78, CJK UNIFIED IDEOGRAPH-84C6 +U+84C9 # 45-54, CJK UNIFIED IDEOGRAPH-84C9 +U+84CA # 72-67, CJK UNIFIED IDEOGRAPH-84CA +U+84CB # 19-24, CJK UNIFIED IDEOGRAPH-84CB +U+84CD # 72-73, CJK UNIFIED IDEOGRAPH-84CD +U+84D0 # 72-76, CJK UNIFIED IDEOGRAPH-84D0 +U+84D1 # 44-12, CJK UNIFIED IDEOGRAPH-84D1 +U+84D6 # 72-79, CJK UNIFIED IDEOGRAPH-84D6 +U+84D9 # 72-72, CJK UNIFIED IDEOGRAPH-84D9 +U+84DA # 72-75, CJK UNIFIED IDEOGRAPH-84DA +U+84EC # 43-09, CJK UNIFIED IDEOGRAPH-84EC +U+84EE # 47-01, CJK UNIFIED IDEOGRAPH-84EE +U+84F4 # 72-83, CJK UNIFIED IDEOGRAPH-84F4 +U+84FC # 72-90, CJK UNIFIED IDEOGRAPH-84FC +U+84FF # 72-82, CJK UNIFIED IDEOGRAPH-84FF +U+8500 # 28-35, CJK UNIFIED IDEOGRAPH-8500 +U+8506 # 72-49, CJK UNIFIED IDEOGRAPH-8506 +U+8511 # 42-46, CJK UNIFIED IDEOGRAPH-8511 +U+8513 # 44-02, CJK UNIFIED IDEOGRAPH-8513 +U+8514 # 72-89, CJK UNIFIED IDEOGRAPH-8514 +U+8515 # 72-88, CJK UNIFIED IDEOGRAPH-8515 +U+8517 # 72-84, CJK UNIFIED IDEOGRAPH-8517 +U+8518 # 72-85, CJK UNIFIED IDEOGRAPH-8518 +U+851A # 17-22, CJK UNIFIED IDEOGRAPH-851A +U+851F # 72-87, CJK UNIFIED IDEOGRAPH-851F +U+8521 # 72-81, CJK UNIFIED IDEOGRAPH-8521 +U+8526 # 36-53, CJK UNIFIED IDEOGRAPH-8526 +U+852C # 72-86, CJK UNIFIED IDEOGRAPH-852C +U+852D # 16-94, CJK UNIFIED IDEOGRAPH-852D +U+8535 # 34-02, CJK UNIFIED IDEOGRAPH-8535 +U+853D # 42-35, CJK UNIFIED IDEOGRAPH-853D +U+8540 # 72-91, CJK UNIFIED IDEOGRAPH-8540 +U+8541 # 73-01, CJK UNIFIED IDEOGRAPH-8541 +U+8543 # 40-57, CJK UNIFIED IDEOGRAPH-8543 +U+8548 # 72-94, CJK UNIFIED IDEOGRAPH-8548 +U+8549 # 30-54, CJK UNIFIED IDEOGRAPH-8549 +U+854A # 28-41, CJK UNIFIED IDEOGRAPH-854A +U+854B # 73-03, CJK UNIFIED IDEOGRAPH-854B +U+854E # 22-30, CJK UNIFIED IDEOGRAPH-854E +U+8555 # 73-04, CJK UNIFIED IDEOGRAPH-8555 +U+8557 # 41-89, CJK UNIFIED IDEOGRAPH-8557 +U+8558 # 72-93, CJK UNIFIED IDEOGRAPH-8558 +U+855A # 72-54, CJK UNIFIED IDEOGRAPH-855A +U+8563 # 72-92, CJK UNIFIED IDEOGRAPH-8563 +U+8568 # 47-47, CJK UNIFIED IDEOGRAPH-8568 +U+8569 # 38-02, CJK UNIFIED IDEOGRAPH-8569 +U+856A # 41-83, CJK UNIFIED IDEOGRAPH-856A +U+856D # 73-11, CJK UNIFIED IDEOGRAPH-856D +U+8577 # 73-17, CJK UNIFIED IDEOGRAPH-8577 +U+857E # 73-18, CJK UNIFIED IDEOGRAPH-857E +U+8580 # 73-05, CJK UNIFIED IDEOGRAPH-8580 +U+8584 # 39-86, CJK UNIFIED IDEOGRAPH-8584 +U+8587 # 73-15, CJK UNIFIED IDEOGRAPH-8587 +U+8588 # 73-07, CJK UNIFIED IDEOGRAPH-8588 +U+858A # 73-09, CJK UNIFIED IDEOGRAPH-858A +U+8590 # 73-19, CJK UNIFIED IDEOGRAPH-8590 +U+8591 # 73-08, CJK UNIFIED IDEOGRAPH-8591 +U+8594 # 73-12, CJK UNIFIED IDEOGRAPH-8594 +U+8597 # 17-82, CJK UNIFIED IDEOGRAPH-8597 +U+8599 # 38-69, CJK UNIFIED IDEOGRAPH-8599 +U+859B # 73-13, CJK UNIFIED IDEOGRAPH-859B +U+859C # 73-16, CJK UNIFIED IDEOGRAPH-859C +U+85A4 # 73-06, CJK UNIFIED IDEOGRAPH-85A4 +U+85A6 # 33-06, CJK UNIFIED IDEOGRAPH-85A6 +U+85A8 # 73-10, CJK UNIFIED IDEOGRAPH-85A8 +U+85A9 # 27-07, CJK UNIFIED IDEOGRAPH-85A9 +U+85AA # 31-37, CJK UNIFIED IDEOGRAPH-85AA +U+85AB # 23-16, CJK UNIFIED IDEOGRAPH-85AB +U+85AC # 44-84, CJK UNIFIED IDEOGRAPH-85AC +U+85AE # 44-89, CJK UNIFIED IDEOGRAPH-85AE +U+85AF # 29-82, CJK UNIFIED IDEOGRAPH-85AF +U+85B9 # 73-23, CJK UNIFIED IDEOGRAPH-85B9 +U+85BA # 73-21, CJK UNIFIED IDEOGRAPH-85BA +U+85C1 # 47-46, CJK UNIFIED IDEOGRAPH-85C1 +U+85C9 # 73-20, CJK UNIFIED IDEOGRAPH-85C9 +U+85CD # 45-85, CJK UNIFIED IDEOGRAPH-85CD +U+85CF # 73-22, CJK UNIFIED IDEOGRAPH-85CF +U+85D0 # 73-24, CJK UNIFIED IDEOGRAPH-85D0 +U+85D5 # 73-25, CJK UNIFIED IDEOGRAPH-85D5 +U+85DC # 73-28, CJK UNIFIED IDEOGRAPH-85DC +U+85DD # 73-26, CJK UNIFIED IDEOGRAPH-85DD +U+85E4 # 38-03, CJK UNIFIED IDEOGRAPH-85E4 +U+85E5 # 73-27, CJK UNIFIED IDEOGRAPH-85E5 +U+85E9 # 40-45, CJK UNIFIED IDEOGRAPH-85E9 +U+85EA # 73-14, CJK UNIFIED IDEOGRAPH-85EA +U+85F7 # 29-83, CJK UNIFIED IDEOGRAPH-85F7 +U+85F9 # 73-29, CJK UNIFIED IDEOGRAPH-85F9 +U+85FA # 73-34, CJK UNIFIED IDEOGRAPH-85FA +U+85FB # 33-84, CJK UNIFIED IDEOGRAPH-85FB +U+85FE # 73-33, CJK UNIFIED IDEOGRAPH-85FE +U+8602 # 73-02, CJK UNIFIED IDEOGRAPH-8602 +U+8606 # 73-35, CJK UNIFIED IDEOGRAPH-8606 +U+8607 # 33-41, CJK UNIFIED IDEOGRAPH-8607 +U+860A # 73-30, CJK UNIFIED IDEOGRAPH-860A +U+860B # 73-32, CJK UNIFIED IDEOGRAPH-860B +U+8613 # 73-31, CJK UNIFIED IDEOGRAPH-8613 +U+8616 # 61-17, CJK UNIFIED IDEOGRAPH-8616 +U+8617 # 61-02, CJK UNIFIED IDEOGRAPH-8617 +U+861A # 73-37, CJK UNIFIED IDEOGRAPH-861A +U+8622 # 73-36, CJK UNIFIED IDEOGRAPH-8622 +U+862D # 45-86, CJK UNIFIED IDEOGRAPH-862D +U+862F # 66-28, CJK UNIFIED IDEOGRAPH-862F +U+8630 # 73-38, CJK UNIFIED IDEOGRAPH-8630 +U+863F # 73-39, CJK UNIFIED IDEOGRAPH-863F +U+864D # 73-40, CJK UNIFIED IDEOGRAPH-864D +U+864E # 24-55, CJK UNIFIED IDEOGRAPH-864E +U+8650 # 21-52, CJK UNIFIED IDEOGRAPH-8650 +U+8654 # 73-42, CJK UNIFIED IDEOGRAPH-8654 +U+8655 # 49-61, CJK UNIFIED IDEOGRAPH-8655 +U+865A # 21-85, CJK UNIFIED IDEOGRAPH-865A +U+865C # 46-26, CJK UNIFIED IDEOGRAPH-865C +U+865E # 22-83, CJK UNIFIED IDEOGRAPH-865E +U+865F # 73-43, CJK UNIFIED IDEOGRAPH-865F +U+8667 # 73-44, CJK UNIFIED IDEOGRAPH-8667 +U+866B # 35-78, CJK UNIFIED IDEOGRAPH-866B +U+8671 # 73-45, CJK UNIFIED IDEOGRAPH-8671 +U+8679 # 38-90, CJK UNIFIED IDEOGRAPH-8679 +U+867B # 16-26, CJK UNIFIED IDEOGRAPH-867B +U+868A # 18-67, CJK UNIFIED IDEOGRAPH-868A +U+868B # 73-50, CJK UNIFIED IDEOGRAPH-868B +U+868C # 73-51, CJK UNIFIED IDEOGRAPH-868C +U+8693 # 73-46, CJK UNIFIED IDEOGRAPH-8693 +U+8695 # 27-29, CJK UNIFIED IDEOGRAPH-8695 +U+86A3 # 73-47, CJK UNIFIED IDEOGRAPH-86A3 +U+86A4 # 39-34, CJK UNIFIED IDEOGRAPH-86A4 +U+86A9 # 73-48, CJK UNIFIED IDEOGRAPH-86A9 +U+86AA # 73-49, CJK UNIFIED IDEOGRAPH-86AA +U+86AB # 73-59, CJK UNIFIED IDEOGRAPH-86AB +U+86AF # 73-53, CJK UNIFIED IDEOGRAPH-86AF +U+86B0 # 73-56, CJK UNIFIED IDEOGRAPH-86B0 +U+86B6 # 73-52, CJK UNIFIED IDEOGRAPH-86B6 +U+86C4 # 73-54, CJK UNIFIED IDEOGRAPH-86C4 +U+86C6 # 73-55, CJK UNIFIED IDEOGRAPH-86C6 +U+86C7 # 28-56, CJK UNIFIED IDEOGRAPH-86C7 +U+86C9 # 73-57, CJK UNIFIED IDEOGRAPH-86C9 +U+86CB # 35-33, CJK UNIFIED IDEOGRAPH-86CB +U+86CD # 23-54, CJK UNIFIED IDEOGRAPH-86CD +U+86CE # 19-34, CJK UNIFIED IDEOGRAPH-86CE +U+86D4 # 73-60, CJK UNIFIED IDEOGRAPH-86D4 +U+86D9 # 19-31, CJK UNIFIED IDEOGRAPH-86D9 +U+86DB # 73-65, CJK UNIFIED IDEOGRAPH-86DB +U+86DE # 73-61, CJK UNIFIED IDEOGRAPH-86DE +U+86DF # 73-64, CJK UNIFIED IDEOGRAPH-86DF +U+86E4 # 40-26, CJK UNIFIED IDEOGRAPH-86E4 +U+86E9 # 73-62, CJK UNIFIED IDEOGRAPH-86E9 +U+86EC # 73-63, CJK UNIFIED IDEOGRAPH-86EC +U+86ED # 41-40, CJK UNIFIED IDEOGRAPH-86ED +U+86EE # 40-58, CJK UNIFIED IDEOGRAPH-86EE +U+86EF # 73-66, CJK UNIFIED IDEOGRAPH-86EF +U+86F8 # 34-93, CJK UNIFIED IDEOGRAPH-86F8 +U+86F9 # 73-76, CJK UNIFIED IDEOGRAPH-86F9 +U+86FB # 73-72, CJK UNIFIED IDEOGRAPH-86FB +U+86FE # 18-75, CJK UNIFIED IDEOGRAPH-86FE +U+8700 # 73-70, CJK UNIFIED IDEOGRAPH-8700 +U+8702 # 43-10, CJK UNIFIED IDEOGRAPH-8702 +U+8703 # 73-71, CJK UNIFIED IDEOGRAPH-8703 +U+8706 # 73-68, CJK UNIFIED IDEOGRAPH-8706 +U+8708 # 73-69, CJK UNIFIED IDEOGRAPH-8708 +U+8709 # 73-74, CJK UNIFIED IDEOGRAPH-8709 +U+870A # 73-77, CJK UNIFIED IDEOGRAPH-870A +U+870D # 73-75, CJK UNIFIED IDEOGRAPH-870D +U+8711 # 73-73, CJK UNIFIED IDEOGRAPH-8711 +U+8712 # 73-67, CJK UNIFIED IDEOGRAPH-8712 +U+8718 # 35-56, CJK UNIFIED IDEOGRAPH-8718 +U+871A # 73-84, CJK UNIFIED IDEOGRAPH-871A +U+871C # 44-10, CJK UNIFIED IDEOGRAPH-871C +U+8725 # 73-82, CJK UNIFIED IDEOGRAPH-8725 +U+8729 # 73-83, CJK UNIFIED IDEOGRAPH-8729 +U+8734 # 73-78, CJK UNIFIED IDEOGRAPH-8734 +U+8737 # 73-80, CJK UNIFIED IDEOGRAPH-8737 +U+873B # 73-81, CJK UNIFIED IDEOGRAPH-873B +U+873F # 73-79, CJK UNIFIED IDEOGRAPH-873F +U+8749 # 32-70, CJK UNIFIED IDEOGRAPH-8749 +U+874B # 47-25, CJK UNIFIED IDEOGRAPH-874B +U+874C # 73-88, CJK UNIFIED IDEOGRAPH-874C +U+874E # 73-89, CJK UNIFIED IDEOGRAPH-874E +U+8753 # 74-01, CJK UNIFIED IDEOGRAPH-8753 +U+8755 # 31-10, CJK UNIFIED IDEOGRAPH-8755 +U+8757 # 73-91, CJK UNIFIED IDEOGRAPH-8757 +U+8759 # 73-94, CJK UNIFIED IDEOGRAPH-8759 +U+875F # 73-86, CJK UNIFIED IDEOGRAPH-875F +U+8760 # 73-85, CJK UNIFIED IDEOGRAPH-8760 +U+8763 # 74-02, CJK UNIFIED IDEOGRAPH-8763 +U+8766 # 18-60, CJK UNIFIED IDEOGRAPH-8766 +U+8768 # 73-92, CJK UNIFIED IDEOGRAPH-8768 +U+876A # 74-03, CJK UNIFIED IDEOGRAPH-876A +U+876E # 73-93, CJK UNIFIED IDEOGRAPH-876E +U+8774 # 73-90, CJK UNIFIED IDEOGRAPH-8774 +U+8776 # 36-19, CJK UNIFIED IDEOGRAPH-8776 +U+8778 # 73-87, CJK UNIFIED IDEOGRAPH-8778 +U+877F # 39-72, CJK UNIFIED IDEOGRAPH-877F +U+8782 # 74-07, CJK UNIFIED IDEOGRAPH-8782 +U+878D # 45-27, CJK UNIFIED IDEOGRAPH-878D +U+879F # 74-06, CJK UNIFIED IDEOGRAPH-879F +U+87A2 # 74-05, CJK UNIFIED IDEOGRAPH-87A2 +U+87AB # 74-14, CJK UNIFIED IDEOGRAPH-87AB +U+87AF # 74-08, CJK UNIFIED IDEOGRAPH-87AF +U+87B3 # 74-16, CJK UNIFIED IDEOGRAPH-87B3 +U+87BA # 45-70, CJK UNIFIED IDEOGRAPH-87BA +U+87BB # 74-19, CJK UNIFIED IDEOGRAPH-87BB +U+87BD # 74-10, CJK UNIFIED IDEOGRAPH-87BD +U+87C0 # 74-11, CJK UNIFIED IDEOGRAPH-87C0 +U+87C4 # 74-15, CJK UNIFIED IDEOGRAPH-87C4 +U+87C6 # 74-18, CJK UNIFIED IDEOGRAPH-87C6 +U+87C7 # 74-17, CJK UNIFIED IDEOGRAPH-87C7 +U+87CB # 74-09, CJK UNIFIED IDEOGRAPH-87CB +U+87D0 # 74-12, CJK UNIFIED IDEOGRAPH-87D0 +U+87D2 # 74-29, CJK UNIFIED IDEOGRAPH-87D2 +U+87E0 # 74-22, CJK UNIFIED IDEOGRAPH-87E0 +U+87EF # 74-20, CJK UNIFIED IDEOGRAPH-87EF +U+87F2 # 74-21, CJK UNIFIED IDEOGRAPH-87F2 +U+87F6 # 74-26, CJK UNIFIED IDEOGRAPH-87F6 +U+87F7 # 74-27, CJK UNIFIED IDEOGRAPH-87F7 +U+87F9 # 19-10, CJK UNIFIED IDEOGRAPH-87F9 +U+87FB # 21-34, CJK UNIFIED IDEOGRAPH-87FB +U+87FE # 74-25, CJK UNIFIED IDEOGRAPH-87FE +U+8805 # 74-04, CJK UNIFIED IDEOGRAPH-8805 +U+880D # 74-24, CJK UNIFIED IDEOGRAPH-880D +U+880E # 74-28, CJK UNIFIED IDEOGRAPH-880E +U+880F # 74-23, CJK UNIFIED IDEOGRAPH-880F +U+8811 # 74-30, CJK UNIFIED IDEOGRAPH-8811 +U+8815 # 74-32, CJK UNIFIED IDEOGRAPH-8815 +U+8816 # 74-31, CJK UNIFIED IDEOGRAPH-8816 +U+8821 # 74-34, CJK UNIFIED IDEOGRAPH-8821 +U+8822 # 74-33, CJK UNIFIED IDEOGRAPH-8822 +U+8823 # 73-58, CJK UNIFIED IDEOGRAPH-8823 +U+8827 # 74-38, CJK UNIFIED IDEOGRAPH-8827 +U+8831 # 74-35, CJK UNIFIED IDEOGRAPH-8831 +U+8836 # 74-36, CJK UNIFIED IDEOGRAPH-8836 +U+8839 # 74-37, CJK UNIFIED IDEOGRAPH-8839 +U+883B # 74-39, CJK UNIFIED IDEOGRAPH-883B +U+8840 # 23-76, CJK UNIFIED IDEOGRAPH-8840 +U+8842 # 74-41, CJK UNIFIED IDEOGRAPH-8842 +U+8844 # 74-40, CJK UNIFIED IDEOGRAPH-8844 +U+8846 # 29-16, CJK UNIFIED IDEOGRAPH-8846 +U+884C # 25-52, CJK UNIFIED IDEOGRAPH-884C +U+884D # 62-07, CJK UNIFIED IDEOGRAPH-884D +U+8852 # 74-42, CJK UNIFIED IDEOGRAPH-8852 +U+8853 # 29-49, CJK UNIFIED IDEOGRAPH-8853 +U+8857 # 19-25, CJK UNIFIED IDEOGRAPH-8857 +U+8859 # 74-43, CJK UNIFIED IDEOGRAPH-8859 +U+885B # 17-50, CJK UNIFIED IDEOGRAPH-885B +U+885D # 30-55, CJK UNIFIED IDEOGRAPH-885D +U+885E # 74-44, CJK UNIFIED IDEOGRAPH-885E +U+8861 # 25-53, CJK UNIFIED IDEOGRAPH-8861 +U+8862 # 74-45, CJK UNIFIED IDEOGRAPH-8862 +U+8863 # 16-65, CJK UNIFIED IDEOGRAPH-8863 +U+8868 # 41-29, CJK UNIFIED IDEOGRAPH-8868 +U+886B # 74-46, CJK UNIFIED IDEOGRAPH-886B +U+8870 # 31-74, CJK UNIFIED IDEOGRAPH-8870 +U+8872 # 74-53, CJK UNIFIED IDEOGRAPH-8872 +U+8875 # 74-50, CJK UNIFIED IDEOGRAPH-8875 +U+8877 # 35-79, CJK UNIFIED IDEOGRAPH-8877 +U+887D # 74-51, CJK UNIFIED IDEOGRAPH-887D +U+887E # 74-48, CJK UNIFIED IDEOGRAPH-887E +U+887F # 22-62, CJK UNIFIED IDEOGRAPH-887F +U+8881 # 74-47, CJK UNIFIED IDEOGRAPH-8881 +U+8882 # 74-54, CJK UNIFIED IDEOGRAPH-8882 +U+8888 # 23-22, CJK UNIFIED IDEOGRAPH-8888 +U+888B # 34-62, CJK UNIFIED IDEOGRAPH-888B +U+888D # 74-60, CJK UNIFIED IDEOGRAPH-888D +U+8892 # 74-56, CJK UNIFIED IDEOGRAPH-8892 +U+8896 # 34-21, CJK UNIFIED IDEOGRAPH-8896 +U+8897 # 74-55, CJK UNIFIED IDEOGRAPH-8897 +U+8899 # 74-58, CJK UNIFIED IDEOGRAPH-8899 +U+889E # 74-49, CJK UNIFIED IDEOGRAPH-889E +U+88A2 # 74-59, CJK UNIFIED IDEOGRAPH-88A2 +U+88A4 # 74-61, CJK UNIFIED IDEOGRAPH-88A4 +U+88AB # 40-79, CJK UNIFIED IDEOGRAPH-88AB +U+88AE # 74-57, CJK UNIFIED IDEOGRAPH-88AE +U+88B0 # 74-62, CJK UNIFIED IDEOGRAPH-88B0 +U+88B1 # 74-64, CJK UNIFIED IDEOGRAPH-88B1 +U+88B4 # 24-51, CJK UNIFIED IDEOGRAPH-88B4 +U+88B5 # 74-52, CJK UNIFIED IDEOGRAPH-88B5 +U+88B7 # 16-33, CJK UNIFIED IDEOGRAPH-88B7 +U+88BF # 74-63, CJK UNIFIED IDEOGRAPH-88BF +U+88C1 # 26-59, CJK UNIFIED IDEOGRAPH-88C1 +U+88C2 # 46-86, CJK UNIFIED IDEOGRAPH-88C2 +U+88C3 # 74-65, CJK UNIFIED IDEOGRAPH-88C3 +U+88C4 # 74-66, CJK UNIFIED IDEOGRAPH-88C4 +U+88C5 # 33-85, CJK UNIFIED IDEOGRAPH-88C5 +U+88CF # 46-02, CJK UNIFIED IDEOGRAPH-88CF +U+88D4 # 74-67, CJK UNIFIED IDEOGRAPH-88D4 +U+88D5 # 45-21, CJK UNIFIED IDEOGRAPH-88D5 +U+88D8 # 74-68, CJK UNIFIED IDEOGRAPH-88D8 +U+88D9 # 74-69, CJK UNIFIED IDEOGRAPH-88D9 +U+88DC # 42-68, CJK UNIFIED IDEOGRAPH-88DC +U+88DD # 74-70, CJK UNIFIED IDEOGRAPH-88DD +U+88DF # 26-32, CJK UNIFIED IDEOGRAPH-88DF +U+88E1 # 46-03, CJK UNIFIED IDEOGRAPH-88E1 +U+88E8 # 74-75, CJK UNIFIED IDEOGRAPH-88E8 +U+88F2 # 74-76, CJK UNIFIED IDEOGRAPH-88F2 +U+88F3 # 30-56, CJK UNIFIED IDEOGRAPH-88F3 +U+88F4 # 74-74, CJK UNIFIED IDEOGRAPH-88F4 +U+88F8 # 45-71, CJK UNIFIED IDEOGRAPH-88F8 +U+88F9 # 74-71, CJK UNIFIED IDEOGRAPH-88F9 +U+88FC # 74-73, CJK UNIFIED IDEOGRAPH-88FC +U+88FD # 32-29, CJK UNIFIED IDEOGRAPH-88FD +U+88FE # 31-94, CJK UNIFIED IDEOGRAPH-88FE +U+8902 # 74-72, CJK UNIFIED IDEOGRAPH-8902 +U+8904 # 74-77, CJK UNIFIED IDEOGRAPH-8904 +U+8907 # 42-03, CJK UNIFIED IDEOGRAPH-8907 +U+890A # 74-79, CJK UNIFIED IDEOGRAPH-890A +U+890C # 74-78, CJK UNIFIED IDEOGRAPH-890C +U+8910 # 19-76, CJK UNIFIED IDEOGRAPH-8910 +U+8912 # 43-11, CJK UNIFIED IDEOGRAPH-8912 +U+8913 # 74-80, CJK UNIFIED IDEOGRAPH-8913 +U+891D # 74-92, CJK UNIFIED IDEOGRAPH-891D +U+891E # 74-82, CJK UNIFIED IDEOGRAPH-891E +U+8925 # 74-83, CJK UNIFIED IDEOGRAPH-8925 +U+892A # 74-84, CJK UNIFIED IDEOGRAPH-892A +U+892B # 74-85, CJK UNIFIED IDEOGRAPH-892B +U+8936 # 74-89, CJK UNIFIED IDEOGRAPH-8936 +U+8938 # 74-90, CJK UNIFIED IDEOGRAPH-8938 +U+893B # 74-88, CJK UNIFIED IDEOGRAPH-893B +U+8941 # 74-86, CJK UNIFIED IDEOGRAPH-8941 +U+8943 # 74-81, CJK UNIFIED IDEOGRAPH-8943 +U+8944 # 74-87, CJK UNIFIED IDEOGRAPH-8944 +U+894C # 74-91, CJK UNIFIED IDEOGRAPH-894C +U+894D # 80-23, CJK UNIFIED IDEOGRAPH-894D +U+8956 # 18-08, CJK UNIFIED IDEOGRAPH-8956 +U+895E # 74-94, CJK UNIFIED IDEOGRAPH-895E +U+895F # 22-63, CJK UNIFIED IDEOGRAPH-895F +U+8960 # 74-93, CJK UNIFIED IDEOGRAPH-8960 +U+8964 # 75-02, CJK UNIFIED IDEOGRAPH-8964 +U+8966 # 75-01, CJK UNIFIED IDEOGRAPH-8966 +U+896A # 75-04, CJK UNIFIED IDEOGRAPH-896A +U+896D # 75-03, CJK UNIFIED IDEOGRAPH-896D +U+896F # 75-05, CJK UNIFIED IDEOGRAPH-896F +U+8972 # 29-17, CJK UNIFIED IDEOGRAPH-8972 +U+8974 # 75-06, CJK UNIFIED IDEOGRAPH-8974 +U+8977 # 75-07, CJK UNIFIED IDEOGRAPH-8977 +U+897E # 75-08, CJK UNIFIED IDEOGRAPH-897E +U+897F # 32-30, CJK UNIFIED IDEOGRAPH-897F +U+8981 # 45-55, CJK UNIFIED IDEOGRAPH-8981 +U+8983 # 75-09, CJK UNIFIED IDEOGRAPH-8983 +U+8986 # 42-04, CJK UNIFIED IDEOGRAPH-8986 +U+8987 # 39-38, CJK UNIFIED IDEOGRAPH-8987 +U+8988 # 75-10, CJK UNIFIED IDEOGRAPH-8988 +U+898A # 75-11, CJK UNIFIED IDEOGRAPH-898A +U+898B # 24-11, CJK UNIFIED IDEOGRAPH-898B +U+898F # 21-12, CJK UNIFIED IDEOGRAPH-898F +U+8993 # 75-12, CJK UNIFIED IDEOGRAPH-8993 +U+8996 # 27-75, CJK UNIFIED IDEOGRAPH-8996 +U+8997 # 39-33, CJK UNIFIED IDEOGRAPH-8997 +U+8998 # 75-13, CJK UNIFIED IDEOGRAPH-8998 +U+899A # 19-48, CJK UNIFIED IDEOGRAPH-899A +U+89A1 # 75-14, CJK UNIFIED IDEOGRAPH-89A1 +U+89A6 # 75-16, CJK UNIFIED IDEOGRAPH-89A6 +U+89A7 # 45-87, CJK UNIFIED IDEOGRAPH-89A7 +U+89A9 # 75-15, CJK UNIFIED IDEOGRAPH-89A9 +U+89AA # 31-38, CJK UNIFIED IDEOGRAPH-89AA +U+89AC # 75-17, CJK UNIFIED IDEOGRAPH-89AC +U+89AF # 75-18, CJK UNIFIED IDEOGRAPH-89AF +U+89B2 # 75-19, CJK UNIFIED IDEOGRAPH-89B2 +U+89B3 # 20-49, CJK UNIFIED IDEOGRAPH-89B3 +U+89BA # 75-20, CJK UNIFIED IDEOGRAPH-89BA +U+89BD # 75-21, CJK UNIFIED IDEOGRAPH-89BD +U+89BF # 75-22, CJK UNIFIED IDEOGRAPH-89BF +U+89C0 # 75-23, CJK UNIFIED IDEOGRAPH-89C0 +U+89D2 # 19-49, CJK UNIFIED IDEOGRAPH-89D2 +U+89DA # 75-24, CJK UNIFIED IDEOGRAPH-89DA +U+89DC # 75-25, CJK UNIFIED IDEOGRAPH-89DC +U+89DD # 75-26, CJK UNIFIED IDEOGRAPH-89DD +U+89E3 # 18-82, CJK UNIFIED IDEOGRAPH-89E3 +U+89E6 # 31-08, CJK UNIFIED IDEOGRAPH-89E6 +U+89E7 # 75-27, CJK UNIFIED IDEOGRAPH-89E7 +U+89F4 # 75-28, CJK UNIFIED IDEOGRAPH-89F4 +U+89F8 # 75-29, CJK UNIFIED IDEOGRAPH-89F8 +U+8A00 # 24-32, CJK UNIFIED IDEOGRAPH-8A00 +U+8A02 # 36-91, CJK UNIFIED IDEOGRAPH-8A02 +U+8A03 # 75-30, CJK UNIFIED IDEOGRAPH-8A03 +U+8A08 # 23-55, CJK UNIFIED IDEOGRAPH-8A08 +U+8A0A # 31-54, CJK UNIFIED IDEOGRAPH-8A0A +U+8A0C # 75-33, CJK UNIFIED IDEOGRAPH-8A0C +U+8A0E # 38-04, CJK UNIFIED IDEOGRAPH-8A0E +U+8A10 # 75-32, CJK UNIFIED IDEOGRAPH-8A10 +U+8A13 # 23-17, CJK UNIFIED IDEOGRAPH-8A13 +U+8A16 # 75-31, CJK UNIFIED IDEOGRAPH-8A16 +U+8A17 # 34-87, CJK UNIFIED IDEOGRAPH-8A17 +U+8A18 # 21-13, CJK UNIFIED IDEOGRAPH-8A18 +U+8A1B # 75-34, CJK UNIFIED IDEOGRAPH-8A1B +U+8A1D # 75-35, CJK UNIFIED IDEOGRAPH-8A1D +U+8A1F # 30-57, CJK UNIFIED IDEOGRAPH-8A1F +U+8A23 # 23-77, CJK UNIFIED IDEOGRAPH-8A23 +U+8A25 # 75-36, CJK UNIFIED IDEOGRAPH-8A25 +U+8A2A # 43-12, CJK UNIFIED IDEOGRAPH-8A2A +U+8A2D # 32-63, CJK UNIFIED IDEOGRAPH-8A2D +U+8A31 # 21-86, CJK UNIFIED IDEOGRAPH-8A31 +U+8A33 # 44-85, CJK UNIFIED IDEOGRAPH-8A33 +U+8A34 # 33-42, CJK UNIFIED IDEOGRAPH-8A34 +U+8A36 # 75-37, CJK UNIFIED IDEOGRAPH-8A36 +U+8A3A # 31-39, CJK UNIFIED IDEOGRAPH-8A3A +U+8A3B # 35-80, CJK UNIFIED IDEOGRAPH-8A3B +U+8A3C # 30-58, CJK UNIFIED IDEOGRAPH-8A3C +U+8A41 # 75-38, CJK UNIFIED IDEOGRAPH-8A41 +U+8A46 # 75-41, CJK UNIFIED IDEOGRAPH-8A46 +U+8A48 # 75-42, CJK UNIFIED IDEOGRAPH-8A48 +U+8A50 # 26-30, CJK UNIFIED IDEOGRAPH-8A50 +U+8A51 # 34-34, CJK UNIFIED IDEOGRAPH-8A51 +U+8A52 # 75-40, CJK UNIFIED IDEOGRAPH-8A52 +U+8A54 # 30-59, CJK UNIFIED IDEOGRAPH-8A54 +U+8A55 # 41-30, CJK UNIFIED IDEOGRAPH-8A55 +U+8A5B # 75-39, CJK UNIFIED IDEOGRAPH-8A5B +U+8A5E # 27-76, CJK UNIFIED IDEOGRAPH-8A5E +U+8A60 # 17-51, CJK UNIFIED IDEOGRAPH-8A60 +U+8A62 # 75-46, CJK UNIFIED IDEOGRAPH-8A62 +U+8A63 # 23-56, CJK UNIFIED IDEOGRAPH-8A63 +U+8A66 # 27-78, CJK UNIFIED IDEOGRAPH-8A66 +U+8A69 # 27-77, CJK UNIFIED IDEOGRAPH-8A69 +U+8A6B # 47-45, CJK UNIFIED IDEOGRAPH-8A6B +U+8A6C # 75-45, CJK UNIFIED IDEOGRAPH-8A6C +U+8A6D # 75-44, CJK UNIFIED IDEOGRAPH-8A6D +U+8A6E # 33-07, CJK UNIFIED IDEOGRAPH-8A6E +U+8A70 # 21-45, CJK UNIFIED IDEOGRAPH-8A70 +U+8A71 # 47-35, CJK UNIFIED IDEOGRAPH-8A71 +U+8A72 # 19-26, CJK UNIFIED IDEOGRAPH-8A72 +U+8A73 # 30-60, CJK UNIFIED IDEOGRAPH-8A73 +U+8A7C # 75-43, CJK UNIFIED IDEOGRAPH-8A7C +U+8A82 # 75-48, CJK UNIFIED IDEOGRAPH-8A82 +U+8A84 # 75-49, CJK UNIFIED IDEOGRAPH-8A84 +U+8A85 # 75-47, CJK UNIFIED IDEOGRAPH-8A85 +U+8A87 # 24-56, CJK UNIFIED IDEOGRAPH-8A87 +U+8A89 # 45-32, CJK UNIFIED IDEOGRAPH-8A89 +U+8A8C # 27-79, CJK UNIFIED IDEOGRAPH-8A8C +U+8A8D # 39-07, CJK UNIFIED IDEOGRAPH-8A8D +U+8A91 # 75-52, CJK UNIFIED IDEOGRAPH-8A91 +U+8A93 # 32-32, CJK UNIFIED IDEOGRAPH-8A93 +U+8A95 # 35-34, CJK UNIFIED IDEOGRAPH-8A95 +U+8A98 # 45-22, CJK UNIFIED IDEOGRAPH-8A98 +U+8A9A # 75-55, CJK UNIFIED IDEOGRAPH-8A9A +U+8A9E # 24-76, CJK UNIFIED IDEOGRAPH-8A9E +U+8AA0 # 32-31, CJK UNIFIED IDEOGRAPH-8AA0 +U+8AA1 # 75-51, CJK UNIFIED IDEOGRAPH-8AA1 +U+8AA3 # 75-56, CJK UNIFIED IDEOGRAPH-8AA3 +U+8AA4 # 24-77, CJK UNIFIED IDEOGRAPH-8AA4 +U+8AA5 # 75-53, CJK UNIFIED IDEOGRAPH-8AA5 +U+8AA6 # 75-54, CJK UNIFIED IDEOGRAPH-8AA6 +U+8AA8 # 75-50, CJK UNIFIED IDEOGRAPH-8AA8 +U+8AAC # 32-66, CJK UNIFIED IDEOGRAPH-8AAC +U+8AAD # 38-41, CJK UNIFIED IDEOGRAPH-8AAD +U+8AB0 # 35-15, CJK UNIFIED IDEOGRAPH-8AB0 +U+8AB2 # 18-61, CJK UNIFIED IDEOGRAPH-8AB2 +U+8AB9 # 40-80, CJK UNIFIED IDEOGRAPH-8AB9 +U+8ABC # 21-35, CJK UNIFIED IDEOGRAPH-8ABC +U+8ABF # 36-20, CJK UNIFIED IDEOGRAPH-8ABF +U+8AC2 # 75-59, CJK UNIFIED IDEOGRAPH-8AC2 +U+8AC4 # 75-57, CJK UNIFIED IDEOGRAPH-8AC4 +U+8AC7 # 35-44, CJK UNIFIED IDEOGRAPH-8AC7 +U+8ACB # 32-33, CJK UNIFIED IDEOGRAPH-8ACB +U+8ACC # 20-50, CJK UNIFIED IDEOGRAPH-8ACC +U+8ACD # 75-58, CJK UNIFIED IDEOGRAPH-8ACD +U+8ACF # 31-59, CJK UNIFIED IDEOGRAPH-8ACF +U+8AD2 # 46-42, CJK UNIFIED IDEOGRAPH-8AD2 +U+8AD6 # 47-32, CJK UNIFIED IDEOGRAPH-8AD6 +U+8ADA # 75-60, CJK UNIFIED IDEOGRAPH-8ADA +U+8ADB # 75-71, CJK UNIFIED IDEOGRAPH-8ADB +U+8ADC # 36-21, CJK UNIFIED IDEOGRAPH-8ADC +U+8ADE # 75-70, CJK UNIFIED IDEOGRAPH-8ADE +U+8AE0 # 75-67, CJK UNIFIED IDEOGRAPH-8AE0 +U+8AE1 # 75-75, CJK UNIFIED IDEOGRAPH-8AE1 +U+8AE2 # 75-68, CJK UNIFIED IDEOGRAPH-8AE2 +U+8AE4 # 75-64, CJK UNIFIED IDEOGRAPH-8AE4 +U+8AE6 # 36-92, CJK UNIFIED IDEOGRAPH-8AE6 +U+8AE7 # 75-63, CJK UNIFIED IDEOGRAPH-8AE7 +U+8AEB # 75-61, CJK UNIFIED IDEOGRAPH-8AEB +U+8AED # 45-01, CJK UNIFIED IDEOGRAPH-8AED +U+8AEE # 27-80, CJK UNIFIED IDEOGRAPH-8AEE +U+8AF1 # 75-65, CJK UNIFIED IDEOGRAPH-8AF1 +U+8AF3 # 75-62, CJK UNIFIED IDEOGRAPH-8AF3 +U+8AF7 # 75-69, CJK UNIFIED IDEOGRAPH-8AF7 +U+8AF8 # 29-84, CJK UNIFIED IDEOGRAPH-8AF8 +U+8AFA # 24-33, CJK UNIFIED IDEOGRAPH-8AFA +U+8AFE # 34-90, CJK UNIFIED IDEOGRAPH-8AFE +U+8B00 # 43-37, CJK UNIFIED IDEOGRAPH-8B00 +U+8B01 # 17-58, CJK UNIFIED IDEOGRAPH-8B01 +U+8B02 # 16-66, CJK UNIFIED IDEOGRAPH-8B02 +U+8B04 # 38-05, CJK UNIFIED IDEOGRAPH-8B04 +U+8B07 # 75-73, CJK UNIFIED IDEOGRAPH-8B07 +U+8B0C # 75-72, CJK UNIFIED IDEOGRAPH-8B0C +U+8B0E # 38-70, CJK UNIFIED IDEOGRAPH-8B0E +U+8B10 # 75-77, CJK UNIFIED IDEOGRAPH-8B10 +U+8B14 # 75-66, CJK UNIFIED IDEOGRAPH-8B14 +U+8B16 # 75-76, CJK UNIFIED IDEOGRAPH-8B16 +U+8B17 # 75-78, CJK UNIFIED IDEOGRAPH-8B17 +U+8B19 # 24-12, CJK UNIFIED IDEOGRAPH-8B19 +U+8B1A # 75-74, CJK UNIFIED IDEOGRAPH-8B1A +U+8B1B # 25-54, CJK UNIFIED IDEOGRAPH-8B1B +U+8B1D # 28-53, CJK UNIFIED IDEOGRAPH-8B1D +U+8B20 # 75-79, CJK UNIFIED IDEOGRAPH-8B20 +U+8B21 # 45-56, CJK UNIFIED IDEOGRAPH-8B21 +U+8B26 # 75-82, CJK UNIFIED IDEOGRAPH-8B26 +U+8B28 # 75-85, CJK UNIFIED IDEOGRAPH-8B28 +U+8B2B # 75-83, CJK UNIFIED IDEOGRAPH-8B2B +U+8B2C # 41-21, CJK UNIFIED IDEOGRAPH-8B2C +U+8B33 # 75-80, CJK UNIFIED IDEOGRAPH-8B33 +U+8B39 # 22-64, CJK UNIFIED IDEOGRAPH-8B39 +U+8B3E # 75-84, CJK UNIFIED IDEOGRAPH-8B3E +U+8B41 # 75-86, CJK UNIFIED IDEOGRAPH-8B41 +U+8B49 # 75-90, CJK UNIFIED IDEOGRAPH-8B49 +U+8B4C # 75-87, CJK UNIFIED IDEOGRAPH-8B4C +U+8B4E # 75-89, CJK UNIFIED IDEOGRAPH-8B4E +U+8B4F # 75-88, CJK UNIFIED IDEOGRAPH-8B4F +U+8B56 # 75-91, CJK UNIFIED IDEOGRAPH-8B56 +U+8B58 # 28-17, CJK UNIFIED IDEOGRAPH-8B58 +U+8B5A # 75-93, CJK UNIFIED IDEOGRAPH-8B5A +U+8B5B # 75-92, CJK UNIFIED IDEOGRAPH-8B5B +U+8B5C # 41-72, CJK UNIFIED IDEOGRAPH-8B5C +U+8B5F # 76-01, CJK UNIFIED IDEOGRAPH-8B5F +U+8B66 # 23-57, CJK UNIFIED IDEOGRAPH-8B66 +U+8B6B # 75-94, CJK UNIFIED IDEOGRAPH-8B6B +U+8B6C # 76-02, CJK UNIFIED IDEOGRAPH-8B6C +U+8B6F # 76-03, CJK UNIFIED IDEOGRAPH-8B6F +U+8B70 # 21-36, CJK UNIFIED IDEOGRAPH-8B70 +U+8B71 # 70-33, CJK UNIFIED IDEOGRAPH-8B71 +U+8B72 # 30-89, CJK UNIFIED IDEOGRAPH-8B72 +U+8B74 # 76-04, CJK UNIFIED IDEOGRAPH-8B74 +U+8B77 # 24-78, CJK UNIFIED IDEOGRAPH-8B77 +U+8B7D # 76-05, CJK UNIFIED IDEOGRAPH-8B7D +U+8B80 # 76-06, CJK UNIFIED IDEOGRAPH-8B80 +U+8B83 # 27-30, CJK UNIFIED IDEOGRAPH-8B83 +U+8B8A # 58-46, CJK UNIFIED IDEOGRAPH-8B8A +U+8B8C # 76-07, CJK UNIFIED IDEOGRAPH-8B8C +U+8B8E # 76-08, CJK UNIFIED IDEOGRAPH-8B8E +U+8B90 # 29-18, CJK UNIFIED IDEOGRAPH-8B90 +U+8B92 # 76-09, CJK UNIFIED IDEOGRAPH-8B92 +U+8B93 # 76-10, CJK UNIFIED IDEOGRAPH-8B93 +U+8B96 # 76-11, CJK UNIFIED IDEOGRAPH-8B96 +U+8B99 # 76-12, CJK UNIFIED IDEOGRAPH-8B99 +U+8B9A # 76-13, CJK UNIFIED IDEOGRAPH-8B9A +U+8C37 # 35-11, CJK UNIFIED IDEOGRAPH-8C37 +U+8C3A # 76-14, CJK UNIFIED IDEOGRAPH-8C3A +U+8C3F # 76-16, CJK UNIFIED IDEOGRAPH-8C3F +U+8C41 # 76-15, CJK UNIFIED IDEOGRAPH-8C41 +U+8C46 # 38-06, CJK UNIFIED IDEOGRAPH-8C46 +U+8C48 # 76-17, CJK UNIFIED IDEOGRAPH-8C48 +U+8C4A # 43-13, CJK UNIFIED IDEOGRAPH-8C4A +U+8C4C # 76-18, CJK UNIFIED IDEOGRAPH-8C4C +U+8C4E # 76-19, CJK UNIFIED IDEOGRAPH-8C4E +U+8C50 # 76-20, CJK UNIFIED IDEOGRAPH-8C50 +U+8C55 # 76-21, CJK UNIFIED IDEOGRAPH-8C55 +U+8C5A # 38-58, CJK UNIFIED IDEOGRAPH-8C5A +U+8C61 # 30-61, CJK UNIFIED IDEOGRAPH-8C61 +U+8C62 # 76-22, CJK UNIFIED IDEOGRAPH-8C62 +U+8C6A # 25-75, CJK UNIFIED IDEOGRAPH-8C6A +U+8C6B # 48-14, CJK UNIFIED IDEOGRAPH-8C6B +U+8C6C # 76-23, CJK UNIFIED IDEOGRAPH-8C6C +U+8C78 # 76-24, CJK UNIFIED IDEOGRAPH-8C78 +U+8C79 # 41-31, CJK UNIFIED IDEOGRAPH-8C79 +U+8C7A # 76-25, CJK UNIFIED IDEOGRAPH-8C7A +U+8C7C # 76-33, CJK UNIFIED IDEOGRAPH-8C7C +U+8C82 # 76-26, CJK UNIFIED IDEOGRAPH-8C82 +U+8C85 # 76-28, CJK UNIFIED IDEOGRAPH-8C85 +U+8C89 # 76-27, CJK UNIFIED IDEOGRAPH-8C89 +U+8C8A # 76-29, CJK UNIFIED IDEOGRAPH-8C8A +U+8C8C # 43-38, CJK UNIFIED IDEOGRAPH-8C8C +U+8C8D # 76-30, CJK UNIFIED IDEOGRAPH-8C8D +U+8C8E # 76-31, CJK UNIFIED IDEOGRAPH-8C8E +U+8C94 # 76-32, CJK UNIFIED IDEOGRAPH-8C94 +U+8C98 # 76-34, CJK UNIFIED IDEOGRAPH-8C98 +U+8C9D # 19-13, CJK UNIFIED IDEOGRAPH-8C9D +U+8C9E # 36-71, CJK UNIFIED IDEOGRAPH-8C9E +U+8CA0 # 41-73, CJK UNIFIED IDEOGRAPH-8CA0 +U+8CA1 # 26-66, CJK UNIFIED IDEOGRAPH-8CA1 +U+8CA2 # 25-55, CJK UNIFIED IDEOGRAPH-8CA2 +U+8CA7 # 41-47, CJK UNIFIED IDEOGRAPH-8CA7 +U+8CA8 # 18-63, CJK UNIFIED IDEOGRAPH-8CA8 +U+8CA9 # 40-46, CJK UNIFIED IDEOGRAPH-8CA9 +U+8CAA # 76-37, CJK UNIFIED IDEOGRAPH-8CAA +U+8CAB # 20-51, CJK UNIFIED IDEOGRAPH-8CAB +U+8CAC # 32-53, CJK UNIFIED IDEOGRAPH-8CAC +U+8CAD # 76-36, CJK UNIFIED IDEOGRAPH-8CAD +U+8CAE # 76-41, CJK UNIFIED IDEOGRAPH-8CAE +U+8CAF # 35-89, CJK UNIFIED IDEOGRAPH-8CAF +U+8CB0 # 44-67, CJK UNIFIED IDEOGRAPH-8CB0 +U+8CB2 # 76-39, CJK UNIFIED IDEOGRAPH-8CB2 +U+8CB3 # 76-40, CJK UNIFIED IDEOGRAPH-8CB3 +U+8CB4 # 21-14, CJK UNIFIED IDEOGRAPH-8CB4 +U+8CB6 # 76-42, CJK UNIFIED IDEOGRAPH-8CB6 +U+8CB7 # 39-67, CJK UNIFIED IDEOGRAPH-8CB7 +U+8CB8 # 34-63, CJK UNIFIED IDEOGRAPH-8CB8 +U+8CBB # 40-81, CJK UNIFIED IDEOGRAPH-8CBB +U+8CBC # 37-29, CJK UNIFIED IDEOGRAPH-8CBC +U+8CBD # 76-38, CJK UNIFIED IDEOGRAPH-8CBD +U+8CBF # 43-39, CJK UNIFIED IDEOGRAPH-8CBF +U+8CC0 # 18-76, CJK UNIFIED IDEOGRAPH-8CC0 +U+8CC1 # 76-44, CJK UNIFIED IDEOGRAPH-8CC1 +U+8CC2 # 47-08, CJK UNIFIED IDEOGRAPH-8CC2 +U+8CC3 # 36-34, CJK UNIFIED IDEOGRAPH-8CC3 +U+8CC4 # 47-37, CJK UNIFIED IDEOGRAPH-8CC4 +U+8CC7 # 27-81, CJK UNIFIED IDEOGRAPH-8CC7 +U+8CC8 # 76-43, CJK UNIFIED IDEOGRAPH-8CC8 +U+8CCA # 34-17, CJK UNIFIED IDEOGRAPH-8CCA +U+8CCD # 76-60, CJK UNIFIED IDEOGRAPH-8CCD +U+8CCE # 33-08, CJK UNIFIED IDEOGRAPH-8CCE +U+8CD1 # 38-88, CJK UNIFIED IDEOGRAPH-8CD1 +U+8CD3 # 41-48, CJK UNIFIED IDEOGRAPH-8CD3 +U+8CDA # 76-47, CJK UNIFIED IDEOGRAPH-8CDA +U+8CDB # 27-31, CJK UNIFIED IDEOGRAPH-8CDB +U+8CDC # 27-82, CJK UNIFIED IDEOGRAPH-8CDC +U+8CDE # 30-62, CJK UNIFIED IDEOGRAPH-8CDE +U+8CE0 # 39-69, CJK UNIFIED IDEOGRAPH-8CE0 +U+8CE2 # 24-13, CJK UNIFIED IDEOGRAPH-8CE2 +U+8CE3 # 76-46, CJK UNIFIED IDEOGRAPH-8CE3 +U+8CE4 # 76-45, CJK UNIFIED IDEOGRAPH-8CE4 +U+8CE6 # 41-74, CJK UNIFIED IDEOGRAPH-8CE6 +U+8CEA # 28-33, CJK UNIFIED IDEOGRAPH-8CEA +U+8CED # 37-50, CJK UNIFIED IDEOGRAPH-8CED +U+8CFA # 76-49, CJK UNIFIED IDEOGRAPH-8CFA +U+8CFB # 76-50, CJK UNIFIED IDEOGRAPH-8CFB +U+8CFC # 25-56, CJK UNIFIED IDEOGRAPH-8CFC +U+8CFD # 76-48, CJK UNIFIED IDEOGRAPH-8CFD +U+8D04 # 76-51, CJK UNIFIED IDEOGRAPH-8D04 +U+8D05 # 76-52, CJK UNIFIED IDEOGRAPH-8D05 +U+8D07 # 76-54, CJK UNIFIED IDEOGRAPH-8D07 +U+8D08 # 34-03, CJK UNIFIED IDEOGRAPH-8D08 +U+8D0A # 76-53, CJK UNIFIED IDEOGRAPH-8D0A +U+8D0B # 20-70, CJK UNIFIED IDEOGRAPH-8D0B +U+8D0D # 76-56, CJK UNIFIED IDEOGRAPH-8D0D +U+8D0F # 76-55, CJK UNIFIED IDEOGRAPH-8D0F +U+8D10 # 76-57, CJK UNIFIED IDEOGRAPH-8D10 +U+8D13 # 76-59, CJK UNIFIED IDEOGRAPH-8D13 +U+8D14 # 76-61, CJK UNIFIED IDEOGRAPH-8D14 +U+8D16 # 76-62, CJK UNIFIED IDEOGRAPH-8D16 +U+8D64 # 32-54, CJK UNIFIED IDEOGRAPH-8D64 +U+8D66 # 28-47, CJK UNIFIED IDEOGRAPH-8D66 +U+8D67 # 76-63, CJK UNIFIED IDEOGRAPH-8D67 +U+8D6B # 19-50, CJK UNIFIED IDEOGRAPH-8D6B +U+8D6D # 76-64, CJK UNIFIED IDEOGRAPH-8D6D +U+8D70 # 33-86, CJK UNIFIED IDEOGRAPH-8D70 +U+8D71 # 76-65, CJK UNIFIED IDEOGRAPH-8D71 +U+8D73 # 76-66, CJK UNIFIED IDEOGRAPH-8D73 +U+8D74 # 41-75, CJK UNIFIED IDEOGRAPH-8D74 +U+8D77 # 21-15, CJK UNIFIED IDEOGRAPH-8D77 +U+8D81 # 76-67, CJK UNIFIED IDEOGRAPH-8D81 +U+8D85 # 36-22, CJK UNIFIED IDEOGRAPH-8D85 +U+8D8A # 17-59, CJK UNIFIED IDEOGRAPH-8D8A +U+8D99 # 76-68, CJK UNIFIED IDEOGRAPH-8D99 +U+8DA3 # 28-81, CJK UNIFIED IDEOGRAPH-8DA3 +U+8DA8 # 31-86, CJK UNIFIED IDEOGRAPH-8DA8 +U+8DB3 # 34-13, CJK UNIFIED IDEOGRAPH-8DB3 +U+8DBA # 76-71, CJK UNIFIED IDEOGRAPH-8DBA +U+8DBE # 76-70, CJK UNIFIED IDEOGRAPH-8DBE +U+8DC2 # 76-69, CJK UNIFIED IDEOGRAPH-8DC2 +U+8DCB # 76-77, CJK UNIFIED IDEOGRAPH-8DCB +U+8DCC # 76-75, CJK UNIFIED IDEOGRAPH-8DCC +U+8DCF # 76-72, CJK UNIFIED IDEOGRAPH-8DCF +U+8DD6 # 76-74, CJK UNIFIED IDEOGRAPH-8DD6 +U+8DDA # 76-73, CJK UNIFIED IDEOGRAPH-8DDA +U+8DDB # 76-76, CJK UNIFIED IDEOGRAPH-8DDB +U+8DDD # 21-87, CJK UNIFIED IDEOGRAPH-8DDD +U+8DDF # 76-80, CJK UNIFIED IDEOGRAPH-8DDF +U+8DE1 # 32-55, CJK UNIFIED IDEOGRAPH-8DE1 +U+8DE3 # 76-81, CJK UNIFIED IDEOGRAPH-8DE3 +U+8DE8 # 24-57, CJK UNIFIED IDEOGRAPH-8DE8 +U+8DEA # 76-78, CJK UNIFIED IDEOGRAPH-8DEA +U+8DEB # 76-79, CJK UNIFIED IDEOGRAPH-8DEB +U+8DEF # 47-09, CJK UNIFIED IDEOGRAPH-8DEF +U+8DF3 # 36-23, CJK UNIFIED IDEOGRAPH-8DF3 +U+8DF5 # 33-09, CJK UNIFIED IDEOGRAPH-8DF5 +U+8DFC # 76-82, CJK UNIFIED IDEOGRAPH-8DFC +U+8DFF # 76-85, CJK UNIFIED IDEOGRAPH-8DFF +U+8E08 # 76-83, CJK UNIFIED IDEOGRAPH-8E08 +U+8E09 # 76-84, CJK UNIFIED IDEOGRAPH-8E09 +U+8E0A # 45-57, CJK UNIFIED IDEOGRAPH-8E0A +U+8E0F # 38-07, CJK UNIFIED IDEOGRAPH-8E0F +U+8E10 # 76-88, CJK UNIFIED IDEOGRAPH-8E10 +U+8E1D # 76-86, CJK UNIFIED IDEOGRAPH-8E1D +U+8E1E # 76-87, CJK UNIFIED IDEOGRAPH-8E1E +U+8E1F # 76-89, CJK UNIFIED IDEOGRAPH-8E1F +U+8E2A # 77-09, CJK UNIFIED IDEOGRAPH-8E2A +U+8E30 # 76-92, CJK UNIFIED IDEOGRAPH-8E30 +U+8E34 # 76-93, CJK UNIFIED IDEOGRAPH-8E34 +U+8E35 # 76-91, CJK UNIFIED IDEOGRAPH-8E35 +U+8E42 # 76-90, CJK UNIFIED IDEOGRAPH-8E42 +U+8E44 # 36-93, CJK UNIFIED IDEOGRAPH-8E44 +U+8E47 # 77-01, CJK UNIFIED IDEOGRAPH-8E47 +U+8E48 # 77-05, CJK UNIFIED IDEOGRAPH-8E48 +U+8E49 # 77-02, CJK UNIFIED IDEOGRAPH-8E49 +U+8E4A # 76-94, CJK UNIFIED IDEOGRAPH-8E4A +U+8E4C # 77-03, CJK UNIFIED IDEOGRAPH-8E4C +U+8E50 # 77-04, CJK UNIFIED IDEOGRAPH-8E50 +U+8E55 # 77-11, CJK UNIFIED IDEOGRAPH-8E55 +U+8E59 # 77-06, CJK UNIFIED IDEOGRAPH-8E59 +U+8E5F # 32-56, CJK UNIFIED IDEOGRAPH-8E5F +U+8E60 # 77-08, CJK UNIFIED IDEOGRAPH-8E60 +U+8E63 # 77-10, CJK UNIFIED IDEOGRAPH-8E63 +U+8E64 # 77-07, CJK UNIFIED IDEOGRAPH-8E64 +U+8E72 # 77-13, CJK UNIFIED IDEOGRAPH-8E72 +U+8E74 # 29-19, CJK UNIFIED IDEOGRAPH-8E74 +U+8E76 # 77-12, CJK UNIFIED IDEOGRAPH-8E76 +U+8E7C # 77-14, CJK UNIFIED IDEOGRAPH-8E7C +U+8E81 # 77-15, CJK UNIFIED IDEOGRAPH-8E81 +U+8E84 # 77-18, CJK UNIFIED IDEOGRAPH-8E84 +U+8E85 # 77-17, CJK UNIFIED IDEOGRAPH-8E85 +U+8E87 # 77-16, CJK UNIFIED IDEOGRAPH-8E87 +U+8E8A # 77-20, CJK UNIFIED IDEOGRAPH-8E8A +U+8E8B # 77-19, CJK UNIFIED IDEOGRAPH-8E8B +U+8E8D # 44-86, CJK UNIFIED IDEOGRAPH-8E8D +U+8E91 # 77-22, CJK UNIFIED IDEOGRAPH-8E91 +U+8E93 # 77-21, CJK UNIFIED IDEOGRAPH-8E93 +U+8E94 # 77-23, CJK UNIFIED IDEOGRAPH-8E94 +U+8E99 # 77-24, CJK UNIFIED IDEOGRAPH-8E99 +U+8EA1 # 77-26, CJK UNIFIED IDEOGRAPH-8EA1 +U+8EAA # 77-25, CJK UNIFIED IDEOGRAPH-8EAA +U+8EAB # 31-40, CJK UNIFIED IDEOGRAPH-8EAB +U+8EAC # 77-27, CJK UNIFIED IDEOGRAPH-8EAC +U+8EAF # 22-77, CJK UNIFIED IDEOGRAPH-8EAF +U+8EB0 # 77-28, CJK UNIFIED IDEOGRAPH-8EB0 +U+8EB1 # 77-30, CJK UNIFIED IDEOGRAPH-8EB1 +U+8EBE # 77-31, CJK UNIFIED IDEOGRAPH-8EBE +U+8EC5 # 77-32, CJK UNIFIED IDEOGRAPH-8EC5 +U+8EC6 # 77-29, CJK UNIFIED IDEOGRAPH-8EC6 +U+8EC8 # 77-33, CJK UNIFIED IDEOGRAPH-8EC8 +U+8ECA # 28-54, CJK UNIFIED IDEOGRAPH-8ECA +U+8ECB # 77-34, CJK UNIFIED IDEOGRAPH-8ECB +U+8ECC # 21-16, CJK UNIFIED IDEOGRAPH-8ECC +U+8ECD # 23-19, CJK UNIFIED IDEOGRAPH-8ECD +U+8ED2 # 24-14, CJK UNIFIED IDEOGRAPH-8ED2 +U+8EDB # 77-35, CJK UNIFIED IDEOGRAPH-8EDB +U+8EDF # 38-80, CJK UNIFIED IDEOGRAPH-8EDF +U+8EE2 # 37-30, CJK UNIFIED IDEOGRAPH-8EE2 +U+8EE3 # 77-36, CJK UNIFIED IDEOGRAPH-8EE3 +U+8EEB # 77-39, CJK UNIFIED IDEOGRAPH-8EEB +U+8EF8 # 28-20, CJK UNIFIED IDEOGRAPH-8EF8 +U+8EFB # 77-38, CJK UNIFIED IDEOGRAPH-8EFB +U+8EFC # 77-37, CJK UNIFIED IDEOGRAPH-8EFC +U+8EFD # 23-58, CJK UNIFIED IDEOGRAPH-8EFD +U+8EFE # 77-40, CJK UNIFIED IDEOGRAPH-8EFE +U+8F03 # 19-51, CJK UNIFIED IDEOGRAPH-8F03 +U+8F05 # 77-42, CJK UNIFIED IDEOGRAPH-8F05 +U+8F09 # 26-60, CJK UNIFIED IDEOGRAPH-8F09 +U+8F0A # 77-41, CJK UNIFIED IDEOGRAPH-8F0A +U+8F0C # 77-50, CJK UNIFIED IDEOGRAPH-8F0C +U+8F12 # 77-44, CJK UNIFIED IDEOGRAPH-8F12 +U+8F13 # 77-46, CJK UNIFIED IDEOGRAPH-8F13 +U+8F14 # 42-69, CJK UNIFIED IDEOGRAPH-8F14 +U+8F15 # 77-43, CJK UNIFIED IDEOGRAPH-8F15 +U+8F19 # 77-45, CJK UNIFIED IDEOGRAPH-8F19 +U+8F1B # 77-49, CJK UNIFIED IDEOGRAPH-8F1B +U+8F1C # 77-47, CJK UNIFIED IDEOGRAPH-8F1C +U+8F1D # 21-17, CJK UNIFIED IDEOGRAPH-8F1D +U+8F1F # 77-48, CJK UNIFIED IDEOGRAPH-8F1F +U+8F26 # 77-51, CJK UNIFIED IDEOGRAPH-8F26 +U+8F29 # 39-58, CJK UNIFIED IDEOGRAPH-8F29 +U+8F2A # 46-56, CJK UNIFIED IDEOGRAPH-8F2A +U+8F2F # 29-20, CJK UNIFIED IDEOGRAPH-8F2F +U+8F33 # 77-52, CJK UNIFIED IDEOGRAPH-8F33 +U+8F38 # 45-02, CJK UNIFIED IDEOGRAPH-8F38 +U+8F39 # 77-54, CJK UNIFIED IDEOGRAPH-8F39 +U+8F3B # 77-53, CJK UNIFIED IDEOGRAPH-8F3B +U+8F3E # 77-57, CJK UNIFIED IDEOGRAPH-8F3E +U+8F3F # 45-33, CJK UNIFIED IDEOGRAPH-8F3F +U+8F42 # 77-56, CJK UNIFIED IDEOGRAPH-8F42 +U+8F44 # 19-77, CJK UNIFIED IDEOGRAPH-8F44 +U+8F45 # 77-55, CJK UNIFIED IDEOGRAPH-8F45 +U+8F46 # 77-60, CJK UNIFIED IDEOGRAPH-8F46 +U+8F49 # 77-59, CJK UNIFIED IDEOGRAPH-8F49 +U+8F4C # 77-58, CJK UNIFIED IDEOGRAPH-8F4C +U+8F4D # 37-18, CJK UNIFIED IDEOGRAPH-8F4D +U+8F4E # 77-61, CJK UNIFIED IDEOGRAPH-8F4E +U+8F57 # 77-62, CJK UNIFIED IDEOGRAPH-8F57 +U+8F5C # 77-63, CJK UNIFIED IDEOGRAPH-8F5C +U+8F5F # 25-76, CJK UNIFIED IDEOGRAPH-8F5F +U+8F61 # 23-05, CJK UNIFIED IDEOGRAPH-8F61 +U+8F62 # 77-64, CJK UNIFIED IDEOGRAPH-8F62 +U+8F63 # 77-65, CJK UNIFIED IDEOGRAPH-8F63 +U+8F64 # 77-66, CJK UNIFIED IDEOGRAPH-8F64 +U+8F9B # 31-41, CJK UNIFIED IDEOGRAPH-8F9B +U+8F9C # 77-67, CJK UNIFIED IDEOGRAPH-8F9C +U+8F9E # 28-13, CJK UNIFIED IDEOGRAPH-8F9E +U+8F9F # 77-68, CJK UNIFIED IDEOGRAPH-8F9F +U+8FA3 # 77-69, CJK UNIFIED IDEOGRAPH-8FA3 +U+8FA7 # 50-01, CJK UNIFIED IDEOGRAPH-8FA7 +U+8FA8 # 49-94, CJK UNIFIED IDEOGRAPH-8FA8 +U+8FAD # 77-70, CJK UNIFIED IDEOGRAPH-8FAD +U+8FAE # 69-80, CJK UNIFIED IDEOGRAPH-8FAE +U+8FAF # 77-71, CJK UNIFIED IDEOGRAPH-8FAF +U+8FB0 # 35-04, CJK UNIFIED IDEOGRAPH-8FB0 +U+8FB1 # 31-11, CJK UNIFIED IDEOGRAPH-8FB1 +U+8FB2 # 39-32, CJK UNIFIED IDEOGRAPH-8FB2 +U+8FB7 # 77-72, CJK UNIFIED IDEOGRAPH-8FB7 +U+8FBA # 42-53, CJK UNIFIED IDEOGRAPH-8FBA +U+8FBB # 36-52, CJK UNIFIED IDEOGRAPH-8FBB +U+8FBC # 25-94, CJK UNIFIED IDEOGRAPH-8FBC +U+8FBF # 35-09, CJK UNIFIED IDEOGRAPH-8FBF +U+8FC2 # 17-10, CJK UNIFIED IDEOGRAPH-8FC2 +U+8FC4 # 43-88, CJK UNIFIED IDEOGRAPH-8FC4 +U+8FC5 # 31-55, CJK UNIFIED IDEOGRAPH-8FC5 +U+8FCE # 23-62, CJK UNIFIED IDEOGRAPH-8FCE +U+8FD1 # 22-65, CJK UNIFIED IDEOGRAPH-8FD1 +U+8FD4 # 42-54, CJK UNIFIED IDEOGRAPH-8FD4 +U+8FDA # 77-73, CJK UNIFIED IDEOGRAPH-8FDA +U+8FE2 # 77-75, CJK UNIFIED IDEOGRAPH-8FE2 +U+8FE5 # 77-74, CJK UNIFIED IDEOGRAPH-8FE5 +U+8FE6 # 18-64, CJK UNIFIED IDEOGRAPH-8FE6 +U+8FE9 # 38-86, CJK UNIFIED IDEOGRAPH-8FE9 +U+8FEA # 77-76, CJK UNIFIED IDEOGRAPH-8FEA +U+8FEB # 39-87, CJK UNIFIED IDEOGRAPH-8FEB +U+8FED # 37-19, CJK UNIFIED IDEOGRAPH-8FED +U+8FEF # 77-77, CJK UNIFIED IDEOGRAPH-8FEF +U+8FF0 # 29-50, CJK UNIFIED IDEOGRAPH-8FF0 +U+8FF4 # 77-79, CJK UNIFIED IDEOGRAPH-8FF4 +U+8FF7 # 44-34, CJK UNIFIED IDEOGRAPH-8FF7 +U+8FF8 # 77-94, CJK UNIFIED IDEOGRAPH-8FF8 +U+8FF9 # 77-81, CJK UNIFIED IDEOGRAPH-8FF9 +U+8FFA # 77-82, CJK UNIFIED IDEOGRAPH-8FFA +U+8FFD # 36-41, CJK UNIFIED IDEOGRAPH-8FFD +U+9000 # 34-64, CJK UNIFIED IDEOGRAPH-9000 +U+9001 # 33-87, CJK UNIFIED IDEOGRAPH-9001 +U+9003 # 38-08, CJK UNIFIED IDEOGRAPH-9003 +U+9005 # 77-80, CJK UNIFIED IDEOGRAPH-9005 +U+9006 # 21-53, CJK UNIFIED IDEOGRAPH-9006 +U+900B # 77-89, CJK UNIFIED IDEOGRAPH-900B +U+900D # 77-86, CJK UNIFIED IDEOGRAPH-900D +U+900E # 78-05, CJK UNIFIED IDEOGRAPH-900E +U+900F # 38-09, CJK UNIFIED IDEOGRAPH-900F +U+9010 # 35-64, CJK UNIFIED IDEOGRAPH-9010 +U+9011 # 77-83, CJK UNIFIED IDEOGRAPH-9011 +U+9013 # 36-94, CJK UNIFIED IDEOGRAPH-9013 +U+9014 # 37-51, CJK UNIFIED IDEOGRAPH-9014 +U+9015 # 77-84, CJK UNIFIED IDEOGRAPH-9015 +U+9016 # 77-88, CJK UNIFIED IDEOGRAPH-9016 +U+9017 # 31-64, CJK UNIFIED IDEOGRAPH-9017 +U+9019 # 39-71, CJK UNIFIED IDEOGRAPH-9019 +U+901A # 36-44, CJK UNIFIED IDEOGRAPH-901A +U+901D # 32-34, CJK UNIFIED IDEOGRAPH-901D +U+901E # 77-87, CJK UNIFIED IDEOGRAPH-901E +U+901F # 34-14, CJK UNIFIED IDEOGRAPH-901F +U+9020 # 34-04, CJK UNIFIED IDEOGRAPH-9020 +U+9021 # 77-85, CJK UNIFIED IDEOGRAPH-9021 +U+9022 # 16-09, CJK UNIFIED IDEOGRAPH-9022 +U+9023 # 47-02, CJK UNIFIED IDEOGRAPH-9023 +U+9027 # 77-90, CJK UNIFIED IDEOGRAPH-9027 +U+902E # 34-65, CJK UNIFIED IDEOGRAPH-902E +U+9031 # 29-21, CJK UNIFIED IDEOGRAPH-9031 +U+9032 # 31-42, CJK UNIFIED IDEOGRAPH-9032 +U+9035 # 77-92, CJK UNIFIED IDEOGRAPH-9035 +U+9036 # 77-91, CJK UNIFIED IDEOGRAPH-9036 +U+9038 # 16-79, CJK UNIFIED IDEOGRAPH-9038 +U+9039 # 77-93, CJK UNIFIED IDEOGRAPH-9039 +U+903C # 41-15, CJK UNIFIED IDEOGRAPH-903C +U+903E # 78-07, CJK UNIFIED IDEOGRAPH-903E +U+9041 # 38-59, CJK UNIFIED IDEOGRAPH-9041 +U+9042 # 31-75, CJK UNIFIED IDEOGRAPH-9042 +U+9045 # 35-57, CJK UNIFIED IDEOGRAPH-9045 +U+9047 # 22-88, CJK UNIFIED IDEOGRAPH-9047 +U+9049 # 78-06, CJK UNIFIED IDEOGRAPH-9049 +U+904A # 45-23, CJK UNIFIED IDEOGRAPH-904A +U+904B # 17-31, CJK UNIFIED IDEOGRAPH-904B +U+904D # 42-55, CJK UNIFIED IDEOGRAPH-904D +U+904E # 18-65, CJK UNIFIED IDEOGRAPH-904E +U+904F # 78-01, CJK UNIFIED IDEOGRAPH-904F +U+9050 # 78-02, CJK UNIFIED IDEOGRAPH-9050 +U+9051 # 78-03, CJK UNIFIED IDEOGRAPH-9051 +U+9052 # 78-04, CJK UNIFIED IDEOGRAPH-9052 +U+9053 # 38-27, CJK UNIFIED IDEOGRAPH-9053 +U+9054 # 35-03, CJK UNIFIED IDEOGRAPH-9054 +U+9055 # 16-67, CJK UNIFIED IDEOGRAPH-9055 +U+9056 # 78-08, CJK UNIFIED IDEOGRAPH-9056 +U+9058 # 78-09, CJK UNIFIED IDEOGRAPH-9058 +U+9059 # 84-03, CJK UNIFIED IDEOGRAPH-9059 +U+905C # 34-29, CJK UNIFIED IDEOGRAPH-905C +U+905E # 78-10, CJK UNIFIED IDEOGRAPH-905E +U+9060 # 17-83, CJK UNIFIED IDEOGRAPH-9060 +U+9061 # 33-44, CJK UNIFIED IDEOGRAPH-9061 +U+9063 # 24-15, CJK UNIFIED IDEOGRAPH-9063 +U+9065 # 45-58, CJK UNIFIED IDEOGRAPH-9065 +U+9068 # 78-11, CJK UNIFIED IDEOGRAPH-9068 +U+9069 # 37-12, CJK UNIFIED IDEOGRAPH-9069 +U+906D # 33-88, CJK UNIFIED IDEOGRAPH-906D +U+906E # 28-55, CJK UNIFIED IDEOGRAPH-906E +U+906F # 78-12, CJK UNIFIED IDEOGRAPH-906F +U+9072 # 78-15, CJK UNIFIED IDEOGRAPH-9072 +U+9075 # 29-69, CJK UNIFIED IDEOGRAPH-9075 +U+9076 # 78-13, CJK UNIFIED IDEOGRAPH-9076 +U+9077 # 33-11, CJK UNIFIED IDEOGRAPH-9077 +U+9078 # 33-10, CJK UNIFIED IDEOGRAPH-9078 +U+907A # 16-68, CJK UNIFIED IDEOGRAPH-907A +U+907C # 46-43, CJK UNIFIED IDEOGRAPH-907C +U+907D # 78-17, CJK UNIFIED IDEOGRAPH-907D +U+907F # 40-82, CJK UNIFIED IDEOGRAPH-907F +U+9080 # 78-19, CJK UNIFIED IDEOGRAPH-9080 +U+9081 # 78-18, CJK UNIFIED IDEOGRAPH-9081 +U+9082 # 78-16, CJK UNIFIED IDEOGRAPH-9082 +U+9083 # 67-68, CJK UNIFIED IDEOGRAPH-9083 +U+9084 # 20-52, CJK UNIFIED IDEOGRAPH-9084 +U+9087 # 77-78, CJK UNIFIED IDEOGRAPH-9087 +U+9089 # 78-21, CJK UNIFIED IDEOGRAPH-9089 +U+908A # 78-20, CJK UNIFIED IDEOGRAPH-908A +U+908F # 78-22, CJK UNIFIED IDEOGRAPH-908F +U+9091 # 45-24, CJK UNIFIED IDEOGRAPH-9091 +U+90A3 # 38-65, CJK UNIFIED IDEOGRAPH-90A3 +U+90A6 # 43-14, CJK UNIFIED IDEOGRAPH-90A6 +U+90A8 # 78-23, CJK UNIFIED IDEOGRAPH-90A8 +U+90AA # 28-57, CJK UNIFIED IDEOGRAPH-90AA +U+90AF # 78-24, CJK UNIFIED IDEOGRAPH-90AF +U+90B1 # 78-25, CJK UNIFIED IDEOGRAPH-90B1 +U+90B5 # 78-26, CJK UNIFIED IDEOGRAPH-90B5 +U+90B8 # 37-01, CJK UNIFIED IDEOGRAPH-90B8 +U+90C1 # 16-74, CJK UNIFIED IDEOGRAPH-90C1 +U+90CA # 25-57, CJK UNIFIED IDEOGRAPH-90CA +U+90CE # 47-26, CJK UNIFIED IDEOGRAPH-90CE +U+90DB # 78-30, CJK UNIFIED IDEOGRAPH-90DB +U+90E1 # 23-20, CJK UNIFIED IDEOGRAPH-90E1 +U+90E2 # 78-27, CJK UNIFIED IDEOGRAPH-90E2 +U+90E4 # 78-28, CJK UNIFIED IDEOGRAPH-90E4 +U+90E8 # 41-84, CJK UNIFIED IDEOGRAPH-90E8 +U+90ED # 19-52, CJK UNIFIED IDEOGRAPH-90ED +U+90F5 # 45-25, CJK UNIFIED IDEOGRAPH-90F5 +U+90F7 # 22-31, CJK UNIFIED IDEOGRAPH-90F7 +U+90FD # 37-52, CJK UNIFIED IDEOGRAPH-90FD +U+9102 # 78-31, CJK UNIFIED IDEOGRAPH-9102 +U+9112 # 78-32, CJK UNIFIED IDEOGRAPH-9112 +U+9119 # 78-33, CJK UNIFIED IDEOGRAPH-9119 +U+912D # 37-02, CJK UNIFIED IDEOGRAPH-912D +U+9130 # 78-35, CJK UNIFIED IDEOGRAPH-9130 +U+9132 # 78-34, CJK UNIFIED IDEOGRAPH-9132 +U+9149 # 38-51, CJK UNIFIED IDEOGRAPH-9149 +U+914A # 78-36, CJK UNIFIED IDEOGRAPH-914A +U+914B # 29-22, CJK UNIFIED IDEOGRAPH-914B +U+914C # 28-64, CJK UNIFIED IDEOGRAPH-914C +U+914D # 39-59, CJK UNIFIED IDEOGRAPH-914D +U+914E # 35-81, CJK UNIFIED IDEOGRAPH-914E +U+9152 # 28-82, CJK UNIFIED IDEOGRAPH-9152 +U+9154 # 31-76, CJK UNIFIED IDEOGRAPH-9154 +U+9156 # 78-37, CJK UNIFIED IDEOGRAPH-9156 +U+9158 # 78-38, CJK UNIFIED IDEOGRAPH-9158 +U+9162 # 31-61, CJK UNIFIED IDEOGRAPH-9162 +U+9163 # 78-39, CJK UNIFIED IDEOGRAPH-9163 +U+9165 # 78-40, CJK UNIFIED IDEOGRAPH-9165 +U+9169 # 78-41, CJK UNIFIED IDEOGRAPH-9169 +U+916A # 45-79, CJK UNIFIED IDEOGRAPH-916A +U+916C # 29-23, CJK UNIFIED IDEOGRAPH-916C +U+9172 # 78-43, CJK UNIFIED IDEOGRAPH-9172 +U+9173 # 78-42, CJK UNIFIED IDEOGRAPH-9173 +U+9175 # 25-58, CJK UNIFIED IDEOGRAPH-9175 +U+9177 # 25-83, CJK UNIFIED IDEOGRAPH-9177 +U+9178 # 27-32, CJK UNIFIED IDEOGRAPH-9178 +U+9182 # 78-46, CJK UNIFIED IDEOGRAPH-9182 +U+9187 # 29-70, CJK UNIFIED IDEOGRAPH-9187 +U+9189 # 78-45, CJK UNIFIED IDEOGRAPH-9189 +U+918B # 78-44, CJK UNIFIED IDEOGRAPH-918B +U+918D # 34-73, CJK UNIFIED IDEOGRAPH-918D +U+9190 # 24-79, CJK UNIFIED IDEOGRAPH-9190 +U+9192 # 32-35, CJK UNIFIED IDEOGRAPH-9192 +U+9197 # 40-16, CJK UNIFIED IDEOGRAPH-9197 +U+919C # 29-25, CJK UNIFIED IDEOGRAPH-919C +U+91A2 # 78-47, CJK UNIFIED IDEOGRAPH-91A2 +U+91A4 # 30-63, CJK UNIFIED IDEOGRAPH-91A4 +U+91AA # 78-50, CJK UNIFIED IDEOGRAPH-91AA +U+91AB # 78-48, CJK UNIFIED IDEOGRAPH-91AB +U+91AF # 78-49, CJK UNIFIED IDEOGRAPH-91AF +U+91B4 # 78-52, CJK UNIFIED IDEOGRAPH-91B4 +U+91B5 # 78-51, CJK UNIFIED IDEOGRAPH-91B5 +U+91B8 # 30-90, CJK UNIFIED IDEOGRAPH-91B8 +U+91BA # 78-53, CJK UNIFIED IDEOGRAPH-91BA +U+91C0 # 78-54, CJK UNIFIED IDEOGRAPH-91C0 +U+91C1 # 78-55, CJK UNIFIED IDEOGRAPH-91C1 +U+91C6 # 40-48, CJK UNIFIED IDEOGRAPH-91C6 +U+91C7 # 26-51, CJK UNIFIED IDEOGRAPH-91C7 +U+91C8 # 28-65, CJK UNIFIED IDEOGRAPH-91C8 +U+91C9 # 78-56, CJK UNIFIED IDEOGRAPH-91C9 +U+91CB # 78-57, CJK UNIFIED IDEOGRAPH-91CB +U+91CC # 46-04, CJK UNIFIED IDEOGRAPH-91CC +U+91CD # 29-37, CJK UNIFIED IDEOGRAPH-91CD +U+91CE # 44-78, CJK UNIFIED IDEOGRAPH-91CE +U+91CF # 46-44, CJK UNIFIED IDEOGRAPH-91CF +U+91D0 # 78-58, CJK UNIFIED IDEOGRAPH-91D0 +U+91D1 # 22-66, CJK UNIFIED IDEOGRAPH-91D1 +U+91D6 # 78-59, CJK UNIFIED IDEOGRAPH-91D6 +U+91D8 # 37-03, CJK UNIFIED IDEOGRAPH-91D8 +U+91DB # 78-62, CJK UNIFIED IDEOGRAPH-91DB +U+91DC # 19-88, CJK UNIFIED IDEOGRAPH-91DC +U+91DD # 31-43, CJK UNIFIED IDEOGRAPH-91DD +U+91DF # 78-60, CJK UNIFIED IDEOGRAPH-91DF +U+91E1 # 78-61, CJK UNIFIED IDEOGRAPH-91E1 +U+91E3 # 36-64, CJK UNIFIED IDEOGRAPH-91E3 +U+91E6 # 43-53, CJK UNIFIED IDEOGRAPH-91E6 +U+91E7 # 22-92, CJK UNIFIED IDEOGRAPH-91E7 +U+91F5 # 78-64, CJK UNIFIED IDEOGRAPH-91F5 +U+91F6 # 78-65, CJK UNIFIED IDEOGRAPH-91F6 +U+91FC # 78-63, CJK UNIFIED IDEOGRAPH-91FC +U+91FF # 78-67, CJK UNIFIED IDEOGRAPH-91FF +U+920D # 38-63, CJK UNIFIED IDEOGRAPH-920D +U+920E # 19-35, CJK UNIFIED IDEOGRAPH-920E +U+9211 # 78-71, CJK UNIFIED IDEOGRAPH-9211 +U+9214 # 78-68, CJK UNIFIED IDEOGRAPH-9214 +U+9215 # 78-70, CJK UNIFIED IDEOGRAPH-9215 +U+921E # 78-66, CJK UNIFIED IDEOGRAPH-921E +U+9229 # 79-47, CJK UNIFIED IDEOGRAPH-9229 +U+922C # 78-69, CJK UNIFIED IDEOGRAPH-922C +U+9234 # 46-75, CJK UNIFIED IDEOGRAPH-9234 +U+9237 # 24-58, CJK UNIFIED IDEOGRAPH-9237 +U+923F # 78-79, CJK UNIFIED IDEOGRAPH-923F +U+9244 # 37-20, CJK UNIFIED IDEOGRAPH-9244 +U+9245 # 78-74, CJK UNIFIED IDEOGRAPH-9245 +U+9248 # 78-77, CJK UNIFIED IDEOGRAPH-9248 +U+9249 # 78-75, CJK UNIFIED IDEOGRAPH-9249 +U+924B # 78-80, CJK UNIFIED IDEOGRAPH-924B +U+9250 # 78-81, CJK UNIFIED IDEOGRAPH-9250 +U+9257 # 78-73, CJK UNIFIED IDEOGRAPH-9257 +U+925A # 78-86, CJK UNIFIED IDEOGRAPH-925A +U+925B # 17-84, CJK UNIFIED IDEOGRAPH-925B +U+925E # 78-72, CJK UNIFIED IDEOGRAPH-925E +U+9262 # 40-13, CJK UNIFIED IDEOGRAPH-9262 +U+9264 # 78-76, CJK UNIFIED IDEOGRAPH-9264 +U+9266 # 30-64, CJK UNIFIED IDEOGRAPH-9266 +U+9271 # 25-59, CJK UNIFIED IDEOGRAPH-9271 +U+927E # 43-40, CJK UNIFIED IDEOGRAPH-927E +U+9280 # 22-68, CJK UNIFIED IDEOGRAPH-9280 +U+9283 # 29-38, CJK UNIFIED IDEOGRAPH-9283 +U+9285 # 38-28, CJK UNIFIED IDEOGRAPH-9285 +U+9291 # 33-13, CJK UNIFIED IDEOGRAPH-9291 +U+9293 # 78-84, CJK UNIFIED IDEOGRAPH-9293 +U+9295 # 78-78, CJK UNIFIED IDEOGRAPH-9295 +U+9296 # 78-83, CJK UNIFIED IDEOGRAPH-9296 +U+9298 # 44-35, CJK UNIFIED IDEOGRAPH-9298 +U+929A # 36-24, CJK UNIFIED IDEOGRAPH-929A +U+929B # 78-85, CJK UNIFIED IDEOGRAPH-929B +U+929C # 78-82, CJK UNIFIED IDEOGRAPH-929C +U+92AD # 33-12, CJK UNIFIED IDEOGRAPH-92AD +U+92B7 # 78-89, CJK UNIFIED IDEOGRAPH-92B7 +U+92B9 # 78-88, CJK UNIFIED IDEOGRAPH-92B9 +U+92CF # 78-87, CJK UNIFIED IDEOGRAPH-92CF +U+92D2 # 43-15, CJK UNIFIED IDEOGRAPH-92D2 +U+92E4 # 29-91, CJK UNIFIED IDEOGRAPH-92E4 +U+92E9 # 78-90, CJK UNIFIED IDEOGRAPH-92E9 +U+92EA # 42-63, CJK UNIFIED IDEOGRAPH-92EA +U+92ED # 17-52, CJK UNIFIED IDEOGRAPH-92ED +U+92F2 # 41-38, CJK UNIFIED IDEOGRAPH-92F2 +U+92F3 # 35-82, CJK UNIFIED IDEOGRAPH-92F3 +U+92F8 # 21-88, CJK UNIFIED IDEOGRAPH-92F8 +U+92FA # 78-92, CJK UNIFIED IDEOGRAPH-92FA +U+92FC # 25-61, CJK UNIFIED IDEOGRAPH-92FC +U+9306 # 27-12, CJK UNIFIED IDEOGRAPH-9306 +U+930F # 78-91, CJK UNIFIED IDEOGRAPH-930F +U+9310 # 31-77, CJK UNIFIED IDEOGRAPH-9310 +U+9318 # 31-78, CJK UNIFIED IDEOGRAPH-9318 +U+9319 # 79-01, CJK UNIFIED IDEOGRAPH-9319 +U+931A # 79-03, CJK UNIFIED IDEOGRAPH-931A +U+9320 # 30-91, CJK UNIFIED IDEOGRAPH-9320 +U+9322 # 79-02, CJK UNIFIED IDEOGRAPH-9322 +U+9323 # 79-04, CJK UNIFIED IDEOGRAPH-9323 +U+9326 # 22-51, CJK UNIFIED IDEOGRAPH-9326 +U+9328 # 41-37, CJK UNIFIED IDEOGRAPH-9328 +U+932B # 28-66, CJK UNIFIED IDEOGRAPH-932B +U+932C # 47-03, CJK UNIFIED IDEOGRAPH-932C +U+932E # 78-94, CJK UNIFIED IDEOGRAPH-932E +U+932F # 26-88, CJK UNIFIED IDEOGRAPH-932F +U+9332 # 47-31, CJK UNIFIED IDEOGRAPH-9332 +U+9335 # 79-06, CJK UNIFIED IDEOGRAPH-9335 +U+933A # 79-05, CJK UNIFIED IDEOGRAPH-933A +U+933B # 79-07, CJK UNIFIED IDEOGRAPH-933B +U+9344 # 78-93, CJK UNIFIED IDEOGRAPH-9344 +U+934B # 38-73, CJK UNIFIED IDEOGRAPH-934B +U+934D # 37-53, CJK UNIFIED IDEOGRAPH-934D +U+9354 # 36-55, CJK UNIFIED IDEOGRAPH-9354 +U+9356 # 79-12, CJK UNIFIED IDEOGRAPH-9356 +U+935B # 35-35, CJK UNIFIED IDEOGRAPH-935B +U+935C # 79-08, CJK UNIFIED IDEOGRAPH-935C +U+9360 # 79-09, CJK UNIFIED IDEOGRAPH-9360 +U+936C # 23-13, CJK UNIFIED IDEOGRAPH-936C +U+936E # 79-11, CJK UNIFIED IDEOGRAPH-936E +U+9375 # 24-16, CJK UNIFIED IDEOGRAPH-9375 +U+937C # 79-10, CJK UNIFIED IDEOGRAPH-937C +U+937E # 30-65, CJK UNIFIED IDEOGRAPH-937E +U+938C # 19-89, CJK UNIFIED IDEOGRAPH-938C +U+9394 # 79-16, CJK UNIFIED IDEOGRAPH-9394 +U+9396 # 26-31, CJK UNIFIED IDEOGRAPH-9396 +U+9397 # 33-89, CJK UNIFIED IDEOGRAPH-9397 +U+939A # 36-42, CJK UNIFIED IDEOGRAPH-939A +U+93A7 # 19-27, CJK UNIFIED IDEOGRAPH-93A7 +U+93AC # 79-14, CJK UNIFIED IDEOGRAPH-93AC +U+93AD # 79-15, CJK UNIFIED IDEOGRAPH-93AD +U+93AE # 36-35, CJK UNIFIED IDEOGRAPH-93AE +U+93B0 # 79-13, CJK UNIFIED IDEOGRAPH-93B0 +U+93B9 # 79-17, CJK UNIFIED IDEOGRAPH-93B9 +U+93C3 # 79-23, CJK UNIFIED IDEOGRAPH-93C3 +U+93C8 # 79-26, CJK UNIFIED IDEOGRAPH-93C8 +U+93D0 # 79-25, CJK UNIFIED IDEOGRAPH-93D0 +U+93D1 # 37-13, CJK UNIFIED IDEOGRAPH-93D1 +U+93D6 # 79-18, CJK UNIFIED IDEOGRAPH-93D6 +U+93D7 # 79-19, CJK UNIFIED IDEOGRAPH-93D7 +U+93D8 # 79-22, CJK UNIFIED IDEOGRAPH-93D8 +U+93DD # 79-24, CJK UNIFIED IDEOGRAPH-93DD +U+93E1 # 22-32, CJK UNIFIED IDEOGRAPH-93E1 +U+93E4 # 79-27, CJK UNIFIED IDEOGRAPH-93E4 +U+93E5 # 79-21, CJK UNIFIED IDEOGRAPH-93E5 +U+93E8 # 79-20, CJK UNIFIED IDEOGRAPH-93E8 +U+9403 # 79-31, CJK UNIFIED IDEOGRAPH-9403 +U+9407 # 79-32, CJK UNIFIED IDEOGRAPH-9407 +U+9410 # 79-33, CJK UNIFIED IDEOGRAPH-9410 +U+9413 # 79-30, CJK UNIFIED IDEOGRAPH-9413 +U+9414 # 79-29, CJK UNIFIED IDEOGRAPH-9414 +U+9418 # 30-66, CJK UNIFIED IDEOGRAPH-9418 +U+9419 # 38-10, CJK UNIFIED IDEOGRAPH-9419 +U+941A # 79-28, CJK UNIFIED IDEOGRAPH-941A +U+9421 # 79-37, CJK UNIFIED IDEOGRAPH-9421 +U+942B # 79-35, CJK UNIFIED IDEOGRAPH-942B +U+9435 # 79-36, CJK UNIFIED IDEOGRAPH-9435 +U+9436 # 79-34, CJK UNIFIED IDEOGRAPH-9436 +U+9438 # 34-88, CJK UNIFIED IDEOGRAPH-9438 +U+943A # 79-38, CJK UNIFIED IDEOGRAPH-943A +U+9441 # 79-39, CJK UNIFIED IDEOGRAPH-9441 +U+9444 # 79-41, CJK UNIFIED IDEOGRAPH-9444 +U+9451 # 20-53, CJK UNIFIED IDEOGRAPH-9451 +U+9452 # 79-40, CJK UNIFIED IDEOGRAPH-9452 +U+9453 # 44-90, CJK UNIFIED IDEOGRAPH-9453 +U+945A # 79-52, CJK UNIFIED IDEOGRAPH-945A +U+945B # 79-42, CJK UNIFIED IDEOGRAPH-945B +U+945E # 79-45, CJK UNIFIED IDEOGRAPH-945E +U+9460 # 79-43, CJK UNIFIED IDEOGRAPH-9460 +U+9462 # 79-44, CJK UNIFIED IDEOGRAPH-9462 +U+946A # 79-46, CJK UNIFIED IDEOGRAPH-946A +U+9470 # 79-48, CJK UNIFIED IDEOGRAPH-9470 +U+9475 # 79-49, CJK UNIFIED IDEOGRAPH-9475 +U+9477 # 79-50, CJK UNIFIED IDEOGRAPH-9477 +U+947C # 79-53, CJK UNIFIED IDEOGRAPH-947C +U+947D # 79-51, CJK UNIFIED IDEOGRAPH-947D +U+947E # 79-54, CJK UNIFIED IDEOGRAPH-947E +U+947F # 79-56, CJK UNIFIED IDEOGRAPH-947F +U+9481 # 79-55, CJK UNIFIED IDEOGRAPH-9481 +U+9577 # 36-25, CJK UNIFIED IDEOGRAPH-9577 +U+9580 # 44-71, CJK UNIFIED IDEOGRAPH-9580 +U+9582 # 79-57, CJK UNIFIED IDEOGRAPH-9582 +U+9583 # 33-14, CJK UNIFIED IDEOGRAPH-9583 +U+9587 # 79-58, CJK UNIFIED IDEOGRAPH-9587 +U+9589 # 42-36, CJK UNIFIED IDEOGRAPH-9589 +U+958A # 79-59, CJK UNIFIED IDEOGRAPH-958A +U+958B # 19-11, CJK UNIFIED IDEOGRAPH-958B +U+958F # 17-28, CJK UNIFIED IDEOGRAPH-958F +U+9591 # 20-55, CJK UNIFIED IDEOGRAPH-9591 +U+9593 # 20-54, CJK UNIFIED IDEOGRAPH-9593 +U+9594 # 79-60, CJK UNIFIED IDEOGRAPH-9594 +U+9596 # 79-61, CJK UNIFIED IDEOGRAPH-9596 +U+9598 # 79-62, CJK UNIFIED IDEOGRAPH-9598 +U+9599 # 79-63, CJK UNIFIED IDEOGRAPH-9599 +U+95A0 # 79-64, CJK UNIFIED IDEOGRAPH-95A0 +U+95A2 # 20-56, CJK UNIFIED IDEOGRAPH-95A2 +U+95A3 # 19-53, CJK UNIFIED IDEOGRAPH-95A3 +U+95A4 # 25-62, CJK UNIFIED IDEOGRAPH-95A4 +U+95A5 # 40-22, CJK UNIFIED IDEOGRAPH-95A5 +U+95A7 # 79-66, CJK UNIFIED IDEOGRAPH-95A7 +U+95A8 # 79-65, CJK UNIFIED IDEOGRAPH-95A8 +U+95AD # 79-67, CJK UNIFIED IDEOGRAPH-95AD +U+95B2 # 17-60, CJK UNIFIED IDEOGRAPH-95B2 +U+95B9 # 79-70, CJK UNIFIED IDEOGRAPH-95B9 +U+95BB # 79-69, CJK UNIFIED IDEOGRAPH-95BB +U+95BC # 79-68, CJK UNIFIED IDEOGRAPH-95BC +U+95BE # 79-71, CJK UNIFIED IDEOGRAPH-95BE +U+95C3 # 79-74, CJK UNIFIED IDEOGRAPH-95C3 +U+95C7 # 16-39, CJK UNIFIED IDEOGRAPH-95C7 +U+95CA # 79-72, CJK UNIFIED IDEOGRAPH-95CA +U+95CC # 79-76, CJK UNIFIED IDEOGRAPH-95CC +U+95CD # 79-75, CJK UNIFIED IDEOGRAPH-95CD +U+95D4 # 79-78, CJK UNIFIED IDEOGRAPH-95D4 +U+95D5 # 79-77, CJK UNIFIED IDEOGRAPH-95D5 +U+95D6 # 79-79, CJK UNIFIED IDEOGRAPH-95D6 +U+95D8 # 38-14, CJK UNIFIED IDEOGRAPH-95D8 +U+95DC # 79-80, CJK UNIFIED IDEOGRAPH-95DC +U+95E1 # 79-81, CJK UNIFIED IDEOGRAPH-95E1 +U+95E2 # 79-83, CJK UNIFIED IDEOGRAPH-95E2 +U+95E5 # 79-82, CJK UNIFIED IDEOGRAPH-95E5 +U+961C # 41-76, CJK UNIFIED IDEOGRAPH-961C +U+9621 # 79-84, CJK UNIFIED IDEOGRAPH-9621 +U+9628 # 79-85, CJK UNIFIED IDEOGRAPH-9628 +U+962A # 26-69, CJK UNIFIED IDEOGRAPH-962A +U+962E # 79-86, CJK UNIFIED IDEOGRAPH-962E +U+962F # 79-87, CJK UNIFIED IDEOGRAPH-962F +U+9632 # 43-41, CJK UNIFIED IDEOGRAPH-9632 +U+963B # 33-43, CJK UNIFIED IDEOGRAPH-963B +U+963F # 16-04, CJK UNIFIED IDEOGRAPH-963F +U+9640 # 34-43, CJK UNIFIED IDEOGRAPH-9640 +U+9642 # 79-88, CJK UNIFIED IDEOGRAPH-9642 +U+9644 # 41-77, CJK UNIFIED IDEOGRAPH-9644 +U+964B # 79-91, CJK UNIFIED IDEOGRAPH-964B +U+964C # 79-89, CJK UNIFIED IDEOGRAPH-964C +U+964D # 25-63, CJK UNIFIED IDEOGRAPH-964D +U+964F # 79-90, CJK UNIFIED IDEOGRAPH-964F +U+9650 # 24-34, CJK UNIFIED IDEOGRAPH-9650 +U+965B # 42-37, CJK UNIFIED IDEOGRAPH-965B +U+965C # 79-93, CJK UNIFIED IDEOGRAPH-965C +U+965D # 80-01, CJK UNIFIED IDEOGRAPH-965D +U+965E # 79-94, CJK UNIFIED IDEOGRAPH-965E +U+965F # 80-02, CJK UNIFIED IDEOGRAPH-965F +U+9662 # 17-01, CJK UNIFIED IDEOGRAPH-9662 +U+9663 # 31-56, CJK UNIFIED IDEOGRAPH-9663 +U+9664 # 29-92, CJK UNIFIED IDEOGRAPH-9664 +U+9665 # 20-57, CJK UNIFIED IDEOGRAPH-9665 +U+9666 # 80-03, CJK UNIFIED IDEOGRAPH-9666 +U+966A # 39-70, CJK UNIFIED IDEOGRAPH-966A +U+966C # 80-05, CJK UNIFIED IDEOGRAPH-966C +U+9670 # 17-02, CJK UNIFIED IDEOGRAPH-9670 +U+9672 # 80-04, CJK UNIFIED IDEOGRAPH-9672 +U+9673 # 36-36, CJK UNIFIED IDEOGRAPH-9673 +U+9675 # 46-45, CJK UNIFIED IDEOGRAPH-9675 +U+9676 # 38-11, CJK UNIFIED IDEOGRAPH-9676 +U+9677 # 79-92, CJK UNIFIED IDEOGRAPH-9677 +U+9678 # 46-06, CJK UNIFIED IDEOGRAPH-9678 +U+967A # 24-17, CJK UNIFIED IDEOGRAPH-967A +U+967D # 45-59, CJK UNIFIED IDEOGRAPH-967D +U+9685 # 22-89, CJK UNIFIED IDEOGRAPH-9685 +U+9686 # 46-20, CJK UNIFIED IDEOGRAPH-9686 +U+9688 # 23-08, CJK UNIFIED IDEOGRAPH-9688 +U+968A # 34-66, CJK UNIFIED IDEOGRAPH-968A +U+968B # 71-01, CJK UNIFIED IDEOGRAPH-968B +U+968D # 80-06, CJK UNIFIED IDEOGRAPH-968D +U+968E # 19-12, CJK UNIFIED IDEOGRAPH-968E +U+968F # 31-79, CJK UNIFIED IDEOGRAPH-968F +U+9694 # 19-54, CJK UNIFIED IDEOGRAPH-9694 +U+9695 # 80-08, CJK UNIFIED IDEOGRAPH-9695 +U+9697 # 80-09, CJK UNIFIED IDEOGRAPH-9697 +U+9698 # 80-07, CJK UNIFIED IDEOGRAPH-9698 +U+9699 # 23-68, CJK UNIFIED IDEOGRAPH-9699 +U+969B # 26-61, CJK UNIFIED IDEOGRAPH-969B +U+969C # 30-67, CJK UNIFIED IDEOGRAPH-969C +U+96A0 # 17-03, CJK UNIFIED IDEOGRAPH-96A0 +U+96A3 # 46-57, CJK UNIFIED IDEOGRAPH-96A3 +U+96A7 # 80-11, CJK UNIFIED IDEOGRAPH-96A7 +U+96A8 # 78-14, CJK UNIFIED IDEOGRAPH-96A8 +U+96AA # 80-10, CJK UNIFIED IDEOGRAPH-96AA +U+96B0 # 80-14, CJK UNIFIED IDEOGRAPH-96B0 +U+96B1 # 80-12, CJK UNIFIED IDEOGRAPH-96B1 +U+96B2 # 80-13, CJK UNIFIED IDEOGRAPH-96B2 +U+96B4 # 80-15, CJK UNIFIED IDEOGRAPH-96B4 +U+96B6 # 80-16, CJK UNIFIED IDEOGRAPH-96B6 +U+96B7 # 46-76, CJK UNIFIED IDEOGRAPH-96B7 +U+96B8 # 80-17, CJK UNIFIED IDEOGRAPH-96B8 +U+96B9 # 80-18, CJK UNIFIED IDEOGRAPH-96B9 +U+96BB # 32-41, CJK UNIFIED IDEOGRAPH-96BB +U+96BC # 40-27, CJK UNIFIED IDEOGRAPH-96BC +U+96C0 # 31-93, CJK UNIFIED IDEOGRAPH-96C0 +U+96C1 # 20-71, CJK UNIFIED IDEOGRAPH-96C1 +U+96C4 # 45-26, CJK UNIFIED IDEOGRAPH-96C4 +U+96C5 # 18-77, CJK UNIFIED IDEOGRAPH-96C5 +U+96C6 # 29-24, CJK UNIFIED IDEOGRAPH-96C6 +U+96C7 # 24-59, CJK UNIFIED IDEOGRAPH-96C7 +U+96C9 # 80-21, CJK UNIFIED IDEOGRAPH-96C9 +U+96CB # 80-20, CJK UNIFIED IDEOGRAPH-96CB +U+96CC # 27-83, CJK UNIFIED IDEOGRAPH-96CC +U+96CD # 80-22, CJK UNIFIED IDEOGRAPH-96CD +U+96CE # 80-19, CJK UNIFIED IDEOGRAPH-96CE +U+96D1 # 27-08, CJK UNIFIED IDEOGRAPH-96D1 +U+96D5 # 80-26, CJK UNIFIED IDEOGRAPH-96D5 +U+96D6 # 74-13, CJK UNIFIED IDEOGRAPH-96D6 +U+96D9 # 50-54, CJK UNIFIED IDEOGRAPH-96D9 +U+96DB # 31-87, CJK UNIFIED IDEOGRAPH-96DB +U+96DC # 80-24, CJK UNIFIED IDEOGRAPH-96DC +U+96E2 # 46-05, CJK UNIFIED IDEOGRAPH-96E2 +U+96E3 # 38-81, CJK UNIFIED IDEOGRAPH-96E3 +U+96E8 # 17-11, CJK UNIFIED IDEOGRAPH-96E8 +U+96EA # 32-67, CJK UNIFIED IDEOGRAPH-96EA +U+96EB # 28-22, CJK UNIFIED IDEOGRAPH-96EB +U+96F0 # 42-23, CJK UNIFIED IDEOGRAPH-96F0 +U+96F2 # 17-32, CJK UNIFIED IDEOGRAPH-96F2 +U+96F6 # 46-77, CJK UNIFIED IDEOGRAPH-96F6 +U+96F7 # 45-75, CJK UNIFIED IDEOGRAPH-96F7 +U+96F9 # 80-27, CJK UNIFIED IDEOGRAPH-96F9 +U+96FB # 37-37, CJK UNIFIED IDEOGRAPH-96FB +U+9700 # 28-91, CJK UNIFIED IDEOGRAPH-9700 +U+9704 # 80-28, CJK UNIFIED IDEOGRAPH-9704 +U+9706 # 80-29, CJK UNIFIED IDEOGRAPH-9706 +U+9707 # 31-44, CJK UNIFIED IDEOGRAPH-9707 +U+9708 # 80-30, CJK UNIFIED IDEOGRAPH-9708 +U+970A # 46-78, CJK UNIFIED IDEOGRAPH-970A +U+970D # 80-25, CJK UNIFIED IDEOGRAPH-970D +U+970E # 80-32, CJK UNIFIED IDEOGRAPH-970E +U+970F # 80-34, CJK UNIFIED IDEOGRAPH-970F +U+9711 # 80-33, CJK UNIFIED IDEOGRAPH-9711 +U+9713 # 80-31, CJK UNIFIED IDEOGRAPH-9713 +U+9716 # 80-35, CJK UNIFIED IDEOGRAPH-9716 +U+9719 # 80-36, CJK UNIFIED IDEOGRAPH-9719 +U+971C # 33-90, CJK UNIFIED IDEOGRAPH-971C +U+971E # 18-66, CJK UNIFIED IDEOGRAPH-971E +U+9724 # 80-37, CJK UNIFIED IDEOGRAPH-9724 +U+9727 # 44-24, CJK UNIFIED IDEOGRAPH-9727 +U+972A # 80-38, CJK UNIFIED IDEOGRAPH-972A +U+9730 # 80-39, CJK UNIFIED IDEOGRAPH-9730 +U+9732 # 47-10, CJK UNIFIED IDEOGRAPH-9732 +U+9738 # 59-17, CJK UNIFIED IDEOGRAPH-9738 +U+9739 # 80-40, CJK UNIFIED IDEOGRAPH-9739 +U+973D # 80-41, CJK UNIFIED IDEOGRAPH-973D +U+973E # 80-42, CJK UNIFIED IDEOGRAPH-973E +U+9742 # 80-46, CJK UNIFIED IDEOGRAPH-9742 +U+9744 # 80-43, CJK UNIFIED IDEOGRAPH-9744 +U+9746 # 80-44, CJK UNIFIED IDEOGRAPH-9746 +U+9748 # 80-45, CJK UNIFIED IDEOGRAPH-9748 +U+9749 # 80-47, CJK UNIFIED IDEOGRAPH-9749 +U+9752 # 32-36, CJK UNIFIED IDEOGRAPH-9752 +U+9756 # 44-87, CJK UNIFIED IDEOGRAPH-9756 +U+9759 # 32-37, CJK UNIFIED IDEOGRAPH-9759 +U+975C # 80-48, CJK UNIFIED IDEOGRAPH-975C +U+975E # 40-83, CJK UNIFIED IDEOGRAPH-975E +U+9760 # 80-49, CJK UNIFIED IDEOGRAPH-9760 +U+9761 # 83-51, CJK UNIFIED IDEOGRAPH-9761 +U+9762 # 44-44, CJK UNIFIED IDEOGRAPH-9762 +U+9764 # 80-50, CJK UNIFIED IDEOGRAPH-9764 +U+9766 # 80-51, CJK UNIFIED IDEOGRAPH-9766 +U+9768 # 80-52, CJK UNIFIED IDEOGRAPH-9768 +U+9769 # 19-55, CJK UNIFIED IDEOGRAPH-9769 +U+976B # 80-54, CJK UNIFIED IDEOGRAPH-976B +U+976D # 31-57, CJK UNIFIED IDEOGRAPH-976D +U+9771 # 80-55, CJK UNIFIED IDEOGRAPH-9771 +U+9774 # 23-04, CJK UNIFIED IDEOGRAPH-9774 +U+9779 # 80-56, CJK UNIFIED IDEOGRAPH-9779 +U+977A # 80-60, CJK UNIFIED IDEOGRAPH-977A +U+977C # 80-58, CJK UNIFIED IDEOGRAPH-977C +U+9781 # 80-59, CJK UNIFIED IDEOGRAPH-9781 +U+9784 # 19-83, CJK UNIFIED IDEOGRAPH-9784 +U+9785 # 80-57, CJK UNIFIED IDEOGRAPH-9785 +U+9786 # 80-61, CJK UNIFIED IDEOGRAPH-9786 +U+978B # 80-62, CJK UNIFIED IDEOGRAPH-978B +U+978D # 16-40, CJK UNIFIED IDEOGRAPH-978D +U+978F # 80-63, CJK UNIFIED IDEOGRAPH-978F +U+9790 # 80-64, CJK UNIFIED IDEOGRAPH-9790 +U+9798 # 30-68, CJK UNIFIED IDEOGRAPH-9798 +U+979C # 80-65, CJK UNIFIED IDEOGRAPH-979C +U+97A0 # 21-39, CJK UNIFIED IDEOGRAPH-97A0 +U+97A3 # 80-68, CJK UNIFIED IDEOGRAPH-97A3 +U+97A6 # 80-67, CJK UNIFIED IDEOGRAPH-97A6 +U+97A8 # 80-66, CJK UNIFIED IDEOGRAPH-97A8 +U+97AB # 75-81, CJK UNIFIED IDEOGRAPH-97AB +U+97AD # 42-60, CJK UNIFIED IDEOGRAPH-97AD +U+97B3 # 80-69, CJK UNIFIED IDEOGRAPH-97B3 +U+97B4 # 80-70, CJK UNIFIED IDEOGRAPH-97B4 +U+97C3 # 80-71, CJK UNIFIED IDEOGRAPH-97C3 +U+97C6 # 80-72, CJK UNIFIED IDEOGRAPH-97C6 +U+97C8 # 80-73, CJK UNIFIED IDEOGRAPH-97C8 +U+97CB # 80-74, CJK UNIFIED IDEOGRAPH-97CB +U+97D3 # 20-58, CJK UNIFIED IDEOGRAPH-97D3 +U+97DC # 80-75, CJK UNIFIED IDEOGRAPH-97DC +U+97ED # 80-76, CJK UNIFIED IDEOGRAPH-97ED +U+97EE # 39-03, CJK UNIFIED IDEOGRAPH-97EE +U+97F2 # 80-78, CJK UNIFIED IDEOGRAPH-97F2 +U+97F3 # 18-27, CJK UNIFIED IDEOGRAPH-97F3 +U+97F5 # 80-81, CJK UNIFIED IDEOGRAPH-97F5 +U+97F6 # 80-80, CJK UNIFIED IDEOGRAPH-97F6 +U+97FB # 17-04, CJK UNIFIED IDEOGRAPH-97FB +U+97FF # 22-33, CJK UNIFIED IDEOGRAPH-97FF +U+9801 # 42-39, CJK UNIFIED IDEOGRAPH-9801 +U+9802 # 36-26, CJK UNIFIED IDEOGRAPH-9802 +U+9803 # 26-02, CJK UNIFIED IDEOGRAPH-9803 +U+9805 # 25-64, CJK UNIFIED IDEOGRAPH-9805 +U+9806 # 29-71, CJK UNIFIED IDEOGRAPH-9806 +U+9808 # 31-60, CJK UNIFIED IDEOGRAPH-9808 +U+980C # 80-83, CJK UNIFIED IDEOGRAPH-980C +U+980F # 80-82, CJK UNIFIED IDEOGRAPH-980F +U+9810 # 45-34, CJK UNIFIED IDEOGRAPH-9810 +U+9811 # 20-72, CJK UNIFIED IDEOGRAPH-9811 +U+9812 # 40-50, CJK UNIFIED IDEOGRAPH-9812 +U+9813 # 38-60, CJK UNIFIED IDEOGRAPH-9813 +U+9817 # 31-92, CJK UNIFIED IDEOGRAPH-9817 +U+9818 # 46-46, CJK UNIFIED IDEOGRAPH-9818 +U+981A # 23-59, CJK UNIFIED IDEOGRAPH-981A +U+9821 # 80-86, CJK UNIFIED IDEOGRAPH-9821 +U+9824 # 80-85, CJK UNIFIED IDEOGRAPH-9824 +U+982C # 43-43, CJK UNIFIED IDEOGRAPH-982C +U+982D # 38-12, CJK UNIFIED IDEOGRAPH-982D +U+9834 # 17-48, CJK UNIFIED IDEOGRAPH-9834 +U+9837 # 80-87, CJK UNIFIED IDEOGRAPH-9837 +U+9838 # 80-84, CJK UNIFIED IDEOGRAPH-9838 +U+983B # 41-49, CJK UNIFIED IDEOGRAPH-983B +U+983C # 45-74, CJK UNIFIED IDEOGRAPH-983C +U+983D # 80-88, CJK UNIFIED IDEOGRAPH-983D +U+9846 # 80-89, CJK UNIFIED IDEOGRAPH-9846 +U+984B # 80-91, CJK UNIFIED IDEOGRAPH-984B +U+984C # 34-74, CJK UNIFIED IDEOGRAPH-984C +U+984D # 19-59, CJK UNIFIED IDEOGRAPH-984D +U+984E # 19-60, CJK UNIFIED IDEOGRAPH-984E +U+984F # 80-90, CJK UNIFIED IDEOGRAPH-984F +U+9854 # 20-73, CJK UNIFIED IDEOGRAPH-9854 +U+9855 # 24-18, CJK UNIFIED IDEOGRAPH-9855 +U+9858 # 20-74, CJK UNIFIED IDEOGRAPH-9858 +U+985B # 37-31, CJK UNIFIED IDEOGRAPH-985B +U+985E # 46-64, CJK UNIFIED IDEOGRAPH-985E +U+9867 # 24-60, CJK UNIFIED IDEOGRAPH-9867 +U+986B # 80-92, CJK UNIFIED IDEOGRAPH-986B +U+986F # 80-93, CJK UNIFIED IDEOGRAPH-986F +U+9870 # 80-94, CJK UNIFIED IDEOGRAPH-9870 +U+9871 # 81-01, CJK UNIFIED IDEOGRAPH-9871 +U+9873 # 81-03, CJK UNIFIED IDEOGRAPH-9873 +U+9874 # 81-02, CJK UNIFIED IDEOGRAPH-9874 +U+98A8 # 41-87, CJK UNIFIED IDEOGRAPH-98A8 +U+98AA # 81-04, CJK UNIFIED IDEOGRAPH-98AA +U+98AF # 81-05, CJK UNIFIED IDEOGRAPH-98AF +U+98B1 # 81-06, CJK UNIFIED IDEOGRAPH-98B1 +U+98B6 # 81-07, CJK UNIFIED IDEOGRAPH-98B6 +U+98C3 # 81-09, CJK UNIFIED IDEOGRAPH-98C3 +U+98C4 # 81-08, CJK UNIFIED IDEOGRAPH-98C4 +U+98C6 # 81-10, CJK UNIFIED IDEOGRAPH-98C6 +U+98DB # 40-84, CJK UNIFIED IDEOGRAPH-98DB +U+98DC # 70-44, CJK UNIFIED IDEOGRAPH-98DC +U+98DF # 31-09, CJK UNIFIED IDEOGRAPH-98DF +U+98E2 # 21-18, CJK UNIFIED IDEOGRAPH-98E2 +U+98E9 # 81-11, CJK UNIFIED IDEOGRAPH-98E9 +U+98EB # 81-12, CJK UNIFIED IDEOGRAPH-98EB +U+98ED # 50-12, CJK UNIFIED IDEOGRAPH-98ED +U+98EE # 61-27, CJK UNIFIED IDEOGRAPH-98EE +U+98EF # 40-51, CJK UNIFIED IDEOGRAPH-98EF +U+98F2 # 16-91, CJK UNIFIED IDEOGRAPH-98F2 +U+98F4 # 16-27, CJK UNIFIED IDEOGRAPH-98F4 +U+98FC # 27-84, CJK UNIFIED IDEOGRAPH-98FC +U+98FD # 43-16, CJK UNIFIED IDEOGRAPH-98FD +U+98FE # 30-94, CJK UNIFIED IDEOGRAPH-98FE +U+9903 # 81-13, CJK UNIFIED IDEOGRAPH-9903 +U+9905 # 44-63, CJK UNIFIED IDEOGRAPH-9905 +U+9909 # 81-14, CJK UNIFIED IDEOGRAPH-9909 +U+990A # 45-60, CJK UNIFIED IDEOGRAPH-990A +U+990C # 17-34, CJK UNIFIED IDEOGRAPH-990C +U+9910 # 27-33, CJK UNIFIED IDEOGRAPH-9910 +U+9912 # 81-15, CJK UNIFIED IDEOGRAPH-9912 +U+9913 # 18-78, CJK UNIFIED IDEOGRAPH-9913 +U+9914 # 81-16, CJK UNIFIED IDEOGRAPH-9914 +U+9918 # 81-17, CJK UNIFIED IDEOGRAPH-9918 +U+991D # 81-19, CJK UNIFIED IDEOGRAPH-991D +U+991E # 81-20, CJK UNIFIED IDEOGRAPH-991E +U+9920 # 81-22, CJK UNIFIED IDEOGRAPH-9920 +U+9921 # 81-18, CJK UNIFIED IDEOGRAPH-9921 +U+9924 # 81-21, CJK UNIFIED IDEOGRAPH-9924 +U+9928 # 20-59, CJK UNIFIED IDEOGRAPH-9928 +U+992C # 81-23, CJK UNIFIED IDEOGRAPH-992C +U+992E # 81-24, CJK UNIFIED IDEOGRAPH-992E +U+993D # 81-25, CJK UNIFIED IDEOGRAPH-993D +U+993E # 81-26, CJK UNIFIED IDEOGRAPH-993E +U+9942 # 81-27, CJK UNIFIED IDEOGRAPH-9942 +U+9945 # 81-29, CJK UNIFIED IDEOGRAPH-9945 +U+9949 # 81-28, CJK UNIFIED IDEOGRAPH-9949 +U+994B # 81-31, CJK UNIFIED IDEOGRAPH-994B +U+994C # 81-34, CJK UNIFIED IDEOGRAPH-994C +U+9950 # 81-30, CJK UNIFIED IDEOGRAPH-9950 +U+9951 # 81-32, CJK UNIFIED IDEOGRAPH-9951 +U+9952 # 81-33, CJK UNIFIED IDEOGRAPH-9952 +U+9955 # 81-35, CJK UNIFIED IDEOGRAPH-9955 +U+9957 # 22-34, CJK UNIFIED IDEOGRAPH-9957 +U+9996 # 28-83, CJK UNIFIED IDEOGRAPH-9996 +U+9997 # 81-36, CJK UNIFIED IDEOGRAPH-9997 +U+9998 # 81-37, CJK UNIFIED IDEOGRAPH-9998 +U+9999 # 25-65, CJK UNIFIED IDEOGRAPH-9999 +U+99A5 # 81-38, CJK UNIFIED IDEOGRAPH-99A5 +U+99A8 # 19-30, CJK UNIFIED IDEOGRAPH-99A8 +U+99AC # 39-47, CJK UNIFIED IDEOGRAPH-99AC +U+99AD # 81-39, CJK UNIFIED IDEOGRAPH-99AD +U+99AE # 81-40, CJK UNIFIED IDEOGRAPH-99AE +U+99B3 # 35-58, CJK UNIFIED IDEOGRAPH-99B3 +U+99B4 # 38-75, CJK UNIFIED IDEOGRAPH-99B4 +U+99BC # 81-41, CJK UNIFIED IDEOGRAPH-99BC +U+99C1 # 39-93, CJK UNIFIED IDEOGRAPH-99C1 +U+99C4 # 34-44, CJK UNIFIED IDEOGRAPH-99C4 +U+99C5 # 17-56, CJK UNIFIED IDEOGRAPH-99C5 +U+99C6 # 22-78, CJK UNIFIED IDEOGRAPH-99C6 +U+99C8 # 22-79, CJK UNIFIED IDEOGRAPH-99C8 +U+99D0 # 35-83, CJK UNIFIED IDEOGRAPH-99D0 +U+99D1 # 81-46, CJK UNIFIED IDEOGRAPH-99D1 +U+99D2 # 22-80, CJK UNIFIED IDEOGRAPH-99D2 +U+99D5 # 18-79, CJK UNIFIED IDEOGRAPH-99D5 +U+99D8 # 81-45, CJK UNIFIED IDEOGRAPH-99D8 +U+99DB # 81-43, CJK UNIFIED IDEOGRAPH-99DB +U+99DD # 81-44, CJK UNIFIED IDEOGRAPH-99DD +U+99DF # 81-42, CJK UNIFIED IDEOGRAPH-99DF +U+99E2 # 81-56, CJK UNIFIED IDEOGRAPH-99E2 +U+99ED # 81-47, CJK UNIFIED IDEOGRAPH-99ED +U+99EE # 81-48, CJK UNIFIED IDEOGRAPH-99EE +U+99F1 # 81-49, CJK UNIFIED IDEOGRAPH-99F1 +U+99F2 # 81-50, CJK UNIFIED IDEOGRAPH-99F2 +U+99F8 # 81-52, CJK UNIFIED IDEOGRAPH-99F8 +U+99FB # 81-51, CJK UNIFIED IDEOGRAPH-99FB +U+99FF # 29-57, CJK UNIFIED IDEOGRAPH-99FF +U+9A01 # 81-53, CJK UNIFIED IDEOGRAPH-9A01 +U+9A05 # 81-55, CJK UNIFIED IDEOGRAPH-9A05 +U+9A0E # 21-19, CJK UNIFIED IDEOGRAPH-9A0E +U+9A0F # 81-54, CJK UNIFIED IDEOGRAPH-9A0F +U+9A12 # 33-91, CJK UNIFIED IDEOGRAPH-9A12 +U+9A13 # 24-19, CJK UNIFIED IDEOGRAPH-9A13 +U+9A19 # 81-57, CJK UNIFIED IDEOGRAPH-9A19 +U+9A28 # 34-45, CJK UNIFIED IDEOGRAPH-9A28 +U+9A2B # 81-58, CJK UNIFIED IDEOGRAPH-9A2B +U+9A30 # 38-13, CJK UNIFIED IDEOGRAPH-9A30 +U+9A37 # 81-59, CJK UNIFIED IDEOGRAPH-9A37 +U+9A3E # 81-64, CJK UNIFIED IDEOGRAPH-9A3E +U+9A40 # 81-62, CJK UNIFIED IDEOGRAPH-9A40 +U+9A42 # 81-61, CJK UNIFIED IDEOGRAPH-9A42 +U+9A43 # 81-63, CJK UNIFIED IDEOGRAPH-9A43 +U+9A45 # 81-60, CJK UNIFIED IDEOGRAPH-9A45 +U+9A4D # 81-66, CJK UNIFIED IDEOGRAPH-9A4D +U+9A55 # 81-65, CJK UNIFIED IDEOGRAPH-9A55 +U+9A57 # 81-68, CJK UNIFIED IDEOGRAPH-9A57 +U+9A5A # 22-35, CJK UNIFIED IDEOGRAPH-9A5A +U+9A5B # 81-67, CJK UNIFIED IDEOGRAPH-9A5B +U+9A5F # 81-69, CJK UNIFIED IDEOGRAPH-9A5F +U+9A62 # 81-70, CJK UNIFIED IDEOGRAPH-9A62 +U+9A64 # 81-72, CJK UNIFIED IDEOGRAPH-9A64 +U+9A65 # 81-71, CJK UNIFIED IDEOGRAPH-9A65 +U+9A69 # 81-73, CJK UNIFIED IDEOGRAPH-9A69 +U+9A6A # 81-75, CJK UNIFIED IDEOGRAPH-9A6A +U+9A6B # 81-74, CJK UNIFIED IDEOGRAPH-9A6B +U+9AA8 # 25-92, CJK UNIFIED IDEOGRAPH-9AA8 +U+9AAD # 81-76, CJK UNIFIED IDEOGRAPH-9AAD +U+9AB0 # 81-77, CJK UNIFIED IDEOGRAPH-9AB0 +U+9AB8 # 19-28, CJK UNIFIED IDEOGRAPH-9AB8 +U+9ABC # 81-78, CJK UNIFIED IDEOGRAPH-9ABC +U+9AC0 # 81-79, CJK UNIFIED IDEOGRAPH-9AC0 +U+9AC4 # 31-81, CJK UNIFIED IDEOGRAPH-9AC4 +U+9ACF # 81-80, CJK UNIFIED IDEOGRAPH-9ACF +U+9AD1 # 81-81, CJK UNIFIED IDEOGRAPH-9AD1 +U+9AD3 # 81-82, CJK UNIFIED IDEOGRAPH-9AD3 +U+9AD4 # 81-83, CJK UNIFIED IDEOGRAPH-9AD4 +U+9AD8 # 25-66, CJK UNIFIED IDEOGRAPH-9AD8 +U+9ADE # 81-84, CJK UNIFIED IDEOGRAPH-9ADE +U+9ADF # 81-85, CJK UNIFIED IDEOGRAPH-9ADF +U+9AE2 # 81-86, CJK UNIFIED IDEOGRAPH-9AE2 +U+9AE3 # 81-87, CJK UNIFIED IDEOGRAPH-9AE3 +U+9AE6 # 81-88, CJK UNIFIED IDEOGRAPH-9AE6 +U+9AEA # 40-17, CJK UNIFIED IDEOGRAPH-9AEA +U+9AEB # 81-90, CJK UNIFIED IDEOGRAPH-9AEB +U+9AED # 41-06, CJK UNIFIED IDEOGRAPH-9AED +U+9AEE # 81-91, CJK UNIFIED IDEOGRAPH-9AEE +U+9AEF # 81-89, CJK UNIFIED IDEOGRAPH-9AEF +U+9AF1 # 81-93, CJK UNIFIED IDEOGRAPH-9AF1 +U+9AF4 # 81-92, CJK UNIFIED IDEOGRAPH-9AF4 +U+9AF7 # 81-94, CJK UNIFIED IDEOGRAPH-9AF7 +U+9AFB # 82-01, CJK UNIFIED IDEOGRAPH-9AFB +U+9B06 # 82-02, CJK UNIFIED IDEOGRAPH-9B06 +U+9B18 # 82-03, CJK UNIFIED IDEOGRAPH-9B18 +U+9B1A # 82-04, CJK UNIFIED IDEOGRAPH-9B1A +U+9B1F # 82-05, CJK UNIFIED IDEOGRAPH-9B1F +U+9B22 # 82-06, CJK UNIFIED IDEOGRAPH-9B22 +U+9B23 # 82-07, CJK UNIFIED IDEOGRAPH-9B23 +U+9B25 # 82-08, CJK UNIFIED IDEOGRAPH-9B25 +U+9B27 # 82-09, CJK UNIFIED IDEOGRAPH-9B27 +U+9B28 # 82-10, CJK UNIFIED IDEOGRAPH-9B28 +U+9B29 # 82-11, CJK UNIFIED IDEOGRAPH-9B29 +U+9B2A # 82-12, CJK UNIFIED IDEOGRAPH-9B2A +U+9B2E # 82-13, CJK UNIFIED IDEOGRAPH-9B2E +U+9B2F # 82-14, CJK UNIFIED IDEOGRAPH-9B2F +U+9B31 # 61-21, CJK UNIFIED IDEOGRAPH-9B31 +U+9B32 # 82-15, CJK UNIFIED IDEOGRAPH-9B32 +U+9B3B # 68-88, CJK UNIFIED IDEOGRAPH-9B3B +U+9B3C # 21-20, CJK UNIFIED IDEOGRAPH-9B3C +U+9B41 # 19-01, CJK UNIFIED IDEOGRAPH-9B41 +U+9B42 # 26-18, CJK UNIFIED IDEOGRAPH-9B42 +U+9B43 # 82-17, CJK UNIFIED IDEOGRAPH-9B43 +U+9B44 # 82-16, CJK UNIFIED IDEOGRAPH-9B44 +U+9B45 # 44-05, CJK UNIFIED IDEOGRAPH-9B45 +U+9B4D # 82-19, CJK UNIFIED IDEOGRAPH-9B4D +U+9B4E # 82-20, CJK UNIFIED IDEOGRAPH-9B4E +U+9B4F # 82-18, CJK UNIFIED IDEOGRAPH-9B4F +U+9B51 # 82-21, CJK UNIFIED IDEOGRAPH-9B51 +U+9B54 # 43-66, CJK UNIFIED IDEOGRAPH-9B54 +U+9B58 # 82-22, CJK UNIFIED IDEOGRAPH-9B58 +U+9B5A # 21-91, CJK UNIFIED IDEOGRAPH-9B5A +U+9B6F # 47-05, CJK UNIFIED IDEOGRAPH-9B6F +U+9B74 # 82-23, CJK UNIFIED IDEOGRAPH-9B74 +U+9B83 # 82-25, CJK UNIFIED IDEOGRAPH-9B83 +U+9B8E # 16-30, CJK UNIFIED IDEOGRAPH-9B8E +U+9B91 # 82-26, CJK UNIFIED IDEOGRAPH-9B91 +U+9B92 # 42-11, CJK UNIFIED IDEOGRAPH-9B92 +U+9B93 # 82-24, CJK UNIFIED IDEOGRAPH-9B93 +U+9B96 # 82-27, CJK UNIFIED IDEOGRAPH-9B96 +U+9B97 # 82-28, CJK UNIFIED IDEOGRAPH-9B97 +U+9B9F # 82-29, CJK UNIFIED IDEOGRAPH-9B9F +U+9BA0 # 82-30, CJK UNIFIED IDEOGRAPH-9BA0 +U+9BA8 # 82-31, CJK UNIFIED IDEOGRAPH-9BA8 +U+9BAA # 43-78, CJK UNIFIED IDEOGRAPH-9BAA +U+9BAB # 27-13, CJK UNIFIED IDEOGRAPH-9BAB +U+9BAD # 26-90, CJK UNIFIED IDEOGRAPH-9BAD +U+9BAE # 33-15, CJK UNIFIED IDEOGRAPH-9BAE +U+9BB4 # 82-32, CJK UNIFIED IDEOGRAPH-9BB4 +U+9BB9 # 82-35, CJK UNIFIED IDEOGRAPH-9BB9 +U+9BC0 # 82-33, CJK UNIFIED IDEOGRAPH-9BC0 +U+9BC6 # 82-36, CJK UNIFIED IDEOGRAPH-9BC6 +U+9BC9 # 24-81, CJK UNIFIED IDEOGRAPH-9BC9 +U+9BCA # 82-34, CJK UNIFIED IDEOGRAPH-9BCA +U+9BCF # 82-37, CJK UNIFIED IDEOGRAPH-9BCF +U+9BD1 # 82-38, CJK UNIFIED IDEOGRAPH-9BD1 +U+9BD2 # 82-39, CJK UNIFIED IDEOGRAPH-9BD2 +U+9BD4 # 82-43, CJK UNIFIED IDEOGRAPH-9BD4 +U+9BD6 # 27-10, CJK UNIFIED IDEOGRAPH-9BD6 +U+9BDB # 34-68, CJK UNIFIED IDEOGRAPH-9BDB +U+9BE1 # 82-44, CJK UNIFIED IDEOGRAPH-9BE1 +U+9BE2 # 82-41, CJK UNIFIED IDEOGRAPH-9BE2 +U+9BE3 # 82-40, CJK UNIFIED IDEOGRAPH-9BE3 +U+9BE4 # 82-42, CJK UNIFIED IDEOGRAPH-9BE4 +U+9BE8 # 23-63, CJK UNIFIED IDEOGRAPH-9BE8 +U+9BF0 # 82-48, CJK UNIFIED IDEOGRAPH-9BF0 +U+9BF1 # 82-47, CJK UNIFIED IDEOGRAPH-9BF1 +U+9BF2 # 82-46, CJK UNIFIED IDEOGRAPH-9BF2 +U+9BF5 # 16-19, CJK UNIFIED IDEOGRAPH-9BF5 +U+9C04 # 82-58, CJK UNIFIED IDEOGRAPH-9C04 +U+9C06 # 82-54, CJK UNIFIED IDEOGRAPH-9C06 +U+9C08 # 82-55, CJK UNIFIED IDEOGRAPH-9C08 +U+9C09 # 82-51, CJK UNIFIED IDEOGRAPH-9C09 +U+9C0A # 82-57, CJK UNIFIED IDEOGRAPH-9C0A +U+9C0C # 82-53, CJK UNIFIED IDEOGRAPH-9C0C +U+9C0D # 19-66, CJK UNIFIED IDEOGRAPH-9C0D +U+9C10 # 47-44, CJK UNIFIED IDEOGRAPH-9C10 +U+9C12 # 82-56, CJK UNIFIED IDEOGRAPH-9C12 +U+9C13 # 82-52, CJK UNIFIED IDEOGRAPH-9C13 +U+9C14 # 82-50, CJK UNIFIED IDEOGRAPH-9C14 +U+9C15 # 82-49, CJK UNIFIED IDEOGRAPH-9C15 +U+9C1B # 82-60, CJK UNIFIED IDEOGRAPH-9C1B +U+9C21 # 82-63, CJK UNIFIED IDEOGRAPH-9C21 +U+9C24 # 82-62, CJK UNIFIED IDEOGRAPH-9C24 +U+9C25 # 82-61, CJK UNIFIED IDEOGRAPH-9C25 +U+9C2D # 41-41, CJK UNIFIED IDEOGRAPH-9C2D +U+9C2E # 82-59, CJK UNIFIED IDEOGRAPH-9C2E +U+9C2F # 16-83, CJK UNIFIED IDEOGRAPH-9C2F +U+9C30 # 82-64, CJK UNIFIED IDEOGRAPH-9C30 +U+9C32 # 82-66, CJK UNIFIED IDEOGRAPH-9C32 +U+9C39 # 19-79, CJK UNIFIED IDEOGRAPH-9C39 +U+9C3A # 82-45, CJK UNIFIED IDEOGRAPH-9C3A +U+9C3B # 17-23, CJK UNIFIED IDEOGRAPH-9C3B +U+9C3E # 82-68, CJK UNIFIED IDEOGRAPH-9C3E +U+9C46 # 82-67, CJK UNIFIED IDEOGRAPH-9C46 +U+9C47 # 82-65, CJK UNIFIED IDEOGRAPH-9C47 +U+9C48 # 35-13, CJK UNIFIED IDEOGRAPH-9C48 +U+9C52 # 43-80, CJK UNIFIED IDEOGRAPH-9C52 +U+9C57 # 46-58, CJK UNIFIED IDEOGRAPH-9C57 +U+9C5A # 82-69, CJK UNIFIED IDEOGRAPH-9C5A +U+9C60 # 82-70, CJK UNIFIED IDEOGRAPH-9C60 +U+9C67 # 82-71, CJK UNIFIED IDEOGRAPH-9C67 +U+9C76 # 82-72, CJK UNIFIED IDEOGRAPH-9C76 +U+9C78 # 82-73, CJK UNIFIED IDEOGRAPH-9C78 +U+9CE5 # 36-27, CJK UNIFIED IDEOGRAPH-9CE5 +U+9CE7 # 82-74, CJK UNIFIED IDEOGRAPH-9CE7 +U+9CE9 # 40-23, CJK UNIFIED IDEOGRAPH-9CE9 +U+9CEB # 82-79, CJK UNIFIED IDEOGRAPH-9CEB +U+9CEC # 82-75, CJK UNIFIED IDEOGRAPH-9CEC +U+9CF0 # 82-76, CJK UNIFIED IDEOGRAPH-9CF0 +U+9CF3 # 43-17, CJK UNIFIED IDEOGRAPH-9CF3 +U+9CF4 # 44-36, CJK UNIFIED IDEOGRAPH-9CF4 +U+9CF6 # 38-48, CJK UNIFIED IDEOGRAPH-9CF6 +U+9D03 # 82-80, CJK UNIFIED IDEOGRAPH-9D03 +U+9D06 # 82-81, CJK UNIFIED IDEOGRAPH-9D06 +U+9D07 # 38-30, CJK UNIFIED IDEOGRAPH-9D07 +U+9D08 # 82-78, CJK UNIFIED IDEOGRAPH-9D08 +U+9D09 # 82-77, CJK UNIFIED IDEOGRAPH-9D09 +U+9D0E # 18-10, CJK UNIFIED IDEOGRAPH-9D0E +U+9D12 # 82-89, CJK UNIFIED IDEOGRAPH-9D12 +U+9D15 # 82-88, CJK UNIFIED IDEOGRAPH-9D15 +U+9D1B # 17-85, CJK UNIFIED IDEOGRAPH-9D1B +U+9D1F # 82-86, CJK UNIFIED IDEOGRAPH-9D1F +U+9D23 # 82-85, CJK UNIFIED IDEOGRAPH-9D23 +U+9D26 # 82-83, CJK UNIFIED IDEOGRAPH-9D26 +U+9D28 # 19-91, CJK UNIFIED IDEOGRAPH-9D28 +U+9D2A # 82-82, CJK UNIFIED IDEOGRAPH-9D2A +U+9D2B # 28-18, CJK UNIFIED IDEOGRAPH-9D2B +U+9D2C # 18-09, CJK UNIFIED IDEOGRAPH-9D2C +U+9D3B # 25-67, CJK UNIFIED IDEOGRAPH-9D3B +U+9D3E # 82-92, CJK UNIFIED IDEOGRAPH-9D3E +U+9D3F # 82-91, CJK UNIFIED IDEOGRAPH-9D3F +U+9D41 # 82-90, CJK UNIFIED IDEOGRAPH-9D41 +U+9D44 # 82-87, CJK UNIFIED IDEOGRAPH-9D44 +U+9D46 # 82-93, CJK UNIFIED IDEOGRAPH-9D46 +U+9D48 # 82-94, CJK UNIFIED IDEOGRAPH-9D48 +U+9D50 # 83-05, CJK UNIFIED IDEOGRAPH-9D50 +U+9D51 # 83-04, CJK UNIFIED IDEOGRAPH-9D51 +U+9D59 # 83-06, CJK UNIFIED IDEOGRAPH-9D59 +U+9D5C # 17-13, CJK UNIFIED IDEOGRAPH-9D5C +U+9D5D # 83-01, CJK UNIFIED IDEOGRAPH-9D5D +U+9D5E # 83-02, CJK UNIFIED IDEOGRAPH-9D5E +U+9D60 # 25-84, CJK UNIFIED IDEOGRAPH-9D60 +U+9D61 # 44-25, CJK UNIFIED IDEOGRAPH-9D61 +U+9D64 # 83-03, CJK UNIFIED IDEOGRAPH-9D64 +U+9D6C # 43-18, CJK UNIFIED IDEOGRAPH-9D6C +U+9D6F # 83-11, CJK UNIFIED IDEOGRAPH-9D6F +U+9D72 # 83-07, CJK UNIFIED IDEOGRAPH-9D72 +U+9D7A # 83-12, CJK UNIFIED IDEOGRAPH-9D7A +U+9D87 # 83-09, CJK UNIFIED IDEOGRAPH-9D87 +U+9D89 # 83-08, CJK UNIFIED IDEOGRAPH-9D89 +U+9D8F # 23-60, CJK UNIFIED IDEOGRAPH-9D8F +U+9D9A # 83-13, CJK UNIFIED IDEOGRAPH-9D9A +U+9DA4 # 83-14, CJK UNIFIED IDEOGRAPH-9DA4 +U+9DA9 # 83-15, CJK UNIFIED IDEOGRAPH-9DA9 +U+9DAB # 83-10, CJK UNIFIED IDEOGRAPH-9DAB +U+9DAF # 82-84, CJK UNIFIED IDEOGRAPH-9DAF +U+9DB2 # 83-16, CJK UNIFIED IDEOGRAPH-9DB2 +U+9DB4 # 36-65, CJK UNIFIED IDEOGRAPH-9DB4 +U+9DB8 # 83-20, CJK UNIFIED IDEOGRAPH-9DB8 +U+9DBA # 83-21, CJK UNIFIED IDEOGRAPH-9DBA +U+9DBB # 83-19, CJK UNIFIED IDEOGRAPH-9DBB +U+9DC1 # 83-18, CJK UNIFIED IDEOGRAPH-9DC1 +U+9DC2 # 83-24, CJK UNIFIED IDEOGRAPH-9DC2 +U+9DC4 # 83-17, CJK UNIFIED IDEOGRAPH-9DC4 +U+9DC6 # 83-22, CJK UNIFIED IDEOGRAPH-9DC6 +U+9DCF # 83-23, CJK UNIFIED IDEOGRAPH-9DCF +U+9DD3 # 83-26, CJK UNIFIED IDEOGRAPH-9DD3 +U+9DD9 # 83-25, CJK UNIFIED IDEOGRAPH-9DD9 +U+9DE6 # 83-28, CJK UNIFIED IDEOGRAPH-9DE6 +U+9DED # 83-29, CJK UNIFIED IDEOGRAPH-9DED +U+9DEF # 83-30, CJK UNIFIED IDEOGRAPH-9DEF +U+9DF2 # 47-41, CJK UNIFIED IDEOGRAPH-9DF2 +U+9DF8 # 83-27, CJK UNIFIED IDEOGRAPH-9DF8 +U+9DF9 # 34-75, CJK UNIFIED IDEOGRAPH-9DF9 +U+9DFA # 26-77, CJK UNIFIED IDEOGRAPH-9DFA +U+9DFD # 83-31, CJK UNIFIED IDEOGRAPH-9DFD +U+9E1A # 83-32, CJK UNIFIED IDEOGRAPH-9E1A +U+9E1B # 83-33, CJK UNIFIED IDEOGRAPH-9E1B +U+9E1E # 83-34, CJK UNIFIED IDEOGRAPH-9E1E +U+9E75 # 83-35, CJK UNIFIED IDEOGRAPH-9E75 +U+9E78 # 24-20, CJK UNIFIED IDEOGRAPH-9E78 +U+9E79 # 83-36, CJK UNIFIED IDEOGRAPH-9E79 +U+9E7D # 83-37, CJK UNIFIED IDEOGRAPH-9E7D +U+9E7F # 28-15, CJK UNIFIED IDEOGRAPH-9E7F +U+9E81 # 83-38, CJK UNIFIED IDEOGRAPH-9E81 +U+9E88 # 83-39, CJK UNIFIED IDEOGRAPH-9E88 +U+9E8B # 83-40, CJK UNIFIED IDEOGRAPH-9E8B +U+9E8C # 83-41, CJK UNIFIED IDEOGRAPH-9E8C +U+9E91 # 83-44, CJK UNIFIED IDEOGRAPH-9E91 +U+9E92 # 83-42, CJK UNIFIED IDEOGRAPH-9E92 +U+9E93 # 47-28, CJK UNIFIED IDEOGRAPH-9E93 +U+9E95 # 83-43, CJK UNIFIED IDEOGRAPH-9E95 +U+9E97 # 46-79, CJK UNIFIED IDEOGRAPH-9E97 +U+9E9D # 83-45, CJK UNIFIED IDEOGRAPH-9E9D +U+9E9F # 46-59, CJK UNIFIED IDEOGRAPH-9E9F +U+9EA5 # 83-46, CJK UNIFIED IDEOGRAPH-9EA5 +U+9EA6 # 39-94, CJK UNIFIED IDEOGRAPH-9EA6 +U+9EA9 # 83-47, CJK UNIFIED IDEOGRAPH-9EA9 +U+9EAA # 83-49, CJK UNIFIED IDEOGRAPH-9EAA +U+9EAD # 83-50, CJK UNIFIED IDEOGRAPH-9EAD +U+9EB8 # 83-48, CJK UNIFIED IDEOGRAPH-9EB8 +U+9EB9 # 25-77, CJK UNIFIED IDEOGRAPH-9EB9 +U+9EBA # 44-45, CJK UNIFIED IDEOGRAPH-9EBA +U+9EBB # 43-67, CJK UNIFIED IDEOGRAPH-9EBB +U+9EBC # 54-87, CJK UNIFIED IDEOGRAPH-9EBC +U+9EBE # 61-64, CJK UNIFIED IDEOGRAPH-9EBE +U+9EBF # 43-91, CJK UNIFIED IDEOGRAPH-9EBF +U+9EC4 # 18-11, CJK UNIFIED IDEOGRAPH-9EC4 +U+9ECC # 83-52, CJK UNIFIED IDEOGRAPH-9ECC +U+9ECD # 21-48, CJK UNIFIED IDEOGRAPH-9ECD +U+9ECE # 83-53, CJK UNIFIED IDEOGRAPH-9ECE +U+9ECF # 83-54, CJK UNIFIED IDEOGRAPH-9ECF +U+9ED0 # 83-55, CJK UNIFIED IDEOGRAPH-9ED0 +U+9ED2 # 25-85, CJK UNIFIED IDEOGRAPH-9ED2 +U+9ED4 # 83-56, CJK UNIFIED IDEOGRAPH-9ED4 +U+9ED8 # 64-52, CJK UNIFIED IDEOGRAPH-9ED8 +U+9ED9 # 44-59, CJK UNIFIED IDEOGRAPH-9ED9 +U+9EDB # 34-67, CJK UNIFIED IDEOGRAPH-9EDB +U+9EDC # 83-57, CJK UNIFIED IDEOGRAPH-9EDC +U+9EDD # 83-59, CJK UNIFIED IDEOGRAPH-9EDD +U+9EDE # 83-58, CJK UNIFIED IDEOGRAPH-9EDE +U+9EE0 # 83-60, CJK UNIFIED IDEOGRAPH-9EE0 +U+9EE5 # 83-61, CJK UNIFIED IDEOGRAPH-9EE5 +U+9EE8 # 83-62, CJK UNIFIED IDEOGRAPH-9EE8 +U+9EEF # 83-63, CJK UNIFIED IDEOGRAPH-9EEF +U+9EF4 # 83-64, CJK UNIFIED IDEOGRAPH-9EF4 +U+9EF6 # 83-65, CJK UNIFIED IDEOGRAPH-9EF6 +U+9EF7 # 83-66, CJK UNIFIED IDEOGRAPH-9EF7 +U+9EF9 # 83-67, CJK UNIFIED IDEOGRAPH-9EF9 +U+9EFB # 83-68, CJK UNIFIED IDEOGRAPH-9EFB +U+9EFC # 83-69, CJK UNIFIED IDEOGRAPH-9EFC +U+9EFD # 83-70, CJK UNIFIED IDEOGRAPH-9EFD +U+9F07 # 83-71, CJK UNIFIED IDEOGRAPH-9F07 +U+9F08 # 83-72, CJK UNIFIED IDEOGRAPH-9F08 +U+9F0E # 37-04, CJK UNIFIED IDEOGRAPH-9F0E +U+9F13 # 24-61, CJK UNIFIED IDEOGRAPH-9F13 +U+9F15 # 83-74, CJK UNIFIED IDEOGRAPH-9F15 +U+9F20 # 33-45, CJK UNIFIED IDEOGRAPH-9F20 +U+9F21 # 83-75, CJK UNIFIED IDEOGRAPH-9F21 +U+9F2C # 83-76, CJK UNIFIED IDEOGRAPH-9F2C +U+9F3B # 41-01, CJK UNIFIED IDEOGRAPH-9F3B +U+9F3E # 83-77, CJK UNIFIED IDEOGRAPH-9F3E +U+9F4A # 83-78, CJK UNIFIED IDEOGRAPH-9F4A +U+9F4B # 67-23, CJK UNIFIED IDEOGRAPH-9F4B +U+9F4E # 76-58, CJK UNIFIED IDEOGRAPH-9F4E +U+9F4F # 80-77, CJK UNIFIED IDEOGRAPH-9F4F +U+9F52 # 83-79, CJK UNIFIED IDEOGRAPH-9F52 +U+9F54 # 83-80, CJK UNIFIED IDEOGRAPH-9F54 +U+9F5F # 83-82, CJK UNIFIED IDEOGRAPH-9F5F +U+9F60 # 83-83, CJK UNIFIED IDEOGRAPH-9F60 +U+9F61 # 83-84, CJK UNIFIED IDEOGRAPH-9F61 +U+9F62 # 46-80, CJK UNIFIED IDEOGRAPH-9F62 +U+9F63 # 83-81, CJK UNIFIED IDEOGRAPH-9F63 +U+9F66 # 83-85, CJK UNIFIED IDEOGRAPH-9F66 +U+9F67 # 83-86, CJK UNIFIED IDEOGRAPH-9F67 +U+9F6A # 83-88, CJK UNIFIED IDEOGRAPH-9F6A +U+9F6C # 83-87, CJK UNIFIED IDEOGRAPH-9F6C +U+9F72 # 83-90, CJK UNIFIED IDEOGRAPH-9F72 +U+9F76 # 83-91, CJK UNIFIED IDEOGRAPH-9F76 +U+9F77 # 83-89, CJK UNIFIED IDEOGRAPH-9F77 +U+9F8D # 46-22, CJK UNIFIED IDEOGRAPH-9F8D +U+9F95 # 83-92, CJK UNIFIED IDEOGRAPH-9F95 +U+9F9C # 83-93, CJK UNIFIED IDEOGRAPH-9F9C +U+9F9D # 67-52, CJK UNIFIED IDEOGRAPH-9F9D +U+9FA0 # 83-94, CJK UNIFIED IDEOGRAPH-9FA0 diff --git a/java/com/google/domain/registry/tmch/BUILD b/java/com/google/domain/registry/tmch/BUILD new file mode 100644 index 000000000..8ec5b415a --- /dev/null +++ b/java/com/google/domain/registry/tmch/BUILD @@ -0,0 +1,38 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +java_library( + name = "tmch", + srcs = glob(["*.java"]), + resources = glob([ + "*.crl", + "*.crt", + "*.asc", + ]), + deps = [ + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/common/util/concurrent", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/cron", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/request", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/xml", + "//third_party/java/appengine:appengine-api", + "//third_party/java/bouncycastle", + "//third_party/java/bouncycastle_bcpg", + "//third_party/java/dagger", + "//third_party/java/joda_time", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//third_party/java/servlet/servlet_api", + ], +) diff --git a/java/com/google/domain/registry/tmch/ClaimsListParser.java b/java/com/google/domain/registry/tmch/ClaimsListParser.java new file mode 100644 index 000000000..c2fee098e --- /dev/null +++ b/java/com/google/domain/registry/tmch/ClaimsListParser.java @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.tmch.ClaimsListShard; + +import org.joda.time.DateTime; + +import java.util.List; + +/** + * Claims List (MarksDB DNL CSV) Parser. + * + *

This is a quick and dirty CSV parser made specifically for the DNL CSV format defined in the + * TMCH specification. It doesn't support any fancy CSV features like quotes. + * + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.1" + */ +public class ClaimsListParser { + + /** + * Converts the lines from the DNL CSV file into a {@link ClaimsListShard} object. + * + *

Please note that this does not insert the object into the datastore. + */ + public static ClaimsListShard parse(List lines) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + + // First line: , + List firstLine = Splitter.on(',').splitToList(lines.get(0)); + checkArgument(firstLine.size() == 2, String.format( + "Line 1: Expected 2 elements, found %d", firstLine.size())); + + Integer version = Integer.valueOf(firstLine.get(0)); + DateTime creationTime = DateTime.parse(firstLine.get(1)); + checkArgument(version == 1, String.format( + "Line 1: Expected version 1, found %d", version)); + + // Second line contains headers: DNL,lookup-key,insertion-datetime + List secondLine = Splitter.on(',').splitToList(lines.get(1)); + checkArgument(secondLine.size() == 3, String.format( + "Line 2: Expected 3 elements, found %d", secondLine.size())); + checkArgument("DNL".equals(secondLine.get(0)), String.format( + "Line 2: Expected header \"DNL\", found \"%s\"", secondLine.get(0))); + checkArgument("lookup-key".equals(secondLine.get(1)), String.format( + "Line 2: Expected header \"lookup-key\", found \"%s\"", secondLine.get(1))); + checkArgument("insertion-datetime".equals(secondLine.get(2)), String.format( + "Line 2: Expected header \"insertion-datetime\", found \"%s\"", secondLine.get(2))); + + // Subsequent lines: ,, + for (int i = 2; i < lines.size(); i++) { + List currentLine = Splitter.on(',').splitToList(lines.get(i)); + checkArgument(currentLine.size() == 3, String.format( + "Line %d: Expected 3 elements, found %d", i + 1, currentLine.size())); + + String label = currentLine.get(0); + String lookupKey = currentLine.get(1); + DateTime.parse(currentLine.get(2)); // This is the insertion time, currently unused. + builder.put(label, lookupKey); + } + + return ClaimsListShard.create(creationTime, builder.build()); + } +} diff --git a/java/com/google/domain/registry/tmch/LordnLog.java b/java/com/google/domain/registry/tmch/LordnLog.java new file mode 100644 index 000000000..ae580b158 --- /dev/null +++ b/java/com/google/domain/registry/tmch/LordnLog.java @@ -0,0 +1,257 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; + +import org.joda.time.DateTime; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Parser of LORDN log responses from the MarksDB server during the NORDN process. + * + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3.1" + */ +@Immutable +public final class LordnLog implements Iterable> { + + /** Indicates whether or not the LORDN upload succeeded. */ + public enum Status { ACCEPTED, REJECTED } + + /** Result code for individual DN lines. */ + @Immutable + public static final class Result { + + /** Outcome categories for individual DN lines. */ + public enum Outcome { OK, WARNING, ERROR } + + private final int code; + private final String description; + private final Outcome outcome; + + private Result(int code, String description) { + this.code = code; + this.description = description; + if (2000 <= code && code <= 2099) { + this.outcome = Outcome.OK; + } else if (3500 <= code && code <= 3699) { + this.outcome = Outcome.WARNING; + } else if (4500 <= code && code <= 4699) { + this.outcome = Outcome.ERROR; + } else { + throw new IllegalArgumentException("Invalid DN result code: " + code); + } + } + + public int getCode() { + return code; + } + + public String getDescription() { + return description; + } + + public Outcome getOutcome() { + return outcome; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("code", code) + .add("outcome", outcome) + .add("description", description) + .toString(); + } + } + + private static final Map RESULTS = ImmutableMap.builder() + .put(2000, new Result(2000, "OK")) + .put(2001, new Result(2001, "OK but not processed")) + .put(3601, new Result(3601, "TCN Acceptance Date after Registration Date")) + .put(3602, new Result(3602, "Duplicate DN Line")) + .put(3603, new Result(3603, "DNROID Notified Earlier")) + .put(3604, new Result(3604, "TCN Checksum invalid")) + .put(3605, new Result(3605, "TCN Expired")) + .put(3606, new Result(3606, "Wrong TCNID used")) + .put(3609, new Result(3609, "Invalid SMD used")) + .put(3610, new Result(3610, "DN reported outside of the time window")) + .put(3611, new Result(3611, "DN does not match the labels in SMD")) + .put(3612, new Result(3612, "SMDID does not exist")) + .put(3613, new Result(3613, "SMD was revoked when used")) + .put(3614, new Result(3614, "TCNID does not exist")) + .put(3615, new Result(3615, "Recent-dnl-insertion outside of the time window")) + .put(3616, new Result(3616, "Registration Date of DN in claims before the end of Sunrise")) + .put(3617, new Result(3617, "Registrar has not been approved by the TMDB")) + .put(4501, new Result(4501, "Syntax Error in DN Line")) + .put(4601, new Result(4601, "Invalid TLD used")) + .put(4602, new Result(4602, "Registrar ID Invalid")) + .put(4603, new Result(4603, "Registration Date in the future")) + .put(4606, new Result(4606, "TLD not in Sunrise or Claims")) + .put(4607, new Result(4607, "Application Date in the future")) + .put(4608, new Result(4608, "Application Date is later than Registration Date")) + .put(4609, new Result(4609, "TCNID wrong syntax")) + .put(4610, new Result(4610, "TCN Acceptance Date is in the future")) + .put(4611, new Result(4611, "Label has never existed in the TMDB")) + .build(); + + /** Base64 matcher between one and sixty characters. */ + private static final Pattern LOG_ID_PATTERN = Pattern.compile("[-A-Za-z0-9+/=]{1,60}"); + + private final String logId; + private final Status status; + private final DateTime logCreation; + private final DateTime lordnCreation; + private final boolean hasWarnings; + private final ImmutableMap results; + + private LordnLog( + String logId, + Status status, + DateTime logCreation, + DateTime lordnCreation, + boolean hasWarnings, + ImmutableMap results) { + this.logId = logId; + this.status = status; + this.logCreation = logCreation; + this.lordnCreation = lordnCreation; + this.hasWarnings = hasWarnings; + this.results = results; + } + + public String getLogId() { + return logId; + } + + public Status getStatus() { + return status; + } + + public DateTime getLogCreation() { + return logCreation; + } + + public DateTime getLordnCreation() { + return lordnCreation; + } + + public boolean hasWarnings() { + return hasWarnings; + } + + @Nullable + public Result getResult(String roid) { + return results.get(roid); + } + + @Override + public Iterator> iterator() { + return results.entrySet().iterator(); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("logId", logId) + .add("status", status) + .add("logCreation", logCreation) + .add("lordnCreation", lordnCreation) + .add("hasWarnings", hasWarnings) + .add("results", results) + .toString(); + } + + /** Turns lines of NORDN log returned by MarksDB into a data structure. */ + public static LordnLog parse(List lines) { + // First line: ,,, + // ,,, + List firstLine = Splitter.on(',').splitToList(lines.get(0)); + checkArgument(firstLine.size() == 7, String.format( + "Line 1: Expected 7 elements, found %d", firstLine.size())); + + // + , version of the file, this field MUST be 1. + int version = Integer.parseInt(firstLine.get(0)); + checkArgument(version == 1, String.format( + "Line 1: Expected version 1, found %d", version)); + + // + , date and time in UTC that the + // LORDN Log was created. + DateTime logCreation = DateTime.parse(firstLine.get(1)); + + // + , date and time in UTC of + // creation for the LORDN file that this log file is referring + // to. + DateTime lordnCreation = DateTime.parse(firstLine.get(2)); + + // + , unique identifier of the LORDN Log + // provided by the TMDB. This identifier could be used by the + // Registry Operator to unequivocally identify the LORDN Log. + // The identified will be a string of a maximum LENGTH of 60 + // characters from the Base 64 alphabet. + String logId = firstLine.get(3); + checkArgument(LOG_ID_PATTERN.matcher(logId).matches(), + "Line 1: Log ID does not match base64 pattern: %s", logId); + + // + , whether the LORDN file has been accepted for + // processing by the TMDB. Possible values are "accepted" or + // "rejected". + Status status = Status.valueOf(firstLine.get(4).toUpperCase()); + + // + , whether the LORDN Log has any warning result + // codes. Possible values are "no-warnings" or "warnings- + // present". + boolean hasWarnings = !"no-warnings".equals(firstLine.get(5)); + + // + , number of DNs effective allocations + // processed in the LORDN file. + int dnLines = Integer.parseInt(firstLine.get(6)); + int actual = lines.size() - 2; + checkArgument(dnLines == actual, + "Line 1: Number of entries (%d) differs from declaration (%d)", actual, dnLines); + + // Second line contains headers: roid,result-code + checkArgument(lines.get(1).equals("roid,result-code"), + "Line 2: Unexpected header list: %s", lines.get(1)); + + // Subsequent lines: , + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + for (int i = 2; i < lines.size(); i++) { + List currentLine = Splitter.on(',').splitToList(lines.get(i)); + checkArgument(currentLine.size() == 2, String.format( + "Line %d: Expected 2 elements, found %d", i + 1, currentLine.size())); + String roid = currentLine.get(0); + int code = Integer.parseInt(currentLine.get(1)); + Result result = checkNotNull(RESULTS.get(code), + "Line %d: Unknown result code: %d", i, code); + builder.put(roid, result); + } + + return new LordnLog(logId, status, logCreation, lordnCreation, hasWarnings, builder.build()); + } +} diff --git a/java/com/google/domain/registry/tmch/LordnRequestInitializer.java b/java/com/google/domain/registry/tmch/LordnRequestInitializer.java new file mode 100644 index 000000000..610e08587 --- /dev/null +++ b/java/com/google/domain/registry/tmch/LordnRequestInitializer.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.domain.registry.util.UrlFetchUtils.setAuthorizationHeader; + +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.common.base.Optional; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.registry.Registry; + +import javax.inject.Inject; + +/** Helper class for setting the authorization header on a MarksDB LORDN request. */ +final class LordnRequestInitializer { + + @Inject @Key("marksdbLordnPassword") Optional marksdbLordnPassword; + @Inject LordnRequestInitializer() {} + + /** Initializes a URL fetch request for talking to the MarksDB server. */ + void initialize(HTTPRequest request, String tld) { + setAuthorizationHeader(request, getMarksDbLordnCredentials(tld)); + } + + /** Returns the username and password for the current TLD to login to the MarksDB server. */ + private Optional getMarksDbLordnCredentials(String tld) { + if (marksdbLordnPassword.isPresent()) { + String lordnUsername = verifyNotNull(Registry.get(tld).getLordnUsername(), + "lordnUsername is not set for %s.", Registry.get(tld).getTld()); + return Optional.of(String.format("%s:%s", lordnUsername, marksdbLordnPassword.get())); + } else { + return Optional.absent(); + } + } +} diff --git a/java/com/google/domain/registry/tmch/LordnTask.java b/java/com/google/domain/registry/tmch/LordnTask.java new file mode 100644 index 000000000..8ecb26d72 --- /dev/null +++ b/java/com/google/domain/registry/tmch/LordnTask.java @@ -0,0 +1,162 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.appengine.api.taskqueue.LeaseOptions; +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.taskqueue.TaskOptions.Method; +import com.google.appengine.api.taskqueue.TransientFailureException; +import com.google.apphosting.api.DeadlineExceededException; +import com.google.common.base.Joiner; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.Uninterruptibles; +import com.google.domain.registry.model.domain.DomainResource; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.util.NonFinalForTesting; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Helper methods for creating tasks containing CSV line data in the lordn-sunrise and lordn-claims + * queues based on DomainResource changes. + */ +public class LordnTask { + + public static final String QUEUE_SUNRISE = "lordn-sunrise"; + public static final String QUEUE_CLAIMS = "lordn-claims"; + public static final String COLUMNS_CLAIMS = "roid,domain-name,notice-id,registrar-id," + + "registration-datetime,ack-datetime,application-datetime"; + public static final String COLUMNS_SUNRISE = "roid,domain-name,SMD-id,registrar-id," + + "registration-datetime,application-datetime"; + private static final Duration LEASE_PERIOD = Duration.standardHours(1); + + /** This is the max allowable batch size. */ + private static final long BATCH_SIZE = 1000; + + @NonFinalForTesting + private static Long backOffMillis = 2000L; + + /** + * Converts a list of queue tasks, each containing a row of CSV data, into a single newline- + * delimited String. + */ + public static String convertTasksToCsv(List tasks, DateTime now, String columns) { + String header = String.format("1,%s,%d\n%s\n", now, tasks.size(), columns); + StringBuilder csv = new StringBuilder(header); + for (TaskHandle task : checkNotNull(tasks)) { + String payload = new String(task.getPayload()); + if (!Strings.isNullOrEmpty(payload)) { + csv.append(payload).append("\n"); + } + } + return csv.toString(); + } + + /** Leases and returns all tasks from the queue with the specified tag tld, in batches. */ + public static List loadAllTasks(Queue queue, String tld) { + ImmutableList.Builder allTasks = new ImmutableList.Builder<>(); + int numErrors = 0; + long backOff = backOffMillis; + while (true) { + try { + List tasks = queue.leaseTasks(LeaseOptions.Builder + .withTag(tld) + .leasePeriod(LEASE_PERIOD.getMillis(), TimeUnit.MILLISECONDS) + .countLimit(BATCH_SIZE)); + allTasks.addAll(tasks); + if (tasks.isEmpty()) { + return allTasks.build(); + } + } catch (TransientFailureException | DeadlineExceededException e) { + if (++numErrors >= 3) { + throw new RuntimeException("Error leasing tasks", e); + } + Uninterruptibles.sleepUninterruptibly(backOff, TimeUnit.MILLISECONDS); + backOff *= 2; + } + } + } + + /** + * Enqueues a task in the LORDN queue representing a line of CSV for LORDN export. + */ + public static void enqueueDomainResourceTask(DomainResource domain) { + ofy().assertInTransaction(); + // This method needs to use ofy transactionTime as the DomainResource's creationTime because + // CreationTime isn't yet populated when this method is called during the resource flow. + String tld = domain.getTld(); + if (domain.getLaunchNotice() == null) { + getQueue(QUEUE_SUNRISE).add(TaskOptions.Builder + .withTag(tld) + .method(Method.PULL) + .payload(getCsvLineForSunriseDomain(domain, ofy().getTransactionTime()))); + } else { + getQueue(QUEUE_CLAIMS).add(TaskOptions.Builder + .withTag(tld) + .method(Method.PULL) + .payload(getCsvLineForClaimsDomain(domain, ofy().getTransactionTime()))); + } + } + + /** Returns the corresponding CSV LORDN line for a sunrise domain. */ + public static String getCsvLineForSunriseDomain(DomainResource domain, DateTime transactionTime) { + // Only skip nulls in the outer join because only application time is allowed to be null. + Joiner joiner = Joiner.on(','); + return joiner.skipNulls().join( + joiner.join( + domain.getRepoId(), + domain.getFullyQualifiedDomainName(), + domain.getSmdId(), + getIanaIdentifier(domain.getCreationClientId()), + transactionTime), // Used as creation time. + domain.getApplicationTime()); // This may be null for sunrise QLP domains. + } + + /** Returns the corresponding CSV LORDN line for a claims domain. */ + public static String getCsvLineForClaimsDomain(DomainResource domain, DateTime transactionTime) { + // Only skip nulls in the outer join because only application time is allowed to be null. + Joiner joiner = Joiner.on(','); + return joiner.skipNulls().join( + joiner.join( + domain.getRepoId(), + domain.getFullyQualifiedDomainName(), + domain.getLaunchNotice().getNoticeId().getTcnId(), + getIanaIdentifier(domain.getCreationClientId()), + transactionTime, // Used as creation time. + domain.getLaunchNotice().getAcceptedTime()), + domain.getApplicationTime()); // This may be null if this wasn't from landrush. + } + + /** Retrieves the IANA identifier for a registrar based on the client id. */ + private static String getIanaIdentifier(String clientId) { + Registrar registrar = checkNotNull( + Registrar.loadByClientId(clientId), + "No registrar found for client id: %s", clientId); + // Return the string "null" for null identifiers, since some Registrar.Types such as OTE will + // have null iana ids. + return String.valueOf(registrar.getIanaIdentifier()); + } +} diff --git a/java/com/google/domain/registry/tmch/Marksdb.java b/java/com/google/domain/registry/tmch/Marksdb.java new file mode 100644 index 000000000..7129cbc35 --- /dev/null +++ b/java/com/google/domain/registry/tmch/Marksdb.java @@ -0,0 +1,129 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.appengine.api.urlfetch.FetchOptions.Builder.validateCertificate; +import static com.google.appengine.api.urlfetch.HTTPMethod.GET; +import static com.google.domain.registry.util.HexDumper.dumpHex; +import static com.google.domain.registry.util.UrlFetchUtils.setAuthorizationHeader; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.common.base.Optional; +import com.google.common.io.ByteSource; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.util.UrlFetchException; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureList; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URL; +import java.security.Security; +import java.security.SignatureException; +import java.util.List; + +import javax.annotation.Tainted; +import javax.inject.Inject; + +/** Shared code for tasks that download stuff from MarksDB. */ +public final class Marksdb { + + @Inject URLFetchService fetchService; + @Inject @Config("tmchMarksdbUrl") String tmchMarksdbUrl; + @Inject @Key("marksdbPublicKey") PGPPublicKey marksdbPublicKey; + @Inject Marksdb() {} + + /** + * Extracts a {@link PGPSignature} object from a blob of {@code .sig} data. + * + * @throws SignatureException if a signature object couldn't be extracted for any reason. + */ + private static PGPSignature pgpExtractSignature(@Tainted byte[] signature) + throws SignatureException { + try { + ByteArrayInputStream input = new ByteArrayInputStream(signature); + PGPObjectFactory decoder = new BcPGPObjectFactory(PGPUtil.getDecoderStream(input)); + Object object = decoder.nextObject(); + if (object == null) { + throw new SignatureException(String.format( + "No OpenPGP packets found in signature.\n%s", + dumpHex(signature))); + } + if (!(object instanceof PGPSignatureList)) { + throw new SignatureException(String.format( + "Expected PGPSignatureList packet but got %s\n%s", + object.getClass().getSimpleName(), + dumpHex(signature))); + } + PGPSignatureList sigs = (PGPSignatureList) object; + if (sigs.isEmpty()) { + throw new SignatureException(String.format( + "PGPSignatureList doesn't have a PGPSignature.\n%s", + dumpHex(signature))); + } + return sigs.get(0); + } catch (IOException e) { + throw new SignatureException(String.format( + "Failed to extract PGPSignature object from .sig blob.\n%s", + dumpHex(signature)), e); + } + } + + @SuppressWarnings("deprecation") + private static void pgpVerifySignature(byte[] data, byte[] signature, PGPPublicKey publicKey) + throws PGPException, SignatureException { + Security.addProvider(new BouncyCastleProvider()); + PGPSignature sig = pgpExtractSignature(signature); + sig.init(new BcPGPContentVerifierBuilderProvider(), publicKey); + sig.update(data); + if (!sig.verify()) { + throw new SignatureException(String.format( + "MarksDB PGP signature verification failed.\n%s", + dumpHex(signature))); + } + } + + byte[] fetch(URL url, Optional login) throws IOException { + HTTPRequest req = new HTTPRequest(url, GET, validateCertificate().setDeadline(60d)); + setAuthorizationHeader(req, login); + HTTPResponse rsp = fetchService.fetch(req); + if (rsp.getResponseCode() != SC_OK) { + throw new UrlFetchException("Failed to fetch from MarksDB", req, rsp); + } + return rsp.getContent(); + } + + List fetchSignedCsv( + Optional login, String csvPath, String sigPath) + throws IOException, SignatureException, PGPException { + byte[] csv = fetch(new URL(tmchMarksdbUrl + csvPath), login); + byte[] sig = fetch(new URL(tmchMarksdbUrl + sigPath), login); + pgpVerifySignature(csv, sig, marksdbPublicKey); + return ByteSource.wrap(csv).asCharSource(US_ASCII).readLines(); + } +} diff --git a/java/com/google/domain/registry/tmch/NordnUploadAction.java b/java/com/google/domain/registry/tmch/NordnUploadAction.java new file mode 100644 index 000000000..b29f39e7d --- /dev/null +++ b/java/com/google/domain/registry/tmch/NordnUploadAction.java @@ -0,0 +1,165 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; +import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; +import static com.google.appengine.api.urlfetch.FetchOptions.Builder.validateCertificate; +import static com.google.appengine.api.urlfetch.HTTPMethod.POST; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.net.HttpHeaders.LOCATION; +import static com.google.common.net.MediaType.CSV_UTF_8; +import static com.google.domain.registry.tmch.LordnTask.COLUMNS_CLAIMS; +import static com.google.domain.registry.tmch.LordnTask.COLUMNS_SUNRISE; +import static com.google.domain.registry.tmch.LordnTask.convertTasksToCsv; +import static com.google.domain.registry.util.UrlFetchUtils.getHeaderFirst; +import static com.google.domain.registry.util.UrlFetchUtils.setPayloadMultipart; +import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED; + +import com.google.appengine.api.taskqueue.Queue; +import com.google.appengine.api.taskqueue.TaskHandle; +import com.google.appengine.api.taskqueue.TaskOptions; +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.common.base.Optional; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.UrlFetchException; + +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.io.IOException; +import java.net.URL; +import java.util.List; +import java.util.Random; + +import javax.inject.Inject; + +/** + * Action that reads the NORDN pull queues, uploads claims and sunrise marks data to TMCH, and + * enqueues subsequent upload verification tasks. A unique actionLogId is generated and passed + * along to the verify action so that connected verify tasks can be identified by looking at logs. + * + * @see NordnVerifyAction + */ +@Action(path = NordnUploadAction.PATH, method = Action.Method.POST, automaticallyPrintOk = true) +public final class NordnUploadAction implements Runnable { + + static final String PATH = "/_dr/task/nordnUpload"; + static final String LORDN_PHASE_PARAM = "lordn-phase"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + /** + * A unique (enough) id that is outputted in log lines to make it clear which log lines are + * associated with a given invocation of the NordnUploadAction in the event that multiple + * instances execute simultaneously. + */ + private final String actionLogId = String.valueOf(1000000000 + new Random().nextInt(1000000000)); + + @Inject Clock clock; + @Inject LordnRequestInitializer lordnRequestInitializer; + @Inject URLFetchService fetchService; + @Inject @Config("tmchMarksdbUrl") String tmchMarksdbUrl; + @Inject @Parameter(LORDN_PHASE_PARAM) String phase; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject NordnUploadAction() {} + + /** + * These LORDN parameter names correspond to the relative paths in LORDN URLs and cannot be + * changed on our end. + */ + private static final String PARAM_LORDN_PHASE_SUNRISE = "sunrise"; + private static final String PARAM_LORDN_PHASE_CLAIMS = "claims"; + + /** How long to wait before attempting to verify an upload by fetching the log. */ + private static final Duration VERIFY_DELAY = Duration.standardMinutes(30); + + @Override + public void run() { + try { + processLordnTasks(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void processLordnTasks() throws IOException { + checkArgument(phase.equals(PARAM_LORDN_PHASE_SUNRISE) + || phase.equals(PARAM_LORDN_PHASE_CLAIMS), + "Invalid phase specified to Nordn servlet: %s.", phase); + DateTime now = clock.nowUtc(); + Queue queue = getQueue( + phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? LordnTask.QUEUE_SUNRISE : LordnTask.QUEUE_CLAIMS); + String columns = phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? COLUMNS_SUNRISE : COLUMNS_CLAIMS; + List tasks = LordnTask.loadAllTasks(queue, tld); + if (!tasks.isEmpty()) { + String csvData = convertTasksToCsv(tasks, now, columns); + uploadCsvToLordn(String.format("/LORDN/%s/%s", tld, phase), csvData); + queue.deleteTask(tasks); + } + } + + /** + * Upload LORDN file to MarksDB. + * + *

Idempotency: If the exact same LORDN report is uploaded twice, the MarksDB server will + * return the same confirmation number. + * + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3" + */ + private void uploadCsvToLordn(String urlPath, String csvData) throws IOException { + String url = tmchMarksdbUrl + urlPath; + logger.infofmt("LORDN upload task %s: Sending to URL: %s ; data: %s", + actionLogId, url, csvData); + HTTPRequest req = new HTTPRequest(new URL(url), POST, validateCertificate().setDeadline(60d)); + lordnRequestInitializer.initialize(req, tld); + setPayloadMultipart(req, "file", "claims.csv", CSV_UTF_8, csvData); + HTTPResponse rsp = fetchService.fetch(req); + logger.infofmt("LORDN upload task %s response: HTTP response code %d, response data: %s", + actionLogId, rsp.getResponseCode(), rsp.getContent()); + if (rsp.getResponseCode() != SC_ACCEPTED) { + throw new UrlFetchException( + String.format("LORDN upload task %s error: Failed to upload LORDN claims to MarksDB", + actionLogId), + req, rsp); + } + Optional location = getHeaderFirst(rsp, LOCATION); + if (!location.isPresent()) { + throw new UrlFetchException( + String.format("LORDN upload task %s error: MarksDB failed to provide a Location header", + actionLogId), + req, rsp); + } + getQueue(NordnVerifyAction.QUEUE).add(makeVerifyTask(new URL(location.get()), csvData)); + } + + private TaskOptions makeVerifyTask(URL url, String csvData) { + // This task doesn't technically need csvData. The only reason it's passed along is in case the + // upload is rejected, in which case csvData will be logged so that it may be uploaded manually. + return withUrl(NordnVerifyAction.PATH) + .header(NordnVerifyAction.URL_HEADER, url.toString()) + .header(NordnVerifyAction.HEADER_ACTION_LOG_ID, actionLogId) + .param(RequestParameters.PARAM_TLD, tld) + .param(NordnVerifyAction.PARAM_CSV_DATA, csvData) + .countdownMillis(VERIFY_DELAY.getMillis()); + } +} diff --git a/java/com/google/domain/registry/tmch/NordnVerifyAction.java b/java/com/google/domain/registry/tmch/NordnVerifyAction.java new file mode 100644 index 000000000..9c1324db1 --- /dev/null +++ b/java/com/google/domain/registry/tmch/NordnVerifyAction.java @@ -0,0 +1,141 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.appengine.api.urlfetch.FetchOptions.Builder.validateCertificate; +import static com.google.appengine.api.urlfetch.HTTPMethod.GET; +import static java.nio.charset.StandardCharsets.UTF_8; +import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.io.ByteSource; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.request.Header; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.HttpException.ConflictException; +import com.google.domain.registry.request.Parameter; +import com.google.domain.registry.request.RequestParameters; +import com.google.domain.registry.request.Response; +import com.google.domain.registry.util.FormattingLogger; +import com.google.domain.registry.util.UrlFetchException; + +import java.io.IOException; +import java.net.URL; +import java.util.Map.Entry; + +import javax.inject.Inject; + +/** + * NORDN CSV uploading system, verify operation. + * + *

Every three hours (max twenty-six hours) we generate CSV files for each TLD which we need + * to upload to MarksDB. The upload is a two-phase process. We send the CSV data as a POST request + * and get back a 202 Accepted. This response will give us a URL in the Location header, where + * we'll check back later for the actual result. + * + * @see NordnUploadAction + * @see + * http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-5.2.3.3 + */ +@Action(path = NordnVerifyAction.PATH, method = Action.Method.POST, automaticallyPrintOk = true) +public final class NordnVerifyAction implements Runnable { + + public static final String PARAM_CSV_DATA = "csvData"; + + static final String PATH = "/_dr/task/nordnVerify"; + static final String QUEUE = "marksdb"; + static final String URL_HEADER = "X-DomainRegistry-Nordn-Url"; + static final String HEADER_ACTION_LOG_ID = "X-DomainRegistry-ActionLogId"; + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject LordnRequestInitializer lordnRequestInitializer; + @Inject Response response; + @Inject URLFetchService fetchService; + @Inject @Header(URL_HEADER) URL url; + @Inject @Header(HEADER_ACTION_LOG_ID) String actionLogId; + @Inject @Parameter(RequestParameters.PARAM_TLD) String tld; + @Inject @Parameter(PARAM_CSV_DATA) String csvData; + @Inject NordnVerifyAction() {} + + @Override + public void run() { + try { + verify(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Fetch LORDN log file from MarksDB to confirm successful upload. + * + *

Idempotency: The confirmation URL will always return the same result once it becomes + * available. + * + * @throws ConflictException if MarksDB has not yet finished processing the LORDN upload + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3.1" + */ + @VisibleForTesting + LordnLog verify() throws IOException { + if (csvData.isEmpty()) { + throw new BadRequestException( + String.format("LORDN verify task %s: Missing CSV payload.", actionLogId)); + } + logger.infofmt("LORDN verify task %s: Sending request to URL %s.", actionLogId, url); + HTTPRequest req = new HTTPRequest(url, GET, validateCertificate().setDeadline(60d)); + lordnRequestInitializer.initialize(req, tld); + HTTPResponse rsp = fetchService.fetch(req); + logger.infofmt("LORDN verify task %s response: HTTP response code %d, response data: %s", + actionLogId, rsp.getResponseCode(), rsp.getContent()); + if (rsp.getResponseCode() == SC_NO_CONTENT) { + // Send a 400+ status code so App Engine will retry the task. + throw new ConflictException("Not ready"); + } + if (rsp.getResponseCode() != SC_OK) { + throw new UrlFetchException( + String.format("LORDN verify task %s: Failed to verify LORDN upload to MarksDB.", + actionLogId), + req, rsp); + } + LordnLog log = + LordnLog.parse(ByteSource.wrap(rsp.getContent()).asCharSource(UTF_8).readLines()); + if (log.getStatus() == LordnLog.Status.ACCEPTED) { + logger.infofmt("LORDN verify task %s: Upload accepted", actionLogId); + } else { + logger.severefmt("LORDN verify task %s: Upload rejected with reason: %s", actionLogId, log); + } + for (Entry result : log) { + switch (result.getValue().getOutcome()) { + case OK: + break; + case WARNING: + // fall through + case ERROR: + logger.warning(result.toString()); + break; + default: + logger.warningfmt("LORDN verify task %s: Unexpected outcome: %s", + actionLogId, result.toString()); + break; + } + } + return log; + } +} diff --git a/java/com/google/domain/registry/tmch/SmdrlCsvParser.java b/java/com/google/domain/registry/tmch/SmdrlCsvParser.java new file mode 100644 index 000000000..cc434c65b --- /dev/null +++ b/java/com/google/domain/registry/tmch/SmdrlCsvParser.java @@ -0,0 +1,72 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.model.smd.SignedMarkRevocationList; + +import org.joda.time.DateTime; + +import java.util.List; + +/** + * Signed Mark Data Revocation List (SMDRL) CSV Parser + * + *

This is a quick and dirty CSV parser made specifically for the SMDRL CSV format defined in + * the TMCH specification. It doesn't support any fancy CSV features like quotes. + * + * @see "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.2" + */ +public final class SmdrlCsvParser { + + /** Converts the lines from the DNL CSV file into a data structure. */ + public static SignedMarkRevocationList parse(List lines) { + ImmutableMap.Builder revokes = new ImmutableMap.Builder<>(); + + // First line: , + List firstLine = Splitter.on(',').splitToList(lines.get(0)); + checkArgument(firstLine.size() == 2, String.format( + "Line 1: Expected 2 elements, found %d", firstLine.size())); + Integer version = Integer.valueOf(firstLine.get(0)); + checkArgument(version == 1, String.format( + "Line 1: Expected version 1, found %d", version)); + DateTime creationTime = DateTime.parse(firstLine.get(1)).withZone(UTC); + + // Second line contains headers: smd-id,insertion-datetime + List secondLine = Splitter.on(',').splitToList(lines.get(1)); + checkArgument(secondLine.size() == 2, String.format( + "Line 2: Expected 2 elements, found %d", secondLine.size())); + checkArgument("smd-id".equals(secondLine.get(0)), String.format( + "Line 2: Expected header \"smd-id\", found \"%s\"", secondLine.get(0))); + checkArgument("insertion-datetime".equals(secondLine.get(1)), String.format( + "Line 2: Expected header \"insertion-datetime\", found \"%s\"", secondLine.get(1))); + + // Subsequent lines: , + for (int i = 2; i < lines.size(); i++) { + List currentLine = Splitter.on(',').splitToList(lines.get(i)); + checkArgument(currentLine.size() == 2, String.format( + "Line %d: Expected 2 elements, found %d", i + 1, currentLine.size())); + String smdId = currentLine.get(0); + DateTime revokedTime = DateTime.parse(currentLine.get(1)); + revokes.put(smdId, revokedTime); + } + + return SignedMarkRevocationList.create(creationTime, revokes.build()); + } +} diff --git a/java/com/google/domain/registry/tmch/TmchCertificateAuthority.java b/java/com/google/domain/registry/tmch/TmchCertificateAuthority.java new file mode 100644 index 000000000..6c1ae76c1 --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchCertificateAuthority.java @@ -0,0 +1,143 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.Throwables.propagateIfInstanceOf; +import static com.google.domain.registry.util.CacheUtils.memoizeWithLongExpiration; +import static com.google.domain.registry.util.CacheUtils.memoizeWithShortExpiration; +import static com.google.domain.registry.util.ResourceUtils.readResourceUtf8; +import static com.google.domain.registry.util.X509Utils.loadCrl; + +import com.google.common.base.Supplier; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.model.tmch.TmchCrl; +import com.google.domain.registry.util.Clock; +import com.google.domain.registry.util.NonFinalForTesting; +import com.google.domain.registry.util.SystemClock; +import com.google.domain.registry.util.X509Utils; + +import java.security.GeneralSecurityException; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; + +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** Datastore singleton for ICANN's TMCH root certificate and revocation list. */ +@Immutable +@ThreadSafe +public final class TmchCertificateAuthority { + + private static final RegistryEnvironment ENVIRONMENT = RegistryEnvironment.get(); + + private static final String ROOT_CRT_FILE = "icann-tmch.crt"; + private static final String TEST_ROOT_CRT_FILE = "icann-tmch-test.crt"; + private static final String CRL_FILE = "icann-tmch.crl"; + private static final String TEST_CRL_FILE = "icann-tmch-test.crl"; + + /** + * A cached supplier that loads the crl from datastore or chooses a default value. + *

+ * We keep the cache here rather than caching TmchCrl in the model, because loading the crl string + * into an X509CRL instance is expensive and should itself be cached. + */ + private static final Supplier CRL_CACHE = + memoizeWithShortExpiration(new Supplier() { + @Override + public X509CRL get() { + TmchCrl storedCrl = TmchCrl.get(); + try { + X509CRL crl = loadCrl((storedCrl == null) + ? readResourceUtf8( + TmchCertificateAuthority.class, + ENVIRONMENT.config().getTmchCaTestingMode() ? TEST_CRL_FILE : CRL_FILE) + : storedCrl.getCrl()); + crl.verify(getRoot().getPublicKey()); + return crl; + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + }}); + + /** A cached function that loads the crt from a jar resource. */ + private static final Supplier ROOT_CACHE = + memoizeWithLongExpiration(new Supplier() { + @Override + public X509Certificate get() { + try { + X509Certificate root = X509Utils.loadCertificate(readResourceUtf8( + TmchCertificateAuthority.class, + ENVIRONMENT.config().getTmchCaTestingMode() ? TEST_ROOT_CRT_FILE : ROOT_CRT_FILE)); + root.checkValidity(clock.nowUtc().toDate()); + return root; + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + }}); + + @NonFinalForTesting + private static Clock clock = new SystemClock(); + + /** + * Check that {@code cert} is signed by the ICANN TMCH CA root and not revoked. + * + *

Support for certificate chains has not been implemented. + * + * @throws GeneralSecurityException for unsupported protocols, certs not signed by the TMCH, + * incorrect keys, and for invalid, old, not-yet-valid or revoked certificates. + * @see X509Utils#verifyCertificate + */ + public static void verify(X509Certificate cert) throws GeneralSecurityException { + synchronized (TmchCertificateAuthority.class) { + X509Utils.verifyCertificate(getRoot(), getCrl(), cert, clock.nowUtc().toDate()); + } + } + + /** + * Update to the latest TMCH X.509 certificate revocation list and save to the datastore. + * + *

Your ASCII-armored CRL must be signed by the current ICANN root certificate. + * + *

This will not take effect (either on this instance or on others) until the CRL_CACHE next + * refreshes itself. + * + * @throws GeneralSecurityException for unsupported protocols, certs not signed by the TMCH, + * incorrect keys, and for invalid, old, not-yet-valid or revoked certificates. + * @see X509Utils#verifyCrl + */ + public static void updateCrl(String asciiCrl) throws GeneralSecurityException { + X509CRL crl = X509Utils.loadCrl(asciiCrl); + X509Utils.verifyCrl(getRoot(), getCrl(), crl, clock.nowUtc().toDate()); + TmchCrl.set(asciiCrl); + } + + public static X509Certificate getRoot() throws GeneralSecurityException { + try { + return ROOT_CACHE.get(); + } catch (RuntimeException e) { + propagateIfInstanceOf(e.getCause(), GeneralSecurityException.class); + throw e; + } + } + + public static X509CRL getCrl() throws GeneralSecurityException { + try { + return CRL_CACHE.get(); + } catch (RuntimeException e) { + propagateIfInstanceOf(e.getCause(), GeneralSecurityException.class); + throw e; + } + } +} diff --git a/java/com/google/domain/registry/tmch/TmchCrlTask.java b/java/com/google/domain/registry/tmch/TmchCrlTask.java new file mode 100644 index 000000000..33e5dddb7 --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchCrlTask.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.domain.registry.request.Action.Method.POST; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Optional; +import com.google.domain.registry.config.ConfigModule.Config; +import com.google.domain.registry.request.Action; + +import java.io.IOException; +import java.net.URL; +import java.security.GeneralSecurityException; + +import javax.inject.Inject; + +/** Task to download the latest ICANN TMCH CRL from MarksDB. */ +@Action(path = "/_dr/task/tmchCrl", method = POST, automaticallyPrintOk = true) +public final class TmchCrlTask implements Runnable { + + @Inject Marksdb marksdb; + @Inject @Config("tmchCrlUrl") URL tmchCrlUrl; + @Inject TmchCrlTask() {} + + /** Synchronously fetches latest ICANN TMCH CRL and saves it to datastore. */ + @Override + public void run() { + try { + TmchCertificateAuthority + .updateCrl(new String(marksdb.fetch(tmchCrlUrl, Optional.absent()), UTF_8)); + } catch (IOException | GeneralSecurityException e) { + throw new RuntimeException("Failed to update ICANN TMCH CRL.", e); + } + } +} diff --git a/java/com/google/domain/registry/tmch/TmchData.java b/java/com/google/domain/registry/tmch/TmchData.java new file mode 100644 index 000000000..4b92a5401 --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchData.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.CharMatcher.whitespace; + +import com.google.common.io.ByteSource; +import com.google.domain.registry.model.smd.EncodedSignedMark; + +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRing; + +import java.io.IOException; +import java.io.InputStream; + +/** Helper class for common data loaded from the jar and datastore at runtime. */ +public final class TmchData { + + private static final String BEGIN_ENCODED_SMD = "-----BEGIN ENCODED SMD-----"; + private static final String END_ENCODED_SMD = "-----END ENCODED SMD-----"; + + @SuppressWarnings("deprecation") + static PGPPublicKey loadPublicKey(ByteSource pgpPublicKeyFile) { + try (InputStream input = pgpPublicKeyFile.openStream(); + InputStream decoder = PGPUtil.getDecoderStream(input)) { + return new BcPGPPublicKeyRing(decoder).getPublicKey(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** Extracts encoded SMD from an ASCII-armored string. */ + public static EncodedSignedMark readEncodedSignedMark(String data) { + int beginTagIndex = data.indexOf(BEGIN_ENCODED_SMD); + int endTagIndex = data.indexOf(END_ENCODED_SMD); + if (beginTagIndex >= 0 && endTagIndex >= 0) { + data = data.substring(beginTagIndex + BEGIN_ENCODED_SMD.length(), endTagIndex); + } + return EncodedSignedMark.create("base64", whitespace().removeFrom(data)); + } +} diff --git a/java/com/google/domain/registry/tmch/TmchDnlTask.java b/java/com/google/domain/registry/tmch/TmchDnlTask.java new file mode 100644 index 000000000..8051b0f62 --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchDnlTask.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.domain.registry.request.Action.Method.POST; + +import com.google.common.base.Optional; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.tmch.ClaimsListShard; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.util.FormattingLogger; + +import org.bouncycastle.openpgp.PGPException; + +import java.io.IOException; +import java.security.SignatureException; +import java.util.List; + +import javax.inject.Inject; + +/** Task to download the latest domain name list (aka claims list) from MarksDB. */ +@Action(path = "/_dr/task/tmchDnl", method = POST, automaticallyPrintOk = true) +public final class TmchDnlTask implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + private static final String DNL_CSV_PATH = "/dnl/dnl-latest.csv"; + private static final String DNL_SIG_PATH = "/dnl/dnl-latest.sig"; + + @Inject Marksdb marksdb; + @Inject @Key("marksdbDnlLogin") Optional marksdbDnlLogin; + @Inject TmchDnlTask() {} + + /** Synchronously fetches latest domain name list and saves it to datastore. */ + @Override + public void run() { + List lines; + try { + lines = marksdb.fetchSignedCsv(marksdbDnlLogin, DNL_CSV_PATH, DNL_SIG_PATH); + } catch (SignatureException | IOException | PGPException e) { + throw new RuntimeException(e); + } + ClaimsListShard claims = ClaimsListParser.parse(lines); + claims.save(); + logger.infofmt("Inserted %,d claims into datastore, created at %s", + claims.size(), claims.getCreationTime()); + } +} diff --git a/java/com/google/domain/registry/tmch/TmchModule.java b/java/com/google/domain/registry/tmch/TmchModule.java new file mode 100644 index 000000000..fb362765c --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchModule.java @@ -0,0 +1,77 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.io.Resources.asByteSource; +import static com.google.common.io.Resources.getResource; +import static com.google.domain.registry.request.RequestParameters.extractRequiredHeader; +import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; + +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.request.Header; +import com.google.domain.registry.request.HttpException.BadRequestException; +import com.google.domain.registry.request.Parameter; + +import dagger.Module; +import dagger.Provides; + +import org.bouncycastle.openpgp.PGPPublicKey; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.servlet.http.HttpServletRequest; + +/** Dagger module for TMCH package. */ +@Module +public final class TmchModule { + + private static final PGPPublicKey MARKSDB_PUBLIC_KEY = TmchData + .loadPublicKey(asByteSource(getResource(TmchModule.class, "marksdb-public-key.asc"))); + + @Provides + @Key("marksdbPublicKey") + static PGPPublicKey getMarksdbPublicKey() { + return MARKSDB_PUBLIC_KEY; + } + + @Provides + @Parameter(NordnUploadAction.LORDN_PHASE_PARAM) + static String provideLordnPhase(HttpServletRequest req) { + return extractRequiredParameter(req, NordnUploadAction.LORDN_PHASE_PARAM); + } + + @Provides + @Header(NordnVerifyAction.URL_HEADER) + static URL provideUrl(HttpServletRequest req) { + try { + return new URL(extractRequiredHeader(req, NordnVerifyAction.URL_HEADER)); + } catch (MalformedURLException e) { + throw new BadRequestException("Bad URL: " + NordnVerifyAction.URL_HEADER); + } + } + + @Provides + @Header(NordnVerifyAction.HEADER_ACTION_LOG_ID) + static String provideActionLogId(HttpServletRequest req) { + return extractRequiredHeader(req, NordnVerifyAction.HEADER_ACTION_LOG_ID); + } + + @Provides + @Parameter(NordnVerifyAction.PARAM_CSV_DATA) + static String provideCsvData(HttpServletRequest req) { + return extractRequiredParameter(req, NordnVerifyAction.PARAM_CSV_DATA); + } +} diff --git a/java/com/google/domain/registry/tmch/TmchSmdrlTask.java b/java/com/google/domain/registry/tmch/TmchSmdrlTask.java new file mode 100644 index 000000000..1eeb91b9a --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchSmdrlTask.java @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.domain.registry.request.Action.Method.POST; + +import com.google.common.base.Optional; +import com.google.domain.registry.keyring.api.KeyModule.Key; +import com.google.domain.registry.model.smd.SignedMarkRevocationList; +import com.google.domain.registry.request.Action; +import com.google.domain.registry.util.FormattingLogger; + +import org.bouncycastle.openpgp.PGPException; + +import java.io.IOException; +import java.security.SignatureException; +import java.util.List; + +import javax.inject.Inject; + +/** Task to download the latest signed mark revocation list from MarksDB. */ +@Action(path = "/_dr/task/tmchSmdrl", method = POST, automaticallyPrintOk = true) +public final class TmchSmdrlTask implements Runnable { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + private static final String SMDRL_CSV_PATH = "/smdrl/smdrl-latest.csv"; + private static final String SMDRL_SIG_PATH = "/smdrl/smdrl-latest.sig"; + + @Inject Marksdb marksdb; + @Inject @Key("marksdbSmdrlLogin") Optional marksdbSmdrlLogin; + @Inject TmchSmdrlTask() {} + + /** Synchronously fetches latest signed mark revocation list and saves it to datastore. */ + @Override + public void run() { + List lines; + try { + lines = marksdb.fetchSignedCsv(marksdbSmdrlLogin, SMDRL_CSV_PATH, SMDRL_SIG_PATH); + } catch (SignatureException | IOException | PGPException e) { + throw new RuntimeException(e); + } + SignedMarkRevocationList smdrl = SmdrlCsvParser.parse(lines); + smdrl.save(); + logger.infofmt("Inserted %,d smd revocations into datastore, created at %s", + smdrl.size(), smdrl.getCreationTime()); + } +} diff --git a/java/com/google/domain/registry/tmch/TmchXmlSignature.java b/java/com/google/domain/registry/tmch/TmchXmlSignature.java new file mode 100644 index 000000000..ad3e2ce99 --- /dev/null +++ b/java/com/google/domain/registry/tmch/TmchXmlSignature.java @@ -0,0 +1,192 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tmch; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.getRootCause; +import static com.google.common.base.Throwables.propagateIfInstanceOf; +import static com.google.domain.registry.xml.XmlTransformer.loadXmlSchemas; + +import com.google.common.collect.ImmutableList; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.ThreadSafe; +import javax.xml.crypto.AlgorithmMethod; +import javax.xml.crypto.KeySelector; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.KeySelectorResult; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.XMLCryptoContext; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMValidateContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.X509Data; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; + +/** Helper class for verifying TMCH certificates and XML signatures. */ +@ThreadSafe +public final class TmchXmlSignature { + + private static final Schema SCHEMA = + loadXmlSchemas(ImmutableList.of("mark.xsd", "dsig.xsd", "smd.xsd")); + + /** + * Verifies that signed mark data contains a valid signature. + * + *

This method DOES NOT check if the SMD ID is revoked. It's only concerned with the + * cryptographic stuff. + * + * @throws GeneralSecurityException for unsupported protocols, certs not signed by the TMCH, + * incorrect keys, and for invalid, old, not-yet-valid or revoked certificates. + * @throws IOException + * @throws MarshalException + * @throws ParserConfigurationException + * @throws SAXException + */ + public static void verify(byte[] smdXml) + throws GeneralSecurityException, + IOException, + MarshalException, + ParserConfigurationException, + SAXException, + XMLSignatureException { + checkArgument(smdXml.length > 0); + Document doc = parseSmdDocument(new ByteArrayInputStream(smdXml)); + + NodeList signatureNodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); + if (signatureNodes.getLength() != 1) { + throw new XMLSignatureException("Expected exactly one element."); + } + XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM"); + KeyValueKeySelector selector = new KeyValueKeySelector(); + DOMValidateContext context = new DOMValidateContext(selector, signatureNodes.item(0)); + XMLSignature signature = factory.unmarshalXMLSignature(context); + + boolean isValid; + try { + isValid = signature.validate(context); + } catch (XMLSignatureException e) { + Throwable cause = getRootCause(e); + propagateIfInstanceOf(cause, GeneralSecurityException.class); + throw e; + } + if (!isValid) { + throw new XMLSignatureException(explainValidationProblem(context, signature)); + } + } + + private static Document parseSmdDocument(InputStream input) + throws SAXException, IOException, ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setSchema(SCHEMA); + dbf.setAttribute("http://apache.org/xml/features/validation/schema/normalized-value", false); + dbf.setNamespaceAware(true); + return dbf.newDocumentBuilder().parse(input); + } + + private static String explainValidationProblem( + DOMValidateContext context, XMLSignature signature) + throws XMLSignatureException { + @SuppressWarnings("unchecked") // Safe by specification. + List references = signature.getSignedInfo().getReferences(); + StringBuilder builder = new StringBuilder(); + builder.append("Signature failed core validation\n"); + boolean sv = signature.getSignatureValue().validate(context); + builder.append("Signature validation status: " + sv + "\n"); + for (Reference ref : references) { + builder.append("references["); + builder.append(ref.getURI()); + builder.append("] validity status: "); + builder.append(ref.validate(context)); + builder.append("\n"); + } + return builder.toString(); + } + + /** Callback class for DOM validator checks validity of {@code } elements. */ + private static final class KeyValueKeySelector extends KeySelector { + @Nullable + @Override + public KeySelectorResult select( + @Nullable KeyInfo keyInfo, + KeySelector.Purpose purpose, + AlgorithmMethod method, + XMLCryptoContext context) throws KeySelectorException { + if (keyInfo == null) { + return null; + } + for (Object keyInfoChild : keyInfo.getContent()) { + if (keyInfoChild instanceof X509Data) { + X509Data x509Data = (X509Data) keyInfoChild; + for (Object x509DataChild : x509Data.getContent()) { + if (x509DataChild instanceof X509Certificate) { + X509Certificate cert = (X509Certificate) x509DataChild; + try { + TmchCertificateAuthority.verify(cert); + } catch (SignatureException e) { + throw new KeySelectorException(new CertificateSignatureException(e.getMessage())); + } catch (GeneralSecurityException e) { + throw new KeySelectorException(e); + } + return new SimpleKeySelectorResult(cert.getPublicKey()); + } + } + } + } + throw new KeySelectorException("No public key found."); + } + } + + /** @see TmchXmlSignature.KeyValueKeySelector */ + private static class SimpleKeySelectorResult implements KeySelectorResult { + private PublicKey publicKey; + + SimpleKeySelectorResult(PublicKey publicKey) { + this.publicKey = checkNotNull(publicKey, "publicKey"); + } + + @Override + public java.security.Key getKey() { + return publicKey; + } + } + + /** CertificateException wrapper. */ + public static class CertificateSignatureException extends CertificateException { + public CertificateSignatureException(String message) { + super(message); + } + } +} diff --git a/java/com/google/domain/registry/tmch/icann-tmch-test.crl b/java/com/google/domain/registry/tmch/icann-tmch-test.crl new file mode 100644 index 000000000..6643f518d --- /dev/null +++ b/java/com/google/domain/registry/tmch/icann-tmch-test.crl @@ -0,0 +1,15 @@ +-----BEGIN X509 CRL----- +MIICVDCCATwCAQEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxPDA6BgNV +BAoTM0ludGVybmV0IENvcnBvcmF0aW9uIGZvciBBc3NpZ25lZCBOYW1lcyBhbmQg +TnVtYmVyczEvMC0GA1UEAxMmSUNBTk4gVHJhZGVtYXJrIENsZWFyaW5naG91c2Ug +UGlsb3QgQ0EXDTEzMDcwOTAwMDAwMFoXDTE4MDYyNTIzNTk1OVowWzBZAiAusBt6 ++hp7nbLd/oLa0HRKfentcmbRPTYWiDEoJ82FexcNMTMwNzA5MjIwMzIwWjAmMAoG +A1UdFQQDCgEBMBgGA1UdGAQRGA8yMDEzMDcwOTIxMjcwMFqgLzAtMB8GA1UdIwQY +MBaAFMOtPqbWEQBFgFw6V0qKbdwxDZ5xMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEB +CwUAA4IBAQCa3ZHr/qihqZ/M6Eo9SQ2G2dkvT6cs1L71YkiGmCpZdWvYm99sJ3yj +iLe00vEyLWCPcq/qmgmhM0+Ou8ZHZ2nw2f4mzkjRwpzUn8oNMd5FHwlhpcRXHyjH +DhPbX1a5xITPZj9UUq0Lhk+bciCtC+G/jtEIuaIWL5bW1KER+FxI3Tt3888xx17W +0QoQiXEHltjl9zTj09YiVb4usGOQysLzAbhnyG5IBDBn11gWwx/g7rcXFO/z0KIp +h3rKk5noar/kpp/qAzNDyByMfD2uJtHnxHLrafsK3HY6CDLCp6GqLNSA5zxSjVOq +3sEaZYxI0Fg5DqBuN7efSCbM9bwFTYMy +-----END X509 CRL----- diff --git a/java/com/google/domain/registry/tmch/icann-tmch-test.crt b/java/com/google/domain/registry/tmch/icann-tmch-test.crt new file mode 100644 index 000000000..142208b01 --- /dev/null +++ b/java/com/google/domain/registry/tmch/icann-tmch-test.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEVjCCAz6gAwIBAgIgLrAbevoae52y3f6C2tB0Sn3p7XJm0T02FogxKCfNhXkw +DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxPDA6BgNVBAoTM0ludGVybmV0 +IENvcnBvcmF0aW9uIGZvciBBc3NpZ25lZCBOYW1lcyBhbmQgTnVtYmVyczEvMC0G +A1UEAxMmSUNBTk4gVHJhZGVtYXJrIENsZWFyaW5naG91c2UgUGlsb3QgQ0EwHhcN +MTMwNjI2MDAwMDAwWhcNMjMwNjI1MjM1OTU5WjB8MQswCQYDVQQGEwJVUzE8MDoG +A1UEChMzSW50ZXJuZXQgQ29ycG9yYXRpb24gZm9yIEFzc2lnbmVkIE5hbWVzIGFu +ZCBOdW1iZXJzMS8wLQYDVQQDEyZJQ0FOTiBUcmFkZW1hcmsgQ2xlYXJpbmdob3Vz +ZSBQaWxvdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMJiRqFg +iCoDF8zMJMKHPMEuSpjbEl9ZWII+1WawDyt+jw841HsTT+6MwZsqExbQvukgvnuS +lA3Rg3xTFxodMaVZWsVQJy2PXGHVFRLnCp05DYZsMGZabuN9mIekYwtjePo89Lz0 +JtU3ibL3squGG3gg6TLtPjks7Txm18BYPOYLznui32GUz+1aIZuk2p5A/rSldsh3 +bke68IX5WZhKuIxT0+BjS8yfLWI0HCUs71WVxzvlJ1v22/eMK0WEA6+ZhCbOKIav +VtGNJrwIYwhZmxqfiR1HzHTLvrV0SLlJ2bwNk/yzKm8IJfuFezQ5BBtQ2RS9opFX +X8ft3v+uQQQvi+MCAwEAAaOBwzCBwDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud +DgQWBBTDrT6m1hEARYBcOldKim3cMQ2ecTAOBgNVHQ8BAf8EBAMCAQYwNAYDVR0f +BC0wKzApoCegJYYjaHR0cDovL2NybC5pY2Fubi5vcmcvdG1jaF9waWxvdC5jcmww +RQYDVR0gBD4wPDA6BgMqAwQwMzAxBggrBgEFBQcCARYlaHR0cDovL3d3dy5pY2Fu +bi5vcmcvcGlsb3RfcmVwb3NpdG9yeTANBgkqhkiG9w0BAQsFAAOCAQEAKUfEJ5X6 +QAttajjRVseJFQxRXGHTgCaDk8C/1nj1ielZAuZtgdUpWDUr0NnGCi+LHSsgdTYR ++vMrxir7EVYQevrBobELkxeTEfjF9FVqjBHInyPFLOFkz15zGG2IwPJps+vhAd/7 +gT0ph1k2FEkJFGL5LwRf1ms4IX0vDkxTIX8Qxy1jczCiSsoV8pwlhh2NHAkpGQWN +/pTS0Uqi7uU5Bm/IoGvPBzUp5n5SjUMnTZx/+1zAuerSabt483sXBcWsjgl7MqFt +fONiAtNeMNfh60lTMu4zgVwLZTO4TQM5Q2uylPPmZtwnA88QvM2IL85cIYJHd0z9 +jpUQMBGHXF2WQA== +-----END CERTIFICATE----- diff --git a/java/com/google/domain/registry/tmch/icann-tmch.crl b/java/com/google/domain/registry/tmch/icann-tmch.crl new file mode 100644 index 000000000..195795e95 --- /dev/null +++ b/java/com/google/domain/registry/tmch/icann-tmch.crl @@ -0,0 +1,13 @@ +-----BEGIN X509 CRL----- +MIIB8DCB2QIBATANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJVUzE8MDoGA1UE +ChMzSW50ZXJuZXQgQ29ycG9yYXRpb24gZm9yIEFzc2lnbmVkIE5hbWVzIGFuZCBO +dW1iZXJzMSkwJwYDVQQDEyBJQ0FOTiBUcmFkZW1hcmsgQ2xlYXJpbmdob3VzZSBD +QRcNMTMwNzI0MDAwMDAwWhcNMTUwNzIzMjM1OTU5WqAvMC0wHwYDVR0jBBgwFoAU +XMDxlizKTFsp8UB00xs2PkfUbgQwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQAD +ggEBAGmBog7fIBEvnDCV1Pkaiosibnxpp8d3E9NQRJRBlyLSNJKTB7mwcRlyVl/q +nAJrPZy6d01v58KpvrLLYRHkbsHC+qWom61Tu8ssVfGTrN6Re/CY8WtPQiiGjtDF +ZQBLgmjRGsUZ8r5L9DjBQNHEQmEMXYMiV7mId2+08GBHT1QDgUw74RXMqsD8BzeF +BqSyNJwxUzuCeU7xK4xRErnursXZo1fqgEc/zfqm9AjJx2frFmc/aXYvvw13z+ZP +PPsPAeMDUO/LBCGZJAf28LUKn5NmVcUXhYkxprjLuLu7eMveRn7LAiK6LDKL4SXL +AD6ouYPCx82fLnJ8o+2r6tHUHSk= +-----END X509 CRL----- diff --git a/java/com/google/domain/registry/tmch/icann-tmch.crt b/java/com/google/domain/registry/tmch/icann-tmch.crt new file mode 100644 index 000000000..0ece151ce --- /dev/null +++ b/java/com/google/domain/registry/tmch/icann-tmch.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEQjCCAyqgAwIBAgIhAJNCMqhNjz3cXVJPj7yvcZvro1FKQR+dTC6tXazem5g+ +MA0GCSqGSIb3DQEBCwUAMHYxCzAJBgNVBAYTAlVTMTwwOgYDVQQKEzNJbnRlcm5l +dCBDb3Jwb3JhdGlvbiBmb3IgQXNzaWduZWQgTmFtZXMgYW5kIE51bWJlcnMxKTAn +BgNVBAMTIElDQU5OIFRyYWRlbWFyayBDbGVhcmluZ2hvdXNlIENBMB4XDTEzMDcy +NDAwMDAwMFoXDTIzMDcyMzIzNTk1OVowdjELMAkGA1UEBhMCVVMxPDA6BgNVBAoT +M0ludGVybmV0IENvcnBvcmF0aW9uIGZvciBBc3NpZ25lZCBOYW1lcyBhbmQgTnVt +YmVyczEpMCcGA1UEAxMgSUNBTk4gVHJhZGVtYXJrIENsZWFyaW5naG91c2UgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5MX6qpRnqFzEXa9w3G0b8 +LTEVZzpOpcSq2BXJO16+iuZ964mpay2hm2BdZk89hSmZhUy2ePBR6PdS0GMmzzXL +NiyTHJlDIPxxXTR39Iqs8QChJ8wle4pYUu8JUk2vJ0r7PhFweeCCQZ5gvHdCwopS +bXeolj4NCqsvzU8iROsLRHSZbE83i2pkL+qBoyzjny9MO2rvMNPo5WrDNrno6hvC +hlf8Pv77HTNCazI2MeW0ArfLin4pSe6nLnDsQA11SF9bbgwDgVMQFvmB8nEvUbZW +Atnp3auaWqaylC+G0p3frFvMCUJMPrghiPwBABl3bk1GLjXXVl7D8SubKd2Xwv63 +AgMBAAGjgbowgbcwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUXMDxlizK +TFsp8UB00xs2PkfUbgQwDgYDVR0PAQH/BAQDAgEGMC4GA1UdHwQnMCUwI6AhoB+G +HWh0dHA6Ly9jcmwuaWNhbm4ub3JnL3RtY2guY3JsMEIGA1UdIAQ7MDkwBgYEVR0g +ADAvBggrBgEFBQcCATAjMCEGCCsGAQUFBwIBFhVodHRwczovL2NhLmljYW5uLm9y +Zy8wDQYJKoZIhvcNAQELBQADggEBAAM29FBdwQSAx8dD4ZYtCYjXxTonNCP2qveG +wrpMJcq/I3Jp/N4etsnj+K5ej5sSlDuo8sTMF7lgMkgjrc6zgJl0+Gct2RhbRNzN +5ittE9JwJZ3Us4vwiy6gqMO5Ie9YaKMZy2MYP2iFp6AhBKIc2Iz+8aFfnFzdSEx2 +b3xc+t1A09dzpnzU6zvHWUUkTYq9fTg1er1npni9ZErvp0jEyHVWi5GXvWap68XH +pVF6TBmPW2UBEEnFgd3SxbMXLhaD/wzV12tlSYjxaNed+H5qbVVbSVwN9yBeWU29 +/pkZu79TqFFxTd4CJTWOBq0+yLO1Ts2ZZ1l+GgU6e3hI1XERSNc= +-----END CERTIFICATE----- diff --git a/java/com/google/domain/registry/tmch/marksdb-public-key.asc b/java/com/google/domain/registry/tmch/marksdb-public-key.asc new file mode 100644 index 000000000..470442432 --- /dev/null +++ b/java/com/google/domain/registry/tmch/marksdb-public-key.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFHaxrYBCADHDPUdSYCs9wuBUhbGYfi39LKlDLhlmia7Tlv1rSJb8RPcU7DL +eXSU9zKRDpW31KQtHnjARinobjQNc6YXQOGtjDVr3LGTojGT1y+obVmgWytpHNnb +kSu1pktQRDPpYPBMBOD/MVpz8nZxgjYWyYTIkfTgkA/l1YKRyA30ieHVR8qKhJZY +D6u/dViQcdZCLsvs0XYYhPDjNi7M2wzVAdRjh9txnJgDymgqHF59onzkZauyFnc9 +EUEUURITzbfMifvGSZ/h+zdCUT/tSH3wSuVRxXqAh+cApT2c+gI88/TlGci2YOZV +POU24M7xuYPb9rIK4b9tR12ZQF+g/4n9eDprABEBAAG0LHN1cHBvcnQgYXQgbWFy +a3NkYi5vcmcgPHN1cHBvcnRAbWFya3NkYi5vcmc+iQE4BBMBAgAiBQJR2sa2AhsD +BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRC4xOmbTP03TGTCB/9J1xKyNkJe +wsSHhBga4MnBiS3gr3waZSfYaiWvx7br5FxI3Zv2jPAouqkpf8XbJgc4RvqZjFmi +5YSwpLgChSa5DkA6kPgReNCEfPvtBX7iRrZTv7RSSzZUuGiVED9s4Qk0+ppc8RgW +HRLYetvNvMIKL+6bvUlvztr+KM914JpzDEXgkBok2RxVq33FKUMIiy4vinbS2/7N +LpGlCMG7vgdBHIjBItUq9ipCtiDvvmPHiwHErgMgkx67pmDGxViMHDIMpzb8YTHw +lCxRwnLPILmm371hqOuVsu/pUVC16TEzYRDwZGbn4uKzWT0ZvYsPNcFGKC35ujEH +3fACoP6CMt/AuQENBFHaxrYBCADuDjCyxpDMakGSmk5zXIW/r0F9wqpIaPqm7xoR +15ajbvBUguM3gVH7bC4qihaSVFq2S8soWpyu88JyeWFiK+nMiIUALbfwXTA3DdIm +zmA/aKBNCeMyWXH1iy5zDCO0S343HH3/QWYTTy0aSUoMiW4AovKrnbZWti0WOoC4 +a8MUY1Ib1DhG/CJBzx4l52m5jOnmKB4foa7VmaWAjlG/s4ZDoEUPW8p6d2fmF05q +/ImGuzSwXegCuTY7rmkWskf4SshTYryyel76v1SteOFhXFaxcewbQgxIn1uGczd5 +P3/RBznF+Zm9OQK3840sqnhn1y/A3HadT7OI9Ot31TVXpRK5ABEBAAGJAR8EGAEC +AAkFAlHaxrYCGwwACgkQuMTpm0z9N0yzzwgApO1IzPwd5OwFymQNIizKOl3VTBTR +s5xtGBARg3fQsPmQen/SWZXu7VqJzr9QngQRJUT0nqdQPsGqOU72f8UkZGg6UD/o +mqfSfzLnOGnXLpC5g4bR+Z1PHlOV33r0HnWA8GPZsnYOXw414NYLmNW+tlC9t1F0 +WNBevhzXQujBfj0p+Znf3Gap8xvtZ9EAbeYUEpUQXEKh5UcBHBQCzmvDgukISK7w +wBpVWDwLHIYghE9OElat0y+ttD+RhSkUf+ufIw+L6BTHVD5E+W+BFoMFmNU3Kk/y +BoGsCR/i63T3egBVn1IzFezNy8YUVTtqOLyYlIe2R35zafxXs2anwvqA6Q== +=2ED8 +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/java/com/google/domain/registry/tmch/package-info.java b/java/com/google/domain/registry/tmch/package-info.java new file mode 100644 index 000000000..cd5830f82 --- /dev/null +++ b/java/com/google/domain/registry/tmch/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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. + +@javax.annotation.ParametersAreNonnullByDefault +package com.google.domain.registry.tmch; diff --git a/java/com/google/domain/registry/tools/AllocateDomainCommand.java b/java/com/google/domain/registry/tools/AllocateDomainCommand.java new file mode 100644 index 000000000..8d641ea76 --- /dev/null +++ b/java/com/google/domain/registry/tools/AllocateDomainCommand.java @@ -0,0 +1,187 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.io.BaseEncoding.base16; +import static com.google.domain.registry.flows.EppXmlTransformer.unmarshal; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.tools.CommandUtilities.addHeader; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.EppXmlTransformer; +import com.google.domain.registry.model.domain.DesignatedContact; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.model.domain.DomainCommand; +import com.google.domain.registry.model.domain.Period; +import com.google.domain.registry.model.domain.launch.ApplicationStatus; +import com.google.domain.registry.model.domain.launch.LaunchNotice; +import com.google.domain.registry.model.domain.secdns.DelegationSignerData; +import com.google.domain.registry.model.eppinput.EppInput; +import com.google.domain.registry.model.eppinput.EppInput.ResourceCommandWrapper; +import com.google.domain.registry.model.host.HostResource; +import com.google.domain.registry.model.reporting.HistoryEntry; +import com.google.domain.registry.model.smd.SignedMark; +import com.google.domain.registry.tools.soy.DomainAllocateSoyInfo; +import com.google.template.soy.data.SoyMapData; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.googlecode.objectify.Key; +import com.googlecode.objectify.VoidWork; +import com.googlecode.objectify.Work; + +import java.util.ArrayList; +import java.util.List; + +/** Command to allocated a domain from a domain application. */ +@Parameters(separators = " =", commandDescription = "Allocate a domain application") +final class AllocateDomainCommand extends MutatingEppToolCommand { + + @Parameter( + names = "--ids", + description = "Comma-delimited list of application IDs to update.", + required = true) + String ids; + + private final List> applicationKeys = new ArrayList<>(); + + @Override + protected String verify() throws Exception { + StringBuilder builder = new StringBuilder(); + // Check to see that we allocated everything. + return builder.append(ofy().transactNewReadOnly(new Work() { + @Override + public String run() { + String failureMessage = FluentIterable + .from(ofy().load().keys(applicationKeys).values()) + .transform(new Function() { + @Override + public String apply(DomainApplication application) { + return application.getApplicationStatus() == ApplicationStatus.ALLOCATED + ? null : application.getFullyQualifiedDomainName(); + }}) + .join(Joiner.on('\n').skipNulls()); + return failureMessage.isEmpty() ? "ALL SUCCEEDED" : addHeader("FAILURES", failureMessage); + }})).toString(); + } + + /** Extract the registration period from the XML used to create the domain application. */ + private static Period extractPeriodFromXml(byte[] xmlBytes) throws EppException { + EppInput eppInput = unmarshal(xmlBytes); + return ((DomainCommand.Create) + ((ResourceCommandWrapper) eppInput.getCommandWrapper().getCommand()) + .getResourceCommand()).getPeriod(); + } + + @Override + void initMutatingEppToolCommand() { + checkArgument(superuser, "This command MUST be run as --superuser."); + setSoyTemplate(DomainAllocateSoyInfo.getInstance(), DomainAllocateSoyInfo.CREATE); + ofy().transactNewReadOnly(new VoidWork() { + @Override + public void vrun() { + Iterable> keys = transform( + Splitter.on(',').split(ids), + new Function>() { + @Override + public Key apply(String applicationId) { + return Key.create(DomainApplication.class, applicationId); + }}); + for (DomainApplication application : ofy().load().keys(keys).values()) { + // If the application is already allocated print a warning but do not fail. + if (application.getApplicationStatus() == ApplicationStatus.ALLOCATED) { + System.err.printf( + "Application %s has already been allocated\n", application.getRepoId()); + continue; + } + // Ensure domain doesn't already have a final status which it shouldn't be updated from. + checkState( + !application.getApplicationStatus().isFinalStatus(), + "Application has final status %s", + application.getApplicationStatus()); + try { + HistoryEntry history = checkNotNull( + ofy().load() + .type(HistoryEntry.class) + .ancestor(checkNotNull(application)) + .order("modificationTime") + .first() + .now(), + "Could not find any history entries for domain application %s", + application.getRepoId()); + String clientTransactionId = + emptyToNull(history.getTrid().getClientTransactionId()); + Period period = checkNotNull(extractPeriodFromXml(history.getXmlBytes())); + checkArgument(period.getUnit() == Period.Unit.YEARS); + ImmutableMap.Builder contactsMapBuilder = new ImmutableMap.Builder<>(); + for (DesignatedContact contact : application.getContacts()) { + contactsMapBuilder.put( + contact.getType().toString().toLowerCase(), + contact.getContactId().getLinked().get().getForeignKey()); + } + LaunchNotice launchNotice = application.getLaunchNotice(); + addSoyRecord(application.getCurrentSponsorClientId(), new SoyMapData( + "name", application.getFullyQualifiedDomainName(), + "period", period.getValue(), + "nameservers", FluentIterable.from(application.loadNameservers()) + .transform(new Function() { + @Override + public String apply(HostResource host) { + return host.getForeignKey(); + }}) + .toList(), + "registrant", application.loadRegistrant().getForeignKey(), + "contacts", contactsMapBuilder.build(), + "authInfo", application.getAuthInfo().getPw().getValue(), + "smdId", application.getEncodedSignedMarks().isEmpty() + ? null : EppXmlTransformer.unmarshal( + application.getEncodedSignedMarks().get(0).getBytes()).getId(), + "applicationRoid", application.getRepoId(), + "applicationTime", application.getCreationTime().toString(), + "launchNotice", launchNotice == null ? null : ImmutableMap.of( + "noticeId", launchNotice.getNoticeId().getTcnId(), + "expirationTime", launchNotice.getExpirationTime().toString(), + "acceptedTime", launchNotice.getAcceptedTime().toString()), + "dsRecords", FluentIterable.from(application.getDsData()) + .transform(new Function>() { + @Override + public ImmutableMap apply(DelegationSignerData dsData) { + return ImmutableMap.of( + "keyTag", dsData.getKeyTag(), + "algorithm", dsData.getAlgorithm(), + "digestType", dsData.getDigestType(), + "digest", base16().encode(dsData.getDigest())); + }}) + .toList(), + "clTrid", clientTransactionId)); + applicationKeys.add(Key.create(application)); + } catch (EppException e) { + throw new RuntimeException(e); + } + } + } + }); + } +} diff --git a/java/com/google/domain/registry/tools/AppEngineConnection.java b/java/com/google/domain/registry/tools/AppEngineConnection.java new file mode 100644 index 000000000..32bf780bd --- /dev/null +++ b/java/com/google/domain/registry/tools/AppEngineConnection.java @@ -0,0 +1,179 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Suppliers.memoize; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.X_REQUESTED_WITH; +import static com.google.common.net.MediaType.JSON_UTF_8; +import static com.google.domain.registry.security.JsonHttp.JSON_SAFETY_PREFIX; +import static com.google.domain.registry.security.XsrfTokenManager.X_CSRF_TOKEN; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.io.CharStreams; +import com.google.common.net.HostAndPort; +import com.google.common.net.MediaType; +import com.google.domain.registry.config.RegistryEnvironment; +import com.google.domain.registry.security.XsrfTokenManager; +import com.google.domain.registry.tools.ServerSideCommand.Connection; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.time.Duration; +import org.json.simple.JSONValue; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** An http connection to the appengine server. */ +@Parameters(separators = " =") +class AppEngineConnection implements Connection { + + /** Pattern to heuristically extract title tag contents in HTML responses. */ + private static final Pattern HTML_TITLE_TAG_PATTERN = Pattern.compile("(.*?)"); + + + @Parameter( + names = "--server", + description = "HOST[:PORT] to which remote commands are sent.") + private HostAndPort server = RegistryEnvironment.get().config().getServer(); + + @Parameter( + names = "--remote_server_spec", + description = "Combined server spec for the backend to connect to for remote logging.") + private String remoteServerSpec = "gslb:apphosting-frontend:4"; + + @Parameter( + names = "--remote_connection_timeout", + description = "How long to wait for the remote logger server before giving up.") + private Duration remoteConnectionTimeout = Duration.standardSeconds(30); + + /** + * Memoized XSRF security token. + * + *

Computing this is expensive since it needs to load {@code ServerSecret} so do it once. + */ + private final Supplier xsrfToken = + memoize(new Supplier() { + @Override + public String get() { + return XsrfTokenManager.generateToken("admin", getUserId()); + }}); + + @Override + public void prefetchXsrfToken() throws IOException { + // Cause XSRF token to be fetched, and then stay resident in cache (since it's memoized). + xsrfToken.get(); + } + + /** Returns the contents of the title tag in the given HTML, or null if not found. */ + private static String extractHtmlTitle(String html) { + Matcher matcher = HTML_TITLE_TAG_PATTERN.matcher(html); + return (matcher.find() ? matcher.group(1) : null); + } + + @Override + public String send( + String endpoint, Map params, MediaType contentType, byte[] payload) + throws IOException { + HttpURLConnection connection = getHttpURLConnection( + new URL(String.format("http://%s%s?%s", getServer(), endpoint, encodeParams(params)))); + connection.setRequestMethod("POST"); + connection.setUseCaches(false); + connection.setRequestProperty(CONTENT_TYPE, contentType.toString()); + connection.setRequestProperty(X_CSRF_TOKEN, xsrfToken.get()); + connection.setRequestProperty(X_REQUESTED_WITH, "RegistryTool"); + connection.setDoOutput(true); + connection.connect(); + try (OutputStream output = connection.getOutputStream()) { + output.write(payload); + } + if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { + String errorTitle = extractHtmlTitle( + CharStreams.toString(new InputStreamReader(connection.getErrorStream(), UTF_8))); + throw new IOException(String.format( + "Error from %s: %d %s%s", + connection.getURL(), + connection.getResponseCode(), + connection.getResponseMessage(), + (errorTitle == null ? "" : ": " + errorTitle))); + } + return CharStreams.toString(new InputStreamReader(connection.getInputStream(), UTF_8)); + } + + private String encodeParams(Map params) { + return Joiner.on('&').join(Iterables.transform( + params.entrySet(), + new Function, String>() { + @Override + public String apply(Entry entry) { + try { + return entry.getKey() + + "=" + URLEncoder.encode(entry.getValue().toString(), UTF_8.name()); + } catch (Exception e) { // UnsupportedEncodingException + throw new RuntimeException(e); + } + }})); + } + + @Override + @SuppressWarnings("unchecked") + public Map sendJson(String endpoint, Map object) throws IOException { + String response = send( + endpoint, + ImmutableMap.of(), + JSON_UTF_8, + JSONValue.toJSONString(object).getBytes(UTF_8)); + return (Map) JSONValue.parse(response.substring(JSON_SAFETY_PREFIX.length())); + } + + private HttpURLConnection getHttpURLConnection(URL remoteUrl) throws IOException { + // TODO: Figure out authentication. + return (HttpURLConnection) remoteUrl.openConnection(); + } + + @Override + public String getServerUrl() { + return "https://" + getServer().toString().replaceFirst("\\.", "-dot-"); + } + + HostAndPort getServer() { + return server; + } + + boolean isLocalhost() { + return server.getHostText().equals("localhost"); + } + + private String getUserId() { + return isLocalhost() + ? UserIdProvider.getTestUserId() + : UserIdProvider.getProdUserId(); + } +} diff --git a/java/com/google/domain/registry/tools/AuctionStatusCommand.java b/java/com/google/domain/registry/tools/AuctionStatusCommand.java new file mode 100644 index 000000000..702e8fb16 --- /dev/null +++ b/java/com/google/domain/registry/tools/AuctionStatusCommand.java @@ -0,0 +1,121 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.domain.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; +import static com.google.domain.registry.model.registry.Registries.findTldForName; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Function; +import com.google.common.base.Strings; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.model.contact.ContactResource; +import com.google.domain.registry.model.domain.DomainApplication; +import com.google.domain.registry.tools.Command.GtechCommand; +import com.google.domain.registry.tools.Command.RemoteApiCommand; +import com.google.domain.registry.tools.params.PathParameter; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.googlecode.objectify.Work; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +/** Command to check the status of domain applications. */ +@Parameters(separators = " =", commandDescription = "Check auction status") +final class AuctionStatusCommand implements RemoteApiCommand, GtechCommand { + + @Parameter( + description = "Domains(s) to check", + required = true) + private List mainArguments; + + @Parameter( + names = {"-o", "--output"}, + description = "Output file.", + validateWith = PathParameter.OutputFile.class) + private Path output = Paths.get("/dev/stdout"); + + @Override + public void run() throws Exception { + final ImmutableSet domains = ImmutableSet.copyOf(mainArguments); + Files.write(output, FluentIterable + .from(domains) + .transformAndConcat(new Function>() { + @Override + public Iterable apply(String fullyQualifiedDomainName) { + checkState( + findTldForName(InternetDomainName.from(fullyQualifiedDomainName)).isPresent(), + "No tld found for %s", fullyQualifiedDomainName); + return ofy().transactNewReadOnly(new Work>() { + @Override + public Iterable run() { + ImmutableList.Builder applications = + new ImmutableList.Builder<>(); + for (String domain : domains) { + applications.addAll( + loadActiveApplicationsByDomainName(domain, ofy().getTransactionTime())); + } + return Lists.transform( + FluentIterable.from(applications.build()).toSortedList(ORDERING), + APPLICATION_FORMATTER); + }}); + }}), UTF_8); + } + + private static final Ordering ORDERING = new Ordering() { + @Override + public int compare(DomainApplication left, DomainApplication right) { + return ComparisonChain.start() + .compare(left.getFullyQualifiedDomainName(), right.getFullyQualifiedDomainName()) + .compareTrueFirst( + left.getEncodedSignedMarks().isEmpty(), right.getEncodedSignedMarks().isEmpty()) + .compare(left.getApplicationStatus(), right.getApplicationStatus()) + .compare(left.getCreationTime(), right.getCreationTime()) + .result(); + }}; + + private static final Function APPLICATION_FORMATTER = + new Function() { + @Override + public String apply(DomainApplication app) { + ContactResource registrant = checkNotNull(app.loadRegistrant()); + Object[] keysAndValues = new Object[] { + "Domain", app.getFullyQualifiedDomainName(), + "Type", app.getEncodedSignedMarks().isEmpty() ? "Landrush" : "Sunrise", + "Application Status", app.getApplicationStatus(), + "Application ID", app.getForeignKey(), + "Application Timestamp", app.getCreationTime(), + "Last Update", app.getLastEppUpdateTime(), + "Registrar Name", app.getCurrentSponsorClientId(), + "Registrant Email", registrant.getEmailAddress(), + "Registrant Phone", registrant.getVoiceNumber().getPhoneNumber() + }; + return String.format( + Strings.repeat("%-25s= %s\n", keysAndValues.length / 2), keysAndValues); + }}; +} diff --git a/java/com/google/domain/registry/tools/BUILD b/java/com/google/domain/registry/tools/BUILD new file mode 100644 index 000000000..220bfcec6 --- /dev/null +++ b/java/com/google/domain/registry/tools/BUILD @@ -0,0 +1,90 @@ +package( + default_visibility = ["//java/com/google/domain/registry:registry_project"], +) + + +# Restrict visibility to :tools because :remoteapi-internal (and transitively +# :appengine-api-link) should never be linked into an App Engine deploy jar, +# since the App Engine API is provided by the runtime environment. +package_group( + name = "allowed-tools", + packages = [ + "//java/com/google/domain/registry/testing", + "//java/com/google/domain/registry/tools", + "//javatests/com/google/domain/registry/tools", + ], +) + +java_library( + name = "tools", + srcs = glob([ + "*.java", + "javascrap/*.java", + ]), + resources = glob([ + "*.properties", + "sql/*.sql", + ]), + visibility = [":allowed-tools"], + deps = [ + "//apiserving/discoverydata/bigquery:bigqueryv2", + "//java/com/google/api/client/googleapis/auth/oauth2", + "//java/com/google/api/client/http", + "//java/com/google/api/client/http/javanet", + "//java/com/google/api/client/json", + "//java/com/google/api/client/json/jackson2", + "//java/com/google/common/annotations", + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//java/com/google/common/hash", + "//java/com/google/common/io", + "//java/com/google/common/net", + "//java/com/google/common/util/concurrent", + "//java/com/google/domain/registry/bigquery", + "//java/com/google/domain/registry/config", + "//java/com/google/domain/registry/export", + "//java/com/google/domain/registry/flows", + "//java/com/google/domain/registry/keyring/api", + "//java/com/google/domain/registry/model", + "//java/com/google/domain/registry/rde", + "//java/com/google/domain/registry/security", + "//java/com/google/domain/registry/request:modules", + "//java/com/google/domain/registry/tldconfig/idn", + "//java/com/google/domain/registry/tmch", + "//java/com/google/domain/registry/tools/params", + "//java/com/google/domain/registry/tools/server", + "//java/com/google/domain/registry/tools/soy:soy_java_wrappers", + "//java/com/google/domain/registry/util", + "//java/com/google/domain/registry/whois", + "//java/com/google/domain/registry/xjc", + "//java/com/google/domain/registry/xml", + "//third_party/java/appengine:appengine-api", + "//third_party/java/bouncycastle", + "//third_party/java/bouncycastle_bcpg", + "//third_party/java/dagger", + "//third_party/java/jcommander", + "//third_party/java/joda_money", + "//third_party/java/joda_time", + "//third_party/java/json", + "//third_party/java/json_simple", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + + "//third_party/java/appengine:appengine-remote-api", + + "//third_party/closure/templates", + ], +) + +java_binary( + name = "registry_tool", + create_executable = 1, + main_class = "com.google.domain.registry.tools.RegistryTool", + runtime_deps = [ + ":tools", + "//third_party/java/appengine:appengine-api-link", + "//third_party/java/appengine:appengine-remote-api-link", + ], +) + diff --git a/java/com/google/domain/registry/tools/BigqueryCommand.java b/java/com/google/domain/registry/tools/BigqueryCommand.java new file mode 100644 index 000000000..2782779ce --- /dev/null +++ b/java/com/google/domain/registry/tools/BigqueryCommand.java @@ -0,0 +1,46 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import com.google.domain.registry.bigquery.BigqueryConnection; + +import com.beust.jcommander.ParametersDelegate; + +/** A {@link Command} that uses the bigquery client API. */ +abstract class BigqueryCommand implements Command { + + /** Parameter delegate for encapsulating flags needed to set up the {@link BigqueryConnection}. */ + @ParametersDelegate + private BigqueryParameters bigqueryParameters = new BigqueryParameters(); + + /** Connection object for interacting with the Bigquery API. */ + private BigqueryConnection bigquery; + + @Override + public void run() throws Exception { + try (BigqueryConnection autoClosingBigquery = bigqueryParameters.newConnection()) { + bigquery = autoClosingBigquery; + runWithBigquery(); + } + } + + /** Returns the {@link BigqueryConnection} object that has been initialized for use. */ + BigqueryConnection bigquery() { + return bigquery; + } + + /** Subclasses must override this to define command behavior. */ + abstract void runWithBigquery() throws Exception; +} diff --git a/java/com/google/domain/registry/tools/BigqueryCommandUtilities.java b/java/com/google/domain/registry/tools/BigqueryCommandUtilities.java new file mode 100644 index 000000000..be66061b7 --- /dev/null +++ b/java/com/google/domain/registry/tools/BigqueryCommandUtilities.java @@ -0,0 +1,54 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.domain.registry.bigquery.BigqueryConnection.DestinationTable; + +import java.util.concurrent.ExecutionException; + +/** Container class for static utility methods for Bigquery commands. */ +final class BigqueryCommandUtilities { + + /** + * Handler that takes a DestinationTable future and waits on its completion, printing generic + * success/failure messages and wrapping any exception thrown in a TableCreationException. + */ + static void handleTableCreation( + String tableDescription, + ListenableFuture tableFuture) throws TableCreationException { + System.err.printf("Creating %s...\n", tableDescription); + try { + DestinationTable table = tableFuture.get(); + System.err.printf(" - Success: created %s.\n", table.getStringReference()); + } catch (Exception e) { + Throwable error = e; + if (e instanceof ExecutionException) { + error = e.getCause(); + } + String errorMessage = + String.format("Failed to create %s: %s", tableDescription, error.getMessage()); + System.err.printf(" - %s\n", errorMessage); + throw new TableCreationException(errorMessage, error); + } + } + + /** Exception thrown if any error occurs during a table creation stage. */ + static class TableCreationException extends Exception { + TableCreationException(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/java/com/google/domain/registry/tools/BigqueryParameters.java b/java/com/google/domain/registry/tools/BigqueryParameters.java new file mode 100644 index 000000000..c97acd84e --- /dev/null +++ b/java/com/google/domain/registry/tools/BigqueryParameters.java @@ -0,0 +1,103 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.bigquery.BigqueryScopes; +import com.google.domain.registry.bigquery.BigqueryConnection; +import com.google.domain.registry.tools.params.PathParameter; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.time.Duration; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.Executors; + +/** Parameter delegate class to handle flag settings for a command's BigqueryConnection object. */ +@Parameters(separators = " =") +final class BigqueryParameters { + + /** + * Default to 20 threads to stay within Bigquery's rate limit of 20 concurrent queries. + * + * @see "https://cloud.google.com/bigquery/quota-policy" + */ + private static final int DEFAULT_NUM_THREADS = 20; + + @Parameter( + names = "--bigquery_service_account", + description = "Email for the Google APIs service account to use.") + private String bigqueryServiceAccountEmail = + "1080941367941-ic4pknfqcj1q7hhc9ob0bls920v80unu@developer.gserviceaccount.com"; + + @Parameter( + names = "--bigquery_service_account_key", + description = "PKCS file (.p12) containing the private key for the service account.", + validateWith = PathParameter.InputFile.class) + private Path bigqueryServiceAccountKeyFile = Paths.get("key.p12"); + + @Parameter( + names = "--bigquery_dataset", + description = "Name of the default dataset to use, for reading and writing.") + private String bigqueryDataset = BigqueryConnection.DEFAULT_DATASET_NAME; + + @Parameter( + names = "--bigquery_overwrite", + description = "Whether to automatically overwrite existing tables and views.") + private boolean bigqueryOverwrite; + + @Parameter( + names = "--bigquery_poll_interval", + description = "Interval in milliseconds to wait between polls for job status.") + private Duration bigqueryPollInterval = Duration.standardSeconds(1); + + @Parameter( + names = "--bigquery_num_threads", + description = "Number of threads for running simultaneous BigQuery operations.") + private int bigqueryNumThreads = DEFAULT_NUM_THREADS; + + private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + + /** Returns a new BigqueryConnection constructed according to the delegate's flag settings. */ + BigqueryConnection newConnection() throws Exception { + BigqueryConnection connection = new BigqueryConnection.Builder() + .setExecutorService(Executors.newFixedThreadPool(bigqueryNumThreads)) + .setCredential(newCredential()) + .setDatasetId(bigqueryDataset) + .setOverwrite(bigqueryOverwrite) + .setPollInterval(bigqueryPollInterval) + .build(); + connection.initialize(); + return connection; + } + + /** Creates a credential object for the Bigquery client service using a service account. */ + private GoogleCredential newCredential() throws Exception { + return new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT) + .setJsonFactory(JSON_FACTORY) + .setServiceAccountId(bigqueryServiceAccountEmail) + .setServiceAccountScopes(BigqueryScopes.all()) + .setServiceAccountPrivateKeyFromP12File(bigqueryServiceAccountKeyFile.toFile()) + .build(); + } +} diff --git a/java/com/google/domain/registry/tools/CanonicalizeLabelsCommand.java b/java/com/google/domain/registry/tools/CanonicalizeLabelsCommand.java new file mode 100644 index 000000000..a9357f8a0 --- /dev/null +++ b/java/com/google/domain/registry/tools/CanonicalizeLabelsCommand.java @@ -0,0 +1,91 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Joiner; +import com.google.common.io.CharStreams; +import com.google.common.io.Files; +import com.google.domain.registry.tools.Command.GtechCommand; +import com.google.domain.registry.util.DomainNameUtils; +import com.google.domain.registry.util.Idn; +import com.google.domain.registry.util.NonFinalForTesting; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** Command to clean up a set of labels and turn them into punycode. */ +@Parameters(commandDescription = "Canonicalize domain labels") +final class CanonicalizeLabelsCommand implements Command, GtechCommand { + + @Parameter( + description = "Filename of file containing domain labels, one per line", + required = true) + private List mainParameters; + + @NonFinalForTesting + private static InputStream stdin = System.in; + + @Override + public void run() throws IOException { + Set labels = new TreeSet<>(); + for (String label : mainParameters.isEmpty() + ? CharStreams.readLines(new InputStreamReader(stdin)) + : Files.readLines(new File(mainParameters.get(0)), UTF_8)) { + label = label.trim(); + if (label.startsWith("-")) { + label = label.substring(1); + } + if (label.endsWith("-")) { + label = label.substring(0, label.length() - 1); + } + String canonical = canonicalize(label); + if (canonical.startsWith(DomainNameUtils.ACE_PREFIX) + && Idn.toUnicode(canonical).equals(canonical)) { + System.err.println("Bad IDN: " + label); + continue; // Bad IDN code points. + } + labels.add(canonical); + if (!canonical.startsWith("xn--")) { + // Using both "" and "-" to canonicalize labels. + labels.add(canonicalize(label.replaceAll(" ", ""))); + labels.add(canonicalize(label.replaceAll(" ", "-"))); + labels.add(canonicalize(label.replaceAll("_", ""))); + labels.add(canonicalize(label.replaceAll("_", "-"))); + } + } + labels.remove(""); // We used "" for invalid labels. + System.out.println(Joiner.on('\n').join(labels)); + } + + private String canonicalize(String rawLabel) { + try { + return canonicalizeDomainName(rawLabel.replaceAll(" ", "")); + } catch (Exception e) { + System.err.printf("Error canonicalizing %s: %s\n", rawLabel, e.getMessage()); + return ""; + } + } +} diff --git a/java/com/google/domain/registry/tools/CheckSnapshotCommand.java b/java/com/google/domain/registry/tools/CheckSnapshotCommand.java new file mode 100644 index 000000000..1796f1946 --- /dev/null +++ b/java/com/google/domain/registry/tools/CheckSnapshotCommand.java @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import com.google.common.collect.Iterables; +import com.google.domain.registry.export.DatastoreBackupInfo; +import com.google.domain.registry.export.DatastoreBackupService; +import com.google.domain.registry.tools.Command.RemoteApiCommand; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +/** + * Command to check the status of a datastore backup, or "snapshot". + */ +@Parameters(separators = " =", commandDescription = "Check the status of a datastore snapshot") +public class CheckSnapshotCommand implements RemoteApiCommand { + + @Parameter( + names = {"-s", "--snapshot"}, + description = "Unique prefix of the snapshot to check", + required = true) + private String snapshotName; + + @Override + public void run() throws Exception { + Iterable backups = + DatastoreBackupService.get().findAllByNamePrefix(snapshotName); + if (Iterables.isEmpty(backups)) { + System.err.println("No snapshot found with name: " + snapshotName); + return; + } + for (DatastoreBackupInfo backup : backups) { + System.out.println(backup.getInformation()); + } + } +} diff --git a/java/com/google/domain/registry/tools/Command.java b/java/com/google/domain/registry/tools/Command.java new file mode 100644 index 000000000..139efb93d --- /dev/null +++ b/java/com/google/domain/registry/tools/Command.java @@ -0,0 +1,35 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +/** Interface of all commands. */ +public interface Command { + + /** Performs the command. */ + void run() throws Exception; + + /** + * Marker interface for commands that use the remote api. + *

+ * Just implementing this is sufficient to use the remote api; {@link RegistryTool} will install + * it as needed. + */ + public interface RemoteApiCommand extends Command {} + + /** + * Marker interface for commands that are gTech safe. + */ + public interface GtechCommand extends Command {} +} diff --git a/java/com/google/domain/registry/tools/CommandUtilities.java b/java/com/google/domain/registry/tools/CommandUtilities.java new file mode 100644 index 000000000..9c887992c --- /dev/null +++ b/java/com/google/domain/registry/tools/CommandUtilities.java @@ -0,0 +1,68 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.domain.registry.flows.EppXmlTransformer.marshalWithLenientRetry; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Strings; +import com.google.domain.registry.flows.EppException; +import com.google.domain.registry.flows.FlowRunner; +import com.google.domain.registry.flows.FlowRunner.CommitMode; +import com.google.domain.registry.flows.FlowRunner.UserPrivileges; + +/** Container class for static utility methods. */ +class CommandUtilities { + + static String addHeader(String header, String body) { + return String.format("%s:\n%s\n%s", header, Strings.repeat("-", header.length() + 1), body); + } + + /** Prompts for yes/no input using promptText, defaulting to no. */ + static boolean promptForYes(String promptText) { + return promptForYesOrNo(promptText, false); + } + + /** + * Prompts for yes/no input using promptText and returns true for yes and false for no, using + * defaultResponse as the response for empty input. + */ + static boolean promptForYesOrNo(String promptText, boolean defaultResponse) { + String options = defaultResponse ? "Y/n" : "y/N"; + while (true) { + String line = System.console().readLine(String.format("%s (%s): ", promptText, options)); + if (line.isEmpty()) { + return defaultResponse; + } else if ("Y".equalsIgnoreCase(line.substring(0, 1))) { + return true; + } else if ("N".equalsIgnoreCase(line.substring(0, 1))) { + return false; + } + } + } + + /** Prints the provided text with a trailing newline, if text is not null or empty. */ + static void printLineIfNotEmpty(String text) { + if (!Strings.isNullOrEmpty(text)) { + System.out.println(text); + } + } + + static String runFlow( + FlowRunner flowRunner, CommitMode commitMode, UserPrivileges userPrivileges) + throws EppException { + return new String(marshalWithLenientRetry(flowRunner.run(commitMode, userPrivileges)), UTF_8); + } +} diff --git a/java/com/google/domain/registry/tools/ConfirmingCommand.java b/java/com/google/domain/registry/tools/ConfirmingCommand.java new file mode 100644 index 000000000..26f7350e3 --- /dev/null +++ b/java/com/google/domain/registry/tools/ConfirmingCommand.java @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.domain.registry.tools.CommandUtilities.printLineIfNotEmpty; +import static com.google.domain.registry.tools.CommandUtilities.promptForYes; + +import com.beust.jcommander.Parameter; + +/** A {@link Command} that implements a confirmation step before executing. */ +public abstract class ConfirmingCommand implements Command { + + @Parameter( + names = {"-f", "--force"}, + description = "Do not prompt before executing") + boolean force; + + @Override + public final void run() throws Exception { + if (checkExecutionState()) { + init(); + printLineIfNotEmpty(prompt()); + if (force || promptForYes("Perform this command?")) { + System.out.println(execute()); + printLineIfNotEmpty(verify()); + } else { + System.out.println("Command aborted."); + } + } + } + + /** Run any pre-execute command checks and return true if they all pass. */ + protected boolean checkExecutionState() throws Exception { + return true; + } + + /** Initializes the command. */ + protected void init() throws Exception {} + + /** Returns the optional extra confirmation prompt for the command. */ + protected String prompt() throws Exception { + return ""; + } + + /** Perform the command and return a result description. */ + protected abstract String execute() throws Exception; + + /** Verify result and/or perform any post-execution steps, and return optional description. */ + protected String verify() throws Exception { + return ""; + } +} diff --git a/java/com/google/domain/registry/tools/ConvertIdnCommand.java b/java/com/google/domain/registry/tools/ConvertIdnCommand.java new file mode 100644 index 000000000..cf88dcb9b --- /dev/null +++ b/java/com/google/domain/registry/tools/ConvertIdnCommand.java @@ -0,0 +1,48 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.domain.registry.util.DomainNameUtils.ACE_PREFIX; +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; + +import com.google.domain.registry.tools.Command.GtechCommand; +import com.google.domain.registry.util.Idn; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import java.io.IOException; +import java.util.List; + +/** Command to convert IDN labels to/from punycode. */ +@Parameters(commandDescription = "Convert IDNs to/from punycode") +final class ConvertIdnCommand implements Command, GtechCommand { + + @Parameter( + description = "Labels to convert", + required = true) + private List mainParameters; + + @Override + public void run() throws IOException { + for (String label : mainParameters) { + if (label.startsWith(ACE_PREFIX)) { + System.out.println(Idn.toUnicode(label.toLowerCase())); + } else { + System.out.println(canonicalizeDomainName(label)); + } + } + } +} diff --git a/java/com/google/domain/registry/tools/CreateAnchorTenantCommand.java b/java/com/google/domain/registry/tools/CreateAnchorTenantCommand.java new file mode 100644 index 000000000..49b9374ac --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateAnchorTenantCommand.java @@ -0,0 +1,102 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.model.registry.Registries.findTldForNameOrThrow; + +import com.google.common.net.InternetDomainName; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.tools.Command.GtechCommand; +import com.google.domain.registry.tools.soy.CreateAnchorTenantSoyInfo; +import com.google.template.soy.data.SoyMapData; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.money.Money; + +import javax.inject.Inject; + +/** A command to create a new anchor tenant domain. */ +@Parameters(separators = " =", commandDescription = "Provision a domain for an anchor tenant.") +final class CreateAnchorTenantCommand extends MutatingEppToolCommand implements GtechCommand { + + private static final int PASSWORD_LENGTH = 16; + private static final int DEFAULT_ANCHOR_TENANT_PERIOD_YEARS = 2; + + @Parameter( + names = {"-c", "--client"}, + description = "Client identifier of the registrar to execute the command as", + required = true) + String clientIdentifier; + + @Parameter( + names = {"-n", "--domain_name"}, + description = "Domain to create.", + required = true) + private String domainName; + + @Parameter( + names = {"--contact"}, + description = "Contact ID for the request. This will be used for registrant, admin contact," + + "and tech contact.", + required = true) + private String contact; + + @Parameter( + names = {"--reason"}, + description = "Reason for the change.") + private String reason; + + @Parameter( + names = {"--password"}, + description = "Password. Optional, randomly generated if not provided.") + private String password; + + @Parameter( + names = {"--fee"}, + description = "Include fee extension in EPP (required for premium domains).") + private boolean fee; + + @Inject + PasswordGenerator passwordGenerator; + + @Override + void initMutatingEppToolCommand() { + checkArgument(superuser, "This command must be run as a superuser."); + String tld = findTldForNameOrThrow(InternetDomainName.from(domainName)).toString(); + if (isNullOrEmpty(password)) { + password = passwordGenerator.createPassword(PASSWORD_LENGTH); + } + + Money cost = null; + if (fee) { + cost = Registry.get(tld).getDomainCreateCost(domainName, DEFAULT_ANCHOR_TENANT_PERIOD_YEARS); + } + + setSoyTemplate(CreateAnchorTenantSoyInfo.getInstance(), + CreateAnchorTenantSoyInfo.CREATEANCHORTENANT); + addSoyRecord(clientIdentifier, new SoyMapData( + "domainName", domainName, + "contactId", contact, + "reason", reason, + "password", password, + "period", DEFAULT_ANCHOR_TENANT_PERIOD_YEARS, + "feeCurrency", cost != null ? cost.getCurrencyUnit().toString() : null, + "fee", cost != null ? cost.getAmount().toString() : null)); + } +} diff --git a/java/com/google/domain/registry/tools/CreateAuctionCreditsCommand.java b/java/com/google/domain/registry/tools/CreateAuctionCreditsCommand.java new file mode 100644 index 000000000..5a1e589ad --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateAuctionCreditsCommand.java @@ -0,0 +1,215 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.CaseFormat.UPPER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.model.registry.Registries.assertTldExists; +import static java.util.Arrays.asList; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Iterables; +import com.google.domain.registry.model.billing.RegistrarCredit; +import com.google.domain.registry.model.billing.RegistrarCredit.CreditType; +import com.google.domain.registry.model.billing.RegistrarCreditBalance; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registry.Registry; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.money.BigMoney; +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Command for creating new auction credits based on a CSV file from Pool. + *

+ * The CSV file from the auction provider uses double-quotes around every field, so in order to + * extract the raw field value we strip off the quotes after splitting each line by commas. We are + * using a simple parsing strategy that does not support embedded quotation marks, commas, or + * newlines. + *

+ * TODO(b/16009815): Switch this file to using a real CSV parser. + *

+ * Example file format: + *

+ * "Affiliate","DomainName","Email","BidderId","BidderStatus","UpdatedAt",
+ *      "SalePrice","Commissions","CurrencyCode"
+ * "reg1","foo.xn--q9jyb4c","email1@example.com","???_300","INACTIVE","4/3/2014 7:13:09 PM",
+ *      "1000.0000","0.0000","JPY"
+ * "reg2","foo.xn--q9jyb4c","email2@example.net","???_64","WIN","4/3/2014 7:13:09 PM",
+ *      "1000.0000","40.0000","JPY"
+ * 
+ * We only care about three fields: 1) the "Affiliate" field which corresponds to the registrar + * clientId stored in datastore, and which we use to determine which registrar gets the credit, + * 2) the "Commissions" field which contains the amount of the auction credit (as determined by + * logic on the auction provider's side, see the Finance Requirements Doc for more information), and + * 3) the "CurrencyCode" field, which we validate matches the TLD-wide currency for this TLD. + */ +@Parameters(separators = " =", commandDescription = "Create new auction credits based on CSV") +final class CreateAuctionCreditsCommand extends MutatingCommand { + + @Parameter( + names = "--input_file", + description = "CSV file for the Pool.com commissions report", + required = true) + private Path inputFile; + + @Parameter( + names = {"-t", "--tld"}, + description = "The TLD corresponding to this commissions report", + required = true) + private String tld; + + @Parameter( + names = "--effective_time", + description = "The time at which these auction credits should become effective", + required = true) + private DateTime effectiveTime; + + /** Enum containing the headers we expect in the Pool.com CSV file, in order. */ + private enum CsvHeader { + AFFILIATE, + DOMAIN_NAME, + EMAIL, + BIDDER_ID, + BIDDER_STATUS, + UPDATED_AT, + SALE_PRICE, + COMMISSIONS, + CURRENCY_CODE; + + public static List getHeaders() { + return FluentIterable.from(asList(values())) + .transform(new Function() { + @Override + public String apply(CsvHeader header) { + // Returns the name of the header as it appears in the CSV file. + return UPPER_UNDERSCORE.to(UPPER_CAMEL, header.name()); + }}) + .toList(); + } + } + + private static final Pattern QUOTED_STRING = Pattern.compile("\"(.*)\""); + + /** Helper function to unwrap a quoted string, failing if the string is not quoted. */ + private static final Function UNQUOTER = new Function() { + @Override + public String apply(String input) { + Matcher matcher = QUOTED_STRING.matcher(input); + checkArgument(matcher.matches(), "Input not quoted"); + return matcher.group(1); + }}; + + /** Returns the input string of quoted CSV values split into the list of unquoted values. */ + private static List splitCsvLine(String line) { + return FluentIterable.from(Splitter.on(',').split(line)).transform(UNQUOTER).toList(); + } + + @Override + protected void init() throws Exception { + assertTldExists(tld); + ImmutableMultimap creditMap = parseCreditsFromCsv(inputFile, tld); + stageCreditCreations(creditMap); + } + + /** + * Parses the provided CSV file of data from the auction provider and returns a multimap mapping + * each registrar to the collection of auction credit amounts from this TLD's auctions that should + * be awarded to this registrar, and validating that every credit amount's currency is in the + * specified TLD-wide currency. + */ + private static ImmutableMultimap parseCreditsFromCsv( + Path csvFile, String tld) throws IOException { + List lines = Files.readAllLines(csvFile, StandardCharsets.UTF_8); + checkArgument(CsvHeader.getHeaders().equals(splitCsvLine(lines.get(0))), + "Expected CSV header line not present"); + ImmutableMultimap.Builder builder = new ImmutableMultimap.Builder<>(); + for (String line : Iterables.skip(lines, 1)) { + List fields = splitCsvLine(line); + checkArgument(CsvHeader.getHeaders().size() == fields.size(), "Wrong number of fields"); + try { + String registrarId = fields.get(CsvHeader.AFFILIATE.ordinal()); + Registrar registrar = checkNotNull( + Registrar.loadByClientId(registrarId), "Registrar %s not found", registrarId); + CurrencyUnit tldCurrency = Registry.get(tld).getCurrency(); + CurrencyUnit currency = CurrencyUnit.of((fields.get(CsvHeader.CURRENCY_CODE.ordinal()))); + checkArgument(tldCurrency.equals(currency), + "Credit in wrong currency (%s should be %s)", currency, tldCurrency); + // We use BigDecimal and BigMoney to preserve fractional currency units when computing the + // total amount of each credit (since auction credits are percentages of winning bids). + BigDecimal creditAmount = new BigDecimal(fields.get(CsvHeader.COMMISSIONS.ordinal())); + BigMoney credit = BigMoney.of(currency, creditAmount); + builder.put(registrar, credit); + } catch (IllegalArgumentException | IndexOutOfBoundsException e) { + throw new IllegalArgumentException("Error in line: " + line, e); + } + } + return builder.build(); + } + + /** + * Stages the creation of RegistrarCredit and RegistrarCreditBalance instances for each + * registrar in the provided multimap of credit amounts by registrar. The balance instance + * created is the total of all the credit amounts for a given registrar. + */ + private void stageCreditCreations(ImmutableMultimap creditMap) { + DateTime now = DateTime.now(UTC); + CurrencyUnit currency = Registry.get(tld).getCurrency(); + for (Registrar registrar : creditMap.keySet()) { + // Use RoundingMode.UP to be nice and give registrars the extra fractional units. + Money totalAmount = + BigMoney.total(currency, creditMap.get(registrar)).toMoney(RoundingMode.UP); + System.out.printf("Total auction credit balance for %s: %s\n", + registrar.getClientIdentifier(), totalAmount); + + // Create the actual credit and initial credit balance. + RegistrarCredit credit = new RegistrarCredit.Builder() + .setParent(registrar) + .setType(CreditType.AUCTION) + .setCreationTime(now) + .setCurrency(currency) + .setTld(tld) + .build(); + RegistrarCreditBalance creditBalance = new RegistrarCreditBalance.Builder() + .setParent(credit) + .setEffectiveTime(effectiveTime) + .setWrittenTime(now) + .setAmount(totalAmount) + .build(); + stageEntityChange(null, credit); + stageEntityChange(null, creditBalance); + } + } +} diff --git a/java/com/google/domain/registry/tools/CreateContactCommand.java b/java/com/google/domain/registry/tools/CreateContactCommand.java new file mode 100644 index 000000000..f3863a630 --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateContactCommand.java @@ -0,0 +1,137 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.google.domain.registry.tools.Command.GtechCommand; +import com.google.domain.registry.tools.params.PhoneNumberParameter; +import com.google.domain.registry.tools.soy.CreateContactSoyInfo; +import com.google.template.soy.data.SoyMapData; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import java.util.List; + +import javax.inject.Inject; + +/** A command to create a new contact via EPP. */ +@Parameters(separators = " =", commandDescription = "Create a new contact via EPP.") +final class CreateContactCommand extends MutatingEppToolCommand implements GtechCommand { + // TODO(b/19016175): Expand to allow full suite of contact flows. + @Parameter( + names = {"-c", "--client"}, + description = "Client identifier of the registrar to execute the command as", + required = true) + String clientIdentifier; + + @Parameter( + names = {"--id"}, + description = "Contact ID.") + private String id; + + @Parameter( + names = {"--name"}, + description = "Contact name.") + private String name; + + @Parameter( + names = {"--org"}, + description = "Organization") + private String org; + + @Parameter( + names = {"--street"}, + description = "Street lines of address. Can take up to 3 lines.", + variableArity = true) + private List street; + + @Parameter( + names = {"--city"}, + description = "City of address.") + private String city; + + @Parameter( + names = {"--state"}, + description = "State of address.") + private String state; + + @Parameter( + names = {"--zip"}, + description = "Postal code of address.") + private String zip; + + @Parameter( + names = {"--cc"}, + description = "Country code of address.") + private String cc; + + @Parameter( + names = "--phone", + description = "E.164 phone number, e.g. +1.2125650666", + converter = PhoneNumberParameter.class, + validateWith = PhoneNumberParameter.class) + String phone; + + @Parameter( + names = "--fax", + description = "E.164 fax number, e.g. +1.2125650666", + converter = PhoneNumberParameter.class, + validateWith = PhoneNumberParameter.class) + String fax; + + @Parameter( + names = {"--email"}, + description = "Email address.") + private String email; + + @Parameter( + names = {"--password"}, + description = "Password. Optional, randomly generated if not provided.") + private String password; + + @Inject + PasswordGenerator passwordGenerator; + + private static final int PASSWORD_LENGTH = 16; + + @Override + void initMutatingEppToolCommand() { + if (isNullOrEmpty(password)) { + password = passwordGenerator.createPassword(PASSWORD_LENGTH); + } + + checkArgument(street == null || street.size() <= 3, + "Addresses must contain at most 3 street lines."); + + setSoyTemplate(CreateContactSoyInfo.getInstance(), + CreateContactSoyInfo.CREATECONTACT); + addSoyRecord(clientIdentifier, new SoyMapData( + "id", id, + "name", name, + "org", org, + "street", street, + "city", city, + "state", state, + "zip", zip, + "cc", cc, + "phone", phone, + "fax", fax, + "email", email, + "password", password)); + } +} diff --git a/java/com/google/domain/registry/tools/CreateCreditBalanceCommand.java b/java/com/google/domain/registry/tools/CreateCreditBalanceCommand.java new file mode 100644 index 000000000..a47053ec2 --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateCreditBalanceCommand.java @@ -0,0 +1,77 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.domain.registry.model.ofy.ObjectifyService.ofy; + +import com.google.domain.registry.model.billing.RegistrarCredit; +import com.google.domain.registry.model.billing.RegistrarCreditBalance; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.util.SystemClock; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +/** Command for creating a new balance for a registrar credit. */ +@Parameters(separators = " =", commandDescription = "Create a new registrar credit balance") +final class CreateCreditBalanceCommand extends MutatingCommand { + + @Parameter( + names = "--registrar", + description = "Client ID of the registrar owning the credit to create a new balance for", + required = true) + private String registrarId; + + @Parameter( + names = "--credit_id", + description = "ID of credit to create a new balance for", + required = true) + private long creditId; + + @Parameter( + names = "--balance", + description = "The new balance amount", + required = true) + private Money balance; + + @Parameter( + names = "--effective_time", + description = "Point in time at which the new balance amount becomes effective", + required = true) + private DateTime effectiveTime; + + @Override + public void init() throws Exception { + Registrar registrar = checkNotNull( + Registrar.loadByClientId(registrarId), "Registrar %s not found", registrarId); + RegistrarCredit credit = ofy().load() + .type(RegistrarCredit.class) + .parent(registrar) + .id(creditId) + .now(); + checkNotNull(credit, "Registrar credit for %s with ID %s not found", registrarId, creditId); + RegistrarCreditBalance newBalance = new RegistrarCreditBalance.Builder() + .setParent(credit) + .setEffectiveTime(effectiveTime) + .setWrittenTime(new SystemClock().nowUtc()) + .setAmount(balance) + .build(); + stageEntityChange(null, newBalance); + } +} diff --git a/java/com/google/domain/registry/tools/CreateCreditCommand.java b/java/com/google/domain/registry/tools/CreateCreditCommand.java new file mode 100644 index 000000000..67689c435 --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateCreditCommand.java @@ -0,0 +1,95 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.domain.registry.model.billing.RegistrarCredit; +import com.google.domain.registry.model.billing.RegistrarCredit.CreditType; +import com.google.domain.registry.model.billing.RegistrarCreditBalance; +import com.google.domain.registry.model.registrar.Registrar; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import org.joda.money.Money; +import org.joda.time.DateTime; + +import javax.annotation.Nullable; + +/** Command for creating a registrar credit object with an initial balance. */ +@Parameters(separators = " =", commandDescription = "Create a new registrar credit") +final class CreateCreditCommand extends MutatingCommand { + + @Parameter( + names = "--registrar", + description = "Client ID of the registrar who will be awarded this credit", + required = true) + private String registrarId; + + @Parameter( + names = "--type", + description = "Type of credit (AUCTION or PROMOTION)", + required = true) + private CreditType type; + + @Nullable + @Parameter( + names = "--description", + description = "Custom description that will appear on invoice line for this credit") + private String description; + + @Parameter( + names = "--tld", + description = "TLD for which this credit applies", + required = true) + private String tld; + + @Parameter( + names = "--balance", + description = "Initial balance of this credit", + required = true) + private Money balance; + + @Parameter( + names = "--effective_time", + description = "Point in time at which the initial balance becomes effective", + required = true) + private DateTime effectiveTime; + + @Override + protected void init() throws Exception { + DateTime now = DateTime.now(UTC); + Registrar registrar = checkNotNull( + Registrar.loadByClientId(registrarId), "Registrar %s not found", registrarId); + RegistrarCredit credit = new RegistrarCredit.Builder() + .setParent(registrar) + .setType(type) + .setCreationTime(now) + .setCurrency(balance.getCurrencyUnit()) + .setDescription(description) + .setTld(tld) + .build(); + RegistrarCreditBalance creditBalance = new RegistrarCreditBalance.Builder() + .setParent(credit) + .setEffectiveTime(effectiveTime) + .setWrittenTime(now) + .setAmount(balance) + .build(); + stageEntityChange(null, credit); + stageEntityChange(null, creditBalance); + } +} diff --git a/java/com/google/domain/registry/tools/CreateOrUpdatePremiumListCommand.java b/java/com/google/domain/registry/tools/CreateOrUpdatePremiumListCommand.java new file mode 100644 index 000000000..5df147e45 --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateOrUpdatePremiumListCommand.java @@ -0,0 +1,137 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.security.JsonHttp.JSON_SAFETY_PREFIX; +import static com.google.domain.registry.tools.server.CreateOrUpdatePremiumListAction.INPUT_PARAM; +import static com.google.domain.registry.tools.server.CreateOrUpdatePremiumListAction.NAME_PARAM; +import static com.google.domain.registry.util.ListNamingUtils.convertFilePathToName; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableMap; +import com.google.common.net.MediaType; +import com.google.domain.registry.model.registry.label.PremiumList; +import com.google.domain.registry.tools.params.PathParameter; + +import com.beust.jcommander.Parameter; + +import org.json.simple.JSONValue; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Base class for specification of command line parameters common to creating and updating premium + * lists. + */ +abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand + implements ServerSideCommand { + + @Nullable + @Parameter( + names = {"-n", "--name"}, + description = "The name of this premium list (defaults to filename if not specified). " + + "This is almost always the name of the TLD this premium list will be used on.") + String name; + + @Parameter( + names = {"-i", "--input"}, + description = "Filename of premium list to create or update.", + validateWith = PathParameter.InputFile.class, + required = true) + Path inputFile; + + protected Connection connection; + protected int inputLineCount; + + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } + + abstract String getCommandPath(); + + ImmutableMap getParameterMap() { + return ImmutableMap.of(); + } + + @Override + protected void init() throws Exception { + List lines = Files.readAllLines(inputFile, UTF_8); + new PremiumList.Builder() + .setName(name) + .setPremiumListMapFromLines(lines) + .build(); + inputLineCount = lines.size(); + } + + @Override + protected String prompt() throws Exception { + return String.format( + "You are about to save the premium list %s with %d items: ", name, inputLineCount); + } + + @Override + public String execute() throws Exception { + name = isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name; + ImmutableMap.Builder params = new ImmutableMap.Builder<>(); + params.put(NAME_PARAM, name); + params.put(INPUT_PARAM, new String(Files.readAllBytes(inputFile), UTF_8)); + + ImmutableMap extraParams = getParameterMap(); + if (extraParams != null) { + params.putAll(extraParams); + } + + // Call the server and get the response data + String response = connection.send( + getCommandPath(), + params.build(), + MediaType.PLAIN_TEXT_UTF_8, + new byte[0]); + + return extractServerResponse(response); + } + + // TODO(tjb): refactor this behavior into a better general-purpose + // response validation that can be re-used across the new client/server commands. + String extractServerResponse(String response) { + Map responseMap = toMap(JSONValue.parse(stripJsonPrefix(response))); + + // TODO(tjb): consider using jart's FormField Framework. + // See: j/c/g/d/r/ui/server/RegistrarFormFields.java + String status = (String) responseMap.get("status"); + Verify.verify(!status.equals("error"), "Server error: %s", responseMap.get("error")); + return String.format("Successfully saved premium list %s\n", name); + } + + @SuppressWarnings("unchecked") + static Map toMap(Object obj) { + Verify.verify(obj instanceof Map, "JSON object is not a Map: %s", obj); + return (Map) obj; + } + + // TODO(tjb): figure out better place to put this method to make it re-usable + static String stripJsonPrefix(String json) { + Verify.verify(json.startsWith(JSON_SAFETY_PREFIX)); + return json.substring(JSON_SAFETY_PREFIX.length()); + } +} diff --git a/java/com/google/domain/registry/tools/CreateOrUpdateRegistrarCommand.java b/java/com/google/domain/registry/tools/CreateOrUpdateRegistrarCommand.java new file mode 100644 index 000000000..a127c8b3b --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateOrUpdateRegistrarCommand.java @@ -0,0 +1,398 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.isNull; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; +import static com.google.domain.registry.util.RegistrarUtils.normalizeRegistrarName; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.joda.time.DateTimeZone.UTC; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.domain.registry.model.billing.RegistrarBillingUtils; +import com.google.domain.registry.model.registrar.Registrar; +import com.google.domain.registry.model.registrar.Registrar.BillingMethod; +import com.google.domain.registry.model.registrar.RegistrarAddress; +import com.google.domain.registry.tools.params.OptionalLongParameter; +import com.google.domain.registry.tools.params.OptionalPhoneNumberParameter; +import com.google.domain.registry.tools.params.OptionalStringParameter; +import com.google.domain.registry.tools.params.PathParameter; +import com.google.domain.registry.util.CidrAddressBlock; + +import com.beust.jcommander.Parameter; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +/** Shared base class for commands to create or update a {@link Registrar}. */ +abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand { + + @Parameter( + description = "Client identifier of the registrar account", + required = true) + List mainParameters; + + @Parameter( + names = "--registrar_type", + description = "Type of the registrar") + Registrar.Type registrarType; + + @Nullable + @Parameter( + names = "--registrar_state", + description = "Initial state of the registrar") + Registrar.State registrarState; + + @Parameter( + names = "--allowed_tlds", + description = "Comma-delimited list of TLDs which the registrar is allowed to use") + List allowedTlds = new ArrayList<>(); + + @Parameter( + names = "--add_allowed_tlds", + description = "Comma-delimited list of TLDs to add to TLDs a registrar is allowed to use") + List addAllowedTlds = new ArrayList<>(); + + @Nullable + @Parameter( + names = "--password", + description = "Password for the registrar account") + String password; + + @Nullable + @Parameter( + names = "--name", + description = "Name of the registrar") + String registrarName; + + @Nullable + @Parameter( + names = "--email", + description = "Email address of registrar", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + Optional email; + + @Nullable + @Parameter( + names = "--icann_referral_email", + description = "ICANN referral email, as specified in registrar contract") + String icannReferralEmail; + + @Nullable + @Parameter( + names = "--url", + description = "URL of registrar's website", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + private Optional url; + + @Nullable + @Parameter( + names = "--phone", + description = "E.164 phone number, e.g. +1.2125650666", + converter = OptionalPhoneNumberParameter.class, + validateWith = OptionalPhoneNumberParameter.class) + Optional phone; + + @Nullable + @Parameter( + names = "--fax", + description = "E.164 fax number, e.g. +1.2125650666", + converter = OptionalPhoneNumberParameter.class, + validateWith = OptionalPhoneNumberParameter.class) + Optional fax; + + @Nullable + @Parameter( + names = "--cert_file", + description = "File containing client certificate (X.509 PEM)", + validateWith = PathParameter.InputFile.class) + Path clientCertificateFilename; + + @Nullable + @Parameter( + names = "--cert_hash", + description = "Hash of client certificate (SHA256 base64 no padding). Do not use this unless " + + "you want to store ONLY the hash and not the full certificate") + private String clientCertificateHash; + + @Nullable + @Parameter( + names = "--failover_cert_file", + description = "File containing failover client certificate (X.509 PEM)", + validateWith = PathParameter.InputFile.class) + Path failoverClientCertificateFilename; + + @Parameter( + names = "--ip_whitelist", + description = "Comma-delimited list of IP ranges") + List ipWhitelist = new ArrayList<>(); + + @Nullable + @Parameter( + names = "--iana_id", + description = "Registrar IANA ID", + converter = OptionalLongParameter.class, + validateWith = OptionalLongParameter.class) + Optional ianaId; + + @Nullable + @Parameter( + names = "--billing_id", + description = "Registrar Billing ID (i.e. Oracle #)", + converter = OptionalLongParameter.class, + validateWith = OptionalLongParameter.class) + private Optional billingId; + + @Nullable + @Parameter( + names = "--billing_method", + description = "Method by which registry bills this registrar customer") + private BillingMethod billingMethod; + + @Nullable + @Parameter( + names = "--street", + variableArity = true, + description = "Street lines of address. Can take up to 3 lines.") + List street; + + @Nullable + @Parameter( + names = "--city", + description = "City of address") + String city; + + @Nullable + @Parameter( + names = "--state", + description = "State/Province of address. The value \"null\" clears this field.") + String state; + + @Nullable + @Parameter( + names = "--zip", + description = "Postal code of address. The value \"null\" clears this field.") + String zip; + + @Nullable + @Parameter( + names = "--cc", + description = "Country code of address") + String countryCode; + + @Nullable + @Parameter( + names = "--block_premium", + description = "Whether premium name registration should be blocked on this registrar", + arity = 1) + private Boolean blockPremiumNames; + + @Nullable + @Parameter( + names = "--drive_id", + description = "Id of this registrar's folder in Drive", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + Optional driveFolderId; + + @Nullable + @Parameter( + names = "--passcode", + description = "Telephone support passcode") + String phonePasscode; + + @Nullable + @Parameter( + names = "--whois", + description = "Hostname of registrar WHOIS server. (Default: whois.nic.google)") + String whoisServer; + + /** Returns the existing registrar (for update) or null (for creates). */ + @Nullable + abstract Registrar getOldRegistrar(String clientIdentifier); + + protected void initRegistrarCommand() throws Exception {} + + @Override + protected final void init() throws Exception { + initRegistrarCommand(); + DateTime now = DateTime.now(UTC); + for (String clientIdentifier : mainParameters) { + Registrar oldRegistrar = getOldRegistrar(clientIdentifier); + Registrar.Builder builder = (oldRegistrar == null) + ? new Registrar.Builder().setClientIdentifier(clientIdentifier) + : oldRegistrar.asBuilder(); + + if (!isNullOrEmpty(password)) { + builder.setPassword(password); + } + if (!isNullOrEmpty(registrarName)) { + builder.setRegistrarName(registrarName); + } + if (email != null) { + builder.setEmailAddress(email.orNull()); + } + if (url != null) { + builder.setUrl(url.orNull()); + } + if (phone != null) { + builder.setPhoneNumber(phone.orNull()); + } + if (fax != null) { + builder.setFaxNumber(fax.orNull()); + } + if (registrarType != null) { + builder.setType(registrarType); + } + if (registrarState != null) { + builder.setState(registrarState); + } + if (driveFolderId != null) { + builder.setDriveFolderId(driveFolderId.orNull()); + } + if (!allowedTlds.isEmpty()) { + checkArgument(addAllowedTlds.isEmpty(), + "Can't specify both --allowedTlds and --addAllowedTlds"); + ImmutableSet.Builder allowedTldsBuilder = new ImmutableSet.Builder<>(); + for (String allowedTld : allowedTlds) { + allowedTldsBuilder.add(canonicalizeDomainName(allowedTld)); + } + builder.setAllowedTlds(allowedTldsBuilder.build()); + } + if (!addAllowedTlds.isEmpty()) { + ImmutableSet.Builder allowedTldsBuilder = new ImmutableSet.Builder<>(); + if (oldRegistrar != null) { + allowedTldsBuilder.addAll(oldRegistrar.getAllowedTlds()); + } + for (String allowedTld : addAllowedTlds) { + allowedTldsBuilder.add(canonicalizeDomainName(allowedTld)); + } + builder.setAllowedTlds(allowedTldsBuilder.build()); + } + if (!ipWhitelist.isEmpty()) { + ImmutableList.Builder ipWhitelistBuilder = new ImmutableList.Builder<>(); + if (!(ipWhitelist.size() == 1 && ipWhitelist.get(0).contains("null"))) { + for (String ipRange : ipWhitelist) { + ipWhitelistBuilder.add(CidrAddressBlock.create(ipRange)); + } + } + builder.setIpAddressWhitelist(ipWhitelistBuilder.build()); + } + if (clientCertificateFilename != null) { + String asciiCert = new String(Files.readAllBytes(clientCertificateFilename), US_ASCII); + builder.setClientCertificate(asciiCert, now); + } + if (failoverClientCertificateFilename != null) { + String asciiCert = + new String(Files.readAllBytes(failoverClientCertificateFilename), US_ASCII); + builder.setFailoverClientCertificate(asciiCert, now); + } + if (!isNullOrEmpty(clientCertificateHash)) { + checkArgument(clientCertificateFilename == null, + "Can't specify both --cert_hash and --cert_file"); + if ("null".equals(clientCertificateHash)) { + clientCertificateHash = null; + } + builder.setClientCertificateHash(clientCertificateHash); + } + if (ianaId != null) { + builder.setIanaIdentifier(ianaId.orNull()); + } + if (billingId != null) { + builder.setBillingIdentifier(billingId.orNull()); + } + if (billingMethod != null) { + if (oldRegistrar != null && !billingMethod.equals(oldRegistrar.getBillingMethod())) { + Map balances = RegistrarBillingUtils.loadBalance(oldRegistrar); + for (Money balance : balances.values()) { + checkState(balance.isZero(), + "Refusing to change billing method on Registrar '%s' from %s to %s" + + " because current balance is non-zero: %s", + clientIdentifier, oldRegistrar.getBillingMethod(), billingMethod, balances); + } + } + builder.setBillingMethod(billingMethod); + } + List streetAddressFields = Arrays.asList(street, city, state, zip, countryCode); + checkArgument(Iterables.any(streetAddressFields, isNull()) + == Iterables.all(streetAddressFields, isNull()), + "Must specify all fields of address"); + if (street != null) { + // We always set the localized address for now. That should be safe to do since it supports + // unrestricted UTF-8. + builder.setLocalizedAddress(new RegistrarAddress.Builder() + .setStreet(ImmutableList.copyOf(street)) + .setCity(city) + .setState("null".equals(state) ? null : state) + .setZip("null".equals(zip) ? null : zip) + .setCountryCode(countryCode) + .build()); + } + if (blockPremiumNames != null) { + builder.setBlockPremiumNames(blockPremiumNames); + } + // When creating a new REAL registrar or changing the type to REAL, a passcode is required. + // Leave existing REAL registrars alone. + if (Registrar.Type.REAL.equals(registrarType) + && (oldRegistrar == null || oldRegistrar.getPhonePasscode() == null)) { + checkArgument(phonePasscode != null, "--passcode is required for REAL registrars."); + } + if (phonePasscode != null) { + builder.setPhonePasscode(phonePasscode); + } + if (icannReferralEmail != null) { + builder.setIcannReferralEmail(icannReferralEmail); + } + if (whoisServer != null) { + builder.setWhoisServer(whoisServer); + } + + // If the registrarName is being set, verify that it is either null or it normalizes uniquely. + String oldRegistrarName = (oldRegistrar == null) ? null : oldRegistrar.getRegistrarName(); + if (registrarName != null && !registrarName.equals(oldRegistrarName)) { + String normalizedName = normalizeRegistrarName(registrarName); + for (Registrar registrar : Registrar.loadAll()) { + if (registrar.getRegistrarName() != null) { + checkArgument( + !normalizedName.equals(normalizeRegistrarName(registrar.getRegistrarName())), + "The registrar name %s normalizes identically to existing registrar name %s", + registrarName, + registrar.getRegistrarName()); + } + } + } + + stageEntityChange(oldRegistrar, builder.build()); + } + } +} diff --git a/java/com/google/domain/registry/tools/CreateOrUpdateReservedListCommand.java b/java/com/google/domain/registry/tools/CreateOrUpdateReservedListCommand.java new file mode 100644 index 000000000..54cbec86a --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateOrUpdateReservedListCommand.java @@ -0,0 +1,51 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import com.google.domain.registry.tools.params.PathParameter; + +import com.beust.jcommander.Parameter; + +import java.nio.file.Path; + +import javax.annotation.Nullable; + +/** + * Base class for specification of command line parameters common to creating and updating reserved + * lists. + */ +public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand { + + @Nullable + @Parameter( + names = {"-n", "--name"}, + description = "The name of this reserved list (defaults to filename if not specified).") + String name; + + @Parameter( + names = {"-i", "--input"}, + description = "Filename of new reserved list.", + validateWith = PathParameter.InputFile.class, + required = true) + Path input; + + @Nullable + @Parameter( + names = "--should_publish", + description = + "Whether the list is published to the concatenated list on Drive (defaults to true).", + arity = 1) + Boolean shouldPublish; +} diff --git a/java/com/google/domain/registry/tools/CreateOrUpdateTldCommand.java b/java/com/google/domain/registry/tools/CreateOrUpdateTldCommand.java new file mode 100644 index 000000000..83880f82f --- /dev/null +++ b/java/com/google/domain/registry/tools/CreateOrUpdateTldCommand.java @@ -0,0 +1,408 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// 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.google.domain.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.domain.registry.model.RoidSuffixes.isRoidSuffixUsed; +import static com.google.domain.registry.util.CollectionUtils.findDuplicates; +import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; +import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Sets; +import com.google.domain.registry.model.registry.Registries; +import com.google.domain.registry.model.registry.Registry; +import com.google.domain.registry.model.registry.Registry.TldState; +import com.google.domain.registry.model.registry.Registry.TldType; +import com.google.domain.registry.model.registry.label.PremiumList; +import com.google.domain.registry.model.registry.label.ReservedList; +import com.google.domain.registry.tools.params.OptionalStringParameter; +import com.google.domain.registry.tools.params.TransitionListParameter.BillingCostTransitions; +import com.google.domain.registry.tools.params.TransitionListParameter.TldStateTransitions; + +import com.beust.jcommander.Parameter; +import com.googlecode.objectify.Key; + +import org.joda.money.Money; +import org.joda.time.DateTime; +import org.joda.time.Duration; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.Nullable; + +/** Shared base class for commands to create or update a TLD. */ +abstract class CreateOrUpdateTldCommand extends MutatingCommand { + + @Parameter( + description = "Names of the TLDs", + required = true) + List mainParameters; + + @Parameter( + names = "--escrow", + description = "Whether to enable nightly RDE escrow deposits", + arity = 1) + private Boolean escrow; + + @Parameter( + names = "--dns", + description = "Set to false to pause writing to the DNS queue", + arity = 1) + private Boolean dns; + + @Nullable + @Parameter( + names = "--add_grace_period", + description = "Length of the add grace period") + Duration addGracePeriod; + + @Nullable + @Parameter( + names = "--redemption_grace_period", + description = "Length of the redemption grace period") + Duration redemptionGracePeriod; + + @Nullable + @Parameter( + names = "--pending_delete_length", + description = "Length of the pending delete period") + Duration pendingDeleteLength; + + @Nullable + @Parameter( + names = "--automatic_transfer_length", + description = "Length of the automatic transfer period") + private Duration automaticTransferLength; + + @Nullable + @Parameter( + names = "--restore_billing_cost", + description = "One-time billing cost for restoring a domain") + private Money restoreBillingCost; + + @Nullable + @Parameter( + names = "--roid_suffix", + description = "The suffix to be used for ROIDs, e.g. COM for .com domains (which then " + + "creates roids looking like 123ABC-COM)") + String roidSuffix; + + @Nullable + @Parameter( + names = "--server_status_change_cost", + description = "One-time billing cost for a server status change") + private Money serverStatusChangeCost; + + @Nullable + @Parameter( + names = "--tld_type", + description = "Tld type (REAL or TEST)") + private TldType tldType; + + @Nullable + @Parameter( + names = "--premium_price_ack_required", + description = "Whether operations on premium domains require explicit ack of prices", + arity = 1) + private Boolean premiumPriceAckRequired; + + @Nullable + @Parameter( + names = "--create_billing_cost", + description = "Per-year billing cost for creating a domain") + Money createBillingCost; + + @Nullable + @Parameter( + names = "--drive_folder_id", + description = "Id of the folder in drive used to publish information for this TLD", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + Optional driveFolderId; + + @Nullable + @Parameter( + names = "--lordn_username", + description = "Username for LORDN uploads", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + Optional lordnUsername; + + @Nullable + @Parameter( + names = "--premium_list", + description = "The name of the premium list to apply to the TLD", + converter = OptionalStringParameter.class, + validateWith = OptionalStringParameter.class) + Optional premiumListName; + + @Parameter( + names = "--tld_state_transitions", + converter = TldStateTransitions.class, + validateWith = TldStateTransitions.class, + description = "Comma-delimited list of TLD state transitions, of the form " + + "