/* * This file is part of Stack Wallet. * * Copyright (c) 2023 Cypher Stack * All Rights Reserved. * The code is distributed under GPLv3 license, see LICENSE file for details. * Generated by Cypher Stack on 2023-05-26 * */ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'format.dart'; import 'logger.dart'; import '../widgets/desktop/primary_button.dart'; import '../widgets/desktop/secondary_button.dart'; import '../widgets/stack_dialog.dart'; class MoneroNodeConnectionResponse { final X509Certificate? cert; final String? url; final int? port; final bool success; MoneroNodeConnectionResponse(this.cert, this.url, this.port, this.success); } Future testMoneroNodeConnection( Uri uri, bool allowBadX509Certificate, ) async { final client = HttpClient(); MoneroNodeConnectionResponse? badCertResponse; try { client.badCertificateCallback = (cert, url, port) { if (allowBadX509Certificate) { return true; } if (badCertResponse == null) { badCertResponse = MoneroNodeConnectionResponse(cert, url, port, false); } else { return false; } return false; }; final request = await client.postUrl(uri); final body = utf8.encode( jsonEncode({ "jsonrpc": "2.0", "id": "0", "method": "get_info", }), ); request.headers.add( 'Content-Length', body.length.toString(), preserveHeaderCase: true, ); request.headers.set( 'Content-Type', 'application/json', preserveHeaderCase: true, ); request.add(body); final response = await request.close(); final result = await response.transform(utf8.decoder).join(); // TODO: json decoded without error so assume connection exists? // or we can check for certain values in the response to decide return MoneroNodeConnectionResponse(null, null, null, true); } catch (e, s) { if (badCertResponse != null) { return badCertResponse!; } else { Logging.instance.log("$e\n$s", level: LogLevel.Warning); return MoneroNodeConnectionResponse(null, null, null, false); } } finally { client.close(force: true); } } Future showBadX509CertificateDialog( X509Certificate cert, String url, int port, BuildContext context, ) async { final chars = Format.uint8listToString(cert.sha1) .toUpperCase() .characters .toList(growable: false); String sha1 = chars.sublist(0, 2).join(); for (int i = 2; i < chars.length; i += 2) { sha1 += ":${chars.sublist(i, i + 2).join()}"; } final result = await showDialog( context: context, barrierDismissible: false, builder: (context) { return StackDialog( title: "Untrusted X509Certificate", message: "SHA1:\n$sha1", leftButton: SecondaryButton( label: "Cancel", onPressed: () { Navigator.of(context).pop(false); }, ), rightButton: PrimaryButton( label: "Trust", onPressed: () { Navigator.of(context).pop(true); }, ), ); }, ); return result ?? false; }