├── .gitignore ├── .gitattributes ├── Resources ├── four.ico ├── loupe.png ├── patch.png ├── cup-cake.png ├── database.png ├── download.png ├── folder.png ├── reddit.png └── openssl.cfg ├── packages.config ├── App.config ├── Properties ├── Settings.settings ├── Settings.Designer.cs ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── Soap ├── GetCommonName.cs ├── GetVersionInfo.cs └── GetItems.cs ├── Control4.Jailbreak.csproj.user ├── Program.cs ├── Utility ├── Sddp.DeviceResponse.cs ├── SoapClient.cs └── Sddp.cs ├── LICENSE ├── Control4.Jailbreak.sln ├── UI ├── Backup.cs ├── Director.cs ├── LogWindow.cs ├── LogWindow.Designer.cs ├── MainWindow.cs ├── Backup.Designer.cs ├── Certificates.Designer.cs ├── Certificates.cs ├── LogWindow.resx ├── Composer.resx ├── DirectorPatch.resx ├── Certificates.resx ├── Backup.resx ├── DirectorPatch.cs ├── Composer.cs ├── DirectorPatch.Designer.cs ├── Composer.Designer.cs └── MainWindow.Designer.cs ├── README.md ├── Constants.cs ├── DirectorManager.cs ├── Resources.Designer.cs ├── app.manifest ├── Resources.resx └── Control4.Jailbreak.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .vs 3 | bin 4 | obj 5 | packages -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Resources/four.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/four.ico -------------------------------------------------------------------------------- /Resources/loupe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/loupe.png -------------------------------------------------------------------------------- /Resources/patch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/patch.png -------------------------------------------------------------------------------- /Resources/cup-cake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/cup-cake.png -------------------------------------------------------------------------------- /Resources/database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/database.png -------------------------------------------------------------------------------- /Resources/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/download.png -------------------------------------------------------------------------------- /Resources/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/folder.png -------------------------------------------------------------------------------- /Resources/reddit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objects/Control4.Jailbreak/master/Resources/reddit.png -------------------------------------------------------------------------------- /packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Soap/GetCommonName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml.Serialization; 7 | 8 | namespace Garry.Control4.Jailbreak.Soap 9 | { 10 | public class GetCommonName 11 | { 12 | [XmlElement( "common_name" )] 13 | public string CommonName { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Control4.Jailbreak.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace Garry.Control4.Jailbreak 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault( false ); 19 | Application.Run( new MainWindow() ); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Soap/GetVersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml.Serialization; 7 | 8 | namespace Garry.Control4.Jailbreak.Soap 9 | { 10 | public class GetVersionInfo 11 | { 12 | public class Version 13 | { 14 | [XmlAttribute( "name" )] 15 | public string Name { get; set; } 16 | [XmlAttribute( "version" )] 17 | public string VersionNumber { get; set; } 18 | } 19 | 20 | public class VersionList 21 | { 22 | [XmlElement( "version" )] 23 | public Version[] All { get; set; } 24 | } 25 | 26 | [XmlElement( "versions" )] 27 | public VersionList Versions { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Soap/GetItems.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml.Serialization; 7 | 8 | namespace Garry.Control4.Jailbreak.Soap 9 | { 10 | public class GetItems 11 | { 12 | public class SystemItem 13 | { 14 | public class Item 15 | { 16 | [XmlElement( "id" )] 17 | public int Id { get; set; } 18 | 19 | [XmlElement( "name" )] 20 | public string Name { get; set; } 21 | 22 | [XmlElement( "type" )] 23 | public int Type { get; set; } 24 | 25 | // ItemData has some moire shit 26 | } 27 | 28 | [XmlElement( "item" )] 29 | public Item[] All; 30 | } 31 | 32 | [XmlElement( "systemitems" )] 33 | public SystemItem SystemItems { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Utility/Sddp.DeviceResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net; 3 | 4 | namespace Garry.Control4.Jailbreak.Utility 5 | { 6 | partial class Sddp 7 | { 8 | public class DeviceResponse 9 | { 10 | public Dictionary FullHeaders; 11 | public IPEndPoint EndPoint; 12 | 13 | public string Location => GetHeader( "Location" ); 14 | public string Server => GetHeader( "SERVER" ); 15 | public string St => GetHeader( "ST" ); 16 | public string Usn => GetHeader( "USN" ); 17 | public string Host => GetHeader( "Host" ); 18 | public string NTS => GetHeader( "NTS" ); 19 | 20 | public string GetHeader( string name ) 21 | { 22 | FullHeaders.TryGetValue( name, out var value ); 23 | return value; 24 | } 25 | 26 | public override string ToString() => $"{EndPoint.Address}"; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Garry Newman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Garry.Control4.Jailbreak.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Control4.Jailbreak.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29411.108 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Control4.Jailbreak", "Control4.Jailbreak.csproj", "{ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {DF3DE388-B315-4AB1-8043-C4EB6ED31E0C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /UI/Backup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.IO; 11 | using System.Diagnostics; 12 | 13 | namespace Garry.Control4.Jailbreak 14 | { 15 | public partial class Backup : UserControl 16 | { 17 | MainWindow MainWindow; 18 | 19 | public Backup( MainWindow MainWindow ) 20 | { 21 | this.MainWindow = MainWindow; 22 | 23 | InitializeComponent(); 24 | } 25 | 26 | private void MakeABackupOfTheCertificate( object sender, EventArgs e ) 27 | { 28 | if ( MainWindow.ConnectedDirector == null ) 29 | return; 30 | 31 | using ( var ssh = MainWindow.ConnectedDirector.ScpClient ) 32 | { 33 | ssh.Connect(); 34 | 35 | using ( var stream = new MemoryStream() ) 36 | { 37 | ssh.Download( "/etc/openvpn/clientca-prod.pem", stream ); 38 | 39 | SaveFileDialog save = new SaveFileDialog(); 40 | save.Filter = "Certificate File|*.pem"; 41 | save.Title = "Save clientca-prod.pem"; 42 | save.FileName = "clientca-prod-downloadedbackup.pem"; 43 | save.ShowDialog(); 44 | 45 | if ( !string.IsNullOrEmpty( save.FileName ) ) 46 | { 47 | System.IO.File.WriteAllBytes( save.FileName, stream.ToArray() ); 48 | } 49 | } 50 | 51 | ssh.Disconnect(); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What 2 | 3 | Jailbreak tool for Control4 3.2.1 - allowing add/rename/move rooms/drivers/devices without being a dealer. 4 | 5 | # Why 6 | 7 | I'm a nerd. I got home automation in my house so I could play with it, so I could write my own drivers and make it do cool stuff. By default you can't do that without being an authorized dealer - unless you jailbreak your Director. 8 | 9 | There are a few dodgy tools floating around that achieve the same thing, but the process is over-complicated, error prone and out of date. 10 | 11 | I thought it would be safer/easier in the long run to write something open source. 12 | 13 | # How 14 | 15 | Head over to the [releases page](https://github.com/garrynewman/Control4.Jailbreak/releases) and download the zip (not the source). Unzip and run C4Jailbreak.exe. 16 | 17 | ## Follow Each Step 18 | 19 | ![Steps](https://files.facepunch.com/garry/aba22fcf-672e-41e1-8184-f74d4d8a0b53.png) 20 | 21 | ## Enjoy 22 | 23 | You're all done 24 | 25 | # Other stuff 26 | 27 | Everything is at your own risk, obviously. If this tool leads to your house burning down you can't blame me. 28 | 29 | To Control4 - please don't be angry at this tool. I love my control4 automated house and would spend a ton more time and money with you guys if I didn't have to do it through a dealer every time. If you want to contact me I'm at garrynewman@gmail.com <3 30 | 31 | We have a small reddit group for Control4 DIY over at https://www.reddit.com/r/C4diy/ - feel free to ask for help here. 32 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle( "Control4 Jailbreaker" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "Control4 Jailbreaker" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2020" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible( false )] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid( "aba795e1-3a9c-4ef2-bdf5-c4acae48670f" )] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion( "1.0.0.0" )] 36 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 37 | -------------------------------------------------------------------------------- /Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Garry.Control4.Jailbreak 8 | { 9 | public static class Constants 10 | { 11 | public const int Version = 5; 12 | 13 | /// 14 | /// The cert for composer needs to be named cacert-*.pem 15 | /// 16 | public const string ComposerCertName = "cacert-jailbreak.pem"; 17 | 18 | /// 19 | /// Needs to start with Composer_ and can be anything after 20 | /// 21 | public const string CertificateCN = "Composer_GarryJailbreak"; 22 | 23 | /// 24 | /// Should always be this unless they change something internally 25 | /// 26 | public const string CertPassword = "R8lvpqtgYiAeyO8j8Pyd"; 27 | 28 | /// 29 | /// How many days until the certificate expires. Doesn't seem any harm in setting this to 30 | /// a huge value so you don't have to re-crack every year. 31 | /// 32 | public const int CertificateExpireDays = 3650; 33 | 34 | /// 35 | /// Where OpenSSL is installed (it's installed with Composer) 36 | /// 37 | public const string OpenSslExe = @"C:\Program Files (x86)\Control4\Composer\Pro\RemoteAccess\bin\openssl.exe"; 38 | 39 | /// 40 | /// Where OpenSSL's Config is located (it's installed with Composer) 41 | /// 42 | public const string OpenSslConfig = @"Certs\openssl.cfg"; 43 | 44 | /// 45 | /// What version of Director/Composer we're aiming at 46 | /// 47 | public const string TargetDirectorVersion = @"3.2.3"; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /UI/Director.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.Diagnostics; 11 | 12 | namespace Garry.Control4.Jailbreak 13 | { 14 | public partial class Director 15 | { 16 | MainWindow MainWindow; 17 | 18 | public Director( MainWindow mainWindow ) 19 | { 20 | MainWindow = mainWindow; 21 | } 22 | 23 | public async Task RefreshList() 24 | { 25 | using ( var sddp = new Utility.Sddp() ) 26 | { 27 | sddp.OnResponse = r => 28 | { 29 | if ( r.St != "c4:director" ) 30 | return; 31 | 32 | _ = Connect( r ); 33 | }; 34 | 35 | sddp.Search( "c4:director" ); 36 | 37 | await Task.Delay( 4000 ); 38 | } 39 | } 40 | 41 | async Task Connect( Utility.Sddp.DeviceResponse connection ) 42 | { 43 | try 44 | { 45 | MainWindow.DirectorPatch.Address.Text = connection.EndPoint.Address.ToString(); 46 | 47 | MainWindow.SetStatusRight( $"Connecting to {connection.EndPoint.Address}.." ); 48 | 49 | var director = new DirectorManager( connection.EndPoint.Address ); 50 | 51 | var result = await director.TryInitialize(); 52 | if ( !result ) 53 | { 54 | MessageBox.Show( "Couldn't connect to director", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Information ); 55 | return false; 56 | } 57 | 58 | MainWindow.ConnectedDirector = director; 59 | MainWindow.SetStatusRight( $"Connected to {connection.EndPoint.Address}" ); 60 | return true; 61 | } 62 | catch ( System.Exception ) 63 | { 64 | return false; 65 | } 66 | } 67 | 68 | internal void DirectorDisconnected() 69 | { 70 | MainWindow.SetStatusRight( $"Not Connected" ); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UI/LogWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Garry.Control4.Jailbreak 12 | { 13 | public partial class LogWindow : Form 14 | { 15 | public LogWindow( Form mainWindow ) 16 | { 17 | Owner = mainWindow; 18 | InitializeComponent(); 19 | 20 | CenterToParent(); 21 | Show(); 22 | } 23 | 24 | private void Write( string v ) 25 | { 26 | textBox.AppendText( v ); 27 | 28 | textBox.ScrollToCaret(); 29 | textBox.Refresh(); 30 | } 31 | 32 | internal void WriteNormal( string v ) 33 | { 34 | textBox.SelectionColor = Color.Black; 35 | Write( v ); 36 | } 37 | 38 | internal void WriteSuccess( string v ) 39 | { 40 | textBox.SelectionColor = Color.Green; 41 | Write( v ); 42 | } 43 | 44 | internal void WriteWarning( string v ) 45 | { 46 | textBox.SelectionColor = Color.Orange; 47 | Write( v ); 48 | } 49 | 50 | internal void WriteError( System.Exception v ) 51 | { 52 | WriteError( $"\n{v.Message}\n" ); 53 | WriteNormal( $"{v.StackTrace}\n" ); 54 | } 55 | 56 | internal void WriteError( string v ) 57 | { 58 | textBox.SelectionColor = Color.Red; 59 | Write( v ); 60 | } 61 | 62 | internal void WriteTrace( string v ) 63 | { 64 | textBox.SelectionColor = Color.Gray; 65 | Write( v ); 66 | } 67 | 68 | internal void WriteHighlight( string v ) 69 | { 70 | textBox.SelectionColor = Color.Blue; 71 | Write( v ); 72 | } 73 | 74 | private void button1_Click( object sender, EventArgs e ) 75 | { 76 | Close(); 77 | } 78 | 79 | protected override void OnClosed( EventArgs e ) 80 | { 81 | base.OnClosed( e ); 82 | 83 | Owner.Enabled = true; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /DirectorManager.cs: -------------------------------------------------------------------------------- 1 | using Garry.Control4.Jailbreak.Utility; 2 | using Renci.SshNet; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Garry.Control4.Jailbreak 13 | { 14 | public class DirectorManager 15 | { 16 | private IPAddress address; 17 | 18 | SoapClient Soap; 19 | ConnectionInfo SshConnectionInfo; 20 | 21 | public string SystemName { get; private set; } 22 | public string CommonName { get; private set; } 23 | public string Version { get; private set; } 24 | 25 | public DirectorManager( IPAddress address ) 26 | { 27 | this.address = address; 28 | 29 | SshConnectionInfo = new ConnectionInfo( address.ToString(), "jailbreak", new PasswordAuthenticationMethod( "jailbreak", "jailbreak" ) ); 30 | SshConnectionInfo.RetryAttempts = 1; 31 | SshConnectionInfo.Timeout = TimeSpan.FromSeconds( 2 ); 32 | } 33 | 34 | public ScpClient ScpClient => new ScpClient( SshConnectionInfo ); 35 | public SshClient SshClient => new SshClient( SshConnectionInfo ); 36 | 37 | public async Task TryInitialize() 38 | { 39 | 40 | // 41 | // Since 3.1.1 Soap doesn't work, we probably need a certificate or something 42 | // 43 | 44 | //Soap = new SoapClient( address ); 45 | 46 | //var getItems = await Soap.Call( "GetItems", "filter", "1" ); 47 | //var getVersionInfo = await Soap.Call( "GetVersionInfo" ); 48 | //var getCommonName = await Soap.Call( "GetCommonName" ); 49 | 50 | //SystemName = getItems.SystemItems.All.FirstOrDefault( x => x.Type == 1 ).Name; 51 | //CommonName = getCommonName.CommonName; 52 | //Version = getVersionInfo.Versions.All.Single( x => x.Name == "Director" ).VersionNumber; 53 | 54 | Trace.WriteLine( $"Version is {Version}" ); 55 | 56 | return true; 57 | } 58 | 59 | internal async void Reboot( LogWindow log ) 60 | { 61 | log.WriteNormal( $"\nRebooting Director\n\n" ); 62 | 63 | using ( var ssh = SshClient ) 64 | { 65 | log.WriteTrace( $"\nConnecting via SSH.. " ); 66 | 67 | ssh.Connect(); 68 | 69 | log.WriteTrace( $"\n .. connected!" ); 70 | 71 | log.WriteSuccess( $"\n\nYour director is now rebooting. This can take a few minutes and it's a nervous wait - I know.\n" ); 72 | log.WriteSuccess( $"But nothing we've done here will stop your director from booting up, so don't worry.\n" ); 73 | 74 | var cmd = ssh.CreateCommand( "sysman reboot" ); 75 | 76 | var task = cmd.BeginExecute(); 77 | 78 | while( !task.IsCompleted ) 79 | { 80 | await Task.Delay( 10 ); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace C4Mod { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("C4Mod.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /UI/LogWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class LogWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.button1 = new System.Windows.Forms.Button(); 32 | this.textBox = new System.Windows.Forms.RichTextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // button1 36 | // 37 | this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 38 | this.button1.Location = new System.Drawing.Point(790, 482); 39 | this.button1.Name = "button1"; 40 | this.button1.Size = new System.Drawing.Size(99, 23); 41 | this.button1.TabIndex = 0; 42 | this.button1.Text = "Close"; 43 | this.button1.UseVisualStyleBackColor = true; 44 | this.button1.Click += new System.EventHandler(this.button1_Click); 45 | // 46 | // textBox 47 | // 48 | this.textBox.AcceptsTab = true; 49 | this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 50 | | System.Windows.Forms.AnchorStyles.Left) 51 | | System.Windows.Forms.AnchorStyles.Right))); 52 | this.textBox.AutoWordSelection = true; 53 | this.textBox.BackColor = System.Drawing.Color.White; 54 | this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 55 | this.textBox.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 56 | this.textBox.HideSelection = false; 57 | this.textBox.Location = new System.Drawing.Point(12, 12); 58 | this.textBox.Name = "textBox"; 59 | this.textBox.ReadOnly = true; 60 | this.textBox.Size = new System.Drawing.Size(877, 454); 61 | this.textBox.TabIndex = 1; 62 | this.textBox.Text = ""; 63 | // 64 | // LogWindow 65 | // 66 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 67 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 68 | this.ClientSize = new System.Drawing.Size(901, 514); 69 | this.Controls.Add(this.textBox); 70 | this.Controls.Add(this.button1); 71 | this.Name = "LogWindow"; 72 | this.Text = "LogWindow"; 73 | this.ResumeLayout(false); 74 | 75 | } 76 | 77 | #endregion 78 | 79 | private System.Windows.Forms.Button button1; 80 | private System.Windows.Forms.RichTextBox textBox; 81 | } 82 | } -------------------------------------------------------------------------------- /UI/MainWindow.cs: -------------------------------------------------------------------------------- 1 | using Garry.Control4.Jailbreak.Properties; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace Garry.Control4.Jailbreak 13 | { 14 | public partial class MainWindow : Form 15 | { 16 | public Certificates Certificates { get; set; } 17 | public Composer Composer { get; set; } 18 | public Director Director { get; set; } 19 | 20 | public DirectorPatch DirectorPatch { get; set; } 21 | public DirectorManager ConnectedDirector { get; set; } 22 | 23 | 24 | public MainWindow() 25 | { 26 | InitializeComponent(); 27 | 28 | if ( !System.IO.Directory.Exists( "Certs" ) ) 29 | { 30 | System.IO.Directory.CreateDirectory( "Certs" ); 31 | } 32 | 33 | System.IO.File.WriteAllBytes( "Certs/openssl.cfg", Resources.openssl ); 34 | 35 | this.Text += $" - v{Constants.Version} - For C4 v{Constants.TargetDirectorVersion}"; 36 | 37 | TabControl.TabPages.Clear(); 38 | 39 | Director = new Director( this ); 40 | 41 | Certificates = new Certificates( this ); 42 | TabControl.TabPages.Add( "Certificates" ); 43 | Certificates.Parent = TabControl.TabPages[0]; 44 | Certificates.Dock = DockStyle.Fill; 45 | 46 | Composer = new Composer( this ); 47 | TabControl.TabPages.Add( "Composer" ); 48 | Composer.Parent = TabControl.TabPages[ 1 ]; 49 | Composer.Dock = DockStyle.Fill; 50 | 51 | DirectorPatch = new DirectorPatch( this ); 52 | TabControl.TabPages.Add( "Director" ); 53 | DirectorPatch.Parent = TabControl.TabPages[ 2 ]; 54 | DirectorPatch.Dock = DockStyle.Fill; 55 | 56 | CenterToScreen(); 57 | 58 | Load += OnLoaded; 59 | } 60 | 61 | private async void OnLoaded( object sender, EventArgs e ) 62 | { 63 | DirectorDisconnected(); 64 | 65 | await Director.RefreshList(); 66 | } 67 | 68 | private void OnFormClosed( object sender, FormClosedEventArgs e ) 69 | { 70 | Application.Exit(); 71 | } 72 | 73 | public void SetStatusRight( string txt ) 74 | { 75 | this.StatusTextRight.Text = txt; 76 | } 77 | 78 | private void OpenComposerFolder( object sender, EventArgs e ) 79 | { 80 | System.Diagnostics.Process.Start( $"C:\\Program Files (x86)\\Control4\\Composer" ); 81 | } 82 | 83 | private void OpenComposerSettingsFolder( object sender, EventArgs e ) 84 | { 85 | System.Diagnostics.Process.Start( $"{Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData )}\\Control4" ); 86 | } 87 | 88 | internal void DirectorDisconnected() 89 | { 90 | ConnectedDirector = null; 91 | Director.DirectorDisconnected(); 92 | } 93 | 94 | private void ViewOnGithub( object sender, EventArgs e ) 95 | { 96 | System.Diagnostics.Process.Start( $"https://github.com/garrynewman/Control4.Jailbreak" ); 97 | } 98 | 99 | private void FileAndQuit( object sender, EventArgs e ) 100 | { 101 | Application.Exit(); 102 | } 103 | 104 | private void VisitC4Diy( object sender, EventArgs e ) 105 | { 106 | System.Diagnostics.Process.Start( $"https://www.reddit.com/r/C4diy/" ); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Utility/SoapClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.Security; 8 | using System.Net.Sockets; 9 | using System.Security.Authentication; 10 | using System.Security.Cryptography.X509Certificates; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using System.Xml; 14 | using System.Xml.Serialization; 15 | 16 | namespace Garry.Control4.Jailbreak.Utility 17 | { 18 | class SoapClient 19 | { 20 | // 21 | // Apparently you can't use 5020 non ssl mode in 3.1 22 | // 23 | static int port = 5021; 24 | 25 | private IPAddress address; 26 | 27 | public SoapClient( IPAddress address ) 28 | { 29 | this.address = address; 30 | } 31 | 32 | public async Task Call( string methodName, params object[] args ) 33 | { 34 | var argstr = ""; 35 | 36 | if ( args.Length != 0 ) 37 | { 38 | for ( int i = 0; i < args.Length; i += 2 ) 39 | { 40 | argstr += $"{args[i+1]}"; 41 | } 42 | } 43 | 44 | var msg = $"{argstr}M"; 45 | 46 | Trace.WriteLine( $"Out: {msg}" ); 47 | 48 | return await CallDirect( msg ); 49 | } 50 | 51 | public async Task Call( string methodName, params object[] args ) 52 | { 53 | var str = await Call( methodName, args ); 54 | 55 | str = $"\n{str}"; 56 | 57 | XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ), new XmlRootAttribute( "c4soap" ) ); 58 | using ( var strReader = new StringReader( str ) ) 59 | { 60 | using ( XmlReader reader = XmlReader.Create( strReader ) ) 61 | { 62 | return (T)xmlSerializer.Deserialize( reader ); 63 | } 64 | } 65 | } 66 | 67 | private async Task CallDirect( string msg ) 68 | { 69 | using ( var client = new TcpClient( address.ToString(), port ) ) 70 | { 71 | client.ReceiveTimeout = 2000; 72 | client.SendTimeout = 2000; 73 | 74 | using ( var stream = new SslStream( client.GetStream(), false, ( a, b, c, d ) => true ) ) 75 | { 76 | stream.ReadTimeout = 1000; 77 | stream.WriteTimeout = 1000; 78 | 79 | await stream.AuthenticateAsClientAsync( "" ); 80 | 81 | var data = Encoding.UTF8.GetBytes( msg ); 82 | stream.Write( data, 0, data.Length ); 83 | stream.WriteByte( 0 ); 84 | 85 | await stream.FlushAsync(); 86 | 87 | return await ReadResponse( stream ); 88 | } 89 | } 90 | } 91 | 92 | private async Task ReadResponse( SslStream stream ) 93 | { 94 | var data = new Byte[1024]; 95 | int n; 96 | var done = false; 97 | var sb = new StringBuilder(); 98 | while ( !done ) 99 | { 100 | try 101 | { 102 | while ( (n = await stream.ReadAsync( data, 0, data.Length )) > 0 ) 103 | { 104 | // check for last byte 105 | if ( data[n - 1] == 0 ) 106 | { 107 | sb.Append( System.Text.Encoding.ASCII.GetString( data, 0, n - 1 ) ); 108 | done = true; 109 | break; 110 | } 111 | sb.Append( System.Text.Encoding.ASCII.GetString( data, 0, n ) ); 112 | } 113 | } 114 | catch ( System.IO.IOException ) 115 | { 116 | return null; 117 | } 118 | 119 | await Task.Delay( 10 ); 120 | } 121 | 122 | var r = sb.ToString(); 123 | 124 | if ( r.Length < 1024 * 10 ) 125 | Trace.WriteLine( $"Out: {r}" ); 126 | else 127 | Trace.WriteLine( $"Out: {r.Substring( 0, 1024 * 10 )}" ); 128 | 129 | return r; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Utility/Sddp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http.Headers; 7 | using System.Net.NetworkInformation; 8 | using System.Net.Sockets; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Garry.Control4.Jailbreak.Utility 13 | { 14 | partial class Sddp : IDisposable 15 | { 16 | public Socket SearchSocket { get; private set; } 17 | public byte[] ReceiveBytes = new byte[1024]; 18 | 19 | public Action OnResponse; 20 | 21 | EndPoint endPoint; 22 | 23 | public Sddp() 24 | { 25 | endPoint = new IPEndPoint( IPAddress.Any, 0 ); 26 | 27 | SearchSocket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp ); 28 | SearchSocket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1 ); 29 | SearchSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 3 ); 30 | SearchSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption( IPAddress.Parse( "239.255.255.250" ) ) ); 31 | SearchSocket.Bind( endPoint ); 32 | SearchSocket.BeginReceiveFrom( ReceiveBytes, 0, ReceiveBytes.Length, SocketFlags.None, ref endPoint, new AsyncCallback( SearchSocketRecv ), this ); 33 | } 34 | 35 | public void Dispose() 36 | { 37 | SearchSocket?.Shutdown( SocketShutdown.Both ); 38 | SearchSocket = null; 39 | } 40 | 41 | public void Search( string target ) 42 | { 43 | SendMessage( $"M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 5\r\nST: {target}\r\n\r\n\0" ); 44 | } 45 | 46 | public void SendMessage( string message ) 47 | { 48 | var bytes = Encoding.UTF8.GetBytes( message ); 49 | var hostByName = Dns.GetHostEntry( Dns.GetHostName() ); 50 | var addressList = hostByName.AddressList; 51 | var remoteEP = new IPEndPoint( IPAddress.Parse( "239.255.255.250" ), 1900 ); 52 | var array = addressList; 53 | for ( int i = 0; i < array.Length; i++ ) 54 | { 55 | var iPAddress = array[i]; 56 | var addressBytes = iPAddress.GetAddressBytes(); 57 | if ( addressBytes.Length > 4 ) continue; 58 | 59 | var optionValue = (int)addressBytes[0] + ((int)addressBytes[1] << 8) + ((int)addressBytes[2] << 16) + ((int)addressBytes[3] << 24); 60 | 61 | SearchSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastInterface, optionValue ); 62 | SearchSocket.SendTo( bytes, 0, bytes.Length, SocketFlags.None, remoteEP ); 63 | } 64 | } 65 | 66 | private void SearchSocketRecv( IAsyncResult Result ) 67 | { 68 | if ( SearchSocket == null ) 69 | return; 70 | 71 | try 72 | { 73 | EndPoint endPoint = new IPEndPoint( IPAddress.Any, 0 ); 74 | int num = SearchSocket.EndReceiveFrom( Result, ref endPoint ); 75 | 76 | if ( num <= 0 ) return; 77 | var msg = Encoding.UTF8.GetString( ReceiveBytes, 0, num ); 78 | 79 | var lines = msg.Split( '\n', '\r' ); 80 | 81 | var headers = lines.Where( x => x.Contains( ":" ) ) 82 | .ToDictionary( 83 | x => x.Substring( 0, x.IndexOf( ':' ) ).Trim(), 84 | x => x.Substring( x.IndexOf( ':' ) + 1 ).Trim() ); 85 | 86 | if ( headers.Count == 0 ) 87 | return; 88 | 89 | var response = new DeviceResponse 90 | { 91 | FullHeaders = headers, 92 | EndPoint = endPoint as IPEndPoint, 93 | }; 94 | 95 | OnResponse?.Invoke( response ); 96 | } 97 | finally 98 | { 99 | SearchSocket.BeginReceiveFrom( ReceiveBytes, 0, ReceiveBytes.Length, SocketFlags.None, ref endPoint, new AsyncCallback( SearchSocketRecv ), this ); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /UI/Backup.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class Backup 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Backup)); 32 | this.label2 = new System.Windows.Forms.Label(); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.button1 = new System.Windows.Forms.Button(); 35 | this.SuspendLayout(); 36 | // 37 | // label2 38 | // 39 | this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 40 | | System.Windows.Forms.AnchorStyles.Right))); 41 | this.label2.Location = new System.Drawing.Point(24, 53); 42 | this.label2.Name = "label2"; 43 | this.label2.Size = new System.Drawing.Size(390, 207); 44 | this.label2.TabIndex = 2; 45 | this.label2.Text = resources.GetString("label2.Text"); 46 | // 47 | // label1 48 | // 49 | this.label1.AutoSize = true; 50 | this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 51 | this.label1.ForeColor = System.Drawing.SystemColors.Highlight; 52 | this.label1.Location = new System.Drawing.Point(24, 24); 53 | this.label1.Name = "label1"; 54 | this.label1.Size = new System.Drawing.Size(226, 18); 55 | this.label1.TabIndex = 1; 56 | this.label1.Text = "Controller Certificate Backup"; 57 | // 58 | // button1 59 | // 60 | this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 61 | this.button1.AutoSize = true; 62 | this.button1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 63 | this.button1.Image = global:: Garry.Control4.Jailbreak.Properties.Resources.download; 64 | this.button1.Location = new System.Drawing.Point(317, 283); 65 | this.button1.Name = "button1"; 66 | this.button1.Padding = new System.Windows.Forms.Padding(8); 67 | this.button1.Size = new System.Drawing.Size(97, 39); 68 | this.button1.TabIndex = 0; 69 | this.button1.Text = "Download"; 70 | this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 71 | this.button1.UseVisualStyleBackColor = true; 72 | this.button1.Click += new System.EventHandler(this.MakeABackupOfTheCertificate); 73 | // 74 | // BackupAndRestore 75 | // 76 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 77 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 78 | this.Controls.Add(this.label2); 79 | this.Controls.Add(this.label1); 80 | this.Controls.Add(this.button1); 81 | this.Name = "BackupAndRestore"; 82 | this.Size = new System.Drawing.Size(436, 355); 83 | this.ResumeLayout(false); 84 | this.PerformLayout(); 85 | 86 | } 87 | 88 | #endregion 89 | private System.Windows.Forms.Label label2; 90 | private System.Windows.Forms.Label label1; 91 | private System.Windows.Forms.Button button1; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Resources/openssl.cfg: -------------------------------------------------------------------------------- 1 | HOME = . 2 | RANDFILE = $ENV::HOME/.rnd 3 | oid_section = new_oids 4 | [ new_oids ] 5 | 6 | tsa_policy1 = 1.2.3.4.1 7 | tsa_policy2 = 1.2.3.4.5.6 8 | tsa_policy3 = 1.2.3.4.5.7 9 | 10 | #################################################################### 11 | [ ca ] 12 | default_ca = CA_default # The default ca section 13 | 14 | #################################################################### 15 | [ CA_default ] 16 | 17 | dir = ./ca # Where everything is kept 18 | certs = $dir/certs # Where the issued certs are kept 19 | crl_dir = $dir/crl # Where the issued crl are kept 20 | database = $dir/index.txt # database index file. 21 | #unique_subject = no # Set to 'no' to allow creation of 22 | # several ctificates with same subject. 23 | new_certs_dir = $dir/newcerts # default place for new certs. 24 | 25 | certificate = $dir/cacert.pem # The CA certificate 26 | serial = $dir/serial # The current serial number 27 | crlnumber = $dir/crlnumber # the current crl number 28 | # must be commented out to leave a V1 CRL 29 | crl = $dir/crl.pem # The current CRL 30 | private_key = $dir/private/cakey.pem# The private key 31 | RANDFILE = $dir/private/.rand # private random number file 32 | 33 | x509_extensions = usr_cert # The extentions to add to the cert 34 | 35 | # Comment out the following two lines for the "traditional" 36 | # (and highly broken) format. 37 | name_opt = ca_default # Subject Name options 38 | cert_opt = ca_default # Certificate field options 39 | 40 | # Extension copying option: use with caution. 41 | # copy_extensions = copy 42 | 43 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 44 | # so this is commented out by default to leave a V1 CRL. 45 | # crlnumber must also be commented out to leave a V1 CRL. 46 | # crl_extensions = crl_ext 47 | 48 | default_days = 365 # how long to certify for 49 | default_crl_days= 30 # how long before next CRL 50 | default_md = default # use public key default MD 51 | preserve = no # keep passed DN ordering 52 | 53 | # A few difference way of specifying how similar the request should look 54 | # For type CA, the listed attributes must be the same, and the optional 55 | # and supplied fields are just that :-) 56 | policy = policy_match 57 | 58 | # For the CA policy 59 | [ policy_match ] 60 | countryName = optional 61 | stateOrProvinceName = optional 62 | organizationName = optional 63 | organizationalUnitName = optional 64 | commonName = optional 65 | emailAddress = optional 66 | 67 | [ policy_anything ] 68 | countryName = optional 69 | stateOrProvinceName = optional 70 | localityName = optional 71 | organizationName = optional 72 | organizationalUnitName = optional 73 | commonName = optional 74 | emailAddress = optional 75 | 76 | #################################################################### 77 | [ req ] 78 | default_bits = 2048 79 | default_keyfile = privkey.pem 80 | distinguished_name = req_distinguished_name 81 | attributes = req_attributes 82 | x509_extensions = v3_ca # The extentions to add to the self signed cert 83 | string_mask = utf8only 84 | 85 | [ req_distinguished_name ] 86 | countryName = Country Name (2 letter code) 87 | countryName_default = AU 88 | countryName_min = 2 89 | countryName_max = 2 90 | 91 | stateOrProvinceName = State or Province Name (full name) 92 | stateOrProvinceName_default = Some-State 93 | 94 | localityName = Locality Name (eg, city) 95 | 96 | 0.organizationName = Organization Name (eg, company) 97 | 0.organizationName_default = Internet Widgits Pty Ltd 98 | 99 | # we can do this but it is not needed normally :-) 100 | #1.organizationName = Second Organization Name (eg, company) 101 | #1.organizationName_default = World Wide Web Pty Ltd 102 | 103 | organizationalUnitName = Organizational Unit Name (eg, section) 104 | #organizationalUnitName_default = 105 | 106 | commonName = Common Name (e.g. server FQDN or YOUR name) 107 | commonName_max = 64 108 | 109 | emailAddress = Email Address 110 | emailAddress_max = 64 111 | 112 | # SET-ex3 = SET extension number 3 113 | 114 | [ req_attributes ] 115 | challengePassword = A challenge password 116 | challengePassword_min = 4 117 | challengePassword_max = 20 118 | 119 | unstructuredName = An optional company name 120 | 121 | [ usr_cert ] 122 | 123 | basicConstraints=CA:FALSE 124 | 125 | nsComment = "OpenSSL Generated Certificate" 126 | 127 | subjectKeyIdentifier=hash 128 | authorityKeyIdentifier=keyid,issuer 129 | 130 | [ v3_req ] 131 | 132 | basicConstraints = CA:FALSE 133 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 134 | 135 | [ v3_ca ] 136 | 137 | subjectKeyIdentifier=hash 138 | authorityKeyIdentifier=keyid:always,issuer 139 | basicConstraints = CA:true 140 | 141 | [ crl_ext ] 142 | authorityKeyIdentifier=keyid:always 143 | 144 | [ proxy_cert_ext ] 145 | basicConstraints=CA:FALSE 146 | nsComment = "OpenSSL Generated Certificate" 147 | subjectKeyIdentifier=hash 148 | authorityKeyIdentifier=keyid,issuer 149 | proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo 150 | 151 | -------------------------------------------------------------------------------- /UI/Certificates.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class Certificates 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Certificates)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.label2 = new System.Windows.Forms.Label(); 34 | this.button2 = new System.Windows.Forms.Button(); 35 | this.button1 = new System.Windows.Forms.Button(); 36 | this.SuspendLayout(); 37 | // 38 | // label1 39 | // 40 | this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 41 | | System.Windows.Forms.AnchorStyles.Right))); 42 | this.label1.Location = new System.Drawing.Point(15, 79); 43 | this.label1.Name = "label1"; 44 | this.label1.Size = new System.Drawing.Size(469, 176); 45 | this.label1.TabIndex = 14; 46 | this.label1.Text = resources.GetString("label1.Text"); 47 | // 48 | // label2 49 | // 50 | this.label2.AutoSize = true; 51 | this.label2.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 52 | this.label2.ForeColor = System.Drawing.SystemColors.Highlight; 53 | this.label2.Location = new System.Drawing.Point(11, 25); 54 | this.label2.Name = "label2"; 55 | this.label2.Size = new System.Drawing.Size(296, 30); 56 | this.label2.TabIndex = 12; 57 | this.label2.Text = "GENERATE CERTIFICATES"; 58 | // 59 | // button2 60 | // 61 | this.button2.Image = global::Garry.Control4.Jailbreak.Properties.Resources.folder; 62 | this.button2.Location = new System.Drawing.Point(340, 269); 63 | this.button2.Name = "button2"; 64 | this.button2.Size = new System.Drawing.Size(132, 34); 65 | this.button2.TabIndex = 15; 66 | this.button2.Text = "View Certificates"; 67 | this.button2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 68 | this.button2.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 69 | this.button2.UseVisualStyleBackColor = true; 70 | this.button2.Click += new System.EventHandler(this.ViewCertificates); 71 | // 72 | // button1 73 | // 74 | this.button1.Image = global::Garry.Control4.Jailbreak.Properties.Resources.cup_cake; 75 | this.button1.Location = new System.Drawing.Point(229, 269); 76 | this.button1.Name = "button1"; 77 | this.button1.Size = new System.Drawing.Size(105, 34); 78 | this.button1.TabIndex = 13; 79 | this.button1.Text = "Generate"; 80 | this.button1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 81 | this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 82 | this.button1.UseVisualStyleBackColor = true; 83 | this.button1.Click += new System.EventHandler(this.GenerateCertificates); 84 | // 85 | // Certificates 86 | // 87 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 88 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 89 | this.BackColor = System.Drawing.SystemColors.Window; 90 | this.Controls.Add(this.button2); 91 | this.Controls.Add(this.label1); 92 | this.Controls.Add(this.button1); 93 | this.Controls.Add(this.label2); 94 | this.Name = "Certificates"; 95 | this.Size = new System.Drawing.Size(500, 480); 96 | this.ResumeLayout(false); 97 | this.PerformLayout(); 98 | 99 | } 100 | 101 | #endregion 102 | 103 | private System.Windows.Forms.Button button2; 104 | private System.Windows.Forms.Label label1; 105 | private System.Windows.Forms.Button button1; 106 | private System.Windows.Forms.Label label2; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /UI/Certificates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.Diagnostics; 11 | 12 | namespace Garry.Control4.Jailbreak 13 | { 14 | public partial class Certificates : UserControl 15 | { 16 | MainWindow MainWindow; 17 | 18 | public Certificates( MainWindow MainWindow ) 19 | { 20 | this.MainWindow = MainWindow; 21 | 22 | InitializeComponent(); 23 | } 24 | 25 | private void GenerateCertificates( object sender, EventArgs e ) 26 | { 27 | var log = new LogWindow( MainWindow ); 28 | 29 | log.WriteNormal( "Generating Certificates\n" ); 30 | if ( !GenerateCertificates( log ) ) 31 | { 32 | return; 33 | } 34 | log.WriteSuccess( "Certificate Generation Successful" ); 35 | log.WriteNormal( "\n\n" ); 36 | } 37 | 38 | private void ViewCertificates( object sender, EventArgs e ) 39 | { 40 | var folder = System.IO.Path.GetFullPath( "Certs" ); 41 | 42 | if ( !System.IO.Directory.Exists( folder ) ) 43 | { 44 | var log = new LogWindow( MainWindow ); 45 | log.WriteError( $"{folder}doesn't exist - did you generate certificates yet?\n" ); 46 | return; 47 | } 48 | 49 | Process.Start( "explorer.exe", folder ); 50 | } 51 | 52 | bool GenerateCertificates( LogWindow log ) 53 | { 54 | // 55 | // Don't regenerate the certificates. They might be copying the folder 56 | // over to another computer or some shit. 57 | // 58 | if ( System.IO.File.Exists( $"Certs/{Constants.ComposerCertName}" ) && 59 | System.IO.File.Exists( $"Certs/composer.p12" ) && 60 | System.IO.File.Exists( $"Certs/private.key" ) && 61 | System.IO.File.Exists( $"Certs/public.pem" ) ) 62 | { 63 | log.WriteSuccess( $"\nThe certificates already exist - so we're going to use them.\n" ); 64 | System.Threading.Thread.Sleep( 1000 ); 65 | log.WriteSuccess( $"If you want to generate new certificates delete the Certs folder.\n\n" ); 66 | System.Threading.Thread.Sleep( 1000 ); 67 | return true; 68 | } 69 | 70 | if ( !System.IO.File.Exists( Constants.OpenSslExe ) ) 71 | { 72 | log.WriteError( $"Couldn't find {Constants.OpenSslExe} - do you have composer installed?" ); 73 | return false; 74 | } 75 | 76 | if ( !System.IO.File.Exists( Constants.OpenSslConfig ) ) 77 | { 78 | log.WriteError( $"Couldn't find {Constants.OpenSslConfig} - do you have composer installed?" ); 79 | return false; 80 | } 81 | 82 | if ( !System.IO.Directory.Exists( "Certs" ) ) 83 | { 84 | log.WriteTrace( "Creating Certs Folder\n" ); 85 | System.IO.Directory.CreateDirectory( "Certs" ); 86 | } 87 | 88 | // 89 | // generate a self signed private and public key 90 | // 91 | log.WriteNormal( "\nGenerating private + public keys\n" ); 92 | var exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"req -new -x509 -sha256 -nodes -days {Constants.CertificateExpireDays} -newkey rsa:1024 -keyout \"Certs/private.key\" -subj \"/C=US/ST=Utah/L=Draper/O=Control4/OU=Controller Certificates/CN={Constants.CertificateCN}/\" -out \"Certs/public.pem\" -config \"{Constants.OpenSslConfig}\"" ); 93 | 94 | if ( exitCode != 0 ) 95 | { 96 | log.WriteError( $"Failed." ); 97 | return false; 98 | } 99 | 100 | // 101 | // Create the composer.p12 (public key) which sits in your composer config folder 102 | // 103 | log.WriteNormal( "Creating composer.p12\n" ); 104 | exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"pkcs12 -export -out \"Certs/composer.p12\" -inkey \"Certs/private.key\" -in \"Certs/public.pem\" -passout pass:{Constants.CertPassword}" ); 105 | 106 | if ( exitCode != 0 ) 107 | { 108 | log.WriteError( $"Failed." ); 109 | return false; 110 | } 111 | 112 | // 113 | // Get the text for the composer cacert-*.pem 114 | // 115 | log.WriteNormal( $"Creating {Constants.ComposerCertName}\n" ); 116 | var output = RunProcessGetOutput( Constants.OpenSslExe, $"x509 -in \"Certs/public.pem\" -text" ); 117 | System.IO.File.WriteAllText( $"Certs/{Constants.ComposerCertName}", output ); 118 | 119 | return true; 120 | 121 | } 122 | 123 | string RunProcessGetOutput( string exe, string arguments ) 124 | { 125 | ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments ); 126 | startInfo.CreateNoWindow = true; 127 | startInfo.UseShellExecute = false; 128 | startInfo.RedirectStandardOutput = true; 129 | 130 | var process = System.Diagnostics.Process.Start( startInfo ); 131 | 132 | return process.StandardOutput.ReadToEnd(); 133 | } 134 | 135 | int RunProcessPrintOutput( LogWindow log, string exe, string arguments ) 136 | { 137 | log.WriteNormal( System.IO.Path.GetFileName( exe ) ); 138 | log.WriteNormal( " " ); 139 | log.WriteHighlight( arguments ); 140 | log.WriteNormal( "\n" ); 141 | 142 | ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments ); 143 | startInfo.CreateNoWindow = true; 144 | startInfo.UseShellExecute = false; 145 | startInfo.RedirectStandardOutput = true; 146 | 147 | var process = System.Diagnostics.Process.Start( startInfo ); 148 | 149 | process.WaitForExit(); 150 | 151 | var text = process.StandardOutput.ReadToEnd(); 152 | 153 | log.WriteTrace( text ); 154 | 155 | log.WriteNormal( "\n" ); 156 | 157 | return process.ExitCode; 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UI/LogWindow.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UI/Composer.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | We can stop composer checking with Control4 to see if you're a dealer by adding some stuff to the ComposerPro.exe.config file. Without this you'll have to disconnect your internet every time you start Composer. 122 | 123 | -------------------------------------------------------------------------------- /UI/DirectorPatch.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | You need to restart your director for the new certifcates to kick in. You can also do this by right clicking in System Manager and going to Reboot.. 122 | 123 | It can take a few minutes for your director to come back online. It's a scary time but it'll come back. Don't do this while your wife is home because she'll be going fucking mad. 124 | 125 | -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Garry.Control4.Jailbreak.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Garry.Control4.Jailbreak.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap cup_cake { 67 | get { 68 | object obj = ResourceManager.GetObject("cup-cake", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap database { 77 | get { 78 | object obj = ResourceManager.GetObject("database", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap download { 87 | get { 88 | object obj = ResourceManager.GetObject("download", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap folder { 97 | get { 98 | object obj = ResourceManager.GetObject("folder", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 105 | /// 106 | internal static System.Drawing.Icon four { 107 | get { 108 | object obj = ResourceManager.GetObject("four", resourceCulture); 109 | return ((System.Drawing.Icon)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap loupe { 117 | get { 118 | object obj = ResourceManager.GetObject("loupe", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Byte[]. 125 | /// 126 | internal static byte[] openssl { 127 | get { 128 | object obj = ResourceManager.GetObject("openssl", resourceCulture); 129 | return ((byte[])(obj)); 130 | } 131 | } 132 | 133 | /// 134 | /// Looks up a localized resource of type System.Drawing.Bitmap. 135 | /// 136 | internal static System.Drawing.Bitmap patch { 137 | get { 138 | object obj = ResourceManager.GetObject("patch", resourceCulture); 139 | return ((System.Drawing.Bitmap)(obj)); 140 | } 141 | } 142 | 143 | /// 144 | /// Looks up a localized resource of type System.Drawing.Bitmap. 145 | /// 146 | internal static System.Drawing.Bitmap reddit { 147 | get { 148 | object obj = ResourceManager.GetObject("reddit", resourceCulture); 149 | return ((System.Drawing.Bitmap)(obj)); 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /UI/Certificates.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Lets make some certificates. 122 | 123 | This will just generate some certificates we need and put them in a Certs folder next to this exe. 124 | 125 | You only need to do this once, and we'll reuse the certificates in that folder. If you want to use Composer Pro on multiple computers, just copy this exe with the Certs folder to that computer and use this exe to copy the certificates to Composer there. 126 | 127 | We're not doing anything scary yet, but you do need composer pro installed so we can use the openssl.exe it contains. 128 | 129 | 130 | -------------------------------------------------------------------------------- /UI/Backup.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | It's a good idea to grab a copy of this certificate before you do anything and store it on dropbox, google drive, or email it to yourself incase something goes wrong. 122 | 123 | If this certificate gets messed up your dealer won't be able to connect to your system (easily). The certificate file is shared between systems so worst case you'll have to ask a friend for a copy of their backup. 124 | 125 | This file is on your director at /etc/openvpn/clientca-prod.pem - and you can download/upload it yourself using something like WinSCP. Or download it by clicking this button. 126 | 127 | -------------------------------------------------------------------------------- /UI/DirectorPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.IO; 11 | using System.Diagnostics; 12 | using Renci.SshNet; 13 | using System.Linq.Expressions; 14 | using System.Runtime.InteropServices; 15 | using System.Net; 16 | using System.Security.Cryptography; 17 | 18 | namespace Garry.Control4.Jailbreak 19 | { 20 | public partial class DirectorPatch : UserControl 21 | { 22 | MainWindow MainWindow; 23 | 24 | public DirectorPatch( MainWindow MainWindow ) 25 | { 26 | this.MainWindow = MainWindow; 27 | 28 | InitializeComponent(); 29 | } 30 | 31 | 32 | 33 | bool PatchDirector( LogWindow log ) 34 | { 35 | var SshConnectionInfo = new ConnectionInfo( Address.Text.ToString(), Username.Text, new PasswordAuthenticationMethod( Username.Text, Password.Text ) ); 36 | SshConnectionInfo.RetryAttempts = 1; 37 | SshConnectionInfo.Timeout = TimeSpan.FromSeconds( 2 ); 38 | 39 | using ( var ssh = new ScpClient( SshConnectionInfo ) ) 40 | { 41 | log.WriteNormal( $"Connecting to director via SCP.. " ); 42 | 43 | try 44 | { 45 | ssh.Connect(); 46 | } 47 | catch ( System.Exception e ) 48 | { 49 | log.WriteError( e ); 50 | return false; 51 | } 52 | 53 | log.WriteSuccess( $" .. connected!\n" ); 54 | 55 | // Get the existing certificate 56 | using ( var stream = new MemoryStream() ) 57 | { 58 | log.WriteNormal( $"Downloading /etc/openvpn/clientca-prod.pem\n" ); 59 | ssh.Download( "/etc/openvpn/clientca-prod.pem", stream ); 60 | log.WriteSuccess( $"Done - got {stream.Length} bytes\n\n" ); 61 | 62 | stream.Position = 0; 63 | 64 | var backupName = $"/etc/openvpn/clientca-prod.{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}.backup"; 65 | log.WriteNormal( $"Uploading {backupName}\n" ); 66 | ssh.Upload( stream, backupName ); 67 | log.WriteSuccess( $"Done!\n\n" ); 68 | 69 | log.WriteNormal( $"Constructing new clientca-prod.pem\n" ); 70 | using ( StreamReader reader = new StreamReader( stream ) ) 71 | { 72 | stream.Position = 0; 73 | 74 | var certificate = reader.ReadToEnd(); 75 | 76 | certificate += "\n"; 77 | 78 | log.WriteNormal( $" Reading Certs/public.pem\n" ); 79 | var localCert = System.IO.File.ReadAllText( "Certs/public.pem" ); 80 | 81 | var localBackupName = $"Certs/clientca-prod.{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}.backup"; 82 | log.WriteNormal( $" Downloading to {localBackupName}\n" ); 83 | System.IO.File.WriteAllText( localBackupName, certificate ); 84 | 85 | if ( certificate.Contains( localCert ) ) 86 | { 87 | log.WriteError( $"The certificate on the director already contains our public key!\n" ); 88 | return false; 89 | } 90 | else 91 | { 92 | // 93 | // We just add our public key to the end 94 | // 95 | certificate += localCert; 96 | } 97 | 98 | // 99 | // This serves no purpose but it doesn't hurt to have it hanging around 100 | // 101 | localBackupName += ".new"; 102 | log.WriteNormal( $" Downloading to {localBackupName}\n" ); 103 | System.IO.File.WriteAllText( localBackupName, certificate ); 104 | 105 | 106 | // 107 | // Upload the modded certificates to the director 108 | // 109 | log.WriteNormal( $"Uploading New Certificate..\n" ); 110 | using ( var wstream = new MemoryStream() ) 111 | { 112 | using ( StreamWriter writer = new StreamWriter( wstream ) ) 113 | { 114 | writer.Write( certificate ); 115 | writer.Flush(); 116 | 117 | wstream.Position = 0; 118 | ssh.Upload( wstream, "/etc/openvpn/clientca-prod.pem" ); 119 | } 120 | } 121 | 122 | log.WriteSuccess( $"Done!\n" ); 123 | } 124 | } 125 | } 126 | 127 | return true; 128 | } 129 | 130 | 131 | 132 | 133 | private void OpenSystemManager( object sender, EventArgs e ) 134 | { 135 | Process.Start( @"C:\Program Files (x86)\Control4\Composer\Pro\Sysman.exe" ); 136 | } 137 | 138 | private void PatchDirectorCertificates( object sender, EventArgs e ) 139 | { 140 | var log = new LogWindow( MainWindow ); 141 | 142 | try 143 | { 144 | 145 | log.WriteNormal( "Copying To Director\n" ); 146 | if ( !PatchDirector( log ) ) 147 | { 148 | return; 149 | } 150 | log.WriteNormal( "\n\n" ); 151 | } 152 | catch ( System.Exception ex ) 153 | { 154 | log.WriteError( ex ); 155 | } 156 | } 157 | 158 | private void OnAddressChanged( object sender, EventArgs e ) 159 | { 160 | _ = WorkoutPassword(); 161 | } 162 | 163 | async Task WorkoutPassword() 164 | { 165 | var address = Address.Text; 166 | 167 | await Task.Run( () => 168 | { 169 | var password = GetDirectorRootPassword( address ); 170 | if ( password != null ) 171 | { 172 | Invoke( (Action)( () => 173 | { 174 | if ( Address.Text == address ) 175 | { 176 | Password.Text = password; 177 | } 178 | }) ); 179 | } 180 | } 181 | ); 182 | } 183 | 184 | [DllImport( "iphlpapi.dll", ExactSpelling = true )] 185 | public static extern int SendARP( int DestIP, int SrcIP, [Out] byte[] pMacAddr, ref int PhyAddrLen ); 186 | 187 | private static string GetDirectorRootPassword( string address ) 188 | { 189 | var salt = Convert.FromBase64String( "STlqJGd1fTkjI25CWz1hK1YuMURseXA/UnU5QGp6cF4=" ); 190 | 191 | try 192 | { 193 | var hostIPAddress = IPAddress.Parse( address ); 194 | var ab = new byte[6]; 195 | int len = ab.Length; 196 | var r = SendARP( (int)hostIPAddress.Address, 0, ab, ref len ); 197 | if ( r != 0 ) return null; 198 | var macAddress = BitConverter.ToString( ab, 0, 6 ).Replace( "-", "" ); 199 | 200 | var password = Convert.ToBase64String( new Rfc2898DeriveBytes( macAddress, salt, macAddress.Length * 397, HashAlgorithmName.SHA384 ).GetBytes( 33 ) ); 201 | return password; 202 | } 203 | catch ( System.Exception ) 204 | { 205 | return null; 206 | } 207 | } 208 | 209 | private void RebootDirector( object sender, EventArgs e ) 210 | { 211 | var log = new LogWindow( MainWindow ); 212 | 213 | try 214 | { 215 | var SshConnectionInfo = new ConnectionInfo( Address.Text.ToString(), Username.Text, new PasswordAuthenticationMethod( Username.Text, Password.Text ) ); 216 | SshConnectionInfo.RetryAttempts = 1; 217 | SshConnectionInfo.Timeout = TimeSpan.FromSeconds( 5 ); 218 | 219 | log.WriteTrace( "Connecting To Director..\n" ); 220 | 221 | using ( var ssh = new SshClient( SshConnectionInfo ) ) 222 | { 223 | ssh.Connect(); 224 | 225 | log.WriteTrace( "Connected!\n" ); 226 | 227 | log.WriteTrace( "Running Reboot Command..\n" ); 228 | var r = ssh.RunCommand( "reboot" ); 229 | log.WriteTrace( $"Response Was: {r.Result}\n" ); 230 | 231 | log.WriteSuccess( $"Your system is rebooting - it can take a while - don't panic, give it 10 minutes!" ); 232 | } 233 | } 234 | catch ( System.Exception ex ) 235 | { 236 | log.WriteError( ex ); 237 | } 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /UI/Composer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.IO; 11 | using System.Diagnostics; 12 | 13 | namespace Garry.Control4.Jailbreak 14 | { 15 | public partial class Composer : UserControl 16 | { 17 | const string NewExtension = ".modded.exe"; 18 | 19 | MainWindow MainWindow; 20 | 21 | public Composer( MainWindow MainWindow ) 22 | { 23 | this.MainWindow = MainWindow; 24 | 25 | InitializeComponent(); 26 | } 27 | 28 | private void PatchComposer( object sender, EventArgs eventargs ) 29 | { 30 | var oldLine = @" 31 | 32 | 33 | 34 | "; 35 | var newLine = @" 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | "; 45 | 46 | var log = new LogWindow( MainWindow ); 47 | 48 | log.WriteTrace( "Asking for ComposerPro.exe.config location\n" ); 49 | 50 | OpenFileDialog open = new OpenFileDialog(); 51 | open.Filter = "Config Files|*.config"; 52 | open.Title = "Find Original ComposerPro.exe.config"; 53 | open.InitialDirectory = "C:\\Program Files (x86)\\Control4\\Composer\\Pro"; 54 | open.FileName = "ComposerPro.exe.config"; 55 | 56 | if ( open.ShowDialog() != DialogResult.OK ) 57 | { 58 | log.WriteError( "Cancelled\n" ); 59 | return; 60 | } 61 | 62 | if ( string.IsNullOrEmpty( open.FileName ) ) 63 | { 64 | log.WriteError( "Filename was invalid\n" ); 65 | return; 66 | } 67 | 68 | log.WriteNormal( "Opening " ); 69 | log.WriteHighlight( $"{open.FileName}\n" ); 70 | 71 | var contents = System.IO.File.ReadAllText( open.FileName ); 72 | 73 | if ( !contents.Contains( oldLine ) ) 74 | { 75 | log.WriteHighlight( "Couldn't find the line - probably already patched??" ); 76 | return; 77 | } 78 | 79 | log.WriteHighlight( $"Writing Backup..\n" ); 80 | System.IO.File.WriteAllText( open.FileName + $".backup-{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}", contents ); 81 | 82 | log.WriteHighlight( $"Writing New File..\n" ); 83 | contents = contents.Replace( oldLine, newLine ); 84 | 85 | System.IO.File.WriteAllText( open.FileName, contents ); 86 | log.WriteHighlight( $"Done!\n" ); 87 | } 88 | 89 | private void SearchGoogleForComposer( object sender, EventArgs e ) 90 | { 91 | System.Diagnostics.Process.Start( $"https://www.google.com/search?q=ComposerPro-3.1.3.574885-res.exe" ); 92 | } 93 | 94 | private void OpenControl4Reddit( object sender, EventArgs e ) 95 | { 96 | System.Diagnostics.Process.Start( $"https://www.reddit.com/r/C4diy/" ); 97 | } 98 | 99 | private void UpdateCertificates( object sender, EventArgs e ) 100 | { 101 | var log = new LogWindow( MainWindow ); 102 | 103 | try 104 | { 105 | log.WriteNormal( "Copying To Composer\n" ); 106 | UpdateComposerCertificate( log ); 107 | } 108 | catch ( System.Exception ex ) 109 | { 110 | log.WriteError( ex ); 111 | } 112 | } 113 | 114 | 115 | bool UpdateComposerCertificate( LogWindow log ) 116 | { 117 | var configFolder = $"{Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData )}\\Control4\\Composer"; 118 | 119 | log.WriteNormal( "\nCreating new Composer Key\n" ); 120 | var exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"genrsa -out Certs/composer.key 1024 -config \"{Constants.OpenSslConfig}\"" ); 121 | 122 | if ( exitCode != 0 ) 123 | { 124 | log.WriteError( $"Failed." ); 125 | return false; 126 | } 127 | 128 | log.WriteNormal( "\nCreating Signing Request\n" ); 129 | exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"req -new -nodes -key Certs/composer.key -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -out Certs/composer.csr -config \"{Constants.OpenSslConfig}\"" ); 130 | 131 | if ( exitCode != 0 ) 132 | { 133 | log.WriteError( $"Failed." ); 134 | return false; 135 | } 136 | 137 | System.IO.Directory.CreateDirectory( "ca" ); 138 | System.IO.Directory.CreateDirectory( "ca/newcerts" ); 139 | System.IO.File.WriteAllText( "ca/index.txt", "" ); 140 | 141 | log.WriteNormal( "\nSigning Request\n" ); 142 | exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"ca -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -preserveDN -days 365 -batch -create_serial -cert Certs/public.pem -keyfile Certs/private.key -out Certs/composer.pem -in Certs/composer.csr -config \"{Constants.OpenSslConfig}\"" ); 143 | 144 | if ( exitCode != 0 ) 145 | { 146 | log.WriteError( $"Failed." ); 147 | return false; 148 | } 149 | 150 | // 151 | // Create the composer.p12 (public key) which sits in your composer config folder 152 | // 153 | log.WriteNormal( "Creating composer.p12\n" ); 154 | exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"pkcs12 -export -out \"Certs/composer.p12\" -inkey \"Certs/composer.key\" -in \"Certs/composer.pem\" -passout pass:{Constants.CertPassword}" ); 155 | 156 | if ( exitCode != 0 ) 157 | { 158 | log.WriteError( $"Failed." ); 159 | return false; 160 | } 161 | 162 | // 163 | // Get the text for the composer cacert-*.pem 164 | // 165 | log.WriteNormal( $"Creating {Constants.ComposerCertName}\n" ); 166 | var output = RunProcessGetOutput( Constants.OpenSslExe, $"x509 -in \"Certs/public.pem\" -text" ); 167 | System.IO.File.WriteAllText( $"Certs/{Constants.ComposerCertName}", output ); 168 | 169 | CopyFile( log, $"Certs/{Constants.ComposerCertName}", $"{configFolder}\\{Constants.ComposerCertName}" ); 170 | CopyFile( log, $"Certs/composer.p12", $"{configFolder}\\composer.p12" ); 171 | 172 | log.WriteNormal( "\n\n" ); 173 | log.WriteSuccess( "Success - composer should be good for 30 days\n\n" ); 174 | log.WriteSuccess( "Once it starts complaining that you had x days left to renew, just run this step again\n\n" ); 175 | log.WriteSuccess( "You shouldn't need to patch your Director again unless you update to a new version or delete the Certs folder next to this exe.\n\n" ); 176 | 177 | return true; 178 | } 179 | 180 | private void CopyFile( LogWindow log, string a, string b ) 181 | { 182 | log.WriteNormal( $"Copying " ); 183 | log.WriteHighlight( a ); 184 | log.WriteNormal( $" to " ); 185 | log.WriteHighlight( b ); 186 | log.WriteNormal( $"\n" ); 187 | 188 | System.IO.File.Copy( a, b, true ); 189 | } 190 | 191 | int RunProcessPrintOutput( LogWindow log, string exe, string arguments ) 192 | { 193 | log.WriteNormal( System.IO.Path.GetFileName( exe ) ); 194 | log.WriteNormal( " " ); 195 | log.WriteHighlight( arguments ); 196 | log.WriteNormal( "\n" ); 197 | 198 | ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments ); 199 | startInfo.WorkingDirectory = Environment.CurrentDirectory; 200 | startInfo.CreateNoWindow = true; 201 | startInfo.UseShellExecute = false; 202 | startInfo.RedirectStandardOutput = true; 203 | startInfo.RedirectStandardError = true; 204 | 205 | var process = System.Diagnostics.Process.Start( startInfo ); 206 | 207 | log.WriteTrace( process.StandardOutput.ReadToEnd() ); 208 | log.WriteTrace( process.StandardError.ReadToEnd() ); 209 | 210 | process.WaitForExit(); 211 | 212 | log.WriteTrace( process.StandardError.ReadToEnd() ); 213 | log.WriteTrace( process.StandardOutput.ReadToEnd() ); 214 | 215 | log.WriteNormal( "\n" ); 216 | 217 | return process.ExitCode; 218 | } 219 | 220 | string RunProcessGetOutput( string exe, string arguments ) 221 | { 222 | ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments ); 223 | startInfo.CreateNoWindow = true; 224 | startInfo.UseShellExecute = false; 225 | startInfo.RedirectStandardOutput = true; 226 | 227 | var process = System.Diagnostics.Process.Start( startInfo ); 228 | 229 | return process.StandardOutput.ReadToEnd(); 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\patch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\cup-cake.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\four.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\loupe.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | ..\Resources\reddit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | ..\Resources\download.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | 143 | ..\Resources\database.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 144 | 145 | 146 | ..\Resources\openssl.cfg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 147 | 148 | -------------------------------------------------------------------------------- /Control4.Jailbreak.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {ABA795E1-3A9C-4EF2-BDF5-C4ACAE48670F} 8 | WinExe 9 | Garry.Control4.Jailbreak 10 | C4Jailbreak 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | AnyCPU 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | app.manifest 53 | 54 | 55 | Resources\four.ico 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | packages\SSH.NET.2020.0.1\lib\net40\Renci.SshNet.dll 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | True 84 | True 85 | Resources.resx 86 | 87 | 88 | UserControl 89 | 90 | 91 | Certificates.cs 92 | 93 | 94 | UserControl 95 | 96 | 97 | DirectorPatch.cs 98 | 99 | 100 | UserControl 101 | 102 | 103 | 104 | UserControl 105 | 106 | 107 | Composer.cs 108 | 109 | 110 | UserControl 111 | 112 | 113 | Backup.cs 114 | 115 | 116 | Form 117 | 118 | 119 | LogWindow.cs 120 | 121 | 122 | Form 123 | 124 | 125 | MainWindow.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | Certificates.cs 137 | 138 | 139 | DirectorPatch.cs 140 | 141 | 142 | Composer.cs 143 | 144 | 145 | Backup.cs 146 | 147 | 148 | LogWindow.cs 149 | 150 | 151 | MainWindow.cs 152 | 153 | 154 | ResXFileCodeGenerator 155 | Designer 156 | Resources.Designer.cs 157 | 158 | 159 | 160 | 161 | SettingsSingleFileGenerator 162 | Settings.Designer.cs 163 | 164 | 165 | True 166 | Settings.settings 167 | True 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | False 186 | Microsoft .NET Framework 4.7.2 %28x86 and x64%29 187 | true 188 | 189 | 190 | False 191 | .NET Framework 3.5 SP1 192 | false 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /UI/DirectorPatch.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class DirectorPatch 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DirectorPatch)); 32 | this.label6 = new System.Windows.Forms.Label(); 33 | this.label7 = new System.Windows.Forms.Label(); 34 | this.button4 = new System.Windows.Forms.Button(); 35 | this.Password = new System.Windows.Forms.TextBox(); 36 | this.Username = new System.Windows.Forms.TextBox(); 37 | this.Address = new System.Windows.Forms.TextBox(); 38 | this.label10 = new System.Windows.Forms.Label(); 39 | this.label11 = new System.Windows.Forms.Label(); 40 | this.label12 = new System.Windows.Forms.Label(); 41 | this.label13 = new System.Windows.Forms.Label(); 42 | this.label14 = new System.Windows.Forms.Label(); 43 | this.button1 = new System.Windows.Forms.Button(); 44 | this.SuspendLayout(); 45 | // 46 | // label6 47 | // 48 | this.label6.AutoSize = true; 49 | this.label6.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold); 50 | this.label6.ForeColor = System.Drawing.SystemColors.Highlight; 51 | this.label6.Location = new System.Drawing.Point(12, 16); 52 | this.label6.Name = "label6"; 53 | this.label6.Size = new System.Drawing.Size(276, 30); 54 | this.label6.TabIndex = 16; 55 | this.label6.Text = "DIRECTOR CERTIFICATE"; 56 | // 57 | // label7 58 | // 59 | this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 60 | | System.Windows.Forms.AnchorStyles.Right))); 61 | this.label7.Location = new System.Drawing.Point(16, 74); 62 | this.label7.Name = "label7"; 63 | this.label7.Size = new System.Drawing.Size(466, 63); 64 | this.label7.TabIndex = 17; 65 | this.label7.Text = "If you created a user we\'ll be able to patch the director with the new certificat" + 66 | "e.\r\n\r\nWe can work out the password to your director, just make sure the Address " + 67 | "is correct!\r\n"; 68 | // 69 | // button4 70 | // 71 | this.button4.Image = global::Garry.Control4.Jailbreak.Properties.Resources.cup_cake; 72 | this.button4.Location = new System.Drawing.Point(297, 179); 73 | this.button4.Name = "button4"; 74 | this.button4.Size = new System.Drawing.Size(185, 34); 75 | this.button4.TabIndex = 18; 76 | this.button4.Text = "Patch Director Certificates"; 77 | this.button4.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 78 | this.button4.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 79 | this.button4.UseVisualStyleBackColor = true; 80 | this.button4.Click += new System.EventHandler(this.PatchDirectorCertificates); 81 | // 82 | // Password 83 | // 84 | this.Password.Location = new System.Drawing.Point(245, 153); 85 | this.Password.Name = "Password"; 86 | this.Password.Size = new System.Drawing.Size(237, 20); 87 | this.Password.TabIndex = 22; 88 | this.Password.Text = "jailbreak"; 89 | // 90 | // Username 91 | // 92 | this.Username.Location = new System.Drawing.Point(152, 153); 93 | this.Username.Name = "Username"; 94 | this.Username.Size = new System.Drawing.Size(87, 20); 95 | this.Username.TabIndex = 23; 96 | this.Username.Text = "root"; 97 | // 98 | // Address 99 | // 100 | this.Address.Location = new System.Drawing.Point(16, 153); 101 | this.Address.Name = "Address"; 102 | this.Address.Size = new System.Drawing.Size(130, 20); 103 | this.Address.TabIndex = 24; 104 | this.Address.Text = "127.0.0.1"; 105 | this.Address.TextChanged += new System.EventHandler(this.OnAddressChanged); 106 | // 107 | // label10 108 | // 109 | this.label10.AutoSize = true; 110 | this.label10.Location = new System.Drawing.Point(17, 137); 111 | this.label10.Name = "label10"; 112 | this.label10.Size = new System.Drawing.Size(45, 13); 113 | this.label10.TabIndex = 25; 114 | this.label10.Text = "Address"; 115 | // 116 | // label11 117 | // 118 | this.label11.AutoSize = true; 119 | this.label11.Location = new System.Drawing.Point(149, 137); 120 | this.label11.Name = "label11"; 121 | this.label11.Size = new System.Drawing.Size(55, 13); 122 | this.label11.TabIndex = 26; 123 | this.label11.Text = "Username"; 124 | // 125 | // label12 126 | // 127 | this.label12.AutoSize = true; 128 | this.label12.Location = new System.Drawing.Point(242, 137); 129 | this.label12.Name = "label12"; 130 | this.label12.Size = new System.Drawing.Size(53, 13); 131 | this.label12.TabIndex = 27; 132 | this.label12.Text = "Password"; 133 | // 134 | // label13 135 | // 136 | this.label13.AutoSize = true; 137 | this.label13.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold); 138 | this.label13.ForeColor = System.Drawing.SystemColors.Highlight; 139 | this.label13.Location = new System.Drawing.Point(12, 243); 140 | this.label13.Name = "label13"; 141 | this.label13.Size = new System.Drawing.Size(235, 30); 142 | this.label13.TabIndex = 28; 143 | this.label13.Text = "RESTART DIRECTOR"; 144 | // 145 | // label14 146 | // 147 | this.label14.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 148 | | System.Windows.Forms.AnchorStyles.Right))); 149 | this.label14.Location = new System.Drawing.Point(17, 283); 150 | this.label14.Name = "label14"; 151 | this.label14.Size = new System.Drawing.Size(466, 71); 152 | this.label14.TabIndex = 29; 153 | this.label14.Text = resources.GetString("label14.Text"); 154 | // 155 | // button1 156 | // 157 | this.button1.Location = new System.Drawing.Point(297, 380); 158 | this.button1.Name = "button1"; 159 | this.button1.Size = new System.Drawing.Size(185, 34); 160 | this.button1.TabIndex = 30; 161 | this.button1.Text = "Reboot Director"; 162 | this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 163 | this.button1.UseVisualStyleBackColor = true; 164 | this.button1.Click += new System.EventHandler(this.RebootDirector); 165 | // 166 | // DirectorPatch 167 | // 168 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 169 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 170 | this.BackColor = System.Drawing.SystemColors.Window; 171 | this.Controls.Add(this.button1); 172 | this.Controls.Add(this.label14); 173 | this.Controls.Add(this.label13); 174 | this.Controls.Add(this.label12); 175 | this.Controls.Add(this.label11); 176 | this.Controls.Add(this.label10); 177 | this.Controls.Add(this.Address); 178 | this.Controls.Add(this.Username); 179 | this.Controls.Add(this.Password); 180 | this.Controls.Add(this.button4); 181 | this.Controls.Add(this.label7); 182 | this.Controls.Add(this.label6); 183 | this.Name = "DirectorPatch"; 184 | this.Size = new System.Drawing.Size(500, 443); 185 | this.ResumeLayout(false); 186 | this.PerformLayout(); 187 | 188 | } 189 | 190 | #endregion 191 | private System.Windows.Forms.Label label6; 192 | private System.Windows.Forms.Label label7; 193 | private System.Windows.Forms.Button button4; 194 | private System.Windows.Forms.TextBox Password; 195 | private System.Windows.Forms.TextBox Username; 196 | private System.Windows.Forms.Label label10; 197 | private System.Windows.Forms.Label label11; 198 | private System.Windows.Forms.Label label12; 199 | public System.Windows.Forms.TextBox Address; 200 | private System.Windows.Forms.Label label13; 201 | private System.Windows.Forms.Label label14; 202 | private System.Windows.Forms.Button button1; 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /UI/Composer.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class Composer 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Composer)); 32 | this.label4 = new System.Windows.Forms.Label(); 33 | this.label2 = new System.Windows.Forms.Label(); 34 | this.label5 = new System.Windows.Forms.Label(); 35 | this.label3 = new System.Windows.Forms.Label(); 36 | this.button3 = new System.Windows.Forms.Button(); 37 | this.button1 = new System.Windows.Forms.Button(); 38 | this.button2 = new System.Windows.Forms.Button(); 39 | this.button5 = new System.Windows.Forms.Button(); 40 | this.label8 = new System.Windows.Forms.Label(); 41 | this.label9 = new System.Windows.Forms.Label(); 42 | this.SuspendLayout(); 43 | // 44 | // label4 45 | // 46 | this.label4.AutoSize = true; 47 | this.label4.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold); 48 | this.label4.ForeColor = System.Drawing.SystemColors.Highlight; 49 | this.label4.Location = new System.Drawing.Point(13, 177); 50 | this.label4.Name = "label4"; 51 | this.label4.Size = new System.Drawing.Size(237, 30); 52 | this.label4.TabIndex = 3; 53 | this.label4.Text = "COMPOSER CONFIG"; 54 | // 55 | // label2 56 | // 57 | this.label2.AutoSize = true; 58 | this.label2.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold); 59 | this.label2.ForeColor = System.Drawing.SystemColors.Highlight; 60 | this.label2.Location = new System.Drawing.Point(13, 28); 61 | this.label2.Name = "label2"; 62 | this.label2.Size = new System.Drawing.Size(304, 30); 63 | this.label2.TabIndex = 7; 64 | this.label2.Text = "GETTING COMPOSER PRO"; 65 | // 66 | // label5 67 | // 68 | this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 69 | | System.Windows.Forms.AnchorStyles.Right))); 70 | this.label5.Location = new System.Drawing.Point(19, 71); 71 | this.label5.Name = "label5"; 72 | this.label5.Size = new System.Drawing.Size(330, 80); 73 | this.label5.TabIndex = 8; 74 | this.label5.Text = "The Composer version should match the version of your system.\r\n\r\nIt doesn\'t feel " + 75 | "right linking to Composer Pro downloads but they\'re quite easy to find if you kn" + 76 | "ow the filename. "; 77 | // 78 | // label3 79 | // 80 | this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 81 | | System.Windows.Forms.AnchorStyles.Right))); 82 | this.label3.Location = new System.Drawing.Point(15, 221); 83 | this.label3.Name = "label3"; 84 | this.label3.Size = new System.Drawing.Size(463, 45); 85 | this.label3.TabIndex = 4; 86 | this.label3.Text = resources.GetString("label3.Text"); 87 | // 88 | // button3 89 | // 90 | this.button3.Anchor = System.Windows.Forms.AnchorStyles.None; 91 | this.button3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 92 | this.button3.Image = global::Garry.Control4.Jailbreak.Properties.Resources.reddit; 93 | this.button3.Location = new System.Drawing.Point(355, 114); 94 | this.button3.Name = "button3"; 95 | this.button3.Size = new System.Drawing.Size(123, 37); 96 | this.button3.TabIndex = 10; 97 | this.button3.Text = " r/c4diy"; 98 | this.button3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 99 | this.button3.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 100 | this.button3.UseVisualStyleBackColor = true; 101 | this.button3.Click += new System.EventHandler(this.OpenControl4Reddit); 102 | // 103 | // button1 104 | // 105 | this.button1.Anchor = System.Windows.Forms.AnchorStyles.None; 106 | this.button1.Image = global::Garry.Control4.Jailbreak.Properties.Resources.loupe; 107 | this.button1.Location = new System.Drawing.Point(355, 71); 108 | this.button1.Name = "button1"; 109 | this.button1.Size = new System.Drawing.Size(123, 37); 110 | this.button1.TabIndex = 9; 111 | this.button1.Text = " Search Google"; 112 | this.button1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 113 | this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 114 | this.button1.UseVisualStyleBackColor = true; 115 | this.button1.Click += new System.EventHandler(this.SearchGoogleForComposer); 116 | // 117 | // button2 118 | // 119 | this.button2.Anchor = System.Windows.Forms.AnchorStyles.None; 120 | this.button2.AutoSize = true; 121 | this.button2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 122 | this.button2.Image = global::Garry.Control4.Jailbreak.Properties.Resources.patch; 123 | this.button2.Location = new System.Drawing.Point(349, 269); 124 | this.button2.Name = "button2"; 125 | this.button2.Padding = new System.Windows.Forms.Padding(8); 126 | this.button2.Size = new System.Drawing.Size(129, 39); 127 | this.button2.TabIndex = 5; 128 | this.button2.Text = "Patch Config File"; 129 | this.button2.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 130 | this.button2.UseVisualStyleBackColor = true; 131 | this.button2.Click += new System.EventHandler(this.PatchComposer); 132 | // 133 | // button5 134 | // 135 | this.button5.Anchor = System.Windows.Forms.AnchorStyles.None; 136 | this.button5.Image = global::Garry.Control4.Jailbreak.Properties.Resources.cup_cake; 137 | this.button5.Location = new System.Drawing.Point(349, 420); 138 | this.button5.Name = "button5"; 139 | this.button5.Size = new System.Drawing.Size(129, 34); 140 | this.button5.TabIndex = 24; 141 | this.button5.Text = "Update Certificates"; 142 | this.button5.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 143 | this.button5.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 144 | this.button5.UseVisualStyleBackColor = true; 145 | this.button5.Click += new System.EventHandler(this.UpdateCertificates); 146 | // 147 | // label8 148 | // 149 | this.label8.Location = new System.Drawing.Point(15, 366); 150 | this.label8.Name = "label8"; 151 | this.label8.Size = new System.Drawing.Size(468, 40); 152 | this.label8.TabIndex = 23; 153 | this.label8.Text = "Your Composer needs to have a certificate matching the one on your Director in or" + 154 | "der to connect. So lets copy the certificate we generated into your composer con" + 155 | "fig folder so it does."; 156 | // 157 | // label9 158 | // 159 | this.label9.AutoSize = true; 160 | this.label9.Font = new System.Drawing.Font("Microsoft YaHei", 16F, System.Drawing.FontStyle.Bold); 161 | this.label9.ForeColor = System.Drawing.SystemColors.Highlight; 162 | this.label9.Location = new System.Drawing.Point(13, 322); 163 | this.label9.Name = "label9"; 164 | this.label9.Size = new System.Drawing.Size(291, 30); 165 | this.label9.TabIndex = 22; 166 | this.label9.Text = "COMPOSER CERTIFICATE"; 167 | // 168 | // Composer 169 | // 170 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 171 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 172 | this.BackColor = System.Drawing.SystemColors.Window; 173 | this.Controls.Add(this.button5); 174 | this.Controls.Add(this.label8); 175 | this.Controls.Add(this.label9); 176 | this.Controls.Add(this.button3); 177 | this.Controls.Add(this.button1); 178 | this.Controls.Add(this.label5); 179 | this.Controls.Add(this.label2); 180 | this.Controls.Add(this.label3); 181 | this.Controls.Add(this.button2); 182 | this.Controls.Add(this.label4); 183 | this.Name = "Composer"; 184 | this.Size = new System.Drawing.Size(500, 480); 185 | this.ResumeLayout(false); 186 | this.PerformLayout(); 187 | 188 | } 189 | 190 | #endregion 191 | private System.Windows.Forms.Label label4; 192 | private System.Windows.Forms.Button button2; 193 | private System.Windows.Forms.Label label2; 194 | private System.Windows.Forms.Label label5; 195 | private System.Windows.Forms.Button button1; 196 | private System.Windows.Forms.Button button3; 197 | private System.Windows.Forms.Label label3; 198 | private System.Windows.Forms.Button button5; 199 | private System.Windows.Forms.Label label8; 200 | private System.Windows.Forms.Label label9; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /UI/MainWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Garry.Control4.Jailbreak 2 | { 3 | partial class MainWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if ( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); 32 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 33 | this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 34 | this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.foldersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.composerFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.composerSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.rc4diyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.splitContainer3 = new System.Windows.Forms.SplitContainer(); 42 | this.TabControl = new System.Windows.Forms.TabControl(); 43 | this.tabPage1 = new System.Windows.Forms.TabPage(); 44 | this.tabPage2 = new System.Windows.Forms.TabPage(); 45 | this.StatusTextLeft = new System.Windows.Forms.Label(); 46 | this.StatusTextRight = new System.Windows.Forms.Label(); 47 | this.menuStrip1.SuspendLayout(); 48 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); 49 | this.splitContainer3.Panel1.SuspendLayout(); 50 | this.splitContainer3.Panel2.SuspendLayout(); 51 | this.splitContainer3.SuspendLayout(); 52 | this.TabControl.SuspendLayout(); 53 | this.SuspendLayout(); 54 | // 55 | // menuStrip1 56 | // 57 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 58 | this.fileToolStripMenuItem, 59 | this.foldersToolStripMenuItem, 60 | this.helpToolStripMenuItem}); 61 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 62 | this.menuStrip1.Name = "menuStrip1"; 63 | this.menuStrip1.Size = new System.Drawing.Size(504, 24); 64 | this.menuStrip1.TabIndex = 1; 65 | this.menuStrip1.Text = "menuStrip1"; 66 | // 67 | // fileToolStripMenuItem 68 | // 69 | this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 70 | this.quitToolStripMenuItem}); 71 | this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; 72 | this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); 73 | this.fileToolStripMenuItem.Text = "File"; 74 | // 75 | // quitToolStripMenuItem 76 | // 77 | this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; 78 | this.quitToolStripMenuItem.Size = new System.Drawing.Size(97, 22); 79 | this.quitToolStripMenuItem.Text = "Quit"; 80 | this.quitToolStripMenuItem.Click += new System.EventHandler(this.FileAndQuit); 81 | // 82 | // foldersToolStripMenuItem 83 | // 84 | this.foldersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 85 | this.composerFolderToolStripMenuItem, 86 | this.composerSettingsToolStripMenuItem}); 87 | this.foldersToolStripMenuItem.Name = "foldersToolStripMenuItem"; 88 | this.foldersToolStripMenuItem.Size = new System.Drawing.Size(57, 20); 89 | this.foldersToolStripMenuItem.Text = "Folders"; 90 | // 91 | // composerFolderToolStripMenuItem 92 | // 93 | this.composerFolderToolStripMenuItem.Name = "composerFolderToolStripMenuItem"; 94 | this.composerFolderToolStripMenuItem.Size = new System.Drawing.Size(174, 22); 95 | this.composerFolderToolStripMenuItem.Text = "Composer Folder"; 96 | this.composerFolderToolStripMenuItem.Click += new System.EventHandler(this.OpenComposerFolder); 97 | // 98 | // composerSettingsToolStripMenuItem 99 | // 100 | this.composerSettingsToolStripMenuItem.Name = "composerSettingsToolStripMenuItem"; 101 | this.composerSettingsToolStripMenuItem.Size = new System.Drawing.Size(174, 22); 102 | this.composerSettingsToolStripMenuItem.Text = "Composer Settings"; 103 | this.composerSettingsToolStripMenuItem.Click += new System.EventHandler(this.OpenComposerSettingsFolder); 104 | // 105 | // helpToolStripMenuItem 106 | // 107 | this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 108 | this.aboutToolStripMenuItem, 109 | this.rc4diyToolStripMenuItem}); 110 | this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; 111 | this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); 112 | this.helpToolStripMenuItem.Text = "Help"; 113 | // 114 | // aboutToolStripMenuItem 115 | // 116 | this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; 117 | this.aboutToolStripMenuItem.Size = new System.Drawing.Size(183, 22); 118 | this.aboutToolStripMenuItem.Text = "View On GitHub"; 119 | this.aboutToolStripMenuItem.Click += new System.EventHandler(this.ViewOnGithub); 120 | // 121 | // rc4diyToolStripMenuItem 122 | // 123 | this.rc4diyToolStripMenuItem.Name = "rc4diyToolStripMenuItem"; 124 | this.rc4diyToolStripMenuItem.Size = new System.Drawing.Size(183, 22); 125 | this.rc4diyToolStripMenuItem.Text = "Visit C4diy on Reddit"; 126 | this.rc4diyToolStripMenuItem.Click += new System.EventHandler(this.VisitC4Diy); 127 | // 128 | // splitContainer3 129 | // 130 | this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; 131 | this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; 132 | this.splitContainer3.IsSplitterFixed = true; 133 | this.splitContainer3.Location = new System.Drawing.Point(0, 24); 134 | this.splitContainer3.Name = "splitContainer3"; 135 | this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; 136 | // 137 | // splitContainer3.Panel1 138 | // 139 | this.splitContainer3.Panel1.Controls.Add(this.TabControl); 140 | this.splitContainer3.Panel1.Margin = new System.Windows.Forms.Padding(5); 141 | this.splitContainer3.Panel1.Padding = new System.Windows.Forms.Padding(5, 5, 5, 0); 142 | // 143 | // splitContainer3.Panel2 144 | // 145 | this.splitContainer3.Panel2.Controls.Add(this.StatusTextLeft); 146 | this.splitContainer3.Panel2.Controls.Add(this.StatusTextRight); 147 | this.splitContainer3.Panel2.Padding = new System.Windows.Forms.Padding(4); 148 | this.splitContainer3.Panel2MinSize = 20; 149 | this.splitContainer3.Size = new System.Drawing.Size(504, 537); 150 | this.splitContainer3.SplitterDistance = 511; 151 | this.splitContainer3.SplitterWidth = 1; 152 | this.splitContainer3.TabIndex = 2; 153 | // 154 | // TabControl 155 | // 156 | this.TabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 157 | | System.Windows.Forms.AnchorStyles.Left) 158 | | System.Windows.Forms.AnchorStyles.Right))); 159 | this.TabControl.Controls.Add(this.tabPage1); 160 | this.TabControl.Controls.Add(this.tabPage2); 161 | this.TabControl.Location = new System.Drawing.Point(0, 0); 162 | this.TabControl.Name = "TabControl"; 163 | this.TabControl.SelectedIndex = 0; 164 | this.TabControl.Size = new System.Drawing.Size(504, 525); 165 | this.TabControl.TabIndex = 0; 166 | // 167 | // tabPage1 168 | // 169 | this.tabPage1.Location = new System.Drawing.Point(4, 22); 170 | this.tabPage1.Name = "tabPage1"; 171 | this.tabPage1.Padding = new System.Windows.Forms.Padding(3); 172 | this.tabPage1.Size = new System.Drawing.Size(496, 499); 173 | this.tabPage1.TabIndex = 0; 174 | this.tabPage1.Text = "tabPage1"; 175 | this.tabPage1.UseVisualStyleBackColor = true; 176 | // 177 | // tabPage2 178 | // 179 | this.tabPage2.Location = new System.Drawing.Point(4, 22); 180 | this.tabPage2.Name = "tabPage2"; 181 | this.tabPage2.Padding = new System.Windows.Forms.Padding(3); 182 | this.tabPage2.Size = new System.Drawing.Size(496, 496); 183 | this.tabPage2.TabIndex = 1; 184 | this.tabPage2.Text = "tabPage2"; 185 | this.tabPage2.UseVisualStyleBackColor = true; 186 | // 187 | // StatusTextLeft 188 | // 189 | this.StatusTextLeft.AutoSize = true; 190 | this.StatusTextLeft.BackColor = System.Drawing.Color.Transparent; 191 | this.StatusTextLeft.Dock = System.Windows.Forms.DockStyle.Left; 192 | this.StatusTextLeft.Location = new System.Drawing.Point(4, 4); 193 | this.StatusTextLeft.Name = "StatusTextLeft"; 194 | this.StatusTextLeft.Size = new System.Drawing.Size(0, 13); 195 | this.StatusTextLeft.TabIndex = 0; 196 | this.StatusTextLeft.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 197 | // 198 | // StatusTextRight 199 | // 200 | this.StatusTextRight.AutoSize = true; 201 | this.StatusTextRight.BackColor = System.Drawing.Color.Transparent; 202 | this.StatusTextRight.Dock = System.Windows.Forms.DockStyle.Right; 203 | this.StatusTextRight.Location = new System.Drawing.Point(500, 4); 204 | this.StatusTextRight.Name = "StatusTextRight"; 205 | this.StatusTextRight.Size = new System.Drawing.Size(0, 13); 206 | this.StatusTextRight.TabIndex = 1; 207 | this.StatusTextRight.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 208 | // 209 | // MainWindow 210 | // 211 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 212 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 213 | this.ClientSize = new System.Drawing.Size(504, 561); 214 | this.Controls.Add(this.splitContainer3); 215 | this.Controls.Add(this.menuStrip1); 216 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 217 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 218 | this.MainMenuStrip = this.menuStrip1; 219 | this.MaximumSize = new System.Drawing.Size(520, 600); 220 | this.MinimumSize = new System.Drawing.Size(520, 600); 221 | this.Name = "MainWindow"; 222 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 223 | this.Text = "Garry\'s Control4 Jailbreak"; 224 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnFormClosed); 225 | this.menuStrip1.ResumeLayout(false); 226 | this.menuStrip1.PerformLayout(); 227 | this.splitContainer3.Panel1.ResumeLayout(false); 228 | this.splitContainer3.Panel2.ResumeLayout(false); 229 | this.splitContainer3.Panel2.PerformLayout(); 230 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); 231 | this.splitContainer3.ResumeLayout(false); 232 | this.TabControl.ResumeLayout(false); 233 | this.ResumeLayout(false); 234 | this.PerformLayout(); 235 | 236 | } 237 | 238 | #endregion 239 | private System.Windows.Forms.MenuStrip menuStrip1; 240 | private System.Windows.Forms.SplitContainer splitContainer3; 241 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; 242 | private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem; 243 | private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; 244 | private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; 245 | private System.Windows.Forms.Label StatusTextLeft; 246 | private System.Windows.Forms.Label StatusTextRight; 247 | private System.Windows.Forms.ToolStripMenuItem foldersToolStripMenuItem; 248 | private System.Windows.Forms.ToolStripMenuItem composerFolderToolStripMenuItem; 249 | private System.Windows.Forms.ToolStripMenuItem composerSettingsToolStripMenuItem; 250 | private System.Windows.Forms.ToolStripMenuItem rc4diyToolStripMenuItem; 251 | private System.Windows.Forms.TabControl TabControl; 252 | private System.Windows.Forms.TabPage tabPage1; 253 | private System.Windows.Forms.TabPage tabPage2; 254 | } 255 | } --------------------------------------------------------------------------------