From e1cfd6234e392fd8305dd6056b8d05a16f3ce2a6 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Fri, 6 Jul 2018 02:29:51 -0400 Subject: [PATCH] Rewrite for Material Design and KeyStore This commit contains a long-awaited rewrite to address many long-standing issues. This patch contains: 1. a totally new UI focused on Material Design compliance 2. all tokens are stored in the Android KeyStore 3. support for sending codes over Bluetooth LE to computers via Jelling 4. extensive unit testing 5. expanded branding options (cf. image= and color=) 6. default branding for major issuers (needs docs) 7. sane behavior surrounding the addition of multiple tokens 8. warnings on weak cryptographic parameters 9. token locking (authentication required to get token code) All this goodness comes with some costs: 1. Android API 23+ is required. This is necessary for KeyStore access. 2. Manual token adding is gone. Use QR code or otpauth:// link. 3. Use of the KeyStore makes token secrets impossible to extract. 4. Tokens are immutable. Existing changes will be discarded on upgrade. Closes: #190 Closes: #96 Closes: #78 Closes: #77 Closes: #68 Closes: #55 Closes: #48 Closes: #45 Closes: #43 Closes: #16 Fixes: #187 Fixes: #185 Fixes: #176 Fixes: #175 Fixes: #172 Fixes: #170 Fixes: #167 Fixes: #161 Fixes: #144 Fixes: #142 Fixes: #136 Fixes: #123 Fixes: #122 Fixes: #110 Fixes: #90 Fixes: #89 Fixes: #84 Fixes: #74 Fixes: #69 Fixes: #67 Fixes: #66 Fixes: #65 Fixes: #63 Fixes: #62 Fixes: #61 Fixes: #58 Fixes: #54 Fixes: #53 Fixes: #49 Fixes: #40 Fixes: #21 Fixes: #14 Fixes: #8 Fixes: #7 Fixes: #6 --- .travis.yml | 4 +- COPYING.icons | 10 - app/build.gradle | 36 -- app/src/main/ic_freeotp_logo-web.png | Bin 46837 -> 0 bytes .../apps/authenticator/Base32String.java | 161 ----- .../fedorahosted/freeotp/AboutActivity.java | 70 --- .../freeotp/BaseReorderableAdapter.java | 113 ---- .../fedorahosted/freeotp/MainActivity.java | 191 ------ .../fedorahosted/freeotp/ProgressCircle.java | 129 ---- .../java/org/fedorahosted/freeotp/Token.java | 346 ----------- .../fedorahosted/freeotp/TokenAdapter.java | 146 ----- .../org/fedorahosted/freeotp/TokenCode.java | 85 --- .../org/fedorahosted/freeotp/TokenLayout.java | 180 ------ .../freeotp/TokenPersistence.java | 227 ------- .../freeotp/add/ScanActivity.java | 162 ----- .../freeotp/add/ScanFrameProcessor.java | 71 --- .../freeotp/edit/BaseActivity.java | 24 - .../freeotp/edit/DeleteActivity.java | 44 -- .../freeotp/edit/EditActivity.java | 176 ------ app/src/main/res/anim/fadein.xml | 8 - app/src/main/res/anim/fadeout.xml | 8 - app/src/main/res/anim/token_image_fadein.xml | 8 - app/src/main/res/anim/token_image_fadeout.xml | 8 - app/src/main/res/color/menu.xml | 27 - .../main/res/drawable-hdpi/ic_action_edit.png | Bin 884 -> 0 bytes .../main/res/drawable-hdpi/ic_launcher.png | Bin 4799 -> 0 bytes app/src/main/res/drawable-hdpi/qrcode.png | Bin 316 -> 0 bytes .../main/res/drawable-ldpi/ic_launcher.png | Bin 2514 -> 0 bytes .../main/res/drawable-mdpi/ic_action_edit.png | Bin 587 -> 0 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 3136 -> 0 bytes app/src/main/res/drawable-mdpi/qrcode.png | Bin 350 -> 0 bytes .../res/drawable-xhdpi/ic_action_edit.png | Bin 1179 -> 0 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 9839 -> 0 bytes app/src/main/res/drawable-xhdpi/qrcode.png | Bin 429 -> 0 bytes .../res/drawable-xxhdpi/ic_action_edit.png | Bin 1670 -> 0 bytes app/src/main/res/drawable-xxhdpi/logo.png | Bin 27060 -> 0 bytes app/src/main/res/drawable-xxhdpi/qrcode.png | Bin 495 -> 0 bytes app/src/main/res/drawable/ic_freeotp.xml | 102 ---- .../drawable/ic_freeotp_logo_background.xml | 74 --- app/src/main/res/drawable/menu.xml | 41 -- app/src/main/res/drawable/scan.xml | 10 - app/src/main/res/layout/about.xml | 63 -- app/src/main/res/layout/delete.xml | 56 -- app/src/main/res/layout/edit.xml | 56 -- app/src/main/res/layout/main.xml | 51 -- app/src/main/res/layout/metadata.xml | 35 -- app/src/main/res/layout/titles.xml | 28 - app/src/main/res/layout/token.xml | 90 --- .../res/mipmap-anydpi-v26/ic_freeotp_logo.xml | 5 - .../ic_freeotp_logo_round.xml | 5 - .../main/res/mipmap-hdpi/ic_freeotp_logo.png | Bin 3655 -> 0 bytes .../ic_freeotp_logo_foreground.png | Bin 10847 -> 0 bytes .../res/mipmap-hdpi/ic_freeotp_logo_round.png | Bin 4923 -> 0 bytes .../main/res/mipmap-mdpi/ic_freeotp_logo.png | Bin 2399 -> 0 bytes .../ic_freeotp_logo_foreground.png | Bin 6302 -> 0 bytes .../res/mipmap-mdpi/ic_freeotp_logo_round.png | Bin 2868 -> 0 bytes .../main/res/mipmap-xhdpi/ic_freeotp_logo.png | Bin 5473 -> 0 bytes .../ic_freeotp_logo_foreground.png | Bin 16045 -> 0 bytes .../mipmap-xhdpi/ic_freeotp_logo_round.png | Bin 7253 -> 0 bytes .../res/mipmap-xxhdpi/ic_freeotp_logo.png | Bin 8873 -> 0 bytes .../ic_freeotp_logo_foreground.png | Bin 28296 -> 0 bytes .../mipmap-xxhdpi/ic_freeotp_logo_round.png | Bin 12001 -> 0 bytes .../res/mipmap-xxxhdpi/ic_freeotp_logo.png | Bin 12738 -> 0 bytes .../ic_freeotp_logo_foreground.png | Bin 43060 -> 0 bytes .../mipmap-xxxhdpi/ic_freeotp_logo_round.png | Bin 17690 -> 0 bytes app/src/main/res/values-hu/strings.xml | 43 -- app/src/main/res/values-v11/styles.xml | 11 - app/src/main/res/values-v14/styles.xml | 12 - app/src/main/res/values/strings.xml | 43 -- app/src/main/res/values/styles.xml | 43 -- .../fedorahosted/freeotp/TokenCodeTest.java | 52 -- .../freeotp/TokenPersistenceTest.java | 211 ------- .../org/fedorahosted/freeotp/TokenTest.java | 232 ------- .../fedorahosted/freeotp/TokenTestUtils.java | 46 -- build.gradle | 11 +- gradle.properties | 13 + gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 5 - gradlew | 78 +-- gradlew.bat | 14 +- ic_launcher-web.png | Bin 44704 -> 0 bytes mobile/build.gradle | 52 ++ mobile/proguard-rules.pro | 21 + .../org/fedorahosted/freeotp/Context.java | 567 ++++++++++++++++++ .../freeotp/MemorySharedPreferences.java | 197 ++++++ .../freeotp/TokenAdapterTest.java | 181 ++++++ .../fedorahosted/freeotp/TokenCompatTest.java | 307 ++++++++++ .../freeotp/TokenRFC4226Test.java | 40 ++ .../freeotp/TokenRFC6238Test.java | 76 +++ .../freeotp/TokenUriInvalidTest.java | 91 +++ {app => mobile}/src/main/AndroidManifest.xml | 70 +-- .../java/org/fedorahosted/freeotp/Code.java | 113 ++++ .../java/org/fedorahosted/freeotp/Token.java | 375 ++++++++++++ .../fedorahosted/freeotp/main/Activity.java | 407 +++++++++++++ .../fedorahosted/freeotp/main/Adapter.java | 253 ++++++++ .../freeotp/main/ScanDialogFragment.java | 240 ++++++++ .../fedorahosted/freeotp/main/ViewHolder.java | 304 ++++++++++ .../freeotp/main/share/Adapter.java | 165 +++++ .../freeotp/main/share/Clipboard.java | 53 ++ .../freeotp/main/share/Discoverable.java | 113 ++++ .../freeotp/main/share/Jelling.java | 349 +++++++++++ .../freeotp/main/share/ShareFragment.java | 146 +++++ .../freeotp/main/share/SortableItem.java | 56 ++ .../main/share/SortableItemAdapter.java | 69 +++ .../fedorahosted/freeotp/utils/Base32.java | 94 +++ .../utils/GridLayoutItemDecoration.java | 54 ++ .../freeotp/utils/SelectableAdapter.java | 142 +++++ .../freeotp/utils/SquareFrameLayout.java | 10 +- .../org/fedorahosted/freeotp/utils/Time.java | 29 + .../src/main/res/drawable/button.xml | 15 +- mobile/src/main/res/drawable/fa_500px.xml | 11 + .../main/res/drawable/fa_accessible_icon.xml | 11 + mobile/src/main/res/drawable/fa_accusoft.xml | 11 + mobile/src/main/res/drawable/fa_adn.xml | 11 + mobile/src/main/res/drawable/fa_adversal.xml | 11 + .../main/res/drawable/fa_affiliatetheme.xml | 11 + mobile/src/main/res/drawable/fa_algolia.xml | 11 + mobile/src/main/res/drawable/fa_amazon.xml | 11 + .../src/main/res/drawable/fa_amazon_pay.xml | 11 + mobile/src/main/res/drawable/fa_amilia.xml | 11 + mobile/src/main/res/drawable/fa_android.xml | 11 + mobile/src/main/res/drawable/fa_angellist.xml | 11 + .../main/res/drawable/fa_angrycreative.xml | 11 + mobile/src/main/res/drawable/fa_angular.xml | 11 + mobile/src/main/res/drawable/fa_app_store.xml | 11 + .../main/res/drawable/fa_app_store_ios.xml | 11 + mobile/src/main/res/drawable/fa_apper.xml | 11 + mobile/src/main/res/drawable/fa_apple.xml | 11 + mobile/src/main/res/drawable/fa_apple_pay.xml | 11 + .../src/main/res/drawable/fa_asymmetrik.xml | 11 + mobile/src/main/res/drawable/fa_audible.xml | 11 + .../src/main/res/drawable/fa_autoprefixer.xml | 11 + mobile/src/main/res/drawable/fa_avianex.xml | 11 + mobile/src/main/res/drawable/fa_aws.xml | 11 + mobile/src/main/res/drawable/fa_bandcamp.xml | 11 + mobile/src/main/res/drawable/fa_behance.xml | 11 + mobile/src/main/res/drawable/fa_bimobject.xml | 11 + mobile/src/main/res/drawable/fa_bitbucket.xml | 11 + mobile/src/main/res/drawable/fa_bitcoin.xml | 11 + mobile/src/main/res/drawable/fa_bity.xml | 11 + mobile/src/main/res/drawable/fa_black_tie.xml | 11 + .../src/main/res/drawable/fa_blackberry.xml | 11 + mobile/src/main/res/drawable/fa_blogger.xml | 11 + mobile/src/main/res/drawable/fa_blogger_b.xml | 11 + mobile/src/main/res/drawable/fa_bluetooth.xml | 11 + .../src/main/res/drawable/fa_bluetooth_b.xml | 11 + mobile/src/main/res/drawable/fa_btc.xml | 11 + .../main/res/drawable/fa_buromobelexperte.xml | 11 + .../src/main/res/drawable/fa_buysellads.xml | 11 + .../src/main/res/drawable/fa_centercode.xml | 11 + mobile/src/main/res/drawable/fa_chrome.xml | 11 + .../src/main/res/drawable/fa_cloudscale.xml | 11 + .../src/main/res/drawable/fa_cloudsmith.xml | 11 + .../src/main/res/drawable/fa_cloudversify.xml | 11 + mobile/src/main/res/drawable/fa_codepen.xml | 11 + mobile/src/main/res/drawable/fa_codiepie.xml | 11 + .../main/res/drawable/fa_connectdevelop.xml | 11 + mobile/src/main/res/drawable/fa_contao.xml | 11 + mobile/src/main/res/drawable/fa_cpanel.xml | 11 + mobile/src/main/res/drawable/fa_css3.xml | 11 + .../src/main/res/drawable/fa_cuttlefish.xml | 11 + mobile/src/main/res/drawable/fa_d_and_d.xml | 11 + mobile/src/main/res/drawable/fa_dashcube.xml | 11 + mobile/src/main/res/drawable/fa_delicious.xml | 11 + mobile/src/main/res/drawable/fa_deploydog.xml | 11 + mobile/src/main/res/drawable/fa_deskpro.xml | 11 + .../src/main/res/drawable/fa_deviantart.xml | 11 + mobile/src/main/res/drawable/fa_digg.xml | 11 + .../main/res/drawable/fa_digital_ocean.xml | 11 + mobile/src/main/res/drawable/fa_discord.xml | 11 + mobile/src/main/res/drawable/fa_discourse.xml | 11 + mobile/src/main/res/drawable/fa_dochub.xml | 11 + mobile/src/main/res/drawable/fa_docker.xml | 11 + .../main/res/drawable/fa_draft2digital.xml | 11 + mobile/src/main/res/drawable/fa_dribbble.xml | 11 + mobile/src/main/res/drawable/fa_dropbox.xml | 11 + mobile/src/main/res/drawable/fa_drupal.xml | 11 + mobile/src/main/res/drawable/fa_dyalog.xml | 11 + .../src/main/res/drawable/fa_earlybirds.xml | 11 + mobile/src/main/res/drawable/fa_ebay.xml | 11 + mobile/src/main/res/drawable/fa_edge.xml | 11 + mobile/src/main/res/drawable/fa_elementor.xml | 11 + mobile/src/main/res/drawable/fa_ember.xml | 11 + mobile/src/main/res/drawable/fa_empire.xml | 11 + mobile/src/main/res/drawable/fa_envira.xml | 11 + mobile/src/main/res/drawable/fa_erlang.xml | 11 + mobile/src/main/res/drawable/fa_ethereum.xml | 11 + mobile/src/main/res/drawable/fa_etsy.xml | 11 + .../src/main/res/drawable/fa_expeditedssl.xml | 11 + mobile/src/main/res/drawable/fa_facebook.xml | 11 + .../src/main/res/drawable/fa_facebook_f.xml | 11 + .../res/drawable/fa_facebook_messenger.xml | 11 + mobile/src/main/res/drawable/fa_firefox.xml | 11 + .../src/main/res/drawable/fa_firstdraft.xml | 11 + mobile/src/main/res/drawable/fa_flickr.xml | 11 + mobile/src/main/res/drawable/fa_flipboard.xml | 11 + mobile/src/main/res/drawable/fa_fly.xml | 11 + .../src/main/res/drawable/fa_font_awesome.xml | 11 + .../res/drawable/fa_font_awesome_flag.xml | 11 + .../drawable/fa_font_awesome_logo_full.xml | 11 + mobile/src/main/res/drawable/fa_fonticons.xml | 11 + .../src/main/res/drawable/fa_fonticons_fi.xml | 11 + .../src/main/res/drawable/fa_fort_awesome.xml | 11 + mobile/src/main/res/drawable/fa_forumbee.xml | 11 + .../src/main/res/drawable/fa_foursquare.xml | 11 + .../main/res/drawable/fa_free_code_camp.xml | 11 + mobile/src/main/res/drawable/fa_freebsd.xml | 11 + mobile/src/main/res/drawable/fa_fulcrum.xml | 11 + .../src/main/res/drawable/fa_get_pocket.xml | 11 + mobile/src/main/res/drawable/fa_gg.xml | 11 + mobile/src/main/res/drawable/fa_git.xml | 11 + mobile/src/main/res/drawable/fa_github.xml | 11 + mobile/src/main/res/drawable/fa_gitkraken.xml | 11 + mobile/src/main/res/drawable/fa_gitlab.xml | 11 + mobile/src/main/res/drawable/fa_gitter.xml | 11 + mobile/src/main/res/drawable/fa_glide.xml | 11 + mobile/src/main/res/drawable/fa_glide_g.xml | 11 + mobile/src/main/res/drawable/fa_gofore.xml | 11 + mobile/src/main/res/drawable/fa_goodreads.xml | 11 + .../src/main/res/drawable/fa_goodreads_g.xml | 11 + mobile/src/main/res/drawable/fa_google.xml | 11 + .../src/main/res/drawable/fa_google_drive.xml | 11 + .../src/main/res/drawable/fa_google_play.xml | 11 + .../src/main/res/drawable/fa_google_plus.xml | 11 + .../main/res/drawable/fa_google_plus_g.xml | 11 + .../main/res/drawable/fa_google_wallet.xml | 11 + mobile/src/main/res/drawable/fa_gratipay.xml | 11 + mobile/src/main/res/drawable/fa_grav.xml | 11 + mobile/src/main/res/drawable/fa_gripfire.xml | 11 + mobile/src/main/res/drawable/fa_grunt.xml | 11 + mobile/src/main/res/drawable/fa_gulp.xml | 11 + .../src/main/res/drawable/fa_hacker_news.xml | 11 + mobile/src/main/res/drawable/fa_hips.xml | 11 + .../main/res/drawable/fa_hire_a_helper.xml | 11 + mobile/src/main/res/drawable/fa_hornbill.xml | 11 + mobile/src/main/res/drawable/fa_hotjar.xml | 11 + mobile/src/main/res/drawable/fa_houzz.xml | 11 + mobile/src/main/res/drawable/fa_html5.xml | 11 + mobile/src/main/res/drawable/fa_hubspot.xml | 11 + mobile/src/main/res/drawable/fa_imdb.xml | 11 + mobile/src/main/res/drawable/fa_instagram.xml | 11 + .../res/drawable/fa_internet_explorer.xml | 11 + mobile/src/main/res/drawable/fa_ioxhost.xml | 11 + mobile/src/main/res/drawable/fa_itunes.xml | 11 + .../src/main/res/drawable/fa_itunes_note.xml | 11 + mobile/src/main/res/drawable/fa_java.xml | 11 + mobile/src/main/res/drawable/fa_jenkins.xml | 11 + mobile/src/main/res/drawable/fa_joget.xml | 11 + mobile/src/main/res/drawable/fa_joomla.xml | 11 + mobile/src/main/res/drawable/fa_js.xml | 11 + mobile/src/main/res/drawable/fa_jsfiddle.xml | 11 + mobile/src/main/res/drawable/fa_keybase.xml | 11 + mobile/src/main/res/drawable/fa_keycdn.xml | 11 + .../src/main/res/drawable/fa_kickstarter.xml | 11 + .../main/res/drawable/fa_kickstarter_k.xml | 11 + mobile/src/main/res/drawable/fa_korvue.xml | 11 + mobile/src/main/res/drawable/fa_laravel.xml | 11 + mobile/src/main/res/drawable/fa_lastfm.xml | 11 + mobile/src/main/res/drawable/fa_leanpub.xml | 11 + mobile/src/main/res/drawable/fa_less.xml | 11 + mobile/src/main/res/drawable/fa_line.xml | 11 + mobile/src/main/res/drawable/fa_linkedin.xml | 11 + .../src/main/res/drawable/fa_linkedin_in.xml | 11 + mobile/src/main/res/drawable/fa_linode.xml | 11 + mobile/src/main/res/drawable/fa_linux.xml | 11 + mobile/src/main/res/drawable/fa_lyft.xml | 11 + mobile/src/main/res/drawable/fa_magento.xml | 11 + mobile/src/main/res/drawable/fa_mailchimp.xml | 11 + .../src/main/res/drawable/fa_mandalorian.xml | 11 + mobile/src/main/res/drawable/fa_mastodon.xml | 11 + mobile/src/main/res/drawable/fa_maxcdn.xml | 11 + mobile/src/main/res/drawable/fa_medapps.xml | 11 + mobile/src/main/res/drawable/fa_medium.xml | 11 + mobile/src/main/res/drawable/fa_medium_m.xml | 11 + mobile/src/main/res/drawable/fa_medrt.xml | 11 + mobile/src/main/res/drawable/fa_meetup.xml | 11 + mobile/src/main/res/drawable/fa_megaport.xml | 11 + mobile/src/main/res/drawable/fa_microsoft.xml | 11 + mobile/src/main/res/drawable/fa_mix.xml | 11 + mobile/src/main/res/drawable/fa_mixcloud.xml | 11 + mobile/src/main/res/drawable/fa_mizuni.xml | 11 + mobile/src/main/res/drawable/fa_modx.xml | 11 + mobile/src/main/res/drawable/fa_monero.xml | 11 + mobile/src/main/res/drawable/fa_napster.xml | 11 + mobile/src/main/res/drawable/fa_nimblr.xml | 11 + .../main/res/drawable/fa_nintendo_switch.xml | 11 + mobile/src/main/res/drawable/fa_node.xml | 11 + mobile/src/main/res/drawable/fa_node_js.xml | 11 + mobile/src/main/res/drawable/fa_npm.xml | 11 + mobile/src/main/res/drawable/fa_ns8.xml | 11 + .../src/main/res/drawable/fa_nutritionix.xml | 11 + .../main/res/drawable/fa_odnoklassniki.xml | 11 + mobile/src/main/res/drawable/fa_opencart.xml | 11 + mobile/src/main/res/drawable/fa_openid.xml | 11 + mobile/src/main/res/drawable/fa_opera.xml | 11 + .../main/res/drawable/fa_optin_monster.xml | 11 + mobile/src/main/res/drawable/fa_osi.xml | 11 + mobile/src/main/res/drawable/fa_page4.xml | 11 + mobile/src/main/res/drawable/fa_pagelines.xml | 11 + mobile/src/main/res/drawable/fa_palfed.xml | 11 + mobile/src/main/res/drawable/fa_patreon.xml | 11 + mobile/src/main/res/drawable/fa_paypal.xml | 11 + mobile/src/main/res/drawable/fa_periscope.xml | 11 + .../src/main/res/drawable/fa_phabricator.xml | 11 + .../res/drawable/fa_phoenix_framework.xml | 11 + .../main/res/drawable/fa_phoenix_squadron.xml | 11 + mobile/src/main/res/drawable/fa_php.xml | 11 + mobile/src/main/res/drawable/fa_pinterest.xml | 11 + .../src/main/res/drawable/fa_pinterest_p.xml | 11 + .../src/main/res/drawable/fa_playstation.xml | 11 + .../src/main/res/drawable/fa_product_hunt.xml | 11 + mobile/src/main/res/drawable/fa_pushed.xml | 11 + mobile/src/main/res/drawable/fa_python.xml | 11 + mobile/src/main/res/drawable/fa_qq.xml | 11 + mobile/src/main/res/drawable/fa_quinscape.xml | 11 + mobile/src/main/res/drawable/fa_quora.xml | 11 + mobile/src/main/res/drawable/fa_r_project.xml | 11 + mobile/src/main/res/drawable/fa_ravelry.xml | 11 + mobile/src/main/res/drawable/fa_react.xml | 11 + mobile/src/main/res/drawable/fa_readme.xml | 11 + mobile/src/main/res/drawable/fa_rebel.xml | 11 + mobile/src/main/res/drawable/fa_red_river.xml | 11 + mobile/src/main/res/drawable/fa_reddit.xml | 11 + .../src/main/res/drawable/fa_reddit_alien.xml | 11 + mobile/src/main/res/drawable/fa_rendact.xml | 11 + mobile/src/main/res/drawable/fa_renren.xml | 11 + mobile/src/main/res/drawable/fa_replyd.xml | 11 + .../src/main/res/drawable/fa_researchgate.xml | 11 + mobile/src/main/res/drawable/fa_resolving.xml | 11 + .../src/main/res/drawable/fa_rocketchat.xml | 11 + mobile/src/main/res/drawable/fa_rockrms.xml | 11 + mobile/src/main/res/drawable/fa_safari.xml | 11 + mobile/src/main/res/drawable/fa_sass.xml | 11 + mobile/src/main/res/drawable/fa_schlix.xml | 11 + mobile/src/main/res/drawable/fa_scribd.xml | 11 + .../src/main/res/drawable/fa_searchengin.xml | 11 + mobile/src/main/res/drawable/fa_sellcast.xml | 11 + mobile/src/main/res/drawable/fa_sellsy.xml | 11 + .../src/main/res/drawable/fa_servicestack.xml | 11 + .../src/main/res/drawable/fa_shirtsinbulk.xml | 11 + mobile/src/main/res/drawable/fa_shopware.xml | 11 + .../src/main/res/drawable/fa_simplybuilt.xml | 11 + mobile/src/main/res/drawable/fa_sistrix.xml | 11 + mobile/src/main/res/drawable/fa_sith.xml | 11 + mobile/src/main/res/drawable/fa_skyatlas.xml | 11 + mobile/src/main/res/drawable/fa_skype.xml | 11 + mobile/src/main/res/drawable/fa_slack.xml | 11 + .../src/main/res/drawable/fa_slack_hash.xml | 11 + .../src/main/res/drawable/fa_slideshare.xml | 11 + mobile/src/main/res/drawable/fa_snapchat.xml | 11 + .../main/res/drawable/fa_snapchat_ghost.xml | 11 + .../src/main/res/drawable/fa_soundcloud.xml | 11 + mobile/src/main/res/drawable/fa_speakap.xml | 11 + mobile/src/main/res/drawable/fa_spotify.xml | 11 + .../src/main/res/drawable/fa_squarespace.xml | 11 + .../main/res/drawable/fa_stack_exchange.xml | 11 + .../main/res/drawable/fa_stack_overflow.xml | 11 + .../src/main/res/drawable/fa_staylinked.xml | 11 + mobile/src/main/res/drawable/fa_steam.xml | 11 + .../src/main/res/drawable/fa_steam_symbol.xml | 11 + .../src/main/res/drawable/fa_sticker_mule.xml | 11 + mobile/src/main/res/drawable/fa_strava.xml | 11 + mobile/src/main/res/drawable/fa_stripe.xml | 11 + mobile/src/main/res/drawable/fa_stripe_s.xml | 11 + .../src/main/res/drawable/fa_studiovinari.xml | 11 + .../src/main/res/drawable/fa_stumbleupon.xml | 11 + .../src/main/res/drawable/fa_superpowers.xml | 11 + mobile/src/main/res/drawable/fa_supple.xml | 11 + mobile/src/main/res/drawable/fa_teamspeak.xml | 11 + mobile/src/main/res/drawable/fa_telegram.xml | 11 + .../main/res/drawable/fa_telegram_plane.xml | 11 + .../main/res/drawable/fa_tencent_weibo.xml | 11 + mobile/src/main/res/drawable/fa_themeco.xml | 11 + mobile/src/main/res/drawable/fa_themeisle.xml | 11 + .../main/res/drawable/fa_trade_federation.xml | 11 + mobile/src/main/res/drawable/fa_trello.xml | 11 + .../src/main/res/drawable/fa_tripadvisor.xml | 11 + mobile/src/main/res/drawable/fa_tumblr.xml | 11 + mobile/src/main/res/drawable/fa_twitch.xml | 11 + mobile/src/main/res/drawable/fa_twitter.xml | 11 + mobile/src/main/res/drawable/fa_typo3.xml | 11 + mobile/src/main/res/drawable/fa_uber.xml | 11 + mobile/src/main/res/drawable/fa_uikit.xml | 11 + .../src/main/res/drawable/fa_uniregistry.xml | 11 + mobile/src/main/res/drawable/fa_untappd.xml | 11 + mobile/src/main/res/drawable/fa_usb.xml | 11 + mobile/src/main/res/drawable/fa_ussunnah.xml | 11 + mobile/src/main/res/drawable/fa_vaadin.xml | 11 + mobile/src/main/res/drawable/fa_viacoin.xml | 11 + mobile/src/main/res/drawable/fa_viadeo.xml | 11 + mobile/src/main/res/drawable/fa_viber.xml | 11 + mobile/src/main/res/drawable/fa_vimeo.xml | 11 + mobile/src/main/res/drawable/fa_vimeo_v.xml | 11 + mobile/src/main/res/drawable/fa_vine.xml | 11 + mobile/src/main/res/drawable/fa_vk.xml | 11 + mobile/src/main/res/drawable/fa_vnv.xml | 11 + mobile/src/main/res/drawable/fa_vuejs.xml | 11 + mobile/src/main/res/drawable/fa_weebly.xml | 11 + mobile/src/main/res/drawable/fa_weibo.xml | 11 + mobile/src/main/res/drawable/fa_weixin.xml | 11 + mobile/src/main/res/drawable/fa_whatsapp.xml | 11 + mobile/src/main/res/drawable/fa_whmcs.xml | 11 + .../src/main/res/drawable/fa_wikipedia_w.xml | 11 + mobile/src/main/res/drawable/fa_windows.xml | 11 + mobile/src/main/res/drawable/fa_wix.xml | 11 + .../res/drawable/fa_wolf_pack_battalion.xml | 11 + mobile/src/main/res/drawable/fa_wordpress.xml | 11 + .../main/res/drawable/fa_wordpress_simple.xml | 11 + .../src/main/res/drawable/fa_wpbeginner.xml | 11 + .../src/main/res/drawable/fa_wpexplorer.xml | 11 + mobile/src/main/res/drawable/fa_wpforms.xml | 11 + mobile/src/main/res/drawable/fa_xbox.xml | 11 + mobile/src/main/res/drawable/fa_xing.xml | 11 + .../src/main/res/drawable/fa_y_combinator.xml | 11 + mobile/src/main/res/drawable/fa_yahoo.xml | 11 + mobile/src/main/res/drawable/fa_yandex.xml | 11 + .../res/drawable/fa_yandex_international.xml | 11 + mobile/src/main/res/drawable/fa_yelp.xml | 11 + mobile/src/main/res/drawable/fa_yoast.xml | 11 + mobile/src/main/res/drawable/fa_youtube.xml | 11 + mobile/src/main/res/drawable/ic_about.xml | 13 + mobile/src/main/res/drawable/ic_add.xml | 7 + mobile/src/main/res/drawable/ic_bluetooth.xml | 15 + mobile/src/main/res/drawable/ic_check.xml | 13 + mobile/src/main/res/drawable/ic_copy.xml | 14 + mobile/src/main/res/drawable/ic_delete.xml | 13 + mobile/src/main/res/drawable/ic_down.xml | 13 + mobile/src/main/res/drawable/ic_freeotp.png | Bin 0 -> 113981 bytes mobile/src/main/res/drawable/ic_hotp.xml | 7 + mobile/src/main/res/drawable/ic_lock.xml | 7 + mobile/src/main/res/drawable/ic_scan.xml | 7 + mobile/src/main/res/drawable/ic_share.xml | 13 + mobile/src/main/res/drawable/ic_totp.xml | 7 + mobile/src/main/res/drawable/ic_up.xml | 13 + .../src/main/res/drawable/progress.xml | 23 +- mobile/src/main/res/layout/activity_main.xml | 74 +++ .../src/main/res/layout/fragment_scan.xml | 55 +- .../src/main/res/layout/fragment_share.xml | 25 +- mobile/src/main/res/layout/target.xml | 76 +++ mobile/src/main/res/layout/token.xml | 169 ++++++ mobile/src/main/res/menu/menu_main.xml | 60 ++ .../src/main/res/values-sw600dp/integers.xml | 24 + mobile/src/main/res/values/colors.xml | 69 +++ .../src/main/res/values/dimens.xml | 6 +- .../src/main/res/values/drawables.xml | 11 +- mobile/src/main/res/values/integers.xml | 24 + mobile/src/main/res/values/strings.xml | 64 ++ mobile/src/main/res/values/styles.xml | 45 ++ .../org/fedorahosted/freeotp/Base32Test.java | 48 ++ settings.gradle | 2 +- 450 files changed, 8855 insertions(+), 3725 deletions(-) delete mode 100644 COPYING.icons delete mode 100644 app/build.gradle delete mode 100644 app/src/main/ic_freeotp_logo-web.png delete mode 100644 app/src/main/java/com/google/android/apps/authenticator/Base32String.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/AboutActivity.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/BaseReorderableAdapter.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/MainActivity.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/ProgressCircle.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/Token.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/TokenAdapter.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/TokenCode.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/TokenLayout.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/TokenPersistence.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/add/ScanActivity.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/add/ScanFrameProcessor.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/edit/BaseActivity.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/edit/DeleteActivity.java delete mode 100644 app/src/main/java/org/fedorahosted/freeotp/edit/EditActivity.java delete mode 100644 app/src/main/res/anim/fadein.xml delete mode 100644 app/src/main/res/anim/fadeout.xml delete mode 100644 app/src/main/res/anim/token_image_fadein.xml delete mode 100644 app/src/main/res/anim/token_image_fadeout.xml delete mode 100644 app/src/main/res/color/menu.xml delete mode 100644 app/src/main/res/drawable-hdpi/ic_action_edit.png delete mode 100644 app/src/main/res/drawable-hdpi/ic_launcher.png delete mode 100644 app/src/main/res/drawable-hdpi/qrcode.png delete mode 100644 app/src/main/res/drawable-ldpi/ic_launcher.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_action_edit.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_launcher.png delete mode 100644 app/src/main/res/drawable-mdpi/qrcode.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_action_edit.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_launcher.png delete mode 100644 app/src/main/res/drawable-xhdpi/qrcode.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_edit.png delete mode 100644 app/src/main/res/drawable-xxhdpi/logo.png delete mode 100644 app/src/main/res/drawable-xxhdpi/qrcode.png delete mode 100644 app/src/main/res/drawable/ic_freeotp.xml delete mode 100644 app/src/main/res/drawable/ic_freeotp_logo_background.xml delete mode 100644 app/src/main/res/drawable/menu.xml delete mode 100644 app/src/main/res/drawable/scan.xml delete mode 100644 app/src/main/res/layout/about.xml delete mode 100644 app/src/main/res/layout/delete.xml delete mode 100644 app/src/main/res/layout/edit.xml delete mode 100644 app/src/main/res/layout/main.xml delete mode 100644 app/src/main/res/layout/metadata.xml delete mode 100644 app/src/main/res/layout/titles.xml delete mode 100644 app/src/main/res/layout/token.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_freeotp_logo.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_freeotp_logo_round.xml delete mode 100644 app/src/main/res/mipmap-hdpi/ic_freeotp_logo.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_freeotp_logo_foreground.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_freeotp_logo_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_freeotp_logo.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_freeotp_logo_foreground.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_freeotp_logo_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_freeotp_logo.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_freeotp_logo_foreground.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_freeotp_logo_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_freeotp_logo.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_freeotp_logo_foreground.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_freeotp_logo_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_freeotp_logo.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_freeotp_logo_foreground.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_freeotp_logo_round.png delete mode 100644 app/src/main/res/values-hu/strings.xml delete mode 100644 app/src/main/res/values-v11/styles.xml delete mode 100644 app/src/main/res/values-v14/styles.xml delete mode 100644 app/src/main/res/values/strings.xml delete mode 100644 app/src/main/res/values/styles.xml delete mode 100644 app/src/test/java/org/fedorahosted/freeotp/TokenCodeTest.java delete mode 100644 app/src/test/java/org/fedorahosted/freeotp/TokenPersistenceTest.java delete mode 100644 app/src/test/java/org/fedorahosted/freeotp/TokenTest.java delete mode 100644 app/src/test/java/org/fedorahosted/freeotp/TokenTestUtils.java create mode 100644 gradle.properties delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100644 ic_launcher-web.png create mode 100644 mobile/build.gradle create mode 100644 mobile/proguard-rules.pro create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/Context.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/MemorySharedPreferences.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/TokenAdapterTest.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/TokenCompatTest.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/TokenRFC4226Test.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/TokenRFC6238Test.java create mode 100644 mobile/src/androidTest/java/org/fedorahosted/freeotp/TokenUriInvalidTest.java rename {app => mobile}/src/main/AndroidManifest.xml (57%) create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/Code.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/Token.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/Activity.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/Adapter.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/ScanDialogFragment.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/ViewHolder.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/Adapter.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/Clipboard.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/Discoverable.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/Jelling.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/ShareFragment.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/SortableItem.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/main/share/SortableItemAdapter.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/utils/Base32.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/utils/GridLayoutItemDecoration.java create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/utils/SelectableAdapter.java rename app/src/main/java/org/fedorahosted/freeotp/add/ScanWindowFrameLayout.java => mobile/src/main/java/org/fedorahosted/freeotp/utils/SquareFrameLayout.java (80%) create mode 100644 mobile/src/main/java/org/fedorahosted/freeotp/utils/Time.java rename app/src/main/res/drawable/token.xml => mobile/src/main/res/drawable/button.xml (69%) create mode 100644 mobile/src/main/res/drawable/fa_500px.xml create mode 100644 mobile/src/main/res/drawable/fa_accessible_icon.xml create mode 100644 mobile/src/main/res/drawable/fa_accusoft.xml create mode 100644 mobile/src/main/res/drawable/fa_adn.xml create mode 100644 mobile/src/main/res/drawable/fa_adversal.xml create mode 100644 mobile/src/main/res/drawable/fa_affiliatetheme.xml create mode 100644 mobile/src/main/res/drawable/fa_algolia.xml create mode 100644 mobile/src/main/res/drawable/fa_amazon.xml create mode 100644 mobile/src/main/res/drawable/fa_amazon_pay.xml create mode 100644 mobile/src/main/res/drawable/fa_amilia.xml create mode 100644 mobile/src/main/res/drawable/fa_android.xml create mode 100644 mobile/src/main/res/drawable/fa_angellist.xml create mode 100644 mobile/src/main/res/drawable/fa_angrycreative.xml create mode 100644 mobile/src/main/res/drawable/fa_angular.xml create mode 100644 mobile/src/main/res/drawable/fa_app_store.xml create mode 100644 mobile/src/main/res/drawable/fa_app_store_ios.xml create mode 100644 mobile/src/main/res/drawable/fa_apper.xml create mode 100644 mobile/src/main/res/drawable/fa_apple.xml create mode 100644 mobile/src/main/res/drawable/fa_apple_pay.xml create mode 100644 mobile/src/main/res/drawable/fa_asymmetrik.xml create mode 100644 mobile/src/main/res/drawable/fa_audible.xml create mode 100644 mobile/src/main/res/drawable/fa_autoprefixer.xml create mode 100644 mobile/src/main/res/drawable/fa_avianex.xml create mode 100644 mobile/src/main/res/drawable/fa_aws.xml create mode 100644 mobile/src/main/res/drawable/fa_bandcamp.xml create mode 100644 mobile/src/main/res/drawable/fa_behance.xml create mode 100644 mobile/src/main/res/drawable/fa_bimobject.xml create mode 100644 mobile/src/main/res/drawable/fa_bitbucket.xml create mode 100644 mobile/src/main/res/drawable/fa_bitcoin.xml create mode 100644 mobile/src/main/res/drawable/fa_bity.xml create mode 100644 mobile/src/main/res/drawable/fa_black_tie.xml create mode 100644 mobile/src/main/res/drawable/fa_blackberry.xml create mode 100644 mobile/src/main/res/drawable/fa_blogger.xml create mode 100644 mobile/src/main/res/drawable/fa_blogger_b.xml create mode 100644 mobile/src/main/res/drawable/fa_bluetooth.xml create mode 100644 mobile/src/main/res/drawable/fa_bluetooth_b.xml create mode 100644 mobile/src/main/res/drawable/fa_btc.xml create mode 100644 mobile/src/main/res/drawable/fa_buromobelexperte.xml create mode 100644 mobile/src/main/res/drawable/fa_buysellads.xml create mode 100644 mobile/src/main/res/drawable/fa_centercode.xml create mode 100644 mobile/src/main/res/drawable/fa_chrome.xml create mode 100644 mobile/src/main/res/drawable/fa_cloudscale.xml create mode 100644 mobile/src/main/res/drawable/fa_cloudsmith.xml create mode 100644 mobile/src/main/res/drawable/fa_cloudversify.xml create mode 100644 mobile/src/main/res/drawable/fa_codepen.xml create mode 100644 mobile/src/main/res/drawable/fa_codiepie.xml create mode 100644 mobile/src/main/res/drawable/fa_connectdevelop.xml create mode 100644 mobile/src/main/res/drawable/fa_contao.xml create mode 100644 mobile/src/main/res/drawable/fa_cpanel.xml create mode 100644 mobile/src/main/res/drawable/fa_css3.xml create mode 100644 mobile/src/main/res/drawable/fa_cuttlefish.xml create mode 100644 mobile/src/main/res/drawable/fa_d_and_d.xml create mode 100644 mobile/src/main/res/drawable/fa_dashcube.xml create mode 100644 mobile/src/main/res/drawable/fa_delicious.xml create mode 100644 mobile/src/main/res/drawable/fa_deploydog.xml create mode 100644 mobile/src/main/res/drawable/fa_deskpro.xml create mode 100644 mobile/src/main/res/drawable/fa_deviantart.xml create mode 100644 mobile/src/main/res/drawable/fa_digg.xml create mode 100644 mobile/src/main/res/drawable/fa_digital_ocean.xml create mode 100644 mobile/src/main/res/drawable/fa_discord.xml create mode 100644 mobile/src/main/res/drawable/fa_discourse.xml create mode 100644 mobile/src/main/res/drawable/fa_dochub.xml create mode 100644 mobile/src/main/res/drawable/fa_docker.xml create mode 100644 mobile/src/main/res/drawable/fa_draft2digital.xml create mode 100644 mobile/src/main/res/drawable/fa_dribbble.xml create mode 100644 mobile/src/main/res/drawable/fa_dropbox.xml create mode 100644 mobile/src/main/res/drawable/fa_drupal.xml create mode 100644 mobile/src/main/res/drawable/fa_dyalog.xml create mode 100644 mobile/src/main/res/drawable/fa_earlybirds.xml create mode 100644 mobile/src/main/res/drawable/fa_ebay.xml create mode 100644 mobile/src/main/res/drawable/fa_edge.xml create mode 100644 mobile/src/main/res/drawable/fa_elementor.xml create mode 100644 mobile/src/main/res/drawable/fa_ember.xml create mode 100644 mobile/src/main/res/drawable/fa_empire.xml create mode 100644 mobile/src/main/res/drawable/fa_envira.xml create mode 100644 mobile/src/main/res/drawable/fa_erlang.xml create mode 100644 mobile/src/main/res/drawable/fa_ethereum.xml create mode 100644 mobile/src/main/res/drawable/fa_etsy.xml create mode 100644 mobile/src/main/res/drawable/fa_expeditedssl.xml create mode 100644 mobile/src/main/res/drawable/fa_facebook.xml create mode 100644 mobile/src/main/res/drawable/fa_facebook_f.xml create mode 100644 mobile/src/main/res/drawable/fa_facebook_messenger.xml create mode 100644 mobile/src/main/res/drawable/fa_firefox.xml create mode 100644 mobile/src/main/res/drawable/fa_firstdraft.xml create mode 100644 mobile/src/main/res/drawable/fa_flickr.xml create mode 100644 mobile/src/main/res/drawable/fa_flipboard.xml create mode 100644 mobile/src/main/res/drawable/fa_fly.xml create mode 100644 mobile/src/main/res/drawable/fa_font_awesome.xml create mode 100644 mobile/src/main/res/drawable/fa_font_awesome_flag.xml create mode 100644 mobile/src/main/res/drawable/fa_font_awesome_logo_full.xml create mode 100644 mobile/src/main/res/drawable/fa_fonticons.xml create mode 100644 mobile/src/main/res/drawable/fa_fonticons_fi.xml create mode 100644 mobile/src/main/res/drawable/fa_fort_awesome.xml create mode 100644 mobile/src/main/res/drawable/fa_forumbee.xml create mode 100644 mobile/src/main/res/drawable/fa_foursquare.xml create mode 100644 mobile/src/main/res/drawable/fa_free_code_camp.xml create mode 100644 mobile/src/main/res/drawable/fa_freebsd.xml create mode 100644 mobile/src/main/res/drawable/fa_fulcrum.xml create mode 100644 mobile/src/main/res/drawable/fa_get_pocket.xml create mode 100644 mobile/src/main/res/drawable/fa_gg.xml create mode 100644 mobile/src/main/res/drawable/fa_git.xml create mode 100644 mobile/src/main/res/drawable/fa_github.xml create mode 100644 mobile/src/main/res/drawable/fa_gitkraken.xml create mode 100644 mobile/src/main/res/drawable/fa_gitlab.xml create mode 100644 mobile/src/main/res/drawable/fa_gitter.xml create mode 100644 mobile/src/main/res/drawable/fa_glide.xml create mode 100644 mobile/src/main/res/drawable/fa_glide_g.xml create mode 100644 mobile/src/main/res/drawable/fa_gofore.xml create mode 100644 mobile/src/main/res/drawable/fa_goodreads.xml create mode 100644 mobile/src/main/res/drawable/fa_goodreads_g.xml create mode 100644 mobile/src/main/res/drawable/fa_google.xml create mode 100644 mobile/src/main/res/drawable/fa_google_drive.xml create mode 100644 mobile/src/main/res/drawable/fa_google_play.xml create mode 100644 mobile/src/main/res/drawable/fa_google_plus.xml create mode 100644 mobile/src/main/res/drawable/fa_google_plus_g.xml create mode 100644 mobile/src/main/res/drawable/fa_google_wallet.xml create mode 100644 mobile/src/main/res/drawable/fa_gratipay.xml create mode 100644 mobile/src/main/res/drawable/fa_grav.xml create mode 100644 mobile/src/main/res/drawable/fa_gripfire.xml create mode 100644 mobile/src/main/res/drawable/fa_grunt.xml create mode 100644 mobile/src/main/res/drawable/fa_gulp.xml create mode 100644 mobile/src/main/res/drawable/fa_hacker_news.xml create mode 100644 mobile/src/main/res/drawable/fa_hips.xml create mode 100644 mobile/src/main/res/drawable/fa_hire_a_helper.xml create mode 100644 mobile/src/main/res/drawable/fa_hornbill.xml create mode 100644 mobile/src/main/res/drawable/fa_hotjar.xml create mode 100644 mobile/src/main/res/drawable/fa_houzz.xml create mode 100644 mobile/src/main/res/drawable/fa_html5.xml create mode 100644 mobile/src/main/res/drawable/fa_hubspot.xml create mode 100644 mobile/src/main/res/drawable/fa_imdb.xml create mode 100644 mobile/src/main/res/drawable/fa_instagram.xml create mode 100644 mobile/src/main/res/drawable/fa_internet_explorer.xml create mode 100644 mobile/src/main/res/drawable/fa_ioxhost.xml create mode 100644 mobile/src/main/res/drawable/fa_itunes.xml create mode 100644 mobile/src/main/res/drawable/fa_itunes_note.xml create mode 100644 mobile/src/main/res/drawable/fa_java.xml create mode 100644 mobile/src/main/res/drawable/fa_jenkins.xml create mode 100644 mobile/src/main/res/drawable/fa_joget.xml create mode 100644 mobile/src/main/res/drawable/fa_joomla.xml create mode 100644 mobile/src/main/res/drawable/fa_js.xml create mode 100644 mobile/src/main/res/drawable/fa_jsfiddle.xml create mode 100644 mobile/src/main/res/drawable/fa_keybase.xml create mode 100644 mobile/src/main/res/drawable/fa_keycdn.xml create mode 100644 mobile/src/main/res/drawable/fa_kickstarter.xml create mode 100644 mobile/src/main/res/drawable/fa_kickstarter_k.xml create mode 100644 mobile/src/main/res/drawable/fa_korvue.xml create mode 100644 mobile/src/main/res/drawable/fa_laravel.xml create mode 100644 mobile/src/main/res/drawable/fa_lastfm.xml create mode 100644 mobile/src/main/res/drawable/fa_leanpub.xml create mode 100644 mobile/src/main/res/drawable/fa_less.xml create mode 100644 mobile/src/main/res/drawable/fa_line.xml create mode 100644 mobile/src/main/res/drawable/fa_linkedin.xml create mode 100644 mobile/src/main/res/drawable/fa_linkedin_in.xml create mode 100644 mobile/src/main/res/drawable/fa_linode.xml create mode 100644 mobile/src/main/res/drawable/fa_linux.xml create mode 100644 mobile/src/main/res/drawable/fa_lyft.xml create mode 100644 mobile/src/main/res/drawable/fa_magento.xml create mode 100644 mobile/src/main/res/drawable/fa_mailchimp.xml create mode 100644 mobile/src/main/res/drawable/fa_mandalorian.xml create mode 100644 mobile/src/main/res/drawable/fa_mastodon.xml create mode 100644 mobile/src/main/res/drawable/fa_maxcdn.xml create mode 100644 mobile/src/main/res/drawable/fa_medapps.xml create mode 100644 mobile/src/main/res/drawable/fa_medium.xml create mode 100644 mobile/src/main/res/drawable/fa_medium_m.xml create mode 100644 mobile/src/main/res/drawable/fa_medrt.xml create mode 100644 mobile/src/main/res/drawable/fa_meetup.xml create mode 100644 mobile/src/main/res/drawable/fa_megaport.xml create mode 100644 mobile/src/main/res/drawable/fa_microsoft.xml create mode 100644 mobile/src/main/res/drawable/fa_mix.xml create mode 100644 mobile/src/main/res/drawable/fa_mixcloud.xml create mode 100644 mobile/src/main/res/drawable/fa_mizuni.xml create mode 100644 mobile/src/main/res/drawable/fa_modx.xml create mode 100644 mobile/src/main/res/drawable/fa_monero.xml create mode 100644 mobile/src/main/res/drawable/fa_napster.xml create mode 100644 mobile/src/main/res/drawable/fa_nimblr.xml create mode 100644 mobile/src/main/res/drawable/fa_nintendo_switch.xml create mode 100644 mobile/src/main/res/drawable/fa_node.xml create mode 100644 mobile/src/main/res/drawable/fa_node_js.xml create mode 100644 mobile/src/main/res/drawable/fa_npm.xml create mode 100644 mobile/src/main/res/drawable/fa_ns8.xml create mode 100644 mobile/src/main/res/drawable/fa_nutritionix.xml create mode 100644 mobile/src/main/res/drawable/fa_odnoklassniki.xml create mode 100644 mobile/src/main/res/drawable/fa_opencart.xml create mode 100644 mobile/src/main/res/drawable/fa_openid.xml create mode 100644 mobile/src/main/res/drawable/fa_opera.xml create mode 100644 mobile/src/main/res/drawable/fa_optin_monster.xml create mode 100644 mobile/src/main/res/drawable/fa_osi.xml create mode 100644 mobile/src/main/res/drawable/fa_page4.xml create mode 100644 mobile/src/main/res/drawable/fa_pagelines.xml create mode 100644 mobile/src/main/res/drawable/fa_palfed.xml create mode 100644 mobile/src/main/res/drawable/fa_patreon.xml create mode 100644 mobile/src/main/res/drawable/fa_paypal.xml create mode 100644 mobile/src/main/res/drawable/fa_periscope.xml create mode 100644 mobile/src/main/res/drawable/fa_phabricator.xml create mode 100644 mobile/src/main/res/drawable/fa_phoenix_framework.xml create mode 100644 mobile/src/main/res/drawable/fa_phoenix_squadron.xml create mode 100644 mobile/src/main/res/drawable/fa_php.xml create mode 100644 mobile/src/main/res/drawable/fa_pinterest.xml create mode 100644 mobile/src/main/res/drawable/fa_pinterest_p.xml create mode 100644 mobile/src/main/res/drawable/fa_playstation.xml create mode 100644 mobile/src/main/res/drawable/fa_product_hunt.xml create mode 100644 mobile/src/main/res/drawable/fa_pushed.xml create mode 100644 mobile/src/main/res/drawable/fa_python.xml create mode 100644 mobile/src/main/res/drawable/fa_qq.xml create mode 100644 mobile/src/main/res/drawable/fa_quinscape.xml create mode 100644 mobile/src/main/res/drawable/fa_quora.xml create mode 100644 mobile/src/main/res/drawable/fa_r_project.xml create mode 100644 mobile/src/main/res/drawable/fa_ravelry.xml create mode 100644 mobile/src/main/res/drawable/fa_react.xml create mode 100644 mobile/src/main/res/drawable/fa_readme.xml create mode 100644 mobile/src/main/res/drawable/fa_rebel.xml create mode 100644 mobile/src/main/res/drawable/fa_red_river.xml create mode 100644 mobile/src/main/res/drawable/fa_reddit.xml create mode 100644 mobile/src/main/res/drawable/fa_reddit_alien.xml create mode 100644 mobile/src/main/res/drawable/fa_rendact.xml create mode 100644 mobile/src/main/res/drawable/fa_renren.xml create mode 100644 mobile/src/main/res/drawable/fa_replyd.xml create mode 100644 mobile/src/main/res/drawable/fa_researchgate.xml create mode 100644 mobile/src/main/res/drawable/fa_resolving.xml create mode 100644 mobile/src/main/res/drawable/fa_rocketchat.xml create mode 100644 mobile/src/main/res/drawable/fa_rockrms.xml create mode 100644 mobile/src/main/res/drawable/fa_safari.xml create mode 100644 mobile/src/main/res/drawable/fa_sass.xml create mode 100644 mobile/src/main/res/drawable/fa_schlix.xml create mode 100644 mobile/src/main/res/drawable/fa_scribd.xml create mode 100644 mobile/src/main/res/drawable/fa_searchengin.xml create mode 100644 mobile/src/main/res/drawable/fa_sellcast.xml create mode 100644 mobile/src/main/res/drawable/fa_sellsy.xml create mode 100644 mobile/src/main/res/drawable/fa_servicestack.xml create mode 100644 mobile/src/main/res/drawable/fa_shirtsinbulk.xml create mode 100644 mobile/src/main/res/drawable/fa_shopware.xml create mode 100644 mobile/src/main/res/drawable/fa_simplybuilt.xml create mode 100644 mobile/src/main/res/drawable/fa_sistrix.xml create mode 100644 mobile/src/main/res/drawable/fa_sith.xml create mode 100644 mobile/src/main/res/drawable/fa_skyatlas.xml create mode 100644 mobile/src/main/res/drawable/fa_skype.xml create mode 100644 mobile/src/main/res/drawable/fa_slack.xml create mode 100644 mobile/src/main/res/drawable/fa_slack_hash.xml create mode 100644 mobile/src/main/res/drawable/fa_slideshare.xml create mode 100644 mobile/src/main/res/drawable/fa_snapchat.xml create mode 100644 mobile/src/main/res/drawable/fa_snapchat_ghost.xml create mode 100644 mobile/src/main/res/drawable/fa_soundcloud.xml create mode 100644 mobile/src/main/res/drawable/fa_speakap.xml create mode 100644 mobile/src/main/res/drawable/fa_spotify.xml create mode 100644 mobile/src/main/res/drawable/fa_squarespace.xml create mode 100644 mobile/src/main/res/drawable/fa_stack_exchange.xml create mode 100644 mobile/src/main/res/drawable/fa_stack_overflow.xml create mode 100644 mobile/src/main/res/drawable/fa_staylinked.xml create mode 100644 mobile/src/main/res/drawable/fa_steam.xml create mode 100644 mobile/src/main/res/drawable/fa_steam_symbol.xml create mode 100644 mobile/src/main/res/drawable/fa_sticker_mule.xml create mode 100644 mobile/src/main/res/drawable/fa_strava.xml create mode 100644 mobile/src/main/res/drawable/fa_stripe.xml create mode 100644 mobile/src/main/res/drawable/fa_stripe_s.xml create mode 100644 mobile/src/main/res/drawable/fa_studiovinari.xml create mode 100644 mobile/src/main/res/drawable/fa_stumbleupon.xml create mode 100644 mobile/src/main/res/drawable/fa_superpowers.xml create mode 100644 mobile/src/main/res/drawable/fa_supple.xml create mode 100644 mobile/src/main/res/drawable/fa_teamspeak.xml create mode 100644 mobile/src/main/res/drawable/fa_telegram.xml create mode 100644 mobile/src/main/res/drawable/fa_telegram_plane.xml create mode 100644 mobile/src/main/res/drawable/fa_tencent_weibo.xml create mode 100644 mobile/src/main/res/drawable/fa_themeco.xml create mode 100644 mobile/src/main/res/drawable/fa_themeisle.xml create mode 100644 mobile/src/main/res/drawable/fa_trade_federation.xml create mode 100644 mobile/src/main/res/drawable/fa_trello.xml create mode 100644 mobile/src/main/res/drawable/fa_tripadvisor.xml create mode 100644 mobile/src/main/res/drawable/fa_tumblr.xml create mode 100644 mobile/src/main/res/drawable/fa_twitch.xml create mode 100644 mobile/src/main/res/drawable/fa_twitter.xml create mode 100644 mobile/src/main/res/drawable/fa_typo3.xml create mode 100644 mobile/src/main/res/drawable/fa_uber.xml create mode 100644 mobile/src/main/res/drawable/fa_uikit.xml create mode 100644 mobile/src/main/res/drawable/fa_uniregistry.xml create mode 100644 mobile/src/main/res/drawable/fa_untappd.xml create mode 100644 mobile/src/main/res/drawable/fa_usb.xml create mode 100644 mobile/src/main/res/drawable/fa_ussunnah.xml create mode 100644 mobile/src/main/res/drawable/fa_vaadin.xml create mode 100644 mobile/src/main/res/drawable/fa_viacoin.xml create mode 100644 mobile/src/main/res/drawable/fa_viadeo.xml create mode 100644 mobile/src/main/res/drawable/fa_viber.xml create mode 100644 mobile/src/main/res/drawable/fa_vimeo.xml create mode 100644 mobile/src/main/res/drawable/fa_vimeo_v.xml create mode 100644 mobile/src/main/res/drawable/fa_vine.xml create mode 100644 mobile/src/main/res/drawable/fa_vk.xml create mode 100644 mobile/src/main/res/drawable/fa_vnv.xml create mode 100644 mobile/src/main/res/drawable/fa_vuejs.xml create mode 100644 mobile/src/main/res/drawable/fa_weebly.xml create mode 100644 mobile/src/main/res/drawable/fa_weibo.xml create mode 100644 mobile/src/main/res/drawable/fa_weixin.xml create mode 100644 mobile/src/main/res/drawable/fa_whatsapp.xml create mode 100644 mobile/src/main/res/drawable/fa_whmcs.xml create mode 100644 mobile/src/main/res/drawable/fa_wikipedia_w.xml create mode 100644 mobile/src/main/res/drawable/fa_windows.xml create mode 100644 mobile/src/main/res/drawable/fa_wix.xml create mode 100644 mobile/src/main/res/drawable/fa_wolf_pack_battalion.xml create mode 100644 mobile/src/main/res/drawable/fa_wordpress.xml create mode 100644 mobile/src/main/res/drawable/fa_wordpress_simple.xml create mode 100644 mobile/src/main/res/drawable/fa_wpbeginner.xml create mode 100644 mobile/src/main/res/drawable/fa_wpexplorer.xml create mode 100644 mobile/src/main/res/drawable/fa_wpforms.xml create mode 100644 mobile/src/main/res/drawable/fa_xbox.xml create mode 100644 mobile/src/main/res/drawable/fa_xing.xml create mode 100644 mobile/src/main/res/drawable/fa_y_combinator.xml create mode 100644 mobile/src/main/res/drawable/fa_yahoo.xml create mode 100644 mobile/src/main/res/drawable/fa_yandex.xml create mode 100644 mobile/src/main/res/drawable/fa_yandex_international.xml create mode 100644 mobile/src/main/res/drawable/fa_yelp.xml create mode 100644 mobile/src/main/res/drawable/fa_yoast.xml create mode 100644 mobile/src/main/res/drawable/fa_youtube.xml create mode 100644 mobile/src/main/res/drawable/ic_about.xml create mode 100644 mobile/src/main/res/drawable/ic_add.xml create mode 100644 mobile/src/main/res/drawable/ic_bluetooth.xml create mode 100644 mobile/src/main/res/drawable/ic_check.xml create mode 100644 mobile/src/main/res/drawable/ic_copy.xml create mode 100644 mobile/src/main/res/drawable/ic_delete.xml create mode 100644 mobile/src/main/res/drawable/ic_down.xml create mode 100644 mobile/src/main/res/drawable/ic_freeotp.png create mode 100644 mobile/src/main/res/drawable/ic_hotp.xml create mode 100644 mobile/src/main/res/drawable/ic_lock.xml create mode 100644 mobile/src/main/res/drawable/ic_scan.xml create mode 100644 mobile/src/main/res/drawable/ic_share.xml create mode 100644 mobile/src/main/res/drawable/ic_totp.xml create mode 100644 mobile/src/main/res/drawable/ic_up.xml rename app/src/main/res/menu/token.xml => mobile/src/main/res/drawable/progress.xml (62%) create mode 100644 mobile/src/main/res/layout/activity_main.xml rename app/src/main/res/layout/scan.xml => mobile/src/main/res/layout/fragment_scan.xml (57%) rename app/src/main/res/menu/main.xml => mobile/src/main/res/layout/fragment_share.xml (57%) create mode 100644 mobile/src/main/res/layout/target.xml create mode 100644 mobile/src/main/res/layout/token.xml create mode 100644 mobile/src/main/res/menu/menu_main.xml create mode 100644 mobile/src/main/res/values-sw600dp/integers.xml create mode 100644 mobile/src/main/res/values/colors.xml rename app/src/main/res/values/tags.xml => mobile/src/main/res/values/dimens.xml (81%) rename app/src/main/res/values/attrs.xml => mobile/src/main/res/values/drawables.xml (72%) create mode 100644 mobile/src/main/res/values/integers.xml create mode 100644 mobile/src/main/res/values/strings.xml create mode 100644 mobile/src/main/res/values/styles.xml create mode 100644 mobile/src/test/java/org/fedorahosted/freeotp/Base32Test.java diff --git a/.travis.yml b/.travis.yml index b11fc38e..6e3d4d64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,5 @@ android: components: - tools - platform-tools - - build-tools-26.0.2 - - android-26 + - build-tools-27.0.3 + - android-27 diff --git a/COPYING.icons b/COPYING.icons deleted file mode 100644 index dfdcaf3a..00000000 --- a/COPYING.icons +++ /dev/null @@ -1,10 +0,0 @@ -Unless otherwise noted, icons used by this application are reproduced from -the Android Action Bar Icon Pack which is work created and shared by the -Android Open Source Project and used according to terms described in the -Creative Commons 2.5 Attribution License. - - * http://creativecommons.org/licenses/by/2.5/legalcode - * https://developer.android.com/license.html - -Original Icons: - * ic_launcher.png - Copyright 2013: Red Hat, Inc. diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index a141e4ab..00000000 --- a/app/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -apply plugin: 'com.android.application' - -dependencies { - compile 'com.google.zxing:core:3.3.0' - compile 'com.google.code.gson:gson:2.8.2' - compile 'com.squareup.picasso:picasso:2.5.2' - compile 'io.fotoapparat.fotoapparat:library:1.4.1' - testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:1.10.19' -} - -allprojects { - gradle.projectsEvaluated { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" - } - } -} - -android { - lintOptions { - abortOnError false - } - - testOptions { - unitTests.returnDefaultValues = true - } - - defaultConfig { - minSdkVersion 23 - targetSdkVersion 26 - } - - compileSdkVersion 26 // NOTE: update build-tools-* in .travis.yml - buildToolsVersion '26.0.2' // NOTE: update build-tools-* in .travis.yml -} diff --git a/app/src/main/ic_freeotp_logo-web.png b/app/src/main/ic_freeotp_logo-web.png deleted file mode 100644 index 540fb101133f8ff84125452dfe6729d40813a395..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46837 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
  • >$|k+ixR}2V=`UZWbErTeouTbC>9g+2)f~keVbl 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 Yetq^{pE0mr27n(kBTK`N`mWLc2Sc49`v3p{ diff --git a/app/src/main/java/com/google/android/apps/authenticator/Base32String.java b/app/src/main/java/com/google/android/apps/authenticator/Base32String.java deleted file mode 100644 index d5d55313..00000000 --- a/app/src/main/java/com/google/android/apps/authenticator/Base32String.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2009 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.apps.authenticator; - -import java.util.HashMap; -import java.util.Locale; - -/** - * Encodes arbitrary byte arrays as case-insensitive base-32 strings. - *

    - * The implementation is slightly different than in RFC 4648. During encoding, - * padding is not added, and during decoding the last incomplete chunk is not - * taken into account. The result is that multiple strings decode to the same - * byte array, for example, string of sixteen 7s ("7...7") and seventeen 7s both - * decode to the same byte array. - * TODO(sarvar): Revisit this encoding and whether this ambiguity needs fixing. - * - * @author sweis@google.com (Steve Weis) - * @author Neal Gafter - */ -public class Base32String { - // singleton - - private static final Base32String INSTANCE = - new Base32String("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); // RFC 4648/3548 - - static Base32String getInstance() { - return INSTANCE; - } - - // 32 alpha-numeric characters. - private String ALPHABET; - private char[] DIGITS; - private int MASK; - private int SHIFT; - private HashMap CHAR_MAP; - - static final String SEPARATOR = "-"; - - protected Base32String(String alphabet) { - this.ALPHABET = alphabet; - DIGITS = ALPHABET.toCharArray(); - MASK = DIGITS.length - 1; - SHIFT = Integer.numberOfTrailingZeros(DIGITS.length); - CHAR_MAP = new HashMap(); - for (int i = 0; i < DIGITS.length; i++) { - CHAR_MAP.put(DIGITS[i], i); - } - } - - public static byte[] decode(String encoded) throws DecodingException { - return getInstance().decodeInternal(encoded); - } - - protected byte[] decodeInternal(String encoded) throws DecodingException { - // Remove whitespace and separators - encoded = encoded.trim().replaceAll(SEPARATOR, "").replaceAll(" ", ""); - - // Remove padding. Note: the padding is used as hint to determine how many - // bits to decode from the last incomplete chunk (which is commented out - // below, so this may have been wrong to start with). - encoded = encoded.replaceFirst("[=]*$", ""); - - // Canonicalize to all upper case - encoded = encoded.toUpperCase(Locale.US); - if (encoded.length() == 0) { - return new byte[0]; - } - int encodedLength = encoded.length(); - int outLength = encodedLength * SHIFT / 8; - byte[] result = new byte[outLength]; - int buffer = 0; - int next = 0; - int bitsLeft = 0; - for (char c : encoded.toCharArray()) { - if (!CHAR_MAP.containsKey(c)) { - throw new DecodingException("Illegal character: " + c); - } - buffer <<= SHIFT; - buffer |= CHAR_MAP.get(c) & MASK; - bitsLeft += SHIFT; - if (bitsLeft >= 8) { - result[next++] = (byte) (buffer >> (bitsLeft - 8)); - bitsLeft -= 8; - } - } - // We'll ignore leftover bits for now. - // - // if (next != outLength || bitsLeft >= SHIFT) { - // throw new DecodingException("Bits left: " + bitsLeft); - // } - return result; - } - - public static String encode(byte[] data) { - return getInstance().encodeInternal(data); - } - - protected String encodeInternal(byte[] data) { - if (data.length == 0) { - return ""; - } - - // SHIFT is the number of bits per output character, so the length of the - // output is the length of the input multiplied by 8/SHIFT, rounded up. - if (data.length >= (1 << 28)) { - // The computation below will fail, so don't do it. - throw new IllegalArgumentException(); - } - - int outputLength = (data.length * 8 + SHIFT - 1) / SHIFT; - StringBuilder result = new StringBuilder(outputLength); - - int buffer = data[0]; - int next = 1; - int bitsLeft = 8; - while (bitsLeft > 0 || next < data.length) { - if (bitsLeft < SHIFT) { - if (next < data.length) { - buffer <<= 8; - buffer |= (data[next++] & 0xff); - bitsLeft += 8; - } else { - int pad = SHIFT - bitsLeft; - buffer <<= pad; - bitsLeft += pad; - } - } - int index = MASK & (buffer >> (bitsLeft - SHIFT)); - bitsLeft -= SHIFT; - result.append(DIGITS[index]); - } - return result.toString(); - } - - @Override - // enforce that this class is a singleton - public Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - - public static class DecodingException extends Exception { - public DecodingException(String message) { - super(message); - } - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/AboutActivity.java b/app/src/main/java/org/fedorahosted/freeotp/AboutActivity.java deleted file mode 100644 index 22715d89..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/AboutActivity.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.app.Activity; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.os.Bundle; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.widget.TextView; - -public class AboutActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.about); - } - - @Override - @SuppressWarnings("deprecation") - //suppress because Html.fromHtml(String, int) requires minSdkVersion 24 - public void onStart() { - super.onStart(); - - Resources res = getResources(); - TextView tv; - - try { - PackageManager pm = getPackageManager(); - PackageInfo info = pm.getPackageInfo(getPackageName(), 0); - String version = res.getString(R.string.about_version, info.versionName, info.versionCode); - tv = findViewById(R.id.about_version); - tv.setText(version); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - - String apache2 = res.getString(R.string.link_apache2); - String license = res.getString(R.string.about_license, apache2); - tv = findViewById(R.id.about_license); - tv.setMovementMethod(LinkMovementMethod.getInstance()); - tv.setText(Html.fromHtml(license)); - - String lwebsite = res.getString(R.string.link_website); - String swebsite = res.getString(R.string.about_website, lwebsite); - tv = findViewById(R.id.about_website); - tv.setMovementMethod(LinkMovementMethod.getInstance()); - tv.setText(Html.fromHtml(swebsite)); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/BaseReorderableAdapter.java b/app/src/main/java/org/fedorahosted/freeotp/BaseReorderableAdapter.java deleted file mode 100644 index b0bfe229..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/BaseReorderableAdapter.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.content.ClipData; -import android.view.DragEvent; -import android.view.View; -import android.view.View.DragShadowBuilder; -import android.view.View.OnDragListener; -import android.view.View.OnLongClickListener; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -public abstract class BaseReorderableAdapter extends BaseAdapter { - private class Reference { - public Reference(T t) { - reference = t; - } - - T reference; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - int type = getItemViewType(position); - convertView = createView(parent, type); - - convertView.setOnDragListener(new OnDragListener() { - @Override - @SuppressWarnings("unchecked") - //unavoidable generic type problems -> Reference - public boolean onDrag(View dstView, DragEvent event) { - Reference ref = (Reference) event.getLocalState(); - final View srcView = ref.reference; - - switch (event.getAction()) { - case DragEvent.ACTION_DRAG_ENTERED: - srcView.setVisibility(View.VISIBLE); - dstView.setVisibility(View.INVISIBLE); - - move(((Integer) srcView.getTag(R.id.reorder_key)), - ((Integer) dstView.getTag(R.id.reorder_key))); - ref.reference = dstView; - break; - - case DragEvent.ACTION_DRAG_ENDED: - srcView.post(new Runnable() { - @Override - public void run() { - srcView.setVisibility(View.VISIBLE); - } - }); - break; - } - - return true; - } - }); - - convertView.setOnLongClickListener(new OnLongClickListener() { - @Override - public boolean onLongClick(final View view) { - // Force a reset of any states - notifyDataSetChanged(); - - // Start the drag on the main loop to allow - // the above state reset to settle. - view.post(new Runnable() { - @Override - @SuppressWarnings("deprecation") - //startDrag() --> suppress deprecation because startDragAndDrop() requires minSdkVersion 24 - public void run() { - ClipData data = ClipData.newPlainText("", ""); - DragShadowBuilder sb = new View.DragShadowBuilder(view); - view.startDrag(data, sb, new Reference<>(view), 0); - } - }); - - return true; - } - }); - } - - convertView.setTag(R.id.reorder_key, position); - bindView(convertView, position); - return convertView; - } - - protected abstract void move(int fromPosition, int toPosition); - - protected abstract void bindView(View view, int position); - - protected abstract View createView(ViewGroup parent, int type); -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/MainActivity.java b/app/src/main/java/org/fedorahosted/freeotp/MainActivity.java deleted file mode 100644 index 4f2444a8..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/MainActivity.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * Authors: Siemens AG - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * Copyright (C) 2017 Max Wittig, Siemens AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Portions Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.Manifest; -import android.widget.Toast; - -import org.fedorahosted.freeotp.add.ScanActivity; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.IntentFilter; -import android.database.DataSetObserver; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.WindowManager.LayoutParams; -import android.widget.GridView; - -public class MainActivity extends Activity implements OnMenuItemClickListener { - private TokenAdapter mTokenAdapter; - public static final String ACTION_IMAGE_SAVED = "org.fedorahosted.freeotp.ACTION_IMAGE_SAVED"; - private DataSetObserver mDataSetObserver; - private final int PERMISSIONS_REQUEST_CAMERA = 1; - private RefreshListBroadcastReceiver receiver; - - private class RefreshListBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - mTokenAdapter.notifyDataSetChanged(); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - onNewIntent(getIntent()); - setContentView(R.layout.main); - - mTokenAdapter = new TokenAdapter(this); - receiver = new RefreshListBroadcastReceiver(); - registerReceiver(receiver, new IntentFilter(ACTION_IMAGE_SAVED)); - ((GridView) findViewById(R.id.grid)).setAdapter(mTokenAdapter); - - // Don't permit screenshots since these might contain OTP codes. - getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE); - - mDataSetObserver = new DataSetObserver() { - @Override - public void onChanged() { - super.onChanged(); - if (mTokenAdapter.getCount() == 0) - findViewById(android.R.id.empty).setVisibility(View.VISIBLE); - else - findViewById(android.R.id.empty).setVisibility(View.GONE); - } - }; - mTokenAdapter.registerDataSetObserver(mDataSetObserver); - } - - @Override - protected void onResume() { - super.onResume(); - mTokenAdapter.notifyDataSetChanged(); - } - - @Override - protected void onPause() { - super.onPause(); - mTokenAdapter.notifyDataSetChanged(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mTokenAdapter.unregisterDataSetObserver(mDataSetObserver); - unregisterReceiver(receiver); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.main, menu); - menu.findItem(R.id.action_scan).setVisible(ScanActivity.hasCamera(this)); - menu.findItem(R.id.action_scan).setOnMenuItemClickListener(this); - menu.findItem(R.id.action_about).setOnMenuItemClickListener(this); - return true; - } - - private void tryOpenCamera() { - if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CAMERA); - } - else { - // permission is already granted - openCamera(); - } - } - - private void openCamera() { - startActivity(new Intent(this, ScanActivity.class)); - overridePendingTransition(R.anim.fadein, R.anim.fadeout); - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_scan: - tryOpenCamera(); - return true; - - case R.id.action_about: - startActivity(new Intent(this, AboutActivity.class)); - return true; - } - - return false; - } - - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], int[] grantResults) { - switch (requestCode) { - case PERMISSIONS_REQUEST_CAMERA: { - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - openCamera(); - } else { - Toast.makeText(MainActivity.this, R.string.error_permission_camera_open, Toast.LENGTH_LONG).show(); - } - return; - } - } - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - Uri uri = intent.getData(); - if (uri != null) { - try { - TokenPersistence.saveAsync(this, new Token(uri)); - } catch (Token.TokenUriInvalidException e) { - e.printStackTrace(); - } - } - - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/ProgressCircle.java b/app/src/main/java/org/fedorahosted/freeotp/ProgressCircle.java deleted file mode 100644 index ed7bad62..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/ProgressCircle.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.content.Context; -import android.content.res.Resources.Theme; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Rect; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.View; - -public class ProgressCircle extends View { - private Paint mPaint; - private RectF mRectF; - private Rect mRect; - private int mProgress; - private int mMax; - private boolean mHollow; - private float mPadding; - private float mStrokeWidth; - - public ProgressCircle(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setup(context, attrs); - } - - public ProgressCircle(Context context, AttributeSet attrs) { - super(context, attrs); - setup(context, attrs); - } - - public ProgressCircle(Context context) { - super(context); - setup(context, null); - } - - private void setup(Context context, AttributeSet attrs) { - DisplayMetrics dm = getResources().getDisplayMetrics(); - mPadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, dm); - mStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm); - - mRectF = new RectF(); - mRect = new Rect(); - - mPaint = new Paint(); - mPaint.setARGB(0x99, 0x33, 0x33, 0x33); - mPaint.setAntiAlias(true); - mPaint.setStrokeCap(Paint.Cap.BUTT); - - if (attrs != null) { - Theme t = context.getTheme(); - TypedArray a = t.obtainStyledAttributes(attrs, R.styleable.ProgressCircle, 0, 0); - - try { - setMax(a.getInteger(R.styleable.ProgressCircle_max, 100)); - setHollow(a.getBoolean(R.styleable.ProgressCircle_hollow, false)); - } finally { - a.recycle(); - } - } - } - - public void setMax(int max) { - this.mMax = max; - } - - public int getMax() { - return mMax; - } - - public void setHollow(boolean hollow) { - mHollow = hollow; - mPaint.setStyle(hollow ? Style.STROKE : Style.FILL); - mPaint.setStrokeWidth(hollow ? mStrokeWidth : 0); - } - - public boolean getHollow() { - return mHollow; - } - - public void setProgress(int progress) { - mProgress = progress; - - int percent = mProgress * 100 / getMax(); - if (percent > 25 || mProgress == 0) - mPaint.setARGB(0x99, 0x33, 0x33, 0x33); - else - mPaint.setARGB(0x99, 0xff, 0xe0 * percent / 25, 0x00); - - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - getDrawingRect(mRect); - - mRect.left += getPaddingLeft() + mPadding; - mRect.top += getPaddingTop() + mPadding; - mRect.right -= getPaddingRight() + mPadding; - mRect.bottom -= getPaddingBottom() + mPadding; - mRectF.set(mRect); - - canvas.drawArc(mRectF, -90, mProgress * 360 / getMax(), !mHollow, mPaint); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/Token.java b/app/src/main/java/org/fedorahosted/freeotp/Token.java deleted file mode 100644 index e6c8ac0a..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/Token.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import java.io.File; -import java.nio.ByteBuffer; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import android.net.Uri; - -import com.google.android.apps.authenticator.Base32String; -import com.google.android.apps.authenticator.Base32String.DecodingException; - -public class Token { - public static class TokenUriInvalidException extends Exception { - private static final long serialVersionUID = -1108624734612362345L; - } - - public static enum TokenType { - HOTP, TOTP - } - - private static char[] STEAMCHARS = new char[] { - '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', - 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', - 'R', 'T', 'V', 'W', 'X', 'Y'}; - - private String issuerInt; - private String issuerExt; - private String issuerAlt; - private String label; - private String labelAlt; - private String image; - private String imageAlt; - private TokenType type; - private String algo; - private byte[] secret; - private int digits; - private long counter; - private int period; - - private Token(Uri uri, boolean internal) throws TokenUriInvalidException { - validateTokenURI(uri); - - String path = uri.getPath(); - // Strip the path of its leading '/' - path = path.replaceFirst("/",""); - - if (path.length() == 0) - throw new TokenUriInvalidException(); - - int i = path.indexOf(':'); - issuerExt = i < 0 ? "" : path.substring(0, i); - issuerInt = uri.getQueryParameter("issuer"); - label = path.substring(i >= 0 ? i + 1 : 0); - - algo = uri.getQueryParameter("algorithm"); - if (algo == null) - algo = "sha1"; - algo = algo.toUpperCase(Locale.US); - try { - Mac.getInstance("Hmac" + algo); - } catch (NoSuchAlgorithmException e1) { - throw new TokenUriInvalidException(); - } - - try { - String d = uri.getQueryParameter("digits"); - if (d == null) - d = "6"; - digits = Integer.parseInt(d); - if (!issuerExt.equals("Steam") && digits != 6 && digits != 8) - throw new TokenUriInvalidException(); - } catch (NumberFormatException e) { - throw new TokenUriInvalidException(); - } - - try { - String p = uri.getQueryParameter("period"); - if (p == null) - p = "30"; - period = Integer.parseInt(p); - period = (period > 0) ? period : 30; // Avoid divide-by-zero - } catch (NumberFormatException e) { - throw new TokenUriInvalidException(); - } - - if (type == TokenType.HOTP) { - try { - String c = uri.getQueryParameter("counter"); - if (c == null) - c = "0"; - counter = Long.parseLong(c); - } catch (NumberFormatException e) { - throw new TokenUriInvalidException(); - } - } - - try { - String s = uri.getQueryParameter("secret"); - secret = Base32String.decode(s); - } catch (DecodingException e) { - throw new TokenUriInvalidException(); - } catch (NullPointerException e) { - throw new TokenUriInvalidException(); - } - - image = uri.getQueryParameter("image"); - - if (internal) { - setIssuer(uri.getQueryParameter("issueralt")); - setLabel(uri.getQueryParameter("labelalt")); - } - } - - private void validateTokenURI(Uri uri) throws TokenUriInvalidException{ - if (uri == null) throw new TokenUriInvalidException(); - - if (uri.getScheme() == null || !uri.getScheme().equals("otpauth")){ - throw new TokenUriInvalidException(); - } - - if (uri.getAuthority() == null) throw new TokenUriInvalidException(); - - if (uri.getAuthority().equals("totp")) { - type = TokenType.TOTP; - } else if (uri.getAuthority().equals("hotp")) - type = TokenType.HOTP; - else { - throw new TokenUriInvalidException(); - } - - if (uri.getPath() == null) throw new TokenUriInvalidException(); - } - - private String getHOTP(long counter) { - // Encode counter in network byte order - ByteBuffer bb = ByteBuffer.allocate(8); - bb.putLong(counter); - - // Create digits divisor - int div = 1; - for (int i = digits; i > 0; i--) - div *= 10; - - // Create the HMAC - try { - Mac mac = Mac.getInstance("Hmac" + algo); - mac.init(new SecretKeySpec(secret, "Hmac" + algo)); - - // Do the hashing - byte[] digest = mac.doFinal(bb.array()); - - // Truncate - int binary; - int off = digest[digest.length - 1] & 0xf; - binary = (digest[off] & 0x7f) << 0x18; - binary |= (digest[off + 1] & 0xff) << 0x10; - binary |= (digest[off + 2] & 0xff) << 0x08; - binary |= (digest[off + 3] & 0xff); - - String hotp = ""; - if (issuerExt.equals("Steam")) { - for (int i = 0; i < digits; i++) { - hotp += STEAMCHARS[binary % STEAMCHARS.length]; - binary /= STEAMCHARS.length; - } - } else { - binary = binary % div; - - // Zero pad - hotp = Integer.toString(binary); - while (hotp.length() != digits) - hotp = "0" + hotp; - } - - return hotp; - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - - return ""; - } - - public Token(String uri, boolean internal) throws TokenUriInvalidException { - this(Uri.parse(uri), internal); - } - - public Token(Uri uri) throws TokenUriInvalidException { - this(uri, false); - } - - public Token(String uri) throws TokenUriInvalidException { - this(Uri.parse(uri)); - } - - public String getID() { - String id; - if (issuerInt != null && !issuerInt.equals("")) - id = issuerInt + ":" + label; - else if (issuerExt != null && !issuerExt.equals("")) - id = issuerExt + ":" + label; - else - id = label; - - return id; - } - - // NOTE: This changes internal data. You MUST save the token immediately. - public void setIssuer(String issuer) { - issuerAlt = (issuer == null || issuer.equals(this.issuerExt)) ? null : issuer; - } - - public String getIssuer() { - if (issuerAlt != null) - return issuerAlt; - return issuerExt != null ? issuerExt : ""; - } - - // NOTE: This changes internal data. You MUST save the token immediately. - public void setLabel(String label) { - labelAlt = (label == null || label.equals(this.label)) ? null : label; - } - - public String getLabel() { - if (labelAlt != null) - return labelAlt; - return label != null ? label : ""; - } - - public int getDigits() { - return digits; - } - - // NOTE: This may change internal data. You MUST save the token immediately. - public TokenCode generateCodes() { - long cur = System.currentTimeMillis(); - - switch (type) { - case HOTP: - return new TokenCode(getHOTP(counter++), cur, cur + (period * 1000)); - - case TOTP: - long counter = cur / 1000 / period; - return new TokenCode(getHOTP(counter + 0), - (counter + 0) * period * 1000, - (counter + 1) * period * 1000, - new TokenCode(getHOTP(counter + 1), - (counter + 1) * period * 1000, - (counter + 2) * period * 1000)); - } - - return null; - } - - public TokenType getType() { - return type; - } - - public Uri toUri() { - String issuerLabel = !issuerExt.equals("") ? issuerExt + ":" + label : label; - - Uri.Builder builder = new Uri.Builder().scheme("otpauth").path(issuerLabel) - .appendQueryParameter("secret", Base32String.encode(secret)) - .appendQueryParameter("issuer", issuerInt == null ? issuerExt : issuerInt) - .appendQueryParameter("algorithm", algo) - .appendQueryParameter("digits", Integer.toString(digits)) - .appendQueryParameter("period", Integer.toString(period)); - - switch (type) { - case HOTP: - builder.authority("hotp"); - builder.appendQueryParameter("counter", Long.toString(counter + 1)); - break; - case TOTP: - builder.authority("totp"); - break; - } - - return builder.build(); - } - - @Override - public String toString() { - return toUri().toString(); - } - - /** - * delete image, which is attached to the token from storage - */ - public void deleteImage() { - Uri imageUri = getImage(); - if (imageUri != null) { - File image = new File(imageUri.getPath()); - if (image.exists()) - image.delete(); - } - } - - public void setImage(Uri image) { - //delete old token image, before assigning the new one - deleteImage(); - - imageAlt = null; - if (image == null) - return; - - if (this.image == null || !Uri.parse(this.image).equals(image)) - imageAlt = image.toString(); - } - - public Uri getImage() { - if (imageAlt != null) - return Uri.parse(imageAlt); - - if (image != null) - return Uri.parse(image); - - return null; - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/TokenAdapter.java b/app/src/main/java/org/fedorahosted/freeotp/TokenAdapter.java deleted file mode 100644 index cdf1c7a4..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/TokenAdapter.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.database.DataSetObserver; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.PopupMenu; -import android.widget.Toast; - -import org.fedorahosted.freeotp.edit.DeleteActivity; -import org.fedorahosted.freeotp.edit.EditActivity; - -import java.util.HashMap; -import java.util.Map; - -public class TokenAdapter extends BaseReorderableAdapter { - private final TokenPersistence mTokenPersistence; - private final LayoutInflater mLayoutInflater; - private final ClipboardManager mClipMan; - private final Map mTokenCodes; - - public TokenAdapter(Context ctx) { - mTokenPersistence = new TokenPersistence(ctx); - mLayoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mClipMan = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); - mTokenCodes = new HashMap<>(); - registerDataSetObserver(new DataSetObserver() { - @Override - public void onChanged() { - mTokenCodes.clear(); - } - - @Override - public void onInvalidated() { - mTokenCodes.clear(); - } - }); - } - - @Override - public int getCount() { - return mTokenPersistence.length(); - } - - @Override - public Token getItem(int position) { - return mTokenPersistence.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - protected void move(int fromPosition, int toPosition) { - mTokenPersistence.move(fromPosition, toPosition); - notifyDataSetChanged(); - } - - @Override - protected void bindView(View view, final int position) { - final Context ctx = view.getContext(); - TokenLayout tl = (TokenLayout) view; - Token token = getItem(position); - - tl.bind(token, R.menu.token, new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - Intent i; - - switch (item.getItemId()) { - case R.id.action_edit: - i = new Intent(ctx, EditActivity.class); - i.putExtra(EditActivity.EXTRA_POSITION, position); - ctx.startActivity(i); - break; - - case R.id.action_delete: - i = new Intent(ctx, DeleteActivity.class); - i.putExtra(DeleteActivity.EXTRA_POSITION, position); - ctx.startActivity(i); - break; - } - - return true; - } - }); - - tl.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - TokenPersistence tp = new TokenPersistence(ctx); - - // Increment the token. - Token token = tp.get(position); - TokenCode codes = token.generateCodes(); - //save token. Image wasn't changed here, so just save it in sync - new TokenPersistence(ctx).save(token); - - // Copy code to clipboard. - mClipMan.setPrimaryClip(ClipData.newPlainText(null, codes.getCurrentCode())); - Toast.makeText(v.getContext().getApplicationContext(), - R.string.code_copied, - Toast.LENGTH_SHORT).show(); - - mTokenCodes.put(token.getID(), codes); - ((TokenLayout) v).start(token.getType(), codes, true); - } - }); - - TokenCode tc = mTokenCodes.get(token.getID()); - if (tc != null && tc.getCurrentCode() != null) - tl.start(token.getType(), tc, false); - } - - @Override - protected View createView(ViewGroup parent, int type) { - return mLayoutInflater.inflate(R.layout.token, parent, false); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/TokenCode.java b/app/src/main/java/org/fedorahosted/freeotp/TokenCode.java deleted file mode 100644 index 772e59b4..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/TokenCode.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2014 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -public class TokenCode { - private final String mCode; - private final long mStart; - private final long mUntil; - private TokenCode mNext; - - public TokenCode(String code, long start, long until) { - mCode = code; - mStart = start; - mUntil = until; - } - - public TokenCode(TokenCode prev, String code, long start, long until) { - this(code, start, until); - prev.mNext = this; - } - - public TokenCode(String code, long start, long until, TokenCode next) { - this(code, start, until); - mNext = next; - } - - public String getCurrentCode() { - TokenCode active = getActive(System.currentTimeMillis()); - if (active == null) - return null; - return active.mCode; - } - - public int getTotalProgress() { - long cur = System.currentTimeMillis(); - long total = getLast().mUntil - mStart; - long state = total - (cur - mStart); - return (int) (state * 1000 / total); - } - - public int getCurrentProgress() { - long cur = System.currentTimeMillis(); - TokenCode active = getActive(cur); - if (active == null) - return 0; - - long total = active.mUntil - active.mStart; - long state = total - (cur - active.mStart); - return (int) (state * 1000 / total); - } - - private TokenCode getActive(long curTime) { - if (curTime >= mStart && curTime < mUntil) - return this; - - if (mNext == null) - return null; - - return this.mNext.getActive(curTime); - } - - private TokenCode getLast() { - if (mNext == null) - return this; - return this.mNext.getLast(); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/TokenLayout.java b/app/src/main/java/org/fedorahosted/freeotp/TokenLayout.java deleted file mode 100644 index 64751080..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/TokenLayout.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.PopupMenu; -import android.widget.TextView; - -import com.squareup.picasso.Picasso; - -public class TokenLayout extends FrameLayout implements View.OnClickListener, Runnable { - private ProgressCircle mProgressInner; - private ProgressCircle mProgressOuter; - private ImageView mImage; - private TextView mCode; - private TextView mIssuer; - private TextView mLabel; - private ImageView mMenu; - private PopupMenu mPopupMenu; - - private TokenCode mCodes; - private Token.TokenType mType; - private String mPlaceholder; - private long mStartTime; - - public TokenLayout(Context context) { - super(context); - } - - public TokenLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public TokenLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - mProgressInner = findViewById(R.id.progressInner); - mProgressOuter = findViewById(R.id.progressOuter); - mImage = findViewById(R.id.image); - mCode = findViewById(R.id.code); - mIssuer = findViewById(R.id.issuer); - mLabel = findViewById(R.id.label); - mMenu = findViewById(R.id.menu); - - mPopupMenu = new PopupMenu(getContext(), mMenu); - mMenu.setOnClickListener(this); - } - - public void bind(Token token, int menu, PopupMenu.OnMenuItemClickListener micl) { - mCodes = null; - - // Setup menu. - mPopupMenu.getMenu().clear(); - mPopupMenu.getMenuInflater().inflate(menu, mPopupMenu.getMenu()); - mPopupMenu.setOnMenuItemClickListener(micl); - - // Cancel all active animations. - setEnabled(true); - removeCallbacks(this); - mImage.clearAnimation(); - mProgressInner.clearAnimation(); - mProgressOuter.clearAnimation(); - mProgressInner.setVisibility(View.GONE); - mProgressOuter.setVisibility(View.GONE); - - // Get the code placeholder. - char[] placeholder = new char[token.getDigits()]; - for (int i = 0; i < placeholder.length; i++) - placeholder[i] = '-'; - mPlaceholder = new String(placeholder); - - // Show the image. - Picasso.with(getContext()) - .load(token.getImage()) - .placeholder(R.mipmap.ic_freeotp_logo_foreground) - .fit() - .into(mImage); - - // Set the labels. - mLabel.setText(token.getLabel()); - mIssuer.setText(token.getIssuer()); - mCode.setText(mPlaceholder); - if (mIssuer.getText().length() == 0) { - mIssuer.setText(token.getLabel()); - mLabel.setVisibility(View.GONE); - } else { - mLabel.setVisibility(View.VISIBLE); - } - } - - private void animate(View view, int anim, boolean animate) { - Animation a = AnimationUtils.loadAnimation(view.getContext(), anim); - if (!animate) - a.setDuration(0); - view.startAnimation(a); - } - - public void start(Token.TokenType type, TokenCode codes, boolean animate) { - mCodes = codes; - mType = type; - - // Start animations. - mProgressInner.setVisibility(View.VISIBLE); - animate(mProgressInner, R.anim.fadein, animate); - animate(mImage, R.anim.token_image_fadeout, animate); - - // Handle type-specific UI. - switch (type) { - case HOTP: - setEnabled(false); - break; - case TOTP: - mProgressOuter.setVisibility(View.VISIBLE); - animate(mProgressOuter, R.anim.fadein, animate); - break; - } - - mStartTime = System.currentTimeMillis(); - post(this); - } - - @Override - public void onClick(View v) { - mPopupMenu.show(); - } - - @Override - public void run() { - // Get the current data - String code = mCodes == null ? null : mCodes.getCurrentCode(); - if (code != null) { - // Determine whether to enable/disable the view. - if (!isEnabled()) - setEnabled(System.currentTimeMillis() - mStartTime > 5000); - - // Update the fields - mCode.setText(code); - mProgressInner.setProgress(mCodes.getCurrentProgress()); - if (mType != Token.TokenType.HOTP) - mProgressOuter.setProgress(mCodes.getTotalProgress()); - - postDelayed(this, 100); - return; - } - - mCode.setText(mPlaceholder); - mProgressInner.setVisibility(View.GONE); - mProgressOuter.setVisibility(View.GONE); - animate(mImage, R.anim.token_image_fadein, true); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/TokenPersistence.java b/app/src/main/java/org/fedorahosted/freeotp/TokenPersistence.java deleted file mode 100644 index 253ac158..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/TokenPersistence.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.AsyncTask; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; -import com.google.gson.reflect.TypeToken; -import com.squareup.picasso.Picasso; - -import org.fedorahosted.freeotp.Token.TokenUriInvalidException; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; - -public class TokenPersistence { - private static final String NAME = "tokens"; - private static final String ORDER = "tokenOrder"; - private final SharedPreferences prefs; - private final Gson gson; - - private List getTokenOrder() { - Type type = new TypeToken>(){}.getType(); - String str = prefs.getString(ORDER, "[]"); - List order = gson.fromJson(str, type); - return order == null ? new LinkedList() : order; - } - - private SharedPreferences.Editor setTokenOrder(List order) { - return prefs.edit().putString(ORDER, gson.toJson(order)); - } - - public TokenPersistence(Context ctx) { - prefs = ctx.getApplicationContext().getSharedPreferences(NAME, Context.MODE_PRIVATE); - gson = new Gson(); - } - - public int length() { - return getTokenOrder().size(); - } - - public boolean tokenExists(Token token) { - return prefs.contains(token.getID()); - } - - public Token get(int position) { - String key = getTokenOrder().get(position); - String str = prefs.getString(key, null); - - try { - return gson.fromJson(str, Token.class); - } catch (JsonSyntaxException jse) { - // Backwards compatibility for URL-based persistence. - try { - return new Token(str, true); - } catch (TokenUriInvalidException tuie) { - tuie.printStackTrace(); - } - } - - return null; - } - - public void save(Token token) { - String key = token.getID(); - - //if token exists, just update it - if (prefs.contains(key)) { - prefs.edit().putString(token.getID(), gson.toJson(token)).apply(); - return; - } - - List order = getTokenOrder(); - order.add(0, key); - setTokenOrder(order).putString(key, gson.toJson(token)).apply(); - } - - public void move(int fromPosition, int toPosition) { - if (fromPosition == toPosition) - return; - - List order = getTokenOrder(); - if (fromPosition < 0 || fromPosition > order.size()) - return; - if (toPosition < 0 || toPosition > order.size()) - return; - - order.add(toPosition, order.remove(fromPosition)); - setTokenOrder(order).apply(); - } - - public void delete(int position) { - List order = getTokenOrder(); - String key = order.remove(position); - setTokenOrder(order).remove(key).apply(); - } - - /** - * Save token async, because Image needs to be downloaded/copied to storage - * @param context Application Context - * @param token Token (with Image, Image will be saved by the async task) - */ - public static void saveAsync(Context context, final Token token) { - File outFile = null; - if(token.getImage() != null) - outFile = new File(context.getFilesDir(), "img_" + UUID.randomUUID().toString() + ".png"); - new SaveTokenTask().execute(new TaskParams(token, outFile, context)); - } - - /** - * Data class for SaveTokenTask - */ - private static class ReturnParams { - private final Token token; - private final Context context; - - public ReturnParams(Token token, Context context) { - this.token = token; - this.context = context; - } - - public Token getToken() { - return token; - } - - public Context getContext() { - return context; - } - } - - /** - * Data class for SaveTokenTask - */ - private static class TaskParams { - private final File outFile; - private final Context mContext; - private final Token token; - - public TaskParams(Token token, File outFile, Context mContext) { - this.token = token; - this.outFile = outFile; - this.mContext = mContext; - } - - public Context getContext() { - return mContext; - } - - public Token getToken() { - return token; - } - - public File getOutFile() { - return outFile; - } - } - - /** - * Downloads/copies images to FreeOTP storage - * Saves token in PostExecute - */ - private static class SaveTokenTask extends AsyncTask { - protected ReturnParams doInBackground(TaskParams... params) { - final TaskParams taskParams = params[0]; - if(taskParams.getToken().getImage() != null) { - try { - Bitmap bitmap = Picasso.with(taskParams.getContext()) - .load(taskParams.getToken() - .getImage()) - .resize(200, 200) // it's just an icon - .onlyScaleDown() //resize image, if bigger than 200x200 - .get(); - File outFile = taskParams.getOutFile(); - //saveAsync image - FileOutputStream out = new FileOutputStream(outFile); - bitmap.compress(Bitmap.CompressFormat.PNG, 50, out); - out.close(); - taskParams.getToken().setImage(Uri.fromFile(outFile)); - } catch (IOException e) { - e.printStackTrace(); - //set image to null to prevent internet link in image, in case image - //was scanned, when no connection existed - taskParams.getToken().setImage(null); - } - } - return new ReturnParams(taskParams.getToken(), taskParams.getContext()); - } - - @Override - protected void onPostExecute(ReturnParams returnParams) { - super.onPostExecute(returnParams); - //we downloaded the image, now save it normally - new TokenPersistence(returnParams.getContext()).save(returnParams.getToken()); - //refresh TokenAdapter - returnParams.context.sendBroadcast(new Intent(MainActivity.ACTION_IMAGE_SAVED)); - } - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/add/ScanActivity.java b/app/src/main/java/org/fedorahosted/freeotp/add/ScanActivity.java deleted file mode 100644 index e1b37565..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/add/ScanActivity.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * Authors: Siemens AG - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * Copyright (C) 2017 Max Wittig, Siemens AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp.add; - -import org.fedorahosted.freeotp.R; -import org.fedorahosted.freeotp.Token; -import org.fedorahosted.freeotp.TokenPersistence; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.view.View; -import android.widget.ImageView; -import com.squareup.picasso.Callback; -import com.squareup.picasso.Picasso; -import io.fotoapparat.Fotoapparat; -import io.fotoapparat.parameter.ScaleType; -import io.fotoapparat.parameter.selector.FocusModeSelectors; -import io.fotoapparat.view.CameraView; -import static io.fotoapparat.parameter.selector.FocusModeSelectors.autoFocus; -import static io.fotoapparat.parameter.selector.FocusModeSelectors.fixed; -import static io.fotoapparat.parameter.selector.LensPositionSelectors.back; -import static io.fotoapparat.parameter.selector.Selectors.firstAvailable; -import static io.fotoapparat.parameter.selector.SizeSelectors.biggestSize; - -public class ScanActivity extends Activity { - private Fotoapparat fotoapparat; - private static ScanBroadcastReceiver receiver; - - public class ScanBroadcastReceiver extends BroadcastReceiver { - public static final String ACTION = "org.fedorahosted.freeotp.ACTION_CODE_SCANNED"; - - @Override - public void onReceive(Context context, Intent intent) { - String text = intent.getStringExtra("scanResult"); - addTokenAndFinish(text); - } - } - - public static boolean hasCamera(Context context) { - PackageManager pm = context.getPackageManager(); - return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA); - } - - private void addTokenAndFinish(String text) { - Token token = null; - try { - token = new Token(text); - } catch (Token.TokenUriInvalidException e) { - e.printStackTrace(); - } - - //do not receive any more broadcasts - this.unregisterReceiver(receiver); - - //check if token already exists - if (new TokenPersistence(ScanActivity.this).tokenExists(token)) { - finish(); - return; - } - - TokenPersistence.saveAsync(ScanActivity.this, token); - if (token == null || token.getImage() == null) { - finish(); - return; - } - - final ImageView image = (ImageView) findViewById(R.id.image); - Picasso.with(ScanActivity.this) - .load(token.getImage()) - .placeholder(R.drawable.scan) - .into(image, new Callback() { - @Override - public void onSuccess() { - findViewById(R.id.progress).setVisibility(View.INVISIBLE); - image.setAlpha(0.9f); - image.postDelayed(new Runnable() { - @Override - public void run() { - finish(); - } - }, 2000); - } - - @Override - public void onError() { - finish(); - } - }); - } - - @Override - public void onDestroy() { - super.onDestroy(); - try { - this.unregisterReceiver(receiver); - } - catch (IllegalArgumentException e) { - // catch exception, when trying to unregister receiver again - // there seems to be no way to check, if receiver if registered - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - receiver = new ScanBroadcastReceiver(); - this.registerReceiver(receiver, new IntentFilter(ScanBroadcastReceiver.ACTION)); - setContentView(R.layout.scan); - CameraView cameraView = findViewById(R.id.camera_view); - - fotoapparat = Fotoapparat - .with(this) - .into(cameraView) - .previewScaleType(ScaleType.CENTER_CROP) - .photoSize(biggestSize()) - .lensPosition(back()) - .focusMode(firstAvailable( - FocusModeSelectors.continuousFocus(), - autoFocus(), - fixed() - )) - .frameProcessor(new ScanFrameProcessor(this)) - .build(); - } - - @Override - protected void onStart() { - super.onStart(); - fotoapparat.start(); - } - - @Override - protected void onStop() { - super.onStop(); - fotoapparat.stop(); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/add/ScanFrameProcessor.java b/app/src/main/java/org/fedorahosted/freeotp/add/ScanFrameProcessor.java deleted file mode 100644 index 13b4cd70..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/add/ScanFrameProcessor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * Authors: Siemens AG - * - * Copyright (C) 2013 Nathaniel McCallum, Red Hat - * Copyright (C) 2017 Max Wittig, Siemens AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp.add; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import com.google.zxing.*; -import com.google.zxing.common.HybridBinarizer; -import com.google.zxing.qrcode.QRCodeReader; -import io.fotoapparat.preview.Frame; -import io.fotoapparat.preview.FrameProcessor; - -public class ScanFrameProcessor implements FrameProcessor { - - private static Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper()); - private Reader reader; - private Context scanActivityContext; - - public ScanFrameProcessor(Context context) { - scanActivityContext = context; - } - - @Override - public void processFrame(final Frame frame) { - MAIN_THREAD_HANDLER.post(new Runnable() { - @Override - public void run() { - try { - reader = new QRCodeReader(); - LuminanceSource ls = new PlanarYUVLuminanceSource( - frame.image, frame.size.width, frame.size.height, - 0, 0, frame.size.width, frame.size.height, false); - Result r = reader.decode(new BinaryBitmap(new HybridBinarizer(ls))); - sendTextToActivity(r.getText()); - } - catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - private void sendTextToActivity(String text) { - Intent intent = new Intent(); - intent.setAction(ScanActivity.ScanBroadcastReceiver.ACTION); - intent.putExtra("scanResult", text); - scanActivityContext.sendBroadcast(intent); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/edit/BaseActivity.java b/app/src/main/java/org/fedorahosted/freeotp/edit/BaseActivity.java deleted file mode 100644 index 6f635bdf..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/edit/BaseActivity.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.fedorahosted.freeotp.edit; - -import android.app.Activity; -import android.os.Bundle; -import org.fedorahosted.freeotp.BuildConfig; - -public abstract class BaseActivity extends Activity { - public static final String EXTRA_POSITION = "position"; - private int mPosition; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Get the position of the token. This MUST exist. - mPosition = getIntent().getIntExtra(EXTRA_POSITION, -1); - if(BuildConfig.DEBUG && mPosition < 0) - throw new RuntimeException("Could not create BaseActivity"); - } - - protected int getPosition() { - return mPosition; - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/edit/DeleteActivity.java b/app/src/main/java/org/fedorahosted/freeotp/edit/DeleteActivity.java deleted file mode 100644 index 51403cd3..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/edit/DeleteActivity.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.fedorahosted.freeotp.edit; - -import org.fedorahosted.freeotp.R; -import org.fedorahosted.freeotp.Token; -import org.fedorahosted.freeotp.TokenPersistence; - -import android.os.Bundle; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.squareup.picasso.Picasso; - -public class DeleteActivity extends BaseActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.delete); - - final Token token = new TokenPersistence(this).get(getPosition()); - ((TextView) findViewById(R.id.issuer)).setText(token.getIssuer()); - ((TextView) findViewById(R.id.label)).setText(token.getLabel()); - Picasso.with(this) - .load(token.getImage()) - .placeholder(R.mipmap.ic_freeotp_logo_foreground) - .into((ImageView) findViewById(R.id.image)); - - findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - //delete the image that was copied to storage, before deleting the token - token.deleteImage(); - new TokenPersistence(DeleteActivity.this).delete(getPosition()); - finish(); - } - }); - } -} diff --git a/app/src/main/java/org/fedorahosted/freeotp/edit/EditActivity.java b/app/src/main/java/org/fedorahosted/freeotp/edit/EditActivity.java deleted file mode 100644 index 4ecb5622..00000000 --- a/app/src/main/java/org/fedorahosted/freeotp/edit/EditActivity.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * FreeOTP - * - * Authors: Nathaniel McCallum - * - * Copyright (C) 2014 Nathaniel McCallum, Red Hat - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.fedorahosted.freeotp.edit; - -import android.widget.Toast; - -import org.fedorahosted.freeotp.R; -import org.fedorahosted.freeotp.Token; -import org.fedorahosted.freeotp.TokenPersistence; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageButton; - -import com.squareup.picasso.Picasso; - -public class EditActivity extends BaseActivity implements TextWatcher, View.OnClickListener { - private EditText mIssuer; - private EditText mLabel; - private ImageButton mImage; - private Button mRestore; - private Button mSave; - - private String mIssuerCurrent; - private String mIssuerDefault; - private String mLabelCurrent; - private String mLabelDefault; - private Uri mImageCurrent; - private Uri mImageDefault; - private Uri mImageDisplay; - private Token token; - private final int REQUEST_IMAGE_OPEN = 1; - - private void showImage(Uri uri) { - mImageDisplay = uri; - onTextChanged(null, 0, 0, 0); - Picasso.with(this) - .load(uri) - .placeholder(R.mipmap.ic_freeotp_logo_foreground) - .into(mImage); - } - - private boolean imageIs(Uri uri) { - if (uri == null) - return mImageDisplay == null; - - return uri.equals(mImageDisplay); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.edit); - - // Get token values. - token = new TokenPersistence(this).get(getPosition()); - mIssuerCurrent = token.getIssuer(); - mLabelCurrent = token.getLabel(); - mImageCurrent = token.getImage(); - mIssuerDefault = token.getIssuer(); - mLabelDefault = token.getLabel(); - mImageDefault = token.getImage(); - - // Get references to widgets. - mIssuer = findViewById(R.id.issuer); - mLabel = findViewById(R.id.label); - mImage = findViewById(R.id.image); - mRestore = findViewById(R.id.restore); - mSave = findViewById(R.id.save); - - // Setup text changed listeners. - mIssuer.addTextChangedListener(this); - mLabel.addTextChangedListener(this); - - // Setup click callbacks. - findViewById(R.id.cancel).setOnClickListener(this); - findViewById(R.id.save).setOnClickListener(this); - findViewById(R.id.restore).setOnClickListener(this); - mImage.setOnClickListener(this); - - // Setup initial state. - showImage(mImageCurrent); - mLabel.setText(mLabelCurrent); - mIssuer.setText(mIssuerCurrent); - mIssuer.setSelection(mIssuer.getText().length()); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (resultCode == RESULT_OK) { - if (requestCode == REQUEST_IMAGE_OPEN) { - //mImageDisplay is set in showImage - showImage(data.getData()); - token.setImage(mImageDisplay); - } - else { - Toast.makeText(EditActivity.this, R.string.error_image_open, Toast.LENGTH_LONG).show(); - } - } - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - String label = mLabel.getText().toString(); - String issuer = mIssuer.getText().toString(); - mSave.setEnabled(!label.equals(mLabelCurrent) || !issuer.equals(mIssuerCurrent) || !imageIs(mImageCurrent)); - mRestore.setEnabled(!label.equals(mLabelDefault) || !issuer.equals(mIssuerDefault) || !imageIs(mImageDefault)); - } - - @Override - public void afterTextChanged(Editable s) { - - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.image: - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - intent.setType("image/*"); - intent.addCategory(Intent.CATEGORY_OPENABLE); - startActivityForResult(intent, REQUEST_IMAGE_OPEN); - break; - - case R.id.restore: - mLabel.setText(mLabelDefault); - mIssuer.setText(mIssuerDefault); - mIssuer.setSelection(mIssuer.getText().length()); - showImage(mImageDefault); - break; - - case R.id.save: - TokenPersistence tp = new TokenPersistence(this); - Token token = tp.get(getPosition()); - token.setIssuer(mIssuer.getText().toString()); - token.setLabel(mLabel.getText().toString()); - token.setImage(mImageDisplay); - TokenPersistence.saveAsync(this, token); - - case R.id.cancel: - finish(); - break; - } - } -} diff --git a/app/src/main/res/anim/fadein.xml b/app/src/main/res/anim/fadein.xml deleted file mode 100644 index df8e48b1..00000000 --- a/app/src/main/res/anim/fadein.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/anim/fadeout.xml b/app/src/main/res/anim/fadeout.xml deleted file mode 100644 index b04fa183..00000000 --- a/app/src/main/res/anim/fadeout.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/anim/token_image_fadein.xml b/app/src/main/res/anim/token_image_fadein.xml deleted file mode 100644 index 7e0b4f58..00000000 --- a/app/src/main/res/anim/token_image_fadein.xml +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/app/src/main/res/anim/token_image_fadeout.xml b/app/src/main/res/anim/token_image_fadeout.xml deleted file mode 100644 index 2ebbc41d..00000000 --- a/app/src/main/res/anim/token_image_fadeout.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/color/menu.xml b/app/src/main/res/color/menu.xml deleted file mode 100644 index cefc6c32..00000000 --- a/app/src/main/res/color/menu.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_action_edit.png b/app/src/main/res/drawable-hdpi/ic_action_edit.png deleted file mode 100644 index 5f7c6eff38c2a503c1cfc2c4794850ad2c06d23f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 884 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 diff --git a/app/src/main/res/drawable-hdpi/qrcode.png b/app/src/main/res/drawable-hdpi/qrcode.png deleted file mode 100644 index e5806e64019225c64505ec20df944481b2d38939..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 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 OFN^BoODQGoJMtgFiYCzj diff --git a/app/src/main/res/drawable-mdpi/ic_action_edit.png b/app/src/main/res/drawable-mdpi/ic_action_edit.png deleted file mode 100644 index 650b4d8993a6590ec68b789441206638ad6a5b35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 587 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 Uv~C5Iv-wZ&VC#%5NBGA72MQN#j{pDw diff --git a/app/src/main/res/drawable-mdpi/qrcode.png b/app/src/main/res/drawable-mdpi/qrcode.png deleted file mode 100644 index b4d964d95f2974cff7314104d5fa7f9c890ecb1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8wRq zxP?KOkzv*x37{Z*iKnkC`#laeVF7WqF3(t?(0fl8#}JR>Z$ljU4lD2^ckKV>TO;;X zz;$EqLjD^{p^IY;`W|1nWpB4LVzb@1<@b{B&abd&U-a+H)mb~^iqBR(ezQ=av&M?I z*o>ja<5owW;WyvXbF)qycjjB}q}G=4`ztcjKh1 zU|~h;i;KPOkpZ*LJgPk+HJfdFw&UUZ9;zDKOipcK`gPka_Q9E&ofGHqh0E^<^qTO- uYsZ0U3sp68=bY{C{qnDLKf7SP#lCRW_lH9qc&7rr&fw|l=d#Wzp$P!iK8|w$ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_edit.png b/app/src/main/res/drawable-xhdpi/ic_action_edit.png deleted file mode 100644 index 8ab436d8746d96fa4e003d3b516bfc3d4960df4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1179 zcmV;M1Z4Y(P)Yzs0ki6E&g_H zZtn8-_O=&yV#N~KFN*h5UOEUDUOzTD0AbK%0@O86LSf%30+eJ|6Gv9>2nbJUN7uKR zkPIL5fn58^nj8?y^oZqIaaZDbP2885z7zLl|CDXBN%=s|_2inq6$HqGKF9-K$?gNe zO)D|IDs403U37DD?kRq2D4}f)0VJU(ej(saNWi?(46sX30LT*W$bLOW2?&9oPyN@F zf&F}+asQiD-J!IhxY<^^!8$Yi4hxy?ZYoS~F;(KT}ngAp=0dP(NYD(Ng)(vU&0NGw1_>Fj{(`2yxDf`oY_MG}DUS>^FPoq6>LM=YRvH0^tQ1Cqy+yI2_6fi zz+7&RIQemJBmo)0t0a6-#`ODP$qVpKR`4SyASZaWhiDP3&pAJbvd?W5!@&pEM9gy^ zVX%)kKa3ksSO8vYX2%!>j0ikzc@!_JVhQ+>S;Z3Y_bi5nZWFeE*IDE!gaDht=MDh@ zzhN`@+@nDmd38B%hdn5h6jp%G6#^(vqe@V!qGbd4%mgSixTwl*co?&|KI`^x8HcCO z3O-K`XcC~yx7`Y6XQ+x@8^C8GfNwaeDr+f2S19AVGKryM2hR;Ys{)o|(#hLC05?MxkgT)Hd-uS2qK;?H%;Ma}?Hl-o| zhDP%9ndH1Yixj3RU@fLC(-+#-5WvNVg$SAd3WmRq<(8xXwd)JM-13|;vLpgrj^?aM tYC|)WzDZwNmsVP7rIl8i-S$_20RXOO5G<352)Y0O002ovPDHLkV1kOuAU*&9 diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index 14cc390540b4c2380696ac0025ac9a54cf982aca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9839 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 diff --git a/app/src/main/res/drawable-xhdpi/qrcode.png b/app/src/main/res/drawable-xhdpi/qrcode.png deleted file mode 100644 index b9a691c373b00a9849123a0d315797ef0c6b56c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmV;e0aE^nP)Fm1?meP1|kJvvKnVmUCMG7{ XE#%ojD_>S%00000NkvXXu0mjf_y4Fz diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_edit.png b/app/src/main/res/drawable-xxhdpi/ic_action_edit.png deleted file mode 100644 index f2b2078b0787cf6f5722033b5b794cb5fdcba000..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1670 zcmV;126_33P)mMdBG5BtRs>(%|z-Jayzec#NEWNGgrec!$x`*v3e0)apv5C{YUfj}S-2z)|KC|Je8!NEQ~ zbg6atrAuzp^Yimi1SpsI=hRvW-6qsVB*at%uuJ}c$mTUeA4!Cz#DMkF&w+(l0E{Uf3`Ky|VB6!#)GRJ_ zq<#?KC}kdy1uwEr*lM1T|ClQSEVI`;37A5?A|Mt0;-vs^B}CXy z$n~ksiHMsBA>g0)Sd7$JEsKCT!+yq(@h0nBpza#^9CV*@gAjYv0)x-|Gn++w&O7Qx4t_@1e6QjMfCs05K8y)W3L3TKz^DC z7~$r^NtgQRZfC-eLtZ2BLja59CyEf`iu#5Cxi?-_G6fOajm zvH(5nX|Uf{ZD3ddb|jqnO1^ag*zF{pqw1Nii4Qc}s>g&?BEJj^=x6A291#y-1;e1& zS}d-8RVDHPtJ_lA?ePdpN0I>BEMW!c>y^19%k&`i4j5V z<)5+;O_#~HDgcr8ELc6%kSYQnj<_*|2>H-m*Jbjp#efXKHz{L!Y3xYWvl*w!w;6={ z1+Im7C;WpM9fM$}$+szhjf!X2xX;XW@~sHK!Piz%t)r!;iwHO56#2F+z-GO_Yiu7M zxlDdx0SW})B>bp7zu?)eljPg5fPM*|X<)dap{wK$m41kip6)y8N?pdGpDkE%=5S@#1DSXaOL9C_z;q5C{YUfj}S-2m}H_etZ*P04TpsYf3?Y QLjV8(07*qoM6N<$f`u#-@c;k- diff --git a/app/src/main/res/drawable-xxhdpi/logo.png b/app/src/main/res/drawable-xxhdpi/logo.png deleted file mode 100644 index 8939e47b08bc563c5baeaa25db643a456019bb34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27060 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

  • wu=vQ~Y3Ik~4E-(mRyq~(ZR=Sf1b9Xk)x5Hgr+j!En zC*q=k&8%SD%9lKm!8b@|-lr)+^|!Tz$_|n5)JT%l0sG2=O_e7!j@kR{TJ+9EHoSp4 zP6O22X$R}>(TyHA?2dw+mX@9l2DIhb>GNT|3K1#RC2Js#Vh z(qmDFQ7;+AJ-j^h=7Y}`oX-g#x7_q(62!4F!O1zhAfy0fb)dm8nY~+fEz@RKXr-uv z8oody%xIQZx6Fdh`}~s0-^}G>o@n3=2aKGpz3v>k)RC4Pu;9Bwl@yjxusH*>(gkby z=pen?HMV0r6IHydC7_<&R8u*$wxpLr;4q`L2fuz1X7!gelr8k&z3!*N(YH9It%_zK z`kW1JxxJYFHz!GqZj~x6_pjSfI{_8S-}|`aa6e#4D-5eQt6dNS1>w&{NyIV{|-}`LXK{3YhUSU!q-G zc-XZ(K+uRCuv=sAl11CN_rtSZ-6nFi8`{^;-Mj-RekKqTb+I&61T!7l!uy``Zn3Wb*stJ-$q%DpgUGK!q0N(fU|0kD_GP>&+b|u$ zy8jSZ1b^VkWGD(@p(e-AB!(-?izyyOU`;@H)x`s}u^v&D4dSZz8jWypt7GC*a<(3^txv1I?S|6I8z+Iu6MPb-#t6-pJ-2q`H&SIdnXu#cB?bmDhc#$N(`#{?Q z)Ih}_P#{3zG6Jk#aU>chdk%VM2+dpt1g-C><1($OgP>;i?p**uUr<;`916%Du@4Dy z!+cL;=s{Lep(cy`EFNy3o3g}HAxT~^H&js zq_QK@bW6k8Au~RZq}kkPY!f9)LT2KCwXz-nHe7~Bhy~wWd;s}YLuNk%4_4DMclVK* z!}%PXV!q)Zq%i{Gi}ZSo`H5Pgwh7O^T#Vlbwxs8ori(-bnAI`ucy2;HwIHZZNVp5D z{y86I&dmq834`-2ybEH&&AWG1Y=d;$hXYQl_d^FYnRq4ChIBP^8wi%Z(4!l27_8`^ zT5CWk^3p6XTn@^eP z?L@Pf!OU$|IEt2&{2&YGjdq%mK8b+h%*3*V_>KvcIn~#EzfoIVAyi=d_NvmUh=gI@ z<5gO@{k#yTW1Dejf8E@(F75-|X2%5#zFlbwD8kLTu65!r(&4&aN0!eyb(Yvr@mFp@ zP50#zRa8gp)fTuQgXGLLnw8U1L^KA zLMqu3C3dlS9AJ~b2rRMPk%3IB&uw&_xp(%Eo0EC<`j^=+e^&{CJ|Ho`iWSIhxAIypeT3M!G))c)R@QtH&<^0sW_F(#x zE5IVp^|pj{?@KNg9BMLzP-B-xEon+GRxq6zNb@~}fqy)&9Q71Iq}^ZF1wCiK%U1v{j!)`x5N=6)uPL-!WL-<^+l+2aD2L0sEdg<0hEu}XT z>z#|zi)9!f&}?z6OOVa8`S1 z+S;&HY4uvsC(?$YO_3iIi{8X$kg3iCiH?jfmX~i=((>9PIiarQ(~x+3Gz?jqms!?~ zrCh4A11VG}0XV`K!_5*Epu9BgzF2N{CwNc{q470=JN?KKbd;2j;&>#W9LgsL1D>=8 z2BBaB@2q`^S?j;4e~ErIeOgZE7l}46(LJb^ap??K&z9wzV!;$}P1t&n!vT%y9i`%1 z)Uv<3)(=#YW?QTB=3nq2V(5;l?`?d((_b^1h0k)exguVp-&G4-tjseY zl~ndWQ^*$r>_D8=u1%6psJ6G`@uc9Yt2R>!bfBGx7ybH6>XU9Q99%DzT8zR_#zXg^ zWg$^{pl>W|JiS4FOku@aQ@eTx^l_*W_h!oQvA*dxExCxWdiQQx;R;%w4Xc{`yHLRO zV@s{I&2uw=Ss2vc+d>e&2kBp{$ql7vYmF_I@o=WFrK@}R2nt935DvZaKv8yZivd>Ix8 zljiPV_D87+l`;MTU{y2(sMpQMm6;3%W}UpABLLNOOl)=71E|%mTzG8=*K} zB2ysE9pVIYi^O?SGMUEi6xZ)3w!fBo%C)4H7}EK4;XqhXV$na2K9Ffapss%@m~eV(S-t4#wb}3Jjjg`8v-yXwQ}S&PghX8+E|mj+1z9+@ zWx_g13do&WAGXcbD_{nEz1r|9MLvsQZ+*fAva-SJb2`&>qfQ%HvlAx>KnS-+O6Yg9}N!84q2BXI=5%CU0=Dc~F{H+J(F2(V_2HG5D2uZ3n;h_z)b)rS6r|gn6UUsolw3Dvf4-fuW$)d_wRyH8)PhAw z*_Ra?C5@U2jY`q5>7-!$Z`#bMLy%49TMr+KX%5Edw<6Dxyu{Qn+6|%Hy@U@Ke@CaxJ!{OhmoUt*elTMG?qYwf~Uh!>t< zNE!0N!40@t`jgg_*rGMa`^crOXu%{}_x+monu*&}ORsM094nbHzO(BZ2UhP4*Xkur zkbUZHaiYZ5awrr5)jY)&LD!R4cy>zKW?` zZd}Pp9xlD}Etnmp>QbwuP%JyYE2J{Q?IW)wY32~%lS!vhvDfGg_l`F{q00+#5z?Gb zwBY0M9naf*4FdajUMDel`=)Vn+yHs86{~sN4^kKp&XhhWpO(L0BeA^+@zkTfXkpW= za&a{cPhZ*OLl(z37UhV-APv(Elx`p16-vt;MZ8xB+WY#xp53y%%v$p2htSHKs8IL$!^sa~GE4F`b*@C^e>dEDa_aKoYry4VP-8Mb^03!e zhpjjRzk}tUFw4){7y;E`$&8efTQ0z)P2D)XWGHx76!|2~v1wQ$Q>cuz(^3>`Z9Oom z;_KjyuW`tu<<%0SWVd!|0_UL$iMOItK=3pV7@@w>g0jdk3kJ$jU`Y;Fl-F`~jThv_ z26{^8J);!&uYbh0AC+bgaRgD)+4hMHUZB7C_@@x$Opo`nWiVD--_IZ0HsbK~NXQf_ z;-%+GF&a4H02|dh0k&J1&FEmE5?H9e%Hh^ka~d*QXNWQ z$;%j=>gxRIPbU_~huiCrBcqrU1@WF2s_Chz%`D~Z0ZciqQj{Z^p(t}{SlvLWeOOX; zY07zKu+rN!z`G$^gGq?A4j$}Gy`-9P#bmHpltZO}E!~m+d9um;5jwP9XY0=6fh4|; zc;N?%YO}}6HyMOWlyfl_Bs?fmTHCGx@RoY@QZLs7pZCXk?+%l&DnX!)j2I4zSpsT8 zJ>H6tR6)LWw};KlK&FUU$j6eVo*U2EEci1f8u(AItMzv0t{jE$t_oMv9!Jo2rsFuWwL<_vpT1@&?g z{-!`>!xKdJGJR)15{U7hT%WW3mc)HP)em1ITAoL;!-0dw@qA2Bb^Q2S+(Ut(7xwNH z4j5!}PUkkYt#Wm5Z%QrWXT-GEye8lW(zP(jl@i|8N*dFujr|%`ss|0AE}XWDcDp)YXAGc3H?*khzldjR*^KT$nlq7fUmMu z))71<$?nzIy%&xZ=&ybmF`+5b(AIifeiyxA=DXmXNG0znFD1l9B= zXP9Vz9(iHV63Yh^Exo_A=&p5oRpM{x2_r)0CF_!_%d2LnAhA3aKMfZaX?Jox3b0*q~f zIHdd43*lK*m>2ZGx4C} z5$8_zsHT>Denys3QN_UWnMSP*pd+Segvb$}~+dpD!%*t*9` zd7a1X#oEA2&Wy_Nu=KhT**xRf6b{dlS510G`EnU`ZMG^>PpG`>w$shldh)OU#*${0s{NYLDdD2wgPpAGLVgQ1*IFXl(r=( zFgmh=O;Gm7ydFh>S_`#y!#8p*9h3(=3#&^(!;wf0DC(7jt%Uy|&@m^T2xxf6i9--h zEeK?}y@srXBh{zw!h$1TYueUpD?w@V=WkU6WX~bz0+_RQhIusodBs19z-BaITG)~v z`3hI96>{B~p*Ge#zgj%=ZQUwz=6fwgAjH4DwoWy}{_cUpXMvmkYVAS%`6RxNZ{bj} z6grhD?ot;KhDCR)j9zF9hHfYE?s<1)O8mx?s#eV-mzV$||HhlSAc3HmN?BFNB;b)P z)nXeG?$)0~qf^@gxTm6d$Z2KsJJ>*r%JRcdiizkGN`x-AQR=2ve{g7r1)_(%`~+rs zE`5KQEb9Cx(fi1>bH*uW?A@+kLc=N=1FX*@foh!ePVC1g&L0mrLSpoM1NB=&rI7pf z977BXr)&036WfymzGY0C&{t8Q)}YTjh;I)=zj(EpX**VXH21q}#9JAJ^3sDC#NlnE zQ(Sx%j{!%U(F<^y-1!7ocKCoWH^{aP(~%+|-D=^~NjYM{>Qn&pn~ilh#@;h=Fj zAm;K-!Wn1)hS-k%+$ZWrs^3P;I{}3ZY6E(}7$jf58!vc^#fzBf6&sEh@!u%1>#CL8 zk?JC=AF&pP7pO+2obWL#sTd1NoR4i$1ij*VdQ(X-hNTE&%3ZbujciPN6XyU&XZ6P~couDve=g}OP1M5|UoTK! zgVh7U>aTtqbo{ZGEY1fVb$NT<@Xv~+s%e;t@cA6@6cH2$L3uW#RT6|A z{lvtY_*4$Kjv0M9yl@2>$iG90UVILDkoaY`^Mf4k2`(YdE8R}@bubLe1cl_$YKEI@U1;BL8B*NgGExL@ZC#A2X5x8)m6nxS#;KaMQTYgYx(I0|RmP>}3vkp5_%OC<^dj!Xai z!rtR290tt@ZQfd}^PH9Zd22CZ$LF^9yAHw_W;!vRfoolbjzPoAcs+7SB)QFm65Hhr z{P>VPiWskH|9BOmk5_%!G2b(~qzt=hg8$JExT4q!A(*W>iIIs@JYth*8Z_#Q@uodK z5M`zpprHvh^`V-oS&n7l0waV{Yc8jts1WIzgtwIb>$#-#lf2TJIRvOZ@Bi)aJVl$5 zBf0?4Z;~?M!*uhnnT-TcQYPkyabby1fF5sY>nwz42tBZKrL?sVi{N2fBGt<+n2B$-PWPj?@K)Q`s zeYS|o@ys~Jcl*Bd#k+fMs!jWdED2mx`c;GISKTUOjHs-*=(6}1+arT}s zEx8|nXfVHexWT6yPY0E%9gn`;D_nejZqncrN|&iVX&b2>y?9(mR}%Q^i$x=$=Rwwn zEbMCi#OkY{j8P6OfF}^NMNke0C)GQv($=Fe=Xv^w;d-l<(s=t~w=G|x z$?8XlQ$CZ7abC++VR??d$jJTaZ@4;=503v%%x!+Ws|f6uzvjwbcvWNFG2lpfC}!1z zv-42;EtL697l+Rte7uTZ{)--YWY&6h&r9Q-7qX%8536gpB@|B0SrRWSBC7%W98Ny5 z5>d(UZ;y0cAEC}utL*Q=_&>fSm&Bt>cWsNW%N}o-Y_$0_B`kGNb`^n3 z`}`Yj?m+3h1WjD7$G5U>iD!sHsFN(E1Dd=dKBAyvnQ9u-02EiMf#%18mXaqdmq)Gz z3;dJH{$Zq-B6i>run)bDqtrhT=*;2ot1Z7;Sv@l)pu?nu5Q9q;=HBoPK3c`iUiPzB z!GY?14tW8@YK=9WQn=l~hGyP25q$(V4@gL0=8 zjfE8oxVPQz2I>UmJzToQ_Uabu!Z%Q&AMS~+tR!lQ01gH{5Hbb9Q5CME?w6GXu2NNo z>4Mr#9aO>CSlKCi`I%?fs%}gF4ZmU2?pBBb4)dy5w9uO;Ov0Di_ z_B0iyw_|(vZ$9pEIBox>xI1%rH=a5Y?9!;|sfe`#je(fm?ZF5{taKtr22I!dNVbM24Zj^_TzVcmYb7{ zi#J_5I{PA?(lUed5T@K&o?&J`yX$aUH`0i)v)+X-F67bR#VoUQ+?75U@uT9!8_TD{ zO5Aq;C&)nS1OkH9o%?d#50BqQ%^>-rh?wYXWEzQ}#-lsi#DrUKQ zD2|)6!!-OJBR_8(YcjW_^_v<-1h|o7w_!aQqF(EVE*Uu$C!S)FifXo90+ zvwj{SH0#aO{9gLBWn)NaAR|&#SfS)rnKtEj4l|?U7fEeb9#uBmL&WORH~MTwV|md7Z&~N}nn*D`8L0zYwNl3V zEtZJ_Ww(Of7_ryIo79h=@GN(qfufKsgG)6&qjaBva;jx8k^ifZYPy{HY-UvD@fcPE zsmy`!%FUWONwpDmb*f{NUEtBfi(4V4M-S_V8CkjI|1d>dE@0><1QIsAB zwvJU)Q{{AW^+Nvb3ZdOnhbvZh#~$ATwrP~=8#(;pK$Pyz3)gJ0*hA0ub8pmvTrfxl zRXhmHOI=);ubGVm?vKQ8M$4juGBJYXA?bg0S48b>iFuRGaUg#cM{fIbU)S+oJ!3_t zPA9T&Jjb!g(HI>PHXO`!?ocm&^PLaS*i9YpE%pKAP>55YtSnzV@@??(d#qZ}^>foD zo4kPm=QGJnUF`yG(BJ{N*#aFS&3;Q{u1kJprFGcx{4DxCY?3_9G z$Iiy69|+G09ZmG8)*cY5uK<=uyWu@4FV);yJpyBk2rc4&Q&m#3zSjD)5Wst7z3=!I zcF)UlI2d^`o*a*X$44ambcRhEbpd1domv(9{I9*@0FVR^qYtKopr=8nCGgw_-kw=6 zD>%seM#z8+_+EDS6iZt>18qGBv^6LZH!XU8d_nUB5QDr7E{vuEO01{C@SyiFW0gGy z}tCm_ZV91xe2(jPHh zO1VA3XpN!AGq{ezQ!j@latU!8A*JC$+#!2w0_Wb&wFYkkEs4FL=bRI?2=9RhKmly}O$H7(IRsihna4lOJHk%1 zrEh5-T`3*qkT1+0tZ@jI%Wios=T)D5jE_Hjd6q#LtfF81z$J9jW#VwMt#HCwOcibT z*aq2y%DXdk_2fbnmu{>w2!6rbmq16AeIGhJTW5(p$12kJ`>8g*dK>EMJL$OE|5`)p;C<%2GLdNB;0B2R9hojug{eCixU~XZ}@lr3RX^ zp||Z7+W~y+; zW^`P*z@vKb;@3>Z8TjI^p)8{u=2GM)Y3_O3OIEA<_M|xifY-Az?8MKMbJrY;MM>U)q8%maN+g`J1_aF~}zmF2T?45Kscdwz~Kvd`<1h#o4WvJ1@pqYBLp0 zcaEHyu58()k~&K$mWD0CrtWaY8reS2>!NHgVRTu|gh34k$CH zUJim5TBHDow2ZWq8M8=`_-T67!?vyLTC1IV6q)vT{&L?db~t&g#u|pL5 zxaMf=3vbfM;5+I(u#T3%tJrdE1miovr3am$%$gvK+w>o!Y=ebtfCs#xu=fL!_W*Z@ zX&?ouz1)liPT6e6>LDc(16i7L>lKv)Nbm;UMxB>^D;02mVJ(`uF~Sb_LwwB(_o3=q z)nU%60DZmZ7dGi?--ED5g-C2R;Y&@g26t!oBC`60*x20+^06lS zvzYI{G=&$e;Px}?nz7!v*UX8yh}uyk9T~@|cqPh)>)S`r$j*knqTGVI$r0y9E1j1x zRaI@2K?wziDUK7kWI}}~gSgTz8c|F+Vnn6?eNt@VV)5pFy}5pIxa9Kf)3?VERYnu%IL{ zHn?{UJzRr(Gbvg5Rq#2Pw?~W{2Csk95>1i(J_Rwm%MpF`xJhR5za~g~*Ry+Y6 ztP&t!pOp^B26ZO&mZ!hze3MM?H-ISZgR-q)P3z6jZO$x7{Urjgv2B7{l5l)oy@@fqC`}&9- z;%eIk`bq9lZ0UfFGJLm(II?Bo?PKUrTs8y8HhiVY>jH!X_fVo&YmFurw|Ep49K;~Xiq3mB(=LL?5pK&0m1`68G= zs1gh~ppyUkiP&FhrZYo}jfdIH^b}kEC0eiYi%oFIE<3V;aK!X~&eHxFs?BQo-91pw z@YK1^LKL>9gx7W;_Q(G@1pU7w%e%NBv+zSm2XDYaFmVqISlwNa&RKgqT{@s?5wEB| z7a-R^P{z9W!x{g-0r+=%|1Z?ky;7J`&vDz#28-Kibq*qi&FlXff&nV;`T_clmPFA1 zJD&&|_zz$@C3mIlFy5v(xb~u*Y6fDXzX{AgB_|q4j$$+XKOoD8a!5V>52Qq#wX<9+%Rjk=_#665U`?^#tnKY%w{9GMzXxUni2{%Rzeq!c zihh&mX^g@@MCaek>HpRs@6EUVhc4ysYa?3Q21m8fAn3351o_CQ$ZE<-DC^VZVp+`E zO54b)Y2uvrXG2~{)O-ACMkb@QZM~s4bNJYt)lWkNg?uV+O;TPjQ+e1DDpST)mQndHSznEv> zJ`^w=%i(6evs@7$)Ibz-o*CJM(zS8!-ShZz>^x(=41i&!hbJ-MgR8gdZEA~%OYwIB z5Mx%LDbt8J*FCaq!jVPR^u&SEO&qT+rJ6togDW3^dr!cGOGR$#54@@n%0VRV=fK`BTS)6|G7Jl%KXamu z?dz%6UU!_ZkC?1xQRHhw>!wE1er%Ttn4LM0(ZQ%}CPRp%2{e#upKz|?K+w(giQK|Y-3<;+l@IkGD zru;!#w?hcoC&D0q^se);-wH4#7Hoo)sEnn}b)OBYgIr9H$yI*TnMphyIi$VxunbQx ztt0t<`h;lVgqGT5T5ua*&?^}edGK`+{QSr-B;r}35Up0*5DMX{k)TL`#&;$oT*Hsm z!X9ya2y-GSFF{ANj5}v=bEB>xbZ(|DHv#ne|5R2l(LOq-)d2iD?dmZ;D6MWd$TW)9 zZ1d^#&(%%m!IJ#3rM0^cFR&1{KYs?aGxhBa4AQZ|k*hv9DR?wab_%ggb>7E;d8+{i zA{P9w5KkWFGJmDLhVwvKk&{l!AdgeRl$#2Dx*4#@q*SiHqE5?wgP|^a#sU7?0j69J z^FW-6F0RuOYo3f!{lOBF*oIN?;__xI7PQjW@vt}jt_;*jHL*Q&r`U^?@6V8bHS0JR zbHJY)QWUHvJ>6P&1C<-(N z@Z7z{r3;J{fJ{*-U?P0scS~lT(@TL2)CTPznp39VQ;s8Tu z0_pQUni0cfLX%DIkRfB;@99)wTQ^~RiJIt*nRrd zTK87oAdtR+AWXz1G47tO9lEg9;)1AOcx_gDtP~goftF$~r(a#*!?ag${3gPYxz|4sMT4aO z(tvcIgP|O{ZvqU#b%1*#m6Zim5dyRHMya?@K};MTG?M8)1Cx);>mY^t3e=&IeH%N# z)DK8=@5hrf<%3GXc0d(5!$Ffr7!Se^f;P>K5-JG6kvsBER*m0?iy z9Zb1rkaG#lNtRyB+9#`-%OB$KbPS2}p*i#;xjJ`2Ts~WsE;e004dKUrvVSg6ZnpxhYfkia^Itb_l556NUm(-$bIX`ibN;3OF0tNACW?0a=}r;O*-*1wq}h@siK0^CL?tv425jLIbu| z`#0Q7smee5!DvQs1+9Er2UNBV=(u>0R;^(!XCeaIa2l!}>g-sIZ1)TL%Bx1ILgLPv zk%fqB1*1$fc;om2RCXM^K@@3Riv`FOWC!y!pz{KY0#UOi=wZRIq#qLXT7A;$%5VZb zB{}`8PT;;2i@2zh=Rjja{ac!SWKkPX8O7rDqe$DdBu2$KXsOW1b7(#K^Kg`n@qW}q zZ0+>sMUbV0Bjy{)=v|8u+2n@X>b@7UCf4K?@?<_$S_XjTwOa1crOFSln8_HwK|pM!RhCI^i)$|wIj7dtB&wi{ZQ&;**1gQ z*QCi4UFAHzwl(|9q$%6v1oy#*Nl&g^4~dimMqVI z|57(w1;$4oK;sV{1u^%U?;fV>&muQgc1ork5Htc+&i`;&t zic!`>!&X{?TtVAh47t4b!da$c9j4oC%sNNw8++0*l`X{M!jc1@$DSl!tVC-mRn9M` zEaC5NAIG^xnvQmzYhRmIJ)O_^zbd=(XsF+R|CtoND3!8gt0ca%m+Z!uBqU3U?3FDU zL-ut>vKNKOlC82Y*<%- zeqQevve$zWqT@LlUC*szEiA-^YcE;{ZS<2O_3yHU}lRVn+Bma@`WZmgt)Q1T+TRmAsq;Di8!EQJqb2Wri=pV`9wvh6s;{4PIF6JQCk9K zsvxqV4&&h=UZ1%dr2qP4L|$=~QK2W!;u#~N&mM~zEPim7bANR2dh6QBT13R6FhC%( zf_&Km)hL^k|B+fUsg6#W*>*^6!n-_-?q3^11*7`-WcP?z32&948>9xztiTk^;4iK? zgE8)|NaAC4nWuq{Qro>m8@pT=a)V5wo<%LbIowiSp0 zCbkLBZAVWxEU=f}ysw8^0&KAdy#>GPC?H}_-E3`CTQ|a#xM_ORQo@lJ*iFU zdNvHdjs)iVCa2`xX=%dC4BkJVHyo$*W*}P;J-okQ z6s`EMx-PvToG8 z$wFVK>#=<+;8lpX?{3MGt2+~Ai|cQDj9sJXaS&rdA&y$El1Jm`Pk;AQkI+07o#9dF zJj2z_O1;rDyC?kAEfQ8QF|bB_c;$WGylUt7Bk%{^MCyG7P8XZe#z!!!$9riMm2;5b zoS~%QL}KNzF}B+%LcXw~5=3Wl{!0GRIoUV&(SOED;+ei>t8$ra7C%|oX&auW4A@P0 zjL{(_b2aFOt;k0XSeA{8lbsUPZ)$^3eRr#6#U6P7yg1<9AYVH>1=j_EDeOl#c*(8V z%|%&DkJRGB^iGXeI(>=y&}PXtvLJ(U3GZoGc@8#6b!n?)fxOkaJ${zSj?^iKp1@ia zHS#UFOB*K$y68g6p)aHh^re?{TbxK<^}v{$vR<}lgJmmetyT6&pHYz92N{nk%FoYvmPRzI=e5?vid=kYF$>%>vagev5>bu_RC@CnvtcIV?=ySW~*LTq%$gv;OjWwmzq+jxb7PtR@V&q>dU_ zIR(7>=+}^NHRG#?|Eo;D00r$?D<{%Y4SK0iZMFjWXE#`;xkt-|Lg&5*LN7c$s_&&= z64lQ%jVT=Qaecp*e(Sy=g@jfiDkx@cg_$_fF?BlyJk^XnI%U_3Ypxq*E}N$0AUQGmiCs@9md;%|M+AihXS#}rN@`>kNr*xE^c=>lYM z?*cNvJy2sWgQ8MSRuy?XXMzD%`x&@C^*k}4>k4z=lKT*qHLuLHUuW)-$7s5v`DU>k z^J6|wJc1l9q5k}tnSRMVEww%M$W6Frp8XotOpkNqP_llcfhCQ*#|1q62f^pR#5vVY z6TewB7%aw5L=!MKZL`)SjArh?eZ0~*Qm)@wy?6F-;7|iOcr*u>?hR~xUUD%AusWv>FMTfYk*%vU@)&; zhgI~)Ne^$yTOX_7J8X{)&eA9SHY~@MIS}{J;ACNBm<7J&I>>_IHxEYc=x>D~`@cIh zcY(x8i;bJB2@e3-mBg5H0Ax*gYX6y+HSz=Jc@T}31qM&6{(~>JBob(u!?e=`<-hiUUrIMgHqH!K;}D|yJ!@*oWlkq0M|=}4jiGcPr$U*B^z=qP&;Ta4=^S*QIlLVeo&qD4X5U zlgIbc^9+7mZ?cihSo#O^s&UDL9JIAq-YYdiv9MPKC6EqlL=tzEc>5Y@XqfU3g0x@! z4X0Y0f#x(k-AC^Z3uT(Py}S~4Nun*>0w9(uau#8A<0SMz{ZkNiRzt~h;)MI(@+= zGo)9=Fc|60j{DrnUw!d9%jMcjBVe}bv#-ymI8w>oCPnoVaud%gIbgfLo+)@51k{*= z5G4L-Q;yJUp?2%WSev+q-|{j)C}$k3f)K`RXWZo>#XD)tYDo^t z`6_O{`Ky)0tmPcuJH$$rTwmDA`muAtA^nNGjNn7|by%zRE*2!Vipb$>l6(R*dsU6y z;?Zv>riBLlZEboR?&s}fvcC#Z*ZqW6cv`PKNV1;TYH$**H)njTDXgg0@^UsEPO@rI zV~hOa`-1gSR$-^gJwI`2d`$7kF4b_TRGr`B4p>nYja$jLeys-hoSF09bCwrkiOzDb%%gYQ;+!qZA25zY^xCWq)h0jiZ%_TRn97G-A(GwZ0r6$_o#a3p)$-T7(8!4}|&@qZ%}BtXu~WYz8}km*zbT zgZ&oQk2nki8KY>jzD*VlwJ{s(?JXUq_$`%+Ni0tR4QlU+kv*PzC*s0+51c&E4A5(m ze)0HN5eJuLOzR-l;eMspRcRb9X44Paq}_{FQdwO+H=S%Wwdx)bCURE(-ie0`U3*nz zCO#X!SL^22rkY^87+nK;t5QSxtl-x@>$imzqOtE% z(=2~RL-t}c)R%M8}y*&BW zx{(W(HR+r3+Vi`G<_3e5S@&2|($HKZi?Z`0r39d3i~R0(MPAXK9U{S!S(OmvvuREK-V?+{Z5w`|BYGoN!E zo>ZF$bI!NT8`Vsv4k64L)5Y6AB>2Ps98_)(`)KGCzGj|!s38#eS6pS;?ensua@kw7 zDafA(gca;eKBbw}AycfB<@_aU3WFQvDOlTO_qUs!@1SggCfB-dwyiS{bAQ8iE9+xE zf%Kxe$`Y4C?+D#W*>S&DHS3aE*($0xoQ=!CB>N!)12gT<=muQ49bCm=-4OW zu@B#}@?&Ooio12olRaxb+mMHa)7SAh*+N2(!mDFXx$VrvP+#OT`!+_fq%zR#{wSrH zql_d=FqUs?JkEe95>ZjkOU!X|4N}AFnR3A>Olw~?Z+RW5czb~VkY&HM#TlBD{Myc) zXZ)jw9mqN^3(k}OX{tUToP!|xe4%NnoW8$Qr&|q^PWQe*yY1~alQUXB8;q)xDWaAW z=k6PAaD8`}nByqRT@%hIe1bySb;enl3d9xm2POpOK0ID!{;^^%`Fm-keEvwJmngH< zlLZbL&CS;=XvNa0rSoTTX3&4n&xeA_pquXNRp##yGnGLT-@n=OYxR3V9GzAk(9?N0 z7e1*V<3vpfxOGBJrVwTUn92yYG}09J!GRGuMjt;G$s1h`^&B%={rq?^@&lHJ*TkEh zBKnelU;C(li5M@~D6)0LsPX0cT!=@v}zPL?D5aT$b0Wk=iH1S8)AJ7Uv zx@fIRs)4E<&2u-ZDIP29QOPkXS>oCk#j40==DS4h0!Xzl|9I!VK43mhVm1>G2c=C+ zFsh+o7|R51Z0ltU`|M{tAV%1r3q7Q1_TGV1@$n~IEU%9C03+|cdafj=zJS6`VJ7+W zTj4ljNhNtaZ-OCL3AlLeaV+%yv#N#BQJpb4o>l~S}=d!f0p6PlS{T|o84N+ENucjnQNWmdpkQq3%!1ClHsZS82b-ds>_ z&k7$|90vqiBJZ(33|Cq07s?J#9%d_TCxY$s=gWS-7IEW4I7iX}hI}dHRW|C%b872k zu-?TJWTmt#KU89lX}CX4QkmWeoiBRa&@~B|RTPV5%A6U8Xt4>_`+{dgeUo^p>S1X* z#3*Huo=*BFJst5=9py$a%2tePQl-SzSTB`C058IdpN6sk7Do3WbdaL8x0=+_))NEh z>|X7(>7S~5BI4B0yGo(X^To%M?XVw0R^_$}z5GyD-a`!Q1Gpzn(wrYXuGX$*FGD>< ztYn5cqztFW3@_qxelt;X{Q+WFRg$2ErljcC&{N-3|N5}ib3xR6zaT{3nX zNfFDla>pR5Il#cw|53%Vn7RkkI^dPgQ8bFSsS?>F?RuhvAh}v4^-^EhN+GX*KH`pz zCcnX8K%jytfy(xWp?MX~uZpp;%JECQLTBQ=D*$m0(s>?oI?kn0I@+*`OU{D!+F{$s zIUvT0Hzh&nqV_^CDzPt29}*bPC3(#DaM-egB`AA)qPvpXNr~z^u}7Z ziQb_40c^mI$QB3uHHaGQob0q#?O7Tds#rNCR@y$^9^0YeeioW1-;Uc^J`GXk02pq& z_aKw%1Opy$Gl2C_>{CZ=am%P+R9n<7Y~Evz-q3Gxb-tTyuAU@Tp(3v^-UJ$t&Zi1& zdCjUIvI!po3~E)FQENB>cIrKso`ZA67{~(R?=T~L=}3pcINjzBKZo5^aIYX=J~&vh zjZ?(Z343-|=J!uzLk=&QuqXNm;VGwRA5a=CBaSKon z5#vtL#=YYenOaD!xTo#4GN6&{_`v=0g<;A_4}^c4wfKD12x!%K;56K4@}Tq!{E7ai z_{nt^&+VJzZYRyZGrp1H*ZNmp@j9Gxl9ItJvEMRMepnsOq)fn;T z@fZDK4TqyK!W0LxW!msdTX$%_pOxf1GYvc9!SpxIaZQWC$uNDK)3)$zLNuEpp+vFp zw#7Y_7Y~zty}qeCO8Ls1t$uQw1HHcgD~ zzjK0-r_@#V}#tG?Iz&V#vd1lSZAp9M$EE!ico1D>HE?IZb?)YeUE*EK}=RLkgD#Sue;P-hawQRH0I&~Ci3X3ouplV?`nc&|@^ zgN`p_L8kvgknaxAGmpv~MU~k6Lh6v8)sv2~_}*nYm~lxCSk6nP>Cw^=isKNbNQsqw zx@k<)s~6U4)iktNm=*SO?Ti}>+8$`CqbSpeZ(kwYJ#e0zCEQ_V{0|$rBc|*K3#3Uw zc`x^~2S|cjibo)2%B-*n0YNhWlc%a5F z{`)s?CN-@8ug}7$L2%WZO%g%+_QM)Nj>3yJE&tPppWX-HpK|<9&+6O#Nc;rK$B1L- zVJPEY-OhCw+s%R?GH+mF|F@>onuCYe?`IlQ@~os6P9U&sUea3hzqIOKKe>I;ZT$cA z9S`OHsqFriVDBX;r;q9XG7SH!koH0HSzud59DJyJ{qOr1pG1{tL=Zh=3oFrVI3*y6 Nmd2%X#cI}f{{z{cGd}vsBw^R8&@7beuq_b)5D*DvMm!uRy4g3wdtf9q}B-LZUp7Jmx4GS?fU-yN3sl(#sUL!G&6v z`q&@hK~@7P+siV1x&wBs>002ovPDHLkV1j%z%zOX< diff --git a/app/src/main/res/drawable/ic_freeotp.xml b/app/src/main/res/drawable/ic_freeotp.xml deleted file mode 100644 index 03c14358..00000000 --- a/app/src/main/res/drawable/ic_freeotp.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/ic_freeotp_logo_background.xml b/app/src/main/res/drawable/ic_freeotp_logo_background.xml deleted file mode 100644 index 01f0af0a..00000000 --- a/app/src/main/res/drawable/ic_freeotp_logo_background.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/menu.xml b/app/src/main/res/drawable/menu.xml deleted file mode 100644 index d66b1090..00000000 --- a/app/src/main/res/drawable/menu.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/scan.xml b/app/src/main/res/drawable/scan.xml deleted file mode 100644 index ad7b1852..00000000 --- a/app/src/main/res/drawable/scan.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml deleted file mode 100644 index a3691ee5..00000000 --- a/app/src/main/res/layout/about.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/delete.xml b/app/src/main/res/layout/delete.xml deleted file mode 100644 index a8c51ae0..00000000 --- a/app/src/main/res/layout/delete.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - -