Compare commits

...

4 Commits

  1. 2
      ninfs/__init__.py
  2. 74
      ninfs/gui/wizardcontainer.py
  3. 3
      ninfs/mountinfo.py
  4. 4
      standalone.spec

2
ninfs/__init__.py

@ -7,4 +7,4 @@ @@ -7,4 +7,4 @@
__author__ = 'ihaveamac'
__copyright__ = 'Copyright (c) 2017-2021 Ian Burgwin'
__license__ = 'MIT'
__version__ = '2.0a7'
__version__ = '2.0a8'

74
ninfs/gui/wizardcontainer.py

@ -14,7 +14,7 @@ from typing import TYPE_CHECKING @@ -14,7 +14,7 @@ from typing import TYPE_CHECKING
import mountinfo
from .opendir import open_directory
from .optionsframes import RadiobuttonContainer
from .optionsframes import CheckbuttonContainer, RadiobuttonContainer
from .outputviewer import OutputViewer
from .setupwizard import *
@ -22,6 +22,9 @@ if TYPE_CHECKING: @@ -22,6 +22,9 @@ if TYPE_CHECKING:
from typing import List, Optional, Type
from . import NinfsGUI
# importing this from __init__ would cause a circular import, and it's just easier to copy this again
is_windows = platform == 'win32'
wizard_bases = {
'cci': CCISetup,
'cdn': CDNSetup,
@ -39,7 +42,7 @@ wizard_bases = { @@ -39,7 +42,7 @@ wizard_bases = {
'threedsx': ThreeDSXSetup,
}
if platform == 'win32':
if is_windows:
from ctypes import windll
from string import ascii_uppercase
@ -96,7 +99,7 @@ class WizardTypeSelector(WizardBase): @@ -96,7 +99,7 @@ class WizardTypeSelector(WizardBase):
class WizardMountAdvancedOptions(tk.Toplevel):
def __init__(self, parent: 'WizardContainer' = None, *, current: 'dict'):
def __init__(self, parent: 'WizardContainer' = None, *, current: 'dict', show_dev_keys: bool):
super().__init__(parent)
self.wm_title('Advanced mount options')
@ -115,30 +118,51 @@ class WizardMountAdvancedOptions(tk.Toplevel): @@ -115,30 +118,51 @@ class WizardMountAdvancedOptions(tk.Toplevel):
container = ttk.Frame(outer_container)
container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
label = ttk.Label(container, text='External user access')
label.grid(row=0, column=0, padx=(0, 8), sticky=tk.NW)
if show_dev_keys:
label_opt = ttk.Label(container, text='Options')
label_opt.grid(row=0, column=0, padx=(0, 10), sticky=tk.NW)
opts = [
("Don't allow other users", 'none'),
('Allow access by root (-o allow_root)', 'allow_root'),
('Allow access by other users (-o allow_other)', 'allow_other'),
]
self.rb_container = RadiobuttonContainer(container, options=opts, default=current['user_access'])
self.rb_container.grid(row=0, column=1)
enabled = []
if current['use_dev']:
enabled.append('Use developer-unit keys')
self.check_opt = CheckbuttonContainer(container, options=['Use developer-unit keys'], enabled=enabled)
self.check_opt.grid(row=0, column=1, pady=(0, 10), sticky=tk.NW)
else:
self.check_opt = None
if not is_windows:
label_eua = ttk.Label(container, text='External user access')
label_eua.grid(row=1, column=0, padx=(0, 8), sticky=tk.NW)
opts_eua = [
("Don't allow other users", 'none'),
('Allow access by root (-o allow_root)', 'allow_root'),
('Allow access by other users (-o allow_other)', 'allow_other'),
]
self.rb_container_eua = RadiobuttonContainer(container, options=opts_eua, default=current['user_access'])
self.rb_container_eua.grid(row=1, column=1, pady=(0, 10))
else:
self.rb_container_eua = None
def ok():
self.ok_clicked = True
self.destroy()
ok_button = ttk.Button(container, text='OK', command=ok)
ok_button.grid(row=1, column=0, columnspan=2, pady=(10, 0))
ok_button.grid(row=2, column=0, columnspan=2)
self.geometry("+%d+%d" % (parent.winfo_rootx() + 50, parent.winfo_rooty() + 50))
self.wm_deiconify()
def get_options(self):
return {'user_access': self.rb_container.get_selected()}
user_access = 'none'
use_dev = False
if self.rb_container_eua:
user_access = self.rb_container_eua.get_selected()
if self.check_opt:
use_dev = self.check_opt.get_values()['Use developer-unit keys']
return {'user_access': user_access, 'use_dev': use_dev}
def wait_for_response(self):
self.wait_window()
@ -155,13 +179,13 @@ class WizardMountPointSelector(WizardBase): @@ -155,13 +179,13 @@ class WizardMountPointSelector(WizardBase):
self.mounttype = mounttype
self.cmdargs = cmdargs
self.adv_options = {'user_access': 'none'}
self.adv_options = {'user_access': 'none', 'use_dev': False}
# special case for nand types here, which should not be mounted to a drive letter
if platform == 'win32' and not cmdargs[0].startswith('nand'):
if is_windows and not cmdargs[0].startswith('nand'):
self.is_drive_letter = True
drive_letters = [x + ':' for x in get_unused_drives()]
drive_letters = ['A:', 'B:']
container, drive_selector, drive_selector_var = self.make_option_menu('Select the drive letter to use:',
*drive_letters)
@ -169,6 +193,11 @@ class WizardMountPointSelector(WizardBase): @@ -169,6 +193,11 @@ class WizardMountPointSelector(WizardBase):
self.mount_point_var = drive_selector_var
if cmdargs[0] in mountinfo.supports_dev_keys:
# the only advanced option for windows users is dev keys, so hide this button if that doesn't apply
adv_options_button = ttk.Button(self, text='Advanced mount options', command=self.show_advanced_options)
adv_options_button.pack(fill=tk.X, expand=True)
self.wizardcontainer.set_next_enabled(True)
else:
@ -182,8 +211,8 @@ class WizardMountPointSelector(WizardBase): @@ -182,8 +211,8 @@ class WizardMountPointSelector(WizardBase):
container, mount_textbox, mount_textbox_var = self.make_directory_picker(labeltext, 'Select mountpoint')
container.pack(fill=tk.X, expand=True)
# no advanced options needed on windows yet
if platform != 'win32':
if (not is_windows) or cmdargs[0] in mountinfo.supports_dev_keys:
# the only advanced option for windows users is dev keys, so hide this button if that doesn't apply
adv_options_button = ttk.Button(self, text='Advanced mount options', command=self.show_advanced_options)
adv_options_button.pack(fill=tk.X, expand=True)
@ -192,17 +221,20 @@ class WizardMountPointSelector(WizardBase): @@ -192,17 +221,20 @@ class WizardMountPointSelector(WizardBase):
self.mount_point_var = mount_textbox_var
def show_advanced_options(self):
adv_options_window = WizardMountAdvancedOptions(self.wizardcontainer, current=self.adv_options)
adv_options_window = WizardMountAdvancedOptions(self.wizardcontainer, current=self.adv_options,
show_dev_keys=self.cmdargs[0] in mountinfo.supports_dev_keys)
adv_options_window.focus_set()
if adv_options_window.wait_for_response():
self.adv_options.update(adv_options_window.get_options())
def next_pressed(self):
if platform == 'win32' and not self.is_drive_letter:
if is_windows and not self.is_drive_letter:
if len(os.listdir(self.mount_point_var.get())) != 0:
mb.showerror('ninfs', 'Directory must be empty.')
return
extra_args = []
if self.adv_options['use_dev']:
extra_args.append('--dev')
if self.adv_options['user_access'] != 'none':
extra_args.extend(('-o', self.adv_options['user_access']))
self.wizardcontainer.mount(self.mounttype, self.cmdargs + extra_args, self.mount_point_var.get(),

3
ninfs/mountinfo.py

@ -85,6 +85,9 @@ categories = { @@ -85,6 +85,9 @@ categories = {
'iQue Player': ['nandbb']
}
# this will add the "Use developer-unit keys" option to Advanced options in the gui
supports_dev_keys = ['cci', 'cdn', 'cia', 'nandctr', 'ncch', 'sd', 'sdtitle']
def get_type_info(mount_type):
return types[aliases.get(mount_type, mount_type)]

4
standalone.spec

@ -66,7 +66,7 @@ app = BUNDLE(coll, @@ -66,7 +66,7 @@ app = BUNDLE(coll,
'LSMinimumSystemVersion': '10.12.6',
#'NSRequiresAquaSystemAppearance': True,
#'NSHighResolutionCapable': True,
'CFBundleShortVersionString': '2.0a7',
'CFBundleVersion': '2003',
'CFBundleShortVersionString': '2.0a8',
'CFBundleVersion': '2004',
}
)

Loading…
Cancel
Save