using System; using System.IO; using System.IO.Pipes; using System.Text; using System.Threading; using System.Web.Script.Serialization; using System.Collections.Generic; using System.Windows.Forms; using Microsoft.Win32; internal static class Bridge { const string Host = "online.turkservis.aiturk"; const string Origin = "chrome-extension://ikcplfhgapaabedillejmggjcabpkolp/"; const int MaxFrame = 512 * 1024; static readonly object OutputLock = new object(); static readonly JavaScriptSerializer Json = new JavaScriptSerializer { MaxJsonLength = MaxFrame }; static readonly Encoding Utf8 = new UTF8Encoding(false, true); static string ProductDirectory() { string local = Environment.GetEnvironmentVariable("LOCALAPPDATA"); if (String.IsNullOrEmpty(local) || !Path.IsPathRooted(local)) local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); return Path.Combine(local, "TurkServis", "AITURK-IDE"); } static byte[] ReadExactly(Stream source, int count, bool eofAllowed) { var buffer = new byte[count]; int offset = 0; while (offset < count) { int read = source.Read(buffer, offset, count - offset); if (read == 0) { if (offset == 0 && eofAllowed) return null; throw new EndOfStreamException(); } offset += read; } return buffer; } static void WriteFrame(Stream output, string message) { byte[] data = Utf8.GetBytes(message); if (data.Length > MaxFrame) throw new InvalidDataException(); lock (OutputLock) { byte[] size = BitConverter.GetBytes(data.Length); output.Write(size, 0, size.Length); output.Write(data, 0, data.Length); output.Flush(); } } [STAThread] static int Main(string[] args) { if (args.Length == 0 || args[0] == "--install" || args[0] == "--uninstall") return Install(args.Length > 0 && args[0] == "--uninstall"); if (args[0] != Origin) return 2; Stream output = Console.OpenStandardOutput(); try { string discoveryPath = Path.Combine(ProductDirectory(), "chrome-bridge.json"); if (new FileInfo(discoveryPath).Length > 4096) throw new InvalidDataException(); var discovery = Json.Deserialize>(File.ReadAllText(discoveryPath)); string pipeName = Convert.ToString(discovery["pipe"]); string token = Convert.ToString(discovery["token"]); if (!System.Text.RegularExpressions.Regex.IsMatch(pipeName, "^aiturk-chrome-[a-f0-9]{32}$") || !System.Text.RegularExpressions.Regex.IsMatch(token, "^[a-f0-9]{64}$")) throw new InvalidDataException(); using (var pipe = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) { pipe.Connect(5000); var writer = new StreamWriter(pipe, Utf8) { AutoFlush = true }; writer.WriteLine(Json.Serialize(new { token = token })); var reader = new StreamReader(pipe, Utf8, false, 4096, true); var receiver = new Thread(() => { try { // Bounded character-by-character line framing: ReadLine alone // would allocate without a cap for a malformed local peer. var line = new StringBuilder(); int value; while ((value = reader.Read()) != -1) { if (value == '\n') { WriteFrame(output, line.ToString()); line.Clear(); } else { line.Append((char)value); if (line.Length > MaxFrame) throw new InvalidDataException(); } } } catch { } Environment.Exit(0); }); receiver.IsBackground = true; receiver.Start(); Stream input = Console.OpenStandardInput(); while (true) { byte[] header = ReadExactly(input, 4, true); if (header == null) break; uint size = BitConverter.ToUInt32(header, 0); if (size == 0 || size > MaxFrame) throw new InvalidDataException(); string frame = Utf8.GetString(ReadExactly(input, (int)size, false)); // Normalize JSON so embedded newlines cannot inject pipe frames. var message = Json.Deserialize>(frame); writer.WriteLine(Json.Serialize(message)); } } return 0; } catch { try { WriteFrame(output, Json.Serialize(new { @event = "error", message = "AITURK IDE bağlantısı bulunamadı. Chrome destekli IDE sürümünü açın; ardından Yeniden bağlan düğmesine basın." })); } catch { } return 1; } } static int Install(bool remove) { string destination = Path.Combine(ProductDirectory(), "ChromeNativeHost"); string keyPath = @"Software\Google\Chrome\NativeMessagingHosts\" + Host; string message = remove ? "Chrome bağlantı kaydı kaldırılacak. IDE konuşmaları ve eklenti dosyaları korunur. Devam edilsin mi?" : "AITURK Chrome bağlantısı bu Windows kullanıcısı için kurulacak. Yalnızca AITURK eklentisi, açık IDE'deki konuşmaları okuyup mesaj gönderebilecek. Yönetici yetkisi gerekmez. Devam edilsin mi?"; if (MessageBox.Show(message, "AITURK Chrome Bağlantısı", MessageBoxButtons.YesNo, MessageBoxIcon.Information) != DialogResult.Yes) return 0; try { if (remove) { Registry.CurrentUser.DeleteSubKey(keyPath, false); MessageBox.Show("Chrome bağlantı kaydı kaldırıldı. Dosyalar ve konuşmalar korundu.", "AITURK"); return 0; } Directory.CreateDirectory(destination); string target = Path.Combine(destination, "AiturkChromeBridge.exe"); string source = System.Reflection.Assembly.GetExecutingAssembly().Location; if (!String.Equals(Path.GetFullPath(source), Path.GetFullPath(target), StringComparison.OrdinalIgnoreCase)) File.Copy(source, target, true); string manifest = Path.Combine(destination, Host + ".json"); File.WriteAllText(manifest, Json.Serialize(new { name = Host, description = "AITURK IDE Chrome bridge", path = target, type = "stdio", allowed_origins = new[] { Origin } }), new UTF8Encoding(false)); using (RegistryKey registry = Registry.CurrentUser.CreateSubKey(keyPath)) registry.SetValue("", manifest); MessageBox.Show("Bağlantı kuruldu.\n\n1. Chrome destekli AITURK IDE'yi açın.\n2. Chrome'da chrome://extensions sayfasını açın.\n3. Geliştirici modunu açıp Paketlenmemiş öğe yükle ile ZIP içindeki extension klasörünü seçin.\n4. AITURK simgesine basın.\n\nEklenti klasörünü silmeyin veya taşımayın.", "AITURK Chrome hazır"); return 0; } catch (Exception error) { MessageBox.Show("Kurulum tamamlanamadı. Chrome yan panelini kapatıp tekrar deneyin.\n" + error.Message, "AITURK", MessageBoxButtons.OK, MessageBoxIcon.Error); return 1; } } }