diff --git a/Graphics/android-icon-copier/.gitignore b/Graphics/android-icon-copier/.gitignore new file mode 100644 index 000000000..3336b9152 --- /dev/null +++ b/Graphics/android-icon-copier/.gitignore @@ -0,0 +1,81 @@ +# Python + +*.py[cod] + +# Options +/options.json + +# Packages +*.egg +*.egg-info +/dist +/build +/eggs +/parts +/bin +/var +/sdist +/develop-eggs +/lib +/lib64 +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +### Generic + +*.log +*.sqlite? + +### Compiled binaries + +*.class +*.jar + +*.o +*.bin +*.a +*.lib +*.so +*.out + +*.obj +*.exe +*.dll +*.com + +### *nix OS / apps + +*.swp +*~ + +### Mac OS generated + +__MACOSX +Icon? +*.DS_Store +*.DS_Store? +._* +.Spotlight* +.Trashes + +### Windows generated + +ehthumbs.db +thumbs.db +Thumbs.db + diff --git a/Graphics/android-icon-copier/LICENSE b/Graphics/android-icon-copier/LICENSE new file mode 100644 index 000000000..4dc1175a5 --- /dev/null +++ b/Graphics/android-icon-copier/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Lucas Tan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Graphics/android-icon-copier/README.md b/Graphics/android-icon-copier/README.md new file mode 100644 index 000000000..3e12ae472 --- /dev/null +++ b/Graphics/android-icon-copier/README.md @@ -0,0 +1,109 @@ +[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--icon--copier-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1325) + +What is this +============ +A commandline tool to copy Android Material Design and FontAwesome icons to your + project folders: `drawable-ldpi`, `drawable-mdpi`, and etc. + +How it works +============ +It downloads from these repos: +- Material design: https://github.com/google/material-design-icons +- FontAwesome and "Classic" Android: https://github.com/svenkapudija/Android-Action-Bar-Icons + +Resolution supported +==================== + | l | m | h | xh | xxh | xxxh | +--------|---|---|---|----|-----|------| +FA | Y | Y | Y | Y | Y | - | +Classic | - | Y | Y | Y | Y | - | +Material| - | Y | Y | Y | Y | Y | + +Sizes supported +=============== +Material: 18, 24, 36, 48 dp. +FA and Classic: 32 dp only. + + +Usage +===== +
+Usage:
+Material      : ./copy {proj path} {category} {color} {icon name} [size]
+Classic and FA: ./copy {proj path} {fa/classic} {color} {icon name}
+
+ +`[]` denotes optional args. +**Args are case sensitive!** + +- `proj path`: Path to project folder relative to `base path`. + - `base path` can be defined in options file (see below). + - Auto-detects new or old project structure: `MyProject/src/main/res` or + `MyProject/res`. +- `category`: Either "classic", "fa", or Material category. +- `color`: Color of icon: Either "white", "grey" or "black". + - For Classic and FA, "white" refers to the Holo Dark theme (dark background). + "Grey" refers to the Holo Light theme. + - For Material, "grey" refers to grey600. +- `icon name`: Name of icon (must replace spaces and dashes with underscores). + - Without any prefix. Examples: FontAwesome "thumbs_up", Classic "search". +- `size` (integer): for Material only, Size in dp, defaults to 24 which is the + action bar icon size for material design. + +Examples +-------- +- `./copy MyProject maps white place` + - Downloads to `BasePath/MyProject/{src/main}/res/drawable-{m,h,xh,xxh,xxh}dpi +- `./copy MyProject maps white place 48` +- `./copy Path/to/MyProject fa grey thumbs_up` + +Windows users need to use `python copy` instead (I think). + +Filename mapping +================ +The tool also supports filename mapping of destination png files. (see options) +Mapping vars: + +- `cat`: category +- `name`: name as specified in commandline. +- `color`: color as specified: white, black, grey. +- `size`: integer only. +- `bg`: derived from color. black => bright, white => dark, grey => light. +- `bgSuffix`: "_dark" if bg is dark else empty string. + +Options file +============ +Named `options.json` in same dir. Sample: +```json +{ + "basePath": "~/Documents", + "filenameMap": { + "classic": "ic_action_{name}{bgSuffix}.png", + "fa": "ic_action_fa_{name}{bgSuffix}.png", + "material": "ic_{name}_{color}_{size}dp.png" + } +} +``` + +~ is expanded to the user home dir. + +`./copy Path/to/MyProject fa white thumbs_up` results in the +target filename of `ic_action_fa_thumbs_up_dark.png`. + +Installation +============ +- Python >= 2.7 (older or newer ver might work, you may try.) +- Python Requests package: `pip install requests` +- Git clone this repo or download the script. + +Icon cheatsheet +=============== +- Material: http://google.github.io/material-design-icons/ +- FA: http://fortawesome.github.io/Font-Awesome/icons/ (icons in 4.2 not supported) +- Classic: coming soon. + +License +======= +This project is under the MIT License. (see LICENSE) + +Please refer to the respective icon library for its licensing info. diff --git a/Graphics/android-icon-copier/classic.py b/Graphics/android-icon-copier/classic.py new file mode 100644 index 000000000..17ae1aac4 --- /dev/null +++ b/Graphics/android-icon-copier/classic.py @@ -0,0 +1,146 @@ +# Maps icon name to the dir name. +CLASSIC_MAP = { + 'about': '13_extra_actions_about', + 'accept': '01_core_accept', + 'accounts': '10_device_access_accounts', + 'add_alarm': '10_device_access_add_alarm', + 'add_group': '06_social_add_group', + 'add_person': '06_social_add_person', + 'add_to_queue': '09_media_add_to_queue', + 'airplane_mode_off': '10_device_access_airplane_mode_off', + 'airplane_mode_on': '10_device_access_airplane_mode_on', + 'alarms': '10_device_access_alarms', + 'attachment': '05_content_attachment', + 'back': '02_navigation_back', + 'backspace': '05_content_backspace', + 'bad': '03_rating_bad', + 'battery': '10_device_access_battery', + 'bightness_low': '10_device_access_bightness_low', + 'bluetooth': '10_device_access_bluetooth', + 'bluetooth_connected': '10_device_access_bluetooth_connected', + 'bluetooth_searching': '10_device_access_bluetooth_searching', + 'brightness_auto': '10_device_access_brightness_auto', + 'brightness_high': '10_device_access_brightness_high', + 'brightness_medium': '10_device_access_brightness_medium', + 'call': '01_core_call', + 'camera': '08_camera_camera', + 'cancel': '01_core_cancel', + 'cast': '09_media_cast', + 'cc_bcc': '06_social_cc_bcc', + 'chat': '06_social_chat', + 'cloud': '04_collections_cloud', + 'collapse': '02_navigation_collapse', + 'collection': '04_collections_collection', + 'computer': '11_hardware_computer', + 'copy': '01_core_copy', + 'crop': '08_camera_crop', + 'cut': '01_core_cut', + 'data_usage': '10_device_access_data_usage', + 'dial_pad': '10_device_access_dial_pad', + 'directions': '07_location_directions', + 'discard': '01_core_discard', + 'dock': '11_hardware_dock', + 'download': '09_media_download', + 'edit': '01_core_edit', + 'email': '05_content_email', + 'end_call': '10_device_access_end_call', + 'error': '12_alerts_and_states_error', + 'event': '05_content_event', + 'expand': '02_navigation_expand', + 'fast_forward': '09_media_fast_forward', + 'favorite': '03_rating_favorite', + 'flash_automatic': '08_camera_flash_automatic', + 'flash_off': '08_camera_flash_off', + 'flash_on': '08_camera_flash_on', + 'forward': '06_social_forward', + 'full_screen': '09_media_full_screen', + 'gamepad': '11_hardware_gamepad', + 'go_to_today': '04_collections_go_to_today', + 'good': '03_rating_good', + 'group': '06_social_group', + 'half_important': '03_rating_half_important', + 'headphones': '11_hardware_headphones', + 'headset': '11_hardware_headset', + 'help': '13_extra_actions_help', + 'import_export': '05_content_import_export', + 'important': '03_rating_important', + 'keyboard': '11_hardware_keyboard', + 'labels': '04_collections_labels', + 'location_found': '07_location_location_found', + 'location_off': '07_location_location_off', + 'location_searching': '07_location_location_searching', + 'make_available_offline': '09_media_make_available_offline', + 'map': '07_location_map', + 'merge': '05_content_merge', + 'mic': '08_camera_mic', + 'mic_muted': '08_camera_mic_muted', + 'mouse': '11_hardware_mouse', + 'network_cell': '10_device_access_network_cell', + 'network_wifi': '10_device_access_network_wifi', + 'new': '01_core_new', + 'new_account': '10_device_access_new_account', + 'new_attachment': '05_content_new_attachment', + 'new_email': '05_content_new_email', + 'new_event': '05_content_new_event', + 'new_label': '04_collections_new_label', + 'new_picture': '05_content_new_picture', + 'next': '09_media_next', + 'next_item': '02_navigation_next_item', + 'not_important': '03_rating_not_important', + 'not_secure': '10_device_access_not_secure', + 'overflow': '01_core_overflow', + 'paste': '01_core_paste', + 'pause': '09_media_pause', + 'pause_over_video': '09_media_pause_over_video', + 'person': '06_social_person', + 'phone': '11_hardware_phone', + 'picture': '05_content_picture', + 'place': '07_location_place', + 'play': '09_media_play', + 'play_over_video': '09_media_play_over_video', + 'previous': '09_media_previous', + 'previous_item': '02_navigation_previous_item', + 'read': '05_content_read', + 'refresh': '01_core_refresh', + 'remove': '01_core_remove', + 'repeat': '09_media_repeat', + 'replay': '09_media_replay', + 'reply': '06_social_reply', + 'reply_all': '06_social_reply_all', + 'return_from_full_screen': '09_media_return_from_full_screen', + 'rewind': '09_media_rewind', + 'ring_volume': '10_device_access_ring_volume', + 'rotate_left': '08_camera_rotate_left', + 'rotate_right': '08_camera_rotate_right', + 'save': '05_content_save', + 'screen_locked_to_landscape': '10_device_access_screen_locked_to_landscape', + 'screen_locked_to_portrait': '10_device_access_screen_locked_to_portrait', + 'screen_rotation': '10_device_access_screen_rotation', + 'sd_storage': '10_device_access_sd_storage', + 'search': '01_core_search', + 'secure': '10_device_access_secure', + 'select_all': '01_core_select_all', + 'send_now': '06_social_send_now', + 'settings': '13_extra_actions_settings', + 'share': '01_core_share', + 'shuffle': '09_media_shuffle', + 'slideshow': '09_media_slideshow', + 'sort_by_size': '04_collections_sort_by_size', + 'split': '05_content_split', + 'stop': '09_media_stop', + 'storage': '10_device_access_storage', + 'switch_camera': '08_camera_switch_camera', + 'switch_video': '08_camera_switch_video', + 'time': '10_device_access_time', + 'undo': '01_core_undo', + 'unread': '05_content_unread', + 'upload': '09_media_upload', + 'usb': '10_device_access_usb', + 'video': '08_camera_video', + 'view_as_grid': '04_collections_view_as_grid', + 'view_as_list': '04_collections_view_as_list', + 'volume_muted': '09_media_volume_muted', + 'volume_on': '09_media_volume_on', + 'warning': '12_alerts_and_states_warning', + 'web_site': '07_location_web_site', +} diff --git a/Graphics/android-icon-copier/copy b/Graphics/android-icon-copier/copy new file mode 100755 index 000000000..995a8789e --- /dev/null +++ b/Graphics/android-icon-copier/copy @@ -0,0 +1,162 @@ +#!/usr/bin/env python + +import os +import sys +import shutil +import requests +from os.path import expanduser +import classic + +resolutions = { + 'material': ("m", "h", "xh", "xxh", "xxxh"), + 'fa': ("l", "m", "h", "xh", "xxh"), + 'classic': ("m", "h", "xh", "xxh"), +} + + +class AppError(Exception): + pass + + +def make_filename(filename_format, cat, name, color, size): + args = { + 'cat': cat or '', + 'name': name, + 'color': color, + 'size': size, + } + bg = {'white': 'dark', 'grey': 'light', 'black': 'bright'}.get(color) or '' + bg_suffix = '_dark' if bg == 'dark' else '' + args['bgSuffix'] = bg_suffix + args['bg'] = bg + return filename_format.format(**args) + + +def download_url(url, target_path): + print("Downloading {} to {} ...".format(url, target_path)) + print("") + #r = requests.get(url, stream=True) + r = requests.get(url) + if r.status_code != 200: + raise AppError("url not found, perhaps invalid name, size or color") + with open(target_path, 'wb') as fd: + for chunk in r.iter_content(4096): + fd.write(chunk) + + +def make_material_icon_url(cat, res, name, color, size): + if color == 'grey': + color = 'grey600' + elif color not in ('white', 'black'): + raise AppError('invalid color') + return ('https://raw.githubusercontent.com/google/material-design-icons/master/' + + '{}/drawable-{}dpi/ic_{}_{}_{}dp.png').format(cat, res, name, color, size) + + +def make_fa_icon_url(res, name, color): + if color == 'white': + holo = 'dark' + elif color == 'grey': + holo = 'light' + else: + raise AppError('invalid color') + return ('https://raw.githubusercontent.com/svenkapudija/Android-Action-Bar-Icons/' + + 'master/Font Awesome/holo_{2}/ic_fa_{1}/drawable-{0}dpi/ic_fa_{1}.png').format(res, name, holo) + + +def make_classic_icon_url(res, name, color): + dirname = classic.CLASSIC_MAP.get(name) + if not dirname: + raise AppError('invalid name') + if color == 'white': + holo = 'dark' + elif color == 'grey': + holo = 'light' + else: + raise AppError('invalid color') + return ('https://raw.githubusercontent.com/svenkapudija/Android-Action-Bar-Icons/' + + 'master/Android Stock/holo_{2}/{3}/drawable-{0}dpi/ic_action_{1}.png').format(res, name, holo, dirname) + + +def make_target_path(base_path, proj, res, filename): + res_path1 = os.path.join(base_path, proj, 'src', 'main', 'res') + res_path2 = os.path.join(base_path, proj, 'res') + if os.path.isdir(res_path1): + res_path = res_path1 + elif os.path.isdir(res_path2): + res_path = res_path2 + else: + raise AppError('missing res dir') + res_specific_path = os.path.join(res_path, 'drawable-' + res + 'dpi') + try: + os.mkdir(res_specific_path) + except OSError: + pass + return os.path.join(res_specific_path, filename) + + +def do_material(options, proj_path, cat, name, color, size): + base_path = expanduser(options['basePath']) + filename_map = options['filenameMap'] + + for res in resolutions['material']: + filename = make_filename(filename_map['material'], cat, name, color, size) + target_path = make_target_path(base_path, proj_path, res, filename) + url = make_material_icon_url(cat, res, name, color, size) + download_url(url, target_path) + + +def do_classic_or_fa(options, proj_path, cat, name, color): + base_path = expanduser(options['basePath']) + filename_map = options['filenameMap'] + + for res in resolutions[cat]: + filename = make_filename(filename_map[cat], cat, name, color, size=32) + target_path = make_target_path(base_path, proj_path, res, filename) + url = globals()['make_' + cat + '_icon_url'](res, name, color) + download_url(url, target_path) + + +def print_usage(): + print("Usage:") + print("Material : ./copy [size]") + print("Classic & FA: ./copy ") + print("") + + +def main(): + import json + + if len(sys.argv) < 5: + print_usage() + return + + option_filename = 'options.json' + if not os.path.exists(option_filename): + option_filename = 'options.templ.json' + print("WARNING: using the template options file") + print("You should create your own options.json") + + with open(option_filename, 'r') as fd: + options = json.load(fd) + + proj_path = sys.argv[1] + cat = sys.argv[2] + color = sys.argv[3] + name = sys.argv[4] + + if cat == 'classic' or cat == 'fa': + do_classic_or_fa(options, proj_path, cat, name, color) + else: + size = sys.argv[5] if len(sys.argv) >= 6 else 0 + size = int(size) or 24 + do_material(options, proj_path, cat, name, color, size) + + +if __name__ == "__main__": + try: + main() + except AppError as e: + print(e.message) + + diff --git a/Graphics/android-icon-copier/options.templ.json b/Graphics/android-icon-copier/options.templ.json new file mode 100644 index 000000000..319d90f42 --- /dev/null +++ b/Graphics/android-icon-copier/options.templ.json @@ -0,0 +1,8 @@ +{ + "basePath": "~/Documents", + "filenameMap": { + "classic": "ic_action_{name}{bgSuffix}.png", + "fa": "ic_action_fa_{name}{bgSuffix}.png", + "material": "ic_{name}_{color}_{size}dp.png" + } +} diff --git a/Resources/graphics/All_Icons.svg b/Graphics/drawables/All_Icons.svg similarity index 100% rename from Resources/graphics/All_Icons.svg rename to Graphics/drawables/All_Icons.svg diff --git a/Resources/graphics/create_key_robot.svg b/Graphics/drawables/create_key_robot.svg similarity index 100% rename from Resources/graphics/create_key_robot.svg rename to Graphics/drawables/create_key_robot.svg diff --git a/Resources/graphics/first_time_1.png b/Graphics/drawables/first_time_1.png similarity index 100% rename from Resources/graphics/first_time_1.png rename to Graphics/drawables/first_time_1.png diff --git a/Resources/graphics/first_time_1.svg b/Graphics/drawables/first_time_1.svg similarity index 100% rename from Resources/graphics/first_time_1.svg rename to Graphics/drawables/first_time_1.svg diff --git a/Resources/graphics/function.png b/Graphics/drawables/function.png similarity index 100% rename from Resources/graphics/function.png rename to Graphics/drawables/function.png diff --git a/Resources/graphics/function.svg b/Graphics/drawables/function.svg similarity index 100% rename from Resources/graphics/function.svg rename to Graphics/drawables/function.svg diff --git a/Resources/graphics/ic_action_nfc.svg b/Graphics/drawables/ic_action_nfc.svg similarity index 100% rename from Resources/graphics/ic_action_nfc.svg rename to Graphics/drawables/ic_action_nfc.svg diff --git a/Resources/graphics/ic_action_qr_code.svg b/Graphics/drawables/ic_action_qr_code.svg similarity index 100% rename from Resources/graphics/ic_action_qr_code.svg rename to Graphics/drawables/ic_action_qr_code.svg diff --git a/Resources/graphics/ic_action_safeslinger.svg b/Graphics/drawables/ic_action_safeslinger.svg similarity index 100% rename from Resources/graphics/ic_action_safeslinger.svg rename to Graphics/drawables/ic_action_safeslinger.svg diff --git a/Resources/graphics/ic_action_search_cloud.svg b/Graphics/drawables/ic_action_search_cloud.svg similarity index 100% rename from Resources/graphics/ic_action_search_cloud.svg rename to Graphics/drawables/ic_action_search_cloud.svg diff --git a/Resources/graphics/ic_launcher_old.svg b/Graphics/drawables/ic_launcher_old.svg similarity index 100% rename from Resources/graphics/ic_launcher_old.svg rename to Graphics/drawables/ic_launcher_old.svg diff --git a/Resources/graphics/icon_sizes.txt b/Graphics/drawables/icon_sizes.txt similarity index 100% rename from Resources/graphics/icon_sizes.txt rename to Graphics/drawables/icon_sizes.txt diff --git a/Resources/graphics/key_flag_authenticate.svg b/Graphics/drawables/key_flag_authenticate.svg similarity index 100% rename from Resources/graphics/key_flag_authenticate.svg rename to Graphics/drawables/key_flag_authenticate.svg diff --git a/Resources/graphics/key_flag_certify.svg b/Graphics/drawables/key_flag_certify.svg similarity index 100% rename from Resources/graphics/key_flag_certify.svg rename to Graphics/drawables/key_flag_certify.svg diff --git a/Resources/graphics/key_flag_encrypt.svg b/Graphics/drawables/key_flag_encrypt.svg similarity index 100% rename from Resources/graphics/key_flag_encrypt.svg rename to Graphics/drawables/key_flag_encrypt.svg diff --git a/Resources/graphics/key_flag_sign.svg b/Graphics/drawables/key_flag_sign.svg similarity index 100% rename from Resources/graphics/key_flag_sign.svg rename to Graphics/drawables/key_flag_sign.svg diff --git a/Resources/graphics/originals/gnupg-infographic/README b/Graphics/drawables/originals/gnupg-infographic/README similarity index 100% rename from Resources/graphics/originals/gnupg-infographic/README rename to Graphics/drawables/originals/gnupg-infographic/README diff --git a/Resources/graphics/originals/gnupg-infographic/gnupg-infographic.png b/Graphics/drawables/originals/gnupg-infographic/gnupg-infographic.png similarity index 100% rename from Resources/graphics/originals/gnupg-infographic/gnupg-infographic.png rename to Graphics/drawables/originals/gnupg-infographic/gnupg-infographic.png diff --git a/Resources/graphics/originals/gnupg-infographic/gnupg-infographic.svg b/Graphics/drawables/originals/gnupg-infographic/gnupg-infographic.svg similarity index 100% rename from Resources/graphics/originals/gnupg-infographic/gnupg-infographic.svg rename to Graphics/drawables/originals/gnupg-infographic/gnupg-infographic.svg diff --git a/Resources/graphics/originals/ic_action_nfc/NFC.png b/Graphics/drawables/originals/ic_action_nfc/NFC.png similarity index 100% rename from Resources/graphics/originals/ic_action_nfc/NFC.png rename to Graphics/drawables/originals/ic_action_nfc/NFC.png diff --git a/Resources/graphics/originals/ic_action_qr_code/ic_menu_qr_code.svg b/Graphics/drawables/originals/ic_action_qr_code/ic_menu_qr_code.svg similarity index 100% rename from Resources/graphics/originals/ic_action_qr_code/ic_menu_qr_code.svg rename to Graphics/drawables/originals/ic_action_qr_code/ic_menu_qr_code.svg diff --git a/Resources/graphics/originals/ic_launcher/AUTHORS b/Graphics/drawables/originals/ic_launcher/AUTHORS similarity index 100% rename from Resources/graphics/originals/ic_launcher/AUTHORS rename to Graphics/drawables/originals/ic_launcher/AUTHORS diff --git a/Resources/graphics/originals/ic_launcher/COPYING b/Graphics/drawables/originals/ic_launcher/COPYING similarity index 100% rename from Resources/graphics/originals/ic_launcher/COPYING rename to Graphics/drawables/originals/ic_launcher/COPYING diff --git a/Resources/graphics/originals/ic_launcher/kgpg_key2_kopete.svgz b/Graphics/drawables/originals/ic_launcher/kgpg_key2_kopete.svgz similarity index 100% rename from Resources/graphics/originals/ic_launcher/kgpg_key2_kopete.svgz rename to Graphics/drawables/originals/ic_launcher/kgpg_key2_kopete.svgz diff --git a/Resources/graphics/originals/modernpgp-icons/README.md b/Graphics/drawables/originals/modernpgp-icons/README.md similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/README.md rename to Graphics/drawables/originals/modernpgp-icons/README.md diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-closed.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-closed.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-closed.svg b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-closed.svg rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed.svg diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@200.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@200.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@300.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@300.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@512x.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-closed@512x.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-closed@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-error.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-error.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-error.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-error.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-error.svg b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-error.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-error.svg rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-error.svg diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-error@200.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-error@200.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-error@300.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-error@300.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-error@512x.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-error@512x.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-error@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-open.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-open.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-open.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-open.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-open.svg b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-open.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-open.svg rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-open.svg diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-open@200.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-open@200.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-open@300.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-open@300.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/encryption/lock-open@512x.png b/Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/encryption/lock-open@512x.png rename to Graphics/drawables/originals/modernpgp-icons/encryption/lock-open@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint.svg b/Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint.svg rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint.svg diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@200.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@200.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@300.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@300.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@512x.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-fingerprint@512x.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-fingerprint@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-key.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-key.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-key.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-key.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-key.svg b/Graphics/drawables/originals/modernpgp-icons/keys/icon-key.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-key.svg rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-key.svg diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-key@200.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-key@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-key@200.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-key@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-key@300.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-key@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-key@300.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-key@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/keys/icon-key@512x.png b/Graphics/drawables/originals/modernpgp-icons/keys/icon-key@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/keys/icon-key@512x.png rename to Graphics/drawables/originals/modernpgp-icons/keys/icon-key@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-expired@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-expired@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-invalid@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-invalid@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-revoked@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-revoked@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unknown@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unknown@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-unverified@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-unverified@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified-cutout@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified-cutout@512x.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified.svg b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified.svg similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified.svg rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified.svg diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@200.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@200.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@200.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@200.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@300.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@300.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@300.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@300.png diff --git a/Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@512x.png b/Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@512x.png similarity index 100% rename from Resources/graphics/originals/modernpgp-icons/signatures/signature-verified@512x.png rename to Graphics/drawables/originals/modernpgp-icons/signatures/signature-verified@512x.png diff --git a/Resources/graphics/originals/tango or oxygen/1270234450.svg b/Graphics/drawables/originals/tango or oxygen/1270234450.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/1270234450.svg rename to Graphics/drawables/originals/tango or oxygen/1270234450.svg diff --git a/Resources/graphics/originals/tango or oxygen/application-pgp-signature.svg b/Graphics/drawables/originals/tango or oxygen/application-pgp-signature.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/application-pgp-signature.svg rename to Graphics/drawables/originals/tango or oxygen/application-pgp-signature.svg diff --git a/Resources/graphics/originals/tango or oxygen/application-pkcs7-signature.svg b/Graphics/drawables/originals/tango or oxygen/application-pkcs7-signature.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/application-pkcs7-signature.svg rename to Graphics/drawables/originals/tango or oxygen/application-pkcs7-signature.svg diff --git a/Resources/graphics/originals/tango or oxygen/osa_id_card.svg b/Graphics/drawables/originals/tango or oxygen/osa_id_card.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/osa_id_card.svg rename to Graphics/drawables/originals/tango or oxygen/osa_id_card.svg diff --git a/Resources/graphics/originals/tango or oxygen/osa_padlock.svg b/Graphics/drawables/originals/tango or oxygen/osa_padlock.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/osa_padlock.svg rename to Graphics/drawables/originals/tango or oxygen/osa_padlock.svg diff --git a/Resources/graphics/originals/tango or oxygen/tango-style-pen.svg b/Graphics/drawables/originals/tango or oxygen/tango-style-pen.svg similarity index 100% rename from Resources/graphics/originals/tango or oxygen/tango-style-pen.svg rename to Graphics/drawables/originals/tango or oxygen/tango-style-pen.svg diff --git a/Resources/graphics/status_lock_closed.svg b/Graphics/drawables/status_lock_closed.svg similarity index 100% rename from Resources/graphics/status_lock_closed.svg rename to Graphics/drawables/status_lock_closed.svg diff --git a/Resources/graphics/status_lock_error.svg b/Graphics/drawables/status_lock_error.svg similarity index 100% rename from Resources/graphics/status_lock_error.svg rename to Graphics/drawables/status_lock_error.svg diff --git a/Resources/graphics/status_lock_open.svg b/Graphics/drawables/status_lock_open.svg similarity index 100% rename from Resources/graphics/status_lock_open.svg rename to Graphics/drawables/status_lock_open.svg diff --git a/Resources/graphics/status_signature_expired.svg b/Graphics/drawables/status_signature_expired.svg similarity index 100% rename from Resources/graphics/status_signature_expired.svg rename to Graphics/drawables/status_signature_expired.svg diff --git a/Resources/graphics/status_signature_expired_cutout.svg b/Graphics/drawables/status_signature_expired_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_expired_cutout.svg rename to Graphics/drawables/status_signature_expired_cutout.svg diff --git a/Resources/graphics/status_signature_invalid.svg b/Graphics/drawables/status_signature_invalid.svg similarity index 100% rename from Resources/graphics/status_signature_invalid.svg rename to Graphics/drawables/status_signature_invalid.svg diff --git a/Resources/graphics/status_signature_invalid_cutout.svg b/Graphics/drawables/status_signature_invalid_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_invalid_cutout.svg rename to Graphics/drawables/status_signature_invalid_cutout.svg diff --git a/Resources/graphics/status_signature_revoked.svg b/Graphics/drawables/status_signature_revoked.svg similarity index 100% rename from Resources/graphics/status_signature_revoked.svg rename to Graphics/drawables/status_signature_revoked.svg diff --git a/Resources/graphics/status_signature_revoked_cutout.svg b/Graphics/drawables/status_signature_revoked_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_revoked_cutout.svg rename to Graphics/drawables/status_signature_revoked_cutout.svg diff --git a/Resources/graphics/status_signature_unknown.svg b/Graphics/drawables/status_signature_unknown.svg similarity index 100% rename from Resources/graphics/status_signature_unknown.svg rename to Graphics/drawables/status_signature_unknown.svg diff --git a/Resources/graphics/status_signature_unknown_cutout.svg b/Graphics/drawables/status_signature_unknown_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_unknown_cutout.svg rename to Graphics/drawables/status_signature_unknown_cutout.svg diff --git a/Resources/graphics/status_signature_unverified.svg b/Graphics/drawables/status_signature_unverified.svg similarity index 100% rename from Resources/graphics/status_signature_unverified.svg rename to Graphics/drawables/status_signature_unverified.svg diff --git a/Resources/graphics/status_signature_unverified_cutout.svg b/Graphics/drawables/status_signature_unverified_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_unverified_cutout.svg rename to Graphics/drawables/status_signature_unverified_cutout.svg diff --git a/Resources/graphics/status_signature_verified.svg b/Graphics/drawables/status_signature_verified.svg similarity index 100% rename from Resources/graphics/status_signature_verified.svg rename to Graphics/drawables/status_signature_verified.svg diff --git a/Resources/graphics/status_signature_verified_cutout.svg b/Graphics/drawables/status_signature_verified_cutout.svg similarity index 100% rename from Resources/graphics/status_signature_verified_cutout.svg rename to Graphics/drawables/status_signature_verified_cutout.svg diff --git a/Graphics/get-material-icons.sh b/Graphics/get-material-icons.sh new file mode 100755 index 000000000..0d7d688f2 --- /dev/null +++ b/Graphics/get-material-icons.sh @@ -0,0 +1,16 @@ +# https://google.github.io/material-design-icons/ +cd ./android-icon-copier/ +python copy OpenKeychain action white search 24 +python copy OpenKeychain navigation white arrow_back 24 +python copy OpenKeychain navigation white close 24 +python copy OpenKeychain navigation white check 24 +python copy OpenKeychain navigation black expand_less 24 +python copy OpenKeychain navigation black expand_more 24 +python copy OpenKeychain navigation white refresh 24 + +# navigation drawer sections +python copy OpenKeychain communication black vpn_key 24 +python copy OpenKeychain action black lock_open 24 +python copy OpenKeychain action black lock_outline 24 +python copy OpenKeychain navigation black apps 24 +python copy OpenKeychain action black settings 24 \ No newline at end of file diff --git a/Resources/new icon/Feature Graphic.psd b/Graphics/material-launcher/Feature Graphic.psd similarity index 100% rename from Resources/new icon/Feature Graphic.psd rename to Graphics/material-launcher/Feature Graphic.psd diff --git a/Resources/new icon/Feature-Graphic.png b/Graphics/material-launcher/Feature-Graphic.png similarity index 100% rename from Resources/new icon/Feature-Graphic.png rename to Graphics/material-launcher/Feature-Graphic.png diff --git a/Resources/new icon/preview.psd b/Graphics/material-launcher/preview.psd similarity index 100% rename from Resources/new icon/preview.psd rename to Graphics/material-launcher/preview.psd diff --git a/Resources/new icon/preview1.png b/Graphics/material-launcher/preview1.png similarity index 100% rename from Resources/new icon/preview1.png rename to Graphics/material-launcher/preview1.png diff --git a/Resources/new icon/preview2.png b/Graphics/material-launcher/preview2.png similarity index 100% rename from Resources/new icon/preview2.png rename to Graphics/material-launcher/preview2.png diff --git a/Resources/new icon/preview3.png b/Graphics/material-launcher/preview3.png similarity index 100% rename from Resources/new icon/preview3.png rename to Graphics/material-launcher/preview3.png diff --git a/Resources/new icon/ready-launcher-icons/144/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/144/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/144/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/144/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/144/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/144/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/144/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/144/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/144/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/144/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/144/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/144/vector-src.png diff --git a/Resources/new icon/ready-launcher-icons/192/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/192/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/192/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/192/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/192/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/192/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/192/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/192/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/192/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/192/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/192/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/192/vector-src.png diff --git a/Resources/new icon/ready-launcher-icons/48/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/48/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/48/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/48/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/48/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/48/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/48/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/48/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/48/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/48/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/48/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/48/vector-src.png diff --git a/Resources/new icon/ready-launcher-icons/512/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/512/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/512/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/512/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/512/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/512/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/512/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/512/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/512/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/512/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/512/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/512/vector-src.png diff --git a/Resources/new icon/ready-launcher-icons/72/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/72/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/72/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/72/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/72/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/72/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/72/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/72/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/72/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/72/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/72/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/72/vector-src.png diff --git a/Resources/new icon/ready-launcher-icons/96/vector-src-blue.png b/Graphics/material-launcher/ready-launcher-icons/96/vector-src-blue.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/96/vector-src-blue.png rename to Graphics/material-launcher/ready-launcher-icons/96/vector-src-blue.png diff --git a/Resources/new icon/ready-launcher-icons/96/vector-src-purple.png b/Graphics/material-launcher/ready-launcher-icons/96/vector-src-purple.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/96/vector-src-purple.png rename to Graphics/material-launcher/ready-launcher-icons/96/vector-src-purple.png diff --git a/Resources/new icon/ready-launcher-icons/96/vector-src.png b/Graphics/material-launcher/ready-launcher-icons/96/vector-src.png similarity index 100% rename from Resources/new icon/ready-launcher-icons/96/vector-src.png rename to Graphics/material-launcher/ready-launcher-icons/96/vector-src.png diff --git a/Resources/new icon/vector-src blue.ai b/Graphics/material-launcher/vector-src blue.ai similarity index 100% rename from Resources/new icon/vector-src blue.ai rename to Graphics/material-launcher/vector-src blue.ai diff --git a/Resources/new icon/vector-src purple.ai b/Graphics/material-launcher/vector-src purple.ai similarity index 100% rename from Resources/new icon/vector-src purple.ai rename to Graphics/material-launcher/vector-src purple.ai diff --git a/Resources/new icon/vector-src purple.psd b/Graphics/material-launcher/vector-src purple.psd similarity index 100% rename from Resources/new icon/vector-src purple.psd rename to Graphics/material-launcher/vector-src purple.psd diff --git a/Resources/new icon/vector-src.ai b/Graphics/material-launcher/vector-src.ai similarity index 100% rename from Resources/new icon/vector-src.ai rename to Graphics/material-launcher/vector-src.ai diff --git a/Resources/new icon/vector-src.psd b/Graphics/material-launcher/vector-src.psd similarity index 100% rename from Resources/new icon/vector-src.psd rename to Graphics/material-launcher/vector-src.psd diff --git a/Graphics/material-launcher/vector-src.svg b/Graphics/material-launcher/vector-src.svg new file mode 100644 index 000000000..a4d255d48 --- /dev/null +++ b/Graphics/material-launcher/vector-src.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/new icon/vector.psd b/Graphics/material-launcher/vector.psd similarity index 100% rename from Resources/new icon/vector.psd rename to Graphics/material-launcher/vector.psd diff --git a/Graphics/update-drawables.sh b/Graphics/update-drawables.sh new file mode 100755 index 000000000..eef97c7c3 --- /dev/null +++ b/Graphics/update-drawables.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +APP_DIR=../OpenKeychain/src/main +MDPI_DIR=$APP_DIR/res/drawable-mdpi +HDPI_DIR=$APP_DIR/res/drawable-hdpi +XDPI_DIR=$APP_DIR/res/drawable-xhdpi +XXDPI_DIR=$APP_DIR/res/drawable-xxhdpi +XXXDPI_DIR=$APP_DIR/res/drawable-xxxhdpi +PLAY_DIR=./drawables/ +SRC_DIR=./drawables/ + + + +# Launcher Icon: +# ----------------------- +# mdpi: 48x48 +# hdpi: 72x72 +# xhdpi: 96x96 +# xxhdpi: 144x144. +# xxxhdpi 192x192. +# google play: 512x512 + +# Adobe Illustrator (.ai) exports by Tha Phlash are way better than the Inkscape exports (.svg) + +#NAME="ic_launcher" + +#inkscape -w 48 -h 48 -e "$MDPI_DIR/$NAME.png" $NAME.svg +#inkscape -w 72 -h 72 -e "$HDPI_DIR/$NAME.png" $NAME.svg +#inkscape -w 96 -h 96 -e "$XDPI_DIR/$NAME.png" $NAME.svg +#inkscape -w 144 -h 144 -e "$XXDPI_DIR/$NAME.png" $NAME.svg +#inkscape -w 192 -h 192 -e "$XXXDPI_DIR/$NAME.png" $NAME.svg +#inkscape -w 512 -h 512 -e "$PLAY_DIR/$NAME.png" $NAME.svg + +# Actionbar Icons +# ----------------------- +# mdpi: 32x32 +# hdpi: 48x48 +# xhdpi: 64x64 +# xxhdpi: 96x96 + +for NAME in "ic_action_nfc" "ic_action_qr_code" "ic_action_safeslinger" "ic_action_search_cloud" +do +echo $NAME +inkscape -w 32 -h 32 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 48 -h 48 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 64 -h 64 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 96 -h 96 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +done + +for NAME in "status_lock_closed" "status_lock_error" "status_lock_open" "status_signature_expired_cutout" "status_signature_expired" "status_signature_invalid_cutout" "status_signature_invalid" "status_signature_revoked_cutout" "status_signature_revoked" "status_signature_unknown_cutout" "status_signature_unknown" "status_signature_unverified_cutout" "status_signature_unverified" "status_signature_verified_cutout" "status_signature_verified" "key_flag_authenticate" "key_flag_certify" "key_flag_encrypt" "key_flag_sign" +do +echo $NAME +inkscape -w 24 -h 24 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 32 -h 32 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 48 -h 48 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 64 -h 64 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +done + +for NAME in "create_key_robot" +do +echo $NAME +inkscape -w 48 -h 48 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 64 -h 64 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 96 -h 96 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +inkscape -w 128 -h 128 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg" +done \ No newline at end of file diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java new file mode 100644 index 000000000..40ade064b --- /dev/null +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.operations; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowLog; +import org.spongycastle.bcpg.sig.KeyFlags; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; +import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; +import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel; +import org.sufficientlysecure.keychain.util.ProgressScaler; +import org.sufficientlysecure.keychain.util.TestingUtils; + +import java.io.PrintStream; +import java.security.Security; +import java.util.Iterator; + +@RunWith(RobolectricTestRunner.class) +@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19 +public class PromoteKeyOperationTest { + + static UncachedKeyRing mStaticRing; + static String mKeyPhrase1 = TestingUtils.genPassphrase(true); + + static PrintStream oldShadowStream; + + @BeforeClass + public static void setUpOnce() throws Exception { + Security.insertProviderAt(new BouncyCastleProvider(), 1); + oldShadowStream = ShadowLog.stream; + // ShadowLog.stream = System.out; + + PgpKeyOperation op = new PgpKeyOperation(null); + + { + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddUserIds.add("derp"); + parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1); + + PgpEditKeyResult result = op.createSecretKeyRing(parcel); + Assert.assertTrue("initial test key creation must succeed", result.success()); + Assert.assertNotNull("initial test key creation must succeed", result.getRing()); + + mStaticRing = result.getRing(); + } + + } + + @Before + public void setUp() throws Exception { + ProviderHelper providerHelper = new ProviderHelper(Robolectric.application); + + // don't log verbosely here, we're not here to test imports + ShadowLog.stream = oldShadowStream; + + providerHelper.savePublicKeyRing(mStaticRing.extractPublicKeyRing(), new ProgressScaler()); + + // ok NOW log verbosely! + ShadowLog.stream = System.out; + } + + @Test + public void testPromote() throws Exception { + PromoteKeyOperation op = new PromoteKeyOperation(Robolectric.application, + new ProviderHelper(Robolectric.application), null, null); + + PromoteKeyResult result = op.execute(mStaticRing.getMasterKeyId()); + + Assert.assertTrue("promotion must succeed", result.success()); + + { + CachedPublicKeyRing ring = new ProviderHelper(Robolectric.application) + .getCachedPublicKeyRing(mStaticRing.getMasterKeyId()); + Assert.assertTrue("key must have a secret now", ring.hasAnySecret()); + + Iterator it = mStaticRing.getPublicKeys(); + while (it.hasNext()) { + long keyId = it.next().getKeyId(); + Assert.assertEquals("all subkeys must be divert-to-card", + SecretKeyType.GNU_DUMMY, ring.getSecretKeyType(keyId)); + } + } + + // second attempt should fail + result = op.execute(mStaticRing.getMasterKeyId()); + Assert.assertFalse("promotion of secret key must fail", result.success()); + + } + +} diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java index 52115a76d..0288d2937 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java @@ -34,6 +34,8 @@ import org.spongycastle.bcpg.S2K; import org.spongycastle.bcpg.SecretKeyPacket; import org.spongycastle.bcpg.SecretSubkeyPacket; import org.spongycastle.bcpg.SignaturePacket; +import org.spongycastle.bcpg.UserAttributePacket; +import org.spongycastle.bcpg.UserAttributeSubpacket; import org.spongycastle.bcpg.UserIDPacket; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.provider.BouncyCastleProvider; @@ -657,7 +659,8 @@ public class PgpKeyOperationTest { { // re-add second subkey parcel.reset(); - parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, null)); + // re-certify the revoked subkey + parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true)); modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB); @@ -699,7 +702,7 @@ public class PgpKeyOperationTest { public void testSubkeyStrip() throws Exception { long keyId = KeyringTestingHelper.getSubkeyId(ring, 1); - parcel.mStripSubKeys.add(keyId); + parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null)); applyModificationWithChecks(parcel, ring, onlyA, onlyB); Assert.assertEquals("one extra packet in original", 1, onlyA.size()); @@ -725,7 +728,7 @@ public class PgpKeyOperationTest { public void testMasterStrip() throws Exception { long keyId = ring.getMasterKeyId(); - parcel.mStripSubKeys.add(keyId); + parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null)); applyModificationWithChecks(parcel, ring, onlyA, onlyB); Assert.assertEquals("one extra packet in original", 1, onlyA.size()); @@ -744,6 +747,44 @@ public class PgpKeyOperationTest { Assert.assertEquals("new packet secret key data should have length zero", 0, ((SecretKeyPacket) p).getSecretKeyData().length); Assert.assertNull("new packet should have no iv data", ((SecretKeyPacket) p).getIV()); + } + + @Test + public void testRestrictedStrip() throws Exception { + + long keyId = KeyringTestingHelper.getSubkeyId(ring, 1); + UncachedKeyRing modified; + + { // we should be able to change the stripped/divert status of subkeys without passphrase + parcel.reset(); + parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null)); + modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, null); + Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); + Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); + Assert.assertEquals("new packet should have GNU_DUMMY S2K type", + S2K.GNU_DUMMY_S2K, ((SecretKeyPacket) p).getS2K().getType()); + Assert.assertEquals("new packet should have GNU_DUMMY protection mode stripped", + S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY, ((SecretKeyPacket) p).getS2K().getProtectionMode()); + } + + { // and again, changing to divert-to-card + parcel.reset(); + byte[] serial = new byte[] { + 0x6a, 0x6f, 0x6c, 0x6f, 0x73, 0x77, 0x61, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, serial)); + modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, null); + Assert.assertEquals("one extra packet in modified", 1, onlyB.size()); + Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); + Assert.assertEquals("new packet should have GNU_DUMMY S2K type", + S2K.GNU_DUMMY_S2K, ((SecretKeyPacket) p).getS2K().getType()); + Assert.assertEquals("new packet should have GNU_DUMMY protection mode divert-to-card", + S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD, ((SecretKeyPacket) p).getS2K().getProtectionMode()); + Assert.assertArrayEquals("new packet should have correct serial number as iv", + serial, ((SecretKeyPacket) p).getIV()); + + } } @@ -864,6 +905,70 @@ public class PgpKeyOperationTest { } + @Test + public void testUserAttributeAdd() throws Exception { + + { + parcel.mAddUserAttribute.add(WrappedUserAttribute.fromData(new byte[0])); + assertModifyFailure("adding an empty user attribute should fail", ring, parcel, + LogType.MSG_MF_UAT_ERROR_EMPTY); + } + + parcel.reset(); + + Random r = new Random(); + int type = r.nextInt(110)+1; + byte[] data = new byte[r.nextInt(2000)]; + new Random().nextBytes(data); + + WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); + parcel.mAddUserAttribute.add(uat); + + UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); + + Assert.assertEquals("no extra packets in original", 0, onlyA.size()); + Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size()); + + Assert.assertTrue("keyring must contain added user attribute", + modified.getPublicKey().getUnorderedUserAttributes().contains(uat)); + + Packet p; + + p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); + Assert.assertTrue("first new packet must be user attribute", p instanceof UserAttributePacket); + { + UserAttributeSubpacket[] subpackets = ((UserAttributePacket) p).getSubpackets(); + Assert.assertEquals("user attribute packet must contain one subpacket", + 1, subpackets.length); + Assert.assertEquals("user attribute subpacket type must be as specified above", + type, subpackets[0].getType()); + Assert.assertArrayEquals("user attribute subpacket data must be as specified above", + data, subpackets[0].getData()); + } + + p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(1).buf)).readPacket(); + Assert.assertTrue("second new packet must be signature", p instanceof SignaturePacket); + Assert.assertEquals("signature type must be positive certification", + PGPSignature.POSITIVE_CERTIFICATION, ((SignaturePacket) p).getSignatureType()); + + // make sure packets can be distinguished by timestamp + Thread.sleep(1000); + + // applying the same modification AGAIN should not add more certifications but drop those + // as duplicates + modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, passphrase, true, false); + + Assert.assertEquals("duplicate modification: one extra packet in original", 1, onlyA.size()); + Assert.assertEquals("duplicate modification: one extra packet in modified", 1, onlyB.size()); + + p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket(); + Assert.assertTrue("lost packet must be signature", p instanceof SignaturePacket); + p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket(); + Assert.assertTrue("new packet must be signature", p instanceof SignaturePacket); + + } + + @Test public void testUserIdPrimary() throws Exception { @@ -1026,6 +1131,17 @@ public class PgpKeyOperationTest { } + @Test + public void testRestricted () throws Exception { + + CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0); + + parcel.mAddUserIds.add("discord"); + PgpKeyOperation op = new PgpKeyOperation(null); + PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, parcel, null); + Assert.assertFalse("non-restricted operations should fail without passphrase", result.success()); + } + private static UncachedKeyRing applyModificationWithChecks(SaveKeyringParcel parcel, UncachedKeyRing ring, ArrayList onlyA, diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java index 721d1a51d..f9e0d52c3 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java @@ -104,6 +104,12 @@ public class UncachedKeyringCanonicalizeTest { parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); + { + WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100, + "sunshine, sunshine, ladybugs awake~".getBytes()); + parcel.mAddUserAttribute.add(uat); + } + // passphrase is tested in PgpKeyOperationTest, just use empty here parcel.mNewUnlock = new ChangeUnlockParcel(""); PgpKeyOperation op = new PgpKeyOperation(null); @@ -116,7 +122,7 @@ public class UncachedKeyringCanonicalizeTest { staticRing = staticRing.canonicalize(new OperationLog(), 0).getUncachedKeyRing(); // just for later reference - totalPackets = 9; + totalPackets = 11; // we sleep here for a second, to make sure all new certificates have different timestamps Thread.sleep(1000); @@ -150,8 +156,8 @@ public class UncachedKeyringCanonicalizeTest { Assert.assertEquals("packet #4 should be signature", PacketTags.SIGNATURE, it.next().tag); - Assert.assertEquals("packet #5 should be secret subkey", - PacketTags.SECRET_SUBKEY, it.next().tag); + Assert.assertEquals("packet #5 should be user id", + PacketTags.USER_ATTRIBUTE, it.next().tag); Assert.assertEquals("packet #6 should be signature", PacketTags.SIGNATURE, it.next().tag); @@ -160,7 +166,12 @@ public class UncachedKeyringCanonicalizeTest { Assert.assertEquals("packet #8 should be signature", PacketTags.SIGNATURE, it.next().tag); - Assert.assertFalse("exactly 9 packets total", it.hasNext()); + Assert.assertEquals("packet #9 should be secret subkey", + PacketTags.SECRET_SUBKEY, it.next().tag); + Assert.assertEquals("packet #10 should be signature", + PacketTags.SIGNATURE, it.next().tag); + + Assert.assertFalse("exactly 11 packets total", it.hasNext()); Assert.assertArrayEquals("created keyring should be constant through canonicalization", ring.getEncoded(), ring.canonicalize(log, 0).getEncoded()); @@ -380,7 +391,7 @@ public class UncachedKeyringCanonicalizeTest { @Test public void testSubkeyDestroy() throws Exception { // signature for second key (first subkey) - UncachedKeyRing modified = KeyringTestingHelper.removePacket(ring, 6); + UncachedKeyRing modified = KeyringTestingHelper.removePacket(ring, 8); // canonicalization should fail, because there are no valid uids left CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0); @@ -424,7 +435,7 @@ public class UncachedKeyringCanonicalizeTest { secretKey.getPublicKey(), pKey.getPublicKey()); // inject in the right position - UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 6); + UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 8); // canonicalize, and check if we lose the bad signature CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0); @@ -449,7 +460,7 @@ public class UncachedKeyringCanonicalizeTest { secretKey.getPublicKey(), pKey.getPublicKey()); // inject in the right position - UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 6); + UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 8); // canonicalize, and check if we lose the bad signature CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0); @@ -481,10 +492,10 @@ public class UncachedKeyringCanonicalizeTest { secretKey, PGPSignature.SUBKEY_BINDING, subHashedPacketsGen, secretKey.getPublicKey(), pKey.getPublicKey()); - UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig1.getEncoded(), 8); - modified = KeyringTestingHelper.injectPacket(modified, sig2.getEncoded(), 9); - modified = KeyringTestingHelper.injectPacket(modified, sig1.getEncoded(), 10); - modified = KeyringTestingHelper.injectPacket(modified, sig3.getEncoded(), 11); + UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig1.getEncoded(), 10); + modified = KeyringTestingHelper.injectPacket(modified, sig2.getEncoded(), 11); + modified = KeyringTestingHelper.injectPacket(modified, sig1.getEncoded(), 12); + modified = KeyringTestingHelper.injectPacket(modified, sig3.getEncoded(), 13); // canonicalize, and check if we lose the bad signature CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0); @@ -512,13 +523,13 @@ public class UncachedKeyringCanonicalizeTest { // get subkey packets Iterator it = KeyringTestingHelper.parseKeyring(ring.getEncoded()); - RawPacket subKey = KeyringTestingHelper.getNth(it, 5); + RawPacket subKey = KeyringTestingHelper.getNth(it, 7); RawPacket subSig = it.next(); // inject at a second position UncachedKeyRing modified = ring; - modified = KeyringTestingHelper.injectPacket(modified, subKey.buf, 7); - modified = KeyringTestingHelper.injectPacket(modified, subSig.buf, 8); + modified = KeyringTestingHelper.injectPacket(modified, subKey.buf, 9); + modified = KeyringTestingHelper.injectPacket(modified, subSig.buf, 10); // canonicalize, and check if we lose the bad signature OperationLog log = new OperationLog(); @@ -557,7 +568,7 @@ public class UncachedKeyringCanonicalizeTest { sKey = new PGPSecretKey(masterSecretKey.getPrivateKey(), subPubKey, sha1Calc, false, keyEncryptor); } - UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sKey.getEncoded(), 5); + UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sKey.getEncoded(), 7); // canonicalize, and check if we lose the bad signature OperationLog log = new OperationLog(); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java index 7f6f480d4..ccd47d0ee 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java @@ -46,6 +46,7 @@ import java.io.ByteArrayInputStream; import java.security.Security; import java.util.ArrayList; import java.util.Iterator; +import java.util.Random; /** Tests for the UncachedKeyring.merge method. * @@ -97,6 +98,12 @@ public class UncachedKeyringMergeTest { parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); + { + WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100, + "sunshine, sunshine, ladybugs awake~".getBytes()); + parcel.mAddUserAttribute.add(uat); + } + // passphrase is tested in PgpKeyOperationTest, just use empty here parcel.mNewUnlock = new ChangeUnlockParcel(""); PgpKeyOperation op = new PgpKeyOperation(null); @@ -339,6 +346,36 @@ public class UncachedKeyringMergeTest { } } + @Test + public void testAddedUserAttributeSignature() throws Exception { + + final UncachedKeyRing modified; { + parcel.reset(); + + Random r = new Random(); + int type = r.nextInt(110)+1; + byte[] data = new byte[r.nextInt(2000)]; + new Random().nextBytes(data); + + WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); + parcel.mAddUserAttribute.add(uat); + + CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing( + ringA.getEncoded(), false, 0); + modified = op.modifySecretKeyRing(secretRing, parcel, "").getRing(); + } + + { + UncachedKeyRing merged = ringA.merge(modified, log, 0); + Assert.assertNotNull("merge must succeed", merged); + Assert.assertFalse( + "merging keyring with extra user attribute into its base should yield that same keyring", + KeyringTestingHelper.diffKeyrings(merged.getEncoded(), modified.getEncoded(), onlyA, onlyB) + ); + } + + } + private UncachedKeyRing mergeWithChecks(UncachedKeyRing a, UncachedKeyRing b) throws Exception { return mergeWithChecks(a, b, a); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java index a3c58a5c8..65395f1ab 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java @@ -37,6 +37,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Iterator; +import java.util.Random; @RunWith(RobolectricTestRunner.class) @org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19 @@ -59,6 +60,15 @@ public class UncachedKeyringTest { parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); + { + Random r = new Random(); + int type = r.nextInt(110)+1; + byte[] data = new byte[r.nextInt(2000)]; + new Random().nextBytes(data); + + WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data); + parcel.mAddUserAttribute.add(uat); + } // passphrase is tested in PgpKeyOperationTest, just use empty here parcel.mNewUnlock = new ChangeUnlockParcel(""); PgpKeyOperation op = new PgpKeyOperation(null); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java index e4a1d62ae..171ecc377 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java @@ -106,8 +106,8 @@ public class ProviderHelperSaveTest { UncachedKeyRing pub = readRingFromResource("/test-keys/mailvelope_07_no_key_flags.asc"); long keyId = pub.getMasterKeyId(); - Assert.assertNull("key flags should be null", - pub.canonicalize(new OperationLog(), 0).getPublicKey().getKeyUsage()); + Assert.assertEquals("key flags should be zero", + 0, (long) pub.canonicalize(new OperationLog(), 0).getPublicKey().getKeyUsage()); mProviderHelper.savePublicKeyRing(pub); @@ -117,7 +117,8 @@ public class ProviderHelperSaveTest { Assert.assertEquals("master key should be encryption key", keyId, pubRing.getEncryptId()); Assert.assertEquals("master key should be encryption key (cached)", keyId, cachedRing.getEncryptId()); - Assert.assertNull("canonicalized key flags should be null", pubRing.getPublicKey().getKeyUsage()); + Assert.assertEquals("canonicalized key flags should be zero", + 0, (long) pubRing.getPublicKey().getKeyUsage()); Assert.assertTrue("master key should be able to certify", pubRing.getPublicKey().canCertify()); Assert.assertTrue("master key should be allowed to sign", pubRing.getPublicKey().canSign()); Assert.assertTrue("master key should be able to encrypt", pubRing.getPublicKey().canEncrypt()); diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index ff3a63fd7..c55adc5cf 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -3,14 +3,13 @@ apply plugin: 'com.android.application' dependencies { // NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information - compile 'com.android.support:support-v4:21.0.2' - compile 'com.android.support:appcompat-v7:21.0.2' + compile 'com.android.support:support-v4:21.0.3' + compile 'com.android.support:appcompat-v7:21.0.3' + compile 'com.android.support:recyclerview-v7:21.0.3' compile project(':extern:openpgp-api-lib') compile project(':extern:openkeychain-api-lib') compile project(':extern:html-textview') compile project(':extern:StickyListHeaders:library') - compile project(':extern:zxing-qr-code') - compile project(':extern:zxing-android-integration') compile project(':extern:spongycastle:core') compile project(':extern:spongycastle:pg') compile project(':extern:spongycastle:pkix') @@ -21,6 +20,13 @@ dependencies { compile project(':extern:TokenAutoComplete:library') compile project(':extern:safeslinger-exchange') compile project(':extern:android-lockpattern:code') + + // TODO: include as submodule?: + compile 'com.journeyapps:zxing-android-embedded:2.0.1@aar' + compile 'com.journeyapps:zxing-android-integration:2.0.1@aar' + compile 'com.google.zxing:core:3.0.1' + compile 'com.jpardogo.materialtabstrip:library:1.0.8' + compile 'it.neokree:MaterialNavigationDrawer:1.3' } android { @@ -28,10 +34,15 @@ android { buildToolsVersion '21.1.1' defaultConfig { - minSdkVersion 9 + minSdkVersion 15 targetSdkVersion 21 } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + /* * To sign release build, create file gradle.properties in ~/.gradle/ with this content: * diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 9fc79e6f1..536b66319 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -31,10 +31,7 @@ For OI Filemanager it makes no difference, gpg files can't be associated --> - - - - + @@ -434,7 +431,7 @@ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java index 255ca1cde..3b281876f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java @@ -32,10 +32,10 @@ public class CloudSearch { public static ArrayList search(final String query, Preferences.CloudSearchPrefs cloudPrefs) throws Keyserver.CloudSearchFailureException { - final ArrayList servers = new ArrayList(); + final ArrayList servers = new ArrayList<>(); // it's a Vector for sync, multiple threads might report problems - final Vector problems = new Vector(); + final Vector problems = new Vector<>(); if (cloudPrefs.searchKeyserver) { servers.add(new HkpKeyserver(cloudPrefs.keyserver)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 7f07b8162..f39c552a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -234,7 +234,7 @@ public class HkpKeyserver extends Keyserver { @Override public ArrayList search(String query) throws QueryFailedException, QueryNeedsRepairException { - ArrayList results = new ArrayList(); + ArrayList results = new ArrayList<>(); if (query.length() < 3) { throw new QueryTooShortException(); @@ -305,7 +305,7 @@ public class HkpKeyserver extends Keyserver { entry.setRevoked(matcher.group(6).contains("r")); entry.setExpired(matcher.group(6).contains("e")); - ArrayList userIds = new ArrayList(); + ArrayList userIds = new ArrayList<>(); final String uidLines = matcher.group(7); final Matcher uidMatcher = UID_LINE.matcher(uidLines); while (uidMatcher.find()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index d60d7757b..1d5ee76a4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -89,7 +89,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { public ImportKeysListEntry createFromParcel(final Parcel source) { ImportKeysListEntry vr = new ImportKeysListEntry(); vr.mPrimaryUserId = source.readString(); - vr.mUserIds = new ArrayList(); + vr.mUserIds = new ArrayList<>(); source.readStringList(vr.mUserIds); vr.mMergedUserIds = (HashMap>) source.readSerializable(); vr.mKeyId = source.readLong(); @@ -103,7 +103,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { vr.mSecretKey = source.readByte() == 1; vr.mSelected = source.readByte() == 1; vr.mExtraData = source.readString(); - vr.mOrigins = new ArrayList(); + vr.mOrigins = new ArrayList<>(); source.readStringList(vr.mOrigins); return vr; @@ -265,8 +265,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable { mSecretKey = false; // do not select by default mSelected = false; - mUserIds = new ArrayList(); - mOrigins = new ArrayList(); + mUserIds = new ArrayList<>(); + mOrigins = new ArrayList<>(); } /** @@ -304,7 +304,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { } public void updateMergedUserIds() { - mMergedUserIds = new HashMap>(); + mMergedUserIds = new HashMap<>(); for (String userId : mUserIds) { String[] userIdSplit = KeyRing.splitUserId(userId); @@ -315,7 +315,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { // email if (userIdSplit[1] != null) { if (!mMergedUserIds.containsKey(userIdSplit[0])) { - HashSet emails = new HashSet(); + HashSet emails = new HashSet<>(); emails.add(userIdSplit[1]); mMergedUserIds.put(userIdSplit[0], emails); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java index 2363a40b3..e310e9a3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java @@ -36,7 +36,7 @@ public class KeybaseKeyserver extends Keyserver { @Override public ArrayList search(String query) throws QueryFailedException, QueryNeedsRepairException { - ArrayList results = new ArrayList(); + ArrayList results = new ArrayList<>(); if (query.startsWith("0x")) { // cut off "0x" if a user is searching for a key id @@ -81,7 +81,7 @@ public class KeybaseKeyserver extends Keyserver { final int algorithmId = match.getAlgorithmId(); entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitStrength, null)); - ArrayList userIds = new ArrayList(); + ArrayList userIds = new ArrayList<>(); String name = ""; if (fullName != null) { name = fullName + " " + name; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java index c400eb813..e796bdc91 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java @@ -77,6 +77,12 @@ public abstract class BaseOperation implements PassphraseCacheInterface { return mCancelled != null && mCancelled.get(); } + protected void setPreventCancel () { + if (mProgressable != null) { + mProgressable.setPreventCancel(); + } + } + @Override public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException { try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index a5eb95b07..3b391814e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -78,7 +78,7 @@ public class CertifyOperation extends BaseOperation { return new CertifyResult(CertifyResult.RESULT_ERROR, log); } - ArrayList certifiedKeys = new ArrayList(); + ArrayList certifiedKeys = new ArrayList<>(); log.add(LogType.MSG_CRT_CERTIFYING, 1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 4d466593b..106c62688 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -11,7 +11,6 @@ import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; -import org.sufficientlysecure.keychain.service.CertifyActionsParcel; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; @@ -29,7 +28,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * create key operations in PgpKeyOperation. It takes care of fetching * and saving the key before and after the operation. * - * @see CertifyActionsParcel + * @see SaveKeyringParcel * */ public class EditKeyOperation extends BaseOperation { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java index 6ca28142f..cd8a33c20 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java @@ -137,7 +137,7 @@ public class ImportExportOperation extends BaseOperation { } int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0; - ArrayList importedMasterKeyIds = new ArrayList(); + ArrayList importedMasterKeyIds = new ArrayList<>(); boolean cancelled = false; int position = 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java new file mode 100644 index 000000000..f10d11684 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java @@ -0,0 +1,103 @@ +package org.sufficientlysecure.keychain.operations; + +import android.content.Context; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; +import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; +import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; +import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.Progressable; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.ProgressScaler; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** An operation which promotes a public key ring to a secret one. + * + * This operation can only be applied to public key rings where no secret key + * is available. Doing this "promotes" the public key ring to a secret one + * without secret key material, using a GNU_DUMMY s2k type. + * + */ +public class PromoteKeyOperation extends BaseOperation { + + public PromoteKeyOperation(Context context, ProviderHelper providerHelper, + Progressable progressable, AtomicBoolean cancelled) { + super(context, providerHelper, progressable, cancelled); + } + + public PromoteKeyResult execute(long masterKeyId) { + + OperationLog log = new OperationLog(); + log.add(LogType.MSG_PR, 0); + + // Perform actual type change + UncachedKeyRing promotedRing; + { + + try { + + // This operation is only allowed for pure public keys + // TODO delete secret keys if they are stripped, or have been moved to the card? + if (mProviderHelper.getCachedPublicKeyRing(masterKeyId).hasAnySecret()) { + log.add(LogType.MSG_PR_ERROR_ALREADY_SECRET, 2); + return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null); + } + + log.add(LogType.MSG_PR_FETCHING, 1, + KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); + CanonicalizedPublicKeyRing pubRing = + mProviderHelper.getCanonicalizedPublicKeyRing(masterKeyId); + + // create divert-to-card secret key from public key + promotedRing = pubRing.createDummySecretRing(); + + } catch (PgpKeyNotFoundException e) { + log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2); + return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null); + } catch (NotFoundException e) { + log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2); + return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null); + } + } + + // If the edit operation didn't succeed, exit here + if (promotedRing == null) { + // error is already logged by modification + return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null); + } + + // Check if the action was cancelled + if (checkCancelled()) { + log.add(LogType.MSG_OPERATION_CANCELLED, 0); + return new PromoteKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null); + } + + // Cannot cancel from here on out! + setPreventCancel(); + + // Save the new keyring. + SaveKeyringResult saveResult = mProviderHelper + .saveSecretKeyRing(promotedRing, new ProgressScaler(mProgressable, 60, 95, 100)); + log.add(saveResult, 1); + + // If the save operation didn't succeed, exit here + if (!saveResult.success()) { + return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null); + } + + updateProgress(R.string.progress_done, 100, 100); + + log.add(LogType.MSG_PR_SUCCESS, 0); + return new PromoteKeyResult(PromoteKeyResult.RESULT_OK, log, promotedRing.getMasterKeyId()); + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 1388c0eac..d025727b5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -343,6 +343,18 @@ public abstract class OperationResult implements Parcelable { MSG_IP_UID_REORDER(LogLevel.DEBUG, R.string.msg_ip_uid_reorder), MSG_IP_UID_PROCESSING (LogLevel.DEBUG, R.string.msg_ip_uid_processing), MSG_IP_UID_REVOKED (LogLevel.DEBUG, R.string.msg_ip_uid_revoked), + MSG_IP_UAT_CLASSIFYING (LogLevel.DEBUG, R.string.msg_ip_uat_classifying), + MSG_IP_UAT_PROCESSING_IMAGE (LogLevel.DEBUG, R.string.msg_ip_uat_processing_image), + MSG_IP_UAT_PROCESSING_UNKNOWN (LogLevel.DEBUG, R.string.msg_ip_uat_processing_unknown), + MSG_IP_UAT_REVOKED (LogLevel.DEBUG, R.string.msg_ip_uat_revoked), + MSG_IP_UAT_CERT_BAD (LogLevel.WARN, R.string.msg_ip_uat_cert_bad), + MSG_IP_UAT_CERT_OLD (LogLevel.DEBUG, R.string.msg_ip_uat_cert_old), + MSG_IP_UAT_CERT_NONREVOKE (LogLevel.DEBUG, R.string.msg_ip_uat_cert_nonrevoke), + MSG_IP_UAT_CERT_NEW (LogLevel.DEBUG, R.string.msg_ip_uat_cert_new), + MSG_IP_UAT_CERT_ERROR (LogLevel.WARN, R.string.msg_ip_uat_cert_error), + MSG_IP_UAT_CERTS_UNKNOWN (LogLevel.DEBUG, R.plurals.msg_ip_uat_certs_unknown), + MSG_IP_UAT_CERT_GOOD_REVOKE (LogLevel.DEBUG, R.string.msg_ip_uat_cert_good_revoke), + MSG_IP_UAT_CERT_GOOD (LogLevel.DEBUG, R.string.msg_ip_uat_cert_good), // import secret MSG_IS(LogLevel.START, R.string.msg_is), @@ -416,6 +428,21 @@ public abstract class OperationResult implements Parcelable { MSG_KC_UID_REVOKE_OLD (LogLevel.DEBUG, R.string.msg_kc_uid_revoke_old), MSG_KC_UID_REMOVE (LogLevel.DEBUG, R.string.msg_kc_uid_remove), MSG_KC_UID_WARN_ENCODING (LogLevel.WARN, R.string.msg_kc_uid_warn_encoding), + MSG_KC_UAT_JPEG (LogLevel.DEBUG, R.string.msg_kc_uat_jpeg), + MSG_KC_UAT_UNKNOWN (LogLevel.DEBUG, R.string.msg_kc_uat_unknown), + MSG_KC_UAT_BAD_ERR (LogLevel.WARN, R.string.msg_kc_uat_bad_err), + MSG_KC_UAT_BAD_LOCAL (LogLevel.WARN, R.string.msg_kc_uat_bad_local), + MSG_KC_UAT_BAD_TIME (LogLevel.WARN, R.string.msg_kc_uat_bad_time), + MSG_KC_UAT_BAD_TYPE (LogLevel.WARN, R.string.msg_kc_uat_bad_type), + MSG_KC_UAT_BAD (LogLevel.WARN, R.string.msg_kc_uat_bad), + MSG_KC_UAT_CERT_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_cert_dup), + MSG_KC_UAT_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_dup), + MSG_KC_UAT_FOREIGN (LogLevel.DEBUG, R.string.msg_kc_uat_foreign), + MSG_KC_UAT_NO_CERT (LogLevel.DEBUG, R.string.msg_kc_uat_no_cert), + MSG_KC_UAT_REVOKE_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_revoke_dup), + MSG_KC_UAT_REVOKE_OLD (LogLevel.DEBUG, R.string.msg_kc_uat_revoke_old), + MSG_KC_UAT_REMOVE (LogLevel.DEBUG, R.string.msg_kc_uat_remove), + MSG_KC_UAT_WARN_ENCODING (LogLevel.WARN, R.string.msg_kc_uat_warn_encoding), // keyring consolidation @@ -446,6 +473,7 @@ public abstract class OperationResult implements Parcelable { // secret key modify MSG_MF (LogLevel.START, R.string.msg_mr), + MSG_MF_ERROR_DIVERT_SERIAL (LogLevel.ERROR, R.string.msg_mf_error_divert_serial), MSG_MF_ERROR_ENCODE (LogLevel.ERROR, R.string.msg_mf_error_encode), MSG_MF_ERROR_FINGERPRINT (LogLevel.ERROR, R.string.msg_mf_error_fingerprint), MSG_MF_ERROR_KEYID (LogLevel.ERROR, R.string.msg_mf_error_keyid), @@ -458,6 +486,7 @@ public abstract class OperationResult implements Parcelable { MSG_MF_ERROR_PASSPHRASE_MASTER(LogLevel.ERROR, R.string.msg_mf_error_passphrase_master), MSG_MF_ERROR_PAST_EXPIRY(LogLevel.ERROR, R.string.msg_mf_error_past_expiry), MSG_MF_ERROR_PGP (LogLevel.ERROR, R.string.msg_mf_error_pgp), + MSG_MF_ERROR_RESTRICTED(LogLevel.ERROR, R.string.msg_mf_error_restricted), MSG_MF_ERROR_REVOKED_PRIMARY (LogLevel.ERROR, R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_SIG (LogLevel.ERROR, R.string.msg_mf_error_sig), MSG_MF_ERROR_SUBKEY_MISSING(LogLevel.ERROR, R.string.msg_mf_error_subkey_missing), @@ -480,6 +509,9 @@ public abstract class OperationResult implements Parcelable { MSG_MF_UID_PRIMARY (LogLevel.INFO, R.string.msg_mf_uid_primary), MSG_MF_UID_REVOKE (LogLevel.INFO, R.string.msg_mf_uid_revoke), MSG_MF_UID_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_mf_uid_error_empty), + MSG_MF_UAT_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_mf_uat_error_empty), + MSG_MF_UAT_ADD_IMAGE (LogLevel.INFO, R.string.msg_mf_uat_add_image), + MSG_MF_UAT_ADD_UNKNOWN (LogLevel.INFO, R.string.msg_mf_uat_add_unknown), MSG_MF_UNLOCK_ERROR (LogLevel.ERROR, R.string.msg_mf_unlock_error), MSG_MF_UNLOCK (LogLevel.DEBUG, R.string.msg_mf_unlock), @@ -516,6 +548,13 @@ public abstract class OperationResult implements Parcelable { MSG_ED_FETCHING (LogLevel.DEBUG, R.string.msg_ed_fetching), MSG_ED_SUCCESS (LogLevel.OK, R.string.msg_ed_success), + // promote key + MSG_PR (LogLevel.START, R.string.msg_pr), + MSG_PR_ERROR_ALREADY_SECRET (LogLevel.ERROR, R.string.msg_pr_error_already_secret), + MSG_PR_ERROR_KEY_NOT_FOUND (LogLevel.ERROR, R.string.msg_pr_error_key_not_found), + MSG_PR_FETCHING (LogLevel.DEBUG, R.string.msg_pr_fetching), + MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success), + // messages used in UI code MSG_EK_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_ek_error_divert), MSG_EK_ERROR_DUMMY (LogLevel.ERROR, R.string.msg_ek_error_dummy), @@ -696,7 +735,7 @@ public abstract class OperationResult implements Parcelable { public static class OperationLog implements Iterable { - private final List mParcels = new ArrayList(); + private final List mParcels = new ArrayList<>(); /// Simple convenience method public void add(LogType type, int indent, Object... parameters) { @@ -721,7 +760,7 @@ public abstract class OperationResult implements Parcelable { } public boolean containsType(LogType type) { - for(LogEntryParcel entry : new IterableIterator(mParcels.iterator())) { + for(LogEntryParcel entry : new IterableIterator<>(mParcels.iterator())) { if (entry.mType == type) { return true; } @@ -730,7 +769,7 @@ public abstract class OperationResult implements Parcelable { } public boolean containsWarnings() { - for(LogEntryParcel entry : new IterableIterator(mParcels.iterator())) { + for(LogEntryParcel entry : new IterableIterator<>(mParcels.iterator())) { if (entry.mType.mLevel == LogLevel.WARN || entry.mType.mLevel == LogLevel.ERROR) { return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java new file mode 100644 index 000000000..af9aff84a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.operations.results; + +import android.os.Parcel; + +public class PromoteKeyResult extends OperationResult { + + public final Long mMasterKeyId; + + public PromoteKeyResult(int result, OperationLog log, Long masterKeyId) { + super(result, log); + mMasterKeyId = masterKeyId; + } + + public PromoteKeyResult(Parcel source) { + super(source); + mMasterKeyId = source.readLong(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeLong(mMasterKeyId); + } + + public static Creator CREATOR = new Creator() { + public PromoteKeyResult createFromParcel(final Parcel source) { + return new PromoteKeyResult(source); + } + + public PromoteKeyResult[] newArray(final int size) { + return new PromoteKeyResult[size]; + } + }; + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java index db0a9b137..bbf136dac 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.openpgp.PGPKeyRing; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.IterableIterator; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java index 3539a4ceb..b026d9257 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java @@ -53,7 +53,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey { public boolean canSign() { // if key flags subpacket is available, honor it! - if (getKeyUsage() != null) { + if (getKeyUsage() != 0) { return (getKeyUsage() & KeyFlags.SIGN_DATA) != 0; } @@ -66,7 +66,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey { public boolean canCertify() { // if key flags subpacket is available, honor it! - if (getKeyUsage() != null) { + if (getKeyUsage() != 0) { return (getKeyUsage() & KeyFlags.CERTIFY_OTHER) != 0; } @@ -79,7 +79,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey { public boolean canEncrypt() { // if key flags subpacket is available, honor it! - if (getKeyUsage() != null) { + if (getKeyUsage() != 0) { return (getKeyUsage() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0; } @@ -93,7 +93,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey { public boolean canAuthenticate() { // if key flags subpacket is available, honor it! - if (getKeyUsage() != null) { + if (getKeyUsage() != 0) { return (getKeyUsage() & KeyFlags.AUTHENTICATION) != 0; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java index 85ef3eaa4..c2506685d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java @@ -18,9 +18,11 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.bcpg.S2K; import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -76,7 +78,7 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing { public IterableIterator publicKeyIterator() { @SuppressWarnings("unchecked") final Iterator it = getRing().getPublicKeys(); - return new IterableIterator(new Iterator() { + return new IterableIterator<>(new Iterator() { @Override public boolean hasNext() { return it.hasNext(); @@ -94,4 +96,13 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing { }); } + /** Create a dummy secret ring from this key */ + public UncachedKeyRing createDummySecretRing () { + + PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), + S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY); + return new UncachedKeyRing(secRing); + + } + } \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java index cffb09420..40f2f48ad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -182,7 +182,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { * @return */ public LinkedList getSupportedHashAlgorithms() { - LinkedList supported = new LinkedList(); + LinkedList supported = new LinkedList<>(); if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { // No support for MD5 @@ -262,11 +262,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { spGen.setSignatureCreationTime(false, nfcCreationTimestamp); signatureGenerator.setHashedSubpackets(spGen.generate()); return signatureGenerator; - } catch (PgpKeyNotFoundException e) { + } catch (PgpKeyNotFoundException | PGPException e) { // TODO: simply throw PGPException! throw new PgpGeneralException("Error initializing signature!", e); - } catch (PGPException e) { - throw new PgpGeneralException("Error initializing signature!", e); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java index eb589c3f9..b5f6a5b09 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java @@ -18,27 +18,19 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.bcpg.S2K; -import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing { @@ -94,7 +86,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing { public IterableIterator secretKeyIterator() { final Iterator it = mRing.getSecretKeys(); - return new IterableIterator(new Iterator() { + return new IterableIterator<>(new Iterator() { @Override public boolean hasNext() { return it.hasNext(); @@ -114,7 +106,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing { public IterableIterator publicKeyIterator() { final Iterator it = getRing().getPublicKeys(); - return new IterableIterator(new Iterator() { + return new IterableIterator<>(new Iterator() { @Override public boolean hasNext() { return it.hasNext(); @@ -133,7 +125,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing { } public HashMap getLocalNotationData() { - HashMap result = new HashMap(); + HashMap result = new HashMap<>(); Iterator it = getRing().getPublicKey().getKeySignatures(); while (it.hasNext()) { WrappedSignature sig = new WrappedSignature(it.next()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java index aa324c7ed..ed4715681 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.pgp; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.Log; @@ -33,7 +32,7 @@ public class OpenPgpSignatureResultBuilder { // OpenPgpSignatureResult private boolean mSignatureOnly = false; private String mPrimaryUserId; - private ArrayList mUserIds = new ArrayList(); + private ArrayList mUserIds = new ArrayList<>(); private long mKeyId; // builder diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 128928bb3..aebb52a03 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -34,6 +34,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; @@ -134,7 +135,7 @@ public class PgpKeyOperation { public PgpKeyOperation(Progressable progress) { super(); if (progress != null) { - mProgress = new Stack(); + mProgress = new Stack<>(); mProgress.push(progress); } } @@ -287,13 +288,11 @@ public class PgpKeyOperation { // build new key pair return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); - } catch(NoSuchProviderException e) { + } catch(NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e); } catch(NoSuchAlgorithmException e) { log.add(LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent); return null; - } catch(InvalidAlgorithmParameterException e) { - throw new RuntimeException(e); } catch(PGPException e) { Log.e(Constants.TAG, "internal pgp error", e); log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent); @@ -388,6 +387,9 @@ public class PgpKeyOperation { * with a passphrase fails, the operation will fail with an unlocking error. More specific * handling of errors should be done in UI code! * + * If the passphrase is null, only a restricted subset of operations will be available, + * namely stripping of subkeys and changing the protection mode of dummy keys. + * */ public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel, String passphrase) { @@ -428,6 +430,11 @@ public class PgpKeyOperation { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } + // If we have no passphrase, only allow restricted operation + if (passphrase == null) { + return internalRestricted(sKR, saveParcel, log); + } + // read masterKeyFlags, and use the same as before. // since this is the master key, this contains at least CERTIFY_OTHER PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); @@ -478,7 +485,7 @@ public class PgpKeyOperation { PGPPublicKey modifiedPublicKey = masterPublicKey; // 2a. Add certificates for new user ids - subProgressPush(15, 25); + subProgressPush(15, 23); for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) { progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.mAddUserIds.size())); @@ -495,7 +502,7 @@ public class PgpKeyOperation { @SuppressWarnings("unchecked") Iterator it = modifiedPublicKey.getSignaturesForID(userId); if (it != null) { - for (PGPSignature cert : new IterableIterator(it)) { + for (PGPSignature cert : new IterableIterator<>(it)) { if (cert.getKeyID() != masterPublicKey.getKeyID()) { // foreign certificate?! error error error log.add(LogType.MSG_MF_ERROR_INTEGRITY, indent); @@ -522,8 +529,37 @@ public class PgpKeyOperation { } subProgressPop(); - // 2b. Add revocations for revoked user ids - subProgressPush(25, 40); + // 2b. Add certificates for new user ids + subProgressPush(23, 32); + for (int i = 0; i < saveParcel.mAddUserAttribute.size(); i++) { + + progress(R.string.progress_modify_adduat, (i - 1) * (100 / saveParcel.mAddUserAttribute.size())); + WrappedUserAttribute attribute = saveParcel.mAddUserAttribute.get(i); + + switch (attribute.getType()) { + // the 'none' type must not succeed + case WrappedUserAttribute.UAT_NONE: + log.add(LogType.MSG_MF_UAT_ERROR_EMPTY, indent); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + case WrappedUserAttribute.UAT_IMAGE: + log.add(LogType.MSG_MF_UAT_ADD_IMAGE, indent); + break; + default: + log.add(LogType.MSG_MF_UAT_ADD_UNKNOWN, indent); + break; + } + + PGPUserAttributeSubpacketVector vector = attribute.getVector(); + + // generate and add new certificate + PGPSignature cert = generateUserAttributeSignature(masterPrivateKey, + masterPublicKey, vector); + modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert); + } + subProgressPop(); + + // 2c. Add revocations for revoked user ids + subProgressPush(32, 40); for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) { progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / saveParcel.mRevokeUserIds.size())); @@ -685,6 +721,27 @@ public class PgpKeyOperation { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } + if (change.mDummyStrip || change.mDummyDivert != null) { + // IT'S DANGEROUS~ + // no really, it is. this operation irrevocably removes the private key data from the key + if (change.mDummyStrip) { + sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey()); + } else { + // the serial number must be 16 bytes in length + if (change.mDummyDivert.length != 16) { + log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL, + indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } + } + sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); + } + + // This doesn't concern us any further + if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) { + continue; + } + // expiry must not be in the past if (change.mExpiry != null && change.mExpiry != 0 && new Date(change.mExpiry*1000).before(new Date())) { @@ -775,30 +832,6 @@ public class PgpKeyOperation { } subProgressPop(); - // 4c. For each subkey to be stripped... do so - subProgressPush(65, 70); - for (int i = 0; i < saveParcel.mStripSubKeys.size(); i++) { - - progress(R.string.progress_modify_subkeystrip, (i-1) * (100 / saveParcel.mStripSubKeys.size())); - long strip = saveParcel.mStripSubKeys.get(i); - log.add(LogType.MSG_MF_SUBKEY_STRIP, - indent, KeyFormattingUtils.convertKeyIdToHex(strip)); - - PGPSecretKey sKey = sKR.getSecretKey(strip); - if (sKey == null) { - log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING, - indent+1, KeyFormattingUtils.convertKeyIdToHex(strip)); - return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); - } - - // IT'S DANGEROUS~ - // no really, it is. this operation irrevocably removes the private key data from the key - sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey()); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); - - } - subProgressPop(); - // 5. Generate and add new subkeys subProgressPush(70, 90); for (int i = 0; i < saveParcel.mAddSubKeys.size(); i++) { @@ -907,6 +940,73 @@ public class PgpKeyOperation { } + /** This method does the actual modifications in a keyring just like internal, except it + * supports only the subset of operations which require no passphrase, and will error + * otherwise. + */ + private PgpEditKeyResult internalRestricted(PGPSecretKeyRing sKR, SaveKeyringParcel saveParcel, + OperationLog log) { + + int indent = 1; + + progress(R.string.progress_modify, 0); + + // Make sure the saveParcel includes only operations available without passphrae! + if (!saveParcel.isRestrictedOnly()) { + log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } + + // Check if we were cancelled + if (checkCancelled()) { + log.add(LogType.MSG_OPERATION_CANCELLED, indent); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null); + } + + // The only operation we can do here: + // 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card) + subProgressPush(50, 60); + for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) { + + progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / saveParcel.mChangeSubKeys.size())); + SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i); + log.add(LogType.MSG_MF_SUBKEY_CHANGE, + indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); + + PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId); + if (sKey == null) { + log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING, + indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } + + if (change.mDummyStrip || change.mDummyDivert != null) { + // IT'S DANGEROUS~ + // no really, it is. this operation irrevocably removes the private key data from the key + if (change.mDummyStrip) { + sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey()); + } else { + // the serial number must be 16 bytes in length + if (change.mDummyDivert.length != 16) { + log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL, + indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId)); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } + sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mDummyDivert); + } + sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); + } + + } + + // And we're done! + progress(R.string.progress_done, 100); + log.add(LogType.MSG_MF_SUCCESS, indent); + return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR)); + + } + + private static PGPSecretKeyRing applyNewUnlock( PGPSecretKeyRing sKR, PGPPublicKey masterPublicKey, @@ -1174,6 +1274,26 @@ public class PgpKeyOperation { return sGen.generateCertification(userId, pKey); } + private static PGPSignature generateUserAttributeSignature( + PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, + PGPUserAttributeSubpacketVector vector) + throws IOException, PGPException, SignatureException { + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + + PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); + { + /* critical subpackets: we consider those important for a modern pgp implementation */ + hashedPacketsGen.setSignatureCreationTime(true, new Date()); + } + + sGen.setHashedSubpackets(hashedPacketsGen.generate()); + sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey); + return sGen.generateCertification(vector, pKey); + } + private static PGPSignature generateRevocationSignature( PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId) throws IOException, PGPException, SignatureException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index a445e161f..af85bd878 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SignatureSubpacketTags; +import org.spongycastle.bcpg.UserAttributeSubpacketTags; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; @@ -30,6 +31,7 @@ import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; @@ -443,7 +445,7 @@ public class UncachedKeyRing { } } - ArrayList processedUserIds = new ArrayList(); + ArrayList processedUserIds = new ArrayList<>(); for (byte[] rawUserId : new IterableIterator(masterKey.getRawUserIDs())) { String userId = Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId); @@ -468,7 +470,7 @@ public class UncachedKeyRing { @SuppressWarnings("unchecked") Iterator signaturesIt = masterKey.getSignaturesForID(rawUserId); if (signaturesIt != null) { - for (PGPSignature zert : new IterableIterator(signaturesIt)) { + for (PGPSignature zert : new IterableIterator<>(signaturesIt)) { WrappedSignature cert = new WrappedSignature(zert); long certId = cert.getKeyId(); @@ -605,6 +607,170 @@ public class UncachedKeyRing { return null; } + ArrayList processedUserAttributes = new ArrayList<>(); + for (PGPUserAttributeSubpacketVector userAttribute : + new IterableIterator(masterKey.getUserAttributes())) { + + if (userAttribute.getSubpacket(UserAttributeSubpacketTags.IMAGE_ATTRIBUTE) != null) { + log.add(LogType.MSG_KC_UAT_JPEG, indent); + } else { + log.add(LogType.MSG_KC_UAT_UNKNOWN, indent); + } + + try { + indent += 1; + + // check for duplicate user attributes + if (processedUserAttributes.contains(userAttribute)) { + log.add(LogType.MSG_KC_UAT_DUP, indent); + // strip out the first found user id with this name + modified = PGPPublicKey.removeCertification(modified, userAttribute); + } + processedUserAttributes.add(userAttribute); + + PGPSignature selfCert = null; + revocation = null; + + // look through signatures for this specific user id + @SuppressWarnings("unchecked") + Iterator signaturesIt = masterKey.getSignaturesForUserAttribute(userAttribute); + if (signaturesIt != null) { + for (PGPSignature zert : new IterableIterator<>(signaturesIt)) { + WrappedSignature cert = new WrappedSignature(zert); + long certId = cert.getKeyId(); + + int type = zert.getSignatureType(); + if (type != PGPSignature.DEFAULT_CERTIFICATION + && type != PGPSignature.NO_CERTIFICATION + && type != PGPSignature.CASUAL_CERTIFICATION + && type != PGPSignature.POSITIVE_CERTIFICATION + && type != PGPSignature.CERTIFICATION_REVOCATION) { + log.add(LogType.MSG_KC_UAT_BAD_TYPE, + indent, "0x" + Integer.toString(zert.getSignatureType(), 16)); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + continue; + } + + if (cert.getCreationTime().after(nowPlusOneDay)) { + // Creation date in the future? No way! + log.add(LogType.MSG_KC_UAT_BAD_TIME, indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + continue; + } + + if (cert.isLocal()) { + // Creation date in the future? No way! + log.add(LogType.MSG_KC_UAT_BAD_LOCAL, indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + continue; + } + + // If this is a foreign signature, ... + if (certId != masterKeyId) { + // never mind any further for public keys, but remove them from secret ones + if (isSecret()) { + log.add(LogType.MSG_KC_UAT_FOREIGN, + indent, KeyFormattingUtils.convertKeyIdToHex(certId)); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + } + continue; + } + + // Otherwise, first make sure it checks out + try { + cert.init(masterKey); + if (!cert.verifySignature(masterKey, userAttribute)) { + log.add(LogType.MSG_KC_UAT_BAD, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + continue; + } + } catch (PgpGeneralException e) { + log.add(LogType.MSG_KC_UAT_BAD_ERR, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + badCerts += 1; + continue; + } + + switch (type) { + case PGPSignature.DEFAULT_CERTIFICATION: + case PGPSignature.NO_CERTIFICATION: + case PGPSignature.CASUAL_CERTIFICATION: + case PGPSignature.POSITIVE_CERTIFICATION: + if (selfCert == null) { + selfCert = zert; + } else if (selfCert.getCreationTime().before(cert.getCreationTime())) { + log.add(LogType.MSG_KC_UAT_CERT_DUP, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, selfCert); + redundantCerts += 1; + selfCert = zert; + } else { + log.add(LogType.MSG_KC_UAT_CERT_DUP, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + redundantCerts += 1; + } + // If there is a revocation certificate, and it's older than this, drop it + if (revocation != null + && revocation.getCreationTime().before(selfCert.getCreationTime())) { + log.add(LogType.MSG_KC_UAT_REVOKE_OLD, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, revocation); + revocation = null; + redundantCerts += 1; + } + break; + + case PGPSignature.CERTIFICATION_REVOCATION: + // If this is older than the (latest) self cert, drop it + if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) { + log.add(LogType.MSG_KC_UAT_REVOKE_OLD, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + redundantCerts += 1; + continue; + } + // first revocation? remember it. + if (revocation == null) { + revocation = zert; + // more revocations? at least one is superfluous, then. + } else if (revocation.getCreationTime().before(cert.getCreationTime())) { + log.add(LogType.MSG_KC_UAT_REVOKE_DUP, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, revocation); + redundantCerts += 1; + revocation = zert; + } else { + log.add(LogType.MSG_KC_UAT_REVOKE_DUP, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute, zert); + redundantCerts += 1; + } + break; + } + } + } + + // If no valid certificate (if only a revocation) remains, drop it + if (selfCert == null && revocation == null) { + log.add(LogType.MSG_KC_UAT_REMOVE, + indent); + modified = PGPPublicKey.removeCertification(modified, userAttribute); + } + + } finally { + indent -= 1; + } + } + + // Replace modified key in the keyring ring = replacePublicKey(ring, modified); indent -= 1; @@ -612,7 +778,7 @@ public class UncachedKeyRing { } // Keep track of ids we encountered so far - Set knownIds = new HashSet(); + Set knownIds = new HashSet<>(); // Process all keys for (PGPPublicKey key : new IterableIterator(ring.getPublicKeys())) { @@ -852,8 +1018,8 @@ public class UncachedKeyRing { /** This operation merges information from a different keyring, returning a combined * UncachedKeyRing. * - * The combined keyring contains the subkeys and user ids of both input keyrings, but it does - * not necessarily have the canonicalized property. + * The combined keyring contains the subkeys, user ids and user attributes of both input + * keyrings, but it does not necessarily have the canonicalized property. * * @param other The UncachedKeyRing to merge. Must not be empty, and of the same masterKeyId * @return A consolidated UncachedKeyRing with the data of both input keyrings. Same type as @@ -876,7 +1042,7 @@ public class UncachedKeyRing { } // remember which certs we already added. this is cheaper than semantic deduplication - Set certs = new TreeSet(new Comparator() { + Set certs = new TreeSet<>(new Comparator() { public int compare(byte[] left, byte[] right) { // check for length equality if (left.length != right.length) { @@ -958,7 +1124,7 @@ public class UncachedKeyRing { if (signaturesIt == null) { continue; } - for (PGPSignature cert : new IterableIterator(signaturesIt)) { + for (PGPSignature cert : new IterableIterator<>(signaturesIt)) { // Don't merge foreign stuff into secret keys if (cert.getKeyID() != masterKeyId && isSecret()) { continue; @@ -973,6 +1139,32 @@ public class UncachedKeyRing { modified = PGPPublicKey.addCertification(modified, rawUserId, cert); } } + + // Copy over all user attribute certificates + for (PGPUserAttributeSubpacketVector vector : + new IterableIterator(key.getUserAttributes())) { + @SuppressWarnings("unchecked") + Iterator signaturesIt = key.getSignaturesForUserAttribute(vector); + // no signatures for this user attribute attribute, skip it + if (signaturesIt == null) { + continue; + } + for (PGPSignature cert : new IterableIterator<>(signaturesIt)) { + // Don't merge foreign stuff into secret keys + if (cert.getKeyID() != masterKeyId && isSecret()) { + continue; + } + byte[] encoded = cert.getEncoded(); + // Known cert, skip it + if (certs.contains(encoded)) { + continue; + } + newCerts += 1; + certs.add(encoded); + modified = PGPPublicKey.addCertification(modified, vector, cert); + } + } + // If anything changed, save the updated (sub)key if (modified != resultKey) { result = replacePublicKey(result, modified); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index fe3ab96a5..0fe1ccdb6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -20,10 +20,10 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ECPublicBCPGKey; import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -135,7 +135,7 @@ public class UncachedPublicKey { continue; } - for (PGPSignature sig : new IterableIterator(signaturesIt)) { + for (PGPSignature sig : new IterableIterator<>(signaturesIt)) { try { // if this is a revocation, this is not the user id @@ -199,7 +199,7 @@ public class UncachedPublicKey { } public ArrayList getUnorderedUserIds() { - ArrayList userIds = new ArrayList(); + ArrayList userIds = new ArrayList<>(); for (byte[] rawUserId : new IterableIterator(mPublicKey.getRawUserIDs())) { // use our decoding method userIds.add(Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId)); @@ -208,13 +208,22 @@ public class UncachedPublicKey { } public ArrayList getUnorderedRawUserIds() { - ArrayList userIds = new ArrayList(); + ArrayList userIds = new ArrayList<>(); for (byte[] userId : new IterableIterator(mPublicKey.getRawUserIDs())) { userIds.add(userId); } return userIds; } + public ArrayList getUnorderedUserAttributes() { + ArrayList userAttributes = new ArrayList<>(); + for (PGPUserAttributeSubpacketVector userAttribute : + new IterableIterator(mPublicKey.getUserAttributes())) { + userAttributes.add(new WrappedUserAttribute(userAttribute)); + } + return userAttributes; + } + public boolean isElGamalEncrypt() { return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT; } @@ -270,33 +279,83 @@ public class UncachedPublicKey { } } + public Iterator getSignaturesForUserAttribute(WrappedUserAttribute attribute) { + final Iterator it = mPublicKey.getSignaturesForUserAttribute(attribute.getVector()); + if (it != null) { + return new Iterator() { + public void remove() { + it.remove(); + } + public WrappedSignature next() { + return new WrappedSignature(it.next()); + } + public boolean hasNext() { + return it.hasNext(); + } + }; + } else { + return null; + } + } + /** Get all key usage flags. * If at least one key flag subpacket is present return these. If no * subpacket is present it returns null. * * Note that this method has package visiblity because it is used in test * cases. Certificates of UncachedPublicKey instances can NOT be assumed to - * be verified, so the result of this method should not be used in other - * places! + * be verified or even by the correct key, so the result of this method + * should never be used in other places! */ @SuppressWarnings("unchecked") Integer getKeyUsage() { if (mCacheUsage == null) { + PGPSignature mostRecentSig = null; for (PGPSignature sig : new IterableIterator(mPublicKey.getSignatures())) { if (mPublicKey.isMasterKey() && sig.getKeyID() != mPublicKey.getKeyID()) { continue; } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); + switch (sig.getSignatureType()) { + case PGPSignature.DEFAULT_CERTIFICATION: + case PGPSignature.POSITIVE_CERTIFICATION: + case PGPSignature.CASUAL_CERTIFICATION: + case PGPSignature.NO_CERTIFICATION: + case PGPSignature.SUBKEY_BINDING: + break; + // if this is not one of the above types, don't care + default: + continue; + } + + // If we have no sig yet, take the first we can get + if (mostRecentSig == null) { + mostRecentSig = sig; + continue; + } + + // If the new sig is less recent, skip it + if (mostRecentSig.getCreationTime().after(sig.getCreationTime())) { + continue; + } + + // Otherwise, note it down as the new "most recent" one + mostRecentSig = sig; + } + + // Initialize to 0 as cached but empty value, if there is no sig (can't happen + // for canonicalized keyring), or there is no KEY_FLAGS packet in the sig + mCacheUsage = 0; + if (mostRecentSig != null) { + // If a mostRecentSig has been found, (cache and) return its flags + PGPSignatureSubpacketVector hashed = mostRecentSig.getHashedSubPackets(); if (hashed != null && hashed.getSubpacket(SignatureSubpacketTags.KEY_FLAGS) != null) { - // init if at least one key flag subpacket has been found - if (mCacheUsage == null) { - mCacheUsage = 0; - } - mCacheUsage |= hashed.getKeyFlags(); + mCacheUsage = hashed.getKeyFlags(); } } + } return mCacheUsage; } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index c395ca52d..ade075d55 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -29,13 +29,13 @@ import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; -import java.security.SignatureException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -79,7 +79,7 @@ public class WrappedSignature { } public ArrayList getEmbeddedSignatures() { - ArrayList sigs = new ArrayList(); + ArrayList sigs = new ArrayList<>(); if (!mSig.hasSubpackets()) { return sigs; } @@ -199,12 +199,23 @@ public class WrappedSignature { } } + boolean verifySignature(PGPPublicKey key, PGPUserAttributeSubpacketVector attribute) throws PgpGeneralException { + try { + return mSig.verifyCertification(attribute, key); + } catch (PGPException e) { + throw new PgpGeneralException("Error!", e); + } + } + public boolean verifySignature(UncachedPublicKey key, byte[] rawUserId) throws PgpGeneralException { return verifySignature(key.getPublicKey(), rawUserId); } public boolean verifySignature(CanonicalizedPublicKey key, String uid) throws PgpGeneralException { return verifySignature(key.getPublicKey(), uid); } + public boolean verifySignature(UncachedPublicKey key, WrappedUserAttribute attribute) throws PgpGeneralException { + return verifySignature(key.getPublicKey(), attribute.getVector()); + } public static WrappedSignature fromBytes(byte[] data) { PGPObjectFactory factory = new PGPObjectFactory(data); @@ -243,7 +254,7 @@ public class WrappedSignature { } public HashMap getNotation() { - HashMap result = new HashMap(); + HashMap result = new HashMap<>(); // If there is any notation data if (mSig.getHashedSubPackets() != null diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java new file mode 100644 index 000000000..da6d8b287 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.BCPGInputStream; +import org.spongycastle.bcpg.BCPGOutputStream; +import org.spongycastle.bcpg.Packet; +import org.spongycastle.bcpg.UserAttributePacket; +import org.spongycastle.bcpg.UserAttributeSubpacket; +import org.spongycastle.bcpg.UserAttributeSubpacketInputStream; +import org.spongycastle.bcpg.UserAttributeSubpacketTags; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; + +public class WrappedUserAttribute implements Serializable { + + public static final int UAT_NONE = 0; + public static final int UAT_IMAGE = UserAttributeSubpacketTags.IMAGE_ATTRIBUTE; + + private PGPUserAttributeSubpacketVector mVector; + + WrappedUserAttribute(PGPUserAttributeSubpacketVector vector) { + mVector = vector; + } + + PGPUserAttributeSubpacketVector getVector() { + return mVector; + } + + public int getType() { + UserAttributeSubpacket[] subpackets = mVector.toSubpacketArray(); + if (subpackets.length > 0) { + return subpackets[0].getType(); + } + return 0; + } + + public static WrappedUserAttribute fromSubpacket (int type, byte[] data) { + UserAttributeSubpacket subpacket = new UserAttributeSubpacket(type, data); + PGPUserAttributeSubpacketVector vector = new PGPUserAttributeSubpacketVector( + new UserAttributeSubpacket[] { subpacket }); + + return new WrappedUserAttribute(vector); + + } + + public byte[] getEncoded () throws IOException { + UserAttributeSubpacket[] subpackets = mVector.toSubpacketArray(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (UserAttributeSubpacket subpacket : subpackets) { + subpacket.encode(out); + } + return out.toByteArray(); + } + + public static WrappedUserAttribute fromData (byte[] data) throws IOException { + UserAttributeSubpacketInputStream in = + new UserAttributeSubpacketInputStream(new ByteArrayInputStream(data)); + ArrayList list = new ArrayList(); + while (in.available() > 0) { + list.add(in.readPacket()); + } + UserAttributeSubpacket[] result = new UserAttributeSubpacket[list.size()]; + list.toArray(result); + return new WrappedUserAttribute( + new PGPUserAttributeSubpacketVector(result)); + } + + /** Writes this object to an ObjectOutputStream. */ + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BCPGOutputStream bcpg = new BCPGOutputStream(baos); + bcpg.writePacket(new UserAttributePacket(mVector.toSubpacketArray())); + out.writeObject(baos.toByteArray()); + + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + + byte[] data = (byte[]) in.readObject(); + BCPGInputStream bcpg = new BCPGInputStream(new ByteArrayInputStream(data)); + Packet p = bcpg.readPacket(); + if ( ! UserAttributePacket.class.isInstance(p)) { + throw new IOException("Could not decode UserAttributePacket!"); + } + mVector = new PGPUserAttributeSubpacketVector(((UserAttributePacket) p).getSubpackets()); + + } + + private void readObjectNoData() throws ObjectStreamException { + } + + @Override + public boolean equals(Object o) { + if (!WrappedUserAttribute.class.isInstance(o)) { + return false; + } + return mVector.equals(((WrappedUserAttribute) o).mVector); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 2c02e429d..f4e00c36c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -51,9 +51,11 @@ public class KeychainContract { String EXPIRY = "expiry"; } - interface UserIdsColumns { + interface UserPacketsColumns { String MASTER_KEY_ID = "master_key_id"; // foreign key to key_rings._ID + String TYPE = "type"; // not a database id String USER_ID = "user_id"; // not a database id + String ATTRIBUTE_DATA = "attribute_data"; // not a database id String RANK = "rank"; // ONLY used for sorting! no key, no nothing! String IS_PRIMARY = "is_primary"; String IS_REVOKED = "is_revoked"; @@ -105,7 +107,7 @@ public class KeychainContract { public static final String BASE_API_APPS = "api_apps"; public static final String PATH_ACCOUNTS = "accounts"; - public static class KeyRings implements BaseColumns, KeysColumns, UserIdsColumns { + public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns { public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID; public static final String IS_REVOKED = KeysColumns.IS_REVOKED; public static final String VERIFIED = CertsColumns.VERIFIED; @@ -225,7 +227,7 @@ public class KeychainContract { } - public static class UserIds implements UserIdsColumns, BaseColumns { + public static class UserPackets implements UserPacketsColumns, BaseColumns { public static final String VERIFIED = "verified"; public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); @@ -304,7 +306,7 @@ public class KeychainContract { } public static class Certs implements CertsColumns, BaseColumns { - public static final String USER_ID = UserIdsColumns.USER_ID; + public static final String USER_ID = UserPacketsColumns.USER_ID; public static final String SIGNER_UID = "signer_user_id"; public static final int UNVERIFIED = 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 84a50dc65..5ce5eec17 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -33,7 +33,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns; import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity; import org.sufficientlysecure.keychain.util.Log; @@ -52,7 +52,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 6; + private static final int DATABASE_VERSION = 7; static Boolean apgHack = false; private Context mContext; @@ -60,7 +60,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String KEY_RINGS_PUBLIC = "keyrings_public"; String KEY_RINGS_SECRET = "keyrings_secret"; String KEYS = "keys"; - String USER_IDS = "user_ids"; + String USER_PACKETS = "user_ids"; String CERTS = "certs"; String API_APPS = "api_apps"; String API_ACCOUNTS = "api_accounts"; @@ -106,18 +106,20 @@ public class KeychainDatabase extends SQLiteOpenHelper { + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; - private static final String CREATE_USER_IDS = - "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS + "(" - + UserIdsColumns.MASTER_KEY_ID + " INTEGER, " - + UserIdsColumns.USER_ID + " TEXT, " + private static final String CREATE_USER_PACKETS = + "CREATE TABLE IF NOT EXISTS " + Tables.USER_PACKETS + "(" + + UserPacketsColumns.MASTER_KEY_ID + " INTEGER, " + + UserPacketsColumns.TYPE + " INT, " + + UserPacketsColumns.USER_ID + " TEXT, " + + UserPacketsColumns.ATTRIBUTE_DATA + " BLOB, " - + UserIdsColumns.IS_PRIMARY + " INTEGER, " - + UserIdsColumns.IS_REVOKED + " INTEGER, " - + UserIdsColumns.RANK+ " INTEGER, " + + UserPacketsColumns.IS_PRIMARY + " INTEGER, " + + UserPacketsColumns.IS_REVOKED + " INTEGER, " + + UserPacketsColumns.RANK+ " INTEGER, " - + "PRIMARY KEY(" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.USER_ID + "), " - + "UNIQUE (" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.RANK + "), " - + "FOREIGN KEY(" + UserIdsColumns.MASTER_KEY_ID + ") REFERENCES " + + "PRIMARY KEY(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.USER_ID + "), " + + "UNIQUE (" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + "), " + + "FOREIGN KEY(" + UserPacketsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE" + ")"; @@ -138,7 +140,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ") REFERENCES " + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE," + "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ", " + CertsColumns.RANK + ") REFERENCES " - + Tables.USER_IDS + "(" + UserIdsColumns.MASTER_KEY_ID + ", " + UserIdsColumns.RANK + ") ON DELETE CASCADE" + + Tables.USER_PACKETS + "(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + ") ON DELETE CASCADE" + ")"; private static final String CREATE_API_APPS = @@ -189,7 +191,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL(CREATE_KEYRINGS_PUBLIC); db.execSQL(CREATE_KEYRINGS_SECRET); db.execSQL(CREATE_KEYS); - db.execSQL(CREATE_USER_IDS); + db.execSQL(CREATE_USER_PACKETS); db.execSQL(CREATE_CERTS); db.execSQL(CREATE_API_APPS); db.execSQL(CREATE_API_APPS_ACCOUNTS); @@ -238,6 +240,9 @@ public class KeychainDatabase extends SQLiteOpenHelper { case 5: // do consolidate for 3.0 beta3 // fall through + case 6: + db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER"); + db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB"); } // always do consolidate after upgrade diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index d40287690..72475472e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -37,7 +37,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.util.Log; @@ -205,7 +206,7 @@ public class KeychainProvider extends ContentProvider { return Keys.CONTENT_TYPE; case KEY_RING_USER_IDS: - return UserIds.CONTENT_TYPE; + return UserPackets.CONTENT_TYPE; case KEY_RING_SECRET: return KeyRings.CONTENT_ITEM_TYPE; @@ -247,7 +248,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_UNIFIED: case KEY_RINGS_FIND_BY_EMAIL: case KEY_RINGS_FIND_BY_SUBKEY: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); @@ -262,7 +263,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY); projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM); projectionMap.put(KeyRings.FINGERPRINT, Tables.KEYS + "." + Keys.FINGERPRINT); - projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID); + projectionMap.put(KeyRings.USER_ID, UserPackets.USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.KEY_RING_DATA @@ -296,11 +297,12 @@ public class KeychainProvider extends ContentProvider { qb.setTables( Tables.KEYS - + " INNER JOIN " + Tables.USER_IDS + " ON (" + + " INNER JOIN " + Tables.USER_PACKETS + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID - + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0" + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + // we KNOW that the rank zero user packet is a user id! + + " AND " + Tables.USER_PACKETS + "." + UserPackets.RANK + " = 0" + ") LEFT JOIN " + Tables.CERTS + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " @@ -376,7 +378,7 @@ public class KeychainProvider extends ContentProvider { String subkey = Long.valueOf(uri.getLastPathSegment()).toString(); qb.appendWhere(" AND EXISTS (" + " SELECT 1 FROM " + Tables.KEYS + " AS tmp" - + " WHERE tmp." + UserIds.MASTER_KEY_ID + + " WHERE tmp." + UserPackets.MASTER_KEY_ID + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND tmp." + Keys.KEY_ID + " = " + subkey + "" + ")"); @@ -398,15 +400,15 @@ public class KeychainProvider extends ContentProvider { if (i != 0) { emailWhere += " OR "; } - emailWhere += "tmp." + UserIds.USER_ID + " LIKE "; + emailWhere += "tmp." + UserPackets.USER_ID + " LIKE "; // match '*', so it has to be at the *end* of the user id emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">"); gotCondition = true; } if(gotCondition) { qb.appendWhere(" AND EXISTS (" - + " SELECT 1 FROM " + Tables.USER_IDS + " AS tmp" - + " WHERE tmp." + UserIds.MASTER_KEY_ID + + " SELECT 1 FROM " + Tables.USER_PACKETS + " AS tmp" + + " WHERE tmp." + UserPackets.MASTER_KEY_ID + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND (" + emailWhere + ")" + ")"); @@ -420,7 +422,7 @@ public class KeychainProvider extends ContentProvider { } if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; + sortOrder = Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC"; } // uri to watch is all /key_rings/ @@ -430,7 +432,7 @@ public class KeychainProvider extends ContentProvider { } case KEY_RING_KEYS: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(Keys._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(Keys.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK); @@ -458,37 +460,45 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_USER_IDS: case KEY_RING_USER_IDS: { - HashMap projectionMap = new HashMap(); - projectionMap.put(UserIds._ID, Tables.USER_IDS + ".oid AS _id"); - projectionMap.put(UserIds.MASTER_KEY_ID, Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID); - projectionMap.put(UserIds.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID); - projectionMap.put(UserIds.RANK, Tables.USER_IDS + "." + UserIds.RANK); - projectionMap.put(UserIds.IS_PRIMARY, Tables.USER_IDS + "." + UserIds.IS_PRIMARY); - projectionMap.put(UserIds.IS_REVOKED, Tables.USER_IDS + "." + UserIds.IS_REVOKED); + HashMap projectionMap = new HashMap<>(); + projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); + projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); + projectionMap.put(UserPackets.TYPE, Tables.USER_PACKETS + "." + UserPackets.TYPE); + projectionMap.put(UserPackets.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); + projectionMap.put(UserPackets.ATTRIBUTE_DATA, Tables.USER_PACKETS + "." + UserPackets.ATTRIBUTE_DATA); + projectionMap.put(UserPackets.RANK, Tables.USER_PACKETS + "." + UserPackets.RANK); + projectionMap.put(UserPackets.IS_PRIMARY, Tables.USER_PACKETS + "." + UserPackets.IS_PRIMARY); + projectionMap.put(UserPackets.IS_REVOKED, Tables.USER_PACKETS + "." + UserPackets.IS_REVOKED); // we take the minimum (>0) here, where "1" is "verified by known secret key" - projectionMap.put(UserIds.VERIFIED, "MIN(" + Certs.VERIFIED + ") AS " + UserIds.VERIFIED); + projectionMap.put(UserPackets.VERIFIED, "MIN(" + Certs.VERIFIED + ") AS " + UserPackets.VERIFIED); qb.setProjectionMap(projectionMap); - qb.setTables(Tables.USER_IDS + qb.setTables(Tables.USER_PACKETS + " LEFT JOIN " + Tables.CERTS + " ON (" - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " = " + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = " + Tables.CERTS + "." + Certs.MASTER_KEY_ID - + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = " + + " AND " + Tables.USER_PACKETS + "." + UserPackets.RANK + " = " + Tables.CERTS + "." + Certs.RANK + " AND " + Tables.CERTS + "." + Certs.VERIFIED + " > 0" + ")"); - groupBy = Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID - + ", " + Tables.USER_IDS + "." + UserIds.RANK; + groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + + ", " + Tables.USER_PACKETS + "." + UserPackets.RANK; + + // for now, we only respect user ids here, so TYPE must be NULL + // TODO expand with KEY_RING_USER_PACKETS query type which lifts this restriction + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"); // If we are searching for a particular keyring's ids, add where if (match == KEY_RING_USER_IDS) { - qb.appendWhere(Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " = "); + // TODO remove with the thing above + qb.appendWhere(" AND "); + qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(1)); } if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " ASC" - + "," + Tables.USER_IDS + "." + UserIds.RANK + " ASC"; + sortOrder = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " ASC" + + "," + Tables.USER_PACKETS + "." + UserPackets.RANK + " ASC"; } break; @@ -497,7 +507,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_PUBLIC: case KEY_RING_PUBLIC: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id"); projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID); projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA); @@ -515,7 +525,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RINGS_SECRET: case KEY_RING_SECRET: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id"); projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID); projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA); @@ -533,7 +543,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RING_CERTS: case KEY_RING_CERTS_SPECIFIC: { - HashMap projectionMap = new HashMap(); + HashMap projectionMap = new HashMap<>(); projectionMap.put(Certs._ID, Tables.CERTS + ".oid AS " + Certs._ID); projectionMap.put(Certs.MASTER_KEY_ID, Tables.CERTS + "." + Certs.MASTER_KEY_ID); projectionMap.put(Certs.RANK, Tables.CERTS + "." + Certs.RANK); @@ -542,20 +552,24 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(Certs.CREATION, Tables.CERTS + "." + Certs.CREATION); projectionMap.put(Certs.KEY_ID_CERTIFIER, Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER); projectionMap.put(Certs.DATA, Tables.CERTS + "." + Certs.DATA); - projectionMap.put(Certs.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID); - projectionMap.put(Certs.SIGNER_UID, "signer." + UserIds.USER_ID + " AS " + Certs.SIGNER_UID); + projectionMap.put(Certs.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); + projectionMap.put(Certs.SIGNER_UID, "signer." + UserPackets.USER_ID + " AS " + Certs.SIGNER_UID); qb.setProjectionMap(projectionMap); qb.setTables(Tables.CERTS - + " JOIN " + Tables.USER_IDS + " ON (" + + " JOIN " + Tables.USER_PACKETS + " ON (" + Tables.CERTS + "." + Certs.MASTER_KEY_ID + " = " - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " AND " + Tables.CERTS + "." + Certs.RANK + " = " - + Tables.USER_IDS + "." + UserIds.RANK - + ") LEFT JOIN " + Tables.USER_IDS + " AS signer ON (" + + Tables.USER_PACKETS + "." + UserPackets.RANK + // for now, we only return user ids here, so TYPE must be NULL + // TODO at some point, we should lift this restriction + + " AND " + + Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL" + + ") LEFT JOIN " + Tables.USER_PACKETS + " AS signer ON (" + Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER + " = " - + "signer." + UserIds.MASTER_KEY_ID + + "signer." + UserPackets.MASTER_KEY_ID + " AND " + "signer." + Keys.RANK + " = 0" + ")"); @@ -662,8 +676,18 @@ public class KeychainProvider extends ContentProvider { break; case KEY_RING_USER_IDS: - db.insertOrThrow(Tables.USER_IDS, null, values); - keyId = values.getAsLong(UserIds.MASTER_KEY_ID); + // iff TYPE is null, user_id MUST be null as well + if ( ! (values.get(UserPacketsColumns.TYPE) == null + ? (values.get(UserPacketsColumns.USER_ID) != null && values.get(UserPacketsColumns.ATTRIBUTE_DATA) == null) + : (values.get(UserPacketsColumns.ATTRIBUTE_DATA) != null && values.get(UserPacketsColumns.USER_ID) == null) + )) { + throw new AssertionError("Incorrect type for user packet! This is a bug!"); + } + if (values.get(UserPacketsColumns.RANK) == 0 && values.get(UserPacketsColumns.USER_ID) == null) { + throw new AssertionError("Rank 0 user packet must be a user id!"); + } + db.insertOrThrow(Tables.USER_PACKETS, null, values); + keyId = values.getAsLong(UserPackets.MASTER_KEY_ID); break; case KEY_RING_CERTS: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 4f1b4b6c1..a229f454f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -31,6 +31,8 @@ import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; @@ -53,7 +55,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; @@ -169,7 +170,7 @@ public class ProviderHelper { Cursor cursor = mContentResolver.query(uri, proj, selection, null, null); try { - HashMap result = new HashMap(proj.length); + HashMap result = new HashMap<>(proj.length); if (cursor != null && cursor.moveToFirst()) { int pos = 0; for (String p : proj) { @@ -220,7 +221,7 @@ public class ProviderHelper { }, KeyRings.HAS_ANY_SECRET + " = 1", null, null); try { - LongSparseArray result = new LongSparseArray(); + LongSparseArray result = new LongSparseArray<>(); if (cursor != null && cursor.moveToFirst()) do { long masterKeyId = cursor.getLong(0); @@ -349,7 +350,7 @@ public class ProviderHelper { mIndent += 1; // save all keys and userIds included in keyRing object in database - operations = new ArrayList(); + operations = new ArrayList<>(); log(LogType.MSG_IP_INSERT_KEYRING); { // insert keyring @@ -439,18 +440,18 @@ public class ProviderHelper { // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. + List uids = new ArrayList<>(); + if (trustedKeys.size() == 0) { log(LogType.MSG_IP_UID_CLASSIFYING_ZERO); } else { log(LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size()); } mIndent += 1; - List uids = new ArrayList(); - for (byte[] rawUserId : new IterableIterator( - masterKey.getUnorderedRawUserIds().iterator())) { + for (byte[] rawUserId : masterKey.getUnorderedRawUserIds()) { String userId = Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId); - UserIdItem item = new UserIdItem(); + UserPacketItem item = new UserPacketItem(); uids.add(item); item.userId = userId; @@ -459,7 +460,7 @@ public class ProviderHelper { log(LogType.MSG_IP_UID_PROCESSING, userId); mIndent += 1; // look through signatures for this specific key - for (WrappedSignature cert : new IterableIterator( + for (WrappedSignature cert : new IterableIterator<>( masterKey.getSignaturesForRawId(rawUserId))) { long certId = cert.getKeyId(); // self signature @@ -533,6 +534,105 @@ public class ProviderHelper { } mIndent -= 1; + ArrayList userAttributes = masterKey.getUnorderedUserAttributes(); + // Don't spam the log if there aren't even any attributes + if ( ! userAttributes.isEmpty()) { + log(LogType.MSG_IP_UAT_CLASSIFYING); + } + + mIndent += 1; + for (WrappedUserAttribute userAttribute : userAttributes) { + + UserPacketItem item = new UserPacketItem(); + uids.add(item); + item.type = userAttribute.getType(); + item.attributeData = userAttribute.getEncoded(); + + int unknownCerts = 0; + + switch (item.type) { + case WrappedUserAttribute.UAT_IMAGE: + log(LogType.MSG_IP_UAT_PROCESSING_IMAGE); + break; + default: + log(LogType.MSG_IP_UAT_PROCESSING_UNKNOWN); + break; + } + mIndent += 1; + // look through signatures for this specific key + for (WrappedSignature cert : new IterableIterator<>( + masterKey.getSignaturesForUserAttribute(userAttribute))) { + long certId = cert.getKeyId(); + // self signature + if (certId == masterKeyId) { + + // NOTE self-certificates are already verified during canonicalization, + // AND we know there is at most one cert plus at most one revocation + if (!cert.isRevocation()) { + item.selfCert = cert; + } else { + item.isRevoked = true; + log(LogType.MSG_IP_UAT_REVOKED); + } + continue; + + } + + // do we have a trusted key for this? + if (trustedKeys.indexOfKey(certId) < 0) { + unknownCerts += 1; + continue; + } + + // verify signatures from known private keys + CanonicalizedPublicKey trustedKey = trustedKeys.get(certId); + + try { + cert.init(trustedKey); + // if it doesn't certify, leave a note and skip + if ( ! cert.verifySignature(masterKey, userAttribute)) { + log(LogType.MSG_IP_UAT_CERT_BAD); + continue; + } + + log(cert.isRevocation() + ? LogType.MSG_IP_UAT_CERT_GOOD_REVOKE + : LogType.MSG_IP_UAT_CERT_GOOD, + KeyFormattingUtils.convertKeyIdToHexShort(trustedKey.getKeyId()) + ); + + // check if there is a previous certificate + WrappedSignature prev = item.trustedCerts.get(cert.getKeyId()); + if (prev != null) { + // if it's newer, skip this one + if (prev.getCreationTime().after(cert.getCreationTime())) { + log(LogType.MSG_IP_UAT_CERT_OLD); + continue; + } + // if the previous one was a non-revokable certification, no need to look further + if (!prev.isRevocation() && !prev.isRevokable()) { + log(LogType.MSG_IP_UAT_CERT_NONREVOKE); + continue; + } + log(LogType.MSG_IP_UAT_CERT_NEW); + } + item.trustedCerts.put(cert.getKeyId(), cert); + + } catch (PgpGeneralException e) { + log(LogType.MSG_IP_UAT_CERT_ERROR, + KeyFormattingUtils.convertKeyIdToHex(cert.getKeyId())); + } + + } + + if (unknownCerts > 0) { + log(LogType.MSG_IP_UAT_CERTS_UNKNOWN, unknownCerts); + } + mIndent -= 1; + + } + mIndent -= 1; + progress.setProgress(LogType.MSG_IP_UID_REORDER.getMsgId(), 65, 100); log(LogType.MSG_IP_UID_REORDER); // primary before regular before revoked (see UserIdItem.compareTo) @@ -540,7 +640,7 @@ public class ProviderHelper { Collections.sort(uids); // iterate and put into db for (int userIdRank = 0; userIdRank < uids.size(); userIdRank++) { - UserIdItem item = uids.get(userIdRank); + UserPacketItem item = uids.get(userIdRank); operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); if (item.selfCert != null) { // TODO get rid of "self verified" status? this cannot even happen anymore! @@ -605,23 +705,31 @@ public class ProviderHelper { } - private static class UserIdItem implements Comparable { + private static class UserPacketItem implements Comparable { + Integer type; String userId; + byte[] attributeData; boolean isPrimary = false; boolean isRevoked = false; WrappedSignature selfCert; - LongSparseArray trustedCerts = new LongSparseArray(); + LongSparseArray trustedCerts = new LongSparseArray<>(); @Override - public int compareTo(UserIdItem o) { - // if one key is primary but the other isn't, the primary one always comes first - if (isPrimary != o.isPrimary) { - return isPrimary ? -1 : 1; - } + public int compareTo(UserPacketItem o) { // revoked keys always come last! if (isRevoked != o.isRevoked) { return isRevoked ? 1 : -1; } + // if one is a user id, but the other isn't, the user id always comes first. + // we compare for null values here, so != is the correct operator! + // noinspection NumberEquality + if (type != o.type) { + return type == null ? -1 : 1; + } + // if one key is primary but the other isn't, the primary one always comes first + if (isPrimary != o.isPrimary) { + return isPrimary ? -1 : 1; + } return 0; } } @@ -967,7 +1075,7 @@ public class ProviderHelper { // No keys existing might be a legitimate option, we write an empty file in that case cursor.moveToFirst(); ParcelableFileCache cache = - new ParcelableFileCache(mContext, "consolidate_secret.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); cache.writeCache(cursor.getCount(), new Iterator() { ParcelableKeyRing ring; @@ -1029,7 +1137,7 @@ public class ProviderHelper { // No keys existing might be a legitimate option, we write an empty file in that case cursor.moveToFirst(); ParcelableFileCache cache = - new ParcelableFileCache(mContext, "consolidate_public.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); cache.writeCache(cursor.getCount(), new Iterator() { ParcelableKeyRing ring; @@ -1112,9 +1220,9 @@ public class ProviderHelper { mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null); ParcelableFileCache cacheSecret = - new ParcelableFileCache(mContext, "consolidate_secret.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_secret.pcl"); ParcelableFileCache cachePublic = - new ParcelableFileCache(mContext, "consolidate_public.pcl"); + new ParcelableFileCache<>(mContext, "consolidate_public.pcl"); // Set flag that we have a cached consolidation here try { @@ -1234,15 +1342,17 @@ public class ProviderHelper { * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing */ private ContentProviderOperation - buildUserIdOperations(long masterKeyId, UserIdItem item, int rank) { + buildUserIdOperations(long masterKeyId, UserPacketItem item, int rank) { ContentValues values = new ContentValues(); - values.put(UserIds.MASTER_KEY_ID, masterKeyId); - values.put(UserIds.USER_ID, item.userId); - values.put(UserIds.IS_PRIMARY, item.isPrimary); - values.put(UserIds.IS_REVOKED, item.isRevoked); - values.put(UserIds.RANK, rank); + values.put(UserPackets.MASTER_KEY_ID, masterKeyId); + values.put(UserPackets.TYPE, item.type); + values.put(UserPackets.USER_ID, item.userId); + values.put(UserPackets.ATTRIBUTE_DATA, item.attributeData); + values.put(UserPackets.IS_PRIMARY, item.isPrimary); + values.put(UserPackets.IS_REVOKED, item.isRevoked); + values.put(UserPackets.RANK, rank); - Uri uri = UserIds.buildUserIdsUri(masterKeyId); + Uri uri = UserPackets.buildUserIdsUri(masterKeyId); return ContentProviderOperation.newInsert(uri).withValues(values).build(); } @@ -1270,7 +1380,7 @@ public class ProviderHelper { public ArrayList getRegisteredApiApps() { Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null); - ArrayList packageNames = new ArrayList(); + ArrayList packageNames = new ArrayList<>(); try { if (cursor != null) { int packageNameCol = cursor.getColumnIndex(ApiApps.PACKAGE_NAME); @@ -1375,7 +1485,7 @@ public class ProviderHelper { } public Set getAllKeyIdsForApp(Uri uri) { - Set keyIds = new HashSet(); + Set keyIds = new HashSet<>(); Cursor cursor = mContentResolver.query(uri, null, null, null, null); try { @@ -1395,7 +1505,7 @@ public class ProviderHelper { } public Set getAllFingerprints(Uri uri) { - Set fingerprints = new HashSet(); + Set fingerprints = new HashSet<>(); String[] projection = new String[]{KeyRings.FINGERPRINT}; Cursor cursor = mContentResolver.query(uri, projection, null, null, null); try { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 478013f55..f2af43b6f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -85,9 +85,9 @@ public class OpenPgpService extends RemoteService { boolean missingUserIdsCheck = false; boolean duplicateUserIdsCheck = false; - ArrayList keyIds = new ArrayList(); - ArrayList missingUserIds = new ArrayList(); - ArrayList duplicateUserIds = new ArrayList(); + ArrayList keyIds = new ArrayList<>(); + ArrayList missingUserIds = new ArrayList<>(); + ArrayList duplicateUserIds = new ArrayList<>(); if (!noUserIdsCheck) { for (String email : encryptionUserIds) { // try to find the key for this specific email diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java index e71b52ccd..672f59285 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java @@ -27,7 +27,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; -import android.text.TextUtils; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.util.OpenPgpApi; @@ -216,9 +215,7 @@ public abstract class RemoteService extends Service { String[] callingPackages = getPackageManager().getPackagesForUid(uid); // is calling package allowed to use this service? - for (int i = 0; i < callingPackages.length; i++) { - String currentPkg = callingPackages[i]; - + for (String currentPkg : callingPackages) { if (isPackageAllowed(currentPkg)) { return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java index 0e9678980..e5edd6a0f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java @@ -20,14 +20,13 @@ package org.sufficientlysecure.keychain.remote.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; +import org.sufficientlysecure.keychain.ui.BaseActivity; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.operations.results.OperationResult; @@ -35,7 +34,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp import org.sufficientlysecure.keychain.operations.results.SingletonResult; import org.sufficientlysecure.keychain.util.Log; -public class AccountSettingsActivity extends ActionBarActivity { +public class AccountSettingsActivity extends BaseActivity { private Uri mAccountUri; private AccountSettingsFragment mAccountSettingsFragment; @@ -45,17 +44,20 @@ public class AccountSettingsActivity extends ActionBarActivity { super.onCreate(savedInstanceState); // Inflate a "Done" custom action bar - ActionBarHelper.setOneButtonView(getSupportActionBar(), - R.string.api_settings_save, R.drawable.ic_action_done, + setFullScreenDialogDoneClose(R.string.api_settings_save, new View.OnClickListener() { @Override public void onClick(View v) { - // "Done" save(); } + }, + new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } }); - setContentView(R.layout.api_account_settings_activity); mAccountSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById( R.id.api_account_settings_fragment); @@ -72,6 +74,11 @@ public class AccountSettingsActivity extends ActionBarActivity { } } + @Override + protected void initLayout() { + setContentView(R.layout.api_account_settings_activity); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -125,9 +132,4 @@ public class AccountSettingsActivity extends ActionBarActivity { } } - @Override - public void onBackPressed() { - save(); - super.onBackPressed(); - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java index 56e3b22e2..e91482e28 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java @@ -22,8 +22,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; @@ -33,9 +31,10 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.ui.BaseActivity; import org.sufficientlysecure.keychain.util.Log; -public class AppSettingsActivity extends ActionBarActivity { +public class AppSettingsActivity extends BaseActivity { private Uri mAppUri; private AppSettingsFragment mSettingsFragment; @@ -49,12 +48,11 @@ public class AppSettingsActivity extends ActionBarActivity { super.onCreate(savedInstanceState); // let the actionbar look like Android's contact app - ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setIcon(android.R.color.transparent); - actionBar.setHomeButtonEnabled(true); +// ActionBar actionBar = getSupportActionBar(); +// actionBar.setDisplayHomeAsUpEnabled(true); +// actionBar.setIcon(android.R.color.transparent); +// actionBar.setHomeButtonEnabled(true); - setContentView(R.layout.api_app_settings_activity); mSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( R.id.api_app_settings_fragment); @@ -71,6 +69,11 @@ public class AppSettingsActivity extends ActionBarActivity { } } + @Override + protected void initLayout() { + setContentView(R.layout.api_app_settings_activity); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java index 11b0deb33..3b4cc654e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java @@ -21,16 +21,27 @@ import android.os.Bundle; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.DrawerActivity; +import org.sufficientlysecure.keychain.ui.NavDrawerActivity; -public class AppsListActivity extends DrawerActivity { +public class AppsListActivity extends NavDrawerActivity { + +// @Override +// protected void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// +// activateDrawerNavigation(savedInstanceState); +// } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - + public void init(Bundle savedInstanceState) { + super.init(savedInstanceState); setContentView(R.layout.api_apps_list_activity); - - activateDrawerNavigation(savedInstanceState); } + +// @Override +// protected void initLayout() { +// setContentView(R.layout.api_apps_list_activity); +// } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java index d7b723eb0..cbc593b0a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java @@ -22,7 +22,6 @@ import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -39,14 +38,14 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AppSettings; +import org.sufficientlysecure.keychain.ui.BaseActivity; import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; -public class RemoteServiceActivity extends ActionBarActivity { +public class RemoteServiceActivity extends BaseActivity { public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER"; public static final String ACTION_CREATE_ACCOUNT = Constants.INTENT_PREFIX @@ -96,235 +95,250 @@ public class RemoteServiceActivity extends ActionBarActivity { handleActions(getIntent(), savedInstanceState); } + @Override + protected void initLayout() { + // done in handleActions() + } + protected void handleActions(Intent intent, Bundle savedInstanceState) { String action = intent.getAction(); final Bundle extras = intent.getExtras(); - if (ACTION_REGISTER.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE); - Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName); + switch (action) { + case ACTION_REGISTER: { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE); + Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName); - setContentView(R.layout.api_remote_register_app); + setContentView(R.layout.api_remote_register_app); + initToolbar(); - mAppSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( - R.id.api_app_settings_fragment); + mAppSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( + R.id.api_app_settings_fragment); - AppSettings settings = new AppSettings(packageName, packageSignature); - mAppSettingsFragment.setAppSettings(settings); + AppSettings settings = new AppSettings(packageName, packageSignature); + mAppSettingsFragment.setAppSettings(settings); - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), - R.string.api_register_allow, R.drawable.ic_action_done, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Allow + // Inflate a "Done"/"Cancel" custom action bar view + setFullScreenDialogTwoButtons( + R.string.api_register_allow, R.drawable.ic_check_white_24dp, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Allow - mProviderHelper.insertApiApp(mAppSettingsFragment.getAppSettings()); - - // give data through for new service call - Intent resultData = extras.getParcelable(EXTRA_DATA); - RemoteServiceActivity.this.setResult(RESULT_OK, resultData); - RemoteServiceActivity.this.finish(); - } - }, R.string.api_register_disallow, R.drawable.ic_action_cancel, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Disallow - RemoteServiceActivity.this.setResult(RESULT_CANCELED); - RemoteServiceActivity.this.finish(); - } - } - ); - } else if (ACTION_CREATE_ACCOUNT.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - final String accName = extras.getString(EXTRA_ACC_NAME); - - setContentView(R.layout.api_remote_create_account); - - mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById( - R.id.api_account_settings_fragment); - - TextView text = (TextView) findViewById(R.id.api_remote_create_account_text); - - // update existing? - Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName); - AccountSettings settings = mProviderHelper.getApiAccountSettings(uri); - if (settings == null) { - // create new account - settings = new AccountSettings(accName); - mUpdateExistingAccount = false; - - text.setText(R.string.api_create_account_text); - } else { - // update existing account - mUpdateExistingAccount = true; - - text.setText(R.string.api_update_account_text); - } - mAccSettingsFragment.setAccSettings(settings); - - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), - R.string.api_settings_save, R.drawable.ic_action_done, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Save - - // user needs to select a key if it has explicitly requested (None is only allowed for new accounts) - if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) { - Notify.showNotify(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR); - } else { - if (mUpdateExistingAccount) { - Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName); - Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build(); - mProviderHelper.updateApiAccount( - accountUri, - mAccSettingsFragment.getAccSettings()); - } else { - mProviderHelper.insertApiAccount( - KeychainContract.ApiAccounts.buildBaseUri(packageName), - mAccSettingsFragment.getAccSettings()); - } + mProviderHelper.insertApiApp(mAppSettingsFragment.getAppSettings()); // give data through for new service call Intent resultData = extras.getParcelable(EXTRA_DATA); RemoteServiceActivity.this.setResult(RESULT_OK, resultData); RemoteServiceActivity.this.finish(); } + }, R.string.api_register_disallow, R.drawable.ic_close_white_24dp, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Disallow + RemoteServiceActivity.this.setResult(RESULT_CANCELED); + RemoteServiceActivity.this.finish(); + } } - }, R.string.api_settings_cancel, R.drawable.ic_action_cancel, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Cancel - RemoteServiceActivity.this.setResult(RESULT_CANCELED); - RemoteServiceActivity.this.finish(); - } - } - ); - - } else if (ACTION_SELECT_PUB_KEYS.equals(action)) { - long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); - boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true); - ArrayList missingUserIds = intent - .getStringArrayListExtra(EXTRA_MISSING_USER_IDS); - ArrayList dublicateUserIds = intent - .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS); - - SpannableStringBuilder ssb = new SpannableStringBuilder(); - final SpannableString textIntro = new SpannableString( - noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids) - : getString(R.string.api_select_pub_keys_text) - ); - textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append(textIntro); - - if (missingUserIds != null && missingUserIds.size() > 0) { - ssb.append("\n\n"); - ssb.append(getString(R.string.api_select_pub_keys_missing_text)); - ssb.append("\n"); - for (String userId : missingUserIds) { - SpannableString ss = new SpannableString(userId + "\n"); - ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append(ss); - } + ); + break; } - if (dublicateUserIds != null && dublicateUserIds.size() > 0) { - ssb.append("\n\n"); - ssb.append(getString(R.string.api_select_pub_keys_dublicates_text)); - ssb.append("\n"); - for (String userId : dublicateUserIds) { - SpannableString ss = new SpannableString(userId + "\n"); - ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append(ss); + case ACTION_CREATE_ACCOUNT: { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + final String accName = extras.getString(EXTRA_ACC_NAME); + + setContentView(R.layout.api_remote_create_account); + initToolbar(); + + mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById( + R.id.api_account_settings_fragment); + + TextView text = (TextView) findViewById(R.id.api_remote_create_account_text); + + // update existing? + Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName); + AccountSettings settings = mProviderHelper.getApiAccountSettings(uri); + if (settings == null) { + // create new account + settings = new AccountSettings(accName); + mUpdateExistingAccount = false; + + text.setText(R.string.api_create_account_text); + } else { + // update existing account + mUpdateExistingAccount = true; + + text.setText(R.string.api_update_account_text); } + mAccSettingsFragment.setAccSettings(settings); + + // Inflate a "Done"/"Cancel" custom action bar view + setFullScreenDialogDoneClose(R.string.api_settings_save, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Save + + // user needs to select a key if it has explicitly requested (None is only allowed for new accounts) + if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) { + Notify.showNotify(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR); + } else { + if (mUpdateExistingAccount) { + Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName); + Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build(); + mProviderHelper.updateApiAccount( + accountUri, + mAccSettingsFragment.getAccSettings()); + } else { + mProviderHelper.insertApiAccount( + KeychainContract.ApiAccounts.buildBaseUri(packageName), + mAccSettingsFragment.getAccSettings()); + } + + // give data through for new service call + Intent resultData = extras.getParcelable(EXTRA_DATA); + RemoteServiceActivity.this.setResult(RESULT_OK, resultData); + RemoteServiceActivity.this.finish(); + } + } + }, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Cancel + RemoteServiceActivity.this.setResult(RESULT_CANCELED); + RemoteServiceActivity.this.finish(); + } + }); + + break; } + case ACTION_SELECT_PUB_KEYS: { + long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); + boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true); + ArrayList missingUserIds = intent + .getStringArrayListExtra(EXTRA_MISSING_USER_IDS); + ArrayList dublicateUserIds = intent + .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS); - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), - R.string.btn_okay, R.drawable.ic_action_done, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // add key ids to params Bundle for new request - Intent resultData = extras.getParcelable(EXTRA_DATA); - resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS, - mSelectFragment.getSelectedMasterKeyIds()); + SpannableStringBuilder ssb = new SpannableStringBuilder(); + final SpannableString textIntro = new SpannableString( + noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids) + : getString(R.string.api_select_pub_keys_text) + ); + textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(textIntro); - RemoteServiceActivity.this.setResult(RESULT_OK, resultData); - RemoteServiceActivity.this.finish(); - } - }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() { - @Override - public void onClick(View v) { - // cancel - RemoteServiceActivity.this.setResult(RESULT_CANCELED); - RemoteServiceActivity.this.finish(); - } + if (missingUserIds != null && missingUserIds.size() > 0) { + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_missing_text)); + ssb.append("\n"); + for (String userId : missingUserIds) { + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); + } + } + if (dublicateUserIds != null && dublicateUserIds.size() > 0) { + ssb.append("\n\n"); + ssb.append(getString(R.string.api_select_pub_keys_dublicates_text)); + ssb.append("\n"); + for (String userId : dublicateUserIds) { + SpannableString ss = new SpannableString(userId + "\n"); + ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(ss); } - ); - - setContentView(R.layout.api_remote_select_pub_keys); - - // set text on view - TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text); - textView.setText(ssb, TextView.BufferType.SPANNABLE); - - /* Load select pub keys fragment */ - // Check that the activity is using the layout version with - // the fragment_container FrameLayout - if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) { - - // However, if we're being restored from a previous state, - // then we don't need to do anything and should return or else - // we could end up with overlapping fragments. - if (savedInstanceState != null) { - return; } - // Create an instance of the fragment - mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds); + setContentView(R.layout.api_remote_select_pub_keys); + initToolbar(); - // Add the fragment to the 'fragment_container' FrameLayout - getSupportFragmentManager().beginTransaction() - .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit(); - } - } else if (ACTION_ERROR_MESSAGE.equals(action)) { - String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE); + // Inflate a "Done"/"Cancel" custom action bar view + setFullScreenDialogDoneClose(R.string.btn_okay, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // add key ids to params Bundle for new request + Intent resultData = extras.getParcelable(EXTRA_DATA); + resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS, + mSelectFragment.getSelectedMasterKeyIds()); - Spannable redErrorMessage = new SpannableString(errorMessage); - redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + RemoteServiceActivity.this.setResult(RESULT_OK, resultData); + RemoteServiceActivity.this.finish(); + } + }, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // cancel + RemoteServiceActivity.this.setResult(RESULT_CANCELED); + RemoteServiceActivity.this.finish(); + } + }); - // Inflate a "Done" custom action bar view - ActionBarHelper.setOneButtonView(getSupportActionBar(), - R.string.btn_okay, R.drawable.ic_action_done, - new View.OnClickListener() { + // set text on view + TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text); + textView.setText(ssb, TextView.BufferType.SPANNABLE); - @Override - public void onClick(View v) { - RemoteServiceActivity.this.setResult(RESULT_CANCELED); - RemoteServiceActivity.this.finish(); - } + /* Load select pub keys fragment */ + // Check that the activity is using the layout version with + // the fragment_container FrameLayout + if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) { + + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; } - ); - setContentView(R.layout.api_remote_error_message); + // Create an instance of the fragment + mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds); - // set text on view - TextView textView = (TextView) findViewById(R.id.api_app_error_message_text); - textView.setText(redErrorMessage); - } else { - Log.e(Constants.TAG, "Action does not exist!"); - setResult(RESULT_CANCELED); - finish(); + // Add the fragment to the 'fragment_container' FrameLayout + getSupportFragmentManager().beginTransaction() + .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit(); + } + break; + } + case ACTION_ERROR_MESSAGE: { + String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE); + + Spannable redErrorMessage = new SpannableString(errorMessage); + redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + setContentView(R.layout.api_remote_error_message); + initToolbar(); + + // Inflate a "Done" custom action bar view + setFullScreenDialogClose( + new View.OnClickListener() { + + @Override + public void onClick(View v) { + RemoteServiceActivity.this.setResult(RESULT_CANCELED); + RemoteServiceActivity.this.finish(); + } + } + ); + + // set text on view + TextView textView = (TextView) findViewById(R.id.api_app_error_message_text); + textView.setText(redErrorMessage); + break; + } + default: + Log.e(Constants.TAG, "Action does not exist!"); + setResult(RESULT_CANCELED); + finish(); + break; } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java index dd9c0d769..f0dbf0820 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java @@ -34,7 +34,7 @@ public class CertifyActionsParcel implements Parcelable { final public long mMasterKeyId; public CertifyLevel mLevel; - public ArrayList mCertifyActions = new ArrayList(); + public ArrayList mCertifyActions = new ArrayList<>(); public CertifyActionsParcel(long masterKeyId) { mMasterKeyId = masterKeyId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2dc057941..bcb5da277 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -30,9 +30,11 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.CertifyOperation; import org.sufficientlysecure.keychain.operations.DeleteOperation; import org.sufficientlysecure.keychain.operations.EditKeyOperation; +import org.sufficientlysecure.keychain.operations.PromoteKeyOperation; import org.sufficientlysecure.keychain.operations.results.DeleteResult; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.operations.results.ExportResult; +import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.operations.results.CertifyResult; import org.sufficientlysecure.keychain.util.FileHelper; @@ -90,6 +92,8 @@ public class KeychainIntentService extends IntentService implements Progressable public static final String ACTION_EDIT_KEYRING = Constants.INTENT_PREFIX + "EDIT_KEYRING"; + public static final String ACTION_PROMOTE_KEYRING = Constants.INTENT_PREFIX + "PROMOTE_KEYRING"; + public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING"; public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING"; @@ -160,6 +164,10 @@ public class KeychainIntentService extends IntentService implements Progressable // certify key public static final String CERTIFY_PARCEL = "certify_parcel"; + // promote key + public static final String PROMOTE_MASTER_KEY_ID = "promote_master_key_id"; + public static final String PROMOTE_TYPE = "promote_type"; + // consolidate public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery"; @@ -223,301 +231,326 @@ public class KeychainIntentService extends IntentService implements Progressable String action = intent.getAction(); // executeServiceMethod action from extra bundle - if (ACTION_CERTIFY_KEYRING.equals(action)) { - - // Input - CertifyActionsParcel parcel = data.getParcelable(CERTIFY_PARCEL); - String keyServerUri = data.getString(UPLOAD_KEY_SERVER); - - // Operation - CertifyOperation op = new CertifyOperation(this, providerHelper, this, mActionCanceled); - CertifyResult result = op.certify(parcel, keyServerUri); - - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - - } else if (ACTION_CONSOLIDATE.equals(action)) { - - // Operation - ConsolidateResult result; - if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) { - result = new ProviderHelper(this).consolidateDatabaseStep2(this); - } else { - result = new ProviderHelper(this).consolidateDatabaseStep1(this); - } - - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - - } else if (ACTION_DECRYPT_METADATA.equals(action)) { - - try { - /* Input */ - String passphrase = data.getString(DECRYPT_PASSPHRASE); - byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); - - InputData inputData = createDecryptInputData(data); - - /* Operation */ - - Bundle resultData = new Bundle(); - - // verifyText and decrypt returning additional resultData values for the - // verification of signatures - PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( - this, new ProviderHelper(this), this, inputData, null - ); - builder.setAllowSymmetricDecryption(true) - .setPassphrase(passphrase) - .setDecryptMetadataOnly(true) - .setNfcState(nfcDecryptedSessionKey); - - DecryptVerifyResult decryptVerifyResult = builder.build().execute(); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, decryptVerifyResult); - } catch (Exception e) { - sendErrorToHandler(e); - } - - } else if (ACTION_DECRYPT_VERIFY.equals(action)) { - - try { - /* Input */ - String passphrase = data.getString(DECRYPT_PASSPHRASE); - byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); - - InputData inputData = createDecryptInputData(data); - OutputStream outStream = createCryptOutputStream(data); - - /* Operation */ - - Bundle resultData = new Bundle(); - - // verifyText and decrypt returning additional resultData values for the - // verification of signatures - PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( - this, new ProviderHelper(this), this, - inputData, outStream - ); - builder.setAllowSymmetricDecryption(true) - .setPassphrase(passphrase) - .setNfcState(nfcDecryptedSessionKey); - - DecryptVerifyResult decryptVerifyResult = builder.build().execute(); - - outStream.close(); - - resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult); - - /* Output */ - - finalizeDecryptOutputStream(data, resultData, outStream); - - Log.logDebugBundle(resultData, "resultData"); - - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); - } - - } else if (ACTION_DELETE.equals(action)) { - - // Input - long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST); - boolean isSecret = data.getBoolean(DELETE_IS_SECRET); - - // Operation - DeleteOperation op = new DeleteOperation(this, new ProviderHelper(this), this); - DeleteResult result = op.execute(masterKeyIds, isSecret); - - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - - } else if (ACTION_EDIT_KEYRING.equals(action)) { - - // Input - SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL); - String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE); - - // Operation - EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled); - EditKeyResult result = op.execute(saveParcel, passphrase); - - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - - } else if (ACTION_EXPORT_KEYRING.equals(action)) { - - // Input - boolean exportSecret = data.getBoolean(EXPORT_SECRET, false); - String outputFile = data.getString(EXPORT_FILENAME); - Uri outputUri = data.getParcelable(EXPORT_URI); - - boolean exportAll = data.getBoolean(EXPORT_ALL); - long[] masterKeyIds = exportAll ? null : data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID); - - // Operation - ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this); - ExportResult result; - if (outputFile != null) { - result = importExportOperation.exportToFile(masterKeyIds, exportSecret, outputFile); - } else { - result = importExportOperation.exportToUri(masterKeyIds, exportSecret, outputUri); - } - - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - - } else if (ACTION_IMPORT_KEYRING.equals(action)) { - - try { + switch (action) { + case ACTION_CERTIFY_KEYRING: { // Input - String keyServer = data.getString(IMPORT_KEY_SERVER); - Iterator entries; - int numEntries; - if (data.containsKey(IMPORT_KEY_LIST)) { - // get entries from intent - ArrayList list = data.getParcelableArrayList(IMPORT_KEY_LIST); - entries = list.iterator(); - numEntries = list.size(); - } else { - // get entries from cached file - ParcelableFileCache cache = - new ParcelableFileCache(this, "key_import.pcl"); - IteratorWithSize it = cache.readCache(); - entries = it; - numEntries = it.getSize(); - } + CertifyActionsParcel parcel = data.getParcelable(CERTIFY_PARCEL); + String keyServerUri = data.getString(UPLOAD_KEY_SERVER); // Operation - ImportExportOperation importExportOperation = new ImportExportOperation( - this, providerHelper, this, mActionCanceled); - ImportKeyResult result = importExportOperation.importKeyRings(entries, numEntries, keyServer); - - // Special: consolidate on secret key import (cannot be cancelled!) - if (result.mSecret > 0) { - // TODO move this into the import operation - providerHelper.consolidateDatabaseStep1(this); - } - - // Special: make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(); + CertifyOperation op = new CertifyOperation(this, providerHelper, this, mActionCanceled); + CertifyResult result = op.certify(parcel, keyServerUri); // Result sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - } catch (Exception e) { - sendErrorToHandler(e); + + break; } + case ACTION_CONSOLIDATE: { - } else if (ACTION_SIGN_ENCRYPT.equals(action)) { + // Operation + ConsolidateResult result; + if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) { + result = new ProviderHelper(this).consolidateDatabaseStep2(this); + } else { + result = new ProviderHelper(this).consolidateDatabaseStep1(this); + } - try { + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + + break; + } + case ACTION_DECRYPT_METADATA: + + try { /* Input */ - int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET); - Bundle resultData = new Bundle(); + String passphrase = data.getString(DECRYPT_PASSPHRASE); + byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); - long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID); - String sigKeyPassphrase = data.getString(ENCRYPT_SIGNATURE_KEY_PASSPHRASE); + InputData inputData = createDecryptInputData(data); - byte[] nfcHash = data.getByteArray(ENCRYPT_SIGNATURE_NFC_HASH); - Date nfcTimestamp = (Date) data.getSerializable(ENCRYPT_SIGNATURE_NFC_TIMESTAMP); + /* Operation */ - String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE); + Bundle resultData = new Bundle(); - boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR); - long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS); - int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID); - int urisCount = data.containsKey(ENCRYPT_INPUT_URIS) ? data.getParcelableArrayList(ENCRYPT_INPUT_URIS).size() : 1; - for (int i = 0; i < urisCount; i++) { - data.putInt(SELECTED_URI, i); - InputData inputData = createEncryptInputData(data); - OutputStream outStream = createCryptOutputStream(data); - String originalFilename = getOriginalFilename(data); - - /* Operation */ - PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( - this, new ProviderHelper(this), this, inputData, outStream + // verifyText and decrypt returning additional resultData values for the + // verification of signatures + PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( + this, new ProviderHelper(this), this, inputData, null ); - builder.setEnableAsciiArmorOutput(useAsciiArmor) - .setVersionHeader(PgpHelper.getVersionForHeader(this)) - .setCompressionId(compressionId) - .setSymmetricEncryptionAlgorithm( - Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) - .setEncryptionMasterKeyIds(encryptionKeyIds) - .setSymmetricPassphrase(symmetricPassphrase) - .setOriginalFilename(originalFilename); + builder.setAllowSymmetricDecryption(true) + .setPassphrase(passphrase) + .setDecryptMetadataOnly(true) + .setNfcState(nfcDecryptedSessionKey); - try { + DecryptVerifyResult decryptVerifyResult = builder.build().execute(); - // Find the appropriate subkey to sign with - CachedPublicKeyRing signingRing = - new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId); - long sigSubKeyId = signingRing.getSecretSignId(); + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, decryptVerifyResult); + } catch (Exception e) { + sendErrorToHandler(e); + } - // Set signature settings - builder.setSignatureMasterKeyId(sigMasterKeyId) - .setSignatureSubKeyId(sigSubKeyId) - .setSignaturePassphrase(sigKeyPassphrase) - .setSignatureHashAlgorithm( - Preferences.getPreferences(this).getDefaultHashAlgorithm()) - .setAdditionalEncryptId(sigMasterKeyId); - if (nfcHash != null && nfcTimestamp != null) { - builder.setNfcState(nfcHash, nfcTimestamp); - } + break; + case ACTION_DECRYPT_VERIFY: - } catch (PgpKeyNotFoundException e) { - // encrypt-only - // TODO Just silently drop the requested signature? Shouldn't we throw here? - } + try { + /* Input */ + String passphrase = data.getString(DECRYPT_PASSPHRASE); + byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY); - // this assumes that the bytes are cleartext (valid for current implementation!) - if (source == IO_BYTES) { - builder.setCleartextSignature(true); - } + InputData inputData = createDecryptInputData(data); + OutputStream outStream = createCryptOutputStream(data); - SignEncryptResult result = builder.build().execute(); - resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result); + /* Operation */ + + Bundle resultData = new Bundle(); + + // verifyText and decrypt returning additional resultData values for the + // verification of signatures + PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder( + this, new ProviderHelper(this), this, + inputData, outStream + ); + builder.setAllowSymmetricDecryption(true) + .setPassphrase(passphrase) + .setNfcState(nfcDecryptedSessionKey); + + DecryptVerifyResult decryptVerifyResult = builder.build().execute(); outStream.close(); - /* Output */ + resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult); - finalizeEncryptOutputStream(data, resultData, outStream); + /* Output */ + finalizeDecryptOutputStream(data, resultData, outStream); + + Log.logDebugBundle(resultData, "resultData"); + + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + } catch (Exception e) { + sendErrorToHandler(e); } - Log.logDebugBundle(resultData, "resultData"); + break; + case ACTION_DELETE: { - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); - } catch (Exception e) { - sendErrorToHandler(e); + // Input + long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST); + boolean isSecret = data.getBoolean(DELETE_IS_SECRET); + + // Operation + DeleteOperation op = new DeleteOperation(this, new ProviderHelper(this), this); + DeleteResult result = op.execute(masterKeyIds, isSecret); + + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + + break; } + case ACTION_EDIT_KEYRING: { - } else if (ACTION_UPLOAD_KEYRING.equals(action)) { + // Input + SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL); + String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE); - try { + // Operation + EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled); + EditKeyResult result = op.execute(saveParcel, passphrase); - /* Input */ - String keyServer = data.getString(UPLOAD_KEY_SERVER); - // and dataUri! + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - /* Operation */ - HkpKeyserver server = new HkpKeyserver(keyServer); + break; + } + case ACTION_PROMOTE_KEYRING: { - CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri); + // Input + long keyRingId = data.getInt(EXPORT_KEY_RING_MASTER_KEY_ID); + + // Operation + PromoteKeyOperation op = new PromoteKeyOperation(this, providerHelper, this, mActionCanceled); + PromoteKeyResult result = op.execute(keyRingId); + + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + + break; + } + case ACTION_EXPORT_KEYRING: { + + // Input + boolean exportSecret = data.getBoolean(EXPORT_SECRET, false); + String outputFile = data.getString(EXPORT_FILENAME); + Uri outputUri = data.getParcelable(EXPORT_URI); + + boolean exportAll = data.getBoolean(EXPORT_ALL); + long[] masterKeyIds = exportAll ? null : data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID); + + // Operation ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this); + ExportResult result; + if (outputFile != null) { + result = importExportOperation.exportToFile(masterKeyIds, exportSecret, outputFile); + } else { + result = importExportOperation.exportToUri(masterKeyIds, exportSecret, outputUri); + } + + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + + break; + } + case ACTION_IMPORT_KEYRING: try { - importExportOperation.uploadKeyRingToServer(server, keyring); - } catch (Keyserver.AddKeyException e) { - throw new PgpGeneralException("Unable to export key to selected server"); + + // Input + String keyServer = data.getString(IMPORT_KEY_SERVER); + Iterator entries; + int numEntries; + if (data.containsKey(IMPORT_KEY_LIST)) { + // get entries from intent + ArrayList list = data.getParcelableArrayList(IMPORT_KEY_LIST); + entries = list.iterator(); + numEntries = list.size(); + } else { + // get entries from cached file + ParcelableFileCache cache = + new ParcelableFileCache<>(this, "key_import.pcl"); + IteratorWithSize it = cache.readCache(); + entries = it; + numEntries = it.getSize(); + } + + // Operation + ImportExportOperation importExportOperation = new ImportExportOperation( + this, providerHelper, this, mActionCanceled); + ImportKeyResult result = importExportOperation.importKeyRings(entries, numEntries, keyServer); + + // Special: consolidate on secret key import (cannot be cancelled!) + if (result.mSecret > 0) { + // TODO move this into the import operation + providerHelper.consolidateDatabaseStep1(this); + } + + // Special: make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(); + + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); + } catch (Exception e) { + sendErrorToHandler(e); } - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); - } catch (Exception e) { - sendErrorToHandler(e); - } + break; + case ACTION_SIGN_ENCRYPT: + + try { + /* Input */ + int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET); + Bundle resultData = new Bundle(); + + long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID); + String sigKeyPassphrase = data.getString(ENCRYPT_SIGNATURE_KEY_PASSPHRASE); + + byte[] nfcHash = data.getByteArray(ENCRYPT_SIGNATURE_NFC_HASH); + Date nfcTimestamp = (Date) data.getSerializable(ENCRYPT_SIGNATURE_NFC_TIMESTAMP); + + String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE); + + boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR); + long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS); + int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID); + int urisCount = data.containsKey(ENCRYPT_INPUT_URIS) ? data.getParcelableArrayList(ENCRYPT_INPUT_URIS).size() : 1; + for (int i = 0; i < urisCount; i++) { + data.putInt(SELECTED_URI, i); + InputData inputData = createEncryptInputData(data); + OutputStream outStream = createCryptOutputStream(data); + String originalFilename = getOriginalFilename(data); + + /* Operation */ + PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder( + this, new ProviderHelper(this), this, inputData, outStream + ); + builder.setEnableAsciiArmorOutput(useAsciiArmor) + .setVersionHeader(PgpHelper.getVersionForHeader(this)) + .setCompressionId(compressionId) + .setSymmetricEncryptionAlgorithm( + Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) + .setEncryptionMasterKeyIds(encryptionKeyIds) + .setSymmetricPassphrase(symmetricPassphrase) + .setOriginalFilename(originalFilename); + + try { + + // Find the appropriate subkey to sign with + CachedPublicKeyRing signingRing = + new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId); + long sigSubKeyId = signingRing.getSecretSignId(); + + // Set signature settings + builder.setSignatureMasterKeyId(sigMasterKeyId) + .setSignatureSubKeyId(sigSubKeyId) + .setSignaturePassphrase(sigKeyPassphrase) + .setSignatureHashAlgorithm( + Preferences.getPreferences(this).getDefaultHashAlgorithm()) + .setAdditionalEncryptId(sigMasterKeyId); + if (nfcHash != null && nfcTimestamp != null) { + builder.setNfcState(nfcHash, nfcTimestamp); + } + + } catch (PgpKeyNotFoundException e) { + // encrypt-only + // TODO Just silently drop the requested signature? Shouldn't we throw here? + } + + SignEncryptResult result = builder.build().execute(); + resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result); + + outStream.close(); + + /* Output */ + + finalizeEncryptOutputStream(data, resultData, outStream); + + } + + Log.logDebugBundle(resultData, "resultData"); + + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + } catch (Exception e) { + sendErrorToHandler(e); + } + + break; + case ACTION_UPLOAD_KEYRING: + + try { + + /* Input */ + String keyServer = data.getString(UPLOAD_KEY_SERVER); + // and dataUri! + + /* Operation */ + HkpKeyserver server = new HkpKeyserver(keyServer); + + CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri); + ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this); + + try { + importExportOperation.uploadKeyRingToServer(server, keyring); + } catch (Keyserver.AddKeyException e) { + throw new PgpGeneralException("Unable to export key to selected server"); + } + + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); + } catch (Exception e) { + sendErrorToHandler(e); + } + break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 869d2e71b..142814d99 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -39,7 +39,6 @@ import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -103,7 +102,7 @@ public class PassphraseCacheService extends Service { private BroadcastReceiver mIntentReceiver; - private LongSparseArray mPassphraseCache = new LongSparseArray(); + private LongSparseArray mPassphraseCache = new LongSparseArray<>(); Context mContext; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 810190fee..f5df5858c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.service; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import java.io.Serializable; import java.util.ArrayList; @@ -49,6 +50,7 @@ public class SaveKeyringParcel implements Parcelable { public ChangeUnlockParcel mNewUnlock; public ArrayList mAddUserIds; + public ArrayList mAddUserAttribute; public ArrayList mAddSubKeys; public ArrayList mChangeSubKeys; @@ -56,7 +58,6 @@ public class SaveKeyringParcel implements Parcelable { public ArrayList mRevokeUserIds; public ArrayList mRevokeSubKeys; - public ArrayList mStripSubKeys; public SaveKeyringParcel() { reset(); @@ -70,13 +71,30 @@ public class SaveKeyringParcel implements Parcelable { public void reset() { mNewUnlock = null; - mAddUserIds = new ArrayList(); - mAddSubKeys = new ArrayList(); + mAddUserIds = new ArrayList<>(); + mAddUserAttribute = new ArrayList<>(); + mAddSubKeys = new ArrayList<>(); mChangePrimaryUserId = null; - mChangeSubKeys = new ArrayList(); - mRevokeUserIds = new ArrayList(); - mRevokeSubKeys = new ArrayList(); - mStripSubKeys = new ArrayList(); + mChangeSubKeys = new ArrayList<>(); + mRevokeUserIds = new ArrayList<>(); + mRevokeSubKeys = new ArrayList<>(); + } + + /** Returns true iff this parcel does not contain any operations which require a passphrase. */ + public boolean isRestrictedOnly() { + if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty() + || !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeSubKeys .isEmpty() + || !mRevokeSubKeys.isEmpty()) { + return false; + } + + for (SubkeyChange change : mChangeSubKeys) { + if (change.mRecertify || change.mFlags != null || change.mExpiry != null) { + return false; + } + } + + return true; } // performance gain for using Parcelable here would probably be negligible, @@ -109,26 +127,53 @@ public class SaveKeyringParcel implements Parcelable { } public static class SubkeyChange implements Serializable { - public long mKeyId; + public final long mKeyId; public Integer mFlags; // this is a long unix timestamp, in seconds (NOT MILLISECONDS!) public Long mExpiry; + // if this flag is true, the key will be recertified even if all above + // values are no-ops + public boolean mRecertify; + // if this flag is true, the subkey should be changed to a stripped key + public boolean mDummyStrip; + // if this is non-null, the subkey will be changed to a divert-to-card + // key for the given serial number + public byte[] mDummyDivert; public SubkeyChange(long keyId) { mKeyId = keyId; } + public SubkeyChange(long keyId, boolean recertify) { + mKeyId = keyId; + mRecertify = recertify; + } + public SubkeyChange(long keyId, Integer flags, Long expiry) { mKeyId = keyId; mFlags = flags; mExpiry = expiry; } + public SubkeyChange(long keyId, boolean dummyStrip, byte[] dummyDivert) { + this(keyId, null, null); + + // these flags are mutually exclusive! + if (dummyStrip && dummyDivert != null) { + throw new AssertionError( + "cannot set strip and divert flags at the same time - this is a bug!"); + } + mDummyStrip = dummyStrip; + mDummyDivert = dummyDivert; + } + @Override public String toString() { String out = "mKeyId: " + mKeyId + ", "; out += "mFlags: " + mFlags + ", "; - out += "mExpiry: " + mExpiry; + out += "mExpiry: " + mExpiry + ", "; + out += "mDummyStrip: " + mDummyStrip + ", "; + out += "mDummyDivert: [" + (mDummyDivert == null ? 0 : mDummyDivert.length) + " bytes]"; return out; } @@ -162,6 +207,7 @@ public class SaveKeyringParcel implements Parcelable { mNewUnlock = source.readParcelable(getClass().getClassLoader()); mAddUserIds = source.createStringArrayList(); + mAddUserAttribute = (ArrayList) source.readSerializable(); mAddSubKeys = (ArrayList) source.readSerializable(); mChangeSubKeys = (ArrayList) source.readSerializable(); @@ -169,7 +215,6 @@ public class SaveKeyringParcel implements Parcelable { mRevokeUserIds = source.createStringArrayList(); mRevokeSubKeys = (ArrayList) source.readSerializable(); - mStripSubKeys = (ArrayList) source.readSerializable(); } @Override @@ -184,6 +229,7 @@ public class SaveKeyringParcel implements Parcelable { destination.writeParcelable(mNewUnlock, 0); destination.writeStringList(mAddUserIds); + destination.writeSerializable(mAddUserAttribute); destination.writeSerializable(mAddSubKeys); destination.writeSerializable(mChangeSubKeys); @@ -191,7 +237,6 @@ public class SaveKeyringParcel implements Parcelable { destination.writeStringList(mRevokeUserIds); destination.writeSerializable(mRevokeSubKeys); - destination.writeSerializable(mStripSubKeys); } public static final Creator CREATOR = new Creator() { @@ -214,12 +259,12 @@ public class SaveKeyringParcel implements Parcelable { String out = "mMasterKeyId: " + mMasterKeyId + "\n"; out += "mNewUnlock: " + mNewUnlock + "\n"; out += "mAddUserIds: " + mAddUserIds + "\n"; + out += "mAddUserAttribute: " + mAddUserAttribute + "\n"; out += "mAddSubKeys: " + mAddSubKeys + "\n"; out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; out += "mRevokeUserIds: " + mRevokeUserIds + "\n"; - out += "mRevokeSubKeys: " + mRevokeSubKeys + "\n"; - out += "mStripSubKeys: " + mStripSubKeys; + out += "mRevokeSubKeys: " + mRevokeSubKeys; return out; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java new file mode 100644 index 000000000..7423e6828 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.Toolbar; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; + +/** + * Setups Toolbar + */ +public abstract class BaseActivity extends ActionBarActivity { + protected Toolbar mToolbar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initLayout(); + initToolbar(); + } + + protected abstract void initLayout(); + + protected void initToolbar() { + mToolbar = (Toolbar) findViewById(R.id.toolbar); + if (mToolbar != null) { + setSupportActionBar(mToolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + } + + protected void setActionBarIcon(int iconRes) { + mToolbar.setNavigationIcon(iconRes); + } + + /** + * Inflate custom design to look like a full screen dialog, as specified in Material Design Guidelines + * see http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs + */ + protected void setFullScreenDialogDoneClose(int doneText, View.OnClickListener doneOnClickListener, + View.OnClickListener cancelOnClickListener) { + setActionBarIcon(R.drawable.ic_close_white_24dp); + + // Inflate the custom action bar view + final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext() + .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater.inflate(R.layout.full_screen_dialog, null); + + TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.full_screen_dialog_done_text)); + firstTextView.setText(doneText); + customActionBarView.findViewById(R.id.full_screen_dialog_done).setOnClickListener( + doneOnClickListener); + + getSupportActionBar().setDisplayShowCustomEnabled(true); + getSupportActionBar().setDisplayShowTitleEnabled(true); + getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, + Gravity.END)); + mToolbar.setNavigationOnClickListener(cancelOnClickListener); + } + + /** + * Close button only + */ + protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener) { + setActionBarIcon(R.drawable.ic_close_white_24dp); + getSupportActionBar().setDisplayShowTitleEnabled(true); + mToolbar.setNavigationOnClickListener(cancelOnClickListener); + } + + /** + * Inflate custom design with two buttons using drawables. + * This does not conform to the Material Design Guidelines, but we deviate here as this is used + * to indicate "Allow access"/"Disallow access" to the API, which must be clearly indicated + */ + protected void setFullScreenDialogTwoButtons(int firstText, int firstDrawableId, View.OnClickListener firstOnClickListener, + int secondText, int secondDrawableId, View.OnClickListener secondOnClickListener) { + + // Inflate the custom action bar view + final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext() + .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater.inflate( + R.layout.full_screen_dialog_2, null); + + TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)); + firstTextView.setText(firstText); + firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0); + customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( + firstOnClickListener); + TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)); + secondTextView.setText(secondText); + secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0); + customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener( + secondOnClickListener); + + // Show the custom action bar view and hide the normal Home icon and title. + getSupportActionBar().setDisplayShowTitleEnabled(false); + getSupportActionBar().setDisplayShowHomeEnabled(false); + getSupportActionBar().setDisplayHomeAsUpEnabled(false); + getSupportActionBar().setDisplayShowCustomEnabled(true); + getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + } + + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index a97e73934..1fb88b182 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -18,24 +18,19 @@ package org.sufficientlysecure.keychain.ui; -import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; - import org.sufficientlysecure.keychain.R; /** * Signs the specified public key with the specified secret master key */ -public class CertifyKeyActivity extends ActionBarActivity { +public class CertifyKeyActivity extends BaseActivity { public static final String EXTRA_RESULT = "operation_result"; public static final String EXTRA_KEY_IDS = "extra_key_ids"; public static final String EXTRA_CERTIFY_KEY_ID = "certify_key_id"; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - + protected void initLayout() { setContentView(R.layout.certify_key_activity); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 4d10d8639..50d5e3229 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -49,7 +49,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.CertifyActionsParcel; @@ -82,11 +82,11 @@ public class CertifyKeyFragment extends LoaderFragment private long mSignMasterKeyId = Constants.key.none; public static final String[] USER_IDS_PROJECTION = new String[]{ - UserIds._ID, - UserIds.MASTER_KEY_ID, - UserIds.USER_ID, - UserIds.IS_PRIMARY, - UserIds.IS_REVOKED + UserPackets._ID, + UserPackets.MASTER_KEY_ID, + UserPackets.USER_ID, + UserPackets.IS_PRIMARY, + UserPackets.IS_REVOKED }; private static final int INDEX_MASTER_KEY_ID = 1; private static final int INDEX_USER_ID = 2; @@ -182,7 +182,7 @@ public class CertifyKeyFragment extends LoaderFragment @Override public Loader onCreateLoader(int id, Bundle args) { - Uri uri = UserIds.buildUserIdsUri(); + Uri uri = UserPackets.buildUserIdsUri(); String selection, ids[]; { @@ -196,15 +196,15 @@ public class CertifyKeyFragment extends LoaderFragment } } // put together selection string - selection = UserIds.IS_REVOKED + " = 0" + " AND " - + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + selection = UserPackets.IS_REVOKED + " = 0" + " AND " + + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " IN (" + placeholders + ")"; } return new CursorLoader(getActivity(), uri, USER_IDS_PROJECTION, selection, ids, - Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " ASC" - + ", " + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC" + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " ASC" + + ", " + Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC" ); } @@ -234,7 +234,7 @@ public class CertifyKeyFragment extends LoaderFragment long lastMasterKeyId = 0; String lastName = ""; - ArrayList uids = new ArrayList(); + ArrayList uids = new ArrayList<>(); boolean header = true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java index 534ac5811..62c38d136 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -20,11 +20,10 @@ package org.sufficientlysecure.keychain.ui; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; -import android.support.v7.app.ActionBarActivity; import org.sufficientlysecure.keychain.R; -public class CreateKeyActivity extends ActionBarActivity { +public class CreateKeyActivity extends BaseActivity { public static final String EXTRA_NAME = "name"; public static final String EXTRA_EMAIL = "email"; @@ -37,8 +36,6 @@ public class CreateKeyActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.create_key_activity); - // pass extras into fragment CreateKeyInputFragment frag = CreateKeyInputFragment.newInstance( @@ -48,6 +45,11 @@ public class CreateKeyActivity extends ActionBarActivity { loadFragment(null, frag, FRAG_ACTION_START); } + @Override + protected void initLayout() { + setContentView(R.layout.create_key_activity); + } + public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) { // However, if we're being restored from a previous state, // then we don't need to do anything and should return or else diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 2804a5ce6..377a9d1f4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -44,7 +44,6 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; -import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; import org.sufficientlysecure.keychain.util.Log; public class CreateKeyFinalFragment extends Fragment { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java index 6079062a7..8aa9fa6db 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -89,7 +89,7 @@ public class CreateKeyInputFragment extends Fragment { mEmailEdit.setThreshold(1); // Start working from first character mEmailEdit.setAdapter( - new ArrayAdapter + new ArrayAdapter<> (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserEmails(getActivity()) ) @@ -124,7 +124,7 @@ public class CreateKeyInputFragment extends Fragment { mNameEdit.setThreshold(1); // Start working from first character mNameEdit.setAdapter( - new ArrayAdapter + new ArrayAdapter<> (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserNames(getActivity()) ) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 681e22e1e..a84461a92 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -40,8 +40,6 @@ public class DecryptActivity extends DrawerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.decrypt_activity); - activateDrawerNavigation(savedInstanceState); View actionFile = findViewById(R.id.decrypt_files); @@ -66,6 +64,11 @@ public class DecryptActivity extends DrawerActivity { }); } + @Override + protected void initLayout() { + setContentView(R.layout.decrypt_activity); + } + @TargetApi(VERSION_CODES.HONEYCOMB) @Override protected void onResume() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java index 9d972d8c0..7e91889b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java @@ -20,14 +20,13 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.util.Log; -public class DecryptFilesActivity extends ActionBarActivity { +public class DecryptFilesActivity extends BaseActivity { /* Intents */ public static final String ACTION_DECRYPT_DATA = OpenKeychainIntents.DECRYPT_DATA; @@ -41,12 +40,15 @@ public class DecryptFilesActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.decrypt_files_activity); - // Handle intent actions handleActions(savedInstanceState, getIntent()); } + @Override + protected void initLayout() { + setContentView(R.layout.decrypt_files_activity); + } + /** * Handles all actions with this intent * diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java index 2da76088a..2afc4b7b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java @@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; @@ -35,7 +34,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import java.util.regex.Matcher; -public class DecryptTextActivity extends ActionBarActivity { +public class DecryptTextActivity extends BaseActivity { /* Intents */ public static final String ACTION_DECRYPT_TEXT = OpenKeychainIntents.DECRYPT_TEXT; @@ -50,12 +49,15 @@ public class DecryptTextActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.decrypt_text_activity); - // Handle intent actions handleActions(savedInstanceState, getIntent()); } + @Override + protected void initLayout() { + setContentView(R.layout.decrypt_text_activity); + } + /** * Fixing broken PGP MESSAGE Strings coming from GMail/AOSP Mail */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index fa7abf0f5..83ba64ce2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -111,7 +111,7 @@ public class DecryptTextFragment extends DecryptFragment { Intent prototype = createSendIntent(text); String title = getString(R.string.title_share_file); - // we don't want to decrypt the decypted, no inception ;) + // we don't want to decrypt the decrypted, no inception ;) String[] blacklist = new String[]{ Constants.PACKAGE_NAME + ".ui.DecryptTextActivity", "org.thialfihar.android.apg.ui.DecryptActivity" diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java index da46de486..712516b8d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java @@ -27,7 +27,6 @@ import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.FixedDrawerLayout; -import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -42,7 +41,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -public class DrawerActivity extends ActionBarActivity { +public abstract class DrawerActivity extends BaseActivity { private FixedDrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; @@ -179,7 +178,7 @@ public class DrawerActivity extends ActionBarActivity { switch (item.getItemId()) { case MENU_ID_PREFERENCE: { - Intent intent = new Intent(this, PreferencesActivity.class); + Intent intent = new Intent(this, SettingsActivity.class); startActivity(intent); return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 98049d89b..6dc2994cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -19,14 +19,13 @@ package org.sufficientlysecure.keychain.ui; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.util.Log; -public class EditKeyActivity extends ActionBarActivity { +public class EditKeyActivity extends BaseActivity { public static final String EXTRA_SAVE_KEYRING_PARCEL = "save_keyring_parcel"; @@ -36,8 +35,6 @@ public class EditKeyActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.edit_key_activity); - Uri dataUri = getIntent().getData(); SaveKeyringParcel saveKeyringParcel = getIntent().getParcelableExtra(EXTRA_SAVE_KEYRING_PARCEL); if (dataUri == null && saveKeyringParcel == null) { @@ -49,6 +46,11 @@ public class EditKeyActivity extends ActionBarActivity { loadFragment(savedInstanceState, dataUri, saveKeyringParcel); } + @Override + protected void initLayout() { + setContentView(R.layout.edit_key_activity); + } + private void loadFragment(Bundle savedInstanceState, Uri dataUri, SaveKeyringParcel saveKeyringParcel) { // However, if we're being restored from a previous state, // then we don't need to do anything and should return or else diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 0f4bfefd4..25ca6e8fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -29,7 +29,6 @@ import android.os.Messenger; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; -import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -47,6 +46,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; @@ -64,7 +65,6 @@ import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; @@ -146,10 +146,8 @@ public class EditKeyFragment extends LoaderFragment implements @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(), - R.string.btn_save, R.drawable.ic_action_save, + ((EditKeyActivity) getActivity()).setFullScreenDialogDoneClose( + R.string.btn_save, new OnClickListener() { @Override public void onClick(View v) { @@ -160,16 +158,13 @@ public class EditKeyFragment extends LoaderFragment implements saveInDatabase(mCurrentPassphrase); } } - }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, - new OnClickListener() { + }, new OnClickListener() { @Override public void onClick(View v) { - // cancel getActivity().setResult(Activity.RESULT_CANCELED); getActivity().finish(); } - } - ); + }); Uri dataUri = getArguments().getParcelable(ARG_DATA_URI); SaveKeyringParcel saveKeyringParcel = getArguments().getParcelable(ARG_SAVE_KEYRING_PARCEL); @@ -229,10 +224,7 @@ public class EditKeyFragment extends LoaderFragment implements mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint()); mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback(); - } catch (PgpKeyNotFoundException e) { - finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND); - return; - } catch (NotFoundException e) { + } catch (PgpKeyNotFoundException | NotFoundException e) { finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND); return; } @@ -334,7 +326,7 @@ public class EditKeyFragment extends LoaderFragment implements switch (id) { case LOADER_ID_USER_IDS: { - Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri); + Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); return new CursorLoader(getActivity(), baseUri, UserIdsAdapter.USER_IDS_PROJECTION, null, null, null); } @@ -394,8 +386,8 @@ public class EditKeyFragment extends LoaderFragment implements // cache new returned passphrase! mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel( - data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE), - null + data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE), + null ); } } @@ -477,12 +469,13 @@ public class EditKeyFragment extends LoaderFragment implements } break; case EditSubkeyDialogFragment.MESSAGE_STRIP: - // toggle - if (mSaveKeyringParcel.mStripSubKeys.contains(keyId)) { - mSaveKeyringParcel.mStripSubKeys.remove(keyId); - } else { - mSaveKeyringParcel.mStripSubKeys.add(keyId); + SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId); + if (change == null) { + mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null)); + break; } + // toggle + change.mDummyStrip = !change.mDummyStrip; break; } getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index b9058a37d..11780e761 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -14,7 +14,7 @@ import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import java.util.Date; -public abstract class EncryptActivity extends DrawerActivity { +public abstract class EncryptActivity extends NavDrawerActivity { public static final int REQUEST_CODE_PASSPHRASE = 0x00008001; public static final int REQUEST_CODE_NFC = 0x00008002; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index 2d1b66daa..c5404094a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -28,7 +28,6 @@ import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -164,8 +163,8 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi private void updateEncryptionKeys() { List objects = mEncryptKeyView.getObjects(); - List keyIds = new ArrayList(); - List userIds = new ArrayList(); + List keyIds = new ArrayList<>(); + List userIds = new ArrayList<>(); for (Object object : objects) { if (object instanceof EncryptKeyCompletionView.EncryptionKey) { keyIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getKeyId()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index 054d85323..6a5eaa26c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -122,13 +122,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi @Override public ArrayList getInputUris() { - if (mInputUris == null) mInputUris = new ArrayList(); + if (mInputUris == null) mInputUris = new ArrayList<>(); return mInputUris; } @Override public ArrayList getOutputUris() { - if (mOutputUris == null) mOutputUris = new ArrayList(); + if (mOutputUris == null) mOutputUris = new ArrayList<>(); return mOutputUris; } @@ -252,7 +252,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi sendIntent.setType("application/octet-stream"); if (!isModeSymmetric() && mEncryptionUserIds != null) { - Set users = new HashSet(); + Set users = new HashSet<>(); for (String user : mEncryptionUserIds) { String[] userId = KeyRing.splitUserId(user); if (userId[1] != null) { @@ -309,15 +309,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.encrypt_files_activity); - // if called with an intent action, do not init drawer navigation if (ACTION_ENCRYPT_DATA.equals(getIntent().getAction())) { // lock drawer - deactivateDrawerNavigation(); +// deactivateDrawerNavigation(); // TODO: back button to key? } else { - activateDrawerNavigation(savedInstanceState); +// activateDrawerNavigation(savedInstanceState); } // Handle intent actions @@ -327,6 +325,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor(); } +// @Override +// protected void initLayout() { +// setContentView(R.layout.encrypt_files_activity); +// } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.encrypt_file_activity, menu); @@ -379,7 +382,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi String action = intent.getAction(); Bundle extras = intent.getExtras(); String type = intent.getType(); - ArrayList uris = new ArrayList(); + ArrayList uris = new ArrayList<>(); if (extras == null) { extras = new Bundle(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 6961f5ee7..be305cc58 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -59,7 +59,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt private View mShareFile; private ListView mSelectedFiles; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); - private final Map thumbnailCache = new HashMap(); + private final Map thumbnailCache = new HashMap<>(); @Override public void onAttach(Activity activity) { @@ -224,7 +224,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt @Override public void onNotifyUpdate() { // Clear cache if needed - for (Uri uri : new HashSet(thumbnailCache.keySet())) { + for (Uri uri : new HashSet<>(thumbnailCache.keySet())) { if (!mEncryptInterface.getInputUris().contains(uri)) { thumbnailCache.remove(uri); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 958daa122..f9faf683d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -121,13 +121,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv @Override public ArrayList getInputUris() { - if (mInputUris == null) mInputUris = new ArrayList(); + if (mInputUris == null) mInputUris = new ArrayList<>(); return mInputUris; } @Override public ArrayList getOutputUris() { - if (mOutputUris == null) mOutputUris = new ArrayList(); + if (mOutputUris == null) mOutputUris = new ArrayList<>(); return mOutputUris; } @@ -240,13 +240,14 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv sendIntent.putExtra(Intent.EXTRA_TEXT, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); if (!isModeSymmetric() && mEncryptionUserIds != null) { - Set users = new HashSet(); + Set users = new HashSet<>(); for (String user : mEncryptionUserIds) { String[] userId = KeyRing.splitUserId(user); if (userId[1] != null) { users.add(userId[1]); } } + // pass trough email addresses as extra for email applications sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); } return sendIntent; @@ -288,15 +289,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.encrypt_text_activity); - // if called with an intent action, do not init drawer navigation if (ACTION_ENCRYPT_TEXT.equals(getIntent().getAction())) { // lock drawer - deactivateDrawerNavigation(); +// deactivateDrawerNavigation(); // TODO: back button to key? } else { - activateDrawerNavigation(savedInstanceState); +// activateDrawerNavigation(savedInstanceState); } // Handle intent actions @@ -304,6 +303,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv updateModeFragment(); } +// @Override +// protected void initLayout() { +// setContentView(R.layout.encrypt_text_activity); +// } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.encrypt_text_activity, menu); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java index f18e475fc..ce2a049f5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.KeyEvent; import android.view.View; import android.view.Window; @@ -29,7 +28,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Log; -public class FirstTimeActivity extends ActionBarActivity { +public class FirstTimeActivity extends BaseActivity { View mCreateKey; View mImportKey; @@ -43,8 +42,6 @@ public class FirstTimeActivity extends ActionBarActivity { super.onCreate(savedInstanceState); - setContentView(R.layout.first_time_activity); - mCreateKey = findViewById(R.id.first_time_create_key); mImportKey = findViewById(R.id.first_time_import_key); mSkipSetup = findViewById(R.id.first_time_cancel); @@ -72,7 +69,11 @@ public class FirstTimeActivity extends ActionBarActivity { startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); } }); + } + @Override + protected void initLayout() { + setContentView(R.layout.first_time_activity); } @Override @@ -96,7 +97,7 @@ public class FirstTimeActivity extends ActionBarActivity { if (srcData != null) { intent.putExtras(srcData); } - startActivityForResult(intent, 0); + startActivity(intent); finish(); } @@ -105,4 +106,5 @@ public class FirstTimeActivity extends ActionBarActivity { public boolean onKeyDown(int keyCode, KeyEvent event) { return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java index bbc1e4b1f..2eb35351e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java @@ -20,14 +20,14 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; import android.support.v4.view.ViewPager; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; +import android.view.View; + +import com.astuetz.PagerSlidingTabStrip; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; -import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; -public class HelpActivity extends ActionBarActivity { +public class HelpActivity extends BaseActivity { public static final String EXTRA_SELECTED_TAB = "selected_tab"; public static final int TAB_START = 0; @@ -44,16 +44,16 @@ public class HelpActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayShowTitleEnabled(true); - actionBar.setDisplayHomeAsUpEnabled(false); - actionBar.setHomeButtonEnabled(false); - - setContentView(R.layout.help_activity); + mToolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); mViewPager = (ViewPager) findViewById(R.id.pager); - SlidingTabLayout slidingTabLayout = - (SlidingTabLayout) findViewById(R.id.sliding_tab_layout); + PagerSlidingTabStrip slidingTabLayout = + (PagerSlidingTabStrip) findViewById(R.id.sliding_tab_layout); mTabsAdapter = new PagerTabStripAdapter(this); mViewPager.setAdapter(mTabsAdapter); @@ -98,4 +98,9 @@ public class HelpActivity extends ActionBarActivity { // switch to tab selected by extra mViewPager.setCurrentItem(selectedTab); } + + @Override + protected void initLayout() { + setContentView(R.layout.help_activity); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index dfb7b3056..e72e265d4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -29,7 +29,6 @@ import android.os.Message; import android.os.Messenger; import android.os.Parcelable; import android.support.v4.app.Fragment; -import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; @@ -51,7 +50,7 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize import java.io.IOException; import java.util.ArrayList; -public class ImportKeysActivity extends ActionBarActivity { +public class ImportKeysActivity extends BaseActivity { public static final String ACTION_IMPORT_KEY = OpenKeychainIntents.IMPORT_KEY; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT = @@ -90,8 +89,6 @@ public class ImportKeysActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.import_keys_activity); - mImportButton = findViewById(R.id.import_import); mImportButton.setOnClickListener(new OnClickListener() { @Override @@ -103,6 +100,11 @@ public class ImportKeysActivity extends ActionBarActivity { handleActions(savedInstanceState, getIntent()); } + @Override + protected void initLayout() { + setContentView(R.layout.import_keys_activity); + } + protected void handleActions(Bundle savedInstanceState, Intent intent) { String action = intent.getAction(); Bundle extras = intent.getExtras(); @@ -119,95 +121,102 @@ public class ImportKeysActivity extends ActionBarActivity { action = ACTION_IMPORT_KEY; } - if (ACTION_IMPORT_KEY.equals(action)) { + switch (action) { + case ACTION_IMPORT_KEY: /* Keychain's own Actions */ - startFileFragment(savedInstanceState); + startFileFragment(savedInstanceState); - if (dataUri != null) { - // action: directly load data - startListFragment(savedInstanceState, null, dataUri, null); - } else if (extras.containsKey(EXTRA_KEY_BYTES)) { - byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES); + if (dataUri != null) { + // action: directly load data + startListFragment(savedInstanceState, null, dataUri, null); + } else if (extras.containsKey(EXTRA_KEY_BYTES)) { + byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES); - // action: directly load data - startListFragment(savedInstanceState, importData, null, null); - } - } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action) - || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(action) - || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(action)) { + // action: directly load data + startListFragment(savedInstanceState, importData, null, null); + } + break; + case ACTION_IMPORT_KEY_FROM_KEYSERVER: + case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE: + case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT: - // only used for OpenPgpService - if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) { - mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA); - } - if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) { + // only used for OpenPgpService + if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) { + mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA); + } + if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) { /* simple search based on query or key id */ - String query = null; - if (extras.containsKey(EXTRA_QUERY)) { - query = extras.getString(EXTRA_QUERY); - } else if (extras.containsKey(EXTRA_KEY_ID)) { - long keyId = extras.getLong(EXTRA_KEY_ID, 0); - if (keyId != 0) { - query = KeyFormattingUtils.convertKeyIdToHex(keyId); + String query = null; + if (extras.containsKey(EXTRA_QUERY)) { + query = extras.getString(EXTRA_QUERY); + } else if (extras.containsKey(EXTRA_KEY_ID)) { + long keyId = extras.getLong(EXTRA_KEY_ID, 0); + if (keyId != 0) { + query = KeyFormattingUtils.convertKeyIdToHex(keyId); + } } - } - if (query != null && query.length() > 0) { - // display keyserver fragment with query - startCloudFragment(savedInstanceState, query, false); + if (query != null && query.length() > 0) { + // display keyserver fragment with query + startCloudFragment(savedInstanceState, query, false); - // action: search immediately - startListFragment(savedInstanceState, null, null, query); - } else { - Log.e(Constants.TAG, "Query is empty!"); - return; - } - } else if (extras.containsKey(EXTRA_FINGERPRINT)) { + // action: search immediately + startListFragment(savedInstanceState, null, null, query); + } else { + Log.e(Constants.TAG, "Query is empty!"); + return; + } + } else if (extras.containsKey(EXTRA_FINGERPRINT)) { /* * search based on fingerprint, here we can enforce a check in the end * if the right key has been downloaded */ - String fingerprint = extras.getString(EXTRA_FINGERPRINT); - if (isFingerprintValid(fingerprint)) { - String query = "0x" + fingerprint; + String fingerprint = extras.getString(EXTRA_FINGERPRINT); + if (isFingerprintValid(fingerprint)) { + String query = "0x" + fingerprint; - // display keyserver fragment with query - startCloudFragment(savedInstanceState, query, true); + // display keyserver fragment with query + startCloudFragment(savedInstanceState, query, true); - // action: search immediately - startListFragment(savedInstanceState, null, null, query); + // action: search immediately + startListFragment(savedInstanceState, null, null, query); + } + } else { + Log.e(Constants.TAG, + "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " + + "'fingerprint' extra!" + ); + return; } - } else { - Log.e(Constants.TAG, - "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " + - "'fingerprint' extra!" - ); - return; - } - } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { - // NOTE: this only displays the appropriate fragment, no actions are taken - startFileFragment(savedInstanceState); + break; + case ACTION_IMPORT_KEY_FROM_FILE: + // NOTE: this only displays the appropriate fragment, no actions are taken + startFileFragment(savedInstanceState); - // no immediate actions! - startListFragment(savedInstanceState, null, null, null); - } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { - // NOTE: this only displays the appropriate fragment, no actions are taken - startFileFragment(savedInstanceState); + // no immediate actions! + startListFragment(savedInstanceState, null, null, null); + break; + case ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN: + // NOTE: this only displays the appropriate fragment, no actions are taken + startFileFragment(savedInstanceState); - // no immediate actions! - startListFragment(savedInstanceState, null, null, null); - } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) { - // NOTE: this only displays the appropriate fragment, no actions are taken - startFileFragment(savedInstanceState); - // TODO!!!!! + // no immediate actions! + startListFragment(savedInstanceState, null, null, null); + break; + case ACTION_IMPORT_KEY_FROM_NFC: + // NOTE: this only displays the appropriate fragment, no actions are taken + startFileFragment(savedInstanceState); + // TODO!!!!! - // no immediate actions! - startListFragment(savedInstanceState, null, null, null); - } else { - startCloudFragment(savedInstanceState, null, false); - startListFragment(savedInstanceState, null, null, null); + // no immediate actions! + startListFragment(savedInstanceState, null, null, null); + break; + default: + startCloudFragment(savedInstanceState, null, false); + startListFragment(savedInstanceState, null, null, null); + break; } } @@ -353,7 +362,7 @@ public class ImportKeysActivity extends ActionBarActivity { // We parcel this iteratively into a file - anything we can // display here, we should be able to import. ParcelableFileCache cache = - new ParcelableFileCache(this, "key_import.pcl"); + new ParcelableFileCache<>(this, "key_import.pcl"); cache.writeCache(selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -385,7 +394,7 @@ public class ImportKeysActivity extends ActionBarActivity { data.putString(KeychainIntentService.IMPORT_KEY_SERVER, sls.mCloudPrefs.keyserver); // get selected key entries - ArrayList keys = new ArrayList(); + ArrayList keys = new ArrayList<>(); { // change the format into ParcelableKeyRing ArrayList entries = mListFragment.getSelectedEntries(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java index 03aba344a..1d12f49f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java @@ -81,7 +81,7 @@ public class ImportKeysCloudFragment extends Fragment { namesAndEmails.addAll(ContactHelper.getContactMails(getActivity())); mQueryEditText.setThreshold(3); mQueryEditText.setAdapter( - new ArrayAdapter + new ArrayAdapter<> (getActivity(), android.R.layout.simple_spinner_dropdown_item, namesAndEmails ) @@ -110,7 +110,7 @@ public class ImportKeysCloudFragment extends Fragment { mConfigButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - Intent i = new Intent(mImportActivity, PreferencesActivity.class); + Intent i = new Intent(mImportActivity, SettingsActivity.class); // GRR, for some reason I can’t set the Action or I get an incomprehensible // exception about “modern two-pane layouts” // i.setAction(PreferencesActivity.ACTION_PREFS_CLOUD); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 4fe53fb09..6a6140892 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -113,7 +113,7 @@ public class ImportKeysListFragment extends ListFragment implements return mAdapter.getSelectedEntries(); } else { Log.e(Constants.TAG, "Adapter not initialized, returning empty list"); - return new ArrayList(); + return new ArrayList<>(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index ba03400d7..b7f3588eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -41,15 +41,20 @@ import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; -public class KeyListActivity extends DrawerActivity { +import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer; + +public class KeyListActivity extends NavDrawerActivity { public static final int REQUEST_CODE_RESULT_TO_LIST = 1; ExportHelper mExportHelper; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); +// public void onCreate(Bundle savedInstanceState) { + public void init(Bundle savedInstanceState) { + super.init(savedInstanceState); +// super.onCreate(savedInstanceState); +// setActionBarIcon(R.drawable.ic_ab_drawer); setTitle(R.string.nav_keys); @@ -63,12 +68,22 @@ public class KeyListActivity extends DrawerActivity { mExportHelper = new ExportHelper(this); - setContentView(R.layout.key_list_activity); + Intent data = getIntent(); + // If we got an EXTRA_RESULT in the intent, show the notification + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(this).show(); + } // now setup navigation drawer in DrawerActivity... - activateDrawerNavigation(savedInstanceState); +// activateDrawerNavigation(savedInstanceState); } +// @Override +// protected void initLayout() { +// setContentView(R.layout.key_list_activity); +// } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index d0be052d8..fdc598394 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; -import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -31,7 +30,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -52,7 +50,6 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; -import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; @@ -60,16 +57,9 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.results.DeleteResult; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ExportHelper; -import org.sufficientlysecure.keychain.util.KeyUpdateHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -78,15 +68,10 @@ import org.sufficientlysecure.keychain.ui.widget.ListAwareSwipeRefreshLayout; import org.sufficientlysecure.keychain.ui.util.Highlighter; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.ui.util.Notify; -import org.sufficientlysecure.keychain.util.ParcelableFileCache; -import java.io.IOException; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import edu.cmu.cylab.starslinger.exchange.ExchangeActivity; -import edu.cmu.cylab.starslinger.exchange.ExchangeConfig; import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; import se.emilsjolander.stickylistheaders.StickyListHeadersListView; @@ -110,8 +95,6 @@ public class KeyListFragment extends LoaderFragment private String mQuery; private SearchView mSearchView; - boolean hideMenu = false; - /** * Load custom layout with StickyListView from library */ @@ -172,8 +155,8 @@ public class KeyListFragment extends LoaderFragment TextView title = (TextView) getActivity().findViewById(R.id.custom_actionbar_text); title.setText(R.string.swipe_to_update); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - hideMenu = true; - activity.invalidateOptionsMenu(); +// hideMenu = true; +// activity.invalidateOptionsMenu(); } } else { bar.setTitle(getActivity().getTitle()); @@ -184,8 +167,8 @@ public class KeyListFragment extends LoaderFragment bar.setDisplayShowCustomEnabled(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - hideMenu = false; - activity.invalidateOptionsMenu(); +// hideMenu = false; +// activity.invalidateOptionsMenu(); } } } @@ -470,10 +453,6 @@ public class KeyListFragment extends LoaderFragment MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() { @Override public boolean onMenuItemActionExpand(MenuItem item) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - hideMenu = true; - getActivity().invalidateOptionsMenu(); - } // disable swipe-to-refresh // mSwipeRefreshLayout.setIsLocked(true); @@ -485,22 +464,12 @@ public class KeyListFragment extends LoaderFragment mQuery = null; getLoaderManager().restartLoader(0, null, KeyListFragment.this); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - hideMenu = false; - getActivity().invalidateOptionsMenu(); - } // enable swipe-to-refresh // mSwipeRefreshLayout.setIsLocked(false); return true; } }); - if (hideMenu) { - for (int i = 0; i < menu.size(); i++) { - menu.getItem(i).setVisible(false); - } - } - super.onCreateOptionsMenu(menu, inflater); } @@ -533,7 +502,7 @@ public class KeyListFragment extends LoaderFragment private String mQuery; private LayoutInflater mInflater; - private HashMap mSelection = new HashMap(); + private HashMap mSelection = new HashMap<>(); public KeyListAdapter(Context context, Cursor c, int flags) { super(context, c, flags); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java index 4a2b88518..0de7bb391 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java @@ -19,21 +19,18 @@ package org.sufficientlysecure.keychain.ui; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.View; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; -public class LogDisplayActivity extends ActionBarActivity { +public class LogDisplayActivity extends BaseActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Inflate a "Done" custom action bar - ActionBarHelper.setOneButtonView(getSupportActionBar(), - R.string.btn_okay, R.drawable.ic_action_done, + setFullScreenDialogClose( new View.OnClickListener() { @Override public void onClick(View v) { @@ -42,7 +39,10 @@ public class LogDisplayActivity extends ActionBarActivity { } } ); + } + @Override + protected void initLayout() { setContentView(R.layout.log_display_activity); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java new file mode 100644 index 000000000..092334ac3 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.content.Intent; +import android.os.Bundle; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.remote.ui.AppsListActivity; + +import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer; + +public abstract class NavDrawerActivity extends MaterialNavigationDrawer { + + @Override + public void init(Bundle savedInstanceState) { + + // set the header image + this.setDrawerHeaderImage(R.drawable.mat2); + + // create sections + this.addSection(newSection(getString(R.string.app_name), R.drawable.ic_vpn_key_black_24dp, new KeyListFragment())); + + this.addSection(newSection(getString(R.string.title_encrypt_text), R.drawable.ic_lock_outline_black_24dp, new Intent(this, EncryptTextActivity.class))); + this.addSection(newSection(getString(R.string.title_encrypt_files), R.drawable.ic_lock_outline_black_24dp, new Intent(this, EncryptFilesActivity.class))); + this.addSection(newSection(getString(R.string.title_decrypt), R.drawable.ic_lock_open_black_24dp, new Intent(this, DecryptActivity.class))); + this.addSection(newSection(getString(R.string.title_api_registered_apps), R.drawable.ic_apps_black_24dp, new Intent(this, AppsListActivity.class))); + + // create bottom section + this.addBottomSection(newSection(getString(R.string.menu_preferences), R.drawable.ic_settings_black_24dp, new Intent(this, SettingsActivity.class))); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java index d0e40a9b8..7311f4879 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java @@ -15,7 +15,6 @@ import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Build; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.WindowManager; import android.widget.Toast; @@ -23,13 +22,11 @@ import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.Iso7816TLV; import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Locale; /** * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant @@ -38,7 +35,7 @@ import java.util.Locale; * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf */ @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) -public class NfcActivity extends ActionBarActivity { +public class NfcActivity extends BaseActivity { // actions public static final String ACTION_SIGN_HASH = "sign_hash"; @@ -82,8 +79,6 @@ public class NfcActivity extends ActionBarActivity { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - setContentView(R.layout.nfc_activity); - Intent intent = getIntent(); Bundle data = intent.getExtras(); String action = intent.getAction(); @@ -93,36 +88,46 @@ public class NfcActivity extends ActionBarActivity { mKeyId = data.getLong(EXTRA_KEY_ID); } - if (ACTION_SIGN_HASH.equals(action)) { - mAction = action; - mPin = data.getString(EXTRA_PIN); - mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN); - mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO); - mServiceIntent = data.getParcelable(EXTRA_DATA); + switch (action) { + case ACTION_SIGN_HASH: + mAction = action; + mPin = data.getString(EXTRA_PIN); + mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN); + mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO); + mServiceIntent = data.getParcelable(EXTRA_DATA); - Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); - Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); - Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign)); - Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); - } else if (ACTION_DECRYPT_SESSION_KEY.equals(action)) { - mAction = action; - mPin = data.getString(EXTRA_PIN); - mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY); - mServiceIntent = data.getParcelable(EXTRA_DATA); + Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); + Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); + Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign)); + Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); + break; + case ACTION_DECRYPT_SESSION_KEY: + mAction = action; + mPin = data.getString(EXTRA_PIN); + mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY); + mServiceIntent = data.getParcelable(EXTRA_DATA); - Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); - Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); - Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey)); - Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); - } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { - Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!"); - toast("This should not happen! Please create a new bug report that the NFC screen is restarted!"); - finish(); - } else { - Log.d(Constants.TAG, "Action not supported: " + action); + Log.d(Constants.TAG, "NfcActivity mAction: " + mAction); + Log.d(Constants.TAG, "NfcActivity mPin: " + mPin); + Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey)); + Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString()); + break; + case NfcAdapter.ACTION_TAG_DISCOVERED: + Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!"); + toast("This should not happen! Please create a new bug report that the NFC screen is restarted!"); + finish(); + break; + default: + Log.d(Constants.TAG, "Action not supported: " + action); + break; } } + @Override + protected void initLayout() { + setContentView(R.layout.nfc_activity); + } + /** * Called when the system is about to start resuming a previous activity, * disables NFC Foreground Dispatch diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java index cb15dbec2..3e8d688fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java @@ -15,7 +15,6 @@ import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Build; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.WindowManager; import android.widget.Toast; @@ -36,7 +35,7 @@ import java.nio.ByteBuffer; * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf */ @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) -public class NfcIntentActivity extends ActionBarActivity { +public class NfcIntentActivity extends BaseActivity { // special extra for OpenPgpService public static final String EXTRA_DATA = "data"; @@ -54,8 +53,6 @@ public class NfcIntentActivity extends ActionBarActivity { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - setContentView(R.layout.nfc_activity); - Intent intent = getIntent(); Bundle data = intent.getExtras(); String action = intent.getAction(); @@ -87,7 +84,11 @@ public class NfcIntentActivity extends ActionBarActivity { Log.e(Constants.TAG, "IOException!", e); finish(); } + } + @Override + protected void initLayout() { + setContentView(R.layout.nfc_activity); } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java index 93778fd0c..872e888a8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java @@ -209,9 +209,7 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit(); } - } catch (IOException e) { - e.printStackTrace(); - } catch (FormatException e) { + } catch (IOException | FormatException e) { e.printStackTrace(); } @@ -236,9 +234,7 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa nfc.setText(R.string.nfc_wrong_tag); } } - } catch (IOException e) { - e.printStackTrace(); - } catch (FormatException e) { + } catch (IOException | FormatException e) { e.printStackTrace(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java index 5966870df..1a7a028c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java @@ -78,7 +78,11 @@ public class QrCodeScanActivity extends FragmentActivity { // scan using xzing's Barcode Scanner and return result parcel in OpenKeychain returnResult = true; - new IntentIntegrator(this).initiateScan(); + IntentIntegrator integrator = new IntentIntegrator(this); + integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES) + .setPrompt(getString(R.string.import_qr_code_text)) + .setResultDisplayDuration(0) + .initiateScan(); } else if (ACTION_QR_CODE_API.equals(action)) { // scan using xzing's Barcode Scanner from outside OpenKeychain @@ -168,7 +172,7 @@ public class QrCodeScanActivity extends FragmentActivity { return; } - if ( ! result.success()) { + if (!result.success()) { // only return if no success... Intent data = new Intent(); data.putExtras(returnData); @@ -199,7 +203,7 @@ public class QrCodeScanActivity extends FragmentActivity { data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver); ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null); - ArrayList selectedEntries = new ArrayList(); + ArrayList selectedEntries = new ArrayList<>(); selectedEntries.add(keyEntry); data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java index cf0c3eb88..ef1d797be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java @@ -20,14 +20,12 @@ package org.sufficientlysecure.keychain.ui; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -36,7 +34,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; -public class QrCodeViewActivity extends ActionBarActivity { +public class QrCodeViewActivity extends BaseActivity { private ImageView mFingerprintQrCode; @@ -45,8 +43,7 @@ public class QrCodeViewActivity extends ActionBarActivity { super.onCreate(savedInstanceState); // Inflate a "Done" custom action bar - ActionBarHelper.setOneButtonView(getSupportActionBar(), - R.string.btn_okay, R.drawable.ic_action_done, + setFullScreenDialogClose( new View.OnClickListener() { @Override public void onClick(View v) { @@ -56,8 +53,6 @@ public class QrCodeViewActivity extends ActionBarActivity { } ); - setContentView(R.layout.qr_code_activity); - Uri dataUri = getIntent().getData(); if (dataUri == null) { Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); @@ -108,6 +103,11 @@ public class QrCodeViewActivity extends ActionBarActivity { } } + @Override + protected void initLayout() { + setContentView(R.layout.qr_code_activity); + } + @Override protected void onResume() { super.onResume(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java index 20e1bbe97..f95644aff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java @@ -27,13 +27,9 @@ import android.os.Bundle; import android.os.Message; import android.os.Messenger; import android.support.v4.app.FragmentActivity; -import android.support.v7.app.ActionBarActivity; import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.NumberPicker; -import android.widget.Spinner; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -50,13 +46,12 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import edu.cmu.cylab.starslinger.exchange.ExchangeActivity; import edu.cmu.cylab.starslinger.exchange.ExchangeConfig; @TargetApi(Build.VERSION_CODES.HONEYCOMB) -public class SafeSlingerActivity extends ActionBarActivity { +public class SafeSlingerActivity extends BaseActivity { private static final int REQUEST_CODE_SAFE_SLINGER = 211; @@ -69,51 +64,17 @@ public class SafeSlingerActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.safe_slinger_activity); - mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, 0); - // NOTE: there are two versions of this layout, for API >= 11 and one for < 11 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - NumberPicker picker = (NumberPicker) findViewById(R.id.safe_slinger_picker); - picker.setMinValue(2); - picker.setMaxValue(10); - picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - mSelectedNumber = newVal; - } - }); - } else { - Spinner spinner = (Spinner) findViewById(R.id.safe_slinger_spinner); - - List list = new ArrayList(); - list.add("2"); - list.add("3"); - list.add("4"); - list.add("5"); - list.add("6"); - list.add("7"); - list.add("8"); - list.add("9"); - list.add("10"); - - ArrayAdapter dataAdapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, list); - dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(dataAdapter); - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - mSelectedNumber = position + 2; - } - - @Override - public void onNothingSelected(AdapterView parent) { - - } - }); - } + NumberPicker picker = (NumberPicker) findViewById(R.id.safe_slinger_picker); + picker.setMinValue(2); + picker.setMaxValue(10); + picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mSelectedNumber = newVal; + } + }); ImageView buttonIcon = (ImageView) findViewById(R.id.safe_slinger_button_image); buttonIcon.setColorFilter(getResources().getColor(R.color.tertiary_text_light), @@ -128,6 +89,11 @@ public class SafeSlingerActivity extends ActionBarActivity { }); } + @Override + protected void initLayout() { + setContentView(R.layout.safe_slinger_activity); + } + private void startExchange(long masterKeyId, int number) { // retrieve public key blob and start SafeSlinger Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId); @@ -221,7 +187,7 @@ public class SafeSlingerActivity extends ActionBarActivity { // We parcel this iteratively into a file - anything we can // display here, we should be able to import. ParcelableFileCache cache = - new ParcelableFileCache(activity, "key_import.pcl"); + new ParcelableFileCache<>(activity, "key_import.pcl"); cache.writeCache(it.size(), it.iterator()); // fill values for this action @@ -249,7 +215,7 @@ public class SafeSlingerActivity extends ActionBarActivity { } private static ArrayList getSlingedKeys(Bundle extras) { - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); if (extras != null) { byte[] d; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java index 148aa7d67..0e3374833 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java @@ -20,14 +20,12 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; -public class SelectPublicKeyActivity extends ActionBarActivity { +public class SelectPublicKeyActivity extends BaseActivity { // Actions for internal use only: public static final String ACTION_SELECT_PUBLIC_KEYS = Constants.INTENT_PREFIX @@ -47,23 +45,19 @@ public class SelectPublicKeyActivity extends ActionBarActivity { super.onCreate(savedInstanceState); // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done, + setFullScreenDialogDoneClose(R.string.btn_okay, new View.OnClickListener() { @Override public void onClick(View v) { - // ok okClicked(); } - }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() { + }, + new View.OnClickListener() { @Override public void onClick(View v) { - // cancel cancelClicked(); } - } - ); - - setContentView(R.layout.select_public_key_activity); + }); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); @@ -101,6 +95,11 @@ public class SelectPublicKeyActivity extends ActionBarActivity { } + @Override + protected void initLayout() { + setContentView(R.layout.select_public_key_activity); + } + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java index af583bf89..afec3bf06 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java @@ -42,7 +42,6 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter; @@ -216,7 +215,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T public long[] getSelectedMasterKeyIds() { // mListView.getCheckedItemIds() would give the row ids of the KeyRings not the master key // ids! - Vector vector = new Vector(); + Vector vector = new Vector<>(); for (int i = 0; i < getListView().getCount(); ++i) { if (getListView().isItemChecked(i)) { vector.add(mAdapter.getMasterKeyId(i)); @@ -238,7 +237,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T * @return */ public String[] getSelectedUserIds() { - Vector userIds = new Vector(); + Vector userIds = new Vector<>(); for (int i = 0; i < getListView().getCount(); ++i) { if (getListView().isItemChecked(i)) { userIds.add(mAdapter.getUserId(i)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java similarity index 92% rename from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java rename to OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index 51fac4779..e2fc44689 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -17,7 +17,7 @@ package org.sufficientlysecure.keychain.ui; -import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.os.Build; @@ -27,19 +27,22 @@ import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference; +import org.sufficientlysecure.keychain.util.Preferences; import java.util.List; -@SuppressLint("NewApi") -public class PreferencesActivity extends PreferenceActivity { +public class SettingsActivity extends PreferenceActivity { public static final String ACTION_PREFS_CLOUD = "org.sufficientlysecure.keychain.ui.PREFS_CLOUD"; public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV"; @@ -54,6 +57,8 @@ public class PreferencesActivity extends PreferenceActivity { sPreferences = Preferences.getPreferences(this); super.onCreate(savedInstanceState); + setupToolbar(); + String action = getIntent().getAction(); if (action != null && action.equals(ACTION_PREFS_CLOUD)) { @@ -64,9 +69,9 @@ public class PreferencesActivity extends PreferenceActivity { mKeyServerPreference .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { - Intent intent = new Intent(PreferencesActivity.this, - PreferencesKeyServerActivity.class); - intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS, + Intent intent = new Intent(SettingsActivity.this, + SettingsKeyServerActivity.class); + intent.putExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS, sPreferences.getKeyServers()); startActivityForResult(intent, REQUEST_CODE_KEYSERVER_PREF); return false; @@ -130,12 +135,33 @@ public class PreferencesActivity extends PreferenceActivity { initializeUseNumKeypadForYubikeyPin( (CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN)); - } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - // Load the legacy preferences headers - addPreferencesFromResource(R.xml.preference_headers_legacy); } } + /** + * Hack to get Toolbar in PreferenceActivity. See http://stackoverflow.com/a/26614696 + */ + private void setupToolbar() { + ViewGroup root = (ViewGroup) findViewById(android.R.id.content); + LinearLayout content = (LinearLayout) root.getChildAt(0); + LinearLayout toolbarContainer = (LinearLayout) View.inflate(this, R.layout.preference_toolbar_activity, null); + + root.removeAllViews(); + toolbarContainer.addView(content); + root.addView(toolbarContainer); + + Toolbar toolbar = (Toolbar) toolbarContainer.findViewById(R.id.toolbar); + toolbar.setTitle(R.string.title_preferences); + toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp)); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //What to do on back clicked + finish(); + } + }); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -144,7 +170,7 @@ public class PreferencesActivity extends PreferenceActivity { return; } String servers[] = data - .getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS); + .getStringArrayExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS); sPreferences.setKeyServers(servers); mKeyServerPreference.setSummary(keyserverSummary(this)); break; @@ -185,8 +211,8 @@ public class PreferencesActivity extends PreferenceActivity { .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { Intent intent = new Intent(getActivity(), - PreferencesKeyServerActivity.class); - intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS, + SettingsKeyServerActivity.class); + intent.putExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS, sPreferences.getKeyServers()); startActivityForResult(intent, REQUEST_CODE_KEYSERVER_PREF); return false; @@ -208,7 +234,7 @@ public class PreferencesActivity extends PreferenceActivity { return; } String servers[] = data - .getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS); + .getStringArrayExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS); sPreferences.setKeyServers(servers); mKeyServerPreference.setSummary(keyserverSummary(getActivity())); break; @@ -287,6 +313,7 @@ public class PreferencesActivity extends PreferenceActivity { } } + @TargetApi(Build.VERSION_CODES.KITKAT) protected boolean isValidFragment(String fragmentName) { return AdvancedPrefsFragment.class.getName().equals(fragmentName) || CloudSearchPrefsFragment.class.getName().equals(fragmentName) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java similarity index 89% rename from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java rename to OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java index 2a8ef171c..080dc2495 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java @@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -28,14 +27,13 @@ import android.view.ViewGroup; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.ui.widget.Editor; import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor; import java.util.Vector; -public class PreferencesKeyServerActivity extends ActionBarActivity implements OnClickListener, +public class SettingsKeyServerActivity extends BaseActivity implements OnClickListener, EditorListener { public static final String EXTRA_KEY_SERVERS = "key_servers"; @@ -52,23 +50,19 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O super.onCreate(savedInstanceState); // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done, + setFullScreenDialogDoneClose(R.string.btn_save, new View.OnClickListener() { @Override public void onClick(View v) { - // ok okClicked(); } - }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() { + }, + new View.OnClickListener() { @Override public void onClick(View v) { - // cancel cancelClicked(); } - } - ); - - setContentView(R.layout.key_server_preference); + }); mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -102,6 +96,11 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O makeServerList(servers); } + @Override + protected void initLayout() { + setContentView(R.layout.key_server_preference); + } + private void makeServerList(String[] servers) { if (servers != null) { mEditors.removeAllViews(); @@ -137,7 +136,7 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O } private Vector serverList() { - Vector servers = new Vector(); + Vector servers = new Vector<>(); for (int i = 0; i < mEditors.getChildCount(); ++i) { KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i); String tmp = editor.getValue(); @@ -150,7 +149,7 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O private void okClicked() { Intent data = new Intent(); - Vector servers = new Vector(); + Vector servers = new Vector<>(); for (int i = 0; i < mEditors.getChildCount(); ++i) { KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i); String tmp = editor.getValue(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java index 497486a5e..ed86fea0a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java @@ -24,7 +24,6 @@ import android.os.Bundle; import android.os.Message; import android.os.Messenger; import android.support.v4.app.NavUtils; -import android.support.v7.app.ActionBarActivity; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; @@ -44,7 +43,7 @@ import org.sufficientlysecure.keychain.util.Log; /** * Sends the selected public key to a keyserver */ -public class UploadKeyActivity extends ActionBarActivity { +public class UploadKeyActivity extends BaseActivity { private View mUploadButton; private Spinner mKeyServerSpinner; @@ -54,12 +53,10 @@ public class UploadKeyActivity extends ActionBarActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.upload_key_activity); - mUploadButton = findViewById(R.id.upload_key_action_upload); mKeyServerSpinner = (Spinner) findViewById(R.id.upload_key_keyserver); - ArrayAdapter adapter = new ArrayAdapter(this, + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this) .getKeyServers() ); @@ -86,6 +83,11 @@ public class UploadKeyActivity extends ActionBarActivity { } } + @Override + protected void initLayout() { + setContentView(R.layout.upload_key_activity); + } + private void uploadKey() { // Send all information needed to service to upload key in other thread Intent intent = new Intent(this, KeychainIntentService.class); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 34c08a6c7..05d9dd58e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -27,9 +27,6 @@ import android.support.v4.app.NavUtils; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; import android.text.format.DateFormat; import android.view.MenuItem; import android.view.View; @@ -37,7 +34,6 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.pgp.WrappedSignature; @@ -49,7 +45,7 @@ import org.sufficientlysecure.keychain.util.Log; import java.util.Date; -public class ViewCertActivity extends ActionBarActivity +public class ViewCertActivity extends BaseActivity implements LoaderManager.LoaderCallbacks { // These are the rows that we will retrieve. @@ -86,8 +82,6 @@ public class ViewCertActivity extends ActionBarActivity ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); - setContentView(R.layout.view_cert_activity); - mSigneeKey = (TextView) findViewById(R.id.signee_key); mSigneeUid = (TextView) findViewById(R.id.signee_uid); mAlgorithm = (TextView) findViewById(R.id.algorithm); @@ -112,6 +106,11 @@ public class ViewCertActivity extends ActionBarActivity getSupportLoaderManager().initLoader(0, null, this); } + @Override + protected void initLayout() { + setContentView(R.layout.view_cert_activity); + } + @Override public Loader onCreateLoader(int id, Bundle args) { // Now create and return a CursorLoader that will take care of diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 0bc75b3a9..3bb0695a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; import android.content.Intent; import android.database.Cursor; -import android.graphics.PorterDuff; import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; @@ -38,7 +37,6 @@ import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -47,27 +45,26 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import com.astuetz.PagerSlidingTabStrip; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.util.ContactHelper; -import org.sufficientlysecure.keychain.util.ExportHelper; -import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; -import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; -import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout.TabColorizer; -import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.util.ContactHelper; +import org.sufficientlysecure.keychain.util.ExportHelper; +import org.sufficientlysecure.keychain.util.Log; import java.util.Date; import java.util.HashMap; -public class ViewKeyActivity extends ActionBarActivity implements +public class ViewKeyActivity extends BaseActivity implements LoaderManager.LoaderCallbacks { ExportHelper mExportHelper; @@ -81,7 +78,7 @@ public class ViewKeyActivity extends ActionBarActivity implements // view private ViewPager mViewPager; - private SlidingTabLayout mSlidingTabLayout; + private PagerSlidingTabStrip mSlidingTabLayout; private PagerTabStripAdapter mTabsAdapter; private LinearLayout mStatusLayout; @@ -111,27 +108,13 @@ public class ViewKeyActivity extends ActionBarActivity implements actionBar.setIcon(android.R.color.transparent); actionBar.setHomeButtonEnabled(true); - setContentView(R.layout.view_key_activity); - mStatusLayout = (LinearLayout) findViewById(R.id.view_key_status_layout); mStatusText = (TextView) findViewById(R.id.view_key_status_text); mStatusImage = (ImageView) findViewById(R.id.view_key_status_image); mStatusDivider = findViewById(R.id.view_key_status_divider); mViewPager = (ViewPager) findViewById(R.id.view_key_pager); - mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.view_key_sliding_tab_layout); - - mSlidingTabLayout.setCustomTabColorizer(new TabColorizer() { - @Override - public int getIndicatorColor(int position) { - return 0xFFAA66CC; - } - - @Override - public int getDividerColor(int position) { - return 0; - } - }); + mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.view_key_sliding_tab_layout); int switchToTab = TAB_MAIN; Intent intent = getIntent(); @@ -169,6 +152,11 @@ public class ViewKeyActivity extends ActionBarActivity implements mViewPager.setCurrentItem(switchToTab); } + @Override + protected void initLayout() { + setContentView(R.layout.view_key_activity); + } + private void initTabs(Uri dataUri) { mTabsAdapter = new PagerTabStripAdapter(this); mViewPager.setAdapter(mTabsAdapter); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java index f49f8e7cf..471f55c47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java @@ -20,18 +20,15 @@ package org.sufficientlysecure.keychain.ui; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.util.ActionBarHelper; import org.sufficientlysecure.keychain.util.ExportHelper; import org.sufficientlysecure.keychain.util.Log; -public class ViewKeyAdvancedActivity extends ActionBarActivity { +public class ViewKeyAdvancedActivity extends BaseActivity { ExportHelper mExportHelper; ProviderHelper mProviderHelper; @@ -44,8 +41,7 @@ public class ViewKeyAdvancedActivity extends ActionBarActivity { mProviderHelper = new ProviderHelper(this); // Inflate a "Done" custom action bar - ActionBarHelper.setOneButtonView(getSupportActionBar(), - R.string.btn_okay, R.drawable.ic_action_done, + setFullScreenDialogClose( new View.OnClickListener() { @Override public void onClick(View v) { @@ -55,8 +51,6 @@ public class ViewKeyAdvancedActivity extends ActionBarActivity { } ); - setContentView(R.layout.view_key_advanced_activity); - Uri dataUri = getIntent().getData(); if (dataUri == null) { Log.e(Constants.TAG, "Data missing. Should be uri of key!"); @@ -69,6 +63,10 @@ public class ViewKeyAdvancedActivity extends ActionBarActivity { startFragment(savedInstanceState, dataUri); } + @Override + protected void initLayout() { + setContentView(R.layout.view_key_advanced_activity); + } private void startFragment(Bundle savedInstanceState, Uri dataUri) { // However, if we're being restored from a previous state, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java index 9c37f2d94..61bd126ce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java @@ -80,7 +80,7 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements static final String CERTS_SORT_ORDER = KeychainDatabase.Tables.CERTS + "." + KeychainContract.Certs.RANK + " ASC, " + KeychainContract.Certs.VERIFIED + " DESC, " - + KeychainContract.Certs.TYPE + " DESC, " + + KeychainDatabase.Tables.CERTS + "." + KeychainContract.Certs.TYPE + " DESC, " + KeychainContract.Certs.SIGNER_UID + " ASC"; /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index f1453c40c..205d19628 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -37,10 +37,10 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; @@ -199,7 +199,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null); } case LOADER_ID_USER_IDS: { - Uri baseUri = UserIds.buildUserIdsUri(mDataUri); + Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); return new CursorLoader(getActivity(), baseUri, UserIdsAdapter.USER_IDS_PROJECTION, null, null, null); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index aa260b654..7c47cbd0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -228,10 +228,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements } startActivity(Intent.createChooser(sendIntent, title)); } - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, "error processing key!", e); - Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR); - } catch (IOException e) { + } catch (PgpGeneralException | IOException e) { Log.e(Constants.TAG, "error processing key!", e); Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR); } catch (ProviderHelper.NotFoundException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 6c81e9193..8e82dd7d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -95,8 +95,8 @@ public class ImportKeysAdapter extends ArrayAdapter { * @see org.sufficientlysecure.keychain.operations.ImportExportOperation */ public ArrayList getSelectedEntries() { - ArrayList result = new ArrayList(); - ArrayList secrets = new ArrayList(); + ArrayList result = new ArrayList<>(); + ArrayList secrets = new ArrayList<>(); if (mData == null) { return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java index 176c3ff5b..235fdf1d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java @@ -39,7 +39,7 @@ public class ImportKeysListCloudLoader Preferences.CloudSearchPrefs mCloudPrefs; String mServerQuery; - private ArrayList mEntryList = new ArrayList(); + private ArrayList mEntryList = new ArrayList<>(); private AsyncTaskResultWrapper> mEntryListWrapper; public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs) { @@ -51,7 +51,7 @@ public class ImportKeysListCloudLoader @Override public AsyncTaskResultWrapper> loadInBackground() { - mEntryListWrapper = new AsyncTaskResultWrapper>(mEntryList, null); + mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, null); if (mServerQuery == null) { Log.e(Constants.TAG, "mServerQuery is null!"); @@ -119,7 +119,7 @@ public class ImportKeysListCloudLoader mEntryList.addAll(searchResult); } GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null); - mEntryListWrapper = new AsyncTaskResultWrapper>(mEntryList, getKeyResult); + mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult); } catch (Keyserver.CloudSearchFailureException e) { // convert exception to result parcel int error = GetKeyResult.RESULT_ERROR; @@ -140,7 +140,7 @@ public class ImportKeysListCloudLoader OperationResult.OperationLog log = new OperationResult.OperationLog(); log.add(logType, 0); GetKeyResult getKeyResult = new GetKeyResult(error, log); - mEntryListWrapper = new AsyncTaskResultWrapper>(mEntryList, getKeyResult); + mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult); } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index cecad2716..9d1e8468c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -35,7 +35,6 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import java.io.BufferedInputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; public class ImportKeysListLoader extends AsyncTaskLoader>> { @@ -55,8 +54,8 @@ public class ImportKeysListLoader final Context mContext; final InputData mInputData; - ArrayList mData = new ArrayList(); - LongSparseArray mParcelableRings = new LongSparseArray(); + ArrayList mData = new ArrayList<>(); + LongSparseArray mParcelableRings = new LongSparseArray<>(); AsyncTaskResultWrapper> mEntryListWrapper; public ImportKeysListLoader(Context context, InputData inputData) { @@ -73,7 +72,7 @@ public class ImportKeysListLoader } GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null); - mEntryListWrapper = new AsyncTaskResultWrapper>(mData, getKeyResult); + mEntryListWrapper = new AsyncTaskResultWrapper<>(mData, getKeyResult); if (mInputData == null) { Log.e(Constants.TAG, "Input data is null!"); @@ -140,7 +139,7 @@ public class ImportKeysListLoader OperationResult.OperationLog log = new OperationResult.OperationLog(); log.add(OperationResult.LogType.MSG_GET_NO_VALID_KEYS, 0); GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_ERROR_NO_VALID_KEYS, log); - mEntryListWrapper = new AsyncTaskResultWrapper> + mEntryListWrapper = new AsyncTaskResultWrapper<> (mData, getKeyResult); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java index 80d605fb9..b8fe21941 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java @@ -33,7 +33,7 @@ public class KeyValueSpinnerAdapter extends ArrayAdapter { static > SortedSet> entriesSortedByValues( Map map) { - SortedSet> sortedEntries = new TreeSet>( + SortedSet> sortedEntries = new TreeSet<>( new Comparator>() { @Override public int compare(Map.Entry e1, Map.Entry e2) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java index 9f29826ef..47ad5e664 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java @@ -44,7 +44,7 @@ public class MultiUserIdsAdapter extends CursorAdapter { public MultiUserIdsAdapter(Context context, Cursor c, int flags) { super(context, c, flags); mInflater = LayoutInflater.from(context); - mCheckStates = new ArrayList(); + mCheckStates = new ArrayList<>(); } @Override @@ -148,7 +148,7 @@ public class MultiUserIdsAdapter extends CursorAdapter { } public ArrayList getSelectedCertifyActions() { - LongSparseArray actions = new LongSparseArray(); + LongSparseArray actions = new LongSparseArray<>(); for (int i = 0; i < mCheckStates.size(); i++) { if (mCheckStates.get(i)) { mCursor.moveToPosition(i); @@ -171,7 +171,7 @@ public class MultiUserIdsAdapter extends CursorAdapter { } } - ArrayList result = new ArrayList(actions.size()); + ArrayList result = new ArrayList<>(actions.size()); for (int i = 0; i < actions.size(); i++) { result.add(actions.valueAt(i)); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java index 330254a8f..963e77fe9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java @@ -27,7 +27,7 @@ import java.util.ArrayList; public class PagerTabStripAdapter extends FragmentPagerAdapter { protected final Activity mActivity; - protected final ArrayList mTabs = new ArrayList(); + protected final ArrayList mTabs = new ArrayList<>(); static final class TabInfo { public final Class clss; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index a032e96fc..5ba09be7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -35,7 +35,7 @@ import android.widget.ImageView; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; @@ -160,7 +160,11 @@ public class SubkeysAdapter extends CursorAdapter { cursor.getString(INDEX_KEY_CURVE_OID) )); - if (mSaveKeyringParcel != null && mSaveKeyringParcel.mStripSubKeys.contains(keyId)) { + SubkeyChange change = mSaveKeyringParcel != null + ? mSaveKeyringParcel.getSubkeyChange(keyId) + : null; + + if (change != null && change.mDummyStrip) { algorithmStr.append(", "); final SpannableString boldStripped = new SpannableString( context.getString(R.string.key_stripped) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java index 9ddfa90be..44afed351 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java @@ -33,7 +33,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar. private final Context mContext; private final ActionBar mActionBar; private final ViewPager mViewPager; - private final ArrayList mTabs = new ArrayList(); + private final ArrayList mTabs = new ArrayList<>(); static final class TabInfo { public final Class clss; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index a2e1930d3..52c21e253 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.database.Cursor; -import android.graphics.PorterDuff; import android.graphics.Typeface; import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; @@ -32,10 +31,9 @@ import android.widget.ImageView; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; @@ -47,12 +45,12 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC private SaveKeyringParcel mSaveKeyringParcel; public static final String[] USER_IDS_PROJECTION = new String[]{ - UserIds._ID, - UserIds.USER_ID, - UserIds.RANK, - UserIds.VERIFIED, - UserIds.IS_PRIMARY, - UserIds.IS_REVOKED + UserPackets._ID, + UserPackets.USER_ID, + UserPackets.RANK, + UserPackets.VERIFIED, + UserPackets.IS_PRIMARY, + UserPackets.IS_REVOKED }; private static final int INDEX_ID = 0; private static final int INDEX_USER_ID = 1; @@ -223,7 +221,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC } public ArrayList getSelectedUserIds() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (int i = 0; i < mCheckStates.size(); i++) { if (mCheckStates.get(i)) { mCursor.moveToPosition(i); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java index b4119a5eb..d5376cbdc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java @@ -145,20 +145,20 @@ public class AddSubkeyDialogFragment extends DialogFragment { } { - ArrayList> choices = new ArrayList>(); - choices.add(new Choice(Algorithm.DSA, getResources().getString( + ArrayList> choices = new ArrayList<>(); + choices.add(new Choice<>(Algorithm.DSA, getResources().getString( R.string.dsa))); if (!mWillBeMasterKey) { - choices.add(new Choice(Algorithm.ELGAMAL, getResources().getString( + choices.add(new Choice<>(Algorithm.ELGAMAL, getResources().getString( R.string.elgamal))); } - choices.add(new Choice(Algorithm.RSA, getResources().getString( + choices.add(new Choice<>(Algorithm.RSA, getResources().getString( R.string.rsa))); - choices.add(new Choice(Algorithm.ECDSA, getResources().getString( + choices.add(new Choice<>(Algorithm.ECDSA, getResources().getString( R.string.ecdsa))); - choices.add(new Choice(Algorithm.ECDH, getResources().getString( + choices.add(new Choice<>(Algorithm.ECDH, getResources().getString( R.string.ecdh))); - ArrayAdapter> adapter = new ArrayAdapter>(context, + ArrayAdapter> adapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, choices); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mAlgorithmSpinner.setAdapter(adapter); @@ -172,20 +172,20 @@ public class AddSubkeyDialogFragment extends DialogFragment { } // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change - ArrayAdapter keySizeAdapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, + ArrayAdapter keySizeAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mKeySizeSpinner.setAdapter(keySizeAdapter); mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length { - ArrayList> choices = new ArrayList>(); + ArrayList> choices = new ArrayList<>(); - choices.add(new Choice(Curve.NIST_P256, getResources().getString( + choices.add(new Choice<>(Curve.NIST_P256, getResources().getString( R.string.key_curve_nist_p256))); - choices.add(new Choice(Curve.NIST_P384, getResources().getString( + choices.add(new Choice<>(Curve.NIST_P384, getResources().getString( R.string.key_curve_nist_p384))); - choices.add(new Choice(Curve.NIST_P521, getResources().getString( + choices.add(new Choice<>(Curve.NIST_P521, getResources().getString( R.string.key_curve_nist_p521))); /* @see SaveKeyringParcel @@ -197,7 +197,7 @@ public class AddSubkeyDialogFragment extends DialogFragment { R.string.key_curve_bp_p512))); */ - ArrayAdapter> adapter = new ArrayAdapter>(context, + ArrayAdapter> adapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, choices); mCurveSpinner.setAdapter(adapter); // make NIST P-256 the default diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index 3eef04aa7..a4ecc7c27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -85,7 +85,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA mMessenger = getArguments().getParcelable(ARG_MESSENGER); String predefinedName = getArguments().getString(ARG_NAME); - ArrayAdapter autoCompleteEmailAdapter = new ArrayAdapter + ArrayAdapter autoCompleteEmailAdapter = new ArrayAdapter<> (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserEmails(getActivity()) ); @@ -150,7 +150,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA mName.setThreshold(1); // Start working from first character mName.setAdapter( - new ArrayAdapter + new ArrayAdapter<> (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserNames(getActivity()) ) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index 42e21cd57..879e3f6da 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Dialog; +import android.content.ContentResolver; import android.content.DialogInterface; import android.net.Uri; import android.os.Build; @@ -30,6 +31,8 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.FileHelper; +import java.io.File; + public class DeleteFileDialogFragment extends DialogFragment { private static final String ARG_DELETE_URI = "delete_uri"; @@ -69,21 +72,38 @@ public class DeleteFileDialogFragment extends DialogFragment { @Override public void onClick(DialogInterface dialog, int id) { dismiss(); + String scheme = deleteUri.getScheme(); - // We can not securely delete Uris, so just use usual delete on them - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) { + if(scheme.equals(ContentResolver.SCHEME_FILE)) { + if(new File(deleteUri.getPath()).delete()) { + Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + return; + } + } + else if(scheme.equals(ContentResolver.SCHEME_CONTENT)) { + // We can not securely delete Uris, so just use usual delete on them + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) { + Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + return; + } + } + + if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) { + Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + return; + } + + // some Uri's a ContentResolver fails to delete is handled by the java.io.File's delete + // via the path of the Uri + if(new File(deleteUri.getPath()).delete()) { Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); return; } } - if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) { - Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); - return; - } - - Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, deleteFilename), Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, + deleteFilename), Toast.LENGTH_SHORT).show(); // Note: We can't delete every file... // If possible we should find out if deletion is possible before even showing the option to do so. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java deleted file mode 100644 index edd12ec73..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui.util; - -import android.app.Activity; -import android.support.v7.app.ActionBar; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.R; - -public class ActionBarHelper { - - /** - * Sets custom view on ActionBar for Done/Cancel activities - * - * @param actionBar - * @param firstText - * @param firstDrawableId - * @param firstOnClickListener - * @param secondText - * @param secondDrawableId - * @param secondOnClickListener - */ - public static void setTwoButtonView(ActionBar actionBar, - int firstText, int firstDrawableId, OnClickListener firstOnClickListener, - int secondText, int secondDrawableId, OnClickListener secondOnClickListener) { - - // Inflate the custom action bar view - final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext() - .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); - final View customActionBarView = inflater.inflate( - R.layout.actionbar_custom_view_done_cancel, null); - - TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)); - firstTextView.setText(firstText); - firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0); - customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( - firstOnClickListener); - TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)); - secondTextView.setText(secondText); - secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0); - customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener( - secondOnClickListener); - - // Show the custom action bar view and hide the normal Home icon and title. - actionBar.setDisplayShowTitleEnabled(false); - actionBar.setDisplayShowHomeEnabled(false); - actionBar.setDisplayShowCustomEnabled(true); - actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - } - - /** - * Sets custom view on ActionBar for Done activities - * - * @param actionBar - * @param firstText - * @param firstOnClickListener - */ - public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId, - OnClickListener firstOnClickListener) { - // Inflate a "Done" custom action bar view to serve as the "Up" affordance. - final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext() - .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); - final View customActionBarView = inflater - .inflate(R.layout.actionbar_custom_view_done, null); - - TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)); - firstTextView.setText(firstText); - firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0); - customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( - firstOnClickListener); - - // Show the custom action bar view and hide the normal Home icon and title. - actionBar.setDisplayShowTitleEnabled(false); - actionBar.setDisplayShowHomeEnabled(false); - actionBar.setDisplayShowCustomEnabled(true); - actionBar.setCustomView(customActionBarView); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java index 36f38045f..0bb4100c5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java @@ -47,7 +47,7 @@ public class QrCodeUtils { */ public static Bitmap getQRCodeBitmap(final String input, final int size) { try { - final Hashtable hints = new Hashtable(); + final Hashtable hints = new Hashtable<>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); final BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size, size, hints); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 14f42eb04..904cde47e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -29,7 +29,6 @@ import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; public class CertifyKeySpinner extends KeySpinner { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index e03a14989..5f6f13181 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -28,7 +28,6 @@ import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; -import android.text.SpannableStringBuilder; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -46,7 +45,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; @@ -165,7 +163,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { setAdapter(new EncryptKeyAdapter(Collections.emptyList())); return; } - ArrayList keys = new ArrayList(); + ArrayList keys = new ArrayList<>(); while (cursor.moveToNext()) { try { EncryptionKey key = new EncryptionKey(cursor); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java index b456b61ab..34e7b639a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java @@ -33,17 +33,16 @@ import org.sufficientlysecure.keychain.R; /** * Class representing a LinearLayout that can fold and hide it's content when pressed * To use just add the following to your xml layout - - - - - - - + *

+ * + *

+ * + *

+ * */ public class FoldableLinearLayout extends LinearLayout { @@ -75,6 +74,7 @@ public class FoldableLinearLayout extends LinearLayout { /** * Load given attributes to inner variables, + * * @param context * @param attrs */ @@ -87,8 +87,8 @@ public class FoldableLinearLayout extends LinearLayout { a.recycle(); } // If any attribute isn't found then set a default one - mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.id.none) : mFoldedLabel; - mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.id.none) : mUnFoldedLabel; + mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.string.none) : mFoldedLabel; + mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.string.none) : mUnFoldedLabel; } @Override @@ -138,7 +138,7 @@ public class FoldableLinearLayout extends LinearLayout { private void initialiseInnerViews() { mFoldableIcon = (ImageView) mFoldableLayout.findViewById(R.id.foldableIcon); - mFoldableIcon.setImageResource(R.drawable.ic_action_expand); + mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp); mFoldableTextView = (TextView) mFoldableLayout.findViewById(R.id.foldableText); mFoldableTextView.setText(mFoldedLabel); @@ -151,7 +151,7 @@ public class FoldableLinearLayout extends LinearLayout { public void onClick(View view) { mFolded = !mFolded; if (mFolded) { - mFoldableIcon.setImageResource(R.drawable.ic_action_collapse); + mFoldableIcon.setImageResource(R.drawable.ic_expand_less_black_24dp); mFoldableContainer.setVisibility(View.VISIBLE); AlphaAnimation animation = new AlphaAnimation(0f, 1f); animation.setDuration(mShortAnimationDuration); @@ -159,12 +159,13 @@ public class FoldableLinearLayout extends LinearLayout { mFoldableTextView.setText(mUnFoldedLabel); } else { - mFoldableIcon.setImageResource(R.drawable.ic_action_expand); + mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp); AlphaAnimation animation = new AlphaAnimation(1f, 0f); animation.setDuration(mShortAnimationDuration); animation.setAnimationListener(new Animation.AnimationListener() { @Override - public void onAnimationStart(Animation animation) { } + public void onAnimationStart(Animation animation) { + } @Override public void onAnimationEnd(Animation animation) { @@ -173,7 +174,8 @@ public class FoldableLinearLayout extends LinearLayout { } @Override - public void onAnimationRepeat(Animation animation) { } + public void onAnimationRepeat(Animation animation) { + } }); mFoldableContainer.startAnimation(animation); mFoldableTextView.setText(mFoldedLabel); @@ -185,6 +187,7 @@ public class FoldableLinearLayout extends LinearLayout { /** * Adds provided child view to foldableContainer View + * * @param child */ @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java index b3c3eb417..3403208d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java @@ -20,13 +20,8 @@ package org.sufficientlysecure.keychain.ui.widget; import android.content.Context; import android.support.v4.widget.NoScrollableSwipeRefreshLayout; import android.util.AttributeSet; -import android.view.InputDevice; -import android.view.InputDevice.MotionRange; import android.view.MotionEvent; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.util.Log; - import se.emilsjolander.stickylistheaders.StickyListHeadersListView; public class ListAwareSwipeRefreshLayout extends NoScrollableSwipeRefreshLayout { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index 59d05a62e..9c8e4aedb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -26,7 +26,6 @@ import android.support.v4.content.Loader; import android.util.AttributeSet; import android.widget.ImageView; -import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java deleted file mode 100644 index 17471c86c..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.ui.widget; - -import android.content.Context; -import android.graphics.Typeface; -import android.os.Build; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.HorizontalScrollView; -import android.widget.TextView; - -/** - * Copied from http://developer.android.com/samples/SlidingTabsColors/index.html - */ - -/** - * To be used with ViewPager to provide a tab indicator component which give constant feedback as to - * the user's scroll progress. - *

- * To use the component, simply add it to your view hierarchy. Then in your - * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call - * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for. - *

- * The colors can be customized in two ways. The first and simplest is to provide an array of colors - * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The - * alternative is via the {@link TabColorizer} interface which provides you complete control over - * which color is used for any individual position. - *

- * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, - * providing the layout ID of your custom layout. - */ -public class SlidingTabLayout extends HorizontalScrollView { - - /** - * Allows complete control over the colors drawn in the tab layout. Set with - * {@link #setCustomTabColorizer(TabColorizer)}. - */ - public interface TabColorizer { - - /** - * @return return the color of the indicator used when {@code position} is selected. - */ - int getIndicatorColor(int position); - - /** - * @return return the color of the divider drawn to the right of {@code position}. - */ - int getDividerColor(int position); - - } - - private static final int TITLE_OFFSET_DIPS = 24; - private static final int TAB_VIEW_PADDING_DIPS = 16; - private static final int TAB_VIEW_TEXT_SIZE_SP = 12; - - private int mTitleOffset; - - private int mTabViewLayoutId; - private int mTabViewTextViewId; - - private ViewPager mViewPager; - private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; - - private final SlidingTabStrip mTabStrip; - - public SlidingTabLayout(Context context) { - this(context, null); - } - - public SlidingTabLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - // Disable the Scroll Bar - setHorizontalScrollBarEnabled(false); - // Make sure that the Tab Strips fills this View - setFillViewport(true); - - mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); - - mTabStrip = new SlidingTabStrip(context); - addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - } - - /** - * Set the custom {@link TabColorizer} to be used. - *

- * If you only require simple custmisation then you can use - * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve - * similar effects. - */ - public void setCustomTabColorizer(TabColorizer tabColorizer) { - mTabStrip.setCustomTabColorizer(tabColorizer); - } - - /** - * Sets the colors to be used for indicating the selected tab. These colors are treated as a - * circular array. Providing one color will mean that all tabs are indicated with the same color. - */ - public void setSelectedIndicatorColors(int... colors) { - mTabStrip.setSelectedIndicatorColors(colors); - } - - /** - * Sets the colors to be used for tab dividers. These colors are treated as a circular array. - * Providing one color will mean that all tabs are indicated with the same color. - */ - public void setDividerColors(int... colors) { - mTabStrip.setDividerColors(colors); - } - - /** - * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are - * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so - * that the layout can update it's scroll position correctly. - * - * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) - */ - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { - mViewPagerPageChangeListener = listener; - } - - /** - * Set the custom layout to be inflated for the tab views. - * - * @param layoutResId Layout id to be inflated - * @param textViewId id of the {@link TextView} in the inflated view - */ - public void setCustomTabView(int layoutResId, int textViewId) { - mTabViewLayoutId = layoutResId; - mTabViewTextViewId = textViewId; - } - - /** - * Sets the associated view pager. Note that the assumption here is that the pager content - * (number of tabs and tab titles) does not change after this call has been made. - */ - public void setViewPager(ViewPager viewPager) { - mTabStrip.removeAllViews(); - - mViewPager = viewPager; - if (viewPager != null) { - viewPager.setOnPageChangeListener(new InternalViewPagerListener()); - populateTabStrip(); - } - } - - /** - * Create a default view to be used for tabs. This is called if a custom tab view is not set via - * {@link #setCustomTabView(int, int)}. - */ - protected TextView createDefaultTabView(Context context) { - TextView textView = new TextView(context); - textView.setGravity(Gravity.CENTER); - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); - textView.setTypeface(Typeface.DEFAULT_BOLD); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - // If we're running on Honeycomb or newer, then we can use the Theme's - // selectableItemBackground to ensure that the View has a pressed state - TypedValue outValue = new TypedValue(); - getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, - outValue, true); - textView.setBackgroundResource(outValue.resourceId); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style - textView.setAllCaps(true); - } - - int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density); - textView.setPadding(padding, padding, padding, padding); - - return textView; - } - - private void populateTabStrip() { - final PagerAdapter adapter = mViewPager.getAdapter(); - final View.OnClickListener tabClickListener = new TabClickListener(); - - for (int i = 0; i < adapter.getCount(); i++) { - View tabView = null; - TextView tabTitleView = null; - - if (mTabViewLayoutId != 0) { - // If there is a custom tab view layout id set, try and inflate it - tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip, - false); - tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); - } - - if (tabView == null) { - tabView = createDefaultTabView(getContext()); - } - - if (tabTitleView == null && TextView.class.isInstance(tabView)) { - tabTitleView = (TextView) tabView; - } - - tabTitleView.setText(adapter.getPageTitle(i)); - tabView.setOnClickListener(tabClickListener); - - mTabStrip.addView(tabView); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - if (mViewPager != null) { - scrollToTab(mViewPager.getCurrentItem(), 0); - } - } - - private void scrollToTab(int tabIndex, int positionOffset) { - final int tabStripChildCount = mTabStrip.getChildCount(); - if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { - return; - } - - View selectedChild = mTabStrip.getChildAt(tabIndex); - if (selectedChild != null) { - int targetScrollX = selectedChild.getLeft() + positionOffset; - - if (tabIndex > 0 || positionOffset > 0) { - // If we're not at the first child and are mid-scroll, make sure we obey the offset - targetScrollX -= mTitleOffset; - } - - scrollTo(targetScrollX, 0); - } - } - - private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { - private int mScrollState; - - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - int tabStripChildCount = mTabStrip.getChildCount(); - if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { - return; - } - - mTabStrip.onViewPagerPageChanged(position, positionOffset); - - View selectedTitle = mTabStrip.getChildAt(position); - int extraOffset = (selectedTitle != null) - ? (int) (positionOffset * selectedTitle.getWidth()) - : 0; - scrollToTab(position, extraOffset); - - if (mViewPagerPageChangeListener != null) { - mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, - positionOffsetPixels); - } - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - - if (mViewPagerPageChangeListener != null) { - mViewPagerPageChangeListener.onPageScrollStateChanged(state); - } - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mTabStrip.onViewPagerPageChanged(position, 0f); - scrollToTab(position, 0); - } - - if (mViewPagerPageChangeListener != null) { - mViewPagerPageChangeListener.onPageSelected(position); - } - } - - } - - private class TabClickListener implements View.OnClickListener { - @Override - public void onClick(View v) { - for (int i = 0; i < mTabStrip.getChildCount(); i++) { - if (v == mTabStrip.getChildAt(i)) { - mViewPager.setCurrentItem(i); - return; - } - } - } - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java deleted file mode 100644 index 4c41e12c5..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.ui.widget; - -import android.R; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.View; -import android.widget.LinearLayout; - -/** - * Copied from http://developer.android.com/samples/SlidingTabsColors/index.html - */ -class SlidingTabStrip extends LinearLayout { - - private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2; - private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; - private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8; - private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFFAA66CC; - - private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1; - private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20; - private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f; - - private final int mBottomBorderThickness; - private final Paint mBottomBorderPaint; - - private final int mSelectedIndicatorThickness; - private final Paint mSelectedIndicatorPaint; - - private final int mDefaultBottomBorderColor; - - private final Paint mDividerPaint; - private final float mDividerHeight; - - private int mSelectedPosition; - private float mSelectionOffset; - - private SlidingTabLayout.TabColorizer mCustomTabColorizer; - private final SimpleTabColorizer mDefaultTabColorizer; - - SlidingTabStrip(Context context) { - this(context, null); - } - - SlidingTabStrip(Context context, AttributeSet attrs) { - super(context, attrs); - setWillNotDraw(false); - - final float density = getResources().getDisplayMetrics().density; - - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true); - final int themeForegroundColor = outValue.data; - - mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, - DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); - - mDefaultTabColorizer = new SimpleTabColorizer(); - mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); - mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor, - DEFAULT_DIVIDER_COLOR_ALPHA)); - - mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); - mBottomBorderPaint = new Paint(); - mBottomBorderPaint.setColor(mDefaultBottomBorderColor); - - mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); - mSelectedIndicatorPaint = new Paint(); - - mDividerHeight = DEFAULT_DIVIDER_HEIGHT; - mDividerPaint = new Paint(); - mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density)); - } - - void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { - mCustomTabColorizer = customTabColorizer; - invalidate(); - } - - void setSelectedIndicatorColors(int... colors) { - // Make sure that the custom colorizer is removed - mCustomTabColorizer = null; - mDefaultTabColorizer.setIndicatorColors(colors); - invalidate(); - } - - void setDividerColors(int... colors) { - // Make sure that the custom colorizer is removed - mCustomTabColorizer = null; - mDefaultTabColorizer.setDividerColors(colors); - invalidate(); - } - - void onViewPagerPageChanged(int position, float positionOffset) { - mSelectedPosition = position; - mSelectionOffset = positionOffset; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - final int height = getHeight(); - final int childCount = getChildCount(); - final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height); - final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null - ? mCustomTabColorizer - : mDefaultTabColorizer; - - // Thick colored underline below the current selection - if (childCount > 0) { - View selectedTitle = getChildAt(mSelectedPosition); - int left = selectedTitle.getLeft(); - int right = selectedTitle.getRight(); - int color = tabColorizer.getIndicatorColor(mSelectedPosition); - - if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { - int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); - if (color != nextColor) { - color = blendColors(nextColor, color, mSelectionOffset); - } - - // Draw the selection partway between the tabs - View nextTitle = getChildAt(mSelectedPosition + 1); - left = (int) (mSelectionOffset * nextTitle.getLeft() + - (1.0f - mSelectionOffset) * left); - right = (int) (mSelectionOffset * nextTitle.getRight() + - (1.0f - mSelectionOffset) * right); - } - - mSelectedIndicatorPaint.setColor(color); - - canvas.drawRect(left, height - mSelectedIndicatorThickness, right, - height, mSelectedIndicatorPaint); - } - - // Thin underline along the entire bottom edge - canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); - - // Vertical separators between the titles - int separatorTop = (height - dividerHeightPx) / 2; - for (int i = 0; i < childCount - 1; i++) { - View child = getChildAt(i); - mDividerPaint.setColor(tabColorizer.getDividerColor(i)); - canvas.drawLine(child.getRight(), separatorTop, child.getRight(), - separatorTop + dividerHeightPx, mDividerPaint); - } - } - - /** - * Set the alpha value of the {@code color} to be the given {@code alpha} value. - */ - private static int setColorAlpha(int color, byte alpha) { - return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); - } - - /** - * Blend {@code color1} and {@code color2} using the given ratio. - * - * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, - * 0.0 will return {@code color2}. - */ - private static int blendColors(int color1, int color2, float ratio) { - final float inverseRation = 1f - ratio; - float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); - float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); - float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); - return Color.rgb((int) r, (int) g, (int) b); - } - - private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { - private int[] mIndicatorColors; - private int[] mDividerColors; - - @Override - public final int getIndicatorColor(int position) { - return mIndicatorColors[position % mIndicatorColors.length]; - } - - @Override - public final int getDividerColor(int position) { - return mDividerColors[position % mDividerColors.length]; - } - - void setIndicatorColors(int... colors) { - mIndicatorColors = colors; - } - - void setDividerColors(int... colors) { - mDividerColors = colors; - } - } -} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java index 99db634ac..c1955f75b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java @@ -23,7 +23,6 @@ import android.app.Activity; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import java.util.HashMap; @@ -32,9 +31,9 @@ import java.util.HashMap; public class AlgorithmNames { Activity mActivity; - HashMap mEncryptionNames = new HashMap(); - HashMap mHashNames = new HashMap(); - HashMap mCompressionNames = new HashMap(); + HashMap mEncryptionNames = new HashMap<>(); + HashMap mHashNames = new HashMap<>(); + HashMap mCompressionNames = new HashMap<>(); public AlgorithmNames(Activity context) { super(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index 1c4eece6b..11b29f521 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -35,6 +35,7 @@ import android.util.Patterns; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.provider.KeychainContract; @@ -57,10 +58,10 @@ public class ContactHelper { KeychainContract.KeyRings.EXPIRY, KeychainContract.KeyRings.IS_REVOKED}; public static final String[] USER_IDS_PROJECTION = new String[]{ - KeychainContract.UserIds.USER_ID + UserPackets.USER_ID }; - public static final String NON_REVOKED_SELECTION = KeychainContract.UserIds.IS_REVOKED + "=0"; + public static final String NON_REVOKED_SELECTION = UserPackets.IS_REVOKED + "=0"; public static final String[] ID_PROJECTION = new String[]{ContactsContract.RawContacts._ID}; public static final String[] SOURCE_ID_PROJECTION = new String[]{ContactsContract.RawContacts.SOURCE_ID}; @@ -72,20 +73,20 @@ public class ContactHelper { ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?"; - private static final Map photoCache = new HashMap(); + private static final Map photoCache = new HashMap<>(); public static List getPossibleUserEmails(Context context) { Set accountMails = getAccountEmails(context); accountMails.addAll(getMainProfileContactEmails(context)); // now return the Set (without duplicates) as a List - return new ArrayList(accountMails); + return new ArrayList<>(accountMails); } public static List getPossibleUserNames(Context context) { Set accountMails = getAccountEmails(context); Set names = getContactNamesFromEmails(context, accountMails); names.addAll(getMainProfileContactName(context)); - return new ArrayList(names); + return new ArrayList<>(names); } /** @@ -96,7 +97,7 @@ public class ContactHelper { */ private static Set getAccountEmails(Context context) { final Account[] accounts = AccountManager.get(context).getAccounts(); - final Set emailSet = new HashSet(); + final Set emailSet = new HashSet<>(); for (Account account : accounts) { if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { emailSet.add(account.name); @@ -115,7 +116,7 @@ public class ContactHelper { */ private static Set getContactNamesFromEmails(Context context, Set emails) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - Set names = new HashSet(); + Set names = new HashSet<>(); for (String email : emails) { ContentResolver resolver = context.getContentResolver(); Cursor profileCursor = resolver.query( @@ -127,7 +128,7 @@ public class ContactHelper { ); if (profileCursor == null) return null; - Set currNames = new HashSet(); + Set currNames = new HashSet<>(); while (profileCursor.moveToNext()) { String name = profileCursor.getString(1); if (name != null) { @@ -139,7 +140,7 @@ public class ContactHelper { } return names; } else { - return new HashSet(); + return new HashSet<>(); } } @@ -171,7 +172,7 @@ public class ContactHelper { ); if (profileCursor == null) return null; - Set emails = new HashSet(); + Set emails = new HashSet<>(); while (profileCursor.moveToNext()) { String email = profileCursor.getString(0); if (email != null) { @@ -181,7 +182,7 @@ public class ContactHelper { profileCursor.close(); return emails; } else { - return new HashSet(); + return new HashSet<>(); } } @@ -200,7 +201,7 @@ public class ContactHelper { null, null, null); if (profileCursor == null) return null; - Set names = new HashSet(); + Set names = new HashSet<>(); // should only contain one entry! while (profileCursor.moveToNext()) { String name = profileCursor.getString(0); @@ -209,9 +210,9 @@ public class ContactHelper { } } profileCursor.close(); - return new ArrayList(names); + return new ArrayList<>(names); } else { - return new ArrayList(); + return new ArrayList<>(); } } @@ -220,9 +221,9 @@ public class ContactHelper { Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Email.DATA}, null, null, null); - if (mailCursor == null) return new ArrayList(); + if (mailCursor == null) return new ArrayList<>(); - Set mails = new HashSet(); + Set mails = new HashSet<>(); while (mailCursor.moveToNext()) { String email = mailCursor.getString(0); if (email != null) { @@ -230,7 +231,7 @@ public class ContactHelper { } } mailCursor.close(); - return new ArrayList(mails); + return new ArrayList<>(mails); } public static List getContactNames(Context context) { @@ -238,9 +239,9 @@ public class ContactHelper { Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Contacts.DISPLAY_NAME}, null, null, null); - if (cursor == null) return new ArrayList(); + if (cursor == null) return new ArrayList<>(); - Set names = new HashSet(); + Set names = new HashSet<>(); while (cursor.moveToNext()) { String name = cursor.getString(0); if (name != null) { @@ -248,7 +249,7 @@ public class ContactHelper { } } cursor.close(); - return new ArrayList(names); + return new ArrayList<>(names); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @@ -308,7 +309,7 @@ public class ContactHelper { boolean isExpired = !cursor.isNull(4) && new Date(cursor.getLong(4) * 1000).before(new Date()); boolean isRevoked = cursor.getInt(5) > 0; int rawContactId = findRawContactId(resolver, fingerprint); - ArrayList ops = new ArrayList(); + ArrayList ops = new ArrayList<>(); // Do not store expired or revoked keys in contact db - and remove them if they already exist if (isExpired || isRevoked) { @@ -350,7 +351,7 @@ public class ContactHelper { * @return a set of all key fingerprints currently present in the contact db */ private static Set getRawContactFingerprints(ContentResolver resolver) { - HashSet result = new HashSet(); + HashSet result = new HashSet<>(); Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION, ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null); if (fingerprints != null) { @@ -413,7 +414,7 @@ public class ContactHelper { int rawContactId, long masterKeyId) { ops.add(selectByRawContactAndItemType(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI), rawContactId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE).build()); - Cursor ids = resolver.query(KeychainContract.UserIds.buildUserIdsUri(masterKeyId), + Cursor ids = resolver.query(UserPackets.buildUserIdsUri(masterKeyId), USER_IDS_PROJECTION, NON_REVOKED_SELECTION, null, null); if (ids != null) { while (ids.moveToNext()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java index 49d4d8bf8..8334b37ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java @@ -42,13 +42,13 @@ public class EmailKeyHelper { public static void importAll(Context context, Messenger messenger, List mails) { // Collect all candidates as ImportKeysListEntry (set for deduplication) - Set entries = new HashSet(); + Set entries = new HashSet<>(); for (String mail : mails) { entries.addAll(getEmailKeys(context, mail)); } // Put them in a list and import - ArrayList keys = new ArrayList(entries.size()); + ArrayList keys = new ArrayList<>(entries.size()); for (ImportKeysListEntry entry : entries) { keys.add(new ParcelableKeyRing(entry.getFingerprintHex(), entry.getKeyIdHex(), null)); } @@ -56,7 +56,7 @@ public class EmailKeyHelper { } public static Set getEmailKeys(Context context, String mail) { - Set keys = new HashSet(); + Set keys = new HashSet<>(); // Try _hkp._tcp SRV record first String[] mailparts = mail.split("@"); @@ -90,7 +90,7 @@ public class EmailKeyHelper { } public static List getEmailKeys(String mail, Keyserver keyServer) { - Set keys = new HashSet(); + Set keys = new HashSet<>(); try { for (ImportKeysListEntry key : keyServer.search(mail)) { if (key.isRevoked() || key.isExpired()) continue; @@ -103,6 +103,6 @@ public class EmailKeyHelper { } catch (Keyserver.QueryFailedException ignored) { } catch (Keyserver.QueryNeedsRepairException ignored) { } - return new ArrayList(keys); + return new ArrayList<>(keys); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java index 7492d95b2..fee9ff487 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java @@ -25,12 +25,10 @@ import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.support.v7.app.ActionBarActivity; -import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.ExportResult; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java index 90afd3bc0..c0483ad04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java @@ -125,7 +125,7 @@ public class Iso7816TLV { public static Iso7816TLV[] readList(byte[] data, boolean recursive) throws IOException { ByteBuffer buf = ByteBuffer.wrap(data); - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); // read while data is available. this will fail if there is trailing data! while (buf.hasRemaining()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java index 76ec9f75f..943b913d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java @@ -17,21 +17,6 @@ package org.sufficientlysecure.keychain.util; -import android.content.Context; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Messenger; - -import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; - -import java.util.ArrayList; -import java.util.List; - public class KeyUpdateHelper { /* diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java index b4f7c5767..8b165cd57 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java @@ -21,9 +21,6 @@ import android.os.Bundle; import org.sufficientlysecure.keychain.Constants; -import java.io.IOException; -import java.io.StreamTokenizer; -import java.io.StringReader; import java.util.Iterator; import java.util.Set; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java index 3081021cf..5de682fe6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java @@ -32,9 +32,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; /** * When sending large data (over 1MB) through Androids Binder IPC you get diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index 65f4af880..8d4af58d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -182,7 +182,7 @@ public class Preferences { } public boolean useNumKeypadForYubikeyPin() { - return mSharedPreferences.getBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, false); + return mSharedPreferences.getBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, true); } public void setUseNumKeypadForYubikeyPin(boolean useNumKeypadForYubikeyPin) { @@ -200,7 +200,7 @@ public class Preferences { public String[] getKeyServers() { String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS, Constants.Defaults.KEY_SERVERS); - Vector servers = new Vector(); + Vector servers = new Vector<>(); String chunks[] = rawData.split(","); for (String c : chunks) { String tmp = c.trim(); @@ -281,7 +281,7 @@ public class Preferences { case 3: { // migrate keyserver to hkps String[] serversArray = getKeyServers(); - ArrayList servers = new ArrayList(Arrays.asList(serversArray)); + ArrayList servers = new ArrayList<>(Arrays.asList(serversArray)); ListIterator it = servers.listIterator(); while (it.hasNext()) { String server = it.next(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java index 51e58565f..120b84a3b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java @@ -43,16 +43,18 @@ public class ShareHelper { * Put together from some stackoverflow posts... */ public Intent createChooserExcluding(Intent prototype, String title, String[] activityBlacklist) { - // Produced an empty list on Huawei U8860 with Android Version 4.0.3 and weird results on 2.3 + // Produced an empty list on Huawei U8860 with Android Version 4.0.3 // TODO: test on 4.1, 4.2, 4.3, only tested on 4.4 - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + // Disabled on 5.0 because using EXTRA_INITIAL_INTENTS prevents the usage based sorting + // introduced in 5.0: https://medium.com/@xXxXxXxXxXam/how-lollipops-share-menu-is-organized-d204888f606d + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return Intent.createChooser(prototype, title); } - List targetedShareIntents = new ArrayList(); + List targetedShareIntents = new ArrayList<>(); List resInfoList = mContext.getPackageManager().queryIntentActivities(prototype, 0); - List resInfoListFiltered = new ArrayList(); + List resInfoListFiltered = new ArrayList<>(); if (!resInfoList.isEmpty()) { for (ResolveInfo resolveInfo : resInfoList) { // do not add blacklisted ones diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java index 9946d81aa..7e318281d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java @@ -50,7 +50,7 @@ public class TlsHelper { } } - private static Map sStaticCA = new HashMap(); + private static Map sStaticCA = new HashMap<>(); public static void addStaticCA(String domain, byte[] certificate) { sStaticCA.put(domain, certificate); @@ -120,13 +120,7 @@ public class TlsHelper { urlConnection.setSSLSocketFactory(context.getSocketFactory()); return urlConnection; - } catch (CertificateException e) { - throw new TlsHelperException(e); - } catch (NoSuchAlgorithmException e) { - throw new TlsHelperException(e); - } catch (KeyStoreException e) { - throw new TlsHelperException(e); - } catch (KeyManagementException e) { + } catch (CertificateException | KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) { throw new TlsHelperException(e); } } diff --git a/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_default_holo.png deleted file mode 100644 index 0ddafab03..000000000 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_default_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_pressed_holo.png deleted file mode 100644 index c062b17f8..000000000 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/apptheme_fastscroll_thumb_pressed_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png deleted file mode 100644 index e9d2dcb46..000000000 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png deleted file mode 100644 index 29f4de211..000000000 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png new file mode 100644 index 000000000..37931a0ad Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png new file mode 100644 index 000000000..5fa494878 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png new file mode 100644 index 000000000..f42a0e2d2 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png new file mode 100644 index 000000000..0fd15563a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png new file mode 100644 index 000000000..35e3b426f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png new file mode 100644 index 000000000..ed993f35d Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png index 6b2be4bc3..6133816d2 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png and b/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png new file mode 100644 index 000000000..8ac075245 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png new file mode 100644 index 000000000..fc019db72 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png new file mode 100644 index 000000000..cd16fdd50 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_search_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_search_white_24dp.png new file mode 100644 index 000000000..a2fc5b2e7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_search_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png new file mode 100644 index 000000000..b16209fc1 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png new file mode 100644 index 000000000..c900b8ec7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png index f74fcdd8d..964832508 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_focused_holo_light.png index 58a99014e..6f221e7cb 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png index 1d06ee46f..cd3de280a 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_focused_holo_light.png index 0f9718950..e271afeff 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_holo_light.png index 8db606b56..0d06ce453 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_check_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png index 8ee0aa89c..d1e8f795f 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_focused_holo_light.9.png index e6ce2835c..5b295174b 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_default_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png index 0dc2a75ab..0d079e5fe 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_focused_holo_light.png index 0c22251f3..7ef86d832 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_holo_light.png index 932257123..5021bb434 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_off_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png index 82eb795b8..e1e75b295 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_focused_holo_light.png index fbee3366d..c627a6247 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_holo_light.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_holo_light.png index eda8002eb..0a45b94a4 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_radio_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..49343edc3 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png new file mode 100644 index 000000000..a7e6bc3c5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png new file mode 100644 index 000000000..c31f805bd Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png new file mode 100644 index 000000000..aba55810b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png new file mode 100644 index 000000000..9f68344ab Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..0cb6fcfef Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png new file mode 100644 index 000000000..aed04dd6c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png new file mode 100644 index 000000000..43329514c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png new file mode 100644 index 000000000..1d7474560 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png new file mode 100644 index 000000000..a0d649d24 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_default_holo.png new file mode 100644 index 000000000..5ea146b28 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_default_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_pressed_holo.png new file mode 100644 index 000000000..25ad77295 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_fastscroll_thumb_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_activated_holo.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_activated_holo.9.png index e98c2a4d2..63c53a343 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_activated_holo.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_activated_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_focused_holo.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_focused_holo.9.png index 84d9006eb..59d605fba 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_focused_holo.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_list_focused_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_primary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_primary_holo_light.9.png index c14605dab..e3ce6fd56 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_primary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_primary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_secondary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_secondary_holo_light.9.png index 60aefe181..ade0f6d82 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_secondary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progress_secondary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo1.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo1.png index b9977dedb..3889a0e92 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo1.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo1.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo2.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo2.png index 88601174a..d4ca8797f 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo2.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo2.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo3.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo3.png index 6cd634a91..099ba55de 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo3.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo3.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo4.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo4.png index 9456cf4e1..99c38df70 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo4.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo4.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo5.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo5.png index fc6c57e16..cd380c371 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo5.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo5.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo6.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo6.png index 3c2e03356..ddba06e81 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo6.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo6.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo7.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo7.png index 2618d0e50..cef58060d 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo7.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo7.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo8.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo8.png index 56745c26b..74b6d01ae 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo8.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_progressbar_indeterminate_holo8.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_disabled_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_disabled_holo.png new file mode 100644 index 000000000..1a9ced650 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_disabled_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_focused_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_focused_holo.png new file mode 100644 index 000000000..b873aeb30 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_focused_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_normal_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_normal_holo.png new file mode 100644 index 000000000..6451fe6e4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_normal_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_pressed_holo.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_pressed_holo.png new file mode 100644 index 000000000..480786ac4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_control_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_primary_holo.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_primary_holo.9.png new file mode 100644 index 000000000..6bc032e27 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_primary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_secondary_holo.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_secondary_holo.9.png new file mode 100644 index 000000000..880456b02 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_secondary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_track_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_track_holo_light.9.png new file mode 100644 index 000000000..90528b130 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_scrubber_track_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_default_holo_light.9.png index a02ebb450..a5fd6ca04 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_focused_holo_light.9.png index 12c3cd5af..ae4ba5fc1 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_spinner_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_left.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_left.png new file mode 100644 index 000000000..5f262c9d4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_left.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_middle.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_middle.png new file mode 100644 index 000000000..e4f292ff6 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_middle.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_right.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_right.png new file mode 100644 index 000000000..5f5e7f173 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_text_select_handle_right.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_activated_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_activated_holo_light.9.png index 70691cddc..9f400ba30 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_activated_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_activated_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_default_holo_light.9.png index d5ac69c23..5fa1d0315 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_focused_holo_light.9.png index 257eba9a0..96109c07b 100644 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-hdpi/keychaintheme_textfield_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-ldpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-ldpi/ic_launcher.png deleted file mode 100644 index c2b688424..000000000 Binary files a/OpenKeychain/src/main/res/drawable-ldpi/ic_launcher.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_bad.png b/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_bad.png deleted file mode 100644 index 45467992f..000000000 Binary files a/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_bad.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_ok.png b/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_ok.png deleted file mode 100644 index c400a1820..000000000 Binary files a/OpenKeychain/src/main/res/drawable-ldpi/uid_mail_ok.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_default_holo.png deleted file mode 100644 index ebffb16a0..000000000 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_default_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_pressed_holo.png deleted file mode 100644 index b6739b564..000000000 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/apptheme_fastscroll_thumb_pressed_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png deleted file mode 100644 index 4ac28f270..000000000 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png deleted file mode 100644 index bb46bb315..000000000 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png new file mode 100644 index 000000000..5b1fd7766 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png new file mode 100644 index 000000000..9e662f6d4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png new file mode 100644 index 000000000..e91f9048b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png new file mode 100644 index 000000000..e80681aeb Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png new file mode 100644 index 000000000..a5ab2c5d3 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png new file mode 100644 index 000000000..73fc3b422 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png index 6bb29efde..d945a01de 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png and b/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png new file mode 100644 index 000000000..9e6d0f0ac Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png new file mode 100644 index 000000000..1df91994c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png new file mode 100644 index 000000000..235c84f1e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_search_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_search_white_24dp.png new file mode 100644 index 000000000..dff1e3a8a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_search_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png new file mode 100644 index 000000000..3405c951d Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png new file mode 100644 index 000000000..5e8781731 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png index d7be4f996..10a3e55fa 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_focused_holo_light.png index 2c5949eb9..bd65c9fd5 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png index d5e0ef543..3d5364179 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_focused_holo_light.png index d12f33b7d..cae17c8da 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_holo_light.png index 517ea4302..d0ade76a2 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_check_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png index c6a653217..6cf3e64d9 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_focused_holo_light.9.png index dca8db91f..0edd1628a 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_normal_holo_light.9.png index 502f762af..bbe7baafc 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_normal_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_default_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png index ef648d9df..e61c664c5 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_focused_holo_light.png index aefa6e2c7..325125494 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_holo_light.png index 590c37c6c..0d81a6ad4 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_off_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png index fa981c2f4..72f7f3717 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_focused_holo_light.png index b7421f31a..0599c3d62 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_holo_light.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_holo_light.png index 0f3beeea6..247f8c19d 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_radio_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..bf6992195 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png new file mode 100644 index 000000000..3a35a4e3e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png new file mode 100644 index 000000000..0516d15e5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png new file mode 100644 index 000000000..37f70c55d Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png new file mode 100644 index 000000000..98a9f10ac Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..f54b70ffd Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png new file mode 100644 index 000000000..603cb3f30 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png new file mode 100644 index 000000000..e9c001eed Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png new file mode 100644 index 000000000..36b6534b5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png new file mode 100644 index 000000000..54f56e187 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_default_holo.png new file mode 100644 index 000000000..00c08d808 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_default_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_pressed_holo.png new file mode 100644 index 000000000..2532f32dc Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_fastscroll_thumb_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_activated_holo.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_activated_holo.9.png index aa1130332..b6862ea33 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_activated_holo.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_activated_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_focused_holo.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_focused_holo.9.png index 8d1b4af83..cd4d77dc2 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_focused_holo.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_list_focused_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_primary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_primary_holo_light.9.png index fdb236d7c..c1ec11fb9 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_primary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_primary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_secondary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_secondary_holo_light.9.png index 64b72e8ee..14b87c197 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_secondary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progress_secondary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo1.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo1.png index 0cff52503..3331b051d 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo1.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo1.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo2.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo2.png index 3a290e871..c0540bb6d 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo2.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo2.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo3.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo3.png index d6b4a1326..fb502a712 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo3.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo3.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo4.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo4.png index 98061c845..184a0aceb 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo4.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo4.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo5.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo5.png index cf130fdf2..39115cb49 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo5.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo5.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo6.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo6.png index 72d43ea01..c70815d42 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo6.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo6.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo7.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo7.png index 6a7307dcf..48f0571fe 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo7.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo7.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo8.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo8.png index 0d3cb5fe7..242297424 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo8.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_progressbar_indeterminate_holo8.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_disabled_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_disabled_holo.png new file mode 100644 index 000000000..97a637c1b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_disabled_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_focused_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_focused_holo.png new file mode 100644 index 000000000..60874b80c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_focused_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_normal_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_normal_holo.png new file mode 100644 index 000000000..5020b7947 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_normal_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_pressed_holo.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_pressed_holo.png new file mode 100644 index 000000000..e2beb812a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_control_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_primary_holo.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_primary_holo.9.png new file mode 100644 index 000000000..55b07371f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_primary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_secondary_holo.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_secondary_holo.9.png new file mode 100644 index 000000000..9bfdf2318 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_secondary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_track_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_track_holo_light.9.png new file mode 100644 index 000000000..359ae4a1b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_scrubber_track_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_default_holo_light.9.png index 574ea43ba..5303d6ef4 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_focused_holo_light.9.png index 33c452dcd..add105bbb 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_spinner_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_left.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_left.png new file mode 100644 index 000000000..5cb13d1ac Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_left.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_middle.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_middle.png new file mode 100644 index 000000000..6a7607826 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_middle.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_right.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_right.png new file mode 100644 index 000000000..c354870e4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_text_select_handle_right.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_activated_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_activated_holo_light.9.png index 4569d71a9..5358a857a 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_activated_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_activated_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_default_holo_light.9.png index 47302c93e..15efce9bb 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_focused_holo_light.9.png index 39ca1ffda..96a1ac5a2 100644 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-mdpi/keychaintheme_textfield_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_default_holo.png deleted file mode 100644 index 7c5e21eeb..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_default_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_pressed_holo.png deleted file mode 100644 index 86814b45d..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/apptheme_fastscroll_thumb_pressed_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png deleted file mode 100644 index 60ac6b066..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png deleted file mode 100644 index 76937f57a..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png new file mode 100644 index 000000000..c8187799b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png new file mode 100644 index 000000000..addbfc886 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png new file mode 100644 index 000000000..e5024472a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png new file mode 100644 index 000000000..76e07f097 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png new file mode 100644 index 000000000..47c7b52a1 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png new file mode 100644 index 000000000..45d30d999 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png index 6188bbed9..825b18b38 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png new file mode 100644 index 000000000..9cd050100 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png new file mode 100644 index 000000000..ae48a3bf7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png new file mode 100644 index 000000000..5f89fc257 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_search_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_search_white_24dp.png new file mode 100644 index 000000000..043759acd Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_search_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png new file mode 100644 index 000000000..2b775b646 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png new file mode 100644 index 000000000..ccbdce4ab Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png index 0b0606462..8c444bb97 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_focused_holo_light.png index 65d850957..f0e76edea 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png index 80ad53ff0..74347750d 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_focused_holo_light.png index b72dea7f8..eb8004be8 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_holo_light.png index f24991826..00fe90604 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_check_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png index 5c122118e..73106561c 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_focused_holo_light.9.png index e738f8218..0611a95e6 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_normal_holo_light.9.png index 8bb32617b..908d601f7 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_normal_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_default_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png index 83af2dcc3..edcca62f9 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_focused_holo_light.png index b02c9b6d1..697ca2ca7 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_holo_light.png index 2360f30be..08b65d235 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_off_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png index 1a2ed89db..28a808de5 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_focused_holo_light.png index 306e47e71..8454a0e2a 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_holo_light.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_holo_light.png index d22876cb2..330b85e4f 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_radio_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..bc74c108c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png new file mode 100644 index 000000000..61230cbdc Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png new file mode 100644 index 000000000..2abf70dcf Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png new file mode 100644 index 000000000..54e5e8eb7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png new file mode 100644 index 000000000..a096c03ca Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..fd43d3779 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png new file mode 100644 index 000000000..a1a66fbb0 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png new file mode 100644 index 000000000..0bd49f267 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png new file mode 100644 index 000000000..7d1ba0c4a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png new file mode 100644 index 000000000..7490663c6 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_default_holo.png new file mode 100644 index 000000000..da5a4cdb5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_default_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png new file mode 100644 index 000000000..bea07662b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_activated_holo.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_activated_holo.9.png index 6a24d21e7..053686014 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_activated_holo.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_activated_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_focused_holo.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_focused_holo.9.png index 430387245..75c9e3340 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_focused_holo.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_list_focused_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_primary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_primary_holo_light.9.png index 9e08305f5..582d3a05e 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_primary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_primary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_secondary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_secondary_holo_light.9.png index 95c75a6db..c5e146368 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_secondary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progress_secondary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo1.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo1.png index 06f79cba3..f5ce0144a 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo1.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo1.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo2.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo2.png index f7bae4cef..0289af47c 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo2.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo2.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo3.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo3.png index fc5808cbf..60fc76e51 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo3.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo3.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo4.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo4.png index ef108bdf4..ffffb0478 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo4.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo4.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo5.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo5.png index f826eee36..9d4354800 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo5.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo5.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo6.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo6.png index dfd468fe9..b9bd4c6ec 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo6.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo6.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo7.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo7.png index 6a223873c..b33d3eec2 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo7.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo7.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo8.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo8.png index 27a2832af..1df288012 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo8.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_progressbar_indeterminate_holo8.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_disabled_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_disabled_holo.png new file mode 100644 index 000000000..c3389745f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_disabled_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_focused_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_focused_holo.png new file mode 100644 index 000000000..971f70f9f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_focused_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_normal_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_normal_holo.png new file mode 100644 index 000000000..e97197c5a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_normal_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_pressed_holo.png new file mode 100644 index 000000000..afa8bcdc2 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_control_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_primary_holo.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_primary_holo.9.png new file mode 100644 index 000000000..2f81fdcac Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_primary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_secondary_holo.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_secondary_holo.9.png new file mode 100644 index 000000000..51d99830f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_secondary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_track_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_track_holo_light.9.png new file mode 100644 index 000000000..a7d396de2 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_scrubber_track_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_default_holo_light.9.png index 10458c01a..8c469f65d 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_focused_holo_light.9.png index e4d7abf4d..4de02f1ff 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_spinner_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_left.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_left.png new file mode 100644 index 000000000..1d7ea81b1 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_left.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_middle.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_middle.png new file mode 100644 index 000000000..e66240fe2 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_middle.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_right.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_right.png new file mode 100644 index 000000000..92ae3058b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_text_select_handle_right.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_activated_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_activated_holo_light.9.png index dc19219cf..d133f4614 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_activated_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_activated_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_focused_holo_light.9.png index b84a6fed1..88fe46270 100644 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xhdpi/keychaintheme_textfield_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_default_holo.png deleted file mode 100644 index 5e4818bfc..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_default_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_pressed_holo.png deleted file mode 100644 index 7dd89e1f4..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/apptheme_fastscroll_thumb_pressed_holo.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png deleted file mode 100644 index 76ec594dc..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png deleted file mode 100644 index 22003198b..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png new file mode 100644 index 000000000..626543b47 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png new file mode 100644 index 000000000..4057cc545 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png new file mode 100644 index 000000000..6e03d54cf Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png new file mode 100644 index 000000000..0eb9d8b08 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png new file mode 100644 index 000000000..0470e3f02 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png new file mode 100644 index 000000000..aadd04af6 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png index 765738881..4809acc39 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png new file mode 100644 index 000000000..529a7724b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png new file mode 100644 index 000000000..cf149aa37 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png new file mode 100644 index 000000000..72128fe69 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png new file mode 100644 index 000000000..0bbeab150 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png new file mode 100644 index 000000000..47f0e0d82 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png new file mode 100644 index 000000000..736bde37a Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png index c0fdc45b0..645a7bf93 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_focused_holo_light.png index 911bad8a3..bcadf4553 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_holo_light.png index 310ab257c..441cd8660 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_off_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png index 456471129..ed742229d 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_focused_holo_light.png index e67994690..6ac275165 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_holo_light.png index 0c5038fc0..c40b01964 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_check_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png index e90491aee..2268fd1cd 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_focused_holo_light.9.png index a0ba2a3a2..9cfe77d71 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_normal_holo_light.9.png index 24daa6b8a..ee4d44903 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_normal_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_default_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png index 78ab31858..1575dcdaf 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_focused_holo_light.png index 2af5bf37b..2438d4e96 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_holo_light.png index 7d6fa76cd..6112308fa 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_off_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png index 01e04d15e..90163e927 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_disabled_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_focused_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_focused_holo_light.png index 90c4cac28..f9ade3353 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_focused_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_focused_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_holo_light.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_holo_light.png index 7860fc848..df1188084 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_holo_light.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_radio_on_holo_light.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..0e343f7be Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png new file mode 100644 index 000000000..9b3900a77 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png new file mode 100644 index 000000000..e4742d90e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png new file mode 100644 index 000000000..d3ef0e1a6 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png new file mode 100644 index 000000000..c9edf5c87 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_off_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png new file mode 100644 index 000000000..71a96f167 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png new file mode 100644 index 000000000..f0d3a6c97 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_disabled_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png new file mode 100644 index 000000000..90423ce4e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png new file mode 100644 index 000000000..4c95cf030 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_normal_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png new file mode 100644 index 000000000..f907579a0 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_btn_toggle_on_pressed_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_default_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_default_holo.png new file mode 100644 index 000000000..bb03584f3 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_default_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png new file mode 100644 index 000000000..6167f00a5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_fastscroll_thumb_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_activated_holo.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_activated_holo.9.png index b3b0da723..b6b64d316 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_activated_holo.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_activated_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_focused_holo.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_focused_holo.9.png index 0458c7f37..443ba5db5 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_focused_holo.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_list_focused_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_primary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_primary_holo_light.9.png index f89b6477b..16a92d086 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_primary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_primary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_secondary_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_secondary_holo_light.9.png index 30a079d6e..f9622cb95 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_secondary_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progress_secondary_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo1.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo1.png index ca952535f..a7cd41efa 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo1.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo1.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo2.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo2.png index 88804968f..ee8b812aa 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo2.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo2.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo3.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo3.png index 580a9cf9c..9ef2f180b 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo3.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo3.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo4.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo4.png index 8ce77b135..46dddfa8d 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo4.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo4.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo5.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo5.png index 9c17f17a2..808d452ce 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo5.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo5.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo6.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo6.png index 2cab8426e..49858655c 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo6.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo6.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo7.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo7.png index 18d252948..c9ad3229b 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo7.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo7.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo8.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo8.png index d0632ca2d..158279fbd 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo8.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_progressbar_indeterminate_holo8.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_disabled_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_disabled_holo.png new file mode 100644 index 000000000..6c4fe4e8e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_disabled_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_focused_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_focused_holo.png new file mode 100644 index 000000000..37055e319 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_focused_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_normal_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_normal_holo.png new file mode 100644 index 000000000..f6eeaa9e5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_normal_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_pressed_holo.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_pressed_holo.png new file mode 100644 index 000000000..43eca997b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_control_pressed_holo.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_primary_holo.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_primary_holo.9.png new file mode 100644 index 000000000..cac367df7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_primary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_secondary_holo.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_secondary_holo.9.png new file mode 100644 index 000000000..a9cef40e2 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_secondary_holo.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_track_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_track_holo_light.9.png new file mode 100644 index 000000000..1a6f577fc Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_scrubber_track_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_default_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_default_holo_light.9.png index f9facd05d..dfcd63db7 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_default_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_default_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_focused_holo_light.9.png index f7a9f7c55..e3e6c8c0f 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_spinner_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_left.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_left.png new file mode 100644 index 000000000..f55d53bb5 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_left.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_middle.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_middle.png new file mode 100644 index 000000000..212d020b0 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_middle.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_right.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_right.png new file mode 100644 index 000000000..cdffc3863 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_text_select_handle_right.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_activated_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_activated_holo_light.9.png index 733255647..f445e8b33 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_activated_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_activated_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_focused_holo_light.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_focused_holo_light.9.png index 01af8180e..e019443f9 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_focused_holo_light.9.png and b/OpenKeychain/src/main/res/drawable-xxhdpi/keychaintheme_textfield_focused_holo_light.9.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png new file mode 100644 index 000000000..d12d2e796 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png new file mode 100644 index 000000000..02f2f6fe8 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png new file mode 100644 index 000000000..87892840e Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png new file mode 100644 index 000000000..7b2a480a0 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png new file mode 100644 index 000000000..08ae54533 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png new file mode 100644 index 000000000..228b2a982 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png index d85507fef..fab324e93 100644 Binary files a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png new file mode 100644 index 000000000..a0fe0156f Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png new file mode 100644 index 000000000..7460e0894 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png new file mode 100644 index 000000000..d271d8e03 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png new file mode 100644 index 000000000..70c21baf7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png new file mode 100644 index 000000000..bce161d00 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png new file mode 100644 index 000000000..3451d9855 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable/keychaintheme_btn_toggle_holo_light.xml b/OpenKeychain/src/main/res/drawable/keychaintheme_btn_toggle_holo_light.xml new file mode 100644 index 000000000..733728e79 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/keychaintheme_btn_toggle_holo_light.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/drawable/apptheme_fastscroll_thumb_holo.xml b/OpenKeychain/src/main/res/drawable/keychaintheme_fastscroll_thumb_holo.xml similarity index 85% rename from OpenKeychain/src/main/res/drawable/apptheme_fastscroll_thumb_holo.xml rename to OpenKeychain/src/main/res/drawable/keychaintheme_fastscroll_thumb_holo.xml index e7121f083..51b376345 100644 --- a/OpenKeychain/src/main/res/drawable/apptheme_fastscroll_thumb_holo.xml +++ b/OpenKeychain/src/main/res/drawable/keychaintheme_fastscroll_thumb_holo.xml @@ -15,6 +15,6 @@ --> - - + + diff --git a/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_control_selector_holo_light.xml b/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_control_selector_holo_light.xml new file mode 100644 index 000000000..a3b3530ac --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_control_selector_holo_light.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_progress_horizontal_holo_light.xml b/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_progress_horizontal_holo_light.xml new file mode 100644 index 000000000..4ecf8a6c1 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable/keychaintheme_scrubber_progress_horizontal_holo_light.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/drawable/mat2.jpg b/OpenKeychain/src/main/res/drawable/mat2.jpg new file mode 100644 index 000000000..e35902ec7 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable/mat2.jpg differ diff --git a/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml b/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml deleted file mode 100644 index 7e4410f85..000000000 --- a/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml b/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml deleted file mode 100644 index b219038b2..000000000 --- a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml b/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml deleted file mode 100644 index e9047e759..000000000 --- a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_account_settings_activity.xml b/OpenKeychain/src/main/res/layout/api_account_settings_activity.xml index b2a9c11f5..763504f54 100644 --- a/OpenKeychain/src/main/res/layout/api_account_settings_activity.xml +++ b/OpenKeychain/src/main/res/layout/api_account_settings_activity.xml @@ -1,28 +1,37 @@ - - + - - + + + android:layout_height="match_parent"> - + android:layout_height="wrap_content" + android:padding="16dp" + android:orientation="vertical"> - - - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml b/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml index dae9de1f2..800e2eb87 100644 --- a/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml +++ b/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml @@ -1,41 +1,51 @@ - - + - - + + + android:layout_height="match_parent"> - + android:padding="16dp" + android:orientation="vertical"> - + - + - - - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_apps_list_content.xml b/OpenKeychain/src/main/res/layout/api_apps_list_content.xml index 9f9b99045..e1922079c 100644 --- a/OpenKeychain/src/main/res/layout/api_apps_list_content.xml +++ b/OpenKeychain/src/main/res/layout/api_apps_list_content.xml @@ -1,14 +1,24 @@ - + + + + - - \ No newline at end of file + android:layout_height="match_parent" /> + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_remote_create_account.xml b/OpenKeychain/src/main/res/layout/api_remote_create_account.xml index a6a39b1ad..7ae0a0e1e 100644 --- a/OpenKeychain/src/main/res/layout/api_remote_create_account.xml +++ b/OpenKeychain/src/main/res/layout/api_remote_create_account.xml @@ -1,37 +1,48 @@ - + android:layout_height="match_parent"> - + - + android:layout_height="match_parent" + android:orientation="vertical"> - + + + android:layout_height="wrap_content"> - - - + android:padding="16dp" + android:orientation="vertical"> - - - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_remote_error_message.xml b/OpenKeychain/src/main/res/layout/api_remote_error_message.xml index 3d69a25b3..8483222ad 100644 --- a/OpenKeychain/src/main/res/layout/api_remote_error_message.xml +++ b/OpenKeychain/src/main/res/layout/api_remote_error_message.xml @@ -1,16 +1,27 @@ - + - + - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_remote_register_app.xml b/OpenKeychain/src/main/res/layout/api_remote_register_app.xml index f85f3b8f7..19981f59e 100644 --- a/OpenKeychain/src/main/res/layout/api_remote_register_app.xml +++ b/OpenKeychain/src/main/res/layout/api_remote_register_app.xml @@ -1,29 +1,40 @@ - + android:layout_height="match_parent"> - + + + android:layout_height="wrap_content"> - - - + android:padding="16dp" + android:orientation="vertical"> - - + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml b/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml index bf4d0a70d..db54e4a44 100644 --- a/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml +++ b/OpenKeychain/src/main/res/layout/api_remote_select_pub_keys.xml @@ -1,21 +1,32 @@ - + - + - + - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/certify_key_activity.xml b/OpenKeychain/src/main/res/layout/certify_key_activity.xml index 2bf2c4197..3a4c343bb 100644 --- a/OpenKeychain/src/main/res/layout/certify_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/certify_key_activity.xml @@ -1,21 +1,32 @@ - + - + - - - + - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/create_key_activity.xml b/OpenKeychain/src/main/res/layout/create_key_activity.xml index 0bd053c49..5225d4d77 100644 --- a/OpenKeychain/src/main/res/layout/create_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/create_key_activity.xml @@ -1,15 +1,26 @@ - - + - + android:layout_height="match_parent"> - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml index 7f7b2cdce..189579f91 100644 --- a/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_final_fragment.xml @@ -86,7 +86,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/create_key_rsa" - android:textColor="@color/android_green_dark" + android:textColor="@color/android_green_light" android:textAppearance="?android:attr/textAppearanceMedium" android:minHeight="?android:attr/listPreferredItemHeight" android:clickable="true" @@ -128,7 +128,7 @@ android:layout_marginTop="16dp" android:layout_marginBottom="8dp" android:text="@string/create_key_final_robot_text" - android:textColor="@color/android_green_dark" + android:textColor="@color/android_green_light" android:textAppearance="?android:attr/textAppearanceMedium" android:drawableLeft="@drawable/create_key_robot" android:drawablePadding="8dp" /> diff --git a/OpenKeychain/src/main/res/layout/decrypt_content.xml b/OpenKeychain/src/main/res/layout/decrypt_content.xml index 5e7cda4f9..8944c821f 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_content.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_content.xml @@ -1,109 +1,117 @@ - + android:layout_height="match_parent"> - + - - - - - - - - + + android:layout_height="match_parent" + android:paddingTop="4dp" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:orientation="vertical"> + + + + + + + + + + style="@style/SelectableItem" + android:orientation="horizontal"> - + - + + + + + + + - + - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/decrypt_files_activity.xml b/OpenKeychain/src/main/res/layout/decrypt_files_activity.xml index 0380787db..7cc2b35f3 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_files_activity.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_files_activity.xml @@ -1,14 +1,24 @@ - + android:layout_height="match_parent"> - + - + android:layout_height="match_parent" + android:orientation="vertical"> - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml b/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml index e08ecb39e..5098d7ffa 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml @@ -1,14 +1,24 @@ - + android:layout_height="match_parent"> - + - + android:layout_height="match_parent" + android:orientation="vertical"> - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/edit_key_activity.xml b/OpenKeychain/src/main/res/layout/edit_key_activity.xml index 7e71ccf53..dfc12f328 100644 --- a/OpenKeychain/src/main/res/layout/edit_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/edit_key_activity.xml @@ -1,15 +1,25 @@ - - + - + android:layout_height="match_parent"> - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml b/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml index 67f7032c1..d14828ef7 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml @@ -1,24 +1,25 @@ + + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:id="@+id/label_fileCompression" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:paddingRight="10dip" + android:text="@string/label_file_compression" + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:id="@+id/fileCompression" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> diff --git a/OpenKeychain/src/main/res/layout/encrypt_files_content.xml b/OpenKeychain/src/main/res/layout/encrypt_files_content.xml index b44a2bc4d..61c7e69c9 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_files_content.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_files_content.xml @@ -1,23 +1,33 @@ - + android:layout_height="match_parent"> - + - + android:layout_height="match_parent" + android:orientation="vertical"> - + - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_text_content.xml b/OpenKeychain/src/main/res/layout/encrypt_text_content.xml index 809f00204..31ebef798 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_text_content.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_text_content.xml @@ -1,24 +1,33 @@ - + + + + - + - + - + - \ No newline at end of file + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml index 13cf7c225..d6165c1e0 100644 --- a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml +++ b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml @@ -17,7 +17,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginRight="10dp" - android:src="@drawable/ic_action_expand"/> + android:src="@drawable/ic_expand_more_black_24dp"/> + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml new file mode 100644 index 000000000..b1d5efe76 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml similarity index 56% rename from OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml rename to OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml index ec27e394a..7c2c2a62d 100644 --- a/OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml +++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml @@ -1,19 +1,3 @@ - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml similarity index 56% rename from OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml rename to OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml index 2590f272c..cd24a1e6d 100644 --- a/OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml +++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml @@ -1,19 +1,3 @@ - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml new file mode 100644 index 000000000..49018fee1 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml new file mode 100644 index 000000000..ed375094f --- /dev/null +++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/help_activity.xml b/OpenKeychain/src/main/res/layout/help_activity.xml index 3ad087da3..7d3e1834c 100644 --- a/OpenKeychain/src/main/res/layout/help_activity.xml +++ b/OpenKeychain/src/main/res/layout/help_activity.xml @@ -1,17 +1,31 @@ - + android:layout_height="match_parent"> - + + + android:layout_height="match_parent" + android:orientation="vertical"> - + - \ No newline at end of file + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/import_keys_activity.xml b/OpenKeychain/src/main/res/layout/import_keys_activity.xml index 35818e4ea..78eaed02d 100644 --- a/OpenKeychain/src/main/res/layout/import_keys_activity.xml +++ b/OpenKeychain/src/main/res/layout/import_keys_activity.xml @@ -1,68 +1,78 @@ - + android:layout_height="match_parent"> - - - - - - - - - - - + + android:layout_height="match_parent" + android:orientation="vertical"> + + + + - + android:layout_height="16dp" /> + + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/key_list_content.xml b/OpenKeychain/src/main/res/layout/key_list_content.xml index dd230806f..7179793b5 100644 --- a/OpenKeychain/src/main/res/layout/key_list_content.xml +++ b/OpenKeychain/src/main/res/layout/key_list_content.xml @@ -1,47 +1,56 @@ - - + - + + - - --> - - + android:layout_height="0dp" + android:layout_weight="1" /> + - - \ No newline at end of file + diff --git a/OpenKeychain/src/main/res/layout/key_server_preference.xml b/OpenKeychain/src/main/res/layout/key_server_preference.xml index 33866f746..259763e48 100644 --- a/OpenKeychain/src/main/res/layout/key_server_preference.xml +++ b/OpenKeychain/src/main/res/layout/key_server_preference.xml @@ -1,82 +1,94 @@ - + + + + android:layout_height="fill_parent" + android:orientation="vertical"> - - - - - -