No files matched your search
@@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
@@ -52,5 +52,7 @@ AndroidRemote.dll.mdb
|
||||
/ClientServerLib/AndroidRemote/bin/AndroidRemote.dll
|
||||
/ClientServerLib/ClientTest/bin/Debug/Newtonsoft.Json.dll
|
||||
*.apk
|
||||
/Output/ClientServerLib.dll
|
||||
Installer/VocaluxeSetup_0.3.0Beta.exe
|
||||
Output/Vocaluxe_x64.exe
|
||||
/WebserverInitalConfig/bin/Release
|
||||
@@ -1,405 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public class CClient
|
||||
{
|
||||
private bool doConnect;
|
||||
private bool connected;
|
||||
private bool running;
|
||||
private int bufferLength = 8192;
|
||||
|
||||
private Thread clientThread;
|
||||
private IPEndPoint serverEndPoint;
|
||||
private string ip;
|
||||
private int port;
|
||||
|
||||
private CConnection connection;
|
||||
private List<SRequest> requests;
|
||||
private List<SRequest> responses;
|
||||
private Object mutexRequests = new Object();
|
||||
private OnConnectionChanged onConnectionChanged;
|
||||
private OnSend onSend;
|
||||
private OnReceived onReceived;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return connected; }
|
||||
}
|
||||
|
||||
public CClient()
|
||||
{
|
||||
doConnect = false;
|
||||
connected = false;
|
||||
running = true;
|
||||
requests = new List<SRequest>();
|
||||
responses = new List<SRequest>();
|
||||
data = new byte[bufferLength];
|
||||
|
||||
connection = new CConnection(new TcpClient(), -1);
|
||||
}
|
||||
|
||||
public void Connect(string IP = "127.0.0.1", int Port = 3000, string Password = null,
|
||||
OnConnectionChanged OnConnectionChanged = null,
|
||||
OnSend OnSend = null,
|
||||
OnReceived OnReceived = null)
|
||||
{
|
||||
if (!doConnect)
|
||||
{
|
||||
onConnectionChanged = OnConnectionChanged;
|
||||
onSend = OnSend;
|
||||
onReceived = OnReceived;
|
||||
|
||||
ip = IP;
|
||||
port = Port;
|
||||
connection.Password = Password;
|
||||
doConnect = true;
|
||||
|
||||
if (clientThread == null)
|
||||
{
|
||||
running = true;
|
||||
clientThread = new Thread(new ThreadStart(Runner));
|
||||
clientThread.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
if (doConnect)
|
||||
{
|
||||
doConnect = false;
|
||||
|
||||
lock (mutexRequests)
|
||||
{
|
||||
requests.Clear();
|
||||
}
|
||||
|
||||
lock (responses)
|
||||
{
|
||||
responses.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
running = false;
|
||||
|
||||
if (clientThread != null)
|
||||
clientThread.Join(100);
|
||||
|
||||
clientThread = null;
|
||||
DoDisconnect();
|
||||
}
|
||||
|
||||
public void SendMessage(byte[] Message, ResponseCallback Callback)
|
||||
{
|
||||
SRequest req = new SRequest();
|
||||
req.Command = Message;
|
||||
req.Callback = Callback;
|
||||
req.Response = null;
|
||||
|
||||
lock (mutexRequests)
|
||||
{
|
||||
requests.Add(req);
|
||||
}
|
||||
}
|
||||
|
||||
private void Runner()
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
if (!connected && doConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
IPAddress resolvedIP;
|
||||
if (TryResolveIPAddress(ip, out resolvedIP))
|
||||
{
|
||||
serverEndPoint = new IPEndPoint(resolvedIP, port);
|
||||
connection.TcpClient.Connect(serverEndPoint);
|
||||
connected = true;
|
||||
RaiseOnConnectionChanged();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
DoDisconnect();
|
||||
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
if (running && doConnect)
|
||||
Thread.Sleep(10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (connected && !doConnect)
|
||||
{
|
||||
DoDisconnect();
|
||||
}
|
||||
|
||||
if (doConnect && connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
Communicate();
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
catch
|
||||
{
|
||||
DoDisconnect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!doConnect && !connected)
|
||||
{
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
if (running && !doConnect)
|
||||
Thread.Sleep(10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryResolveIPAddress(string serverNameOrURL, out IPAddress resolvedIPAddress)
|
||||
{
|
||||
bool isResolved = false;
|
||||
IPHostEntry hostEntry = null;
|
||||
IPAddress resolvIP = null;
|
||||
try
|
||||
{
|
||||
if (!IPAddress.TryParse(serverNameOrURL, out resolvIP))
|
||||
{
|
||||
hostEntry = Dns.GetHostEntry(serverNameOrURL);
|
||||
if (hostEntry != null && hostEntry.AddressList != null && hostEntry.AddressList.Length > 0)
|
||||
{
|
||||
if (hostEntry.AddressList.Length == 1)
|
||||
{
|
||||
resolvIP = hostEntry.AddressList[0];
|
||||
isResolved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (IPAddress var in hostEntry.AddressList)
|
||||
{
|
||||
if (var.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
resolvIP = var;
|
||||
isResolved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
isResolved = true;
|
||||
}
|
||||
catch (Exception) {}
|
||||
finally
|
||||
{
|
||||
resolvedIPAddress = resolvIP;
|
||||
}
|
||||
return isResolved;
|
||||
}
|
||||
|
||||
private void DoDisconnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.TcpClient.Close();
|
||||
}
|
||||
catch { }
|
||||
|
||||
connection = new CConnection(new TcpClient(), -1);
|
||||
connected = false;
|
||||
doConnect = false;
|
||||
RaiseOnConnectionChanged();
|
||||
}
|
||||
|
||||
private void Communicate()
|
||||
{
|
||||
if (connection.TcpClient == null || !connection.TcpClient.Connected)
|
||||
DoDisconnect();
|
||||
|
||||
NetworkStream clientStream = connection.TcpClient.GetStream();
|
||||
|
||||
int bytesRead;
|
||||
|
||||
if (!connection.KeySet)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
return;
|
||||
|
||||
byte[] serverParam = new byte[bytesRead];
|
||||
Array.Copy(data, serverParam, bytesRead);
|
||||
RaiseOnReceived(serverParam);
|
||||
|
||||
byte[] clientResponse = connection.CreateClientKey(serverParam);
|
||||
RaiseOnSend(clientResponse);
|
||||
clientStream.Write(clientResponse, 0, clientResponse.Length);
|
||||
clientStream.Flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
while (requests.Count > 0)
|
||||
{
|
||||
SRequest res = HandleRequest(requests[0]);
|
||||
lock (responses)
|
||||
{
|
||||
responses.Add(res);
|
||||
}
|
||||
|
||||
lock (mutexRequests)
|
||||
{
|
||||
requests.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { };
|
||||
|
||||
lock (responses)
|
||||
{
|
||||
while (responses.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (responses[0].Callback != null)
|
||||
responses[0].Callback(responses[0].Response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
responses.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private SRequest HandleRequest(SRequest request)
|
||||
{
|
||||
SRequest response = new SRequest();
|
||||
response.Command = request.Command;
|
||||
response.Callback = request.Callback;
|
||||
response.Response = null;
|
||||
|
||||
NetworkStream clientStream = connection.TcpClient.GetStream();
|
||||
|
||||
RaiseOnSend(request.Command);
|
||||
byte[] encrypted = connection.Encrypt(request.Command);
|
||||
|
||||
int sendBytes = 0;
|
||||
while(sendBytes < encrypted.Length)
|
||||
{
|
||||
int bytesToSend = encrypted.Length - sendBytes;
|
||||
if (bytesToSend > bufferLength)
|
||||
bytesToSend = bufferLength;
|
||||
|
||||
clientStream.Write(encrypted, sendBytes, bytesToSend);
|
||||
sendBytes += bytesToSend;
|
||||
}
|
||||
clientStream.Flush();
|
||||
|
||||
byte[] data = new byte[bufferLength];
|
||||
int bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
return response;
|
||||
|
||||
int messageLength = BitConverter.ToInt32(data, 0);
|
||||
while (messageLength > bytesRead)
|
||||
{
|
||||
if (data.Length < messageLength + bufferLength)
|
||||
Array.Resize<byte>(ref data, messageLength + bufferLength);
|
||||
bytesRead += clientStream.Read(data, bytesRead, bufferLength);
|
||||
}
|
||||
|
||||
encrypted = new byte[bytesRead];
|
||||
Array.Copy(data, encrypted, bytesRead);
|
||||
response.Response = connection.Decrypt(encrypted);
|
||||
RaiseOnReceived(response.Response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private void RaiseOnConnectionChanged()
|
||||
{
|
||||
if (onConnectionChanged == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
onConnectionChanged(connected);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void RaiseOnSend(byte[] Message)
|
||||
{
|
||||
if (onSend == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
onSend(Message);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RaiseOnReceived(byte[] Message)
|
||||
{
|
||||
if (onReceived == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
onReceived(Message);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using DiffieHellman;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
internal class CConnection
|
||||
{
|
||||
private bool keySet;
|
||||
private byte[] key;
|
||||
private bool encryption;
|
||||
private string password;
|
||||
private CDiffieHellman dh;
|
||||
private UTF8Encoding encoder;
|
||||
private int connectionID;
|
||||
private static SHA256Managed SHA256 = new SHA256Managed();
|
||||
|
||||
public TcpClient TcpClient;
|
||||
|
||||
public bool KeySet
|
||||
{
|
||||
get { return keySet; }
|
||||
}
|
||||
|
||||
public int ConnectionID
|
||||
{
|
||||
get { return connectionID; }
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
set
|
||||
{
|
||||
password = value;
|
||||
encryption = value != null;
|
||||
keySet = false;
|
||||
}
|
||||
}
|
||||
|
||||
public CConnection(TcpClient client, int ConnectionID, string Password = null)
|
||||
{
|
||||
TcpClient = client;
|
||||
client.NoDelay = true;
|
||||
keySet = false;
|
||||
encryption = Password != null;
|
||||
password = Password;
|
||||
connectionID = ConnectionID;
|
||||
encoder = new UTF8Encoding();
|
||||
key = null;
|
||||
}
|
||||
|
||||
public byte[] GetKeyParams()
|
||||
{
|
||||
if (!encryption)
|
||||
{
|
||||
return encoder.GetBytes("NO ENCRYPTION");
|
||||
}
|
||||
|
||||
if (dh == null)
|
||||
dh = new CDiffieHellman(256).GenerateRequest();
|
||||
|
||||
return encoder.GetBytes(dh.ToString());
|
||||
}
|
||||
|
||||
public byte[] CreateClientKey(byte[] serverParam)
|
||||
{
|
||||
if (serverParam == null)
|
||||
return null;
|
||||
|
||||
string response = encoder.GetString(serverParam, 0, serverParam.Length);
|
||||
if (response == "NO ENCRYPTION")
|
||||
{
|
||||
encryption = false;
|
||||
keySet = true;
|
||||
key = null;
|
||||
return encoder.GetBytes(response);
|
||||
}
|
||||
|
||||
dh = new CDiffieHellman(256).GenerateResponse(response);
|
||||
key = _BuildHash(dh.Key, password);
|
||||
keySet = true;
|
||||
encryption = true;
|
||||
return encoder.GetBytes(dh.ToString());
|
||||
}
|
||||
|
||||
public void CreateServerKey(byte[] clientResponse)
|
||||
{
|
||||
string response = encoder.GetString(clientResponse, 0, clientResponse.Length);
|
||||
|
||||
if (response == "NO ENCRYPTION")
|
||||
{
|
||||
keySet = true;
|
||||
key = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dh == null)
|
||||
return;
|
||||
|
||||
dh.HandleResponse(response);
|
||||
key = _BuildHash(dh.Key, password);
|
||||
keySet = true;
|
||||
}
|
||||
|
||||
public byte[] Encrypt(byte[] Data)
|
||||
{
|
||||
return _Encrypt(_Compress(Data));
|
||||
}
|
||||
|
||||
public byte[] Decrypt(byte[] Data)
|
||||
{
|
||||
return _Decompress(_Decrypt(Data));
|
||||
}
|
||||
|
||||
private byte[] _BuildHash(byte[] Key, string Password)
|
||||
{
|
||||
if (Key == null || Password == null)
|
||||
return null;
|
||||
|
||||
byte[] hash = SHA256.ComputeHash(encoder.GetBytes(Password));
|
||||
byte[] serial = new byte[Key.Length + hash.Length];
|
||||
Array.Copy(Key, serial, Key.Length);
|
||||
Array.Copy(hash, 0, serial, Key.Length, hash.Length);
|
||||
|
||||
return SHA256.ComputeHash(serial);
|
||||
}
|
||||
|
||||
private byte[] _Encrypt(byte[] Data)
|
||||
{
|
||||
if (Data == null || (!keySet && encryption))
|
||||
return Data;
|
||||
|
||||
byte[] dataLength = BitConverter.GetBytes(Data.Length);
|
||||
|
||||
if (!encryption)
|
||||
{
|
||||
int len = 4 + dataLength.Length + Data.Length;
|
||||
byte[] messageLength = BitConverter.GetBytes(len);
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
stream.Write(messageLength, 0, messageLength.Length);
|
||||
stream.Write(dataLength, 0, dataLength.Length);
|
||||
stream.Write(Data, 0, Data.Length);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
using (Aes aes = new AesManaged())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.GenerateIV();
|
||||
|
||||
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(Data, 0, Data.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
|
||||
byte[] encrypted = memoryStream.ToArray();
|
||||
|
||||
int len = 4 + aes.IV.Length + dataLength.Length + encrypted.Length;
|
||||
byte[] messageLength = BitConverter.GetBytes(len);
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
stream.Write(messageLength, 0, messageLength.Length);
|
||||
stream.Write(aes.IV, 0, aes.IV.Length);
|
||||
stream.Write(dataLength, 0, dataLength.Length);
|
||||
stream.Write(encrypted, 0, encrypted.Length);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] _Decrypt(byte[] Data)
|
||||
{
|
||||
if (Data == null || (!keySet && encryption))
|
||||
return Data;
|
||||
|
||||
|
||||
int messageLength = BitConverter.ToInt32(Data, 0);
|
||||
if (messageLength > Data.Length)
|
||||
return null;
|
||||
|
||||
int dataLength;
|
||||
|
||||
if (!encryption)
|
||||
{
|
||||
dataLength = BitConverter.ToInt32(Data, 4);
|
||||
|
||||
byte[] message = new byte[dataLength];
|
||||
Array.Copy(Data, 8, message, 0, dataLength);
|
||||
return message;
|
||||
}
|
||||
|
||||
if (Data.Length < 25)
|
||||
return null;
|
||||
|
||||
byte[] IV = new byte[16];
|
||||
Array.Copy(Data, 4, IV, 0, 16);
|
||||
|
||||
dataLength = BitConverter.ToInt32(Data, 20);
|
||||
|
||||
using (Aes aes = new AesManaged())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.IV = IV;
|
||||
|
||||
byte[] encrypted = new byte[messageLength - 24];
|
||||
Array.Copy(Data, 24, encrypted, 0, encrypted.Length);
|
||||
|
||||
try
|
||||
{
|
||||
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(encrypted, 0, encrypted.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
cryptoStream.Close();
|
||||
|
||||
byte[] decrypted = memoryStream.ToArray();
|
||||
byte[] message = new byte[dataLength];
|
||||
Array.Copy(decrypted, message, dataLength);
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] _Compress(byte[] Data)
|
||||
{
|
||||
if (Data == null)
|
||||
return Data;
|
||||
|
||||
using (var compressed = new MemoryStream())
|
||||
{
|
||||
using (var gz = new GZipStream(compressed, CompressionMode.Compress, true))
|
||||
{
|
||||
gz.Write(Data, 0, Data.Length);
|
||||
}
|
||||
|
||||
byte[] result = null;
|
||||
|
||||
if (compressed.Length < Data.Length)
|
||||
{
|
||||
result = new byte[compressed.Length + 1];
|
||||
result[0] = 1; //data stream is compressed
|
||||
compressed.Position = 0;
|
||||
compressed.Read(result, 1, (int)compressed.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new byte[Data.Length + 1];
|
||||
result[0] = 0; //data stream is not compressed
|
||||
Array.Copy(Data, 0, result, 1, Data.Length);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] _Decompress(byte[] Data)
|
||||
{
|
||||
if (Data == null)
|
||||
return Data;
|
||||
|
||||
if (Data[0] == 0) //not compressed
|
||||
{
|
||||
byte[] result = new byte[Data.Length - 1];
|
||||
Array.Copy(Data, 1, result, 0, result.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
using (var inStream = new MemoryStream())
|
||||
{
|
||||
inStream.Write(Data, 1, Data.Length - 1);
|
||||
inStream.Position = 0;
|
||||
|
||||
using (var outStream = new MemoryStream())
|
||||
{
|
||||
using (var gz = new GZipStream(inStream, CompressionMode.Decompress, true))
|
||||
gz.CopyTo(outStream);
|
||||
|
||||
return outStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,125 +1,125 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public delegate void OnServerDiscovered(string IPAddress, string Hostname);
|
||||
|
||||
public class CDiscover
|
||||
{
|
||||
public static readonly string sTimeout = "Timeout";
|
||||
public static readonly string sFinished = "Finished";
|
||||
|
||||
private string _Keyword;
|
||||
private string _BroadcastAddress;
|
||||
private int _Port;
|
||||
|
||||
private Thread _DiscoverThread;
|
||||
private bool _DiscoverRunning;
|
||||
private OnServerDiscovered _OnDiscovered;
|
||||
|
||||
|
||||
private System.Timers.Timer _BroadcastTimer;
|
||||
|
||||
public CDiscover(int Port, string Keyword, string BroadcastAddress = "255.255.255.255")
|
||||
{
|
||||
_BroadcastAddress = BroadcastAddress;
|
||||
_Port = Port;
|
||||
_Keyword = Keyword;
|
||||
|
||||
_DiscoverRunning = false;
|
||||
_BroadcastTimer = new System.Timers.Timer();
|
||||
_BroadcastTimer.Elapsed += new ElapsedEventHandler(OnBroadcastEvent);
|
||||
_BroadcastTimer.Interval = 2500;
|
||||
}
|
||||
|
||||
public void StartBroadcasting()
|
||||
{
|
||||
_BroadcastTimer.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_BroadcastTimer.Stop();
|
||||
_DiscoverRunning = false;
|
||||
}
|
||||
|
||||
public void Discover(OnServerDiscovered OnDiscovered, int Timeout = 5000)
|
||||
{
|
||||
if (_DiscoverRunning)
|
||||
return;
|
||||
|
||||
_DiscoverRunning = true;
|
||||
_DiscoverThread = new Thread(() => _Discover(Timeout));
|
||||
_OnDiscovered = OnDiscovered;
|
||||
_DiscoverThread.Start();
|
||||
}
|
||||
|
||||
private void OnBroadcastEvent(object source, ElapsedEventArgs e)
|
||||
{
|
||||
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
s.EnableBroadcast = true;
|
||||
IPAddress broadcast = IPAddress.Parse(_BroadcastAddress);
|
||||
byte[] sendbuf = Encoding.UTF8.GetBytes(_Keyword);
|
||||
IPEndPoint ep = new IPEndPoint(broadcast, _Port);
|
||||
|
||||
s.SendTo(sendbuf, ep);
|
||||
s.Close();
|
||||
}
|
||||
|
||||
private void _Discover(int Timeout)
|
||||
{
|
||||
UdpClient listener = null;
|
||||
Stopwatch timer = new Stopwatch();
|
||||
|
||||
List<string> knownServer = new List<string>();
|
||||
bool foundSomething = false;
|
||||
timer.Start();
|
||||
while (_DiscoverRunning && timer.ElapsedMilliseconds < Timeout * 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener = new UdpClient(_Port);
|
||||
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _Port);
|
||||
listener.Client.ReceiveTimeout = Timeout;
|
||||
|
||||
byte[] bytes = listener.Receive(ref groupEP);
|
||||
string message = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
|
||||
|
||||
foundSomething = true;
|
||||
if (!knownServer.Contains(groupEP.Address.ToString()))
|
||||
{
|
||||
knownServer.Add(groupEP.Address.ToString());
|
||||
if (_OnDiscovered != null)
|
||||
{
|
||||
IPHostEntry e = Dns.GetHostEntry(groupEP.Address);
|
||||
string hostname = e.HostName;
|
||||
|
||||
_OnDiscovered(groupEP.Address.ToString(), hostname);
|
||||
}
|
||||
}
|
||||
|
||||
listener.Close();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.Close();
|
||||
}
|
||||
}
|
||||
_DiscoverRunning = false;
|
||||
|
||||
if (!foundSomething)
|
||||
_OnDiscovered(sTimeout, String.Empty);
|
||||
else
|
||||
_OnDiscovered(sFinished, String.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
public delegate void OnServerDiscovered(string IPAddress, string Hostname);
|
||||
|
||||
public class CDiscover
|
||||
{
|
||||
public static readonly string sTimeout = "Timeout";
|
||||
public static readonly string sFinished = "Finished";
|
||||
|
||||
private string _Keyword;
|
||||
private string _BroadcastAddress;
|
||||
private int _Port;
|
||||
|
||||
private Thread _DiscoverThread;
|
||||
private bool _DiscoverRunning;
|
||||
private OnServerDiscovered _OnDiscovered;
|
||||
|
||||
|
||||
private System.Timers.Timer _BroadcastTimer;
|
||||
|
||||
public CDiscover(int Port, string Keyword, string BroadcastAddress = "255.255.255.255")
|
||||
{
|
||||
_BroadcastAddress = BroadcastAddress;
|
||||
_Port = Port;
|
||||
_Keyword = Keyword;
|
||||
|
||||
_DiscoverRunning = false;
|
||||
_BroadcastTimer = new System.Timers.Timer();
|
||||
_BroadcastTimer.Elapsed += new ElapsedEventHandler(OnBroadcastEvent);
|
||||
_BroadcastTimer.Interval = 2500;
|
||||
}
|
||||
|
||||
public void StartBroadcasting()
|
||||
{
|
||||
_BroadcastTimer.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_BroadcastTimer.Stop();
|
||||
_DiscoverRunning = false;
|
||||
}
|
||||
|
||||
public void Discover(OnServerDiscovered OnDiscovered, int Timeout = 5000)
|
||||
{
|
||||
if (_DiscoverRunning)
|
||||
return;
|
||||
|
||||
_DiscoverRunning = true;
|
||||
_DiscoverThread = new Thread(() => _Discover(Timeout));
|
||||
_OnDiscovered = OnDiscovered;
|
||||
_DiscoverThread.Start();
|
||||
}
|
||||
|
||||
private void OnBroadcastEvent(object source, ElapsedEventArgs e)
|
||||
{
|
||||
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
s.EnableBroadcast = true;
|
||||
IPAddress broadcast = IPAddress.Parse(_BroadcastAddress);
|
||||
byte[] sendbuf = Encoding.UTF8.GetBytes(_Keyword);
|
||||
IPEndPoint ep = new IPEndPoint(broadcast, _Port);
|
||||
|
||||
s.SendTo(sendbuf, ep);
|
||||
s.Close();
|
||||
}
|
||||
|
||||
private void _Discover(int Timeout)
|
||||
{
|
||||
UdpClient listener = null;
|
||||
Stopwatch timer = new Stopwatch();
|
||||
|
||||
List<string> knownServer = new List<string>();
|
||||
bool foundSomething = false;
|
||||
timer.Start();
|
||||
while (_DiscoverRunning && timer.ElapsedMilliseconds < Timeout * 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener = new UdpClient(_Port);
|
||||
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _Port);
|
||||
listener.Client.ReceiveTimeout = Timeout;
|
||||
|
||||
byte[] bytes = listener.Receive(ref groupEP);
|
||||
string message = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
|
||||
|
||||
foundSomething = true;
|
||||
if (!knownServer.Contains(groupEP.Address.ToString()))
|
||||
{
|
||||
knownServer.Add(groupEP.Address.ToString());
|
||||
if (_OnDiscovered != null)
|
||||
{
|
||||
IPHostEntry e = Dns.GetHostEntry(groupEP.Address);
|
||||
string hostname = e.HostName;
|
||||
|
||||
_OnDiscovered(groupEP.Address.ToString(), hostname);
|
||||
}
|
||||
}
|
||||
|
||||
listener.Close();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.Close();
|
||||
}
|
||||
}
|
||||
_DiscoverRunning = false;
|
||||
|
||||
if (!foundSomething)
|
||||
_OnDiscovered(sTimeout, String.Empty);
|
||||
else
|
||||
_OnDiscovered(sFinished, String.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,194 +1,313 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace ClientServerLib
|
||||
namespace ServerLib
|
||||
{
|
||||
public class CServer
|
||||
{
|
||||
private TcpListener tcpListener;
|
||||
private Thread listenThread;
|
||||
private int port;
|
||||
private bool encryption;
|
||||
private string password;
|
||||
private int bufferLength = 8192;
|
||||
private bool running;
|
||||
private ServiceHost _Host;
|
||||
private Uri _BaseAddress;
|
||||
private bool _Encrypted = false;
|
||||
|
||||
private HandleRequest requestCallback;
|
||||
|
||||
private Dictionary<int, CConnection> clients;
|
||||
private Queue<int> ids;
|
||||
|
||||
public CServer(HandleRequest RequestCallback, int Port = 3000, string Password = null)
|
||||
private static SendKeyEventDelegate _SendKeyEvent;
|
||||
public static SendKeyEventDelegate SendKeyEvent
|
||||
{
|
||||
port = Port;
|
||||
running = false;
|
||||
requestCallback = RequestCallback;
|
||||
encryption = Password != null;
|
||||
password = Password;
|
||||
internal get { return CServer._SendKeyEvent; }
|
||||
set { CServer._SendKeyEvent = value; }
|
||||
}
|
||||
|
||||
clients = new Dictionary<int, CConnection>();
|
||||
ids = new Queue<int>(1000);
|
||||
#region profile
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
ids.Enqueue(i);
|
||||
private static GetProfileDataDelegate _GetProfileData;
|
||||
public static GetProfileDataDelegate GetProfileData
|
||||
{
|
||||
internal get { return CServer._GetProfileData; }
|
||||
set { CServer._GetProfileData = value; }
|
||||
}
|
||||
|
||||
private static SendProfileDataDelegate _SendProfileData;
|
||||
public static SendProfileDataDelegate SendProfileData
|
||||
{
|
||||
internal get { return CServer._SendProfileData; }
|
||||
set { CServer._SendProfileData = value; }
|
||||
}
|
||||
|
||||
private static GetProfileListDelegate _GetProfileList;
|
||||
public static GetProfileListDelegate GetProfileList
|
||||
{
|
||||
internal get { return CServer._GetProfileList; }
|
||||
set { CServer._GetProfileList = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region photo
|
||||
private static SendPhotoDelegate _SendPhoto;
|
||||
public static SendPhotoDelegate SendPhoto
|
||||
{
|
||||
get { return CServer._SendPhoto; }
|
||||
set { CServer._SendPhoto = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region website
|
||||
|
||||
private static GetSiteFileDelegate _GetSiteFile;
|
||||
public static GetSiteFileDelegate GetSiteFile
|
||||
{
|
||||
internal get { return CServer._GetSiteFile; }
|
||||
set { CServer._GetSiteFile = value; }
|
||||
}
|
||||
|
||||
private static GetDelayedImageDelegate _GetDelayedImage;
|
||||
public static GetDelayedImageDelegate GetDelayedImage
|
||||
{
|
||||
internal get { return CServer._GetDelayedImage; }
|
||||
set { CServer._GetDelayedImage = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region songs
|
||||
|
||||
private static GetSongDelegate _GetSong;
|
||||
public static GetSongDelegate GetSong
|
||||
{
|
||||
internal get { return CServer._GetSong; }
|
||||
set { CServer._GetSong = value; }
|
||||
}
|
||||
|
||||
private static GetAllSongsDelegate _GetAllSongs;
|
||||
public static GetAllSongsDelegate GetAllSongs
|
||||
{
|
||||
internal get { return CServer._GetAllSongs; }
|
||||
set { CServer._GetAllSongs = value; }
|
||||
}
|
||||
|
||||
private static GetCurrentSongIdDelegate _GetCurrentSongId;
|
||||
public static GetCurrentSongIdDelegate GetCurrentSongId
|
||||
{
|
||||
internal get { return CServer._GetCurrentSongId; }
|
||||
set { CServer._GetCurrentSongId = value; }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region playlist
|
||||
|
||||
private static GetPlaylistsDelegate _GetPlaylists;
|
||||
public static GetPlaylistsDelegate GetPlaylists
|
||||
{
|
||||
internal get { return _GetPlaylists; }
|
||||
set { _GetPlaylists = value; }
|
||||
}
|
||||
|
||||
|
||||
private static GetPlaylistDelegate _GetPlaylist;
|
||||
public static GetPlaylistDelegate GetPlaylist
|
||||
{
|
||||
internal get { return _GetPlaylist; }
|
||||
set { _GetPlaylist = value; }
|
||||
}
|
||||
|
||||
private static AddSongToPlaylistDelegate _AddSongToPlaylist;
|
||||
public static AddSongToPlaylistDelegate AddSongToPlaylist
|
||||
{
|
||||
internal get { return _AddSongToPlaylist; }
|
||||
set { _AddSongToPlaylist = value; }
|
||||
}
|
||||
|
||||
private static RemoveSongFromPlaylistDelegate _RemoveSongFromPlaylist;
|
||||
public static RemoveSongFromPlaylistDelegate RemoveSongFromPlaylist
|
||||
{
|
||||
internal get { return _RemoveSongFromPlaylist; }
|
||||
set { _RemoveSongFromPlaylist = value; }
|
||||
}
|
||||
|
||||
private static MoveSongInPlaylistDelegate _MoveSongInPlaylist;
|
||||
public static MoveSongInPlaylistDelegate MoveSongInPlaylist
|
||||
{
|
||||
internal get { return _MoveSongInPlaylist; }
|
||||
set { _MoveSongInPlaylist = value; }
|
||||
}
|
||||
|
||||
private static PlaylistContainsSongDelegate _PlaylistContainsSong;
|
||||
public static PlaylistContainsSongDelegate PlaylistContainsSong
|
||||
{
|
||||
internal get { return _PlaylistContainsSong; }
|
||||
set { _PlaylistContainsSong = value; }
|
||||
}
|
||||
|
||||
private static GetPlaylistSongsDelegate _GetPlaylistSongs;
|
||||
public static GetPlaylistSongsDelegate GetPlaylistSongs
|
||||
{
|
||||
internal get { return _GetPlaylistSongs; }
|
||||
set { _GetPlaylistSongs = value; }
|
||||
}
|
||||
|
||||
private static RemovePlaylistDelegate _RemovePlaylist;
|
||||
public static RemovePlaylistDelegate RemovePlaylist
|
||||
{
|
||||
internal get { return _RemovePlaylist; }
|
||||
set { _RemovePlaylist = value; }
|
||||
}
|
||||
|
||||
private static AddPlaylistDelegate _AddPlaylist;
|
||||
public static AddPlaylistDelegate AddPlaylist
|
||||
{
|
||||
internal get { return _AddPlaylist; }
|
||||
set { _AddPlaylist = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region user management
|
||||
|
||||
private static ValidatePasswordDelegate _ValidatePassword;
|
||||
public static ValidatePasswordDelegate ValidatePassword
|
||||
{
|
||||
internal get { return CServer._ValidatePassword; }
|
||||
set { CServer._ValidatePassword = value; }
|
||||
}
|
||||
|
||||
private static GetUserRoleDelegate _GetUserRole;
|
||||
public static GetUserRoleDelegate GetUserRole
|
||||
{
|
||||
internal get { return CServer._GetUserRole; }
|
||||
set { CServer._GetUserRole = value; }
|
||||
}
|
||||
|
||||
private static SetUserRoleDelegate _SetUserRole;
|
||||
public static SetUserRoleDelegate SetUserRole
|
||||
{
|
||||
internal get { return CServer._SetUserRole; }
|
||||
set { CServer._SetUserRole = value; }
|
||||
}
|
||||
|
||||
private static GetUserIdFromUsernameDelegate _GetUserIdFromUsername;
|
||||
public static GetUserIdFromUsernameDelegate GetUserIdFromUsername
|
||||
{
|
||||
internal get { return CServer._GetUserIdFromUsername; }
|
||||
set { CServer._GetUserIdFromUsername = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public CServer(int port, bool encrypted)
|
||||
{
|
||||
_Init(port, encrypted);
|
||||
}
|
||||
|
||||
#region server control
|
||||
|
||||
private void _Init(int port, bool encrypted)
|
||||
{
|
||||
string hostname = Dns.GetHostName();
|
||||
if (encrypted)
|
||||
{
|
||||
_BaseAddress = new Uri("https://" + hostname + ":" + port + "/");
|
||||
}
|
||||
else
|
||||
{
|
||||
_BaseAddress = new Uri("http://" + hostname + ":" + port + "/");
|
||||
}
|
||||
this._Encrypted = encrypted;
|
||||
_Host = new WebServiceHost(typeof(CWebservice), _BaseAddress);
|
||||
|
||||
WebHttpBinding wb = new WebHttpBinding
|
||||
{
|
||||
MaxReceivedMessageSize = 10485760,
|
||||
MaxBufferSize = 10485760,
|
||||
MaxBufferPoolSize = 10485760,
|
||||
ReaderQuotas = { MaxStringContentLength = 10485760, MaxArrayLength = 10485760, MaxBytesPerRead = 10485760 }
|
||||
};
|
||||
if (encrypted)
|
||||
{
|
||||
wb.Security.Mode = WebHttpSecurityMode.Transport;
|
||||
wb.Security.Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.None };
|
||||
}
|
||||
_Host.AddServiceEndpoint(typeof(ICWebservice), wb, "");
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!running)
|
||||
try
|
||||
{
|
||||
running = true;
|
||||
/*ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
|
||||
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
|
||||
smb.HttpGetEnabled = true;
|
||||
host.Description.Behaviors.Add(smb);*/
|
||||
|
||||
tcpListener = new TcpListener(IPAddress.Any, port);
|
||||
|
||||
listenThread = new Thread(new ThreadStart(ListenForClients));
|
||||
listenThread.Start();
|
||||
_Host.Open();
|
||||
}
|
||||
catch (CommunicationException e)
|
||||
{
|
||||
if (e is AddressAccessDeniedException || e is AddressAlreadyInUseException)
|
||||
{
|
||||
_RegisterUrlAndCert(_BaseAddress.Port);
|
||||
try
|
||||
{
|
||||
_Host.Abort();
|
||||
_Init(_BaseAddress.Port, _Encrypted);
|
||||
_Host.Open();
|
||||
}
|
||||
catch (CommunicationException e2)
|
||||
{
|
||||
_Host.Abort();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_Host.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (running)
|
||||
try
|
||||
{
|
||||
running = false;
|
||||
tcpListener.Stop();
|
||||
Thread.Sleep(100);
|
||||
listenThread.Join();
|
||||
|
||||
lock (clients)
|
||||
{
|
||||
int[] cIDs = new int[clients.Count];
|
||||
clients.Keys.CopyTo(cIDs, 0);
|
||||
|
||||
foreach (int id in cIDs)
|
||||
{
|
||||
clients.Remove(id);
|
||||
ids.Enqueue(id);
|
||||
}
|
||||
}
|
||||
_Host.Close();
|
||||
}
|
||||
catch (CommunicationException e)
|
||||
{
|
||||
_Host.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenForClients()
|
||||
private void _RegisterUrlAndCert(int port)
|
||||
{
|
||||
tcpListener.Start();
|
||||
TcpClient client;
|
||||
#if WIN
|
||||
|
||||
while (running)
|
||||
ProcessStartInfo info = new ProcessStartInfo
|
||||
{
|
||||
//wait for new client
|
||||
try
|
||||
{
|
||||
client = tcpListener.AcceptTcpClient();
|
||||
}
|
||||
catch
|
||||
{
|
||||
client = null;
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
int id = ids.Dequeue();
|
||||
CConnection connection = new CConnection(client, id, password);
|
||||
|
||||
lock (clients)
|
||||
{
|
||||
clients.Add(id, connection);
|
||||
}
|
||||
|
||||
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCom));
|
||||
|
||||
NetworkStream clientStream = client.GetStream();
|
||||
byte[] serverParams = connection.GetKeyParams();
|
||||
|
||||
try
|
||||
{
|
||||
clientStream.Write(serverParams, 0, serverParams.Length);
|
||||
clientStream.Flush();
|
||||
}
|
||||
catch
|
||||
{
|
||||
client = null;
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
clientThread.Start(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleClientCom(object client)
|
||||
{
|
||||
CConnection connection = (CConnection)client;
|
||||
TcpClient tcpClient = (TcpClient)connection.TcpClient;
|
||||
NetworkStream clientStream = tcpClient.GetStream();
|
||||
|
||||
byte[] data = new byte[bufferLength];
|
||||
int bytesRead;
|
||||
|
||||
while (running)
|
||||
FileName = "VocaluxeServerConfig.exe",
|
||||
Arguments = port.ToString() + " " + _Encrypted.ToString(),
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
Verb = "runas"
|
||||
};
|
||||
Process p = Process.Start(info);
|
||||
if (p != null)
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bytesRead = clientStream.Read(data, 0, bufferLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
|
||||
if (!connection.KeySet)
|
||||
{
|
||||
byte[] clientResponse = new byte[bytesRead];
|
||||
Array.Copy(data, clientResponse, bytesRead);
|
||||
connection.CreateServerKey(clientResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
//receive message
|
||||
int messageLength = BitConverter.ToInt32(data, 0);
|
||||
while (messageLength > bytesRead)
|
||||
{
|
||||
if (data.Length < messageLength + bufferLength)
|
||||
Array.Resize<byte>(ref data, messageLength + bufferLength);
|
||||
bytesRead += clientStream.Read(data, bytesRead, bufferLength);
|
||||
}
|
||||
|
||||
byte[] message = new byte[bytesRead];
|
||||
Array.Copy(data, message, bytesRead);
|
||||
byte[] decrypted = connection.Decrypt(message);
|
||||
|
||||
byte[] answer = HandleClientMessage(decrypted, connection);
|
||||
|
||||
//send message
|
||||
byte[] encrypted = connection.Encrypt(answer);
|
||||
|
||||
try
|
||||
{
|
||||
clientStream.Write(encrypted, 0, encrypted.Length);
|
||||
clientStream.Flush();
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
p.WaitForExit();
|
||||
p.Close();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//Required?
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
private byte[] HandleClientMessage(byte[] Message, CConnection connection)
|
||||
{
|
||||
return requestCallback(connection.ConnectionID, Message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.IO;
|
||||
using System.ServiceModel.Channels;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
class CWebservice : ICWebservice
|
||||
{
|
||||
private static Guid _GetSession()
|
||||
{
|
||||
Guid sessionKey = Guid.Empty;
|
||||
string sessionHeader =
|
||||
((HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties["httpRequest"]).Headers["session"];
|
||||
if (string.IsNullOrEmpty(sessionHeader))
|
||||
{
|
||||
return sessionKey;
|
||||
}
|
||||
try
|
||||
{
|
||||
sessionKey = Guid.Parse(sessionHeader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
public void SendKeyEvent(string key)
|
||||
{
|
||||
if (!_CheckRight(EUserRights.UseKeyboard))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (CServer.SendKeyEvent == null)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CServer.SendKeyEvent(key);
|
||||
}
|
||||
}
|
||||
|
||||
#region profile
|
||||
|
||||
public int GetOwnProfileId()
|
||||
{
|
||||
Guid sessionKey = _GetSession();
|
||||
if (sessionKey == Guid.Empty)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int profileId = CSessionControl.GetUserIdFromSession(sessionKey);
|
||||
if (profileId < 0)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return profileId;
|
||||
}
|
||||
|
||||
public void SendProfile(SProfileData profile)
|
||||
{
|
||||
Guid sessionKey = _GetSession();
|
||||
|
||||
if (profile.ProfileId != -1) //-1 is the id for a new profile
|
||||
{
|
||||
if (CSessionControl.GetUserIdFromSession(sessionKey) != profile.ProfileId
|
||||
&& !(_CheckRight(EUserRights.EditAllProfiles) ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (CServer.SendProfileData == null)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
CServer.SendProfileData(profile);
|
||||
}
|
||||
|
||||
public SProfileData GetProfile(int profileId)
|
||||
{
|
||||
Guid sessionKey = _GetSession();
|
||||
if (_CheckRight(EUserRights.ViewOtherProfiles) || CSessionControl.GetUserIdFromSession(sessionKey) == profileId)
|
||||
{
|
||||
if (CServer.GetProfileData == null)
|
||||
{
|
||||
return new SProfileData();
|
||||
}
|
||||
|
||||
bool isReadonly = (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) &&
|
||||
CSessionControl.GetUserIdFromSession(sessionKey) != profileId);
|
||||
|
||||
return CServer.GetProfileData(profileId, isReadonly);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SProfileData();
|
||||
}
|
||||
}
|
||||
|
||||
public SProfileData[] GetProfileList()
|
||||
{
|
||||
if (CServer.GetProfileList == null)
|
||||
{
|
||||
return new SProfileData[] { };
|
||||
}
|
||||
return CServer.GetProfileList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region photo
|
||||
|
||||
public void SendPhoto(SPhotoData photo)
|
||||
{
|
||||
if (_CheckRight(EUserRights.UploadPhotos))
|
||||
{
|
||||
CServer.SendPhoto(photo);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region website
|
||||
|
||||
public Guid Login(string username, string password)
|
||||
{
|
||||
Guid sessionId = CSessionControl.OpenSession(username, password);
|
||||
if (sessionId == Guid.Empty)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "Wrong username or password";
|
||||
}
|
||||
}
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public Stream Index()
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
|
||||
}
|
||||
|
||||
return new MemoryStream(CServer.GetSiteFile("index.html"));
|
||||
}
|
||||
|
||||
public Stream GetJsFile(string filename)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "text/javascript";
|
||||
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||
HttpResponseHeader.Expires,
|
||||
DateTime.UtcNow.AddHours(4).ToString("r"));
|
||||
}
|
||||
|
||||
byte[] data = CServer.GetSiteFile("js/" + filename);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetCssFile(string filename)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "text/css";
|
||||
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||
HttpResponseHeader.Expires,
|
||||
DateTime.UtcNow.AddHours(4).ToString("r"));
|
||||
}
|
||||
|
||||
byte[] data = CServer.GetSiteFile("css/" + filename);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetCssImageFile(string filename)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "image/png";
|
||||
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||
HttpResponseHeader.Expires,
|
||||
DateTime.UtcNow.AddYears(1).ToString("r"));
|
||||
}
|
||||
|
||||
byte[] data = CServer.GetSiteFile("css\\images\\" + filename);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetImgFile(string filename)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "image/png";
|
||||
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||
HttpResponseHeader.Expires,
|
||||
DateTime.UtcNow.AddYears(1).ToString("r"));
|
||||
}
|
||||
|
||||
byte[] data = CServer.GetSiteFile("img/" + filename);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetLocaleFile(string filename)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = "text/javascript";
|
||||
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||
HttpResponseHeader.Expires,
|
||||
DateTime.UtcNow.AddHours(4).ToString("r"));
|
||||
}
|
||||
|
||||
byte[] data = CServer.GetSiteFile("locales/" + filename);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CBase64Image GetDelayedImage(string id)
|
||||
{
|
||||
return CServer.GetDelayedImage(id);
|
||||
}
|
||||
|
||||
public bool IsServerOnline()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region songs
|
||||
|
||||
public SSongInfo GetSong(int songId)
|
||||
{
|
||||
return CServer.GetSong(songId);
|
||||
}
|
||||
|
||||
public int GetCurrentSongId()
|
||||
{
|
||||
return CServer.GetCurrentSongId();
|
||||
}
|
||||
|
||||
public SSongInfo[] GetAllSongs()
|
||||
{
|
||||
return CServer.GetAllSongs();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region playlist
|
||||
|
||||
public SPlaylistInfo[] GetPlaylists()
|
||||
{
|
||||
return CServer.GetPlaylists();
|
||||
}
|
||||
|
||||
public SPlaylistInfo GetPlaylist(int playlistId)
|
||||
{
|
||||
return CServer.GetPlaylist(playlistId);
|
||||
}
|
||||
|
||||
public void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates)
|
||||
{
|
||||
if (_CheckRight(EUserRights.AddSongToPlaylist))
|
||||
{
|
||||
CServer.AddSongToPlaylist(songId, playlistId, allowDuplicates);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSongFromPlaylist(int position, int playlistId, int songId)
|
||||
{
|
||||
if (_CheckRight(EUserRights.RemoveSongsFromPlaylists))
|
||||
{
|
||||
CServer.RemoveSongFromPlaylist(position, playlistId, songId);
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveSongInPlaylist(int newPosition, int playlistId, int songId)
|
||||
{
|
||||
if (_CheckRight(EUserRights.ReorderPlaylists))
|
||||
{
|
||||
CServer.MoveSongInPlaylist(newPosition, playlistId, songId);
|
||||
}
|
||||
}
|
||||
|
||||
public bool PlaylistContainsSong(int songId, int playlistId)
|
||||
{
|
||||
return CServer.PlaylistContainsSong(songId, playlistId);
|
||||
}
|
||||
|
||||
public SPlaylistSongInfo[] GetPlaylistSongs(int playlistId)
|
||||
{
|
||||
return CServer.GetPlaylistSongs(playlistId);
|
||||
}
|
||||
|
||||
public void RemovePlaylist(int playlistId)
|
||||
{
|
||||
if (_CheckRight(EUserRights.DeletePlaylists))
|
||||
{
|
||||
CServer.RemovePlaylist(playlistId);
|
||||
}
|
||||
}
|
||||
|
||||
public int AddPlaylist(string playlistName)
|
||||
{
|
||||
if (_CheckRight(EUserRights.CreatePlaylists))
|
||||
{
|
||||
return CServer.AddPlaylist(playlistName);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region user management
|
||||
|
||||
public int GetUserRole(int profileId)
|
||||
{
|
||||
return CServer.GetUserRole(profileId);
|
||||
}
|
||||
|
||||
public void SetUserRole(int profileId, int userRole)
|
||||
{
|
||||
if (_CheckRight(EUserRights.EditAllProfiles))
|
||||
{
|
||||
CServer.SetUserRole(profileId, userRole);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasUserRight(int right)
|
||||
{
|
||||
return _CheckRightWithNoErrorMessage((EUserRights)right);
|
||||
}
|
||||
|
||||
private static bool _CheckRight(EUserRights requestedRight)
|
||||
{
|
||||
Guid sessionKey = _GetSession();
|
||||
|
||||
if (sessionKey == Guid.Empty)
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CSessionControl.RequestRight(sessionKey, requestedRight))
|
||||
{
|
||||
if (WebOperationContext.Current != null)
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool _CheckRightWithNoErrorMessage(EUserRights requestedRight)
|
||||
{
|
||||
Guid sessionKey = _GetSession();
|
||||
|
||||
if (sessionKey == Guid.Empty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CSessionControl.RequestRight(sessionKey, requestedRight))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
public delegate bool SendKeyEventDelegate(string key);
|
||||
|
||||
|
||||
#region profile
|
||||
|
||||
public delegate SProfileData GetProfileDataDelegate(int profileId, bool isReadonly);
|
||||
public delegate bool SendProfileDataDelegate(SProfileData profile);
|
||||
public delegate SProfileData[] GetProfileListDelegate();
|
||||
|
||||
[DataContract]
|
||||
public struct SProfileData
|
||||
{
|
||||
[DataMember]
|
||||
public CBase64Image Avatar;
|
||||
[DataMember]
|
||||
public string PlayerName;
|
||||
[DataMember]
|
||||
public int Type;
|
||||
[DataMember]
|
||||
public int Difficulty;
|
||||
[DataMember]
|
||||
public int ProfileId;
|
||||
[DataMember]
|
||||
public bool IsEditable;
|
||||
[DataMember]
|
||||
public string Password;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region photo
|
||||
|
||||
public delegate bool SendPhotoDelegate(SPhotoData photo);
|
||||
|
||||
[DataContract]
|
||||
public struct SPhotoData
|
||||
{
|
||||
[DataMember]
|
||||
public CBase64Image Photo;
|
||||
//Add infomation about the user who took this image??
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region website
|
||||
|
||||
public delegate byte[] GetSiteFileDelegate(string filename);
|
||||
|
||||
public delegate CBase64Image GetDelayedImageDelegate(string hashedFilename);
|
||||
|
||||
#endregion
|
||||
|
||||
[DataContract]
|
||||
public class CBase64Image
|
||||
{
|
||||
[DataMember]
|
||||
private string base64Data = "";
|
||||
|
||||
[DataMember]
|
||||
private string imageId = "";
|
||||
|
||||
public CBase64Image(Image img, ImageFormat format)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
img.Save(ms, format);
|
||||
string formatString = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == format.Guid).FilenameExtension.Replace("*.", "").ToLower();
|
||||
base64Data = "data:image/" + formatString + ";base64," + Convert.ToBase64String(ms.ToArray());
|
||||
}
|
||||
|
||||
public CBase64Image(string imageId)
|
||||
{
|
||||
this.imageId = imageId;
|
||||
}
|
||||
|
||||
public Image GetImage()
|
||||
{
|
||||
string onlyBase64Data = base64Data.Substring(base64Data.IndexOf(";base64,") + (";base64,").Length);
|
||||
byte[] imageData = Convert.FromBase64String(onlyBase64Data);
|
||||
MemoryStream ms = new MemoryStream(imageData, 0, imageData.Length);
|
||||
ms.Write(imageData, 0, imageData.Length);
|
||||
Image image = Image.FromStream(ms, true);
|
||||
return image;
|
||||
}
|
||||
|
||||
public string GetImageType()
|
||||
{
|
||||
Match match = Regex.Match(base64Data, "(?<=data:image/)[a-zA-Z]+(?=;base64)");
|
||||
return match.Success ? match.Groups[0].Value : "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region songs
|
||||
|
||||
public delegate SSongInfo GetSongDelegate(int songId);
|
||||
|
||||
public delegate SSongInfo[] GetAllSongsDelegate();
|
||||
|
||||
public delegate int GetCurrentSongIdDelegate();
|
||||
|
||||
|
||||
[DataContract]
|
||||
public struct SSongInfo
|
||||
{
|
||||
[DataMember]
|
||||
public string Title;
|
||||
[DataMember]
|
||||
public string Artist;
|
||||
[DataMember]
|
||||
public CBase64Image Cover;
|
||||
[DataMember]
|
||||
public string Genre { get; set; }
|
||||
[DataMember]
|
||||
public string Language { get; set; }
|
||||
[DataMember]
|
||||
public string Year { get; set; }
|
||||
[DataMember]
|
||||
public bool IsDuet { get; set; }
|
||||
[DataMember]
|
||||
public int SongId { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region playlists
|
||||
public delegate SPlaylistInfo[] GetPlaylistsDelegate();
|
||||
|
||||
public delegate SPlaylistInfo GetPlaylistDelegate(int playlistId);
|
||||
|
||||
public delegate void AddSongToPlaylistDelegate(int songId, int playlistId, bool allowDuplicates);
|
||||
|
||||
public delegate void RemoveSongFromPlaylistDelegate(int position, int playlistId, int songId);
|
||||
|
||||
public delegate void MoveSongInPlaylistDelegate(int newPosition, int playlistId, int songId);
|
||||
|
||||
public delegate bool PlaylistContainsSongDelegate(int songId, int playlistId);
|
||||
|
||||
public delegate SPlaylistSongInfo[] GetPlaylistSongsDelegate(int playlistId);
|
||||
|
||||
public delegate void RemovePlaylistDelegate(int playlistId);
|
||||
|
||||
public delegate int AddPlaylistDelegate(string playlistName);
|
||||
|
||||
[DataContract]
|
||||
public struct SPlaylistSongInfo
|
||||
{
|
||||
[DataMember]
|
||||
public SSongInfo Song;
|
||||
[DataMember]
|
||||
public int PlaylistId;
|
||||
[DataMember]
|
||||
public int PlaylistPosition;
|
||||
[DataMember]
|
||||
public int GameMode;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public struct SPlaylistInfo
|
||||
{
|
||||
[DataMember]
|
||||
public int PlaylistId;
|
||||
[DataMember]
|
||||
public string PlaylistName;
|
||||
[DataMember]
|
||||
public int SongCount;
|
||||
[DataMember]
|
||||
public string LastChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region user management
|
||||
|
||||
public delegate void SetPasswordDelegate(int profileId, string newPassword);
|
||||
|
||||
public delegate bool ValidatePasswordDelegate(int profileId, string password);
|
||||
|
||||
public delegate int GetUserRoleDelegate(int profileId);
|
||||
|
||||
public delegate void SetUserRoleDelegate(int profileId, int userRole);
|
||||
|
||||
public delegate int GetUserIdFromUsernameDelegate(string username);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DiffieHellman
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Diffie-Hellman algorithm.
|
||||
/// </summary>
|
||||
public class CDiffieHellman : IDisposable
|
||||
{
|
||||
#region - Util -
|
||||
static StrongNumberProvider _strongRng = new StrongNumberProvider();
|
||||
#endregion
|
||||
|
||||
#region - Fields -
|
||||
/// <summary>
|
||||
/// The number of bits to generate.
|
||||
/// </summary>
|
||||
private int bits = 256;
|
||||
|
||||
/// <summary>
|
||||
/// The shared prime.
|
||||
/// </summary>
|
||||
BigInteger prime;
|
||||
/// <summary>
|
||||
/// The shared base.
|
||||
/// </summary>
|
||||
BigInteger g;
|
||||
/// <summary>
|
||||
/// The private prime.
|
||||
/// </summary>
|
||||
BigInteger mine;
|
||||
|
||||
/// <summary>
|
||||
/// The final key.
|
||||
/// </summary>
|
||||
byte[] key;
|
||||
/// <summary>
|
||||
/// The string representation/packet.
|
||||
/// </summary>
|
||||
string representation;
|
||||
#endregion
|
||||
|
||||
#region - Properties -
|
||||
/// <summary>
|
||||
/// Gets the final key to use for encryption.
|
||||
/// </summary>
|
||||
public byte[] Key
|
||||
{
|
||||
get { return key; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region - Ctor -
|
||||
public CDiffieHellman()
|
||||
{
|
||||
}
|
||||
|
||||
public CDiffieHellman(int bits)
|
||||
{
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
~CDiffieHellman()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region - Implementation Methods -
|
||||
#region Flow
|
||||
/// <summary>
|
||||
/// Generates a request packet.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public CDiffieHellman GenerateRequest()
|
||||
{
|
||||
// Generate the parameters.
|
||||
prime = BigInteger.GenPseudoPrime(bits, 30, _strongRng);
|
||||
mine = BigInteger.GenPseudoPrime(bits, 30, _strongRng);
|
||||
g = (BigInteger)5;
|
||||
|
||||
// Gemerate the string.
|
||||
StringBuilder rep = new StringBuilder();
|
||||
rep.Append(prime.ToString(36));
|
||||
rep.Append("|");
|
||||
rep.Append(g.ToString(36));
|
||||
rep.Append("|");
|
||||
|
||||
// Generate the send BigInt.
|
||||
using (BigInteger send = g.ModPow(mine, prime))
|
||||
{
|
||||
rep.Append(send.ToString(36));
|
||||
}
|
||||
|
||||
representation = rep.ToString();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a response packet.
|
||||
/// </summary>
|
||||
/// <param name="request">The string representation of the request.</param>
|
||||
/// <returns></returns>
|
||||
public CDiffieHellman GenerateResponse(string request)
|
||||
{
|
||||
string[] parts = request.Split('|');
|
||||
|
||||
// Generate the would-be fields.
|
||||
using (BigInteger prime = new BigInteger(parts[0], 36))
|
||||
using (BigInteger g = new BigInteger(parts[1], 36))
|
||||
using (BigInteger mine = BigInteger.GenPseudoPrime(bits, 30, _strongRng))
|
||||
{
|
||||
// Generate the key.
|
||||
using (BigInteger given = new BigInteger(parts[2], 36))
|
||||
using (BigInteger key = given.ModPow(mine, prime))
|
||||
{
|
||||
this.key = key.GetBytes();
|
||||
}
|
||||
|
||||
// Generate the response.
|
||||
using (BigInteger send = g.ModPow(mine, prime))
|
||||
{
|
||||
this.representation = send.ToString(36);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the key after a response is received.
|
||||
/// </summary>
|
||||
/// <param name="response">The string representation of the response.</param>
|
||||
public void HandleResponse(string response)
|
||||
{
|
||||
// Get the response and modpow it with the stored prime.
|
||||
using (BigInteger given = new BigInteger(response, 36))
|
||||
using (BigInteger key = given.ModPow(mine, prime))
|
||||
{
|
||||
this.key = key.GetBytes();
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return representation;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
/// <summary>
|
||||
/// Ends the calculation. The key will still be available.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Object.ReferenceEquals(prime, null))
|
||||
prime.Dispose();
|
||||
if (!Object.ReferenceEquals(mine, null))
|
||||
mine.Dispose();
|
||||
if (!Object.ReferenceEquals(g, null))
|
||||
g.Dispose();
|
||||
|
||||
prime = null;
|
||||
mine = null;
|
||||
g = null;
|
||||
|
||||
representation = null;
|
||||
GC.Collect();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace DiffieHellman
|
||||
{
|
||||
internal class StrongNumberProvider
|
||||
{
|
||||
private static RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider();
|
||||
|
||||
public uint NextUInt32()
|
||||
{
|
||||
byte[] res = new byte[4];
|
||||
csp.GetBytes(res);
|
||||
return BitConverter.ToUInt32(res, 0);
|
||||
}
|
||||
|
||||
public int NextInt()
|
||||
{
|
||||
byte[] res = new byte[4];
|
||||
csp.GetBytes(res);
|
||||
return BitConverter.ToInt32(res, 0);
|
||||
}
|
||||
|
||||
public Single NextSingle()
|
||||
{
|
||||
float numerator = NextUInt32();
|
||||
float denominator = uint.MaxValue;
|
||||
return numerator / denominator;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
[ServiceContract]
|
||||
public interface ICWebservice
|
||||
{
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/sendKeyEvent?key={key}")]
|
||||
void SendKeyEvent(string key);
|
||||
|
||||
#region profile
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getOwnProfileId")]
|
||||
int GetOwnProfileId();
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "POST",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/sendProfile")]
|
||||
void SendProfile(SProfileData profile);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getProfile?profileId={profileId}")]
|
||||
SProfileData GetProfile(int profileId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getProfileList")]
|
||||
SProfileData[] GetProfileList();
|
||||
|
||||
#endregion
|
||||
|
||||
#region photo
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "POST",
|
||||
RequestFormat = WebMessageFormat.Json,
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/sendPhoto")]
|
||||
void SendPhoto(SPhotoData photo);
|
||||
|
||||
#endregion
|
||||
|
||||
#region website
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/login?username={username}&password={password}")]
|
||||
Guid Login(string username, string password);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "")]
|
||||
Stream Index();
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/js/{filename}")]
|
||||
Stream GetJsFile(String filename);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/css/{filename}")]
|
||||
Stream GetCssFile(String filename);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/css/images/{filename}")]
|
||||
Stream GetCssImageFile(String filename);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/img/{filename}")]
|
||||
Stream GetImgFile(String filename);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/locales/{filename}")]
|
||||
Stream GetLocaleFile(String filename);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/delayedImage?id={id}")]
|
||||
CBase64Image GetDelayedImage(String id);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/isServerOnline")]
|
||||
bool IsServerOnline();
|
||||
|
||||
#endregion
|
||||
|
||||
#region songs
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getSong?songId={songId}")]
|
||||
SSongInfo GetSong(int songId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getCurrentSongId")]
|
||||
int GetCurrentSongId();
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getAllSongs")]
|
||||
SSongInfo[] GetAllSongs();
|
||||
|
||||
#endregion
|
||||
|
||||
#region playlist
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getPlaylists")]
|
||||
SPlaylistInfo[] GetPlaylists();
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getPlaylist?id={playlistId}")]
|
||||
SPlaylistInfo GetPlaylist(int playlistId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/addSongToPlaylist?songId={songId}&playlistId={playlistId}&duplicates={allowDuplicates}")]
|
||||
void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/removeSongFromPlaylist?position={position}&playlistId={playlistId}&songId={songId}")]
|
||||
void RemoveSongFromPlaylist(int position, int playlistId, int songId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/moveSongInPlaylist?newPosition={newPosition}&playlistId={playlistId}&songId={songId}")]
|
||||
void MoveSongInPlaylist(int newPosition, int playlistId, int songId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/playlistContainsSong?songId={songId}&playlistId={playlistId}")]
|
||||
bool PlaylistContainsSong(int songId, int playlistId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getPlaylistSongs?playlistId={playlistId}")]
|
||||
SPlaylistSongInfo[] GetPlaylistSongs(int playlistId);
|
||||
|
||||
[OperationContract, WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/removePlaylist?playlistId={playlistId}")]
|
||||
void RemovePlaylist(int playlistId);
|
||||
|
||||
[OperationContract, WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/addPlaylist?playlistName={playlistName}")]
|
||||
int AddPlaylist(string playlistName);
|
||||
|
||||
#endregion
|
||||
|
||||
#region user management
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/getUserRole?profileId={profileId}")]
|
||||
int GetUserRole(int profileId);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/setUserRole?profileId={profileId}&userRole={userRole}")]
|
||||
void SetUserRole(int profileId, int userRole);
|
||||
|
||||
[OperationContract]
|
||||
[WebInvoke(Method = "GET",
|
||||
ResponseFormat = WebMessageFormat.Json,
|
||||
UriTemplate = "/hasUserRight?right={right}")]
|
||||
bool HasUserRight(int right);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,19 @@
|
||||
<ProjectGuid>{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ClientServerLib</RootNamespace>
|
||||
<RootNamespace>ServerLib</RootNamespace>
|
||||
<AssemblyName>ClientServerLib</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WIN;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
@@ -33,6 +35,11 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@@ -40,15 +47,17 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CClient.cs" />
|
||||
<Compile Include="CConnection.cs" />
|
||||
<Compile Include="CDiscover.cs" />
|
||||
<Compile Include="CServer.cs" />
|
||||
<Compile Include="DeffieHellman\BigInt.cs" />
|
||||
<Compile Include="DeffieHellman\DeffieHellman.cs" />
|
||||
<Compile Include="DeffieHellman\StrongNumberProvider.cs" />
|
||||
<Compile Include="CWebservice.cs" />
|
||||
<Compile Include="DataStructs.cs" />
|
||||
<Compile Include="ICWebservice.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Structs.cs" />
|
||||
<Compile Include="Session.cs" />
|
||||
<Compile Include="SessionControl.cs" />
|
||||
<Compile Include="UserRights.cs" />
|
||||
<Compile Include="UserRoleControl.cs" />
|
||||
<Compile Include="UserRoles.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
internal class CSession
|
||||
{
|
||||
readonly Guid _ID;
|
||||
public Guid Id
|
||||
{
|
||||
get { return _ID; }
|
||||
}
|
||||
|
||||
readonly int _ProfileId;
|
||||
public int ProfileId
|
||||
{
|
||||
get { return _ProfileId; }
|
||||
}
|
||||
|
||||
readonly EUserRoles _Roles;
|
||||
internal EUserRoles Roles
|
||||
{
|
||||
get { return _Roles; }
|
||||
}
|
||||
|
||||
public CSession(Guid id, int profileId, EUserRoles roles)
|
||||
{
|
||||
this._ID = id;
|
||||
this._ProfileId = profileId;
|
||||
this._Roles = roles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
internal static class CSessionControl
|
||||
{
|
||||
private static readonly Dictionary<Guid, CSession> _ActiveSessions = new Dictionary<Guid, CSession>();
|
||||
|
||||
public static Guid OpenSession(string userName, string password)
|
||||
{
|
||||
if (!_ValidateUserAndPassword(userName, password))
|
||||
{
|
||||
return Guid.Empty;
|
||||
}
|
||||
|
||||
Guid newId = Guid.NewGuid();
|
||||
int id = _GetProfileIdFormUsername(userName);
|
||||
EUserRoles roles = _GetUserRoles(id);
|
||||
CSession session = new CSession(newId, id, roles);
|
||||
InvalidateSessions(id);
|
||||
_ActiveSessions.Add(newId, session);
|
||||
|
||||
return newId;
|
||||
}
|
||||
|
||||
private static bool _ValidateUserAndPassword(string userName, string password)
|
||||
{
|
||||
return CServer.ValidatePassword(_GetProfileIdFormUsername(userName), password);
|
||||
}
|
||||
|
||||
private static int _GetProfileIdFormUsername(string username)
|
||||
{
|
||||
return CServer.GetUserIdFromUsername(username);
|
||||
}
|
||||
|
||||
private static EUserRoles _GetUserRoles(int profileId)
|
||||
{
|
||||
return (EUserRoles)CServer.GetUserRole(profileId);
|
||||
}
|
||||
|
||||
internal static void InvalidateSessions(int profileId)
|
||||
{
|
||||
foreach (var s in (from kv in _ActiveSessions
|
||||
where kv.Value.ProfileId == profileId
|
||||
select kv).ToList())
|
||||
{
|
||||
_ActiveSessions.Remove(s.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool RequestRight(Guid sessionId, EUserRights requestedRight)
|
||||
{
|
||||
return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles)
|
||||
.HasFlag(requestedRight)));
|
||||
}
|
||||
|
||||
internal static int GetUserIdFromSession(Guid sessionId)
|
||||
{
|
||||
if (!_ActiveSessions.ContainsKey(sessionId))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return _ActiveSessions[sessionId].ProfileId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ClientServerLib
|
||||
{
|
||||
public delegate void ResponseCallback(byte[] Response);
|
||||
public delegate byte[] HandleRequest(int ConnectionID, byte[] Message);
|
||||
|
||||
public delegate void OnConnectionChanged(bool Connected);
|
||||
public delegate void OnSend(byte[] Message);
|
||||
public delegate void OnReceived(byte[] Message);
|
||||
|
||||
public struct SRequest
|
||||
{
|
||||
public byte[] Command;
|
||||
public byte[] Response;
|
||||
public ResponseCallback Callback;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
[Flags]
|
||||
internal enum EUserRights
|
||||
{
|
||||
None = 0,
|
||||
EditAllProfiles = 1,
|
||||
UploadPhotos = 2,
|
||||
ViewOtherProfiles = 4,
|
||||
UseKeyboard = 8,
|
||||
ReorderPlaylists = 16,
|
||||
AddSongToPlaylist = 32,
|
||||
CreatePlaylists = 64,
|
||||
DeletePlaylists = 128,
|
||||
RemoveSongsFromPlaylists = 256
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
internal static class CUserRoleControl
|
||||
{
|
||||
private static readonly Dictionary<EUserRoles, EUserRights> _RoleRightsMapping = new Dictionary<EUserRoles, EUserRights> {
|
||||
{EUserRoles.Administrator,
|
||||
(EUserRights.EditAllProfiles|
|
||||
EUserRights.UploadPhotos|
|
||||
EUserRights.ViewOtherProfiles|
|
||||
EUserRights.UseKeyboard|
|
||||
EUserRights.AddSongToPlaylist|
|
||||
EUserRights.ReorderPlaylists|
|
||||
EUserRights.CreatePlaylists|
|
||||
EUserRights.DeletePlaylists|
|
||||
EUserRights.RemoveSongsFromPlaylists)},
|
||||
{EUserRoles.AuthenticatedUser,
|
||||
(EUserRights.UploadPhotos|
|
||||
EUserRights.ViewOtherProfiles|
|
||||
EUserRights.UseKeyboard)}
|
||||
};
|
||||
|
||||
|
||||
internal static EUserRights GetUserRightsFromUserRole(EUserRoles userRole)
|
||||
{
|
||||
return _RoleRightsMapping.Where(role => userRole.HasFlag(role.Key))
|
||||
.Select(role => role.Value)
|
||||
.Aggregate(EUserRights.None, (current, r) => current | r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace ServerLib
|
||||
{
|
||||
[Flags]
|
||||
internal enum EUserRoles
|
||||
{
|
||||
AuthenticatedUser = 0,
|
||||
Administrator = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Security.Cryptography;
|
||||
using Security.Cryptography.X509Certificates;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ConfigHttpApi
|
||||
{
|
||||
public static class ConfigHttpApi
|
||||
{
|
||||
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
|
||||
public static void reserveURL(string networkString)
|
||||
{
|
||||
HttpApi.ReserveURL(networkString, "D:(A;;GX;;;S-1-1-0)");
|
||||
}
|
||||
|
||||
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
|
||||
public static void bindCert(string ip, int port, X509Certificate2 cert)
|
||||
{
|
||||
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||
if (HttpApi.QuerySslCertificateInfo(endpoint) != null)
|
||||
{
|
||||
HttpApi.DeleteCertificateBinding(endpoint);
|
||||
}
|
||||
|
||||
HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid("7baf41f1-48b7-42cb-b145-f815499cb48f"));
|
||||
}
|
||||
|
||||
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
|
||||
public static void addCertToStore(X509Certificate2 cert)
|
||||
{
|
||||
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
store.Add(cert);
|
||||
store.Close();
|
||||
}
|
||||
|
||||
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
|
||||
public static X509Certificate2 getSelfSignedCert(string subjectName)
|
||||
{
|
||||
CngKey key = CngKey.Create(CngAlgorithm2.Rsa);
|
||||
X509CertificateCreationParameters param = new X509CertificateCreationParameters(
|
||||
new X500DistinguishedName("CN=Vocaluxe Server"));
|
||||
param.SubjectName = new X500DistinguishedName("CN=localhost");
|
||||
param.EndTime = DateTime.Today.AddYears(20);
|
||||
param.SignatureAlgorithm = X509CertificateSignatureAlgorithm.RsaSha512;
|
||||
OidCollection oc = new OidCollection();
|
||||
oc.Add(new Oid("1.3.6.1.5.5.7.3.1"));
|
||||
X509Extension eku = new X509EnhancedKeyUsageExtension(oc, true);
|
||||
param.Extensions.Add(eku);
|
||||
|
||||
return key.CreateSelfSignedCertificate(param);
|
||||
}
|
||||
|
||||
/*public static X509Certificate2 getCert(string subject)
|
||||
{
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
||||
|
||||
Mono.Security.Authenticode.PrivateKey key = new Mono.Security.Authenticode.PrivateKey { RSA=RSA.Create()};
|
||||
|
||||
|
||||
Mono.Security.X509.X509CertificateBuilder x509 = new Mono.Security.X509.X509CertificateBuilder();
|
||||
x509.IssuerName = "CN=Vocaluxe Server";
|
||||
x509.NotAfter = DateTime.Today.AddYears(20);
|
||||
x509.NotBefore = DateTime.Today.AddDays(-1);
|
||||
x509.SubjectName = subject;
|
||||
x509.SerialNumber = new byte[] { 1 };
|
||||
x509.Version = 3;
|
||||
x509.SubjectPublicKey = rsa;
|
||||
|
||||
ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension();
|
||||
eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.1");
|
||||
x509.Extensions.Add(eku);
|
||||
|
||||
return new X509Certificate2(x509.Sign(rsa));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EC28CFA6-35A8-4971-AB07-37A54E010F69}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ConfigHttpApi</RootNamespace>
|
||||
<AssemblyName>ConfigHttpApi</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Security">
|
||||
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\Libs\clrsecurity_june10\Security.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Security.Cryptography">
|
||||
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\Libs\clrsecurity_june10\Security.Cryptography.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConfigHttpApi.cs" />
|
||||
<Compile Include="HttpApi.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,643 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ConfigHttpApi
|
||||
{
|
||||
internal static class HttpApi
|
||||
{
|
||||
private static readonly HTTPAPI_VERSION HttpApiVersion = new HTTPAPI_VERSION(1, 0);
|
||||
|
||||
#region DllImport
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpInitialize(
|
||||
HTTPAPI_VERSION version,
|
||||
uint flags,
|
||||
IntPtr pReserved);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpSetServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pConfigInformation,
|
||||
int configInformationLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpDeleteServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pConfigInformation,
|
||||
int configInformationLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpTerminate(
|
||||
uint Flags,
|
||||
IntPtr pReserved);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpQueryServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pInputConfigInfo,
|
||||
int inputConfigInfoLength,
|
||||
IntPtr pOutputConfigInfo,
|
||||
int outputConfigInfoLength,
|
||||
[Optional]
|
||||
out int pReturnLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
|
||||
enum HTTP_SERVICE_CONFIG_ID
|
||||
{
|
||||
|
||||
HttpServiceConfigIPListenList = 0,
|
||||
HttpServiceConfigSSLCertInfo,
|
||||
HttpServiceConfigUrlAclInfo,
|
||||
HttpServiceConfigMax
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_SET
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
|
||||
public HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_KEY
|
||||
{
|
||||
public IntPtr pIpPort;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY(IntPtr pIpPort)
|
||||
{
|
||||
this.pIpPort = pIpPort;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_PARAM
|
||||
{
|
||||
public int SslHashLength;
|
||||
public IntPtr pSslHash;
|
||||
public Guid AppId;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pSslCertStoreName;
|
||||
public uint DefaultCertCheckMode;
|
||||
public int DefaultRevocationFreshnessTime;
|
||||
public int DefaultRevocationUrlRetrievalTimeout;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pDefaultSslCtlIdentifier;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pDefaultSslCtlStoreName;
|
||||
public uint DefaultFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
struct HTTPAPI_VERSION
|
||||
{
|
||||
public ushort HttpApiMajorVersion;
|
||||
public ushort HttpApiMinorVersion;
|
||||
|
||||
public HTTPAPI_VERSION(ushort majorVersion, ushort minorVersion)
|
||||
{
|
||||
HttpApiMajorVersion = majorVersion;
|
||||
HttpApiMinorVersion = minorVersion;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
|
||||
public uint dwToken;
|
||||
}
|
||||
|
||||
enum HTTP_SERVICE_CONFIG_QUERY_TYPE
|
||||
{
|
||||
HttpServiceConfigQueryExact = 0,
|
||||
HttpServiceConfigQueryNext,
|
||||
HttpServiceConfigQueryMax
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_URLACL_SET
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
|
||||
public HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct HTTP_SERVICE_CONFIG_URLACL_KEY
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pUrlPrefix;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_URLACL_KEY(string urlPrefix)
|
||||
{
|
||||
pUrlPrefix = urlPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
struct HTTP_SERVICE_CONFIG_URLACL_PARAM
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pStringSecurityDescriptor;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_URLACL_PARAM(string securityDescriptor)
|
||||
{
|
||||
pStringSecurityDescriptor = securityDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
public const uint HTTP_INITIALIZE_CONFIG = 0x00000002;
|
||||
public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT = 0x00000002;
|
||||
public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER = 0x00000004;
|
||||
private const uint NOERROR = 0;
|
||||
private const uint ERROR_INSUFFICIENT_BUFFER = 122;
|
||||
private const uint ERROR_ALREADY_EXISTS = 183;
|
||||
private const uint ERROR_FILE_NOT_FOUND = 2;
|
||||
private const int ERROR_NO_MORE_ITEMS = 259;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
public class SslCertificateInfo
|
||||
{
|
||||
public byte[] Hash { get; set; }
|
||||
public Guid AppId { get; set; }
|
||||
public string StoreName { get; set; }
|
||||
public IPEndPoint IpPort { get; set; }
|
||||
}
|
||||
|
||||
public static SslCertificateInfo QuerySslCertificateInfo(IPEndPoint ipPort)
|
||||
{
|
||||
SslCertificateInfo result = null;
|
||||
|
||||
uint retVal;
|
||||
CallHttpApi(delegate
|
||||
{
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY sslKey = new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
|
||||
HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery =
|
||||
new HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact,
|
||||
KeyDesc = sslKey
|
||||
};
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)));
|
||||
Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);
|
||||
|
||||
IntPtr pOutputConfigInfo = IntPtr.Zero;
|
||||
int returnLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo;
|
||||
int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
if (retVal == ERROR_FILE_NOT_FOUND)
|
||||
return;
|
||||
|
||||
if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122
|
||||
{
|
||||
pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);
|
||||
|
||||
try
|
||||
{
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
var outputConfigInfo =
|
||||
(HTTP_SERVICE_CONFIG_SSL_SET)
|
||||
Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET));
|
||||
|
||||
byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength];
|
||||
Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length);
|
||||
|
||||
Guid appId = outputConfigInfo.ParamDesc.AppId;
|
||||
string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName;
|
||||
|
||||
result = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort };
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pOutputConfigInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void BindCertificate(IPEndPoint ipPort, byte[] hash, StoreName storeName, Guid appId)
|
||||
{
|
||||
if (ipPort == null) throw new ArgumentNullException("ipPort");
|
||||
if (hash == null) throw new ArgumentNullException("hash");
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_SET configSslSet = new HTTP_SERVICE_CONFIG_SSL_SET();
|
||||
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY httpServiceConfigSslKey =
|
||||
new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
HTTP_SERVICE_CONFIG_SSL_PARAM configSslParam = new HTTP_SERVICE_CONFIG_SSL_PARAM();
|
||||
|
||||
|
||||
GCHandle handleHash = GCHandle.Alloc(hash, GCHandleType.Pinned);
|
||||
configSslParam.AppId = appId;
|
||||
configSslParam.DefaultCertCheckMode = 0;
|
||||
configSslParam.DefaultFlags = 0; //HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT;
|
||||
configSslParam.DefaultRevocationFreshnessTime = 0;
|
||||
configSslParam.DefaultRevocationUrlRetrievalTimeout = 0;
|
||||
configSslParam.pSslCertStoreName = storeName.ToString();
|
||||
configSslParam.pSslHash = handleHash.AddrOfPinnedObject();
|
||||
configSslParam.SslHashLength = hash.Length;
|
||||
configSslSet.ParamDesc = configSslParam;
|
||||
configSslSet.KeyDesc = httpServiceConfigSslKey;
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_SET)));
|
||||
Marshal.StructureToPtr(configSslSet, pInputConfigInfo, false);
|
||||
|
||||
try
|
||||
{
|
||||
uint retVal = HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if (ERROR_ALREADY_EXISTS != retVal)
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
retVal = HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (handleHash.IsAllocated)
|
||||
handleHash.Free();
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void DeleteCertificateBinding(params IPEndPoint[] ipPorts)
|
||||
{
|
||||
if (ipPorts == null || ipPorts.Length == 0)
|
||||
return;
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
foreach (var ipPort in ipPorts)
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_SET configSslSet =
|
||||
new HTTP_SERVICE_CONFIG_SSL_SET();
|
||||
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY httpServiceConfigSslKey =
|
||||
new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
configSslSet.KeyDesc = httpServiceConfigSslKey;
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(
|
||||
Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_SET)));
|
||||
Marshal.StructureToPtr(configSslSet, pInputConfigInfo, false);
|
||||
|
||||
try
|
||||
{
|
||||
uint retVal = HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static SslCertificateInfo[] QuerySslCertificateInfo()
|
||||
{
|
||||
var result = new List<SslCertificateInfo>();
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
uint token = 0;
|
||||
|
||||
uint retVal;
|
||||
do
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery =
|
||||
new HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext,
|
||||
dwToken = token,
|
||||
};
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)));
|
||||
Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);
|
||||
|
||||
IntPtr pOutputConfigInfo = IntPtr.Zero;
|
||||
int returnLength = 0;
|
||||
|
||||
const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo;
|
||||
|
||||
try
|
||||
{
|
||||
int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
if (ERROR_NO_MORE_ITEMS == retVal)
|
||||
break;
|
||||
if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122
|
||||
{
|
||||
pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);
|
||||
|
||||
try
|
||||
{
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure(
|
||||
pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET));
|
||||
|
||||
byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength];
|
||||
Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length);
|
||||
|
||||
Guid appId = outputConfigInfo.ParamDesc.AppId;
|
||||
string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName;
|
||||
IPEndPoint ipPort = ReadSockaddrStructure(outputConfigInfo.KeyDesc.pIpPort);
|
||||
|
||||
var resultItem = new SslCertificateInfo
|
||||
{
|
||||
AppId = appId,
|
||||
Hash = hash,
|
||||
StoreName = storeName,
|
||||
IpPort = ipPort
|
||||
};
|
||||
result.Add(resultItem);
|
||||
token++;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pOutputConfigInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
}
|
||||
|
||||
} while (NOERROR == retVal);
|
||||
|
||||
});
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static void ReserveURL(string networkURL, string securityDescriptor)
|
||||
{
|
||||
if (String.IsNullOrEmpty(networkURL)) throw new ArgumentNullException("networkURL");
|
||||
if (String.IsNullOrEmpty(securityDescriptor)) throw new ArgumentNullException("securityDescriptor");
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
uint retVal = (uint)NOERROR; // NOERROR = 0
|
||||
|
||||
HTTP_SERVICE_CONFIG_URLACL_KEY keyDesc = new HTTP_SERVICE_CONFIG_URLACL_KEY(networkURL);
|
||||
HTTP_SERVICE_CONFIG_URLACL_PARAM paramDesc = new HTTP_SERVICE_CONFIG_URLACL_PARAM(securityDescriptor);
|
||||
|
||||
HTTP_SERVICE_CONFIG_URLACL_SET inputConfigInfoSet = new HTTP_SERVICE_CONFIG_URLACL_SET();
|
||||
inputConfigInfoSet.KeyDesc = keyDesc;
|
||||
inputConfigInfoSet.ParamDesc = paramDesc;
|
||||
|
||||
IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_SET)));
|
||||
Marshal.StructureToPtr(inputConfigInfoSet, pInputConfigInfo, false);
|
||||
try
|
||||
{
|
||||
retVal = HttpApi.HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if ((uint)ERROR_ALREADY_EXISTS == retVal) // ERROR_ALREADY_EXISTS = 183
|
||||
{
|
||||
retVal = HttpApi.HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if ((uint)NOERROR == retVal)
|
||||
{
|
||||
retVal = HttpApi.HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
HttpApi.HttpTerminate(HttpApi.HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
}
|
||||
if ((uint)NOERROR != retVal)
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void ThrowWin32ExceptionIfError(uint retVal)
|
||||
{
|
||||
if (NOERROR != retVal)
|
||||
{
|
||||
throw new Win32Exception(Convert.ToInt32(retVal));
|
||||
}
|
||||
}
|
||||
|
||||
private static void CallHttpApi(Action body)
|
||||
{
|
||||
uint retVal = HttpInitialize(HttpApiVersion, HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
try
|
||||
{
|
||||
body();
|
||||
}
|
||||
finally
|
||||
{
|
||||
HttpTerminate(HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unmanaged sockaddr structure to pass to a WinAPI function.
|
||||
/// </summary>
|
||||
/// <param name="ipEndPoint">IP address and port number</param>
|
||||
/// <returns>a handle for the structure. Use the AddrOfPinnedObject Method to get a stable pointer to the object. </returns>
|
||||
/// <remarks>When the handle goes out of scope you must explicitly release it by calling the Free method; otherwise, memory leaks may occur. </remarks>
|
||||
private static GCHandle CreateSockaddrStructure(IPEndPoint ipEndPoint)
|
||||
{
|
||||
SocketAddress socketAddress = ipEndPoint.Serialize();
|
||||
|
||||
// use an array of bytes instead of the sockaddr structure
|
||||
byte[] sockAddrStructureBytes = new byte[socketAddress.Size];
|
||||
GCHandle sockAddrHandle = GCHandle.Alloc(sockAddrStructureBytes, GCHandleType.Pinned);
|
||||
for (int i = 0; i < socketAddress.Size; ++i)
|
||||
{
|
||||
sockAddrStructureBytes[i] = socketAddress[i];
|
||||
}
|
||||
return sockAddrHandle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the unmanaged sockaddr structure returned by a WinAPI function
|
||||
/// </summary>
|
||||
/// <param name="pSockaddrStructure">pointer to the unmanaged sockaddr structure</param>
|
||||
/// <returns>IP address and port number</returns>
|
||||
private static IPEndPoint ReadSockaddrStructure(IntPtr pSockaddrStructure)
|
||||
{
|
||||
short sAddressFamily = Marshal.ReadInt16(pSockaddrStructure);
|
||||
AddressFamily addressFamily = (AddressFamily)sAddressFamily;
|
||||
|
||||
int sockAddrSructureSize;
|
||||
IPEndPoint ipEndPointAny;
|
||||
switch (addressFamily)
|
||||
{
|
||||
case AddressFamily.InterNetwork:
|
||||
// IP v4 address
|
||||
sockAddrSructureSize = 16;
|
||||
ipEndPointAny = new IPEndPoint(IPAddress.Any, 0);
|
||||
break;
|
||||
case AddressFamily.InterNetworkV6:
|
||||
// IP v6 address
|
||||
sockAddrSructureSize = 28;
|
||||
ipEndPointAny = new IPEndPoint(IPAddress.IPv6Any, 0);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("pSockaddrStructure", "Unknown address family");
|
||||
}
|
||||
|
||||
|
||||
// get bytes of the sockadrr structure
|
||||
byte[] sockAddrSructureBytes = new byte[sockAddrSructureSize];
|
||||
Marshal.Copy(pSockaddrStructure, sockAddrSructureBytes, 0, sockAddrSructureSize);
|
||||
|
||||
// create SocketAddress from bytes
|
||||
var socketAddress = new SocketAddress(AddressFamily.Unspecified, sockAddrSructureSize);
|
||||
for (int i = 0; i < sockAddrSructureSize; i++)
|
||||
{
|
||||
socketAddress[i] = sockAddrSructureBytes[i];
|
||||
}
|
||||
|
||||
// create IPEndPoint from SocketAddress
|
||||
IPEndPoint result = (IPEndPoint)ipEndPointAny.Create(socketAddress);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die mit einer Assembly verknüpft sind.
|
||||
[assembly: AssemblyTitle("ConfigHttpApi")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ConfigHttpApi")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("89f719af-3a0d-4704-be7f-16e5b4e19c02")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- config.xml reference: https://build.phonegap.com/docs/config-xml -->
|
||||
<widget xmlns = "http://www.w3.org/ns/widgets"
|
||||
xmlns:gap = "http://phonegap.com/ns/1.0"
|
||||
id = "net.sourceforge.vocaluxe"
|
||||
version = "0.1.0">
|
||||
|
||||
<name>Vocaluxe</name>
|
||||
|
||||
<description>
|
||||
Interact with Vocaluxe via your mobile device.
|
||||
</description>
|
||||
|
||||
<author href="http://vocaluxe.sourceforge.net">
|
||||
Vocaluxe Team
|
||||
</author>
|
||||
|
||||
<!--
|
||||
Enable individual API permissions here.
|
||||
-->
|
||||
<feature name="http://api.phonegap.com/1.0/device" />
|
||||
<feature name="http://api.phonegap.com/1.0/camera" />
|
||||
<feature name="http://api.phonegap.com/1.0/file" />
|
||||
|
||||
<!-- Customize your app and platform with the preference element. -->
|
||||
<preference name="phonegap-version" value="2.9.0" />
|
||||
|
||||
<!-- Plugins can also be added here. -->
|
||||
<gap:plugin name="com.phonegap.plugins.barcodescanner" />
|
||||
|
||||
<!-- Define app icon for each platform. -->
|
||||
<icon src="icon.png" />
|
||||
|
||||
<access origin="*" />
|
||||
</widget>
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -1,11 +1,12 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vocaluxe", "Vocaluxe\Vocaluxe.csproj", "{2A1E0F2D-5392-4BB7-B0A1-A9DFA13E79FF}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9} = {55F89808-4E79-4FFE-BC13-48258913F5C9}
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678} = {6F3E1874-F28A-40E9-AFBD-31934D593678}
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593679} = {6F3E1874-F28A-40E9-AFBD-31934D593679}
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C} = {ED007796-367F-4142-AA55-5450C7645C2C}
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3} = {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}
|
||||
{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} = {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6} = {5A4053F1-5AD5-441F-B254-D97A088127B6}
|
||||
EndProjectSection
|
||||
@@ -20,6 +21,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PartyModeChallengeMedley",
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GstreamerHelper", "GstreamerHelper\GstreamerHelper.vcxproj", "{ED007796-367F-4142-AA55-5450C7645C2C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerLib", "ClientServerLib\ClientServerLib\ServerLib.csproj", "{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebserverInitalConfig", "WebserverInitalConfig\WebserverInitalConfig.csproj", "{55F89808-4E79-4FFE-BC13-48258913F5C9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
DebugLinux|x64 = DebugLinux|x64
|
||||
@@ -102,10 +107,8 @@ Global
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.Build.0 = DebugWin|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.ActiveCfg = DebugWin|x86
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.Build.0 = DebugWin|x86
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.ActiveCfg = InstallerWin|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.Build.0 = InstallerWin|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.ActiveCfg = InstallerWin|x86
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.Build.0 = InstallerWin|x86
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.ActiveCfg = ReleaseWin|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.ActiveCfg = ReleaseWin|x86
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64
|
||||
{5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86
|
||||
@@ -122,10 +125,8 @@ Global
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.Build.0 = DebugWin|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.ActiveCfg = DebugWin|x86
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.Build.0 = DebugWin|x86
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.ActiveCfg = InstallerWin|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.Build.0 = InstallerWin|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.ActiveCfg = InstallerWin|x86
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.Build.0 = InstallerWin|x86
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.ActiveCfg = ReleaseWin|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.ActiveCfg = ReleaseWin|x86
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64
|
||||
{6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86
|
||||
@@ -140,16 +141,40 @@ Global
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x64.Build.0 = DebugWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x86.ActiveCfg = DebugWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x86.Build.0 = DebugWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x64.ActiveCfg = InstallerWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x64.Build.0 = InstallerWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x86.ActiveCfg = InstallerWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x86.Build.0 = InstallerWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x64.ActiveCfg = ReleaseWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x86.ActiveCfg = ReleaseWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|x64.ActiveCfg = ReleaseWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|x86.ActiveCfg = ReleaseWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x64.Build.0 = ReleaseWin|x64
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Win32
|
||||
{ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x86.Build.0 = ReleaseWin|Win32
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x64.ActiveCfg = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x64.Build.0 = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.ActiveCfg = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.Build.0 = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x64.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x86.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.Build.0 = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x86.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x64.ActiveCfg = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x64.Build.0 = Release|Any CPU
|
||||
{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x86.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|x64.ActiveCfg = Debug|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|x86.ActiveCfg = Debug|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x64.ActiveCfg = Debug|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x64.Build.0 = Debug|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x86.ActiveCfg = Debug|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.InstallerWin|x64.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.InstallerWin|x86.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|x86.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.ActiveCfg = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.Build.0 = Release|Any CPU
|
||||
{55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Vocaluxe.Base
|
||||
public static EOffOn ServerActive = EOffOn.TR_CONFIG_OFF;
|
||||
public static EOffOn ServerEncryption = EOffOn.TR_CONFIG_OFF;
|
||||
public static int ServerPort = 3000;
|
||||
public static string ServerPassword = "vocaluxe";
|
||||
//public static string ServerPassword = "vocaluxe";
|
||||
|
||||
//Lists to save parameters and values
|
||||
private static readonly List<string> _Params = new List<string>();
|
||||
@@ -299,7 +299,7 @@ namespace Vocaluxe.Base
|
||||
if (ServerPort < 1 || ServerPort > 65535)
|
||||
ServerPort = 3000;
|
||||
|
||||
xmlReader.GetValue("//root/Server/ServerPassword", out ServerPassword, ServerPassword);
|
||||
//xmlReader.GetValue("//root/Server/ServerPassword", out ServerPassword, ServerPassword);
|
||||
#endregion Server
|
||||
}
|
||||
|
||||
@@ -573,8 +573,8 @@ namespace Vocaluxe.Base
|
||||
writer.WriteComment("Server Port (default: 3000) [1..65535]");
|
||||
writer.WriteElementString("ServerPort", ServerPort.ToString());
|
||||
|
||||
writer.WriteComment("Server Password (default: vocaluxe)");
|
||||
writer.WriteElementString("ServerPassword", ServerPassword);
|
||||
//writer.WriteComment("Server Password (default: vocaluxe)");
|
||||
//writer.WriteElementString("ServerPassword", ServerPassword);
|
||||
|
||||
writer.WriteEndElement();
|
||||
#endregion Server
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
@@ -77,7 +77,7 @@ namespace Vocaluxe.Base
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
var playlist = new CPlaylistFile(file);
|
||||
CPlaylistFile playlist = new CPlaylistFile(file, files.IndexOf(file));
|
||||
_Playlists.Add(playlist);
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace Vocaluxe.Base
|
||||
|
||||
public static int NewPlaylist()
|
||||
{
|
||||
var pl = new CPlaylistFile {PlaylistName = "New Playlist"};
|
||||
CPlaylistFile pl = new CPlaylistFile { PlaylistName = "New Playlist", Id = _Playlists.Count };
|
||||
_Playlists.Add(pl);
|
||||
return _Playlists.Count - 1;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
@@ -305,6 +305,16 @@ namespace Vocaluxe.Base
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public static CProfile GetProfile(int profileID)
|
||||
{
|
||||
if (!IsProfileIDValid(profileID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _Profiles[profileID];
|
||||
}
|
||||
|
||||
public static IEnumerable<CAvatar> GetAvatars()
|
||||
{
|
||||
if (_Avatars.Count == 0)
|
||||
@@ -480,6 +490,14 @@ namespace Vocaluxe.Base
|
||||
return _Profiles[profileID].Avatar.ID;
|
||||
}
|
||||
|
||||
public static CAvatar GetAvatar(int profileID)
|
||||
{
|
||||
if (!IsProfileIDValid(profileID))
|
||||
return null;
|
||||
|
||||
return _Profiles[profileID].Avatar;
|
||||
}
|
||||
|
||||
public static int GetProfileID(int num)
|
||||
{
|
||||
return _Profiles[num].ID;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
@@ -102,6 +102,7 @@ namespace Vocaluxe.Base
|
||||
#endif
|
||||
Path.Combine(DataPath, FolderProfiles)
|
||||
};
|
||||
public static string FolderPhotos = "Photos";
|
||||
public const string FolderSongs = "Songs";
|
||||
public const string FolderSounds = "Sounds";
|
||||
public const string FolderLanguages = "Languages";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#region license
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
@@ -83,47 +83,6 @@ namespace Vocaluxe.Base.Server
|
||||
}
|
||||
#endregion Login
|
||||
|
||||
#region Keyboard
|
||||
#endregion Keyboard
|
||||
|
||||
#region Profiles
|
||||
public static byte[] CreateCommandSendAvatarPicture(int width, int height, byte[] data)
|
||||
{
|
||||
var ap = new SAvatarPicture {Height = height, Width = width, Data = new byte[data.Length]};
|
||||
Array.Copy(data, ap.Data, data.Length);
|
||||
|
||||
return _Serialize(CommandSendAvatarPicture, ap);
|
||||
}
|
||||
|
||||
public static bool DecodeCommandSendAvatarPicture(byte[] message, out SAvatarPicture avatarPicture)
|
||||
{
|
||||
return _TryDeserialize(message, out avatarPicture);
|
||||
}
|
||||
|
||||
public static byte[] CreateCommandSendAvatarPictureJpg(byte[] avatarJpgData)
|
||||
{
|
||||
var ap = new SAvatarPicture {Height = 0, Width = 0, Data = new byte[avatarJpgData.Length]};
|
||||
Array.Copy(avatarJpgData, ap.Data, avatarJpgData.Length);
|
||||
|
||||
return _Serialize(CommandSendAvatarPictureJpg, ap);
|
||||
}
|
||||
|
||||
public static byte[] CreateCommandSendProfile(byte[] avatarJpgData, string playerName, int difficulty)
|
||||
{
|
||||
var ap = new SAvatarPicture {Height = 0, Width = 0, Data = new byte[avatarJpgData.Length]};
|
||||
Array.Copy(avatarJpgData, ap.Data, avatarJpgData.Length);
|
||||
|
||||
var profile = new SProfile {Avatar = ap, PlayerName = playerName, Difficulty = difficulty};
|
||||
|
||||
return _Serialize(CommandSendProfile, profile);
|
||||
}
|
||||
|
||||
public static bool DecodeCommandSendProfile(byte[] message, out SProfile profile)
|
||||
{
|
||||
return _TryDeserialize(message, out profile);
|
||||
}
|
||||
#endregion Profiles
|
||||
|
||||
#region Serializing
|
||||
private static byte[] _Serialize<T>(T obj)
|
||||
{
|
||||
@@ -138,7 +97,7 @@ namespace Vocaluxe.Base.Server
|
||||
stream.Write(cmd, 0, cmd.Length);
|
||||
|
||||
byte[] data;
|
||||
string json = JsonConvert.SerializeObject(obj);
|
||||
string json = JsonConvert.SerializeObject(obj);
|
||||
data = _Encoder.GetBytes(json);
|
||||
stream.Write(data, 0, data.Length);
|
||||
return stream.ToArray();
|
||||
@@ -156,16 +115,16 @@ namespace Vocaluxe.Base.Server
|
||||
|
||||
var data = new byte[message.Length - 4];
|
||||
Array.Copy(message, 4, data, 0, data.Length);
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
obj = JsonConvert.DeserializeObject<T>(_Encoder.GetString(data));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion Serializing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,75 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using ClientServerLib;
|
||||
using ServerLib;
|
||||
using Vocaluxe.Lib.Input;
|
||||
using Vocaluxe.Lib.Playlist;
|
||||
using VocaluxeLib;
|
||||
using VocaluxeLib.Draw;
|
||||
using VocaluxeLib.Menu;
|
||||
using VocaluxeLib.Profile;
|
||||
using VocaluxeLib.Songs;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Vocaluxe.Base.Server
|
||||
{
|
||||
static class CVocaluxeServer
|
||||
{
|
||||
private static CServer _Server;
|
||||
private static CDiscover _Discover;
|
||||
private static Dictionary<int, CClientHandler> _Clients;
|
||||
//private static CDiscover _Discover;
|
||||
|
||||
public static readonly CControllerFramework Controller = new CControllerFramework();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_Clients = new Dictionary<int, CClientHandler>();
|
||||
String pw = (CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON) ? CConfig.ServerPassword : String.Empty;
|
||||
_Server = new CServer(RequestHandler, CConfig.ServerPort, pw);
|
||||
_Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON);
|
||||
|
||||
_Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword);
|
||||
CServer.SendKeyEvent = _SendKeyEvent;
|
||||
CServer.GetProfileData = _GetProfileData;
|
||||
CServer.SendProfileData = _SendProfileData;
|
||||
CServer.GetProfileList = _GetProfileList;
|
||||
CServer.SendPhoto = _SendPhoto;
|
||||
CServer.GetSiteFile = _GetSiteFile;
|
||||
CServer.GetSong = _GetSong;
|
||||
CServer.GetAllSongs = _GetAllSongs;
|
||||
CServer.GetCurrentSongId = _GetCurrentSongId;
|
||||
CServer.ValidatePassword = _ValidatePassword;
|
||||
CServer.GetUserRole = _GetUserRole;
|
||||
CServer.SetUserRole = _SetUserRole;
|
||||
CServer.GetUserIdFromUsername = _GetUserIdFromUsername;
|
||||
CServer.GetDelayedImage = _GetDelayedImage;
|
||||
CServer.GetPlaylists = _GetPlaylists;
|
||||
CServer.GetPlaylist = _GetPlaylist;
|
||||
CServer.AddSongToPlaylist = _AddSongToPlaylist;
|
||||
CServer.RemoveSongFromPlaylist = _RemoveSongFromPlaylist;
|
||||
CServer.MoveSongInPlaylist = _MoveSongInPlaylist;
|
||||
CServer.PlaylistContainsSong = _PlaylistContainsSong;
|
||||
CServer.GetPlaylistSongs = _GetPlaylistSongs;
|
||||
CServer.RemovePlaylist = _RemovePlaylist;
|
||||
CServer.AddPlaylist = _AddPlaylist;
|
||||
|
||||
//_Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword);
|
||||
Controller.Init();
|
||||
}
|
||||
|
||||
@@ -52,158 +78,673 @@ namespace Vocaluxe.Base.Server
|
||||
if (CConfig.ServerActive == EOffOn.TR_CONFIG_ON)
|
||||
{
|
||||
_Server.Start();
|
||||
_Discover.StartBroadcasting();
|
||||
//_Discover.StartBroadcasting();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
_Server.Stop();
|
||||
_Discover.Stop();
|
||||
_Clients = new Dictionary<int, CClientHandler>();
|
||||
//_Discover.Stop();
|
||||
}
|
||||
|
||||
private static byte[] RequestHandler(int connectionID, byte[] message)
|
||||
private static bool _SendKeyEvent(string key)
|
||||
{
|
||||
byte[] answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseNOK);
|
||||
|
||||
if (message == null)
|
||||
return answer;
|
||||
|
||||
if (message.Length < 4)
|
||||
return answer;
|
||||
|
||||
bool loggedIn;
|
||||
lock (_Clients)
|
||||
bool result = false;
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
if (!_Clients.ContainsKey(connectionID))
|
||||
switch (key.ToLower())
|
||||
{
|
||||
var client = new CClientHandler(connectionID);
|
||||
_Clients.Add(connectionID, client);
|
||||
|
||||
//just a small fix: There is no real login at the moment, so set it to true.
|
||||
_Clients[connectionID].LoggedIn = true;
|
||||
}
|
||||
|
||||
|
||||
loggedIn = _Clients[connectionID].LoggedIn;
|
||||
}
|
||||
|
||||
if (!loggedIn)
|
||||
return CCommands.CreateCommandWithoutParams(CCommands.ResponseNOK);
|
||||
|
||||
int command = BitConverter.ToInt32(message, 0);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case CCommands.CommandSendKeyUp:
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Up));
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendKeyDown:
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Down));
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendKeyLeft:
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Left));
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendKeyRight:
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Right));
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendAvatarPicture:
|
||||
|
||||
SAvatarPicture avatarPicture;
|
||||
if (CCommands.DecodeCommandSendAvatarPicture(message, out avatarPicture))
|
||||
{
|
||||
using (var bmp = new Bitmap(avatarPicture.Width, avatarPicture.Height))
|
||||
case "up":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Up));
|
||||
result = true;
|
||||
break;
|
||||
case "down":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Down));
|
||||
result = true;
|
||||
break;
|
||||
case "left":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Left));
|
||||
result = true;
|
||||
break;
|
||||
case "right":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Right));
|
||||
result = true;
|
||||
break;
|
||||
case "escape":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Escape));
|
||||
result = true;
|
||||
break;
|
||||
case "return":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Return));
|
||||
result = true;
|
||||
break;
|
||||
case "tab":
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, Keys.Tab));
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
foreach (char c in key.ToCharArray())
|
||||
{
|
||||
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
Marshal.Copy(avatarPicture.Data, 0, bmpData.Scan0, avatarPicture.Data.Length);
|
||||
bmp.UnlockBits(bmpData);
|
||||
|
||||
const string filename = "snapshot";
|
||||
int i = 0;
|
||||
while (File.Exists(Path.Combine(CSettings.DataPath, CSettings.FolderProfiles, filename + i + ".png")))
|
||||
i++;
|
||||
bmp.Save(Path.Combine(CSettings.DataPath, CSettings.FolderProfiles, filename + i + ".png"), ImageFormat.Png);
|
||||
}
|
||||
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
}
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendAvatarPictureJpg:
|
||||
|
||||
SAvatarPicture avatarPictureJpg;
|
||||
if (CCommands.DecodeCommandSendAvatarPicture(message, out avatarPictureJpg))
|
||||
{
|
||||
if (_AddAvatar(avatarPictureJpg.Data) != String.Empty)
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
}
|
||||
break;
|
||||
|
||||
case CCommands.CommandSendProfile:
|
||||
SProfile profile;
|
||||
if (CCommands.DecodeCommandSendProfile(message, out profile))
|
||||
{
|
||||
try
|
||||
{
|
||||
string avatarFilename = _AddAvatar(profile.Avatar.Data);
|
||||
if (avatarFilename != String.Empty)
|
||||
bool shift = true;
|
||||
char keyChar;
|
||||
if (char.ToUpper(c) != c)
|
||||
{
|
||||
var p = new CProfile
|
||||
{
|
||||
Active = EOffOn.TR_CONFIG_ON,
|
||||
AvatarFileName = avatarFilename,
|
||||
Difficulty = (EGameDifficulty)profile.Difficulty,
|
||||
GuestProfile = EOffOn.TR_CONFIG_OFF,
|
||||
PlayerName = profile.PlayerName
|
||||
};
|
||||
CProfiles.AddProfile(p);
|
||||
answer = CCommands.CreateCommandWithoutParams(CCommands.ResponseOK);
|
||||
keyChar = char.ToUpper(c);
|
||||
shift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyChar = c;
|
||||
}
|
||||
|
||||
if ((keyChar >= 0x30 && keyChar <= 0x39) || (keyChar >= 0x41 && keyChar <= 0x5A))
|
||||
{
|
||||
Keys keys = (Keys)keyChar;
|
||||
if (shift)
|
||||
{
|
||||
keys |= Keys.Shift;
|
||||
}
|
||||
Controller.AddKeyEvent(new SKeyEvent(ESender.Keyboard, false, false, false, false, Char.MinValue, keys));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
catch (Exception) {}
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static string _AddAvatar(byte[] jpgData)
|
||||
#region profile
|
||||
|
||||
private static SProfileData _GetProfileData(int profileId, bool isReadonly)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
return new SProfileData();
|
||||
}
|
||||
return _CreateProfileData(profile, isReadonly);
|
||||
}
|
||||
|
||||
private static bool _SendProfileData(SProfileData profile)
|
||||
{
|
||||
CProfile newProfile;
|
||||
CProfile existingProfile = CProfiles.GetProfile(profile.ProfileId);
|
||||
|
||||
if (existingProfile != null)
|
||||
{
|
||||
newProfile = new CProfile
|
||||
{
|
||||
ID = existingProfile.ID,
|
||||
FileName = existingProfile.FileName,
|
||||
Active = existingProfile.Active,
|
||||
AvatarFileName = existingProfile.AvatarFileName,
|
||||
Avatar = existingProfile.Avatar,
|
||||
Difficulty = existingProfile.Difficulty,
|
||||
GuestProfile = existingProfile.GuestProfile,
|
||||
PlayerName = existingProfile.PlayerName
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
newProfile = new CProfile
|
||||
{
|
||||
Active = EOffOn.TR_CONFIG_ON,
|
||||
GuestProfile = EOffOn.TR_CONFIG_OFF
|
||||
};
|
||||
}
|
||||
|
||||
if (profile.Avatar != null)
|
||||
{
|
||||
newProfile.Avatar = _AddAvatar(profile.Avatar);
|
||||
|
||||
}
|
||||
else if (newProfile.Avatar == null || newProfile.Avatar.ID == -1)
|
||||
{
|
||||
newProfile.Avatar = CProfiles.GetAvatars().First();
|
||||
|
||||
/*CAvatar avatar = new CAvatar(-1);
|
||||
avatar.LoadFromFile("Profiles\\Avatar_f.png");
|
||||
CProfiles.AddAvatar(avatar);
|
||||
newProfile.Avatar = avatar;*/
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(profile.PlayerName))
|
||||
{
|
||||
newProfile.PlayerName = profile.PlayerName;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(newProfile.PlayerName))
|
||||
{
|
||||
newProfile.PlayerName = "DummyName";
|
||||
}
|
||||
|
||||
if (profile.Difficulty >= 0 && profile.Difficulty <= 2)
|
||||
{
|
||||
newProfile.Difficulty = (EGameDifficulty)profile.Difficulty;
|
||||
}
|
||||
|
||||
if (profile.Type >= 0 && profile.Type <= 1)
|
||||
{
|
||||
newProfile.GuestProfile = (EOffOn)profile.Type;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(profile.Password))
|
||||
{
|
||||
if (profile.Password == "***__CLEAR_PASSWORD__***")
|
||||
{
|
||||
newProfile.PasswordSalt = null;
|
||||
newProfile.PasswordHash = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
|
||||
byte[] buffer = new byte[32];
|
||||
rng.GetNonZeroBytes(buffer);
|
||||
byte[] salt = buffer;
|
||||
byte[] hashedPassword = _Hash((new UTF8Encoding()).GetBytes(profile.Password), salt);
|
||||
|
||||
newProfile.PasswordSalt = salt;
|
||||
newProfile.PasswordHash = hashedPassword;
|
||||
}
|
||||
}
|
||||
|
||||
if (existingProfile != null)
|
||||
{
|
||||
CProfiles.EditProfile(newProfile);
|
||||
CProfiles.Update();
|
||||
CProfiles.SaveProfiles();
|
||||
}
|
||||
else
|
||||
{
|
||||
CProfiles.AddProfile(newProfile);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static SProfileData[] _GetProfileList()
|
||||
{
|
||||
List<SProfileData> result = new List<SProfileData>(CProfiles.NumProfiles);
|
||||
|
||||
result.AddRange(CProfiles.GetProfiles().Select(profile => _CreateProfileData(profile, true)));
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private static SProfileData _CreateProfileData(CProfile profile, bool isReadonly)
|
||||
{
|
||||
SProfileData profileData = new SProfileData
|
||||
{
|
||||
IsEditable = !isReadonly,
|
||||
ProfileId = profile.ID,
|
||||
PlayerName = profile.PlayerName,
|
||||
Type = (int)profile.GuestProfile,
|
||||
Difficulty = (int)profile.Difficulty
|
||||
};
|
||||
|
||||
CAvatar avatar = profile.Avatar;
|
||||
if (avatar != null)
|
||||
{
|
||||
if (File.Exists(avatar.FileName))
|
||||
{
|
||||
profileData.Avatar = new CBase64Image(_CreateDelayedImage(avatar.FileName));
|
||||
}
|
||||
}
|
||||
return profileData;
|
||||
}
|
||||
|
||||
private static CAvatar _AddAvatar(CBase64Image avatarData)
|
||||
{
|
||||
string result = String.Empty;
|
||||
try
|
||||
{
|
||||
string filename = Path.Combine(CSettings.DataPath, CSettings.FolderProfiles, "snapshot");
|
||||
int i = 0;
|
||||
while (File.Exists(filename + i + ".jpg"))
|
||||
i++;
|
||||
|
||||
filename = filename + i + ".jpg";
|
||||
FileStream fs = File.Create(filename);
|
||||
fs.Write(jpgData, 0, jpgData.Length);
|
||||
fs.Flush();
|
||||
fs.Close();
|
||||
string filename = _SaveImage(avatarData, "snapshot", CSettings.FolderProfiles);
|
||||
|
||||
var avatar = new CAvatar(-1);
|
||||
if (avatar.LoadFromFile(filename))
|
||||
{
|
||||
CProfiles.AddAvatar(avatar);
|
||||
result = filename;
|
||||
return avatar;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region photo
|
||||
|
||||
private static List<string> photosOfThisRound = new List<string>();
|
||||
|
||||
private static bool _SendPhoto(SPhotoData photoData)
|
||||
{
|
||||
if (photoData.Photo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string name = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||
string filePath = _SaveImage(photoData.Photo, name, CSettings.FolderPhotos);
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
photosOfThisRound.Add(filePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static string[] getPhotosOfThisRound()
|
||||
{
|
||||
var result = photosOfThisRound.ToArray();
|
||||
photosOfThisRound.Clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region website
|
||||
|
||||
private static readonly Dictionary<string, string> _DelayedImagePath = new Dictionary<string, string>();
|
||||
|
||||
private static byte[] _GetSiteFile(string filename)
|
||||
{
|
||||
string path = "Website/" + filename;
|
||||
path = path.Replace("..", "");
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*string content = File.ReadAllText(path);
|
||||
|
||||
content = content.Replace("%SERVER%", System.Net.Dns.GetHostName() + ":" + CConfig.ServerPort);
|
||||
|
||||
|
||||
return Encoding.UTF8.GetBytes(content);*/
|
||||
|
||||
return File.ReadAllBytes(path);
|
||||
}
|
||||
|
||||
private static string _CreateDelayedImage(string filename)
|
||||
{
|
||||
byte[] by = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(filename));
|
||||
var sb = new StringBuilder();
|
||||
foreach (byte b in by)
|
||||
{
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
|
||||
string hashedFilename = sb.ToString();
|
||||
|
||||
if (!_DelayedImagePath.ContainsKey(hashedFilename))
|
||||
{
|
||||
_DelayedImagePath.Add(hashedFilename, filename);
|
||||
}
|
||||
return hashedFilename;
|
||||
}
|
||||
|
||||
private static CBase64Image _GetDelayedImage(string hashedFilename)
|
||||
{
|
||||
if (!_DelayedImagePath.ContainsKey(hashedFilename))
|
||||
{
|
||||
throw new FileNotFoundException("Image not found");
|
||||
}
|
||||
|
||||
string fileName = _DelayedImagePath[hashedFilename];
|
||||
|
||||
if (File.Exists(fileName))
|
||||
{
|
||||
Image image = Image.FromFile(fileName);
|
||||
return new CBase64Image(image, image.RawFormat);
|
||||
}
|
||||
throw new FileNotFoundException("Image not found");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region songs
|
||||
|
||||
private static SSongInfo _GetSong(int songId)
|
||||
{
|
||||
CSong song = CSongs.GetSong(songId);
|
||||
return _GetSongInfo(song, true);
|
||||
}
|
||||
|
||||
private static SSongInfo[] _GetAllSongs()
|
||||
{
|
||||
var songs = CSongs.Songs;
|
||||
return (from s in songs
|
||||
select _GetSongInfo(s, false)).ToArray<SSongInfo>();
|
||||
}
|
||||
|
||||
private static int _GetCurrentSongId()
|
||||
{
|
||||
CSong song = CGame.GetSong();
|
||||
if (song == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return song.ID;
|
||||
}
|
||||
|
||||
private static SSongInfo _GetSongInfo(CSong song, bool includeCover)
|
||||
{
|
||||
SSongInfo result = new SSongInfo();
|
||||
if (song != null)
|
||||
{
|
||||
result.Title = song.Title;
|
||||
result.Artist = song.Artist;
|
||||
result.Genre = song.Genres.FirstOrDefault();
|
||||
result.Language = song.Languages.FirstOrDefault();
|
||||
result.Year = song.Year;
|
||||
result.IsDuet = song.IsDuet;
|
||||
result.SongId = song.ID;
|
||||
if (includeCover)
|
||||
{
|
||||
result.Cover = new CBase64Image(_CreateDelayedImage(song.Folder + "\\" + song.CoverFileName));
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region playlist
|
||||
|
||||
private static SPlaylistInfo[] _GetPlaylists()
|
||||
{
|
||||
return (from p in CPlaylists.Playlists
|
||||
select _GetPlaylistInfo(p)).ToArray();
|
||||
}
|
||||
|
||||
private static SPlaylistInfo _GetPlaylist(int playlistId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
return _GetPlaylistInfo(CPlaylists.Playlists[playlistId]);
|
||||
}
|
||||
|
||||
private static void _AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
|
||||
if (allowDuplicates || !_PlaylistContainsSong(songId, playlistId))
|
||||
{
|
||||
CPlaylists.AddPlaylistSong(playlistId, songId);
|
||||
CPlaylists.SavePlaylist(playlistId);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("song exists in this playlist");
|
||||
}
|
||||
}
|
||||
|
||||
private static void _RemoveSongFromPlaylist(int position, int playlistId, int songId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
if (!_PlaylistContainsSong(songId, playlistId))
|
||||
{
|
||||
throw new ArgumentException("invalid songId");
|
||||
}
|
||||
if (position < 0 || CPlaylists.Playlists[playlistId].Songs.Count <= position
|
||||
|| CPlaylists.Playlists[playlistId].Songs[position].SongID != songId)
|
||||
{
|
||||
throw new ArgumentException("invalid position");
|
||||
}
|
||||
CPlaylists.Playlists[playlistId].DeleteSong(position);
|
||||
CPlaylists.SavePlaylist(playlistId);
|
||||
}
|
||||
|
||||
private static void _MoveSongInPlaylist(int newPosition, int playlistId, int songId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
if (!_PlaylistContainsSong(songId, playlistId))
|
||||
{
|
||||
throw new ArgumentException("invalid songId");
|
||||
}
|
||||
|
||||
if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition)
|
||||
{
|
||||
throw new ArgumentException("invalid newPosition");
|
||||
}
|
||||
|
||||
int oldPosition = CPlaylists.Playlists[playlistId].Songs.FindIndex(s => s.SongID == songId);
|
||||
CPlaylists.MovePlaylistSong(playlistId, oldPosition, newPosition);
|
||||
CPlaylists.SavePlaylist(playlistId);
|
||||
}
|
||||
|
||||
private static bool _PlaylistContainsSong(int songId, int playlistId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
return CPlaylists.Playlists[playlistId].Songs.Any(s => s.SongID == songId);
|
||||
}
|
||||
|
||||
private static SPlaylistSongInfo[] _GetPlaylistSongs(int playlistId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
|
||||
return _GetPlaylistSongInfos(CPlaylists.Playlists[playlistId]);
|
||||
}
|
||||
|
||||
private static SPlaylistSongInfo _GetPlaylistSongInfo(CPlaylistSong playlistSong, int playlistId, int playlistPos)
|
||||
{
|
||||
SPlaylistSongInfo result = new SPlaylistSongInfo();
|
||||
if (playlistSong != null)
|
||||
{
|
||||
result.PlaylistId = playlistId;
|
||||
result.GameMode = (int)playlistSong.GameMode;
|
||||
result.PlaylistPosition = playlistPos;
|
||||
result.Song = _GetSongInfo(CSongs.GetSong(playlistSong.SongID), true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SPlaylistSongInfo[] _GetPlaylistSongInfos(CPlaylistFile playlist)
|
||||
{
|
||||
SPlaylistSongInfo[] result = new SPlaylistSongInfo[playlist.Songs.Count];
|
||||
for (int i = 0; i < playlist.Songs.Count; i++)
|
||||
{
|
||||
result[i] = _GetPlaylistSongInfo(playlist.Songs[i], playlist.Id, i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SPlaylistInfo _GetPlaylistInfo(CPlaylistFile playlist)
|
||||
{
|
||||
return new SPlaylistInfo
|
||||
{
|
||||
PlaylistId = playlist.Id,
|
||||
PlaylistName = playlist.PlaylistName,
|
||||
SongCount = playlist.Songs.Count,
|
||||
LastChanged = DateTime.Now.ToLongDateString()
|
||||
};
|
||||
}
|
||||
|
||||
private static void _RemovePlaylist(int playlistId)
|
||||
{
|
||||
if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0)
|
||||
{
|
||||
throw new ArgumentException("invalid playlistId");
|
||||
}
|
||||
CPlaylists.DeletePlaylist(playlistId);
|
||||
}
|
||||
|
||||
private static int _AddPlaylist(string playlistName)
|
||||
{
|
||||
int newPlaylistId = CPlaylists.NewPlaylist();
|
||||
CPlaylists.Playlists[newPlaylistId].PlaylistName = playlistName;
|
||||
CPlaylists.SavePlaylist(newPlaylistId);
|
||||
|
||||
return newPlaylistId;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region user management
|
||||
|
||||
private static bool _ValidatePassword(int profileId, string password)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid profileId");
|
||||
}
|
||||
|
||||
if (profile.PasswordHash == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
return true; //Allow emty passwords
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] salt = profile.PasswordSalt;
|
||||
return _Hash((new UTF8Encoding()).GetBytes(password), salt).SequenceEqual(profile.PasswordHash);
|
||||
}
|
||||
|
||||
private static bool _ValidatePassword(int profileId, byte[] hashedPassword)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid profileId");
|
||||
}
|
||||
|
||||
if (profile.PasswordHash == null)
|
||||
{
|
||||
if (hashedPassword == null)
|
||||
{
|
||||
return true; //Allow emty passwords
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] salt = profile.PasswordSalt;
|
||||
return hashedPassword.SequenceEqual(profile.PasswordHash);
|
||||
}
|
||||
|
||||
private static byte[] _GetPassowordSalt(int profileId)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid profileId");
|
||||
}
|
||||
|
||||
if (profile.PasswordHash == null)
|
||||
{
|
||||
throw new ArgumentException("Emty password");
|
||||
}
|
||||
|
||||
return profile.PasswordSalt;
|
||||
}
|
||||
|
||||
private static int _GetUserRole(int profileId)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid profileId");
|
||||
}
|
||||
|
||||
return profile.UserRoles;
|
||||
}
|
||||
|
||||
private static void _SetUserRole(int profileId, int userRole)
|
||||
{
|
||||
CProfile profile = CProfiles.GetProfile(profileId);
|
||||
if (profile == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid profileId");
|
||||
}
|
||||
|
||||
profile.UserRoles = userRole;
|
||||
|
||||
CProfiles.EditProfile(profile);
|
||||
CProfiles.Update();
|
||||
CProfiles.SaveProfiles();
|
||||
}
|
||||
|
||||
private static int _GetUserIdFromUsername(string username)
|
||||
{
|
||||
var playerIds = (from p in CProfiles.GetProfiles()
|
||||
where String.Equals(p.PlayerName, username, StringComparison.OrdinalIgnoreCase)
|
||||
select p.ID);
|
||||
if (!playerIds.Any())
|
||||
{
|
||||
throw new ArgumentException("Invalid playername");
|
||||
}
|
||||
|
||||
return playerIds.First();
|
||||
}
|
||||
|
||||
private static byte[] _Hash(byte[] password, byte[] salt)
|
||||
{
|
||||
HashAlgorithm hashAlgo = new SHA256Managed();
|
||||
|
||||
byte[] data = new byte[password.Length + salt.Length];
|
||||
|
||||
password.CopyTo(data, 0);
|
||||
salt.CopyTo(data, password.Length);
|
||||
|
||||
return hashAlgo.ComputeHash(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static string _SaveImage(CBase64Image imageDate, string name, string folder)
|
||||
{
|
||||
Image avatarImage = imageDate.GetImage();
|
||||
string extension = imageDate.GetImageType();
|
||||
|
||||
if (!Directory.Exists(folder))
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
}
|
||||
|
||||
string filename = Path.Combine(folder, name);
|
||||
if (File.Exists(filename + "." + extension))
|
||||
{
|
||||
int i = 0;
|
||||
while (File.Exists(filename + "_" + i + "." + extension))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
filename = filename + "_" + i + "." + extension;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = filename + "." + extension;
|
||||
}
|
||||
|
||||
avatarImage.Save(filename);
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Vocaluxe.Base.Server
|
||||
public byte[] Sha256;
|
||||
}
|
||||
|
||||
public struct SAvatarPicture
|
||||
public struct SPicture
|
||||
{
|
||||
public int Width;
|
||||
public int Height;
|
||||
@@ -31,7 +31,7 @@ namespace Vocaluxe.Base.Server
|
||||
|
||||
public struct SProfile
|
||||
{
|
||||
public SAvatarPicture Avatar;
|
||||
public SPicture Avatar;
|
||||
public string PlayerName;
|
||||
public int Difficulty;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
@@ -31,6 +31,7 @@ namespace Vocaluxe.Lib.Playlist
|
||||
{
|
||||
public string PlaylistName;
|
||||
public string PlaylistFile;
|
||||
public int Id = -1;
|
||||
public List<CPlaylistSong> Songs = new List<CPlaylistSong>();
|
||||
|
||||
public CPlaylistFile()
|
||||
@@ -39,8 +40,9 @@ namespace Vocaluxe.Lib.Playlist
|
||||
PlaylistFile = string.Empty;
|
||||
}
|
||||
|
||||
public CPlaylistFile(string file)
|
||||
public CPlaylistFile(string file, int id)
|
||||
{
|
||||
Id = id;
|
||||
PlaylistFile = file;
|
||||
_LoadPlaylist();
|
||||
}
|
||||
@@ -217,7 +219,7 @@ namespace Vocaluxe.Lib.Playlist
|
||||
if (destNr < 0 || destNr > Songs.Count - 1)
|
||||
return;
|
||||
|
||||
var ps = new CPlaylistSong(songID, gm);
|
||||
CPlaylistSong ps = new CPlaylistSong(songID, gm);
|
||||
Songs.Insert(destNr, ps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">DebugWin</Configuration>
|
||||
@@ -15,7 +15,8 @@
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<StartupObject>Vocaluxe.CMainProgram</StartupObject>
|
||||
<ApplicationIcon>Vocaluxe.ico</ApplicationIcon>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
@@ -174,10 +175,6 @@
|
||||
<HintPath>..\Output\AForge.Video.DirectShow.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ClientServerLib">
|
||||
<HintPath>..\ClientServerLib\ClientServerLib\bin\ClientServerLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Community.CsharpSqlite">
|
||||
<HintPath>..\Output\Community.CsharpSqlite.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -197,6 +194,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.XML" />
|
||||
</ItemGroup>
|
||||
@@ -306,10 +304,122 @@
|
||||
</None>
|
||||
<Compile Include="Lib\Sound\PortAudio\PortAudio.cs" />
|
||||
<None Include="Doc\SQLite.NET.chm" />
|
||||
<Content Include="Website\locales\de.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\locales\en.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Doc\Roadmap.txt" />
|
||||
<Content Include="Vocaluxe.ico" />
|
||||
<Content Include="Website\css\images\ajax-loader.gif">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>images</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\css\images\alert.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\css\images\icons-18-black.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>images</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\css\images\icons-18-white.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>images</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\css\images\icons-36-black.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>images</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\css\images\icons-36-white.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>images</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\css\jquery.mobile-1.3.2.min.css">
|
||||
<CustomToolNamespace>css</CustomToolNamespace>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\css\jquery.mobile.theme-1.3.2.min.css">
|
||||
<CustomToolNamespace>css</CustomToolNamespace>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\css\style.css">
|
||||
<CustomToolNamespace>css</CustomToolNamespace>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\addPlaylist.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\logout.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\music.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\noCover.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\playlist.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\playlists.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\spotify.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\wikipedia.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\youtube.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\index.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\img\admin.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>img</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\img\keyboard.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>img</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\img\photo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>img</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\img\profile.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>img</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\img\profiles.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>img</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\js\i18next-1.7.1.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\js\jquery-1.9.1.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CustomToolNamespace>js</CustomToolNamespace>
|
||||
</Content>
|
||||
<Content Include="Website\js\jquery-ui-1.10.3.custom.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\js\jquery.mobile-1.3.2.min.js">
|
||||
<CustomToolNamespace>js</CustomToolNamespace>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\js\jquery.ui.touch-punch.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Website\js\main.js">
|
||||
<CustomToolNamespace>js</CustomToolNamespace>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client,KB2468871">
|
||||
@@ -324,12 +434,22 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ClientServerLib\ClientServerLib\ServerLib.csproj">
|
||||
<Project>{ec5167e4-ccfb-4cee-987c-cf816f1062a3}</Project>
|
||||
<Name>ServerLib</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\VocaluxeLib\VocaluxeLib.csproj">
|
||||
<Project>{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}</Project>
|
||||
<Name>VocaluxeLib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Website\html\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy /E /D /Y "$(ProjectDir)\Website" "$(SolutionDir)\PhoneGap"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 454 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,12 @@
|
||||
/*! jQuery Mobile 1.3.2 | Git HEAD hash: 528cf0e <> 2013-07-19T22:17:57Z | (c) 2010, 2013 jQuery Foundation, Inc. | jquery.org/license */
|
||||
|
||||
/*!
|
||||
* jQuery Mobile 1.3.2
|
||||
* Git HEAD hash: 528cf0e96940644ea644096bfeb913ed920ffaef <> Date: Fri Jul 19 2013 22:17:57 UTC
|
||||
* http://jquerymobile.com
|
||||
*
|
||||
* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
*/.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:700;text-shadow:0 -1px 0 #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a a.ui-link{color:#7cc4e7;font-weight:700}.ui-bar-a a.ui-link:visited{color:#2489ce}.ui-bar-a a.ui-link:hover{color:#2489ce}.ui-bar-a a.ui-link:active{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 0 #111;font-weight:400;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:700}.ui-body-a .ui-link:visited{color:#2489ce}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a:visited,.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a:visited,.ui-btn-hover-a:hover,.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a:visited,.ui-btn-down-a:hover,.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:700;text-shadow:0 1px 0 #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b a.ui-link{color:#ddf0f8;font-weight:700}.ui-bar-b a.ui-link:visited{color:#ddf0f8}.ui-bar-b a.ui-link:hover{color:#ddf0f8}.ui-bar-b a.ui-link:active{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:400;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:700}.ui-body-b .ui-link:visited{color:#2489ce}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:700;coloLine truncated
|
||||
@@ -0,0 +1,12 @@
|
||||
/*! jQuery Mobile 1.3.2 | Git HEAD hash: 528cf0e <> 2013-07-19T22:17:57Z | (c) 2010, 2013 jQuery Foundation, Inc. | jquery.org/license */
|
||||
|
||||
/*!
|
||||
* jQuery Mobile 1.3.2
|
||||
* Git HEAD hash: 528cf0e96940644ea644096bfeb913ed920ffaef <> Date: Fri Jul 19 2013 22:17:57 UTC
|
||||
* http://jquerymobile.com
|
||||
*
|
||||
* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
*/.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:700;text-shadow:0 -1px 0 #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a a.ui-link{color:#7cc4e7;font-weight:700}.ui-bar-a a.ui-link:visited{color:#2489ce}.ui-bar-a a.ui-link:hover{color:#2489ce}.ui-bar-a a.ui-link:active{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 0 #111;font-weight:400;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:700}.ui-body-a .ui-link:visited{color:#2489ce}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a:visited,.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a:visited,.ui-btn-hover-a:hover,.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:700;color:#fff;text-shadow:0 1px 0 #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a:visited,.ui-btn-down-a:hover,.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:700;text-shadow:0 1px 0 #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b a.ui-link{color:#ddf0f8;font-weight:700}.ui-bar-b a.ui-link:visited{color:#ddf0f8}.ui-bar-b a.ui-link:hover{color:#ddf0f8}.ui-bar-b a.ui-link:active{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:400;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:700}.ui-body-b .ui-link:visited{color:#2489ce}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:700;coloLine truncated
|
||||
@@ -0,0 +1,91 @@
|
||||
#playerAvatar {
|
||||
height: 75%;
|
||||
max-height: 250px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#playerName {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#displayProfileContent {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#keyboardContent {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
}
|
||||
|
||||
.ui-loader-background {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.ui-loading .ui-loader-background {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#displaySongCover {
|
||||
height: 75%;
|
||||
max-height: 250px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#displaySongContent {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#displaySongContent span {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.imageLoaderImg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url(images/ajax-loader.gif);
|
||||
background-size: 45px;
|
||||
border: #000000 solid 0px;
|
||||
content: '';
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.ui-body-c, .ui-overlay-c {
|
||||
background: #000000;
|
||||
}
|
||||
|
||||
.ui-input-search {
|
||||
background: #6E6E6E !important;
|
||||
}
|
||||
|
||||
.ui-listview-filter {
|
||||
background: #000000 !important;
|
||||
}
|
||||
|
||||
.ui-custom-errorIcon {
|
||||
background: url(images/alert.png) !important;
|
||||
background-size: 42px 42px;
|
||||
-webkit-border-radius: 0px !important;
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
||||
.cursorStyleClickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 628 B |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,373 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Vocaluxe</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.min.css" />
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
<script src="js/jquery-1.9.1.min.js"></script>
|
||||
<script src="phonegap.js"></script>
|
||||
<script src="barcodescanner.js"></script>
|
||||
<script>
|
||||
if (document.location.protocol == "file:") {
|
||||
if (typeof (window.deviceAndJqmLoaded) == "undefined") {
|
||||
window.deviceAndJqmLoaded = $.Deferred();
|
||||
}
|
||||
var jqmready = $.Deferred();
|
||||
var deviceready = $.Deferred();
|
||||
|
||||
$(document).bind("mobileinit", function () {
|
||||
jqmready.resolve();
|
||||
});
|
||||
|
||||
function deviceIsReady() {
|
||||
deviceready.resolve();
|
||||
}
|
||||
|
||||
document.addEventListener("deviceready", deviceIsReady, false);
|
||||
|
||||
$.when(jqmready, deviceready).then(function () {
|
||||
window.deviceAndJqmLoaded.resolve();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="js/jquery.mobile-1.3.2.min.js"></script>
|
||||
<script src="js/jquery-ui-1.10.3.custom.min.js"></script>
|
||||
<script src="js/jquery.ui.touch-punch.min.js"></script>
|
||||
<script src="js/i18next-1.7.1.min.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="discover" data-content-theme="a" data-role="page" data-add-back-btn="false">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="discoverConnectHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="discoverContent" data-role="content">
|
||||
<label for="discoverServerAddress" class="input" data-i18n="discoverConnectServerAddress"></label>
|
||||
<input type="text" id="discoverServerAddress" name="discoverServerAddress" data-mini="true">
|
||||
<a data-role="button" id="discoverConnect" data-i18n="discoverConnectButton"></a>
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
<a data-role="button" id="discoverReadQr" data-i18n="discoverReadQrButton"></a>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
<div id="login" data-content-theme="a" data-role="page" data-add-back-btn="false">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="">Login</h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="loginContent" data-role="content">
|
||||
<label for="loginName" class="input" data-i18n="loginName"></label>
|
||||
<input type="text" id="loginName" name="loginName" data-mini="true">
|
||||
<label for="loginPassword" class="input" data-i18n="loginPassword"></label>
|
||||
<input type="password" id="loginPassword" name="loginPassword" data-mini="true">
|
||||
<br />
|
||||
<a data-role="button" id="loginButton" data-i18n="loginButton"></a>
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
<a data-role="button" id="registerButton" data-i18n="registerButton"></a>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="main" data-role="page" data-content-theme="a">
|
||||
<div data-role="header">
|
||||
<h1>Volcaluxe</h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="mainContent" data-role="content" data-add-back-btn="true">
|
||||
<ul data-role="listview">
|
||||
<li>
|
||||
<a id="yourProfileLink" href="#" data-transition="slidefade">
|
||||
<img src="img/profile.png">
|
||||
<h2 data-i18n="mainPageYourProfileLink"></h2>
|
||||
<p data-i18n="mainPageYourProfileLinkDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="currentSongLink" href="#" data-transition="slidefade">
|
||||
<img src="img/music.png">
|
||||
<h2 data-i18n="mainPageCurrentSongLink"></h2>
|
||||
<p data-i18n="mainPageCurrentSongLinkDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#selectSong" data-transition="slidefade">
|
||||
<img src="img/playlist.png">
|
||||
<h2 data-i18n="mainPageSelectSong"></h2>
|
||||
<p data-i18n="mainPageSelectSongDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#selectPlaylist" data-transition="slidefade">
|
||||
<img src="img/playlists.png">
|
||||
<h2 data-i18n="mainPageSelectPlaylist"></h2>
|
||||
<p data-i18n="mainPageSelectPlaylistDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="mainPageSelectProfile" href="#selectProfile" data-transition="slidefade">
|
||||
<img src="img/profiles.png">
|
||||
<h2 data-i18n="mainPageSelectProfile"></h2>
|
||||
<p data-i18n="mainPageSelectProfileDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="mainPageTakePhotoLink" href="#" data-transition="slidefade">
|
||||
<img src="img/photo.png">
|
||||
<h2 data-i18n="mainPageTakePhotoLink"></h2>
|
||||
<p data-i18n="mainPageTakePhotoLinkDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="mainPageKeyboard" href="#keyboard" data-transition="slidefade">
|
||||
<img src="img/keyboard.png">
|
||||
<h2 data-i18n="mainPageKeyboard"></h2>
|
||||
<p data-i18n="mainPageKeyboardDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#selectUserAdmin" data-transition="slidefade">
|
||||
<img src="img/admin.png">
|
||||
<h2 data-i18n="mainPageSelectUserAdmin"></h2>
|
||||
<p data-i18n="mainPageSelectUserAdminDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="mainPageLogoutLink" href="#" data-transition="slidefade">
|
||||
<img src="img/logout.png">
|
||||
<h2 data-i18n="mainPageLogoutLink"></h2>
|
||||
<p data-i18n="mainPageLogoutLinkDesc"></p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="selectProfile" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="selectProfileHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="selectProfileContent" data-role="content">
|
||||
<ul id="selectProfileList" data-role="listview"></ul>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="displayProfile" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="displayProfileHeader">Profile</h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="displayProfileContent" data-role="content">
|
||||
<img id="playerAvatar" src="img/profile.png" alt="Avatar">
|
||||
<label for="playerName" class="input" data-i18n="displayProfileName"></label>
|
||||
<input type="text" id="playerName" name="playerName" data-mini="true" value="Your Name">
|
||||
|
||||
<label for="playerType" class="select" data-i18n="displayProfilePlayerType"></label>
|
||||
<select name="playerType" id="playerType">
|
||||
<option value="0" data-i18n="displayProfilePlayerTypeNormal"></option>
|
||||
<option value="1" data-i18n="displayProfilePlayerTypeGuest"></option>
|
||||
</select>
|
||||
<label for="playerDifficulty" class="select" data-i18n="displayProfilePlayerDifficulty"></label>
|
||||
<select name="playerDifficulty" id="playerDifficulty">
|
||||
<option value="0" data-i18n="displayProfilePlayerDifficultyEasy"></option>
|
||||
<option value="1" data-i18n="displayProfilePlayerDifficultyNormal"></option>
|
||||
<option value="2" data-i18n="displayProfilePlayerDifficultyHard"></option>
|
||||
</select>
|
||||
|
||||
<label id="playerPasswordLabel" for="playerPassword" class="input" data-i18n="displayProfilePlayerPassword"></label>
|
||||
<input type="password" id="playerPassword" name="playerPassword" data-mini="true" value="**oldPassword**">
|
||||
|
||||
<br />
|
||||
<a data-role="button" id="playerSaveButton" data-i18n="displayProfilePlayerSaveButton"></a>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="displaySong" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 id="displaySongTitle" data-i18n="displaySongHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="displaySongContent" data-role="content">
|
||||
<img id="displaySongCover" src="img/noCover.png" alt="Cover">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<label for="displaySongArtist" class="input" data-i18n="displaySongArtist"></label>
|
||||
<span id="displaySongArtist" data-mini="true">-</span>
|
||||
<br />
|
||||
<label for="displaySongGenre" class="input" data-i18n="displaySongGenre"></label>
|
||||
<span id="displaySongGenre" data-mini="true">-</span>
|
||||
<br />
|
||||
<label for="displaySongYear" class="input" data-i18n="displaySongYear"></label>
|
||||
<span id="displaySongYear" data-mini="true">-</span>
|
||||
<br />
|
||||
<label for="displaySongLanguage" class="input" data-i18n="displaySongLanguage"></label>
|
||||
<span id="displaySongLanguage" data-mini="true">-</span>
|
||||
<br />
|
||||
<label for="displaySongIsDuet" class="input" data-i18n="displaySongIsDuet"></label>
|
||||
<span id="displaySongIsDuet" data-mini="true">-</span>
|
||||
<br />
|
||||
<br />
|
||||
<div id="displaySongLinks">
|
||||
<img class="cursorStyleClickable" id="displaySongAddPlaylist" src="img/addPlaylist.png" />
|
||||
<br />
|
||||
<br />
|
||||
<img class="cursorStyleClickable" id="displaySongLinkYoutube" src="img/youtube.png" />
|
||||
<img class="cursorStyleClickable" id="displaySongLinkSpotify" src="img/spotify.png" />
|
||||
<img class="cursorStyleClickable" id="displaySongLinkWikipedia" src="img/wikipedia.png" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /content -->
|
||||
<div data-role="popup" id="popupVideo" data-overlay-theme="a" data-theme="a" data-corners="false" data-tolerance="15,15">
|
||||
<a href="#" data-role="button" data-theme="a" data-icon="delete" data-iconpos="notext" class="ui-btn-right" data-i18n="popupVideoClose"></a>
|
||||
<iframe width="480" height="320" seamless></iframe>
|
||||
</div>
|
||||
<!-- /popup -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="selectSong" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="selectSongHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="selectSongContent" data-role="content">
|
||||
<ul id="selectSongList" data-role="listview" data-filter="true" data-autodividers="true"></ul>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="keyboard" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="keyboardHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="keyboardContent" data-role="content">
|
||||
<div class="ui-grid-b">
|
||||
<div class="ui-block-a"></div>
|
||||
<div class="ui-block-b">
|
||||
<a data-role="button" id="keyboardButtonUp" data-i18n="keyboardButtonUp"></a>
|
||||
</div>
|
||||
<div class="ui-block-c"></div>
|
||||
<div class="ui-block-a">
|
||||
<a data-role="button" id="keyboardButtonLeft" data-i18n="keyboardButtonLeft"></a>
|
||||
</div>
|
||||
<div class="ui-block-b">
|
||||
</div>
|
||||
<div class="ui-block-c">
|
||||
<a data-role="button" id="keyboardButtonRight" data-i18n="keyboardButtonRight"></a>
|
||||
</div>
|
||||
<div class="ui-block-a"></div>
|
||||
<div class="ui-block-b">
|
||||
<a data-role="button" id="keyboardButtonDown" data-i18n="keyboardButtonDown"></a>
|
||||
</div>
|
||||
<div class="ui-block-c"></div>
|
||||
</div>
|
||||
<div class="ui-grid-b">
|
||||
<div class="ui-block-a">
|
||||
<a data-role="button" id="keyboardButtonEscape" data-i18n="keyboardButtonEscape"></a>
|
||||
</div>
|
||||
<div class="ui-block-b">
|
||||
<a data-role="button" id="keyboardButtonTab" data-i18n="keyboardButtonTab"></a>
|
||||
</div>
|
||||
<div class="ui-block-c">
|
||||
<a data-role="button" id="keyboardButtonReturn" data-i18n="keyboardButtonReturn"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div style>
|
||||
<label for="keyboardButtonKeys" data-i18n="keyboardButtonKeys"></label>
|
||||
<input type="text" id="keyboardButtonKeys" data-mini="true">
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="selectUserAdmin" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="selectUserAdminHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="selectUserAdminContent" data-role="content">
|
||||
<ul id="selectUserAdminList" data-role="listview"></ul>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="displayUserAdmin" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="displayUserAdminHeader"></h1>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="displayUserAdminContent" data-role="content">
|
||||
<fieldset data-role="controlgroup">
|
||||
<legend></legend>
|
||||
<input type="checkbox" id="roleAuthenticatedUser" checked="checked" disabled="disabled">
|
||||
<label for="roleAuthenticatedUser">AuthenticatedUser</label>
|
||||
<input type="checkbox" id="roleAdministrator">
|
||||
<label for="roleAdministrator">Administrator</label>
|
||||
</fieldset>
|
||||
<a data-role="button" id="btnRoleSave" data-transition="slidefade" data-i18n="displayUserAdminContentSaveButton"></a>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="selectPlaylist" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div data-role="header">
|
||||
<h1 data-i18n="selectPlaylistHeader"></h1>
|
||||
<a id="selectPlaylistAddPlaylistButton" href="#" class="ui-btn-right" data-icon="add" data-i18n="selectPlaylistAddPlaylistButton"></a>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="selectPlaylistContent" data-role="content">
|
||||
<ul data-split-theme="a" id="selectPlaylistContentList" data-role="listview" data-filter="true"></ul>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div id="displayPlaylist" data-content-theme="a" data-role="page" data-add-back-btn="true">
|
||||
<div id="displayPlaylistHeader" data-role="header">
|
||||
<h1 data-i18n="displayPlaylistHeader"></h1>
|
||||
<a id="displayPlaylistSaveButton" class="ui-btn-right" href="#" data-icon="add" data-i18n="displayPlaylistSaveButton"></a>
|
||||
</div>
|
||||
<!-- /header -->
|
||||
|
||||
<div id="displayPlaylistContent" data-role="content">
|
||||
<ol data-split-theme="a" id="displayPlaylistContentList" data-role="listview" data-filter="true"></ol>
|
||||
</div>
|
||||
<!-- /content -->
|
||||
</div>
|
||||
<!-- /page -->
|
||||
|
||||
<div class="ui-loader-background"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
// i18next, v1.7.1
|
||||
// Copyright (c)2013 Jan Mühlemann (jamuhl).
|
||||
// Distributed under MIT license
|
||||
// http://i18next.com
|
||||
!function(){function a(a,b){if(!b||"function"==typeof b)return a;for(var c in b)a[c]=b[c];return a}function b(a,b,c){var d,e=0,f=a.length,g=void 0===f||"function"==typeof a;if(c)if(g){for(d in a)if(b.apply(a[d],c)===!1)break}else for(;f>e&&b.apply(a[e++],c)!==!1;);else if(g){for(d in a)if(b.call(a[d],d,a[d])===!1)break}else for(;f>e&&b.call(a[e],e,a[e++])!==!1;);return a}function c(a){return"string"==typeof a?a.replace(/[&<>"'\/]/g,function(a){return H[a]}):a}function d(a){var b=function(a){if(window.XMLHttpRequest)return a(null,new XMLHttpRequest);if(window.ActiveXObject)try{return a(null,new ActiveXObject("Msxml2.XMLHTTP"))}catch(b){return a(null,new ActiveXObject("Microsoft.XMLHTTP"))}return a(new Error)},c=function(a){if("string"==typeof a)return a;var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(encodeURIComponent(c)+"="+encodeURIComponent(a[c]));return b.join("&")},d=function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);128>d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(192|d>>6),b+=String.fromCharCode(128|63&d)):(b+=String.fromCharCode(224|d>>12),b+=String.fromCharCode(128|63&d>>6),b+=String.fromCharCode(128|63&d))}return b},e=function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a=d(a);var c,e,f,g,h,i,j,k="",l=0;do c=a.charCodeAt(l++),e=a.charCodeAt(l++),f=a.charCodeAt(l++),g=c>>2,h=(3&c)<<4|e>>4,i=(15&e)<<2|f>>6,j=63&f,isNaN(e)?i=j=64:isNaN(f)&&(j=64),k+=b.charAt(g)+b.charAt(h)+b.charAt(i)+b.charAt(j),c=e=f="",g=h=i=j="";while(l<a.length);return k},f=function(){for(var a=arguments[0],b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}return a},g=function(a,d,e,h){"function"==typeof e&&(h=e,e={}),e.cache=e.cache||!1,e.data=e.data||{},e.headers=e.headers||{},e.jsonp=e.jsonp||!1,e.async=void 0===e.async?!0:e.async;var i,j=f({accept:"*/*","content-type":"application/x-www-form-urlencoded;charset=UTF-8"},g.headers,e.headers);if(i="application/json"===j["content-type"]?JSON.stringify(e.data):c(e.data),"GET"===a){var k=[];if(i&&(k.push(i),i=null),e.cache||k.push("_="+(new Date).getTime()),e.jsonp&&(k.push("callback="+e.jsonp),k.push("jsonp="+e.jsonp)),k=k.join("&"),k.length>1&&(d+=d.indexOf("?")>-1?"&"+k:"?"+k),e.jsonp){var l=document.getElementsByTagName("head")[0],m=document.createElement("script");return m.type="text/javascript",m.src=d,l.appendChild(m),void 0}}b(function(b,c){if(b)return h(b);c.open(a,d,e.async);for(var f in j)j.hasOwnProperty(f)&&c.setRequestHeader(f,j[f]);c.onreadystatechange=function(){if(4===c.readyState){var a=c.responseText||"";if(!h)return;h(c.status,{text:function(){return a},json:function(){return JSON.parse(a)}})}},c.send(i)})},h={authBasic:function(a,b){g.headers.Authorization="Basic "+e(a+":"+b)},connect:function(a,b,c){return g("CONNECT",a,b,c)},del:function(a,b,c){return g("DELETE",a,b,c)},get:function(a,b,c){return g("GET",a,b,c)},head:function(a,b,c){return g("HEAD",a,b,c)},headers:function(a){g.headers=a||{}},isAllowed:function(a,b,c){this.options(a,function(a,d){c(-1!==d.text().indexOf(b))})},options:function(a,b,c){return g("OPTIONS",a,b,c)},patch:function(a,b,c){return g("PATCH",a,b,c)},post:function(a,b,c){return g("POST",a,b,c)},put:function(a,b,c){return g("PUT",a,b,c)},trace:function(a,b,c){return g("TRACE",a,b,c)}},i=a.type?a.type.toLowerCase():"get";h[i](a.url,a,function(b,c){200===b?a.success(c.json(),b,null):a.error(c.text(),b,null)})}function e(a,b){"function"==typeof a&&(b=a,a={}),a=a||{},K.extend(G,a),delete G.fixLng,"string"==typeof G.ns&&(G.ns={namespaces:[G.ns],defaultNs:G.ns}),"string"==typeof G.fallbackNS&&(G.fallbackNS=[G.fallbackNS]),G.interpolationPrefixEscaped=K.regexEscape(G.interpolationPrefix),G.interpolationSuffixEscaped=K.regexEscape(G.interpolationSuffix),G.lng||(G.lng=K.detectLanguage()),G.lng?G.useCookie&&K.cookie.create(G.cookieName,G.lng,G.cookieExpirationTime,G.cookieDomain):(G.lng=G.fallbackLng,G.useCookie&&K.cookie.remove(G.cookieName)),E=K.toLanguages(G.lng),y=E[0],K.log("currentLng set to: "+y);var c=s;a.fixLng&&(c=function(a,b){return b=b||{},b.lng=b.lng||c.lng,s(a,b)},c.lng=y),M.setCurrentLng(y),A&&G.setJqueryExt&&m();var d;if(A&&A.Deferred&&(d=A.Deferred()),!G.resStore){var e=K.toLanguages(G.lng);"string"==typeof G.preload&&(G.preload=[G.preload]);for(var f=0,g=G.preload.length;g>f;f++)for(var h=K.toLanguages(G.preload[f]),i=0,j=h.length;j>i;i++)e.indexOf(h[i])<0&&e.push(h[i]);return B.sync.load(e,G,function(a,e){C=e,F=!0,b&&b(c),d&&d.resolve(c)}),d?d.promise():void 0}return C=G.resStore,F=!0,b&&b(c),d&&d.resolve(c),d?d.promise():void 0}function f(a,b){"string"==typeof a&&(a=[a]);for(var c=0,d=a.length;d>c;c++)G.preload.indexOf(a[c])<0&&G.preload.push(a[c]);return e(b)}function g(a,b,c){"string"!=typeof b?(c=b,b=G.ns.defaultNs):G.ns.namespaces.indexOf(b)<0&&G.ns.namespaces.push(b),C[a]=C[a]||{},C[a][b]=C[a][b]||{},K.extend(C[a][b],c)}function h(a){G.ns.defaultNs=a}function i(a,b){j([a],b)}funLine truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
|
||||
//@ sourceMappingURL=jquery.min.map
|
||||
*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(Line truncated
|
||||
return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+Line truncated
|
||||
}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}reLine truncated
|
||||
@@ -0,0 +1,6 @@
|
||||
/*! jQuery UI - v1.10.3 - 2013-11-03
|
||||
* http://jqueryui.com
|
||||
* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js
|
||||
* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
|
||||
|
||||
(function(e,t){function i(t,i){var s,n,r,o=t.nodeName.toLowerCase();return"area"===o?(s=t.parentNode,n=s.name,t.href&&n&&"map"===s.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&a(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&a(t)}function a(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,a){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),a&&a.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var a,s,n=e(this[0]);n.length&&n[0]!==document;){if(a=n.css("position"),("absolute"===a||"relative"===a||"fixed"===a)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,a){return!!e.data(t,a[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var a=e.attr(t,"tabindex"),s=isNaN(a);return(s||a>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,a){function s(t,i,a,s){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,a&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===a?["Left","Right"]:["Top","Bottom"],r=a.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+a]=function(i){return i===t?o["inner"+a].call(this):this.each(function(){e(this).css(r,s(this,i)+"px")})},e.fn["outer"+a]=function(t,i){return"number"!=typeof t?o["outer"+a].call(this,t):this.each(function(){e(this).css(r,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,a){var s,n=e.ui[t].prototype;for(s in a)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([i,a[s]])},call:function(e,t,i){var a,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(a=0;s.length>a;a++)e.options[s[a][0]]&&s[a][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var a=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[a]>0?!0:(t[a]=1,s=t[a]>0,t[a]=0,s)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,a=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(n){}a(t)},e.widget=function(i,s,a){var n,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],n=u+"-"+i,a||(a=s,s=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:a.version,_proto:e.extend({},a),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(a,function(i,a){return e.isFunction(a)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,n=this._superApply;return this._suLine truncated
|
||||
@@ -0,0 +1,9 @@
|
||||
/*! jQuery Mobile 1.3.2 | Git HEAD hash: 528cf0e <> 2013-07-19T22:17:57Z | (c) 2010, 2013 jQuery Foundation, Inc. | jquery.org/license */
|
||||
!function(a,b,c){"function"==typeof define&&define.amd?define(["jquery"],function(d){return c(d,a,b),d.mobile}):c(a.jQuery,a,b)}(this,document,function(a,b,c,d){!function(a){a.mobile={}}(a),function(a,b,d){var e={};a.mobile=a.extend(a.mobile,{version:"1.3.2",ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:!0,hashListeningEnabled:!0,linkBindingEnabled:!0,defaultPageTransition:"fade",maxTransitionWidth:!1,minScrollBack:250,touchOverflowEnabled:!1,defaultDialogTransition:"pop",pageLoadErrorMessage:"Error Loading Page",pageLoadErrorMessageTheme:"e",phonegapNavigationEnabled:!1,autoInitializePage:!0,pushStateEnabled:!0,ignoreContentEnabled:!1,orientationChangeEnabled:!0,buttonMarkup:{hoverDelay:200},window:a(b),document:a(c),keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},behaviors:{},silentScroll:function(c){"number"!==a.type(c)&&(c=a.mobile.defaultHomeScroll),a.event.special.scrollstart.enabled=!1,setTimeout(function(){b.scrollTo(0,c),a.mobile.document.trigger("silentscroll",{x:0,y:c})},20),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},nsNormalizeDict:e,nsNormalize:function(b){return b?e[b]||(e[b]=a.camelCase(a.mobile.ns+b)):void 0},getInheritedTheme:function(a,b){for(var c,d,e=a[0],f="",g=/ui-(bar|body|overlay)-([a-z])\b/;e&&(c=e.className||"",!(c&&(d=g.exec(c))&&(f=d[2])));)e=e.parentNode;return f||b||"a"},closestPageData:function(a){return a.closest(':jqmData(role="page"), :jqmData(role="dialog")').data("mobile-page")},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;for(var d,e,f,g=b.length,h=a(),i=0;g>i;i++){for(e=b.eq(i),f=!1,d=b[i];d;){var j=d.getAttribute?d.getAttribute("data-"+a.mobile.ns+c):"";if("false"===j){f=!0;break}d=d.parentNode}f||(h=h.add(e))}return h},getScreenHeight:function(){return b.innerHeight||a.mobile.window.height()}},a.mobile),a.fn.jqmData=function(b,c){var e;return"undefined"!=typeof b&&(b&&(b=a.mobile.nsNormalize(b)),e=arguments.length<2||c===d?this.data(b):this.data(b,c)),e},a.jqmData=function(b,c,d){var e;return"undefined"!=typeof c&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,d)),e},a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))},a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))},a.fn.removeWithDependents=function(){a.removeWithDependents(this)},a.removeWithDependents=function(b){var c=a(b);(c.jqmData("dependents")||a()).remove(),c.remove()},a.fn.addDependents=function(b){a.addDependents(a(this),b)},a.addDependents=function(b,c){var d=a(b).jqmData("dependents")||a();a(b).jqmData("dependents",a.merge(d,c))},a.fn.getEncodedText=function(){return a("<div/>").text(a(this).text()).html()},a.fn.jqmEnhanceable=function(){return a.mobile.enhanceable(this)},a.fn.jqmHijackable=function(){return a.mobile.hijackable(this)};var f=a.find,g=/:jqmData\(([^)]*)\)/g;a.find=function(b,c,d,e){return b=b.replace(g,"[data-"+(a.mobile.ns||"")+"$1]"),f.call(this,b,c,d,e)},a.extend(a.find,f),a.find.matches=function(b,c){return a.find(b,null,null,c)},a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}}(a,this),function(a,b){var c=0,d=Array.prototype.slice,e=a.cleanData;a.cleanData=function(b){for(var c,d=0;null!=(c=b[d]);d++)try{a(c).triggerHandler("remove")}catch(f){}e(b)},a.widget=function(b,c,d){var e,f,g,h,i=b.split(".")[0];b=b.split(".")[1],e=i+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][e.toLowerCase()]=function(b){return!!a.data(b,e)},a[i]=a[i]||{},f=a[i][b],g=a[i][b]=function(a,b){return this._createWidget?(arguments.length&&this._createWidget(a,b),void 0):new g(a,b)},a.extend(g,f,{version:d.version,_proto:a.extend({},d),_childConstructors:[]}),h=new c,h.options=a.widget.extend({},h.options),a.each(d,function(b,e){a.isFunction(e)&&(d[b]=function(){var a=function(){return c.prototype[b].apply(this,arguments)},d=function(a){return c.prototype[b].apply(this,a)};return function(){var b,c=this._super,f=this._superApply;return this._super=a,this._superApply=d,b=e.apply(this,arguments),this._super=c,this._superApply=f,b}}())}),g.prototype=a.widget.extend(h,{widgetEventPrefix:f?h.widgetEventPrefix:b},d,{constructor:g,namespace:i,widgetName:b,widgetFullName:e}),f?(a.each(f._childConstructors,function(b,c){var d=c.prototype;a.widget(d.namespace+"."+d.widgetName,g,c._proto)}),delete f._childConstructors):c._childConstructors.push(g),a.widget.bridge(b,g)},a.widget.extend=function(c){for(var e,f,g=d.call(arguments,1),h=0,i=g.length;i>h;h++)for(e in g[h])f=g[h][e],g[h].hasLine truncated
|
||||
}if(d.which&&1!==d.which)return!1;var j,k=d.target;d.originalEvent,c.bind("vmouseup",g).bind("vclick",i),f.bind("vmousecancel",h),j=setTimeout(function(){e(b,"taphold",a.Event("taphold",{target:k}))},a.event.special.tap.tapholdThreshold)})}},a.event.special.swipe={scrollSupressionThreshold:30,durationThreshold:1e3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,start:function(b){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b;return{time:(new Date).getTime(),coords:[c.pageX,c.pageY],origin:a(b.target)}},stop:function(a){var b=a.originalEvent.touches?a.originalEvent.touches[0]:a;return{time:(new Date).getTime(),coords:[b.pageX,b.pageY]}},handleSwipe:function(b,c){c.time-b.time<a.event.special.swipe.durationThreshold&&Math.abs(b.coords[0]-c.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(b.coords[1]-c.coords[1])<a.event.special.swipe.verticalDistanceThreshold&&b.origin.trigger("swipe").trigger(b.coords[0]>c.coords[0]?"swipeleft":"swiperight")},setup:function(){var b=this,c=a(b);c.bind(i,function(b){function e(b){g&&(f=a.event.special.swipe.stop(b),Math.abs(g.coords[0]-f.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault())}var f,g=a.event.special.swipe.start(b);c.bind(k,e).one(j,function(){c.unbind(k,e),g&&f&&a.event.special.swipe.handleSwipe(g,f),g=f=d})})}},a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe",swiperight:"swipe"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)}}})}(a,this),function(a){a.event.special.throttledresize={setup:function(){a(this).bind("resize",f)},teardown:function(){a(this).unbind("resize",f)}};var b,c,d,e=250,f=function(){c=(new Date).getTime(),d=c-g,d>=e?(g=c,a(this).trigger("throttledresize")):(b&&clearTimeout(b),b=setTimeout(f,e-d))},g=0}(a),function(a,b){function d(){var a=e();a!==f&&(f=a,i.trigger(j))}var e,f,g,h,i=a(b),j="orientationchange",k={0:!0,180:!0};if(a.support.orientation){var l=b.innerWidth||i.width(),m=b.innerHeight||i.height(),n=50;g=l>m&&l-m>n,h=k[b.orientation],(g&&h||!g&&!h)&&(k={"-90":!0,90:!0})}a.event.special.orientationchange=a.extend({},a.event.special.orientationchange,{setup:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:(f=e(),i.bind("throttledresize",d),void 0)},teardown:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:(i.unbind("throttledresize",d),void 0)},add:function(a){var b=a.handler;a.handler=function(a){return a.orientation=e(),b.apply(this,arguments)}}}),a.event.special.orientationchange.orientation=e=function(){var d=!0,e=c.documentElement;return d=a.support.orientation?k[b.orientation]:e&&e.clientWidth/e.clientHeight<1.1,d?"portrait":"landscape"},a.fn[j]=function(a){return a?this.bind(j,a):this.trigger(j)},a.attrFn&&(a.attrFn[j]=!0)}(a,this),function(a){a.widget("mobile.page",a.mobile.widget,{options:{theme:"c",domCache:!1,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){return this._trigger("beforecreate")===!1?!1:(this.element.attr("tabindex","0").addClass("ui-page ui-body-"+this.options.theme),this._on(this.element,{pagebeforehide:"removeContainerBackground",pagebeforeshow:"_handlePageBeforeShow"}),void 0)},_handlePageBeforeShow:function(){this.setContainerBackground()},removeContainerBackground:function(){a.mobile.pageContainer.removeClass("ui-overlay-"+a.mobile.getInheritedTheme(this.element.parent()))},setContainerBackground:function(b){this.options.theme&&a.mobile.pageContainer.addClass("ui-overlay-"+(b||this.options.theme))},keepNativeSelector:function(){var b=this.options,c=b.keepNative&&a.trim(b.keepNative);return c&&b.keepNative!==b.keepNativeDefault?[b.keepNative,b.keepNativeDefault].join(", "):b.keepNativeDefault}})}(a),function(a,b,c){var d=function(d){return d===c&&(d=!0),function(c,e,f,g){var h=new a.Deferred,i=e?" reverse":"",j=a.mobile.urlHistory.getActive(),k=j.lastScroll||a.mobile.defaultHomeScroll,l=a.mobile.getScreenHeight(),m=a.mobile.maxTransitionWidth!==!1&&a.mobile.window.width()>a.mobile.maxTransitionWidth,n=!a.support.cssTransitions||m||!c||"none"===c||Math.max(a.mobile.window.scrollTop(),k)>a.mobile.getMaxScrollForTransition(),o=" ui-page-pre-in",p=function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+c)},q=function(){a.event.special.scrollstart.enabled=!1,b.scrollTo(0,k),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},r=function(){g.removeClass(a.mobile.activePageClass+" out in reverse "+c).height("")},s=function(){d?g.animationComplete(t):t(),g.height(l+a.mobile.window.scrollTop()).addClass(c+" out"+i)},t=function(){g&&d&&r(),u()},u=function(){f.css("z-index",-10),f.addClass(a.mobile.activePageClass+o),a.mobile.focusPage(f),f.height(l+k),q(),f.css("z-index",""),n||f.animationComplete(v),f.removeClass(o).addClass(c+" in"+i),n&&v()},v=function(){d||g&&r(),f.removeClass("out in reverse "+c).height(""),p(),a.mobile.window.scrollTop(Line truncated
|
||||
c.parent().is(":jqmData(role='collapsible-set')")&&c.siblings(".ui-collapsible").trigger("collapse")})},_init:function(){var a=this.element,b=a.children(":jqmData(role='collapsible')"),c=b.filter(":jqmData(collapsed='false')");this._refresh("true"),c.trigger("expand")},_refresh:function(b){var c=this.element.children(":jqmData(role='collapsible')");a.mobile.collapsible.prototype.enhance(c.not(".ui-collapsible")),this._addFirstLastClasses(c,this._getVisibles(c,b),b)},refresh:function(){this._refresh(!1)}},a.mobile.behaviors.addFirstLastClasses)),a.mobile.document.bind("pagecreate create",function(b){a.mobile.collapsibleset.prototype.enhanceWithin(b.target)})}(a),function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain ui-body ui-br").contents().filter(function(){return 3===this.nodeType&&!/\S/.test(this.nodeValue)}).remove()},a(c).bind("pagecreate create",function(b){a(":jqmData(role='fieldcontain')",b.target).jqmEnhanceable().fieldcontain()})}(a),function(a){a.fn.grid=function(b){return this.each(function(){var c,d=a(this),e=a.extend({grid:null},b),f=d.children(),g={solo:1,a:2,b:3,c:4,d:5},h=e.grid;if(!h)if(f.length<=5)for(var i in g)g[i]===f.length&&(h=i);else h="a",d.addClass("ui-grid-duo");c=g[h],d.addClass("ui-grid-"+h),f.filter(":nth-child("+c+"n+1)").addClass("ui-block-a"),c>1&&f.filter(":nth-child("+c+"n+2)").addClass("ui-block-b"),c>2&&f.filter(":nth-child("+c+"n+3)").addClass("ui-block-c"),c>3&&f.filter(":nth-child("+c+"n+4)").addClass("ui-block-d"),c>4&&f.filter(":nth-child("+c+"n+5)").addClass("ui-block-e")})}}(a),function(a,b){a.widget("mobile.navbar",a.mobile.widget,{options:{iconpos:"top",grid:null,initSelector:":jqmData(role='navbar')"},_create:function(){var d=this.element,e=d.find("a"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:b;d.addClass("ui-navbar ui-mini").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid}),e.buttonMarkup({corners:!1,shadow:!1,inline:!0,iconpos:f}),d.delegate("a","vclick",function(b){var d=a(b.target).is("a")?a(this):a(this).parent("a");if(!d.is(".ui-disabled, .ui-btn-active")){e.removeClass(a.mobile.activeBtnClass),a(this).addClass(a.mobile.activeBtnClass);var f=a(this);a(c).one("pagehide",function(){f.removeClass(a.mobile.activeBtnClass)})}}),d.closest(".ui-page").bind("pagebeforeshow",function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}}),a.mobile.document.bind("pagecreate create",function(b){a.mobile.navbar.prototype.enhanceWithin(b.target)})}(a),function(a){var b={};a.widget("mobile.listview",a.mobile.widget,a.extend({options:{theme:null,countTheme:"c",headerTheme:"b",dividerTheme:"b",icon:"arrow-r",splitIcon:"arrow-r",splitTheme:"b",corners:!0,shadow:!0,inset:!1,initSelector:":jqmData(role='listview')"},_create:function(){var a=this,b="";b+=a.options.inset?" ui-listview-inset":"",a.options.inset&&(b+=a.options.corners?" ui-corner-all":"",b+=a.options.shadow?" ui-shadow":""),a.element.addClass(function(a,c){return c+" ui-listview"+b}),a.refresh(!0)},_findFirstElementByTagName:function(a,b,c,d){var e={};for(e[c]=e[d]=!0;a;){if(e[a.nodeName])return a;a=a[b]}return null},_getChildrenByTagName:function(b,c,d){var e=[],f={};for(f[c]=f[d]=!0,b=b.firstChild;b;)f[b.nodeName]&&e.push(b),b=b.nextSibling;return a(e)},_addThumbClasses:function(b){var c,d,e=b.length;for(c=0;e>c;c++)d=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),d.length&&(d.addClass("ui-li-thumb"),a(this._findFirstElementByTagName(d[0].parentNode,"parentNode","li","LI")).addClass(d.is(".ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb"))},refresh:function(b){this.parentPage=this.element.closest(".ui-page"),this._createSubPages();var d,e,f,g,h,i,j,k,l,m,n,o,p=this.options,q=this.element,r=q.jqmData("dividertheme")||p.dividerTheme,s=q.jqmData("splittheme"),t=q.jqmData("spliticon"),u=q.jqmData("icon"),v=this._getChildrenByTagName(q[0],"li","LI"),w=!!a.nodeName(q[0],"ol"),x=!a.support.cssPseudoElement,y=q.attr("start"),z={};w&&x&&q.find(".ui-li-dec").remove(),w&&(y||0===y?x?j=parseInt(y,10):(k=parseInt(y,10)-1,q.css("counter-reset","listnumbering "+k)):x&&(j=1)),p.theme||(p.theme=a.mobile.getInheritedTheme(this.element,"c"));for(var A=0,B=v.length;B>A;A++){if(d=v.eq(A),e="ui-li",b||!d.hasClass("ui-li")){f=d.jqmData("theme")||p.theme,g=this._getChildrenByTagName(d[0],"a","A");var C="list-divider"===d.jqmData("role");g.length&&!C?(n=d.jqmData("icon"),d.buttonMarkup({wrapperEls:"div",shadow:!1,corners:!1,iconpos:"right",icon:g.length>1||n===!1?!1:n||u||p.icon,theme:f}),n!==!1&&1===g.length&&d.addClass("ui-li-has-arrow"),g.first().removeClass("ui-link").addClass("ui-link-inherit"),g.length>1&&(e+=" ui-li-has-alt",h=g.last(),i=s||h.jqmData("theme")||p.splitTheme,o=h.jqmData("icon"),h.appendTo(d).attr("title",a.trim(h.getEncodedText())).addClass("ui-li-link-alt").empty().buttonMarkup({shadow:!1,corners:!1,theme:f,icon:!1,iconpos:"notext"}).find(".ui-btn-inner").append(a(c.createElement("span")).Line truncated
|
||||
},_setDisabled:function(a){return this.element.attr("disabled",a),this.button.attr("aria-disabled",a),this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var b="";~this.element[0].className.indexOf("ui-btn-left")&&(b=" ui-btn-left"),~this.element[0].className.indexOf("ui-btn-right")&&(b=" ui-btn-right"),this.select=this.element.removeClass("ui-btn-left ui-btn-right").wrap("<div class='ui-select"+b+"'>"),this.selectID=this.select.attr("id"),this.label=a("label[for='"+this.selectID+"']").addClass("ui-select"),this.isMultiple=this.select[0].multiple,this.options.theme||(this.options.theme=a.mobile.getInheritedTheme(this.select,"c"))},_destroy:function(){var a=this.element.parents(".ui-select");a.length>0&&(a.is(".ui-btn-left, .ui-btn-right")&&this.element.addClass(a.is(".ui-btn-left")?"ui-btn-left":"ui-btn-right"),this.element.insertAfter(a),a.remove())},_create:function(){this._preExtension(),this._trigger("beforeCreate"),this.button=this._button();var c=this,d=this.options,e=d.inline||this.select.jqmData("inline"),f=d.mini||this.select.jqmData("mini"),g=d.icon?d.iconpos||this.select.jqmData("iconpos"):!1,h=(-1===this.select[0].selectedIndex?0:this.select[0].selectedIndex,this.button.insertBefore(this.select).buttonMarkup({theme:d.theme,icon:d.icon,iconpos:g,inline:e,corners:d.corners,shadow:d.shadow,iconshadow:d.iconshadow,mini:f}));this.setButtonText(),d.nativeMenu&&b.opera&&b.opera.version&&h.addClass("ui-select-nativeonly"),this.isMultiple&&(this.buttonCount=a("<span>").addClass("ui-li-count ui-btn-up-c ui-btn-corner-all").hide().appendTo(h.addClass("ui-li-has-count"))),(d.disabled||this.element.attr("disabled"))&&this.disable(),this.select.change(function(){c.refresh(),d.nativeMenu&&this.blur()}),this._handleFormReset(),this.build()},build:function(){var b=this;this.select.appendTo(b.button).bind("vmousedown",function(){b.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){b.button.addClass(a.mobile.focusClass)}).bind("blur",function(){b.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){b.button.trigger("vmouseover")}).bind("vmousemove",function(){b.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){b.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}).bind("change blur",function(){b.button.removeClass("ui-btn-down-"+b.options.theme)}),b.button.bind("vmousedown",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.label.bind("click focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.select.bind("focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.button.bind("mouseup",function(){b.options.preventFocusZoom&&setTimeout(function(){a.mobile.zoom.enable(!0)},0)}),b.select.bind("blur",function(){b.options.preventFocusZoom&&a.mobile.zoom.enable(!0)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var b=this,d=this.selected(),e=this.placeholder,f=a(c.createElement("span"));this.button.find(".ui-btn-text").html(function(){return e=d.length?d.map(function(){return a(this).text()}).get().join(", "):b.placeholder,f.text(e).addClass(b.select.attr("class")).addClass(d.attr("class"))})},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},_reset:function(){this.refresh()},refresh:function(){this.setButtonText(),this.setButtonCount()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(!0),this.button.addClass("ui-disabled")},enable:function(){this._setDisabled(!1),this.button.removeClass("ui-disabled")}},a.mobile.behaviors.formReset)),a.mobile.document.bind("pagecreate create",function(b){a.mobile.selectmenu.prototype.enhanceWithin(b.target,!0)})}(a),function(a,d){function e(a,b,c,d){var e=d;return e=b>a?c+(a-b)/2:Math.min(Math.max(c,d-b/2),c+a-b)}function f(){var c=a.mobile.window;return{x:c.scrollLeft(),y:c.scrollTop(),cx:b.innerWidth||c.width(),cy:b.innerHeight||c.height()}}a.widget("mobile.popup",a.mobile.widget,{options:{theme:null,overlayTheme:null,shadow:!0,corners:!0,transition:"none",positionTo:"origin",tolerance:null,initSelector:":jqmData(role='popup')",closeLinkSelector:"a:jqmData(rel='back')",closeLinkEvents:"click.popup",navigateEvents:"navigate.popup",closeEvents:"navigate.popup pagebeforechange.popup",dismissible:!0,history:!a.mobile.browser.oldIE},_eatEventAndClose:function(a){return a.preventDefault(),a.stopImmediatePropagation(),this.options.dismissible&&this.close(),!1},_resizeScreen:function(){var a=this._ui.container.outerHeight(!0);this._ui.screen.removeAttr("style"),a>this._ui.screen.height()&&this._ui.screen.height(a)},_handleWindowKeyUp:function(bLine truncated
|
||||
return c||(d=Math.round(d-a.mobile.window.height()+b.outerHeight())-60),d},_bindScrollWorkaround:function(){var b=this;this._on(a.mobile.window,{scrollstop:function(){var a=b._viewportOffset();a>2&&b._visible&&b._triggerRedraw()}})},_bindListThumbWorkaround:function(){this.element.closest(".ui-page").addClass("ui-android-2x-fixed")},_triggerRedraw:function(){var b=parseFloat(a(".ui-page-active").css("padding-bottom"));a(".ui-page-active").css("padding-bottom",b+1+"px"),setTimeout(function(){a(".ui-page-active").css("padding-bottom",b+"px")},0)},destroy:function(){this._super(),this.element.closest(".ui-page-active").removeClass("ui-android-2x-fix")}})}(a),function(a,d){a.widget("mobile.panel",a.mobile.widget,{options:{classes:{panel:"ui-panel",panelOpen:"ui-panel-open",panelClosed:"ui-panel-closed",panelFixed:"ui-panel-fixed",panelInner:"ui-panel-inner",modal:"ui-panel-dismiss",modalOpen:"ui-panel-dismiss-open",pagePanel:"ui-page-panel",pagePanelOpen:"ui-page-panel-open",contentWrap:"ui-panel-content-wrap",contentWrapOpen:"ui-panel-content-wrap-open",contentWrapClosed:"ui-panel-content-wrap-closed",contentFixedToolbar:"ui-panel-content-fixed-toolbar",contentFixedToolbarOpen:"ui-panel-content-fixed-toolbar-open",contentFixedToolbarClosed:"ui-panel-content-fixed-toolbar-closed",animate:"ui-panel-animate"},animate:!0,theme:"c",position:"left",dismissible:!0,display:"reveal",initSelector:":jqmData(role='panel')",swipeClose:!0,positionFixed:!1},_panelID:null,_closeLink:null,_page:null,_modal:null,_panelInner:null,_wrapper:null,_fixedToolbar:null,_create:function(){var b=this,c=b.element,d=c.closest(":jqmData(role='page')"),e=function(){var b=a.data(d[0],"mobilePage").options.theme,c="ui-body-"+b;return c},f=function(){var a=c.find("."+b.options.classes.panelInner);return 0===a.length&&(a=c.children().wrapAll('<div class="'+b.options.classes.panelInner+'" />').parent()),a},g=function(){var c=d.find("."+b.options.classes.contentWrap);return 0===c.length&&(c=d.children(".ui-header:not(:jqmData(position='fixed')), .ui-content:not(:jqmData(role='popup')), .ui-footer:not(:jqmData(position='fixed'))").wrapAll('<div class="'+b.options.classes.contentWrap+" "+e()+'" />').parent(),a.support.cssTransform3d&&b.options.animate&&c.addClass(b.options.classes.animate)),c},h=function(){var c=d.find("."+b.options.classes.contentFixedToolbar);return 0===c.length&&(c=d.find(".ui-header:jqmData(position='fixed'), .ui-footer:jqmData(position='fixed')").addClass(b.options.classes.contentFixedToolbar),a.support.cssTransform3d&&b.options.animate&&c.addClass(b.options.classes.animate)),c};a.extend(this,{_panelID:c.attr("id"),_closeLink:c.find(":jqmData(rel='close')"),_page:c.closest(":jqmData(role='page')"),_pageTheme:e(),_panelInner:f(),_wrapper:g(),_fixedToolbar:h()}),b._addPanelClasses(),b._wrapper.addClass(this.options.classes.contentWrapClosed),b._fixedToolbar.addClass(this.options.classes.contentFixedToolbarClosed),b._page.addClass(b.options.classes.pagePanel),a.support.cssTransform3d&&b.options.animate&&this.element.addClass(b.options.classes.animate),b._bindUpdateLayout(),b._bindCloseEvents(),b._bindLinkListeners(),b._bindPageEvents(),b.options.dismissible&&b._createModal(),b._bindSwipeEvents()},_createModal:function(){var b=this;b._modal=a("<div class='"+b.options.classes.modal+"' data-panelid='"+b._panelID+"'></div>").on("mousedown",function(){b.close()}).appendTo(this._page)},_getPosDisplayClasses:function(a){return a+"-position-"+this.options.position+" "+a+"-display-"+this.options.display},_getPanelClasses:function(){var a=this.options.classes.panel+" "+this._getPosDisplayClasses(this.options.classes.panel)+" "+this.options.classes.panelClosed;return this.options.theme&&(a+=" ui-body-"+this.options.theme),this.options.positionFixed&&(a+=" "+this.options.classes.panelFixed),a},_addPanelClasses:function(){this.element.addClass(this._getPanelClasses())},_bindCloseEvents:function(){var a=this;a._closeLink.on("click.panel",function(b){return b.preventDefault(),a.close(),!1}),a.element.on("click.panel","a:jqmData(ajax='false')",function(){a.close()})},_positionPanel:function(){var b=this,c=b._panelInner.outerHeight(),d=c>a.mobile.getScreenHeight();d||!b.options.positionFixed?(d&&(b._unfixPanel(),a.mobile.resetActivePageHeight(c)),b._scrollIntoView(c)):b._fixPanel()},_scrollIntoView:function(c){c<a(b).scrollTop()&&b.scrollTo(0,0)},_bindFixListener:function(){this._on(a(b),{throttledresize:"_positionPanel"})},_unbindFixListener:function(){this._off(a(b),"throttledresize")},_unfixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.removeClass(this.options.classes.panelFixed)},_fixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.addClass(this.options.classes.panelFixed)},_bindUpdateLayout:function(){var a=this;a.element.on("updatelayout",function(){a._open&&a._positionPanel()})},_bindLinkListeners:function(){var b=this;b._page.on("click.panel","a",function(c){if(this.hrLine truncated
|
||||
/*
|
||||
//@ sourceMappingURL=jquery.mobile-1.3.2.min.map
|
||||
*/
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* jQuery UI Touch Punch 0.2.2
|
||||
*
|
||||
* Copyright 2011, Dave Furfero
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.widget.js
|
||||
* jquery.ui.mouse.js
|
||||
*/
|
||||
(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return;}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return;}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f);}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return;}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown");};c._touchMove=function(f){if(!a){return;}this._touchMoved=true;d(f,"mousemove");};c._touchEnd=function(f){if(!a){return;}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click");}a=false;};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f);};})(jQuery);
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"loginName": "Benutzer:",
|
||||
"loginPassword": "Passwort:",
|
||||
"loginButton": "Einloggen",
|
||||
"registerButton": "Erstelle Profil",
|
||||
"discoverReadQrButton": "Fotografiere QRCode",
|
||||
"mainPageYourProfileLink": "Dein Profil",
|
||||
"mainPageYourProfileLinkDesc": "Bearbeite dein Profil",
|
||||
"mainPageCurrentSongLink": "Aktuelles Lied",
|
||||
"mainPageCurrentSongLinkDesc": "Zeigt Informationen über das aktuelle Lied an",
|
||||
"mainPageSelectSong": "Alle Lieder",
|
||||
"mainPageSelectSongDesc": "Listet alle verfügbaren Lieder auf",
|
||||
"mainPageSelectPlaylist": "Alle Playlisten",
|
||||
"mainPageSelectPlaylistDesc": "Listet alle verfügbaren Playlisten auf",
|
||||
"mainPageSelectProfile": "Profile",
|
||||
"mainPageSelectProfileDesc": "Listet alle Profile auf",
|
||||
"mainPageTakePhotoLink": "Nehme Foto auf",
|
||||
"mainPageTakePhotoLinkDesc": "Nimmt ein Foto auf und zeigt es am ende der Runde an",
|
||||
"mainPageKeyboard": "Tastatur",
|
||||
"mainPageKeyboardDesc": "Sende Tastatureingaben",
|
||||
"mainPageSelectUserAdmin": "Administration",
|
||||
"mainPageSelectUserAdminDesc": "Konfiguriere die Benutzerrechte",
|
||||
"mainPageLogoutLink": "Abmelden",
|
||||
"mainPageLogoutLinkDesc": "Beendet diese Sitzung",
|
||||
"selectProfileHeader": "Alle Profile",
|
||||
"displayProfileHeader": "Profile",
|
||||
"displayProfileName": "Name:",
|
||||
"displayProfilePlayerType": "Player Typ:",
|
||||
"displayProfilePlayerTypeNormal": "Normal",
|
||||
"displayProfilePlayerTypeGuest": "Gast",
|
||||
"displayProfilePlayerDifficulty": "Schwierigkeit:",
|
||||
"displayProfilePlayerDifficultyEasy": "Einfach",
|
||||
"displayProfilePlayerDifficultyNormal": "Normal",
|
||||
"displayProfilePlayerDifficultyHard": "Schwer",
|
||||
"displayProfilePlayerPassword": "Neues Passwort:",
|
||||
"displayProfilePlayerSaveButton": "Speichern und hochladen",
|
||||
"displaySongHeader": "Kein aktuelles Lied",
|
||||
"displaySongArtist": "Künstler:",
|
||||
"displaySongGenre": "Genre:",
|
||||
"displaySongYear": "Jahr:",
|
||||
"displaySongLanguage": "Sprache:",
|
||||
"displaySongIsDuet": "Duet:",
|
||||
"popupVideoClose": "Schließen",
|
||||
"selectSongHeader": "Alle Lieder",
|
||||
"keyboardHeader": "Tastatur",
|
||||
"keyboardButtonUp": "hoch",
|
||||
"keyboardButtonLeft": "links",
|
||||
"keyboardButtonRight": "rechts",
|
||||
"keyboardButtonDown": "runter",
|
||||
"keyboardButtonEscape": "Escape",
|
||||
"keyboardButtonTab": "Tab",
|
||||
"keyboardButtonReturn": "Enter",
|
||||
"keyboardButtonKeys": "Um andere Zeichen zu senden, hier tippen:",
|
||||
"selectUserAdminHeader": "Alle Profile",
|
||||
"displayUserAdminHeader": "Profile",
|
||||
"displayUserAdminContentSaveButton": "Speichern",
|
||||
"selectPlaylistHeader": "Wähle eine Playlist",
|
||||
"displayPlaylistHeader": "Playlist",
|
||||
"displayPlaylistSaveButton": "Speichern",
|
||||
"selectPlaylistAddPlaylistButton": "Hinzufügen",
|
||||
"Loading (external)...": "Laden (extern)...",
|
||||
"Loading...": "Laden...",
|
||||
"Creating...": "Erstellen...",
|
||||
"Error...": "Fehler...",
|
||||
"No connection": "Keine Verbindung",
|
||||
"No session": "Keine Sitzung",
|
||||
"Uploading photo...": "Foto hochladen...",
|
||||
"Getting current song...": "Lade aktuelles Lied...",
|
||||
"Login...": "Einloggen...",
|
||||
"Creating profile...": "Erstelle Profil...",
|
||||
"This is not a valid name.": "Dies ist kein gültiger Name.",
|
||||
"Uploading profile...": "Profil hochladen...",
|
||||
"songs": "Lieder",
|
||||
"YourName": "DeinName",
|
||||
"discoverConnectHeader": "Verbinde zum Server",
|
||||
"discoverConnectServerAddress": "Serveradresse:",
|
||||
"discoverConnectButton": "Verbinden",
|
||||
"Checking...": "Prüfen...",
|
||||
"timeout": "Zeitüberschreitung"
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"loginName": "User:",
|
||||
"loginPassword": "Password:",
|
||||
"loginButton": "Login",
|
||||
"registerButton": "Create Profile",
|
||||
"discoverReadQrButton": "Scan QRCode",
|
||||
"mainPageYourProfileLink": "Your Profile",
|
||||
"mainPageYourProfileLinkDesc": "Edit your profile",
|
||||
"mainPageCurrentSongLink": "Current Song",
|
||||
"mainPageCurrentSongLinkDesc": "Display informations about the current song",
|
||||
"mainPageSelectSong": "All songs",
|
||||
"mainPageSelectSongDesc": "Lists all available songs",
|
||||
"mainPageSelectPlaylist": "All playlists",
|
||||
"mainPageSelectPlaylistDesc": "Lists all playlists",
|
||||
"mainPageSelectProfile": "Profiles",
|
||||
"mainPageSelectProfileDesc": "Shows all profiles",
|
||||
"mainPageTakePhotoLink": "Take Photo",
|
||||
"mainPageTakePhotoLinkDesc": "Takes a photo and displays it at the end of the current round",
|
||||
"mainPageKeyboard": "Keyboard",
|
||||
"mainPageKeyboardDesc": "Send keys",
|
||||
"mainPageSelectUserAdmin": "Administration",
|
||||
"mainPageSelectUserAdminDesc": "Configure user rights",
|
||||
"mainPageLogoutLink": "Logout",
|
||||
"mainPageLogoutLinkDesc": "Closes the session",
|
||||
"selectProfileHeader": "All profiles",
|
||||
"displayProfileHeader": "Profile",
|
||||
"displayProfileName": "Name:",
|
||||
"displayProfilePlayerType": "Player Type:",
|
||||
"displayProfilePlayerTypeNormal": "Normal",
|
||||
"displayProfilePlayerTypeGuest": "Guest",
|
||||
"displayProfilePlayerDifficulty": "Difficulty:",
|
||||
"displayProfilePlayerDifficultyEasy": "Easy",
|
||||
"displayProfilePlayerDifficultyNormal": "Normal",
|
||||
"displayProfilePlayerDifficultyHard": "Hard",
|
||||
"displayProfilePlayerPassword": "New Password:",
|
||||
"displayProfilePlayerSaveButton": "Save and upload",
|
||||
"displaySongHeader": "No current song",
|
||||
"displaySongArtist": "Artist:",
|
||||
"displaySongGenre": "Genre:",
|
||||
"displaySongYear": "Year:",
|
||||
"displaySongLanguage": "Language:",
|
||||
"displaySongIsDuet": "Duet:",
|
||||
"popupVideoClose": "Close",
|
||||
"selectSongHeader": "All songs",
|
||||
"keyboardHeader": "Keyboard",
|
||||
"keyboardButtonUp": "up",
|
||||
"keyboardButtonLeft": "left",
|
||||
"keyboardButtonRight": "right",
|
||||
"keyboardButtonDown": "down",
|
||||
"keyboardButtonEscape": "escape",
|
||||
"keyboardButtonTab": "tab",
|
||||
"keyboardButtonReturn": "return",
|
||||
"keyboardButtonKeys": "To send other keys type here:",
|
||||
"selectUserAdminHeader": "All profiles",
|
||||
"displayUserAdminHeader": "Profile",
|
||||
"displayUserAdminContentSaveButton": "Save",
|
||||
"selectPlaylistHeader": "Select a playlist",
|
||||
"displayPlaylistHeader": "Playlist",
|
||||
"displayPlaylistSaveButton": "Save",
|
||||
"selectPlaylistAddPlaylistButton": "Add",
|
||||
"Loading (external)...": "Loading (external)...",
|
||||
"Loading...": "Loading...",
|
||||
"Creating...": "Creating...",
|
||||
"Error...": "Error...",
|
||||
"No connection": "No connection",
|
||||
"No session": "No session",
|
||||
"Uploading photo...": "Uploading photo...",
|
||||
"Getting current song...": "Getting current song...",
|
||||
"Login...": "Login...",
|
||||
"Creating profile...": "Creating profile...",
|
||||
"This is not a valid name.": "This is not a valid name.",
|
||||
"Uploading profile...": "Uploading profile...",
|
||||
"songs": "songs",
|
||||
"YourName": "YourName",
|
||||
"discoverConnectHeader": "Connect to server",
|
||||
"discoverConnectServerAddress": "Serveraddress:",
|
||||
"discoverConnectButton": "Connect",
|
||||
"Checking...": "Checking...",
|
||||
"timeout": "Timeout"
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
<configuration>
|
||||
<startup>
|
||||
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
|
||||
</configuration>
|
||||
@@ -1,18 +1,18 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using VocaluxeLib.Draw;
|
||||
@@ -48,5 +48,10 @@ namespace VocaluxeLib.Profile
|
||||
{
|
||||
CBase.Drawing.RemoveTexture(ref Texture);
|
||||
}
|
||||
|
||||
public string getFileName()
|
||||
{
|
||||
return FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,9 @@ namespace VocaluxeLib.Profile
|
||||
public string FilePath;
|
||||
public string FileName;
|
||||
public string AvatarFileName;
|
||||
public byte[] PasswordHash;
|
||||
public byte[] PasswordSalt;
|
||||
public int UserRoles;
|
||||
|
||||
public EGameDifficulty Difficulty;
|
||||
|
||||
@@ -87,7 +90,15 @@ namespace VocaluxeLib.Profile
|
||||
xmlReader.GetValue("//root/Info/Avatar", out AvatarFileName, String.Empty);
|
||||
xmlReader.TryGetEnumValue("//root/Info/GuestProfile", ref GuestProfile);
|
||||
xmlReader.TryGetEnumValue("//root/Info/Active", ref Active);
|
||||
|
||||
string passwordHash;
|
||||
xmlReader.GetValue("//root/Info/PasswordHash", out passwordHash, "");
|
||||
PasswordHash = !string.IsNullOrEmpty(passwordHash) ? Convert.FromBase64String(passwordHash) : null;
|
||||
string passwordSalt;
|
||||
xmlReader.GetValue("//root/Info/PasswordSalt", out passwordSalt, "");
|
||||
PasswordSalt = !string.IsNullOrEmpty(passwordSalt) ? Convert.FromBase64String(passwordSalt) : null;
|
||||
string userRoles;
|
||||
xmlReader.GetValue("//root/Info/UserRoles", out userRoles, "0");
|
||||
Int32.TryParse(userRoles, out UserRoles);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -104,7 +115,7 @@ namespace VocaluxeLib.Profile
|
||||
string filename = string.Empty;
|
||||
// ReSharper disable LoopCanBeConvertedToQuery
|
||||
foreach (char chr in PlayerName)
|
||||
// ReSharper restore LoopCanBeConvertedToQuery
|
||||
// ReSharper restore LoopCanBeConvertedToQuery
|
||||
{
|
||||
if (char.IsLetter(chr))
|
||||
filename += chr.ToString();
|
||||
@@ -148,6 +159,15 @@ namespace VocaluxeLib.Profile
|
||||
writer.WriteElementString("Avatar", Path.GetFileName(Avatar.FileName));
|
||||
writer.WriteElementString("GuestProfile", Enum.GetName(typeof(EOffOn), GuestProfile));
|
||||
writer.WriteElementString("Active", Enum.GetName(typeof(EOffOn), Active));
|
||||
if (PasswordHash != null)
|
||||
{
|
||||
writer.WriteElementString("PasswordHash", Convert.ToBase64String(PasswordHash));
|
||||
}
|
||||
if (PasswordSalt != null)
|
||||
{
|
||||
writer.WriteElementString("PasswordSalt", Convert.ToBase64String(PasswordSalt));
|
||||
}
|
||||
writer.WriteElementString("UserRoles", UserRoles.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteEndElement(); //end of root
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -0,0 +1,149 @@
|
||||
using Security.Cryptography;
|
||||
using Security.Cryptography.X509Certificates;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NetFwTypeLib;
|
||||
|
||||
namespace WebserverInitalConfig
|
||||
{
|
||||
public static class ConfigHttpApi
|
||||
{
|
||||
|
||||
public static void reserveURL(string networkString)
|
||||
{
|
||||
HttpApi.ReserveURL(networkString, "D:(A;;GX;;;S-1-1-0)");
|
||||
}
|
||||
|
||||
|
||||
public static void bindCert(string ip, int port, X509Certificate2 cert)
|
||||
{
|
||||
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||
if (HttpApi.QuerySslCertificateInfo(endpoint) != null)
|
||||
{
|
||||
HttpApi.DeleteCertificateBinding(endpoint);
|
||||
}
|
||||
|
||||
HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid("{7baf41f1-48b7-42cb-b145-f815499cb48f}"));
|
||||
}
|
||||
|
||||
|
||||
public static void addCertToStore(X509Certificate2 cert)
|
||||
{
|
||||
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
|
||||
X509Certificate2Collection oldCerts = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
|
||||
cert.SubjectName.Name, false);
|
||||
|
||||
foreach (var oldCert in oldCerts)
|
||||
{
|
||||
store.Remove(oldCert);
|
||||
}
|
||||
|
||||
store.Add(cert);
|
||||
store.Close();
|
||||
}
|
||||
|
||||
|
||||
public static X509Certificate2 getSelfSignedCert(string subjectName)
|
||||
{
|
||||
var keyParam = new CngKeyCreationParameters
|
||||
{
|
||||
ExportPolicy = CngExportPolicies.AllowExport,
|
||||
KeyCreationOptions = CngKeyCreationOptions.MachineKey | CngKeyCreationOptions.OverwriteExistingKey,
|
||||
KeyUsage = CngKeyUsages.AllUsages,
|
||||
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
|
||||
};
|
||||
|
||||
keyParam.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.None));
|
||||
|
||||
CngKey key = CngKey.Create(CngAlgorithm2.Rsa, Guid.NewGuid().ToString(), keyParam);
|
||||
|
||||
X509CertificateCreationParameters param = new X509CertificateCreationParameters(
|
||||
new X500DistinguishedName(subjectName));
|
||||
param.SubjectName = new X500DistinguishedName(subjectName);
|
||||
param.EndTime = DateTime.Today.AddYears(20);
|
||||
//param.SignatureAlgorithm = X509CertificateSignatureAlgorithm.RsaSha512;
|
||||
|
||||
OidCollection oc = new OidCollection();
|
||||
oc.Add(new Oid("1.3.6.1.5.5.7.3.1"));
|
||||
X509Extension eku = new X509EnhancedKeyUsageExtension(oc, true);
|
||||
param.Extensions.Add(eku);
|
||||
|
||||
param.TakeOwnershipOfKey = true;
|
||||
|
||||
byte[] rawData = key.CreateSelfSignedCertificate(param).Export(X509ContentType.Pfx, "");
|
||||
var cert = new X509Certificate2(rawData, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
|
||||
cert.FriendlyName = "Vocaluxe Server Certificate";
|
||||
return cert;
|
||||
}
|
||||
|
||||
public static void addFirewallrule(string exePath, int port, bool isTCP)
|
||||
{
|
||||
INetFwMgr manage = (INetFwMgr)Activator.CreateInstance(
|
||||
Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}")));
|
||||
bool isFirewallEnabled = manage.LocalPolicy.CurrentProfile.FirewallEnabled;
|
||||
|
||||
if (isFirewallEnabled)
|
||||
{
|
||||
INetFwAuthorizedApplications applications = manage.LocalPolicy.CurrentProfile.AuthorizedApplications;
|
||||
if ((from INetFwAuthorizedApplication a in applications
|
||||
where a.ProcessImageFileName == exePath
|
||||
select a).Count() == 0)
|
||||
{
|
||||
INetFwAuthorizedApplication application = (INetFwAuthorizedApplication)Activator.CreateInstance(
|
||||
Type.GetTypeFromCLSID(new Guid("{EC9846B3-2762-4A6B-A214-6ACB603462D2}")));
|
||||
|
||||
application.Name = "Vocaluxe";
|
||||
application.ProcessImageFileName = exePath;
|
||||
application.Enabled = true;
|
||||
applications.Add(application);
|
||||
}
|
||||
INetFwOpenPorts openPorts = manage.LocalPolicy.CurrentProfile.GloballyOpenPorts;
|
||||
if ((from INetFwOpenPort p in openPorts
|
||||
where (p.Port == port &&
|
||||
(p.Protocol == (isTCP?NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP)))
|
||||
select p).Count() == 0)
|
||||
{
|
||||
INetFwOpenPort openPort = (INetFwOpenPort)Activator.CreateInstance(
|
||||
Type.GetTypeFromCLSID(new Guid("{0CA545C6-37AD-4A6C-BF92-9F7610067EF5}")));
|
||||
openPort.Enabled = true;
|
||||
openPort.Port = port;
|
||||
openPort.Protocol = (isTCP ? NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP);
|
||||
openPort.Name = "Vocaluxe";
|
||||
|
||||
openPorts.Add(openPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*public static X509Certificate2 getCert(string subject)
|
||||
{
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
||||
|
||||
Mono.Security.Authenticode.PrivateKey key = new Mono.Security.Authenticode.PrivateKey { RSA=RSA.Create()};
|
||||
|
||||
|
||||
Mono.Security.X509.X509CertificateBuilder x509 = new Mono.Security.X509.X509CertificateBuilder();
|
||||
x509.IssuerName = "CN=Vocaluxe Server";
|
||||
x509.NotAfter = DateTime.Today.AddYears(20);
|
||||
x509.NotBefore = DateTime.Today.AddDays(-1);
|
||||
x509.SubjectName = subject;
|
||||
x509.SerialNumber = new byte[] { 1 };
|
||||
x509.Version = 3;
|
||||
x509.SubjectPublicKey = rsa;
|
||||
|
||||
ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension();
|
||||
eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.1");
|
||||
x509.Extensions.Add(eku);
|
||||
|
||||
return new X509Certificate2(x509.Sign(rsa));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,672 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebserverInitalConfig
|
||||
{
|
||||
internal static class HttpApi
|
||||
{
|
||||
private static readonly HTTPAPI_VERSION HttpApiVersion = new HTTPAPI_VERSION(1, 0);
|
||||
|
||||
#region DllImport
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpInitialize(
|
||||
HTTPAPI_VERSION version,
|
||||
uint flags,
|
||||
IntPtr pReserved);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpSetServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pConfigInformation,
|
||||
int configInformationLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpDeleteServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pConfigInformation,
|
||||
int configInformationLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpTerminate(
|
||||
uint Flags,
|
||||
IntPtr pReserved);
|
||||
|
||||
[DllImport("httpapi.dll", SetLastError = true)]
|
||||
static extern uint HttpQueryServiceConfiguration(
|
||||
IntPtr serviceIntPtr,
|
||||
HTTP_SERVICE_CONFIG_ID configId,
|
||||
IntPtr pInputConfigInfo,
|
||||
int inputConfigInfoLength,
|
||||
IntPtr pOutputConfigInfo,
|
||||
int outputConfigInfoLength,
|
||||
[Optional]
|
||||
out int pReturnLength,
|
||||
IntPtr pOverlapped);
|
||||
|
||||
|
||||
enum HTTP_SERVICE_CONFIG_ID
|
||||
{
|
||||
|
||||
HttpServiceConfigIPListenList = 0,
|
||||
HttpServiceConfigSSLCertInfo,
|
||||
HttpServiceConfigUrlAclInfo,
|
||||
HttpServiceConfigMax
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_SET
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
|
||||
public HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_KEY
|
||||
{
|
||||
public IntPtr pIpPort;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY(IntPtr pIpPort)
|
||||
{
|
||||
this.pIpPort = pIpPort;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_PARAM
|
||||
{
|
||||
public int SslHashLength;
|
||||
public IntPtr pSslHash;
|
||||
public Guid AppId;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pSslCertStoreName;
|
||||
public uint DefaultCertCheckMode;
|
||||
public int DefaultRevocationFreshnessTime;
|
||||
public int DefaultRevocationUrlRetrievalTimeout;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pDefaultSslCtlIdentifier;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pDefaultSslCtlStoreName;
|
||||
public uint DefaultFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
struct HTTPAPI_VERSION
|
||||
{
|
||||
public ushort HttpApiMajorVersion;
|
||||
public ushort HttpApiMinorVersion;
|
||||
|
||||
public HTTPAPI_VERSION(ushort majorVersion, ushort minorVersion)
|
||||
{
|
||||
HttpApiMajorVersion = majorVersion;
|
||||
HttpApiMinorVersion = minorVersion;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
|
||||
public HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
|
||||
public uint dwToken;
|
||||
}
|
||||
|
||||
enum HTTP_SERVICE_CONFIG_QUERY_TYPE
|
||||
{
|
||||
HttpServiceConfigQueryExact = 0,
|
||||
HttpServiceConfigQueryNext,
|
||||
HttpServiceConfigQueryMax
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct HTTP_SERVICE_CONFIG_URLACL_SET
|
||||
{
|
||||
public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
|
||||
public HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct HTTP_SERVICE_CONFIG_URLACL_KEY
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pUrlPrefix;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_URLACL_KEY(string urlPrefix)
|
||||
{
|
||||
pUrlPrefix = urlPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
struct HTTP_SERVICE_CONFIG_URLACL_PARAM
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pStringSecurityDescriptor;
|
||||
|
||||
public HTTP_SERVICE_CONFIG_URLACL_PARAM(string securityDescriptor)
|
||||
{
|
||||
pStringSecurityDescriptor = securityDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
public const uint HTTP_INITIALIZE_CONFIG = 0x00000002;
|
||||
public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT = 0x00000002;
|
||||
public const uint HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER = 0x00000004;
|
||||
private const uint NOERROR = 0;
|
||||
private const uint ERROR_INSUFFICIENT_BUFFER = 122;
|
||||
private const uint ERROR_ALREADY_EXISTS = 183;
|
||||
private const uint ERROR_FILE_NOT_FOUND = 2;
|
||||
private const int ERROR_NO_MORE_ITEMS = 259;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
public class SslCertificateInfo
|
||||
{
|
||||
public byte[] Hash { get; set; }
|
||||
public Guid AppId { get; set; }
|
||||
public string StoreName { get; set; }
|
||||
public IPEndPoint IpPort { get; set; }
|
||||
}
|
||||
|
||||
public static SslCertificateInfo QuerySslCertificateInfo(IPEndPoint ipPort)
|
||||
{
|
||||
SslCertificateInfo result = null;
|
||||
|
||||
uint retVal;
|
||||
CallHttpApi(delegate
|
||||
{
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY sslKey = new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
|
||||
HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery =
|
||||
new HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact,
|
||||
KeyDesc = sslKey
|
||||
};
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)));
|
||||
Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);
|
||||
|
||||
IntPtr pOutputConfigInfo = IntPtr.Zero;
|
||||
int returnLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo;
|
||||
int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
if (retVal == ERROR_FILE_NOT_FOUND)
|
||||
return;
|
||||
|
||||
if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122
|
||||
{
|
||||
pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);
|
||||
|
||||
try
|
||||
{
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
var outputConfigInfo =
|
||||
(HTTP_SERVICE_CONFIG_SSL_SET)
|
||||
Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET));
|
||||
|
||||
byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength];
|
||||
Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length);
|
||||
|
||||
Guid appId = outputConfigInfo.ParamDesc.AppId;
|
||||
string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName;
|
||||
|
||||
result = new SslCertificateInfo { AppId = appId, Hash = hash, StoreName = storeName, IpPort = ipPort };
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pOutputConfigInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void BindCertificate(IPEndPoint ipPort, byte[] hash, StoreName storeName, Guid appId)
|
||||
{
|
||||
if (ipPort == null) throw new ArgumentNullException("ipPort");
|
||||
if (hash == null) throw new ArgumentNullException("hash");
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_SET configSslSet = new HTTP_SERVICE_CONFIG_SSL_SET();
|
||||
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY httpServiceConfigSslKey =
|
||||
new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
HTTP_SERVICE_CONFIG_SSL_PARAM configSslParam = new HTTP_SERVICE_CONFIG_SSL_PARAM();
|
||||
|
||||
|
||||
GCHandle handleHash = GCHandle.Alloc(hash, GCHandleType.Pinned);
|
||||
configSslParam.AppId = appId;
|
||||
configSslParam.DefaultCertCheckMode = 0;
|
||||
configSslParam.DefaultFlags = 0; //HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT;
|
||||
configSslParam.DefaultRevocationFreshnessTime = 0;
|
||||
configSslParam.DefaultRevocationUrlRetrievalTimeout = 0;
|
||||
configSslParam.pSslCertStoreName = storeName.ToString();
|
||||
configSslParam.pSslHash = handleHash.AddrOfPinnedObject();
|
||||
configSslParam.SslHashLength = hash.Length;
|
||||
configSslSet.ParamDesc = configSslParam;
|
||||
configSslSet.KeyDesc = httpServiceConfigSslKey;
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_SET)));
|
||||
Marshal.StructureToPtr(configSslSet, pInputConfigInfo, false);
|
||||
|
||||
try
|
||||
{
|
||||
uint retVal = HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if (ERROR_ALREADY_EXISTS != retVal)
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
retVal = HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (handleHash.IsAllocated)
|
||||
handleHash.Free();
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void DeleteCertificateBinding(params IPEndPoint[] ipPorts)
|
||||
{
|
||||
if (ipPorts == null || ipPorts.Length == 0)
|
||||
return;
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
foreach (var ipPort in ipPorts)
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_SET configSslSet =
|
||||
new HTTP_SERVICE_CONFIG_SSL_SET();
|
||||
|
||||
GCHandle sockAddrHandle = CreateSockaddrStructure(ipPort);
|
||||
IntPtr pIpPort = sockAddrHandle.AddrOfPinnedObject();
|
||||
HTTP_SERVICE_CONFIG_SSL_KEY httpServiceConfigSslKey =
|
||||
new HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);
|
||||
configSslSet.KeyDesc = httpServiceConfigSslKey;
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(
|
||||
Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_SET)));
|
||||
Marshal.StructureToPtr(configSslSet, pInputConfigInfo, false);
|
||||
|
||||
try
|
||||
{
|
||||
uint retVal = HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(configSslSet),
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
if (sockAddrHandle.IsAllocated)
|
||||
sockAddrHandle.Free();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static SslCertificateInfo[] QuerySslCertificateInfo()
|
||||
{
|
||||
var result = new List<SslCertificateInfo>();
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
uint token = 0;
|
||||
|
||||
uint retVal;
|
||||
do
|
||||
{
|
||||
HTTP_SERVICE_CONFIG_SSL_QUERY inputConfigInfoQuery =
|
||||
new HTTP_SERVICE_CONFIG_SSL_QUERY
|
||||
{
|
||||
QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext,
|
||||
dwToken = token,
|
||||
};
|
||||
|
||||
IntPtr pInputConfigInfo =
|
||||
Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_SSL_QUERY)));
|
||||
Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);
|
||||
|
||||
IntPtr pOutputConfigInfo = IntPtr.Zero;
|
||||
int returnLength = 0;
|
||||
|
||||
const HTTP_SERVICE_CONFIG_ID queryType = HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo;
|
||||
|
||||
try
|
||||
{
|
||||
int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
if (ERROR_NO_MORE_ITEMS == retVal)
|
||||
break;
|
||||
if (ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122
|
||||
{
|
||||
pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);
|
||||
|
||||
try
|
||||
{
|
||||
retVal = HttpQueryServiceConfiguration(IntPtr.Zero,
|
||||
queryType,
|
||||
pInputConfigInfo,
|
||||
inputConfigInfoSize,
|
||||
pOutputConfigInfo,
|
||||
returnLength,
|
||||
out returnLength,
|
||||
IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
var outputConfigInfo = (HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure(
|
||||
pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_SSL_SET));
|
||||
|
||||
byte[] hash = new byte[outputConfigInfo.ParamDesc.SslHashLength];
|
||||
Marshal.Copy(outputConfigInfo.ParamDesc.pSslHash, hash, 0, hash.Length);
|
||||
|
||||
Guid appId = outputConfigInfo.ParamDesc.AppId;
|
||||
string storeName = outputConfigInfo.ParamDesc.pSslCertStoreName;
|
||||
IPEndPoint ipPort = ReadSockaddrStructure(outputConfigInfo.KeyDesc.pIpPort);
|
||||
|
||||
var resultItem = new SslCertificateInfo
|
||||
{
|
||||
AppId = appId,
|
||||
Hash = hash,
|
||||
StoreName = storeName,
|
||||
IpPort = ipPort
|
||||
};
|
||||
result.Add(resultItem);
|
||||
token++;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pOutputConfigInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
}
|
||||
|
||||
} while (NOERROR == retVal);
|
||||
|
||||
});
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static void ReserveURL(string networkURL, string securityDescriptor)
|
||||
{
|
||||
if (String.IsNullOrEmpty(networkURL)) throw new ArgumentNullException("networkURL");
|
||||
if (String.IsNullOrEmpty(securityDescriptor)) throw new ArgumentNullException("securityDescriptor");
|
||||
|
||||
CallHttpApi(
|
||||
delegate
|
||||
{
|
||||
uint retVal = (uint)NOERROR; // NOERROR = 0
|
||||
|
||||
HTTP_SERVICE_CONFIG_URLACL_KEY keyDesc = new HTTP_SERVICE_CONFIG_URLACL_KEY(networkURL);
|
||||
HTTP_SERVICE_CONFIG_URLACL_PARAM paramDesc = new HTTP_SERVICE_CONFIG_URLACL_PARAM(securityDescriptor);
|
||||
|
||||
HTTP_SERVICE_CONFIG_URLACL_SET inputConfigInfoSet = new HTTP_SERVICE_CONFIG_URLACL_SET();
|
||||
inputConfigInfoSet.KeyDesc = keyDesc;
|
||||
inputConfigInfoSet.ParamDesc = paramDesc;
|
||||
|
||||
IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_SET)));
|
||||
Marshal.StructureToPtr(inputConfigInfoSet, pInputConfigInfo, false);
|
||||
try
|
||||
{
|
||||
retVal = HttpApi.HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if ((uint)ERROR_ALREADY_EXISTS == retVal) // ERROR_ALREADY_EXISTS = 183
|
||||
{
|
||||
retVal = HttpApi.HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
|
||||
if ((uint)NOERROR == retVal)
|
||||
{
|
||||
retVal = HttpApi.HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
}
|
||||
else if ((uint)ERROR_FILE_NOT_FOUND == retVal) // ERROR_FILE_NOT_FOUND = 2
|
||||
{
|
||||
string networkURLOld = networkURL.Contains("https") ? networkURL.Replace("https", "http") :
|
||||
networkURL.Replace("http", "https");
|
||||
HTTP_SERVICE_CONFIG_URLACL_KEY keyDescOld = new HTTP_SERVICE_CONFIG_URLACL_KEY(networkURLOld);
|
||||
HTTP_SERVICE_CONFIG_URLACL_PARAM paramDescOld = new HTTP_SERVICE_CONFIG_URLACL_PARAM(securityDescriptor);
|
||||
|
||||
HTTP_SERVICE_CONFIG_URLACL_SET inputConfigInfoSetOld = new HTTP_SERVICE_CONFIG_URLACL_SET();
|
||||
inputConfigInfoSetOld.KeyDesc = keyDescOld;
|
||||
inputConfigInfoSetOld.ParamDesc = paramDescOld;
|
||||
|
||||
IntPtr pInputConfigInfoOld = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_SET)));
|
||||
Marshal.StructureToPtr(inputConfigInfoSetOld, pInputConfigInfoOld, false);
|
||||
|
||||
retVal = HttpApi.HttpDeleteServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfoOld,
|
||||
Marshal.SizeOf(inputConfigInfoSetOld),
|
||||
IntPtr.Zero);
|
||||
|
||||
if ((uint)NOERROR == retVal)
|
||||
{
|
||||
retVal = HttpApi.HttpSetServiceConfiguration(IntPtr.Zero,
|
||||
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
|
||||
pInputConfigInfo,
|
||||
Marshal.SizeOf(inputConfigInfoSet),
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInputConfigInfo);
|
||||
HttpApi.HttpTerminate(HttpApi.HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
}
|
||||
if ((uint)NOERROR != retVal)
|
||||
{
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void ThrowWin32ExceptionIfError(uint retVal)
|
||||
{
|
||||
if (NOERROR != retVal)
|
||||
{
|
||||
throw new Win32Exception(Convert.ToInt32(retVal));
|
||||
}
|
||||
}
|
||||
|
||||
private static void CallHttpApi(Action body)
|
||||
{
|
||||
uint retVal = HttpInitialize(HttpApiVersion, HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
ThrowWin32ExceptionIfError(retVal);
|
||||
|
||||
try
|
||||
{
|
||||
body();
|
||||
}
|
||||
finally
|
||||
{
|
||||
HttpTerminate(HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unmanaged sockaddr structure to pass to a WinAPI function.
|
||||
/// </summary>
|
||||
/// <param name="ipEndPoint">IP address and port number</param>
|
||||
/// <returns>a handle for the structure. Use the AddrOfPinnedObject Method to get a stable pointer to the object. </returns>
|
||||
/// <remarks>When the handle goes out of scope you must explicitly release it by calling the Free method; otherwise, memory leaks may occur. </remarks>
|
||||
private static GCHandle CreateSockaddrStructure(IPEndPoint ipEndPoint)
|
||||
{
|
||||
SocketAddress socketAddress = ipEndPoint.Serialize();
|
||||
|
||||
// use an array of bytes instead of the sockaddr structure
|
||||
byte[] sockAddrStructureBytes = new byte[socketAddress.Size];
|
||||
GCHandle sockAddrHandle = GCHandle.Alloc(sockAddrStructureBytes, GCHandleType.Pinned);
|
||||
for (int i = 0; i < socketAddress.Size; ++i)
|
||||
{
|
||||
sockAddrStructureBytes[i] = socketAddress[i];
|
||||
}
|
||||
return sockAddrHandle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the unmanaged sockaddr structure returned by a WinAPI function
|
||||
/// </summary>
|
||||
/// <param name="pSockaddrStructure">pointer to the unmanaged sockaddr structure</param>
|
||||
/// <returns>IP address and port number</returns>
|
||||
private static IPEndPoint ReadSockaddrStructure(IntPtr pSockaddrStructure)
|
||||
{
|
||||
short sAddressFamily = Marshal.ReadInt16(pSockaddrStructure);
|
||||
AddressFamily addressFamily = (AddressFamily)sAddressFamily;
|
||||
|
||||
int sockAddrSructureSize;
|
||||
IPEndPoint ipEndPointAny;
|
||||
switch (addressFamily)
|
||||
{
|
||||
case AddressFamily.InterNetwork:
|
||||
// IP v4 address
|
||||
sockAddrSructureSize = 16;
|
||||
ipEndPointAny = new IPEndPoint(IPAddress.Any, 0);
|
||||
break;
|
||||
case AddressFamily.InterNetworkV6:
|
||||
// IP v6 address
|
||||
sockAddrSructureSize = 28;
|
||||
ipEndPointAny = new IPEndPoint(IPAddress.IPv6Any, 0);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("pSockaddrStructure", "Unknown address family");
|
||||
}
|
||||
|
||||
|
||||
// get bytes of the sockadrr structure
|
||||
byte[] sockAddrSructureBytes = new byte[sockAddrSructureSize];
|
||||
Marshal.Copy(pSockaddrStructure, sockAddrSructureBytes, 0, sockAddrSructureSize);
|
||||
|
||||
// create SocketAddress from bytes
|
||||
var socketAddress = new SocketAddress(AddressFamily.Unspecified, sockAddrSructureSize);
|
||||
for (int i = 0; i < sockAddrSructureSize; i++)
|
||||
{
|
||||
socketAddress[i] = sockAddrSructureBytes[i];
|
||||
}
|
||||
|
||||
// create IPEndPoint from SocketAddress
|
||||
IPEndPoint result = (IPEndPoint)ipEndPointAny.Create(socketAddress);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebserverInitalConfig
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
Console.WriteLine("Usage: WebserverInitalConfig port isHttps");
|
||||
}
|
||||
|
||||
ConfigHttpApi.addFirewallrule(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Vocaluxe.exe"), Int32.Parse(args[0]), true);
|
||||
|
||||
if (args[1].ToLower() == "true")
|
||||
{
|
||||
string hostname = Dns.GetHostName();
|
||||
var cert = ConfigHttpApi.getSelfSignedCert("CN=" + hostname + " C=DE O=Vocaluxe OU=Vocaluxe Server");
|
||||
ConfigHttpApi.addCertToStore(cert);
|
||||
ConfigHttpApi.bindCert("0.0.0.0", Int32.Parse(args[0]), cert);
|
||||
ConfigHttpApi.reserveURL("https://+:" + args[0] + "/");
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigHttpApi.reserveURL("http://+:" + args[0] + "/");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die mit einer Assembly verknüpft sind.
|
||||
[assembly: AssemblyTitle("Vocaluxe Server Config")]
|
||||
[assembly: AssemblyDescription("Configures your computer to run the Vocaluxe Server")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Vocaluxe")]
|
||||
[assembly: AssemblyProduct("Vocaluxe Server Config")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("b2df9255-3927-4125-ab3c-23c35794b04d")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
After Width: | Height: | Size: 87 KiB |
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{55F89808-4E79-4FFE-BC13-48258913F5C9}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>WebserverInitalConfig</RootNamespace>
|
||||
<AssemblyName>VocaluxeServerConfig</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Output\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Vocaluxe.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Interop.NetFwTypeLib, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
<HintPath>..\Output\Interop.NetFwTypeLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Security, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Output\Security.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Security.Cryptography, Version=1.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Output\Security.Cryptography.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConfigHttpApi.cs" />
|
||||
<Compile Include="HttpApi.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="app.manifest">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Vocaluxe.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC-Manifestoptionen
|
||||
Wenn Sie die Zugangsebene für das Windows-Benutzerkonto ändern möchten, ersetzen Sie den
|
||||
requestedExecutionLevel-Knoten durch eines der folgenden Elemente.
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
Durch Angeben des requestedExecutionLevel-Knotens wird die Datei- und Registrierungsvirtualisierung deaktiviert.
|
||||
Wenn Sie Datei- und Registrierungsvirtualisierung für Abwärts-
|
||||
kompatibilität verwenden möchten, löschen Sie den requestedExecutionLevel-Knoten.
|
||||
-->
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Eine Liste aller Windows-Versionen, mit denen die Anwendung kompatibel ist.
|
||||
Windows wählt automatisch die am stärksten kompatible Umgebung aus.-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows Vista kompatibel ist, heben Sie die Auskommentierung des folgenden supportedOS-Knotens auf-->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows 7 kompatibel ist, heben Sie die Kommentierung des folgenden supportedOS-Knotens auf.-->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows 8 kompatibel ist, heben Sie die Auskommentierung des folgenden supportedOS-Knotens auf-->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- Designs für allgemeine Windows-Steuerelemente und -Dialogfelder (Windows XP und höher) aktivieren -->
|
||||
<!-- <dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>-->
|
||||
|
||||
</asmv1:assembly>
|
||||