diff --git a/lib/data/model/server/systemd.dart b/lib/data/model/server/systemd.dart index d68e2d76..518f22e6 100644 --- a/lib/data/model/server/systemd.dart +++ b/lib/data/model/server/systemd.dart @@ -96,7 +96,7 @@ final class SystemdUnit { String getCmd({required SystemdUnitFunc func, required bool isRoot}) { final prefix = scope.getCmdPrefix(isRoot); - return '$prefix ${func.name} $name'; + return '$prefix ${func.name} ${name.replaceAll(RegExp(r'[^a-zA-Z0-9\-_.@:]'), '')}'; } List get availableFuncs { diff --git a/lib/data/provider/systemd.dart b/lib/data/provider/systemd.dart index 3247bdf3..3c61d2aa 100644 --- a/lib/data/provider/systemd.dart +++ b/lib/data/provider/systemd.dart @@ -77,11 +77,16 @@ class SystemdNotifier extends _$SystemdNotifier { } Future> _parseUnitObj(List unitNames, SystemdUnitScope scope) async { - final unitNames_ = unitNames.map((e) => e.trim().split('/').last.split('.').first).toList(); + final unitNames_ = unitNames.map((e) { + final fullName = e.trim().split('/').last; + final lastDot = fullName.lastIndexOf('.'); + final name = lastDot > 0 ? fullName.substring(0, lastDot) : fullName; + return name.replaceAll(RegExp(r'[^a-zA-Z0-9\-_.@:]'), ''); + }).toList(); final script = ''' -for unit in ${unitNames_.join(' ')}; do - state=\$(systemctl show --no-pager \$unit) +for unit in ${unitNames_.map((e) => '"$e"').join(' ')}; do + state=\$(systemctl show --no-pager -- "\$unit") echo "\$state" echo -n "\n${ScriptConstants.separator}\n" done @@ -102,10 +107,15 @@ done if (part.startsWith('Id=')) { final val = _getIniVal(part); if (val == null) continue; - // Id=sshd.service - final vals = val.split('.'); - name = vals.first; - type = vals.last; + // Id=org.cups.cupsd.service + final lastDot = val.lastIndexOf('.'); + if (lastDot > 0) { + name = val.substring(0, lastDot); + type = val.substring(lastDot + 1); + } else { + name = val; + type = ''; + } continue; } if (part.startsWith('ActiveState=')) { diff --git a/lib/view/page/systemd.dart b/lib/view/page/systemd.dart index 4c081ca8..9f86b0fb 100644 --- a/lib/view/page/systemd.dart +++ b/lib/view/page/systemd.dart @@ -73,8 +73,7 @@ final class _SystemdPageState extends ConsumerState { } Widget _buildUnitList() { - ref.watch(_pro.select((p) => p.units)); - ref.watch(_pro.select((p) => p.scopeFilter)); + ref.watch(_pro.select((p) => (p.units, p.scopeFilter))); final filteredUnits = _notifier.filteredUnits; if (filteredUnits.isEmpty) { return SliverToBoxAdapter(child: CenterGreyTitle(libL10n.empty).paddingSymmetric(horizontal: 13)); @@ -97,28 +96,42 @@ final class _SystemdPageState extends ConsumerState { Widget _buildUnitFuncs(SystemdUnit unit) { return PopupMenu( items: unit.availableFuncs.map(_buildUnitFuncBtn).toList(), - onSelected: (val) async { - final cmd = unit.getCmd(func: val, isRoot: widget.args.spi.isRoot); - final sure = await context.showRoundDialog( - title: libL10n.attention, - child: SimpleMarkdown(data: '```shell\n$cmd\n```'), - actions: [ - CountDownBtn( - seconds: 1, - onTap: () => context.pop(true), - text: libL10n.ok, - afterColor: Colors.red, - ), - ], - ); - if (sure != true) return; - - final args = SshPageArgs(spi: widget.args.spi, initCmd: cmd); - SSHPage.route.go(context, args); - }, + onSelected: (val) => _handleUnitFuncSelected(unit, val), ); } + void _handleUnitFuncSelected(SystemdUnit unit, SystemdUnitFunc func) { + final cmd = unit.getCmd(func: func, isRoot: widget.args.spi.isRoot); + + if (func == SystemdUnitFunc.stop || func == SystemdUnitFunc.restart) { + _showConfirmDialog(cmd); + } else { + _navigateToSsh(cmd); + } + } + + void _showConfirmDialog(String cmd) async { + final sure = await context.showRoundDialog( + title: libL10n.attention, + child: SimpleMarkdown(data: '```shell\n$cmd\n```'), + actions: [ + Btn.cancel(), + CountDownBtn( + seconds: 3, + onTap: () => context.pop(true), + text: libL10n.ok, + afterColor: Colors.red, + ), + ], + ); + if (sure == true) _navigateToSsh(cmd); + } + + void _navigateToSsh(String cmd) { + final args = SshPageArgs(spi: widget.args.spi, initCmd: cmd); + SSHPage.route.go(context, args); + } + PopupMenuEntry _buildUnitFuncBtn(SystemdUnitFunc func) { return PopupMenuItem( value: func,