>() ?? [];
12 | }
13 | else {
14 | CookieList = [];
15 | }
16 | }
17 | public static void AddCookie(SimpleCookie cookie) {
18 | if (CookieList.Contains(cookie)) {
19 | return;
20 | }
21 | CookieList.Add(cookie);
22 | File.WriteAllText(CookiesPath, CookieList.JsonSerialize());
23 | }
24 | public static void RemoveCookie(SimpleCookie cookie) {
25 | CookieList.Remove(cookie);
26 | File.WriteAllText(CookiesPath, CookieList.JsonSerialize());
27 | }
28 | }
--------------------------------------------------------------------------------
/src/YChanEx/Controls/ExtendedLinkLabel.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.controls;
3 | using System.Windows.Forms;
4 | internal class ExtendedLinkLabel : LinkLabel {
5 | ///
6 | /// Constructor
7 | ///
8 | public ExtendedLinkLabel() {
9 | this.LinkColor = System.Drawing.Color.FromArgb(0x00, 0x66, 0xCC);
10 | this.VisitedLinkColor = System.Drawing.Color.FromArgb(0x80, 0x00, 0x80);
11 | this.ActiveLinkColor = System.Drawing.Color.FromArgb(0xFF, 0x00, 0x00);
12 | }
13 |
14 | [System.Diagnostics.DebuggerStepThrough]
15 | protected override void WndProc(ref Message m) {
16 | switch (m.Msg) {
17 | case NativeMethods.WM_SETCURSOR: {
18 | NativeMethods.SetCursor(NativeMethods.HandCursor);
19 | m.Result = IntPtr.Zero;
20 | } break;
21 |
22 | default: {
23 | base.WndProc(ref m);
24 | } break;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/YChanEx/Controls/ExtendedListView.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.controls;
3 | using System.Windows.Forms;
4 | internal class ExtendedListView : ListView {
5 | protected override void OnHandleCreated(EventArgs e) {
6 | NativeMethods.SetWindowTheme(this.Handle, "explorer", null);
7 | base.OnHandleCreated(e);
8 | }
9 | public string GetColumnWidths() {
10 | System.Text.StringBuilder Output = new();
11 | for (int i = 0; i < Columns.Count; i++) {
12 | Output.Append(Columns[i].Width).Append(',');
13 | }
14 | return Output.Remove(Output.Length - 1, 1).ToString();
15 | }
16 | public void SetColumnWidths(string ColumnSizes) {
17 | string[] Values = ColumnSizes.Split(',');
18 |
19 | if (Values.Length > this.Columns.Count) {
20 | Array.Resize(ref Values, this.Columns.Count);
21 | }
22 |
23 | for (int i = 0; i < Values.Length; i++) {
24 | if (int.TryParse(Values[i], out int Width)) {
25 | this.Columns[i].Width = Width;
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/YChanEx/Enums/ChanType.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | ///
4 | /// Enumeration of the chan types available
5 | ///
6 | public enum ChanType {
7 | ///
8 | /// No chan was selected to download.
9 | ///
10 | Unsupported = -1,
11 | ///
12 | /// 4chan(nel) was selected to download.
13 | ///
14 | FourChan = 0,
15 | ///
16 | /// 420chan was selected to download.
17 | ///
18 | FourTwentyChan = 1,
19 | ///
20 | /// 7chan was selected to download.
21 | ///
22 | SevenChan = 2,
23 | ///
24 | /// 8chan was selected to download.
25 | ///
26 | EightChan = 3,
27 | ///
28 | /// 8kun was selected to download.
29 | ///
30 | EightKun = 4,
31 | ///
32 | /// fchan was selected to download.
33 | ///
34 | fchan = 5,
35 | ///
36 | /// u18chan was selected to download.
37 | ///
38 | u18chan = 6,
39 | ///
40 | /// An archival chan was selected to download.
41 | ///
42 | FoolFuuka = 7,
43 | }
--------------------------------------------------------------------------------
/src/YChanEx/Enums/FileDownloadStatus.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | ///
4 | /// Enumeration of file download status, that determines the current state of the file.
5 | ///
6 | public enum FileDownloadStatus : byte {
7 | ///
8 | /// No attempt to download the file has occurred yet.
9 | /// A download attempt will occur.
10 | ///
11 | Undownloaded = 0,
12 | ///
13 | /// The file successfully downloaded.
14 | /// No download attempt will occur for this file again.
15 | ///
16 | Downloaded = 1,
17 | ///
18 | /// The file was given a 404, and is assumed to be deleted.
19 | /// No download attempt will occur for this file again.
20 | ///
21 | FileNotFound = 2,
22 | ///
23 | /// The file was not able to be downloaded.
24 | /// A download attempt will occur.
25 | ///
26 | Error = 3,
27 | ///
28 | /// The file was removed from the thread.
29 | /// No download attempt will occur for this file again.
30 | ///
31 | RemovedFromThread = 4,
32 | }
--------------------------------------------------------------------------------
/src/YChanEx/Enums/ProxyType.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.controls;
3 | public enum ProxyType : byte {
4 | None = 0x0,
5 | HTTP = 0x1,
6 | SOCKS4 = 0x2,
7 | SOCKS4A = 0x3,
8 | SOCKS5 = 0x4,
9 | }
10 |
--------------------------------------------------------------------------------
/src/YChanEx/Enums/ThreadEvent.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | ///
4 | /// Enumeration of the thread events
5 | ///
6 | public enum ThreadEvent : int {
7 | ///
8 | /// The thread should parse the given information
9 | ///
10 | ParseForInfo = 0,
11 | ///
12 | /// The thread should start to download
13 | ///
14 | StartDownload = 1,
15 | ///
16 | /// The thread should update itself and wait until next download
17 | ///
18 | AfterDownload = 2,
19 | ///
20 | /// Restarts the download from a set state, allowing the main parse and download loop to restart.
21 | ///
22 | RestartDownload = 3,
23 | ///
24 | /// The thread should abort because the user requested it
25 | ///
26 | AbortDownload = 4,
27 | ///
28 | /// The thread should retry because the user requested it
29 | ///
30 | RetryDownload = 5,
31 | ///
32 | /// The thread is being reloaded from a saved file.
33 | ///
34 | ReloadThread = 6,
35 |
36 | ///
37 | /// The thread should abort because the application is closing.
38 | ///
39 | AbortForClosing = 999
40 | }
--------------------------------------------------------------------------------
/src/YChanEx/Enums/ThreadState.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | public enum ThreadState : byte {
4 | ///
5 | /// The thread was alive when it was saved.
6 | ///
7 | ThreadIsAlive = 0x0,
8 | ///
9 | /// The thread 404'd
10 | ///
11 | ThreadIs404 = 0x1,
12 | ///
13 | /// The thread was aborted.
14 | ///
15 | ThreadIsAborted = 0x2,
16 | ///
17 | /// The thread was archived.
18 | ///
19 | ThreadIsArchived = 0x3,
20 | }
21 |
--------------------------------------------------------------------------------
/src/YChanEx/Enums/ThreadStatus.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | ///
4 | /// Enumeration of the various thread statuses available
5 | ///
6 | public enum ThreadStatus : ushort {
7 | ///
8 | /// The thread has an unknown status.
9 | ///
10 | NoStatusSet = 0,
11 |
12 | ///
13 | /// The thread is waiting for the delay to rescan.
14 | ///
15 | Waiting = 1,
16 | ///
17 | /// The thread us currently scanning for files.
18 | ///
19 | ThreadScanning = 2,
20 | ///
21 | /// The thread is currently downloading files.
22 | ///
23 | ThreadDownloading = 3,
24 | ///
25 | /// The thread was not modified since last scan.
26 | ///
27 | ThreadNotModified = 4,
28 | ///
29 | /// The file from the thread has 404'd.
30 | ///
31 | ThreadFile404 = 5,
32 | ///
33 | /// The thread is not allowed to view the content.
34 | ///
35 | ThreadIsNotAllowed = 6,
36 | ///
37 | /// The thread is reloading into memory.
38 | ///
39 | ThreadReloaded = 7,
40 |
41 | ///
42 | /// The thread 404'd
43 | ///
44 | ThreadIs404 = 100,
45 | ///
46 | /// The thread was aborted.
47 | ///
48 | ThreadIsAborted = 101,
49 | ///
50 | /// The thread was archived.
51 | ///
52 | ThreadIsArchived = 102,
53 | ///
54 | /// The thread is going to scan soon.
55 | ///
56 | ThreadScanningSoon = 103,
57 | ///
58 | /// Thread is requesting to update the name
59 | ///
60 | ThreadUpdateName = 104,
61 |
62 | ///
63 | /// The thread information wasn't given when the thread download started.
64 | ///
65 | ThreadInfoNotSet = 200,
66 | ///
67 | /// The thread is retrying the download.
68 | ///
69 | ThreadRetrying = 201,
70 | ///
71 | /// The thread wasn't downloaded properly.
72 | ///
73 | ThreadImproperlyDownloaded = 202,
74 | ///
75 | /// The thread does not have any posts.
76 | ///
77 | NoThreadPosts = 203,
78 | ///
79 | /// The thread could not be parseed.
80 | ///
81 | FailedToParseThreadHtml = 204,
82 | ///
83 | /// The thread encountered an unknown error.
84 | ///
85 | ThreadUnknownError = 205,
86 | ///
87 | /// The thread encountered an exception that wasn't handled.
88 | ///
89 | ThreadUnhandledException = 206,
90 | }
91 |
--------------------------------------------------------------------------------
/src/YChanEx/Forms/frmAbout.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | using System;
4 | using System.Diagnostics;
5 | using System.Windows.Forms;
6 | using murrty.classes;
7 |
8 | public partial class frmAbout : Form {
9 | private const string BodyText = """
10 | ychanex by murrty
11 | build date {0}
12 |
13 | Shrim heals me
14 |
15 | do it for likulau
16 | """;
17 | private Task UpdateTask = Task.CompletedTask;
18 |
19 | public frmAbout() {
20 | InitializeComponent();
21 | pbIcon.Image = Properties.Resources.AboutImage;
22 | pbIcon.Cursor = new Cursor(NativeMethods.LoadCursor(0, NativeMethods.IDC_HAND));
23 | lbVersion.Text = $"v{Program.CurrentVersion}{(Program.DebugMode ? " (deubg)" : "")}";
24 | lbBody.Text = string.Format(BodyText, Properties.Resources.BuildDate);
25 | }
26 |
27 | private async Task CheckUpdate() {
28 | try {
29 | var result = await Updater.CheckForUpdate(true);
30 | if (result == null) {
31 | Log.Warn("could not get update.");
32 | MessageBox.Show("Could not find update.");
33 | return;
34 | }
35 |
36 | if (result == true) {
37 | Updater.ShowUpdateForm(false);
38 | }
39 | else {
40 | MessageBox.Show("No update is available.");
41 | }
42 | }
43 | catch {
44 | Log.Warn("could not get update.");
45 | MessageBox.Show("Could not find update.");
46 | }
47 | }
48 | private void llbCheckForUpdates_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
49 | if (!UpdateTask.IsCompleted) {
50 | return;
51 | }
52 | UpdateTask = CheckUpdate();
53 | }
54 | private void pbIcon_Click(object sender, EventArgs e) {
55 | Process.Start(Program.GithubPage);
56 | }
57 | private void llbGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
58 | Process.Start(Program.GithubPage);
59 | }
60 | }
--------------------------------------------------------------------------------
/src/YChanEx/Forms/frmAddCookie.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | using System;
4 | using System.Net;
5 | using System.Windows.Forms;
6 | public partial class frmAddCookie : Form {
7 | public SimpleCookie? Cookie { get; set; }
8 |
9 | public frmAddCookie() {
10 | InitializeComponent();
11 | }
12 | public frmAddCookie(SimpleCookie? cookie) : this() {
13 | if (cookie != null) {
14 | txtName.Text = cookie.Name.UnlessNull(string.Empty);
15 | txtValue.Text = cookie.Value.UnlessNull(string.Empty);
16 | txtPath.Text = cookie.Path.UnlessNull(string.Empty);
17 | txtDomain.Text = cookie.Domain.UnlessNull(string.Empty);
18 | }
19 | }
20 |
21 | private void btnCancel_Click(object sender, EventArgs e) {
22 | this.DialogResult = DialogResult.Cancel;
23 | }
24 | private void btnAdd_Click(object sender, EventArgs e) {
25 | if (string.IsNullOrWhiteSpace(txtName.Text)) {
26 | txtName.Focus();
27 | System.Media.SystemSounds.Asterisk.Play();
28 | return;
29 | }
30 | if (string.IsNullOrWhiteSpace(txtValue.Text)) {
31 | txtValue.Focus();
32 | System.Media.SystemSounds.Asterisk.Play();
33 | return;
34 | }
35 | if (string.IsNullOrWhiteSpace(txtDomain.Text)) {
36 | txtDomain.Focus();
37 | System.Media.SystemSounds.Asterisk.Play();
38 | return;
39 | }
40 | Cookie = new(txtName.Text, txtValue.Text, txtPath.Text.UnlessNullEmptyWhiteSpace("/"), txtDomain.Text);
41 | this.DialogResult = DialogResult.OK;
42 | }
43 | }
--------------------------------------------------------------------------------
/src/YChanEx/Forms/frmNewName.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | using System;
4 | using System.Windows.Forms;
5 | public partial class frmNewName : Form {
6 | public string SetName { get; private set; }
7 |
8 | public frmNewName(string currentName) {
9 | InitializeComponent();
10 | txtNewName.Text = currentName;
11 | SetName = currentName;
12 | }
13 |
14 | private void txtNewName_KeyDown(object sender, KeyEventArgs e) {
15 | if (e.KeyCode == Keys.Return) {
16 | e.Handled = e.SuppressKeyPress = true;
17 | if (txtNewName.Text.IsNullEmptyWhitespace()) {
18 | System.Media.SystemSounds.Exclamation.Play();
19 | return;
20 | }
21 | this.DialogResult = DialogResult.OK;
22 | }
23 | }
24 | private void btnSetName_Click(object sender, EventArgs e) {
25 | if (txtNewName.Text.IsNullEmptyWhitespace()) {
26 | txtNewName.Focus();
27 | System.Media.SystemSounds.Exclamation.Play();
28 | return;
29 | }
30 | SetName = txtNewName.Text;
31 | this.DialogResult = DialogResult.OK;
32 | }
33 | private void btnCancel_Click(object sender, EventArgs e) {
34 | this.DialogResult = DialogResult.Cancel;
35 | }
36 | private void btnReset_Click(object sender, EventArgs e) {
37 | this.DialogResult = DialogResult.No;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/YChanEx/GlobalNamespaces.cs:
--------------------------------------------------------------------------------
1 | global using System;
2 | global using System.Collections.Generic;
3 | global using System.Linq;
4 | global using System.Threading.Tasks;
5 | global using Version = murrty.Version;
6 |
--------------------------------------------------------------------------------
/src/YChanEx/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | [assembly: SuppressMessage("Style", "IDE1006:Naming Styles")]
4 | [assembly: SuppressMessage("Style", "IDE0290:Use primary constructor")]
5 |
--------------------------------------------------------------------------------
/src/YChanEx/Interfaces/IMainForm.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | public interface IMainFom {
4 | ///
5 | /// Sets the thread status from another thread handle to change the status on the main form.
6 | ///
7 | /// The thread that was 404'd, archived, or aborted.
8 | /// The new custom status to be set onto it.
9 | void SetItemStatus(ThreadInfo Thread, ThreadStatus Status);
10 | ///
11 | /// Removes the thread if it was killed (archived or 404)
12 | ///
13 | /// The thread that was 404'd, archived, or aborted.
14 | void ThreadKilled(ThreadInfo Thread);
15 | ///
16 | /// Adds a thread to the history.
17 | ///
18 | /// The thread that will be added.
19 | void AddToHistory(PreviousThread Thread);
20 | }
21 |
--------------------------------------------------------------------------------
/src/YChanEx/Logging/DwmCompositionInfo.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.classes;
3 | using System.Drawing;
4 | using System.Runtime.InteropServices;
5 | ///
6 | /// A class that contains information about how the dwm will composite on the form
7 | ///
8 | internal sealed class DwmCompositionInfo {
9 | ///
10 | /// The handle that will be written to.
11 | ///
12 | public nint hWnd { get; }
13 |
14 | ///
15 | /// The rectangle where the dwm composition will be drawn at.
16 | ///
17 | public Rectangle DwmRectangle;
18 |
19 | ///
20 | /// Contains relevant information about the positioning of the frame.
21 | ///
22 | public DwmNatives.MARGINS Margins;
23 |
24 | ///
25 | /// Contains the text that will be rendered.
26 | ///
27 | public DwmCompositionTextInfo? Text;
28 |
29 | ///
30 | /// Device context handle.
31 | ///
32 | public nint destdc;
33 |
34 | ///
35 | /// Rect struct to render composition at.
36 | ///
37 | public DwmNatives.RECT Rect;
38 |
39 | ///
40 | /// DIB bitmap for the dwm composition.
41 | ///
42 | public DwmNatives.BITMAPINFO dib;
43 |
44 | public DwmCompositionInfo(nint hWnd, DwmNatives.MARGINS Margins, Rectangle DwmRectangle) {
45 | this.hWnd = hWnd;
46 | this.Margins = Margins;
47 | this.DwmRectangle = DwmRectangle;
48 |
49 | GenerateValues();
50 | }
51 |
52 | public DwmCompositionInfo(nint hWnd, DwmNatives.MARGINS Margins, Rectangle DwmRectangle, DwmCompositionTextInfo NewInfo) {
53 | this.hWnd = hWnd;
54 | this.Margins = Margins;
55 | this.DwmRectangle = DwmRectangle;
56 | Text = NewInfo;
57 |
58 | GenerateValues();
59 | }
60 |
61 | ///
62 | /// Generates used-values for rendering. Created to save lines when generating dwm info with or without text.
63 | ///
64 | private void GenerateValues() {
65 | destdc = DwmNatives.GetDC(hWnd);
66 |
67 | Rect = new() {
68 | top = DwmRectangle.Top,
69 | bottom = DwmRectangle.Bottom,
70 | left = DwmRectangle.Left,
71 | right = DwmRectangle.Right
72 | };
73 |
74 | dib = new();
75 | dib.bmiHeader.biHeight = -(Rect.bottom - Rect.top);
76 | dib.bmiHeader.biWidth = Rect.right - Rect.left;
77 | dib.bmiHeader.biPlanes = 1;
78 | dib.bmiHeader.biSize = Marshal.SizeOf(typeof(DwmNatives.BITMAPINFOHEADER));
79 | dib.bmiHeader.biBitCount = 32;
80 | dib.bmiHeader.biCompression = DwmNatives.BI_RGB;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/YChanEx/Logging/DwmCompositionTextInfo.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.classes;
3 | using System.Drawing;
4 | using System.Runtime.InteropServices;
5 | ///
6 | /// A class that contains information about the text when rendering in the dwm composition.
7 | ///
8 | internal sealed class DwmCompositionTextInfo {
9 | ///
10 | /// The text that will be drawn.
11 | ///
12 | public string Text { get; set; }
13 |
14 | ///
15 | /// The font of the text.
16 | ///
17 | public Font Font { get; set; }
18 |
19 | ///
20 | /// The color of the text.
21 | ///
22 | public Color Color { get; set; }
23 |
24 | ///
25 | /// The size of the glow behind the text. 0 is off.
26 | ///
27 | public int GlowSize { get; set; }
28 |
29 | ///
30 | /// The rectangle where the text will render in.
31 | ///
32 | public Rectangle RenderingRectangle { get; set; }
33 |
34 | ///
35 | /// Rect 1 based for the text
36 | ///
37 | public DwmNatives.RECT Rect1;
38 |
39 | ///
40 | /// Rext 2 based for the glow. ?
41 | ///
42 | public DwmNatives.RECT Rect2;
43 |
44 | ///
45 | /// DIB bitmap for the text.
46 | ///
47 | public DwmNatives.BITMAPINFO BitmapInfo;
48 |
49 | ///
50 | /// Text formatting options.
51 | ///
52 | public DwmNatives.DTTOPTS dttOpts;
53 |
54 | ///
55 | /// Format for the text.
56 | ///
57 | public int uFormat = DwmNatives.DT_SINGLELINE |
58 | DwmNatives.DT_CENTER |
59 | DwmNatives.DT_VCENTER |
60 | DwmNatives.DT_NOPREFIX;
61 |
62 | ///
63 | /// Renderer.
64 | ///
65 | public System.Windows.Forms.VisualStyles.VisualStyleRenderer renderer { get; } =
66 | new(System.Windows.Forms.VisualStyles.VisualStyleElement.Window.Caption.Active);
67 |
68 | public DwmCompositionTextInfo(string text, Font font, Color color, int glowsize, Rectangle rectangle) {
69 | Text = text;
70 | Font = font;
71 | Color = color;
72 | GlowSize = glowsize;
73 | RenderingRectangle = rectangle;
74 |
75 | Rect1.left = rectangle.Left;
76 | Rect1.right = rectangle.Right + 2;
77 | Rect1.top = rectangle.Top;
78 | Rect1.bottom = rectangle.Bottom + 2;
79 |
80 | Rect2.left = 0;
81 | Rect2.top = 0;
82 | Rect2.right = Rect1.right - Rect1.left;
83 | Rect2.bottom = Rect1.bottom - Rect1.top;
84 |
85 | BitmapInfo = new();
86 | BitmapInfo.bmiHeader.biHeight = -(Rect1.bottom - Rect1.top); // negative because DrawThemeTextEx() uses a top-down DIB
87 | BitmapInfo.bmiHeader.biWidth = Rect1.right - Rect1.left;
88 | BitmapInfo.bmiHeader.biPlanes = 1;
89 | BitmapInfo.bmiHeader.biSize = Marshal.SizeOf(typeof(DwmNatives.BITMAPINFOHEADER));
90 | BitmapInfo.bmiHeader.biBitCount = 32;
91 | BitmapInfo.bmiHeader.biCompression = DwmNatives.BI_RGB;
92 |
93 | dttOpts = new() {
94 | dwSize = (uint)Marshal.SizeOf(typeof(DwmNatives.DTTOPTS))
95 | };
96 | if (glowsize > 0) {
97 | dttOpts.dwFlags = DwmNatives.DTT_COMPOSITED |
98 | DwmNatives.DTT_GLOWSIZE |
99 | DwmNatives.DTT_TEXTCOLOR;
100 | }
101 | else {
102 | dttOpts.dwFlags = DwmNatives.DTT_COMPOSITED |
103 | DwmNatives.DTT_TEXTCOLOR;
104 | }
105 | dttOpts.iGlowSize = glowsize;
106 | dttOpts.crText = (uint)ColorTranslator.ToWin32(color);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/YChanEx/Logging/ExceptionType.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.logging;
3 | ///
4 | /// Enum of exception types that may occur during runtime.
5 | ///
6 | [System.ComponentModel.DefaultValue(Unknown)]
7 | internal enum ExceptionType {
8 | ///
9 | /// An unknown exception type, no way for the application to know the after-report state of the application itself.
10 | ///
11 | Unknown,
12 | ///
13 | /// A successfully caught exception which will terminate the try-catch block associated with it.
14 | ///
15 | Caught,
16 | ///
17 | /// An unhandled exception type which will most likely cause the application to exit.
18 | ///
19 | Unhandled,
20 | ///
21 | /// An unhandled thread exception that will allow the application to continue in most situations.
22 | ///
23 | ThreadException
24 | }
25 |
--------------------------------------------------------------------------------
/src/YChanEx/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using System.Resources;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("YChanEx")]
10 | [assembly: AssemblyDescription("Thread downloader for various chans")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("YChanEx")]
14 | [assembly: AssemblyCopyright("Copyright © 2021")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 | [assembly: Guid("f2a0f289-635f-4ec8-829f-cad1c24cb49f")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("2.0.0.0")]
37 | [assembly: AssemblyFileVersion("2.0.0.0")]
38 | [assembly: NeutralResourcesLanguageAttribute("en-US")]
39 |
--------------------------------------------------------------------------------
/src/YChanEx/Resources/AboutImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/AboutImage.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/BuildDate.txt:
--------------------------------------------------------------------------------
1 | 2024-01-17
--------------------------------------------------------------------------------
/src/YChanEx/Resources/ProgramIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/ProgramIcon.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/ProgramIcon_Dead.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/ProgramIcon_Dead.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/420chan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/420chan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/4chan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/4chan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/7chan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/7chan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/8chan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/8chan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/8kun.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/8kun.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/fchan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/fchan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/foolfuuka.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/foolfuuka.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/SiteIcons/u18chan.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/SiteIcons/u18chan.ico
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/404.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/downloading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/downloading.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/error.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/finished-hashmismatch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/finished-hashmismatch.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/finished.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/finished.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/reloaded-downloaded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/reloaded-downloaded.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/reloaded-hashmismatch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/reloaded-hashmismatch.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/reloaded-missing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/reloaded-missing.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/removed-from-thread.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/removed-from-thread.png
--------------------------------------------------------------------------------
/src/YChanEx/Resources/Status/waiting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/murrty/YChanEx/00b16bfa300ea91dac303b411d817a583a779874/src/YChanEx/Resources/Status/waiting.png
--------------------------------------------------------------------------------
/src/YChanEx/Updater/API Data/GithubAsset.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.updater;
3 | using System.Runtime.Serialization;
4 | ///
5 | /// Represents a structure of the data representing the version, such as the content type (x-*) and the size of the file.
6 | ///
7 | [DataContract]
8 | public readonly struct GithubAsset(string Content, long Length) {
9 | ///
10 | /// Gets the content type.
11 | ///
12 | [DataMember(Name = "content_type")]
13 | public string Content { get; init; } = Content;
14 |
15 | ///
16 | /// Gets the size of the file.
17 | ///
18 | [DataMember(Name = "size")]
19 | public long Length { get; init; } = Length;
20 |
21 | ///
22 | /// Initializes an empty asset.
23 | ///
24 | public GithubAsset() : this(string.Empty, 0) { }
25 | }
26 |
--------------------------------------------------------------------------------
/src/YChanEx/Updater/API Data/GithubData.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.updater;
3 | using System.Runtime.Serialization;
4 | using System.Text.RegularExpressions;
5 | using YChanEx;
6 | [DataContract]
7 | public sealed class GithubData {
8 | ///
9 | /// The string header of the update.
10 | ///
11 | [DataMember(Name = "name")]
12 | public string? VersionHeader { get; init; }
13 |
14 | ///
15 | /// The full description of the update.
16 | ///
17 | [DataMember(Name = "body")]
18 | public string? VersionDescription { get; init; }
19 |
20 | ///
21 | /// The tag of the update, which is usually the version.
22 | ///
23 | [DataMember(Name = "tag_name")]
24 | public string? VersionTag { get; init; }
25 |
26 | ///
27 | /// Whether the version posted on Github is a pre-release.
28 | ///
29 | [DataMember(Name = "prerelease")]
30 | public bool VersionPreRelease { get; init; }
31 |
32 | ///
33 | /// The files associated with the update.
34 | ///
35 | [DataMember(Name = "assets")]
36 | public GithubAsset[]? Files { get; init; }
37 |
38 | ///
39 | /// Gets whether this is a newer version of the program.
40 | ///
41 | [IgnoreDataMember]
42 | public bool IsNewerVersion { get; internal set; }
43 |
44 | ///
45 | /// Gets the string hash of the version (if available).
46 | ///
47 | [IgnoreDataMember]
48 | public string? ExecutableHash { get; internal set; }
49 |
50 | ///
51 | /// Gets the struct representation of the version.
52 | ///
53 | [IgnoreDataMember]
54 | public Version Version { get; internal set; }
55 |
56 | ///
57 | /// Gets whether the version is a beta version (or pre-release).
58 | ///
59 | [IgnoreDataMember]
60 | public bool IsBetaVersion => Version.IsBeta;
61 |
62 | [IgnoreDataMember]
63 | public long ExecutableSize { get; private set; }
64 |
65 | ///
66 | /// Tries to parse the executable hash from the version description.
67 | ///
68 | ///
69 | private string? FindHash() {
70 | if (VersionDescription.IsNullEmptyWhitespace()) {
71 | return null;
72 | }
73 | MatchCollection Matches = Regex.Matches(VersionDescription, "(?<=exe sha([- ])256: )(`)?[0-9a-fA-F]{64}(`)?(?=)");
74 | if (Matches.Count > 0) {
75 | return Matches[0].Value;
76 | }
77 | Matches = Regex.Matches(VersionDescription, "(?<=exe sha256: )(`)?[0-9a-fA-F]{64}(`)?(?=)");
78 | if (Matches.Count > 0) {
79 | return Matches[0].Value;
80 | }
81 | return null;
82 | }
83 |
84 | [OnDeserialized]
85 | void Deserialized(StreamingContext ctx) {
86 | // Skip any that cannot be parsed by the version string.
87 | if (!Version.TryParse(VersionTag, out Version vers)) {
88 | return;
89 | }
90 |
91 | Version = vers;
92 | IsNewerVersion = Version > Program.CurrentVersion;
93 | ExecutableHash = FindHash() ?? string.Empty;
94 | ExecutableSize = 0;
95 | if (Files?.Length > 0) {
96 | for (int i = 0; i < Files.Length; i++) {
97 | if (Files[i].Content == "application/x-msdownload") {
98 | ExecutableSize = Files[i].Length;
99 | }
100 | }
101 | }
102 | }
103 |
104 | public static GithubData GetNewestRelease(GithubData[] Releases) {
105 | if (Releases.Length == 0) {
106 | throw new NullReferenceException("The found releases were empty.");
107 | }
108 | GithubData CurrentCheck = Releases[0];
109 | Version NewestVersion = Version.Empty;
110 | for (int i = 0; i < Releases.Length; i++) {
111 | Version Parse = Releases[i].Version;
112 | if (Parse > NewestVersion) {
113 | CurrentCheck = Releases[i];
114 | NewestVersion = Parse;
115 | }
116 | }
117 | return CurrentCheck;
118 | }
119 | }
--------------------------------------------------------------------------------
/src/YChanEx/Updater/Form/frmUpdateAvailable.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace YChanEx;
3 | using System.Windows.Forms;
4 | using murrty.updater;
5 | internal sealed partial class frmUpdateAvailable : Form {
6 | ///
7 | /// Whether the "Skip version" button should be disabled, false if it's an automatic check.
8 | ///
9 | public bool BlockSkip { get; init; }
10 |
11 | ///
12 | /// The update that is available.
13 | ///
14 | internal GithubData UpdateData { get; }
15 |
16 | public frmUpdateAvailable(GithubData UpdateData) {
17 | InitializeComponent();
18 | this.UpdateData = UpdateData;
19 | lbUpdateAvailableCurrentVersion.Text = $"Current version: {Program.CurrentVersion}";
20 | }
21 |
22 | private void frmUpdateAvailable_Load(object? sender, EventArgs e) {
23 | btnUpdateAvailableSkip.Enabled = !BlockSkip;
24 | if (UpdateData.IsBetaVersion) {
25 | lbUpdateAvailableHeader.Text = "A beta update is available";
26 | }
27 | lbUpdateAvailableUpdateVersion.Text = $"Update version: {UpdateData.Version}";
28 | txtUpdateAvailableName.Text = UpdateData.VersionHeader ?? "No header provided";
29 | rtbUpdateAvailableChangelog.Text = UpdateData.VersionDescription ?? "No description provided.";
30 | lbUpdateSize.Text = $"The new executable size is {HtmlControl.GetSize(UpdateData.ExecutableSize)}";
31 | }
32 |
33 | private void btnUpdateAvailableSkip_Click(object? sender, EventArgs e) {
34 | this.DialogResult = DialogResult.Ignore;
35 | }
36 |
37 | private void btnUpdateAvailableUpdate_Click(object? sender, EventArgs e) {
38 | this.DialogResult = DialogResult.Yes;
39 | }
40 |
41 | private void btnUpdateAvailableOk_Click(object? sender, EventArgs e) {
42 | this.DialogResult = DialogResult.OK;
43 | }
44 |
45 | private void rtbUpdateAvailableChangelog_KeyPress(object? sender, KeyPressEventArgs e) {
46 | e.Handled = true;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/BrotliRuntimeException.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Unchecked exception used internally.
8 | [System.Serializable]
9 | internal sealed class BrotliRuntimeException : System.Exception {
10 | internal BrotliRuntimeException() : base() {
11 | }
12 | internal BrotliRuntimeException(string message)
13 | : base(message) {
14 | }
15 | internal BrotliRuntimeException(string message, System.Exception cause)
16 | : base(message, cause) {
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/HuffmanTreeGroup.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Contains a collection of huffman trees with the same alphabet size.
8 | internal sealed class HuffmanTreeGroup {
9 | /// The maximal alphabet size in this group.
10 | private int alphabetSize;
11 | /// Storage for Huffman lookup tables.
12 | internal int[] codes;
13 | ///
14 | /// Offsets of distinct lookup tables in
15 | ///
16 | /// storage.
17 | ///
18 | internal int[] trees;
19 |
20 | /// Initializes the Huffman tree group.
21 | /// POJO to be initialised
22 | /// the maximal alphabet size in this group
23 | /// number of Huffman codes
24 | internal static void Init(HuffmanTreeGroup group, int alphabetSize, int n) {
25 | group.alphabetSize = alphabetSize;
26 | group.codes = new int[n * Huffman.HuffmanMaxTableSize];
27 | group.trees = new int[n];
28 | }
29 |
30 | /// Decodes Huffman trees from input stream and constructs lookup tables.
31 | /// target POJO
32 | /// data source
33 | internal static void Decode(HuffmanTreeGroup group, BitReader br) {
34 | int next = 0;
35 | int n = group.trees.Length;
36 | for (int i = 0; i < n; i++) {
37 | group.trees[i] = next;
38 | Dec.Decode.ReadHuffmanCode(group.alphabetSize, group.codes, next, br);
39 | next += Huffman.HuffmanMaxTableSize;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/IntReader.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2017 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Byte-to-int conversion magic.
8 | internal sealed class IntReader {
9 | private byte[] byteBuffer;
10 | private int[] intBuffer;
11 |
12 | internal static void Init(IntReader ir, byte[] byteBuffer, int[] intBuffer) {
13 | ir.byteBuffer = byteBuffer;
14 | ir.intBuffer = intBuffer;
15 | }
16 |
17 | /// Translates bytes to ints.
18 | ///
19 | /// Translates bytes to ints.
20 | /// NB: intLen == 4 * byteSize!
21 | /// NB: intLen should be less or equal to intBuffer length.
22 | ///
23 | internal static void Convert(IntReader ir, int intLen) {
24 | for (int i = 0; i < intLen; ++i) {
25 | ir.intBuffer[i] = (ir.byteBuffer[i * 4] & unchecked((int)(0xFF)))
26 | | ((ir.byteBuffer[(i * 4) + 1] & unchecked((int)(0xFF))) << 8)
27 | | ((ir.byteBuffer[(i * 4) + 2] & unchecked((int)(0xFF))) << 16)
28 | | ((ir.byteBuffer[(i * 4) + 3] & unchecked((int)(0xFF))) << 24);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/Prefix.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Lookup tables to map prefix codes to value ranges.
8 | ///
9 | /// Lookup tables to map prefix codes to value ranges.
10 | /// This is used during decoding of the block lengths, literal insertion lengths and copy
11 | /// lengths.
12 | ///
Range represents values: [offset, offset + 2 ^ n_bits)
13 | ///
14 | internal static class Prefix {
15 | internal static readonly int[] BlockLengthOffset = [1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497, 753, 1265, 2289, 4337, 8433, 16625];
16 |
17 | internal static readonly int[] BlockLengthNBits = [2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 24];
18 |
19 | internal static readonly int[] InsertLengthOffset = [0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594];
20 |
21 | internal static readonly int[] InsertLengthNBits = [0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24];
22 |
23 | internal static readonly int[] CopyLengthOffset = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, 22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118];
24 |
25 | internal static readonly int[] CopyLengthNBits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24];
26 |
27 | internal static readonly int[] InsertRangeLut = [0, 0, 8, 8, 0, 16, 8, 16, 16];
28 |
29 | internal static readonly int[] CopyRangeLut = [0, 8, 0, 8, 16, 0, 16, 8, 16];
30 | }
31 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/RunningState.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Enumeration of decoding state-machine.
8 | internal enum RunningState : byte {
9 | Uninitialized = 0,
10 | BlockStart = 1,
11 | CompressedBlockStart = 2,
12 | MainLoop = 3,
13 | ReadMetadata = 4,
14 | CopyUncompressed = 5,
15 | InsertLoop = 6,
16 | CopyLoop = 7,
17 | CopyWrapBuffer = 8,
18 | Transform = 9,
19 | Finished = 10,
20 | Closed = 11,
21 | Write = 12,
22 | }
23 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/State.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | internal sealed class State {
8 | internal RunningState runningState = RunningState.Uninitialized;
9 | internal RunningState nextRunningState;
10 | internal readonly BitReader br = new();
11 | internal byte[] ringBuffer;
12 | internal readonly int[] blockTypeTrees = new int[3 * Huffman.HuffmanMaxTableSize];
13 | internal readonly int[] blockLenTrees = new int[3 * Huffman.HuffmanMaxTableSize];
14 | internal int metaBlockLength;
15 | internal bool inputEnd;
16 | internal bool isUncompressed;
17 | internal bool isMetadata;
18 | internal readonly HuffmanTreeGroup hGroup0 = new();
19 | internal readonly HuffmanTreeGroup hGroup1 = new();
20 | internal readonly HuffmanTreeGroup hGroup2 = new();
21 | internal readonly int[] blockLength = new int[3];
22 | internal readonly int[] numBlockTypes = new int[3];
23 | internal readonly int[] blockTypeRb = new int[6];
24 | internal readonly int[] distRb = [16, 15, 11, 4];
25 | internal int pos = 0;
26 | internal int maxDistance = 0;
27 | internal int distRbIdx = 0;
28 | internal bool trivialLiteralContext = false;
29 | internal int literalTreeIndex = 0;
30 | internal int literalTree;
31 | internal int j;
32 | internal int insertLength;
33 | internal byte[] contextModes;
34 | internal byte[] contextMap;
35 | internal int contextMapSlice;
36 | internal int distContextMapSlice;
37 | internal int contextLookupOffset1;
38 | internal int contextLookupOffset2;
39 | internal int treeCommandOffset;
40 | internal int distanceCode;
41 | internal byte[] distContextMap;
42 | internal int numDirectDistanceCodes;
43 | internal int distancePostfixMask;
44 | internal int distancePostfixBits;
45 | internal int distance;
46 | internal int copyLength;
47 | internal int copyDst;
48 | internal int maxBackwardDistance;
49 | internal int maxRingBufferSize;
50 | internal int ringBufferSize = 0;
51 | internal long expectedTotalSize = 0;
52 | internal byte[] customDictionary = new byte[0];
53 | internal int bytesToIgnore = 0;
54 | internal int outputOffset;
55 | internal int outputLength;
56 | internal int outputUsed;
57 | internal int bytesWritten;
58 | internal int bytesToWrite;
59 | internal byte[] output;
60 |
61 | // Current meta-block header information.
62 | private static int DecodeWindowBits(BitReader br) {
63 | if (BitReader.ReadBits(br, 1) == 0) {
64 | return 16;
65 | }
66 | int n = BitReader.ReadBits(br, 3);
67 | if (n != 0) {
68 | return 17 + n;
69 | }
70 | n = BitReader.ReadBits(br, 3);
71 | if (n != 0) {
72 | return 8 + n;
73 | }
74 | return 17;
75 | }
76 |
77 | /// Associate input with decoder state.
78 | /// uninitialized state without associated input
79 | /// compressed data source
80 | internal static void SetInput(State state, System.IO.Stream input) {
81 | if (state.runningState != RunningState.Uninitialized) {
82 | throw new InvalidOperationException("State MUST be uninitialized");
83 | }
84 | BitReader.Init(state.br, input);
85 | int windowBits = DecodeWindowBits(state.br);
86 | if (windowBits == 9) {
87 | /* Reserved case for future expansion. */
88 | throw new BrotliRuntimeException("Invalid 'windowBits' code");
89 | }
90 | state.maxRingBufferSize = 1 << windowBits;
91 | state.maxBackwardDistance = state.maxRingBufferSize - 16;
92 | state.runningState = RunningState.BlockStart;
93 | }
94 |
95 | internal static void Close(State state, bool leaveOpen) {
96 | if (state.runningState == RunningState.Uninitialized) {
97 | throw new InvalidOperationException("State MUST be initialized");
98 | }
99 | if (state.runningState == RunningState.Closed) {
100 | return;
101 | }
102 | state.runningState = RunningState.Closed;
103 | BitReader.Close(state.br, leaveOpen);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/Utils.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// A set of utility methods.
8 | internal sealed class Utils {
9 | private static readonly byte[] ByteZeroes = new byte[1024];
10 | private static readonly int[] IntZeroes = new int[1024];
11 |
12 | /// Fills byte array with zeroes.
13 | ///
14 | /// Fills byte array with zeroes.
15 | /// Current implementation uses
16 | ///
17 | /// , so it should be used for length not
18 | /// less than 16.
19 | ///
20 | /// array to fill with zeroes
21 | /// the first byte to fill
22 | /// number of bytes to change
23 | internal static void FillWithZeroes(byte[] dest, int offset, int length) {
24 | int cursor = 0;
25 | while (cursor < length) {
26 | int step = Math.Min(cursor + 1024, length) - cursor;
27 | Array.Copy(ByteZeroes, 0, dest, offset + cursor, step);
28 | cursor += step;
29 | }
30 | }
31 |
32 | /// Fills int array with zeroes.
33 | ///
34 | /// Fills int array with zeroes.
35 | /// Current implementation uses
36 | ///
37 | /// , so it should be used for length not
38 | /// less than 16.
39 | ///
40 | /// array to fill with zeroes
41 | /// the first item to fill
42 | /// number of item to change
43 | internal static void FillWithZeroes(int[] dest, int offset, int length) {
44 | int cursor = 0;
45 | while (cursor < length) {
46 | int step = Math.Min(cursor + 1024, length) - cursor;
47 | Array.Copy(IntZeroes, 0, dest, offset + cursor, step);
48 | cursor += step;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/Brotli/WordTransformType.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Google Inc. All Rights Reserved.
2 |
3 | Distributed under MIT license.
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 | */
6 | namespace Org.Brotli.Dec;
7 | /// Enumeration of all possible word transformations.
8 | ///
9 | /// Enumeration of all possible word transformations.
10 | /// There are two simple types of transforms: omit X first/last symbols, two character-case
11 | /// transforms and the identity transform.
12 | ///
13 | internal sealed class WordTransformType {
14 | internal const int Identity = 0;
15 | internal const int OmitLast1 = 1;
16 | internal const int OmitLast2 = 2;
17 | internal const int OmitLast3 = 3;
18 | internal const int OmitLast4 = 4;
19 | internal const int OmitLast5 = 5;
20 | internal const int OmitLast6 = 6;
21 | internal const int OmitLast7 = 7;
22 | internal const int OmitLast8 = 8;
23 | internal const int OmitLast9 = 9;
24 | internal const int UppercaseFirst = 10;
25 | internal const int UppercaseAll = 11;
26 | internal const int OmitFirst1 = 12;
27 | internal const int OmitFirst2 = 13;
28 | internal const int OmitFirst3 = 14;
29 | internal const int OmitFirst4 = 15;
30 | internal const int OmitFirst5 = 16;
31 | internal const int OmitFirst6 = 17;
32 | internal const int OmitFirst7 = 18;
33 | internal const int OmitFirst8 = 19;
34 | internal const int OmitFirst9 = 20;
35 |
36 | internal static int GetOmitFirst(int type) => type >= OmitFirst1 ? (type - OmitFirst1 + 1) : 0;
37 | internal static int GetOmitLast(int type) => type <= OmitLast9 ? (type - OmitLast1 + 1) : 0;
38 | }
39 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/CookieParser.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.networking;
3 | using System.Net;
4 | using YChanEx;
5 | internal static class CookieParser {
6 | public static Cookie? GetCookie(string? value, Uri hostUri) {
7 | if (value.IsNullEmptyWhitespace()) {
8 | return null;
9 | }
10 |
11 | string? cookieName = null;
12 | string? cookieValue = null;
13 |
14 | // Get the name and value, it's the first value in the string.
15 | int sepPos = value.IndexOf('=');
16 | int endPos = value.IndexOf(';');
17 |
18 | // Other optionals
19 | string cookiePath = "/";
20 | string cookieDomain = hostUri.Host;
21 | DateTime? expiresOn = null;
22 | bool httpOnly = false;
23 | bool secure = false;
24 |
25 | cookieName = value[..sepPos];
26 | if (endPos > -1) {
27 | cookieValue = value[(sepPos + 1)..endPos];
28 |
29 | if (endPos > value.Length - 1) {
30 | // Check for expire date
31 | int expirePos = value.IndexOf("expires=", StringComparison.OrdinalIgnoreCase);
32 | if (expirePos > -1) {
33 |
34 | }
35 | }
36 | }
37 | else {
38 | cookieValue = value[(sepPos + 1)..];
39 | }
40 |
41 | Cookie cookie = new(cookieName, cookieValue, cookiePath, cookieDomain) {
42 | HttpOnly = httpOnly,
43 | Secure = secure
44 | };
45 | if (expiresOn != null) {
46 | cookie.Expires = expiresOn.Value;
47 | }
48 | return cookie;
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/DelegateHandlerHelpers.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace murrty.networking;
3 | using System.Net.Http;
4 | using System.Threading;
5 | using YChanEx;
6 | internal static class DelegateHandlerHelpers {
7 | public static CancellationTokenSource? CreateToken(HttpRequestMessage request, TimeSpan DefaultTimeout, CancellationToken cancellationToken) {
8 | TimeSpan Timeout;
9 |
10 | #if NET5_0_OR_GREATER
11 | if (request.Options.TryGetValue(RequestMessage.TimeoutKey, out TimeSpan? time) && time.HasValue) {
12 | Timeout = time.Value;
13 | }
14 | else
15 | #endif
16 | if (request.Properties?.TryGetValue(RequestMessage.TimeoutKey, out var tsp) is true && tsp is TimeSpan time) {
17 | Timeout = time;
18 | }
19 | else {
20 | Timeout = DefaultTimeout;
21 | }
22 |
23 | if (Timeout == TimeSpan.Zero) {
24 | return null;
25 | }
26 |
27 | CancellationTokenSource Token = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
28 | Token.CancelAfter(Timeout);
29 | return Token;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Extensions/HttpHeadersExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Extensions;
2 | using System.Net.Http.Headers;
3 | internal static class HttpHeadersExtensions {
4 | public static string GetHeaderString(this HttpHeaders headers, string key) {
5 | if (headers == null) {
6 | throw new ArgumentNullException(nameof(headers));
7 | }
8 |
9 | if (string.IsNullOrEmpty(key)) {
10 | throw new ArgumentNullException(nameof(key));
11 | }
12 |
13 | string value = string.Empty;
14 | string separator = key.Equals("User-Agent") ? " " : ", ";
15 |
16 | if (headers.TryGetValues(key, out IEnumerable values) && values.Count() > 1) {
17 | value = string.Join(separator, values.ToArray());
18 | }
19 |
20 | return value;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Handlers/Socks4ClientHandler.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp;
2 | using SocksSharp.Proxy;
3 | internal class Socks4ClientHandler : ProxyClientHandler {
4 | public Socks4ClientHandler(ProxySettings proxySettings) : base(proxySettings) { }
5 | }
6 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Handlers/Socks4aClientHandler.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp;
2 | using SocksSharp.Proxy;
3 | internal class Socks4aClientHandler : ProxyClientHandler {
4 | public Socks4aClientHandler(ProxySettings proxySettings) : base(proxySettings) { }
5 | }
6 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Handlers/Socks5ClientHandler.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp;
2 | using SocksSharp.Proxy;
3 | internal class Socks5ClientHandler : ProxyClientHandler {
4 | public Socks5ClientHandler(ProxySettings proxySettings) : base(proxySettings) { }
5 | }
6 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Helpers/ContentHelper.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Helpers;
2 | internal static class ContentHelper {
3 | public static bool IsContentHeader(string name) {
4 | //https://github.com/dotnet/corefx/blob/3e72ee5971db5d0bd46606fa672969adde29e307/src/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs
5 | string[] contentHeaders = [
6 | "Last-Modified",
7 | "Expires",
8 | "Content-Type",
9 | "Content-Range",
10 | "Content-MD5",
11 | "Content-Location",
12 | "Content-Length",
13 | "Content-Language",
14 | "Content-Encoding",
15 | "Allow"
16 | ];
17 |
18 | bool isContent = false;
19 | for (int i = 0; i < contentHeaders.Length; i++) {
20 | string header = contentHeaders[i];
21 | isContent = isContent || header.Equals(name, StringComparison.OrdinalIgnoreCase);
22 | }
23 |
24 | return isContent;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Helpers/ExceptionHelper.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Helpers;
2 | internal static class ExceptionHelper {
3 | public static bool ValidateTcpPort(int port) {
4 | return port >= 1 && port <= 65535;
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Helpers/HostHelper.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Core.Helpers;
2 | using SocksSharp.Proxy;
3 | using System.Net;
4 | using System.Net.Sockets;
5 | using System.Text;
6 | internal static class HostHelper {
7 | public static byte[] GetPortBytes(int port) {
8 | return [
9 | (byte)(port / 256),
10 | (byte)(port % 256)];
11 | }
12 |
13 | public static byte[] GetIPAddressBytes(string destinationHost, bool preferIpv4 = true) {
14 | if (!IPAddress.TryParse(destinationHost, out var ipAddr)) {
15 | try {
16 | var ips = Dns.GetHostAddresses(destinationHost);
17 | if (ips.Length > 0) {
18 | if (preferIpv4) {
19 | foreach (var ip in ips) {
20 | var ipBytes = ip.GetAddressBytes();
21 | if (ipBytes.Length == 4) {
22 | return ipBytes;
23 | }
24 | }
25 | }
26 | ipAddr = ips[0];
27 | }
28 | }
29 | catch (Exception ex) {
30 | if (ex is SocketException || ex is ArgumentException) {
31 | throw new ProxyException("Failed to get host address", ex);
32 | }
33 | throw;
34 | }
35 | }
36 |
37 | return ipAddr.GetAddressBytes();
38 | }
39 |
40 | public static byte[] GetHostAddressBytes(byte addressType, string host) {
41 | switch (addressType) {
42 | case Socks5Constants.AddressTypeIPV4:
43 | case Socks5Constants.AddressTypeIPV6:
44 | return IPAddress.Parse(host).GetAddressBytes();
45 |
46 | case Socks5Constants.AddressTypeDomainName:
47 | byte[] bytes = new byte[host.Length + 1];
48 | bytes[0] = (byte)host.Length;
49 | Encoding.ASCII.GetBytes(host).CopyTo(bytes, 1);
50 | return bytes;
51 |
52 | default: return null;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Helpers/ReceiveHelper.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2012-2015 Ruslan Khuduev
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 | namespace SocksSharp.Helpers;
23 | using System.IO;
24 | using System.Text;
25 | internal sealed class ReceiveHelper {
26 | #region Fields
27 | private const int InitialLineSize = 1000;
28 |
29 | private Stream stream;
30 |
31 | private readonly byte[] buffer;
32 | private readonly int bufferSize;
33 |
34 | private int linePosition;
35 | private byte[] lineBuffer = new byte[InitialLineSize];
36 | #endregion
37 |
38 | #region Properties
39 | public bool HasData {
40 | get {
41 | return (this.Length - this.Position) != 0;
42 | }
43 | }
44 |
45 | public int Length { get; private set; }
46 |
47 | public int Position { get; private set; }
48 | #endregion
49 |
50 | public ReceiveHelper(int bufferSize) {
51 | this.bufferSize = bufferSize;
52 | this.buffer = new byte[bufferSize];
53 | }
54 |
55 | #region Methods
56 | public void Init(Stream stream) {
57 | this.stream = stream;
58 | this.linePosition = 0;
59 | this.Length = 0;
60 | this.Position = 0;
61 | }
62 |
63 | public string ReadLine() {
64 | linePosition = 0;
65 |
66 | while (true) {
67 | if (Position == Length) {
68 | Position = 0;
69 | Length = stream.Read(buffer, 0, bufferSize);
70 | if (Length == 0) {
71 | break;
72 | }
73 | }
74 |
75 | byte b = buffer[Position++];
76 | lineBuffer[linePosition++] = b;
77 |
78 | // If a character is considered '\n' | Если считан символ '\n'.
79 | if (b == 10) {
80 | break;
81 | }
82 |
83 | // If the maximum line buffer size limit is reached | Если достигнут максимальный предел размера буфера линии.
84 | if (linePosition == lineBuffer.Length) {
85 | // Double the line buffer size | Увеличиваем размер буфера линии в два раза.
86 | byte[] newLineBuffer = new byte[lineBuffer.Length * 2];
87 | lineBuffer.CopyTo(newLineBuffer, 0);
88 | lineBuffer = newLineBuffer;
89 | }
90 | }
91 |
92 | return Encoding.ASCII.GetString(lineBuffer, 0, linePosition);
93 | }
94 |
95 | public int Read(byte[] buffer, int index, int length) {
96 | int curLength = Length - Position;
97 |
98 | if (curLength > length) {
99 | curLength = length;
100 | }
101 |
102 | Array.Copy(this.buffer, Position, buffer, index, curLength);
103 | Position += curLength;
104 | return curLength;
105 | }
106 | #endregion
107 | }
108 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/Clients/Socks4a.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright © 2012-2015 Ruslan Khuduev
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 | namespace SocksSharp.Proxy;
23 | using System.Text;
24 | using System.Net.Sockets;
25 | using SocksSharp.Core.Helpers;
26 | using static SocksSharp.Proxy.Socks4Constants;
27 | public class Socks4a : Socks4 {
28 | internal protected override void SendCommand(NetworkStream nStream, byte command, string destinationHost, int destinationPort) {
29 | byte[] dstPort = HostHelper.GetPortBytes(destinationPort);
30 | byte[] dstIp = [ 0, 0, 0, 1 ];
31 |
32 | byte[] userId = [];
33 | if (Settings.Credentials != null && !string.IsNullOrEmpty(Settings.Credentials.UserName)) {
34 | userId = Encoding.ASCII.GetBytes(Settings.Credentials.UserName);
35 | }
36 |
37 | byte[] dstAddr = Encoding.ASCII.GetBytes(destinationHost);
38 |
39 | // +----+----+----+----+----+----+----+----+----+----+....+----+----+----+....+----+
40 | // | VN | CD | DSTPORT | DSTIP | USERID |NULL| DSTADDR |NULL|
41 | // +----+----+----+----+----+----+----+----+----+----+....+----+----+----+....+----+
42 | // 1 1 2 4 variable 1 variable 1
43 | byte[] request = new byte[10 + userId.Length + dstAddr.Length];
44 |
45 | request[0] = VersionNumber;
46 | request[1] = command;
47 | dstPort.CopyTo(request, 2);
48 | dstIp.CopyTo(request, 4);
49 | userId.CopyTo(request, 8);
50 | request[8 + userId.Length] = 0x00;
51 | dstAddr.CopyTo(request, 9 + userId.Length);
52 | request[9 + userId.Length + dstAddr.Length] = 0x00;
53 |
54 | nStream.Write(request, 0, request.Length);
55 |
56 | // +----+----+----+----+----+----+----+----+
57 | // | VN | CD | DSTPORT | DSTIP |
58 | // +----+----+----+----+----+----+----+----+
59 | // 1 1 2 4
60 | byte[] response = new byte[8];
61 |
62 | nStream.Read(response, 0, 8);
63 |
64 | byte reply = response[1];
65 |
66 | // If the request is not fulfilled | Если запрос не выполнен.
67 | if (reply != CommandReplyRequestGranted) {
68 | HandleCommandError(reply);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/IProxy.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | using System.Net.Sockets;
3 | ///
4 | /// Provides an interface for proxy client
5 | ///
6 | public interface IProxy {
7 | ///
8 | /// Gets or sets proxy settings
9 | ///
10 | IProxySettings Settings { get; set; }
11 |
12 | ///
13 | /// Create connection to destination host via proxy server.
14 | ///
15 | /// Host
16 | /// Port
17 | /// Connection with proxy server.
18 | /// Connection to destination host
19 | TcpClient CreateConnection(string destinationHost, int destinationPort, TcpClient client);
20 | }
21 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/IProxyClient.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | using System.Net.Sockets;
3 | ///
4 | /// Provides an interface for
5 | ///
6 | ///
7 | public interface IProxyClient where T : IProxy {
8 | ///
9 | /// Gets or sets proxy settings for client
10 | ///
11 | ProxySettings Settings { get; set; }
12 |
13 | ///
14 | /// Create connection via proxy to destination host
15 | ///
16 | /// Destination
17 | NetworkStream GetDestinationStream(string destinationHost, int destinationPort);
18 | }
19 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/IProxySettings.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | using System.Net;
3 | ///
4 | /// Provides an interface for proxy settings
5 | ///
6 | public interface IProxySettings {
7 | ///
8 | /// Gets or sets the credentials to submit to the proxy server for authentication.
9 | ///
10 | NetworkCredential Credentials { get; set; }
11 |
12 | ///
13 | /// Gets or sets a value of host or IP address for the proxy server
14 | ///
15 | string Host { get; set; }
16 |
17 | ///
18 | /// Gets or sets a value of Port for the proxy server
19 | ///
20 | int Port { get; set; }
21 |
22 | ///
23 | /// Gets or sets the amount of time a
24 | /// will wait to connect to the proxy server
25 | ///
26 | int ConnectTimeout { get; set; }
27 |
28 | ///
29 | /// Gets or sets the amount of time a
30 | /// will wait for read or wait data from the proxy server
31 | ///
32 | int ReadWriteTimeOut { get; set; }
33 | }
34 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/IProxySettingsFluent.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | using System.Net;
3 | ///
4 | /// Provides an interface for fluent proxy settings
5 | ///
6 | public interface IProxySettingsFluent {
7 | ///
8 | /// Sets a value of host or IP address for the proxy server
9 | ///
10 | /// Host
11 | ///
12 | IProxySettingsFluent SetHost(string host);
13 |
14 | ///
15 | /// Sets a value of Port for the proxy server
16 | ///
17 | /// Port
18 | ///
19 | IProxySettingsFluent SetPort(int port);
20 |
21 | ///
22 | /// Gets or sets the amount of time a
23 | /// will wait for read or wait data from the proxy server
24 | ///
25 | /// Connection timeout
26 | ///
27 | IProxySettingsFluent SetConnectionTimeout(int connectionTimeout);
28 |
29 | ///
30 | /// Sets the amount of time a
31 | /// will wait to connect to the proxy server
32 | ///
33 | /// Read/Write timeout
34 | ///
35 | IProxySettingsFluent SetReadWriteTimeout(int readwriteTimeout);
36 |
37 | ///
38 | /// Sets the credentials to submit to the proxy server for authentication
39 | ///
40 | /// Credential
41 | ///
42 | IProxySettingsFluent SetCredential(NetworkCredential credential);
43 |
44 | ///
45 | /// Sets the credentials to submit to the proxy server for authentication
46 | ///
47 | /// Username
48 | /// Password
49 | ///
50 | IProxySettingsFluent SetCredential(string username, string password);
51 | }
52 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/ProxyClient.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | using System.Net.Sockets;
3 | using System.Security;
4 | using System.Threading;
5 | ///
6 | /// Represents Proxy Client to
7 | ///
8 | ///
9 | public class ProxyClient : IProxyClient where T : IProxy {
10 | private readonly T client;
11 |
12 | ///
13 | /// Gets or sets proxy settings for client
14 | ///
15 | public ProxySettings Settings { get; set; }
16 |
17 | ///
18 | /// Initialize a new instance of the with proxy handler
19 | ///
20 | public ProxyClient() {
21 | this.client = (T)Activator.CreateInstance(typeof(T));
22 | }
23 |
24 | ///
25 | /// Create connection via proxy to destination host
26 | ///
27 | /// Destination
28 | ///
29 | /// Value of equals or empty.
30 | /// -or-
31 | /// Value of less than 1 or greater than 65535.
32 | /// -or-
33 | /// Value of username length greater than 255.
34 | /// -or-
35 | /// Value of password length greater than 255.
36 | ///
37 | public NetworkStream GetDestinationStream(string destinationHost, int destinationPort) {
38 | TcpClient tcpClient = null;
39 | client.Settings = Settings;
40 |
41 | #region Create Connection
42 | tcpClient = new TcpClient();
43 | Exception connectException = null;
44 | var connectDoneEvent = new ManualResetEventSlim();
45 |
46 | try {
47 | tcpClient.BeginConnect(Settings.Host, Settings.Port, new AsyncCallback(
48 | (ar) => {
49 | if (tcpClient.Client != null) {
50 | try {
51 | tcpClient.EndConnect(ar);
52 | }
53 | catch (Exception ex) {
54 | connectException = ex;
55 | }
56 |
57 | connectDoneEvent.Set();
58 | }
59 | }), tcpClient
60 | );
61 | }
62 | catch (Exception ex) {
63 | tcpClient.Close();
64 |
65 | if (ex is SocketException || ex is SecurityException) {
66 | throw new ProxyException("Failed to connect to proxy-server", ex);
67 | }
68 |
69 | throw;
70 | }
71 |
72 | if (!connectDoneEvent.Wait(Settings.ConnectTimeout)) {
73 | tcpClient.Close();
74 | throw new ProxyException("Failed to connect to proxy-server");
75 | }
76 |
77 | if (connectException != null) {
78 | tcpClient.Close();
79 |
80 | if (connectException is SocketException) {
81 | throw new ProxyException("Failed to connect to proxy-server", connectException);
82 | }
83 | else {
84 | throw connectException;
85 | }
86 | }
87 |
88 | if (!tcpClient.Connected) {
89 | tcpClient.Close();
90 | throw new ProxyException("Failed to connect to proxy-server");
91 | }
92 | #endregion
93 |
94 | tcpClient.SendTimeout = Settings.ReadWriteTimeOut;
95 | tcpClient.ReceiveTimeout = Settings.ReadWriteTimeOut;
96 |
97 | var connectedTcpClient = client.CreateConnection(
98 | destinationHost,
99 | destinationPort,
100 | tcpClient);
101 |
102 | return connectedTcpClient.GetStream();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/ProxyException.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy;
2 | ///
3 | /// Represents errors that occur during proxy execution.
4 | ///
5 | public class ProxyException : Exception {
6 | public ProxyException() : base() { }
7 | ///
8 | /// Initializes a new instance of the with a specified error message
9 | /// and a reference to the inner exception that is the cause of this exception.
10 | ///
11 | /// The error message that explains the reason for the exception.
12 | public ProxyException(string message) : base(message) { }
13 | ///
14 | /// Initializes a new instance of the with a specified error message
15 | /// and a reference to the inner exception that is the cause of this exception.
16 | ///
17 | /// The error message that explains the reason for the exception.
18 | /// The exception that is the cause of the current exception, or a reference.
19 | public ProxyException(string message, Exception innerException) : base(message, innerException) { }
20 | }
21 |
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/Request/RequestBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy.Request;
2 | using System.Net;
3 | using System.Net.Http;
4 | using System.Net.Http.Headers;
5 | using System.Text;
6 | using SocksSharp.Extensions;
7 | internal class RequestBuilder {
8 | private readonly string newLine = "\r\n";
9 |
10 | private readonly HttpRequestMessage request;
11 | private readonly CookieContainer cookies;
12 |
13 | public RequestBuilder(HttpRequestMessage request) : this(request, null) { }
14 |
15 | public RequestBuilder(HttpRequestMessage request, CookieContainer cookies) {
16 | this.request = request;
17 | this.cookies = cookies;
18 | }
19 |
20 | public byte[] BuildStartingLine() {
21 | var uri = request.RequestUri;
22 |
23 | var startingLine = $"{request.Method.Method} {uri.PathAndQuery} HTTP/{request.Version}" + newLine;
24 |
25 | if (string.IsNullOrEmpty(request.Headers.Host)) {
26 | startingLine += "Host: " + uri.Host + newLine;
27 | }
28 |
29 | return ToByteArray(startingLine);
30 | }
31 |
32 | public byte[] BuildHeaders(bool hasContent) {
33 | var headers = GetHeaders(request.Headers);
34 | if (hasContent) {
35 | var contentHeaders = GetHeaders(request.Content.Headers);
36 | headers = !string.IsNullOrWhiteSpace(headers) ? string.Join(newLine, headers, contentHeaders) : contentHeaders;
37 | }
38 |
39 | return ToByteArray(headers + newLine + newLine);
40 | }
41 |
42 | private string GetHeaders(HttpHeaders headers) {
43 | List headersList = [];
44 |
45 | foreach (var header in headers) {
46 | string headerKeyAndValue = string.Empty;
47 |
48 | if (header.Value is string[] values && values.Length < 2) {
49 | if (values.Length > 0 && !string.IsNullOrEmpty(values[0])) {
50 | headerKeyAndValue = header.Key + ": " + values[0];
51 | }
52 | }
53 | else {
54 | string headerValue = headers.GetHeaderString(header.Key);
55 | if (!string.IsNullOrEmpty(headerValue)) {
56 | headerKeyAndValue = header.Key + ": " + headerValue;
57 | }
58 | }
59 |
60 | if (!string.IsNullOrEmpty(headerKeyAndValue)) {
61 | headersList.Add(headerKeyAndValue);
62 | }
63 | }
64 |
65 | if (headers is HttpContentHeaders && !headersList.Contains("Content-Length")) {
66 | var content = headers as HttpContentHeaders;
67 | if (content.ContentLength > 0) {
68 | headersList.Add($"Content-Length: {content.ContentLength}");
69 | }
70 | }
71 |
72 | if (cookies != null) {
73 | var cookiesCollection = cookies.GetCookies(request.RequestUri);
74 | var rawCookies = "Cookie: ";
75 |
76 | foreach (var cookie in cookiesCollection) {
77 | rawCookies += cookie + "; ";
78 | }
79 |
80 | if (cookiesCollection.Count > 0) {
81 | headersList.Add(rawCookies);
82 | }
83 | }
84 |
85 | return string.Join("\r\n", [.. headersList]);
86 | }
87 |
88 | private byte[] ToByteArray(string data) {
89 | return Encoding.ASCII.GetBytes(data);
90 | }
91 | }
--------------------------------------------------------------------------------
/src/fw-runtimes/Networking/SocksSharp/Proxy/Response/IResponseBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace SocksSharp.Proxy.Response;
2 | using System.IO;
3 | using System.Net.Http;
4 | using System.Threading;
5 | public interface IResponseBuilder {
6 | int ReceiveTimeout { get; set; }
7 |
8 | Task GetResponseAsync(HttpRequestMessage request, Stream stream);
9 |
10 | Task GetResponseAsync(HttpRequestMessage request, Stream stream, CancellationToken cancellationToken);
11 | }
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/AllowNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that is allowed as an input even if the
5 | /// corresponding type disallows it.
6 | ///
7 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class AllowNullAttribute : Attribute {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | public AllowNullAttribute() { }
15 | }
16 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/DisallowNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that is disallowed as an input even if the
5 | /// corresponding type allows it.
6 | ///
7 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class DisallowNullAttribute : Attribute {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | public DisallowNullAttribute() { }
15 | }
16 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/DoesNotReturnAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that a method that will never return under any circumstance.
5 | ///
6 | [AttributeUsage(AttributeTargets.Method, Inherited = false)]
7 | [DebuggerNonUserCode]
8 | [ExcludeFromCodeCoverage]
9 | public sealed class DoesNotReturnAttribute : Attribute {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | ///
14 | public DoesNotReturnAttribute() { }
15 | }
16 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/DoesNotReturnIfAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that the method will not return if the associated
5 | /// parameter is passed the specified value.
6 | ///
7 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class DoesNotReturnIfAttribute : Attribute {
11 | ///
12 | /// Gets the condition parameter value.
13 | /// Code after the method is considered unreachable by diagnostics if the argument
14 | /// to the associated parameter matches this value.
15 | ///
16 | public bool ParameterValue { get; }
17 |
18 | ///
19 | /// Initializes a new instance of the
20 | /// class with the specified parameter value.
21 | ///
22 | ///
23 | /// The condition parameter value.
24 | /// Code after the method is considered unreachable by diagnostics if the argument
25 | /// to the associated parameter matches this value.
26 | ///
27 | public DoesNotReturnIfAttribute(bool parameterValue) {
28 | ParameterValue = parameterValue;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Indicates that an API is experimental and it may change in the future.
5 | ///
6 | ///
7 | /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental
8 | /// feature is used. Authors can use this attribute to ship preview features in their assemblies.
9 | ///
10 | [global::System.AttributeUsage(
11 | global::System.AttributeTargets.Assembly |
12 | global::System.AttributeTargets.Module |
13 | global::System.AttributeTargets.Class |
14 | global::System.AttributeTargets.Struct |
15 | global::System.AttributeTargets.Enum |
16 | global::System.AttributeTargets.Constructor |
17 | global::System.AttributeTargets.Method |
18 | global::System.AttributeTargets.Property |
19 | global::System.AttributeTargets.Field |
20 | global::System.AttributeTargets.Event |
21 | global::System.AttributeTargets.Interface |
22 | global::System.AttributeTargets.Delegate,
23 | Inherited = false)]
24 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
25 | public sealed class ExperimentalAttribute : global::System.Attribute {
26 | ///
27 | /// Initializes a new instance of the class,
28 | /// specifying the ID that the compiler will use when reporting a use of the API the attribute applies to.
29 | ///
30 | /// The ID that the compiler will use when reporting a use of the API the attribute applies to.
31 | public ExperimentalAttribute(string diagnosticId) {
32 | DiagnosticId = diagnosticId;
33 | }
34 |
35 | ///
36 | /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to.
37 | ///
38 | /// The unique diagnostic ID.
39 | ///
40 | /// The diagnostic ID is shown in build output for warnings and errors.
41 | /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed.
42 | ///
43 | public string DiagnosticId { get; }
44 |
45 | ///
46 | /// Gets or sets the URL for corresponding documentation.
47 | /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID.
48 | ///
49 | /// The format string that represents a URL to corresponding documentation.
50 | /// An example format string is https://contoso.com/obsoletion-warnings/{0}.
51 | public string? UrlFormat { get; set; }
52 | }
53 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/MaybeNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that an output may be even if the
5 | /// corresponding type disallows it.
6 | ///
7 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class MaybeNullAttribute : Attribute {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | public MaybeNullAttribute() { }
15 | }
16 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/MaybeNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that when a method returns , the parameter may be even if the corresponding type disallows it.
5 | ///
6 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
7 | [DebuggerNonUserCode]
8 | [ExcludeFromCodeCoverage]
9 | public sealed class MaybeNullWhenAttribute : Attribute {
10 | ///
11 | /// Gets the return value condition.
12 | /// If the method returns this value, the associated parameter may be .
13 | ///
14 | public bool ReturnValue { get; }
15 |
16 | ///
17 | /// Initializes the attribute with the specified return value condition.
18 | ///
19 | ///
20 | /// The return value condition.
21 | /// If the method returns this value, the associated parameter may be .
22 | ///
23 | public MaybeNullWhenAttribute(bool returnValue) {
24 | ReturnValue = returnValue;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/MemberNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that the method or property will ensure that the listed field and property members have
5 | /// not- values.
6 | ///
7 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class MemberNotNullAttribute : Attribute {
11 | ///
12 | /// Gets field or property member names.
13 | ///
14 | public string[] Members { get; }
15 |
16 | ///
17 | /// Initializes the attribute with a field or property member.
18 | ///
19 | ///
20 | /// The field or property member that is promised to be not-null.
21 | ///
22 | public MemberNotNullAttribute(string member) {
23 | Members = [ member ];
24 | }
25 |
26 | ///
27 | /// Initializes the attribute with the list of field and property members.
28 | ///
29 | ///
30 | /// The list of field and property members that are promised to be not-null.
31 | ///
32 | public MemberNotNullAttribute(params string[] members) {
33 | Members = members;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/MemberNotNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that the method or property will ensure that the listed field and property members have
5 | /// non- values when returning with the specified return value condition.
6 | ///
7 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class MemberNotNullWhenAttribute : Attribute {
11 | ///
12 | /// Gets the return value condition.
13 | ///
14 | public bool ReturnValue { get; }
15 |
16 | ///
17 | /// Gets field or property member names.
18 | ///
19 | public string[] Members { get; }
20 |
21 | ///
22 | /// Initializes the attribute with the specified return value condition and a field or property member.
23 | ///
24 | ///
25 | /// The return value condition. If the method returns this value,
26 | /// the associated parameter will not be .
27 | ///
28 | ///
29 | /// The field or property member that is promised to be not-.
30 | ///
31 | public MemberNotNullWhenAttribute(bool returnValue, string member) {
32 | ReturnValue = returnValue;
33 | Members = [ member ];
34 | }
35 |
36 | ///
37 | /// Initializes the attribute with the specified return value condition and list
38 | /// of field and property members.
39 | ///
40 | ///
41 | /// The return value condition. If the method returns this value,
42 | /// the associated parameter will not be .
43 | ///
44 | ///
45 | /// The list of field and property members that are promised to be not-null.
46 | ///
47 | public MemberNotNullWhenAttribute(bool returnValue, params string[] members) {
48 | ReturnValue = returnValue;
49 | Members = members;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/NotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that an output is not even if the
5 | /// corresponding type allows it.
6 | ///
7 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class NotNullAttribute : Attribute {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | public NotNullAttribute() { }
15 | }
16 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/NotNullIfNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that the output will be non- if the
5 | /// named parameter is non-.
6 | ///
7 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
8 | [DebuggerNonUserCode]
9 | [ExcludeFromCodeCoverage]
10 | public sealed class NotNullIfNotNullAttribute : Attribute {
11 | ///
12 | /// Gets the associated parameter name.
13 | /// The output will be non- if the argument to the
14 | /// parameter specified is non-.
15 | ///
16 | public string ParameterName { get; }
17 |
18 | ///
19 | /// Initializes the attribute with the associated parameter name.
20 | ///
21 | ///
22 | /// The associated parameter name.
23 | /// The output will be non- if the argument to the
24 | /// parameter specified is non-.
25 | ///
26 | public NotNullIfNotNullAttribute(string parameterName) {
27 | ParameterName = parameterName;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/NotNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that when a method returns ,
5 | /// the parameter will not be even if the corresponding type allows it.
6 | ///
7 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
8 | [ExcludeFromCodeCoverage, DebuggerNonUserCode]
9 | public sealed class NotNullWhenAttribute : Attribute {
10 | ///
11 | /// Gets the return value condition.
12 | /// If the method returns this value, the associated parameter will not be .
13 | ///
14 | public bool ReturnValue { get; }
15 |
16 | ///
17 | /// Initializes the attribute with the specified return value condition.
18 | ///
19 | ///
20 | /// The return value condition.
21 | /// If the method returns this value, the associated parameter will not be .
22 | ///
23 | public NotNullWhenAttribute(bool returnValue) {
24 | ReturnValue = returnValue;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | ///
4 | /// Specifies that this constructor sets all required members for the current type, and callers
5 | /// do not need to set any required members themselves.
6 | ///
7 | [global::System.AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
8 | [global::System.Diagnostics.DebuggerNonUserCode]
9 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
10 | public sealed class SetsRequiredMembersAttribute : Attribute { }
11 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CompilerServices/CollectionBuilderAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace System.Runtime.CompilerServices;
2 | [global::System.AttributeUsage(
3 | global::System.AttributeTargets.Class |
4 | global::System.AttributeTargets.Struct |
5 | global::System.AttributeTargets.Interface,
6 | Inherited = false)]
7 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
8 | public sealed class CollectionBuilderAttribute : Attribute {
9 | ///
10 | /// Initialize the attribute to refer to the method on the type.
11 | ///
12 | /// The type of the builder to use to construct the collection.
13 | /// The name of the method on the builder to use to construct the collection.
14 | ///
15 | /// must refer to a static method that accepts a single parameter of
16 | /// type and returns an instance of the collection being built containing
17 | /// a copy of the data from that span. In future releases of .NET, additional patterns may be supported.
18 | ///
19 | public CollectionBuilderAttribute(Type builderType, string methodName) {
20 | BuilderType = builderType;
21 | MethodName = methodName;
22 | }
23 |
24 | ///
25 | /// Gets the type of the builder to use to construct the collection.
26 | ///
27 | public Type BuilderType { get; }
28 |
29 | ///
30 | /// Gets the name of the method on the builder to use to construct the collection.
31 | ///
32 | ///
33 | /// This should match the metadata name of the target method.
34 | /// For example, this might be ".ctor" if targeting the type's constructor.
35 | ///
36 | public string MethodName { get; }
37 | }
38 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Diagnostics/CompilerServices/StringSyntaxAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Diagnostics.CodeAnalysis;
3 | /// Specifies the syntax used in a string.
4 | [global::System.AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
5 | [global::System.Diagnostics.DebuggerNonUserCode]
6 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
7 | public sealed class StringSyntaxAttribute : Attribute {
8 | /// Initializes the with the identifier of the syntax used.
9 | /// The syntax identifier.
10 | public StringSyntaxAttribute(string syntax) {
11 | Syntax = syntax;
12 | Arguments = [];
13 | }
14 |
15 | /// Initializes the with the identifier of the syntax used.
16 | /// The syntax identifier.
17 | /// Optional arguments associated with the specific syntax employed.
18 | public StringSyntaxAttribute(string syntax, params object?[] arguments) {
19 | Syntax = syntax;
20 | Arguments = arguments;
21 | }
22 |
23 | /// Gets the identifier of the syntax used.
24 | public string Syntax { get; }
25 |
26 | /// Optional arguments associated with the specific syntax employed.
27 | public object?[] Arguments { get; }
28 |
29 | /// The syntax identifier for strings containing composite formats for string formatting.
30 | public const string CompositeFormat = nameof(CompositeFormat);
31 | /// The syntax identifier for strings containing date format specifiers.
32 | public const string DateOnlyFormat = nameof(DateOnlyFormat);
33 | /// The syntax identifier for strings containing date and time format specifiers.
34 | public const string DateTimeFormat = nameof(DateTimeFormat);
35 | /// The syntax identifier for strings containing format specifiers.
36 | public const string EnumFormat = nameof(EnumFormat);
37 | /// The syntax identifier for strings containing format specifiers.
38 | public const string GuidFormat = nameof(GuidFormat);
39 | /// The syntax identifier for strings containing JavaScript Object Notation (JSON).
40 | public const string Json = nameof(Json);
41 | /// The syntax identifier for strings containing numeric format specifiers.
42 | public const string NumericFormat = nameof(NumericFormat);
43 | /// The syntax identifier for strings containing regular expressions.
44 | public const string Regex = nameof(Regex);
45 | /// The syntax identifier for strings containing time format specifiers.
46 | public const string TimeOnlyFormat = nameof(TimeOnlyFormat);
47 | /// The syntax identifier for strings containing format specifiers.
48 | public const string TimeSpanFormat = nameof(TimeSpanFormat);
49 | /// The syntax identifier for strings containing URIs.
50 | public const string Uri = nameof(Uri);
51 | /// The syntax identifier for strings containing XML.
52 | public const string Xml = nameof(Xml);
53 | }
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Range.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | // https://github.com/dotnet/runtime/blob/419e949d258ecee4c40a460fb09c66d974229623/src/libraries/System.Private.CoreLib/src/System/Range.cs
3 | namespace System;
4 | /// Represent a range has start and end indexes.
5 | ///
6 | /// Range is used by the C# compiler to support the range syntax.
7 | ///
8 | /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
9 | /// int[] subArray1 = someArray[0..2]; // { 1, 2 }
10 | /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
11 | ///
12 | ///
13 | [global::System.Diagnostics.DebuggerStepThrough]
14 | public readonly struct Range : IEquatable {
15 | /// Represent the inclusive start index of the Range.
16 | public Index Start { get; }
17 |
18 | /// Represent the exclusive end index of the Range.
19 | public Index End { get; }
20 |
21 | /// Construct a Range object using the start and end indexes.
22 | /// Represent the inclusive start index of the range.
23 | /// Represent the exclusive end index of the range.
24 | public Range(Index start, Index end) {
25 | Start = start;
26 | End = end;
27 | }
28 |
29 | #nullable enable
30 | /// Indicates whether the current Range object is equal to another object of the same type.
31 | /// An object to compare with this object
32 | public override bool Equals(object? value) =>
33 | value is Range r &&
34 | r.Start.Equals(Start) &&
35 | r.End.Equals(End);
36 | #nullable disable
37 |
38 | /// Indicates whether the current Range object is equal to another Range object.
39 | /// An object to compare with this object
40 | public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End);
41 |
42 | /// Returns the hash code for this instance.
43 | public override int GetHashCode() {
44 | return (Start.GetHashCode() * 31) + End.GetHashCode();
45 | }
46 |
47 | /// Converts the value of the current Range object to its equivalent string representation.
48 | public override string ToString() {
49 | return Start + ".." + End;
50 | }
51 |
52 | /// Create a Range object starting from start index to the end of the collection.
53 | public static Range StartAt(Index start) => new(start, Index.End);
54 |
55 | /// Create a Range object starting from first element in the collection to the end Index.
56 | public static Range EndAt(Index end) => new(Index.Start, end);
57 |
58 | /// Create a Range object starting from first element to the end.
59 | public static Range All => new(Index.Start, Index.End);
60 |
61 | /// Calculate the start offset and length of range object using a collection length.
62 | /// The length of the collection that the range will be used with. length has to be a positive value.
63 | ///
64 | /// For performance reason, we don't validate the input length parameter against negative values.
65 | /// It is expected Range will be used with collections which always have non negative length/count.
66 | /// We validate the range is inside the length scope though.
67 | ///
68 | [Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
69 | public (int Offset, int Length) GetOffsetAndLength(int length) {
70 | int start;
71 | Index startIndex = Start;
72 | if (startIndex.IsFromEnd)
73 | start = length - startIndex.Value;
74 | else
75 | start = startIndex.Value;
76 |
77 | int end;
78 | Index endIndex = End;
79 | if (endIndex.IsFromEnd)
80 | end = length - endIndex.Value;
81 | else
82 | end = endIndex.Value;
83 |
84 | if ((uint)end > (uint)length || (uint)start > (uint)end) {
85 | throw new ArgumentOutOfRangeException(nameof(length));
86 | }
87 |
88 | return (start, end - start);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Runtime.CompilerServices;
3 | [global::System.AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
4 | [global::System.Diagnostics.DebuggerNonUserCode]
5 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
6 | public sealed class CallerArgumentExpressionAttribute : Attribute {
7 | public CallerArgumentExpressionAttribute(string parameterName) {
8 | ParameterName = parameterName;
9 | }
10 | public string ParameterName { get; }
11 | }
12 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Runtime.CompilerServices;
3 | ///
4 | /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied.
5 | ///
6 | [global::System.AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
7 | [global::System.Diagnostics.DebuggerNonUserCode]
8 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
9 | public sealed class CompilerFeatureRequiredAttribute : Attribute {
10 | public CompilerFeatureRequiredAttribute(string featureName) {
11 | FeatureName = featureName;
12 | }
13 |
14 | ///
15 | /// The name of the compiler feature.
16 | ///
17 | public string FeatureName { get; }
18 |
19 | ///
20 | /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand .
21 | ///
22 | public bool IsOptional { get; init; }
23 |
24 | ///
25 | /// The used for the ref structs C# feature.
26 | ///
27 | public const string RefStructs = nameof(RefStructs);
28 |
29 | ///
30 | /// The used for the required members C# feature.
31 | ///
32 | public const string RequiredMembers = nameof(RequiredMembers);
33 | }
34 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Runtime/CompilerServices/IsExternalInit.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Runtime.CompilerServices;
3 | using global::System.ComponentModel;
4 | [global::System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
5 | [global::System.Diagnostics.DebuggerNonUserCode]
6 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
7 | public static class IsExternalInit { }
8 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Runtime/CompilerServices/RequiredMemberAttribute.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Runtime.CompilerServices;
3 | /// Specifies that a type has required members or that a member is required.
4 | [global::System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
5 | [global::System.Diagnostics.DebuggerNonUserCode]
6 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
7 | public sealed class RequiredMemberAttribute : Attribute { }
8 |
--------------------------------------------------------------------------------
/src/fw-runtimes/System/Runtime/CompilerServices/RuntimeHelpers.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace System.Runtime.CompilerServices;
3 | [global::System.Diagnostics.DebuggerNonUserCode]
4 | [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
5 | // This will be required to duplicated in projects that require the use of this.
6 | internal static class RuntimeHelpers {
7 | public static int OffsetToStringData { get; }
8 | public static T[] GetSubArray(T[] array, Range range) {
9 | if (array is null) {
10 | throw new ArgumentNullException();
11 | }
12 |
13 | (int offset, int length) = range.GetOffsetAndLength(array.Length);
14 |
15 | if (default(T) is not null || typeof(T[]) == array.GetType()) {
16 | // We know the type of the array to be exactly T[].
17 |
18 | if (length == 0) {
19 | return [];
20 | }
21 |
22 | var dest = new T[length];
23 | Array.Copy(array, offset, dest, 0, length);
24 | return dest;
25 | }
26 | else {
27 | // The array is actually a U[] where U:T.
28 | T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType()!, length);
29 | Array.Copy(array, offset, dest, 0, length);
30 | return dest;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/fw-runtimes/fw-runtimes.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | a0fc4aca-80c0-4151-b41c-d538b779d1a6
5 | 14.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------