2021-03-01 20:36:36 +01:00
|
|
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
|
|
// See LICENSE.txt for license information.
|
|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
|
|
|
using System.Net;
|
|
|
|
using System.Net.Sockets;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Windows;
|
|
|
|
using Windows.Storage;
|
|
|
|
|
|
|
|
namespace Focalboard {
|
|
|
|
/// <summary>
|
|
|
|
/// Interaction logic for App.xaml
|
|
|
|
/// </summary>
|
|
|
|
public partial class App : Application {
|
|
|
|
public string sessionToken = "";
|
|
|
|
public int port;
|
|
|
|
|
|
|
|
private Mutex mutex;
|
|
|
|
|
|
|
|
App() {
|
|
|
|
SingleInstanceCheck();
|
|
|
|
|
|
|
|
Startup += App_Startup;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SingleInstanceCheck() {
|
|
|
|
bool isOnlyInstance = false;
|
|
|
|
mutex = new Mutex(true, @"Focalboard", out isOnlyInstance);
|
|
|
|
if (!isOnlyInstance) {
|
|
|
|
ShowExistingWindow();
|
|
|
|
Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[DllImport("User32.dll")]
|
|
|
|
private static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
|
|
|
|
|
|
[DllImport("user32.dll")]
|
|
|
|
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
|
|
|
|
|
|
// shows the window of the single-instance that is already open
|
|
|
|
private void ShowExistingWindow() {
|
|
|
|
var currentProcess = Process.GetCurrentProcess();
|
|
|
|
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
|
|
|
|
foreach (var process in processes) {
|
|
|
|
// the single-instance already open should have a MainWindowHandle
|
|
|
|
if (process.MainWindowHandle != IntPtr.Zero) {
|
|
|
|
// restores the window in case it was minimized
|
|
|
|
const int SW_SHOWNORMAL = 1;
|
|
|
|
ShowWindow(process.MainWindowHandle, SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
// brings the window to the foreground
|
|
|
|
SetForegroundWindow(process.MainWindowHandle);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void App_Startup(object sender, StartupEventArgs e) {
|
|
|
|
Debug.WriteLine($"App_Startup()");
|
|
|
|
|
|
|
|
try {
|
|
|
|
InitServer();
|
|
|
|
} catch (Exception ex) {
|
|
|
|
MessageBox.Show($"InitServer ERROR: {ex.ToString()}", "Focalboard");
|
|
|
|
Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void InitServer() {
|
|
|
|
port = FindFreePort();
|
|
|
|
Debug.WriteLine("port: {0}", port);
|
|
|
|
|
|
|
|
sessionToken = CreateSessionToken();
|
|
|
|
|
|
|
|
// Need to set CWD so the server can read the config file
|
|
|
|
var appFolder = Utils.GetAppFolder();
|
|
|
|
Directory.SetCurrentDirectory(appFolder);
|
|
|
|
|
2021-04-22 03:25:26 +02:00
|
|
|
string appDataFolder;
|
2021-03-01 20:36:36 +01:00
|
|
|
try {
|
2021-04-22 03:25:26 +02:00
|
|
|
appDataFolder = ApplicationData.Current.LocalFolder.Path;
|
2021-03-01 20:36:36 +01:00
|
|
|
} catch {
|
|
|
|
var documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
2021-04-22 03:25:26 +02:00
|
|
|
appDataFolder = Path.Combine(documentsFolder, "Focalboard");
|
|
|
|
Directory.CreateDirectory(appDataFolder);
|
2021-03-01 20:36:36 +01:00
|
|
|
// Not a UWP app, store in Documents
|
2021-04-22 03:25:26 +02:00
|
|
|
|
|
|
|
// FIXUP code: Copy from old DB location
|
|
|
|
var oldDBPath = Path.Combine(documentsFolder, "focalboard.db");
|
|
|
|
var newDBPath = Path.Combine(appDataFolder, "focalboard.db");
|
|
|
|
if (!File.Exists(newDBPath) && File.Exists(oldDBPath)) {
|
|
|
|
Debug.WriteLine($"Moving DB file from: {oldDBPath} to {newDBPath}");
|
|
|
|
File.Move(oldDBPath, newDBPath);
|
|
|
|
}
|
2021-03-01 20:36:36 +01:00
|
|
|
}
|
2021-04-22 03:25:26 +02:00
|
|
|
|
|
|
|
var dbPath = Path.Combine(appDataFolder, "focalboard.db");
|
2021-03-01 20:36:36 +01:00
|
|
|
Debug.WriteLine($"dbPath: {dbPath}");
|
|
|
|
|
2021-04-22 03:25:26 +02:00
|
|
|
var filesPath = Path.Combine(appDataFolder, "files");
|
|
|
|
Debug.WriteLine($"filesPath: {filesPath}");
|
|
|
|
|
2021-03-01 20:36:36 +01:00
|
|
|
var cwd = Directory.GetCurrentDirectory();
|
|
|
|
var webFolder = Path.Combine(cwd, @"pack");
|
|
|
|
webFolder = webFolder.Replace(@"\", @"/");
|
2021-04-22 03:25:26 +02:00
|
|
|
filesPath = filesPath.Replace(@"\", @"/");
|
2021-03-01 20:36:36 +01:00
|
|
|
dbPath = dbPath.Replace(@"\", @"/");
|
|
|
|
byte[] webFolderBytes = Encoding.UTF8.GetBytes(webFolder);
|
2021-04-22 03:25:26 +02:00
|
|
|
byte[] filesPathBytes = Encoding.UTF8.GetBytes(filesPath);
|
2021-03-01 20:36:36 +01:00
|
|
|
byte[] sessionTokenBytes = Encoding.UTF8.GetBytes(sessionToken);
|
|
|
|
byte[] dbPathBytes = Encoding.UTF8.GetBytes(dbPath);
|
2021-10-26 14:19:20 +02:00
|
|
|
byte[] configFilePathBytes = Encoding.UTF8.GetBytes("");
|
|
|
|
GoFunctions.StartServer(webFolderBytes, filesPathBytes, port, sessionTokenBytes, dbPathBytes, configFilePathBytes);
|
2021-03-01 20:36:36 +01:00
|
|
|
|
|
|
|
Debug.WriteLine("Server started");
|
|
|
|
}
|
|
|
|
|
|
|
|
private string CreateSessionToken() {
|
|
|
|
using (RandomNumberGenerator rng = new RNGCryptoServiceProvider()) {
|
|
|
|
byte[] tokenData = new byte[32];
|
|
|
|
rng.GetBytes(tokenData);
|
|
|
|
|
|
|
|
string token = Convert.ToBase64String(tokenData);
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private int FindFreePort() {
|
|
|
|
int port = 0;
|
|
|
|
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
try {
|
|
|
|
var localEP = new IPEndPoint(IPAddress.Any, 0);
|
|
|
|
socket.Bind(localEP);
|
|
|
|
localEP = (IPEndPoint)socket.LocalEndPoint;
|
|
|
|
port = localEP.Port;
|
|
|
|
} finally {
|
|
|
|
socket.Close();
|
|
|
|
}
|
|
|
|
return port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static class GoFunctions {
|
|
|
|
[DllImport(@"focalboard-server.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
2021-10-26 14:19:20 +02:00
|
|
|
public static extern void StartServer(byte[] webPath, byte[] filesPath, int port, byte[] singleUserToken, byte[] dbConfigString, byte[] configFilePath);
|
2021-03-01 20:36:36 +01:00
|
|
|
|
|
|
|
[DllImport(@"focalboard-server.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
|
|
|
public static extern void StopServer();
|
|
|
|
}
|
|
|
|
}
|